ghi 0.9.0.20130912 → 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e0c68ea7d989b5a9f84393182ce31fc1aa3225d0
4
- data.tar.gz: 4703a58daeadacc4fe7eeb14634707e1689af384
3
+ metadata.gz: c253937537d9abb1e9a721c469220a8e2fb95050
4
+ data.tar.gz: 20c3911c61cbec263eb0347f8a5ce66de3290004
5
5
  SHA512:
6
- metadata.gz: 9285c3ef1ba18302d364ba8690c42bf9f4bd0861ae3c16c57a86dd372e6e958058c6a9b3b4182df3cbde206778a6c1307c3516d7cb5e808ebefc3a18b1219d9f
7
- data.tar.gz: 0a48d81eaae90de2a27a5bf6ff60ac58de04f709638ae3111196e978fd33db416f30b2255b7e33e0cd3ec04551ed770c69ce10832f8a7f40732d9a586977e45b
6
+ metadata.gz: 39bd93ab895a37ca157602f80183978b7c27895a5b6e0af4962ee7dd076a957575854b46aece1fe8b9e1d87a22a574aecd30b5c03c563855144b1870cebdf60a
7
+ data.tar.gz: 4d136961fe3a859f1c9958d4e0d9a067d68074e0e48361074a0f84e00331516c5069cf759505d5676631f398c72c82eb2491df91f921792cb43ecd046146a23b
data/lib/ghi.rb CHANGED
@@ -109,9 +109,14 @@ EOF
109
109
  exit 1
110
110
  end
111
111
 
112
- def config key, upcase = true
112
+ def config key, options = {}
113
+ upcase = options.fetch :upcase, true
114
+ flags = options[:flags]
113
115
  var = key.gsub('core', 'git').gsub '.', '_'
114
- value = ENV[upcase ? var.upcase : var] || `git config #{key}`.chomp
116
+ var.upcase! if upcase
117
+ value = ENV[var] || `git config #{flags} #{key}`
118
+ value = `#{value[1..-1]}` if value.start_with? '!'
119
+ value = value.chomp
115
120
  value unless value.empty?
116
121
  end
117
122
 
@@ -32,28 +32,11 @@ module GHI
32
32
  }
33
33
  @token = res.body['token']
34
34
 
35
- run = []
36
35
  unless username
37
- run << "git config#{' --global' unless local} github.user #{user}"
36
+ system "git config#{' --global' unless local} github.user #{user}"
38
37
  end
39
- run << "git config#{' --global' unless local} ghi.token #{token}"
40
38
 
41
- system run.join('; ')
42
-
43
- unless local
44
- at_exit do
45
- warn <<EOF
46
- Your ~/.gitconfig has been modified by way of:
47
-
48
- #{run.join "\n "}
49
-
50
- #{bright { blink { 'Do not check this change into public source control!' } }}
51
- Alternatively, set the following env var in a private dotfile:
52
-
53
- export GHI_TOKEN="#{token}"
54
- EOF
55
- end
56
- end
39
+ store_token! username, token, local
57
40
  rescue Client::Error => e
58
41
  if e.response['X-GitHub-OTP'] =~ /required/
59
42
  puts "Bad code." if code
@@ -76,6 +59,68 @@ EOF
76
59
  return @password if defined? @password
77
60
  @password = GHI.config 'github.password'
78
61
  end
62
+
63
+ private
64
+
65
+ def store_token! username, token, local
66
+ if security
67
+ run = []
68
+
69
+ run << security('delete', username)
70
+ run << security('add', username, token)
71
+
72
+ find = security 'find', username, false
73
+ run << %(git config#{' --global' unless local} ghi.token "!#{find}")
74
+
75
+ system run.join ' ; '
76
+
77
+ puts "✔︎ Token saved to keychain."
78
+ return
79
+ end
80
+
81
+ command = "git config#{' --global' unless local} ghi.token #{token}"
82
+ system command
83
+
84
+ unless local
85
+ at_exit do
86
+ warn <<EOF
87
+ Your ~/.gitconfig has been modified by way of:
88
+
89
+ #{command}
90
+
91
+ #{bright { blink { 'Do not check this change into public source control!' } }}
92
+
93
+ You can increase security by storing the token in a secure place that can be
94
+ fetched from the command line. E.g., on OS X:
95
+
96
+ git config --global ghi.token \\
97
+ "!security -a #{username} -s github.com -l 'ghi token' -w"
98
+
99
+ Alternatively, set the following env var in a private dotfile:
100
+
101
+ export GHI_TOKEN="#{token}"
102
+ EOF
103
+ end
104
+ end
105
+ end
106
+
107
+ def security command = nil, username = nil, password = nil
108
+ if command.nil? && username.nil? && password.nil?
109
+ return system 'which security >/dev/null'
110
+ end
111
+
112
+ run = [
113
+ 'security',
114
+ "#{command}-internet-password",
115
+ "-a #{username}",
116
+ '-s github.com',
117
+ "-l 'ghi token'"
118
+ ]
119
+ run << %(-w#{" #{password}" if password}) unless password.nil?
120
+ run << '>/dev/null 2>&1' unless command == 'find'
121
+
122
+ run.join ' '
123
+ end
79
124
  end
80
125
  end
81
126
  end
data/lib/ghi/client.rb CHANGED
@@ -97,6 +97,7 @@ module GHI
97
97
  def request method, path, options
98
98
  path = "/api/v3#{path}" if HOST != DEFAULT_HOST
99
99
 
100
+ path = URI.escape path
100
101
  if params = options[:params] and !params.empty?
101
102
  q = params.map { |k, v| "#{CGI.escape k.to_s}=#{CGI.escape v.to_s}" }
102
103
  path += "?#{q.join '&'}"
@@ -114,8 +115,8 @@ module GHI
114
115
  end
115
116
  req.basic_auth username, password if username && password
116
117
 
117
- proxy = GHI.config 'https.proxy', false
118
- proxy ||= GHI.config 'http.proxy', false
118
+ proxy = GHI.config 'https.proxy', :upcase => false
119
+ proxy ||= GHI.config 'http.proxy', :upcase => false
119
120
  if proxy
120
121
  proxy = URI.parse proxy
121
122
  http = Net::HTTP::Proxy(proxy.host, proxy.port).new HOST, PORT
@@ -37,7 +37,7 @@ module GHI
37
37
 
38
38
  def repo
39
39
  return @repo if defined? @repo
40
- @repo = detect_repo || GHI.config('ghi.repo')
40
+ @repo = GHI.config('ghi.repo', :flags => '--local') || detect_repo
41
41
  if @repo && !@repo.include?('/')
42
42
  @repo = [Authorization.username, @repo].join '/'
43
43
  end
@@ -85,8 +85,13 @@ module GHI
85
85
 
86
86
  def issue
87
87
  return @issue if defined? @issue
88
- index = args.index { |arg| /^\d+$/ === arg }
89
- @issue = (args.delete_at index if index)
88
+ if index = args.index { |arg| /^\d+$/ === arg }
89
+ @issue = args.delete_at index
90
+ else
91
+ @issue = `git symbolic-ref --short HEAD 2>/dev/null`[/^\d+/];
92
+ warn "(Inferring issue from branch prefix: ##@issue)" if @issue
93
+ end
94
+ @issue
90
95
  end
91
96
  alias extract_issue issue
92
97
  alias milestone issue
@@ -13,6 +13,7 @@ module GHI
13
13
  opts.banner = 'usage: ghi list [options]'
14
14
  opts.separator ''
15
15
  opts.on '-a', '--global', '--all', 'all of your issues on GitHub' do
16
+ assigns[:filter] = 'all'
16
17
  @repo = nil
17
18
  end
18
19
  opts.on(
@@ -58,12 +59,16 @@ module GHI
58
59
  opts.separator 'Global options'
59
60
  opts.on(
60
61
  '-f', '--filter <by>',
61
- filters = %w(assigned created mentioned subscribed),
62
+ filters = %w[all assigned created mentioned subscribed],
62
63
  Hash[filters.map { |f| [f[0, 1], f] }],
63
- "'assigned', 'created', 'mentioned', or", "'subscribed'"
64
+ filters.map { |f| "'#{f}'" }.join(', ')
64
65
  ) do |filter|
65
66
  assigns[:filter] = filter
66
67
  end
68
+ opts.on '--mine', 'assigned to you' do
69
+ assigns[:filter] = 'assigned'
70
+ assigns[:assignee] = Authorization.username
71
+ end
67
72
  opts.separator ''
68
73
  opts.separator 'Project options'
69
74
  opts.on(
@@ -79,6 +84,7 @@ module GHI
79
84
  assigns[:assignee] = any_or_none_or assignee
80
85
  end
81
86
  opts.on '--mine', 'assigned to you' do
87
+ assigns[:filter] = 'assigned'
82
88
  assigns[:assignee] = Authorization.username
83
89
  end
84
90
  opts.on(
@@ -3,8 +3,8 @@ module GHI
3
3
  module Version
4
4
  MAJOR = 0
5
5
  MINOR = 9
6
- PATCH = 0
7
- PRE = 20130912
6
+ PATCH = 2
7
+ PRE = nil
8
8
 
9
9
  VERSION = [MAJOR, MINOR, PATCH, PRE].compact.join '.'
10
10
 
@@ -9,6 +9,8 @@ module GHI
9
9
  end
10
10
  self.paginate = true # Default.
11
11
 
12
+ attr_accessor :paging
13
+
12
14
  autoload :Colors, 'ghi/formatting/colors'
13
15
  include Colors
14
16
 
@@ -54,6 +56,7 @@ module GHI
54
56
  end
55
57
 
56
58
  puts header if header
59
+ self.paging = true
57
60
  end
58
61
 
59
62
  loop do
@@ -72,10 +75,15 @@ module GHI
72
75
  end
73
76
 
74
77
  def paginate?
75
- $stdout.tty? && $stdout == STDOUT && Formatting.paginate
78
+ ($stdout.tty? && $stdout == STDOUT && Formatting.paginate) || paging?
79
+ end
80
+
81
+ def paging?
82
+ !!paging
76
83
  end
77
84
 
78
85
  def truncate string, reserved
86
+ return string unless paginate?
79
87
  result = string.scan(/.{0,#{columns - reserved}}(?:\s|\Z)/).first.strip
80
88
  result << "..." if result != string
81
89
  result
@@ -136,6 +144,7 @@ module GHI
136
144
  when 'created' then ' you created'
137
145
  when 'mentioned' then ' that mention you'
138
146
  when 'subscribed' then " you're subscribed to"
147
+ when 'all' then ' that you can see'
139
148
  else
140
149
  ' assigned to you'
141
150
  end
data/lib/ghi/json.rb CHANGED
@@ -1,1304 +1,1306 @@
1
- require 'strscan'
2
-
3
- module JSON
4
- module Pure
5
- # This class implements the JSON parser that is used to parse a JSON string
6
- # into a Ruby data structure.
7
- class Parser < StringScanner
8
- STRING = /" ((?:[^\x0-\x1f"\\] |
9
- # escaped special characters:
10
- \\["\\\/bfnrt] |
11
- \\u[0-9a-fA-F]{4} |
12
- # match all but escaped special characters:
13
- \\[\x20-\x21\x23-\x2e\x30-\x5b\x5d-\x61\x63-\x65\x67-\x6d\x6f-\x71\x73\x75-\xff])*)
14
- "/nx
15
- INTEGER = /(-?0|-?[1-9]\d*)/
16
- FLOAT = /(-?
17
- (?:0|[1-9]\d*)
18
- (?:
19
- \.\d+(?i:e[+-]?\d+) |
20
- \.\d+ |
21
- (?i:e[+-]?\d+)
22
- )
23
- )/x
24
- NAN = /NaN/
25
- INFINITY = /Infinity/
26
- MINUS_INFINITY = /-Infinity/
27
- OBJECT_OPEN = /\{/
28
- OBJECT_CLOSE = /\}/
29
- ARRAY_OPEN = /\[/
30
- ARRAY_CLOSE = /\]/
31
- PAIR_DELIMITER = /:/
32
- COLLECTION_DELIMITER = /,/
33
- TRUE = /true/
34
- FALSE = /false/
35
- NULL = /null/
36
- IGNORE = %r(
37
- (?:
38
- //[^\n\r]*[\n\r]| # line comments
39
- /\* # c-style comments
40
- (?:
41
- [^*/]| # normal chars
42
- /[^*]| # slashes that do not start a nested comment
43
- \*[^/]| # asterisks that do not end this comment
44
- /(?=\*/) # single slash before this comment's end
45
- )*
46
- \*/ # the End of this comment
47
- |[ \t\r\n]+ # whitespaces: space, horicontal tab, lf, cr
48
- )+
49
- )mx
50
-
51
- UNPARSED = Object.new
52
-
53
- # Creates a new JSON::Pure::Parser instance for the string _source_.
54
- #
55
- # It will be configured by the _opts_ hash. _opts_ can have the following
56
- # keys:
57
- # * *max_nesting*: The maximum depth of nesting allowed in the parsed data
58
- # structures. Disable depth checking with :max_nesting => false|nil|0,
59
- # it defaults to 19.
60
- # * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
61
- # defiance of RFC 4627 to be parsed by the Parser. This option defaults
62
- # to false.
63
- # * *symbolize_names*: If set to true, returns symbols for the names
64
- # (keys) in a JSON object. Otherwise strings are returned, which is also
65
- # the default.
66
- # * *create_additions*: If set to false, the Parser doesn't create
67
- # additions even if a matchin class and create_id was found. This option
68
- # defaults to true.
69
- # * *object_class*: Defaults to Hash
70
- # * *array_class*: Defaults to Array
71
- # * *quirks_mode*: Enables quirks_mode for parser, that is for example
72
- # parsing single JSON values instead of documents is possible.
73
- def initialize(source, opts = {})
74
- opts ||= {}
75
- unless @quirks_mode = opts[:quirks_mode]
76
- source = convert_encoding source
77
- end
78
- super source
79
- if !opts.key?(:max_nesting) # defaults to 19
80
- @max_nesting = 19
81
- elsif opts[:max_nesting]
82
- @max_nesting = opts[:max_nesting]
83
- else
84
- @max_nesting = 0
85
- end
86
- @allow_nan = !!opts[:allow_nan]
87
- @symbolize_names = !!opts[:symbolize_names]
88
- if opts.key?(:create_additions)
89
- @create_additions = !!opts[:create_additions]
90
- else
91
- @create_additions = true
1
+ unless defined? JSON
2
+ require 'strscan'
3
+
4
+ module JSON
5
+ module Pure
6
+ # This class implements the JSON parser that is used to parse a JSON string
7
+ # into a Ruby data structure.
8
+ class Parser < StringScanner
9
+ STRING = /" ((?:[^\x0-\x1f"\\] |
10
+ # escaped special characters:
11
+ \\["\\\/bfnrt] |
12
+ \\u[0-9a-fA-F]{4} |
13
+ # match all but escaped special characters:
14
+ \\[\x20-\x21\x23-\x2e\x30-\x5b\x5d-\x61\x63-\x65\x67-\x6d\x6f-\x71\x73\x75-\xff])*)
15
+ "/nx
16
+ INTEGER = /(-?0|-?[1-9]\d*)/
17
+ FLOAT = /(-?
18
+ (?:0|[1-9]\d*)
19
+ (?:
20
+ \.\d+(?i:e[+-]?\d+) |
21
+ \.\d+ |
22
+ (?i:e[+-]?\d+)
23
+ )
24
+ )/x
25
+ NAN = /NaN/
26
+ INFINITY = /Infinity/
27
+ MINUS_INFINITY = /-Infinity/
28
+ OBJECT_OPEN = /\{/
29
+ OBJECT_CLOSE = /\}/
30
+ ARRAY_OPEN = /\[/
31
+ ARRAY_CLOSE = /\]/
32
+ PAIR_DELIMITER = /:/
33
+ COLLECTION_DELIMITER = /,/
34
+ TRUE = /true/
35
+ FALSE = /false/
36
+ NULL = /null/
37
+ IGNORE = %r(
38
+ (?:
39
+ //[^\n\r]*[\n\r]| # line comments
40
+ /\* # c-style comments
41
+ (?:
42
+ [^*/]| # normal chars
43
+ /[^*]| # slashes that do not start a nested comment
44
+ \*[^/]| # asterisks that do not end this comment
45
+ /(?=\*/) # single slash before this comment's end
46
+ )*
47
+ \*/ # the End of this comment
48
+ |[ \t\r\n]+ # whitespaces: space, horicontal tab, lf, cr
49
+ )+
50
+ )mx
51
+
52
+ UNPARSED = Object.new
53
+
54
+ # Creates a new JSON::Pure::Parser instance for the string _source_.
55
+ #
56
+ # It will be configured by the _opts_ hash. _opts_ can have the following
57
+ # keys:
58
+ # * *max_nesting*: The maximum depth of nesting allowed in the parsed data
59
+ # structures. Disable depth checking with :max_nesting => false|nil|0,
60
+ # it defaults to 19.
61
+ # * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
62
+ # defiance of RFC 4627 to be parsed by the Parser. This option defaults
63
+ # to false.
64
+ # * *symbolize_names*: If set to true, returns symbols for the names
65
+ # (keys) in a JSON object. Otherwise strings are returned, which is also
66
+ # the default.
67
+ # * *create_additions*: If set to false, the Parser doesn't create
68
+ # additions even if a matchin class and create_id was found. This option
69
+ # defaults to true.
70
+ # * *object_class*: Defaults to Hash
71
+ # * *array_class*: Defaults to Array
72
+ # * *quirks_mode*: Enables quirks_mode for parser, that is for example
73
+ # parsing single JSON values instead of documents is possible.
74
+ def initialize(source, opts = {})
75
+ opts ||= {}
76
+ unless @quirks_mode = opts[:quirks_mode]
77
+ source = convert_encoding source
78
+ end
79
+ super source
80
+ if !opts.key?(:max_nesting) # defaults to 19
81
+ @max_nesting = 19
82
+ elsif opts[:max_nesting]
83
+ @max_nesting = opts[:max_nesting]
84
+ else
85
+ @max_nesting = 0
86
+ end
87
+ @allow_nan = !!opts[:allow_nan]
88
+ @symbolize_names = !!opts[:symbolize_names]
89
+ if opts.key?(:create_additions)
90
+ @create_additions = !!opts[:create_additions]
91
+ else
92
+ @create_additions = true
93
+ end
94
+ @create_id = @create_additions ? JSON.create_id : nil
95
+ @object_class = opts[:object_class] || Hash
96
+ @array_class = opts[:array_class] || Array
97
+ @match_string = opts[:match_string]
92
98
  end
93
- @create_id = @create_additions ? JSON.create_id : nil
94
- @object_class = opts[:object_class] || Hash
95
- @array_class = opts[:array_class] || Array
96
- @match_string = opts[:match_string]
97
- end
98
99
 
99
- alias source string
100
+ alias source string
100
101
 
101
- def quirks_mode?
102
- !!@quirks_mode
103
- end
102
+ def quirks_mode?
103
+ !!@quirks_mode
104
+ end
104
105
 
105
- def reset
106
- super
107
- @current_nesting = 0
108
- end
106
+ def reset
107
+ super
108
+ @current_nesting = 0
109
+ end
109
110
 
110
- # Parses the current JSON string _source_ and returns the complete data
111
- # structure as a result.
112
- def parse
113
- reset
114
- obj = nil
115
- if @quirks_mode
116
- while !eos? && skip(IGNORE)
117
- end
118
- if eos?
119
- raise ParserError, "source did not contain any JSON!"
120
- else
121
- obj = parse_value
122
- obj == UNPARSED and raise ParserError, "source did not contain any JSON!"
123
- end
124
- else
125
- until eos?
126
- case
127
- when scan(OBJECT_OPEN)
128
- obj and raise ParserError, "source '#{peek(20)}' not in JSON!"
129
- @current_nesting = 1
130
- obj = parse_object
131
- when scan(ARRAY_OPEN)
132
- obj and raise ParserError, "source '#{peek(20)}' not in JSON!"
133
- @current_nesting = 1
134
- obj = parse_array
135
- when skip(IGNORE)
136
- ;
111
+ # Parses the current JSON string _source_ and returns the complete data
112
+ # structure as a result.
113
+ def parse
114
+ reset
115
+ obj = nil
116
+ if @quirks_mode
117
+ while !eos? && skip(IGNORE)
118
+ end
119
+ if eos?
120
+ raise ParserError, "source did not contain any JSON!"
137
121
  else
138
- raise ParserError, "source '#{peek(20)}' not in JSON!"
122
+ obj = parse_value
123
+ obj == UNPARSED and raise ParserError, "source did not contain any JSON!"
124
+ end
125
+ else
126
+ until eos?
127
+ case
128
+ when scan(OBJECT_OPEN)
129
+ obj and raise ParserError, "source '#{peek(20)}' not in JSON!"
130
+ @current_nesting = 1
131
+ obj = parse_object
132
+ when scan(ARRAY_OPEN)
133
+ obj and raise ParserError, "source '#{peek(20)}' not in JSON!"
134
+ @current_nesting = 1
135
+ obj = parse_array
136
+ when skip(IGNORE)
137
+ ;
138
+ else
139
+ raise ParserError, "source '#{peek(20)}' not in JSON!"
140
+ end
139
141
  end
142
+ obj or raise ParserError, "source did not contain any JSON!"
140
143
  end
141
- obj or raise ParserError, "source did not contain any JSON!"
144
+ obj
142
145
  end
143
- obj
144
- end
145
146
 
146
- private
147
+ private
147
148
 
148
- def convert_encoding(source)
149
- if source.respond_to?(:to_str)
150
- source = source.to_str
151
- else
152
- raise TypeError, "#{source.inspect} is not like a string"
153
- end
154
- if defined?(::Encoding)
155
- if source.encoding == ::Encoding::ASCII_8BIT
156
- b = source[0, 4].bytes.to_a
149
+ def convert_encoding(source)
150
+ if source.respond_to?(:to_str)
151
+ source = source.to_str
152
+ else
153
+ raise TypeError, "#{source.inspect} is not like a string"
154
+ end
155
+ if defined?(::Encoding)
156
+ if source.encoding == ::Encoding::ASCII_8BIT
157
+ b = source[0, 4].bytes.to_a
158
+ source =
159
+ case
160
+ when b.size >= 4 && b[0] == 0 && b[1] == 0 && b[2] == 0
161
+ source.dup.force_encoding(::Encoding::UTF_32BE).encode!(::Encoding::UTF_8)
162
+ when b.size >= 4 && b[0] == 0 && b[2] == 0
163
+ source.dup.force_encoding(::Encoding::UTF_16BE).encode!(::Encoding::UTF_8)
164
+ when b.size >= 4 && b[1] == 0 && b[2] == 0 && b[3] == 0
165
+ source.dup.force_encoding(::Encoding::UTF_32LE).encode!(::Encoding::UTF_8)
166
+ when b.size >= 4 && b[1] == 0 && b[3] == 0
167
+ source.dup.force_encoding(::Encoding::UTF_16LE).encode!(::Encoding::UTF_8)
168
+ else
169
+ source.dup
170
+ end
171
+ else
172
+ source = source.encode(::Encoding::UTF_8)
173
+ end
174
+ source.force_encoding(::Encoding::ASCII_8BIT)
175
+ else
176
+ b = source
157
177
  source =
158
178
  case
159
179
  when b.size >= 4 && b[0] == 0 && b[1] == 0 && b[2] == 0
160
- source.dup.force_encoding(::Encoding::UTF_32BE).encode!(::Encoding::UTF_8)
180
+ JSON.iconv('utf-8', 'utf-32be', b)
161
181
  when b.size >= 4 && b[0] == 0 && b[2] == 0
162
- source.dup.force_encoding(::Encoding::UTF_16BE).encode!(::Encoding::UTF_8)
182
+ JSON.iconv('utf-8', 'utf-16be', b)
163
183
  when b.size >= 4 && b[1] == 0 && b[2] == 0 && b[3] == 0
164
- source.dup.force_encoding(::Encoding::UTF_32LE).encode!(::Encoding::UTF_8)
184
+ JSON.iconv('utf-8', 'utf-32le', b)
165
185
  when b.size >= 4 && b[1] == 0 && b[3] == 0
166
- source.dup.force_encoding(::Encoding::UTF_16LE).encode!(::Encoding::UTF_8)
186
+ JSON.iconv('utf-8', 'utf-16le', b)
167
187
  else
168
- source.dup
188
+ b
169
189
  end
170
- else
171
- source = source.encode(::Encoding::UTF_8)
172
190
  end
173
- source.force_encoding(::Encoding::ASCII_8BIT)
174
- else
175
- b = source
176
- source =
177
- case
178
- when b.size >= 4 && b[0] == 0 && b[1] == 0 && b[2] == 0
179
- JSON.iconv('utf-8', 'utf-32be', b)
180
- when b.size >= 4 && b[0] == 0 && b[2] == 0
181
- JSON.iconv('utf-8', 'utf-16be', b)
182
- when b.size >= 4 && b[1] == 0 && b[2] == 0 && b[3] == 0
183
- JSON.iconv('utf-8', 'utf-32le', b)
184
- when b.size >= 4 && b[1] == 0 && b[3] == 0
185
- JSON.iconv('utf-8', 'utf-16le', b)
186
- else
187
- b
188
- end
191
+ source
189
192
  end
190
- source
191
- end
192
193
 
193
- # Unescape characters in strings.
194
- UNESCAPE_MAP = Hash.new { |h, k| h[k] = k.chr }
195
- UNESCAPE_MAP.update({
196
- ?" => '"',
197
- ?\\ => '\\',
198
- ?/ => '/',
199
- ?b => "\b",
200
- ?f => "\f",
201
- ?n => "\n",
202
- ?r => "\r",
203
- ?t => "\t",
204
- ?u => nil,
205
- })
206
-
207
- EMPTY_8BIT_STRING = ''
208
- if ::String.method_defined?(:encode)
209
- EMPTY_8BIT_STRING.force_encoding Encoding::ASCII_8BIT
210
- end
194
+ # Unescape characters in strings.
195
+ UNESCAPE_MAP = Hash.new { |h, k| h[k] = k.chr }
196
+ UNESCAPE_MAP.update({
197
+ ?" => '"',
198
+ ?\\ => '\\',
199
+ ?/ => '/',
200
+ ?b => "\b",
201
+ ?f => "\f",
202
+ ?n => "\n",
203
+ ?r => "\r",
204
+ ?t => "\t",
205
+ ?u => nil,
206
+ })
207
+
208
+ EMPTY_8BIT_STRING = ''
209
+ if ::String.method_defined?(:encode)
210
+ EMPTY_8BIT_STRING.force_encoding Encoding::ASCII_8BIT
211
+ end
211
212
 
212
- def parse_string
213
- if scan(STRING)
214
- return '' if self[1].empty?
215
- string = self[1].gsub(%r((?:\\[\\bfnrt"/]|(?:\\u(?:[A-Fa-f\d]{4}))+|\\[\x20-\xff]))n) do |c|
216
- if u = UNESCAPE_MAP[$&[1]]
217
- u
218
- else # \uXXXX
219
- bytes = EMPTY_8BIT_STRING.dup
220
- i = 0
221
- while c[6 * i] == ?\\ && c[6 * i + 1] == ?u
222
- bytes << c[6 * i + 2, 2].to_i(16) << c[6 * i + 4, 2].to_i(16)
223
- i += 1
213
+ def parse_string
214
+ if scan(STRING)
215
+ return '' if self[1].empty?
216
+ string = self[1].gsub(%r((?:\\[\\bfnrt"/]|(?:\\u(?:[A-Fa-f\d]{4}))+|\\[\x20-\xff]))n) do |c|
217
+ if u = UNESCAPE_MAP[$&[1]]
218
+ u
219
+ else # \uXXXX
220
+ bytes = EMPTY_8BIT_STRING.dup
221
+ i = 0
222
+ while c[6 * i] == ?\\ && c[6 * i + 1] == ?u
223
+ bytes << c[6 * i + 2, 2].to_i(16) << c[6 * i + 4, 2].to_i(16)
224
+ i += 1
225
+ end
226
+ JSON.iconv('utf-8', 'utf-16be', bytes)
224
227
  end
225
- JSON.iconv('utf-8', 'utf-16be', bytes)
226
228
  end
227
- end
228
- if string.respond_to?(:force_encoding)
229
- string.force_encoding(::Encoding::UTF_8)
230
- end
231
- if @create_additions and @match_string
232
- for (regexp, klass) in @match_string
233
- klass.json_creatable? or next
234
- string =~ regexp and return klass.json_create(string)
229
+ if string.respond_to?(:force_encoding)
230
+ string.force_encoding(::Encoding::UTF_8)
231
+ end
232
+ if @create_additions and @match_string
233
+ for (regexp, klass) in @match_string
234
+ klass.json_creatable? or next
235
+ string =~ regexp and return klass.json_create(string)
236
+ end
235
237
  end
238
+ string
239
+ else
240
+ UNPARSED
236
241
  end
237
- string
238
- else
239
- UNPARSED
240
- end
241
- rescue => e
242
- raise ParserError, "Caught #{e.class} at '#{peek(20)}': #{e}"
243
- end
244
-
245
- def parse_value
246
- case
247
- when scan(FLOAT)
248
- Float(self[1])
249
- when scan(INTEGER)
250
- Integer(self[1])
251
- when scan(TRUE)
252
- true
253
- when scan(FALSE)
254
- false
255
- when scan(NULL)
256
- nil
257
- when (string = parse_string) != UNPARSED
258
- string
259
- when scan(ARRAY_OPEN)
260
- @current_nesting += 1
261
- ary = parse_array
262
- @current_nesting -= 1
263
- ary
264
- when scan(OBJECT_OPEN)
265
- @current_nesting += 1
266
- obj = parse_object
267
- @current_nesting -= 1
268
- obj
269
- when @allow_nan && scan(NAN)
270
- NaN
271
- when @allow_nan && scan(INFINITY)
272
- Infinity
273
- when @allow_nan && scan(MINUS_INFINITY)
274
- MinusInfinity
275
- else
276
- UNPARSED
242
+ rescue => e
243
+ raise ParserError, "Caught #{e.class} at '#{peek(20)}': #{e}"
277
244
  end
278
- end
279
245
 
280
- def parse_array
281
- raise NestingError, "nesting of #@current_nesting is too deep" if
282
- @max_nesting.nonzero? && @current_nesting > @max_nesting
283
- result = @array_class.new
284
- delim = false
285
- until eos?
246
+ def parse_value
286
247
  case
287
- when (value = parse_value) != UNPARSED
288
- delim = false
289
- result << value
290
- skip(IGNORE)
291
- if scan(COLLECTION_DELIMITER)
292
- delim = true
293
- elsif match?(ARRAY_CLOSE)
294
- ;
295
- else
296
- raise ParserError, "expected ',' or ']' in array at '#{peek(20)}'!"
297
- end
298
- when scan(ARRAY_CLOSE)
299
- if delim
300
- raise ParserError, "expected next element in array at '#{peek(20)}'!"
301
- end
302
- break
303
- when skip(IGNORE)
304
- ;
248
+ when scan(FLOAT)
249
+ Float(self[1])
250
+ when scan(INTEGER)
251
+ Integer(self[1])
252
+ when scan(TRUE)
253
+ true
254
+ when scan(FALSE)
255
+ false
256
+ when scan(NULL)
257
+ nil
258
+ when (string = parse_string) != UNPARSED
259
+ string
260
+ when scan(ARRAY_OPEN)
261
+ @current_nesting += 1
262
+ ary = parse_array
263
+ @current_nesting -= 1
264
+ ary
265
+ when scan(OBJECT_OPEN)
266
+ @current_nesting += 1
267
+ obj = parse_object
268
+ @current_nesting -= 1
269
+ obj
270
+ when @allow_nan && scan(NAN)
271
+ NaN
272
+ when @allow_nan && scan(INFINITY)
273
+ Infinity
274
+ when @allow_nan && scan(MINUS_INFINITY)
275
+ MinusInfinity
305
276
  else
306
- raise ParserError, "unexpected token in array at '#{peek(20)}'!"
277
+ UNPARSED
307
278
  end
308
279
  end
309
- result
310
- end
311
280
 
312
- def parse_object
313
- raise NestingError, "nesting of #@current_nesting is too deep" if
314
- @max_nesting.nonzero? && @current_nesting > @max_nesting
315
- result = @object_class.new
316
- delim = false
317
- until eos?
318
- case
319
- when (string = parse_string) != UNPARSED
320
- skip(IGNORE)
321
- unless scan(PAIR_DELIMITER)
322
- raise ParserError, "expected ':' in object at '#{peek(20)}'!"
323
- end
324
- skip(IGNORE)
325
- unless (value = parse_value).equal? UNPARSED
326
- result[@symbolize_names ? string.to_sym : string] = value
281
+ def parse_array
282
+ raise NestingError, "nesting of #@current_nesting is too deep" if
283
+ @max_nesting.nonzero? && @current_nesting > @max_nesting
284
+ result = @array_class.new
285
+ delim = false
286
+ until eos?
287
+ case
288
+ when (value = parse_value) != UNPARSED
327
289
  delim = false
290
+ result << value
328
291
  skip(IGNORE)
329
292
  if scan(COLLECTION_DELIMITER)
330
293
  delim = true
331
- elsif match?(OBJECT_CLOSE)
294
+ elsif match?(ARRAY_CLOSE)
332
295
  ;
333
296
  else
334
- raise ParserError, "expected ',' or '}' in object at '#{peek(20)}'!"
297
+ raise ParserError, "expected ',' or ']' in array at '#{peek(20)}'!"
298
+ end
299
+ when scan(ARRAY_CLOSE)
300
+ if delim
301
+ raise ParserError, "expected next element in array at '#{peek(20)}'!"
335
302
  end
303
+ break
304
+ when skip(IGNORE)
305
+ ;
336
306
  else
337
- raise ParserError, "expected value in object at '#{peek(20)}'!"
338
- end
339
- when scan(OBJECT_CLOSE)
340
- if delim
341
- raise ParserError, "expected next name, value pair in object at '#{peek(20)}'!"
307
+ raise ParserError, "unexpected token in array at '#{peek(20)}'!"
342
308
  end
343
- if @create_additions and klassname = result[@create_id]
344
- klass = JSON.deep_const_get klassname
345
- break unless klass and klass.json_creatable?
346
- result = klass.json_create(result)
309
+ end
310
+ result
311
+ end
312
+
313
+ def parse_object
314
+ raise NestingError, "nesting of #@current_nesting is too deep" if
315
+ @max_nesting.nonzero? && @current_nesting > @max_nesting
316
+ result = @object_class.new
317
+ delim = false
318
+ until eos?
319
+ case
320
+ when (string = parse_string) != UNPARSED
321
+ skip(IGNORE)
322
+ unless scan(PAIR_DELIMITER)
323
+ raise ParserError, "expected ':' in object at '#{peek(20)}'!"
324
+ end
325
+ skip(IGNORE)
326
+ unless (value = parse_value).equal? UNPARSED
327
+ result[@symbolize_names ? string.to_sym : string] = value
328
+ delim = false
329
+ skip(IGNORE)
330
+ if scan(COLLECTION_DELIMITER)
331
+ delim = true
332
+ elsif match?(OBJECT_CLOSE)
333
+ ;
334
+ else
335
+ raise ParserError, "expected ',' or '}' in object at '#{peek(20)}'!"
336
+ end
337
+ else
338
+ raise ParserError, "expected value in object at '#{peek(20)}'!"
339
+ end
340
+ when scan(OBJECT_CLOSE)
341
+ if delim
342
+ raise ParserError, "expected next name, value pair in object at '#{peek(20)}'!"
343
+ end
344
+ if @create_additions and klassname = result[@create_id]
345
+ klass = JSON.deep_const_get klassname
346
+ break unless klass and klass.json_creatable?
347
+ result = klass.json_create(result)
348
+ end
349
+ break
350
+ when skip(IGNORE)
351
+ ;
352
+ else
353
+ raise ParserError, "unexpected token in object at '#{peek(20)}'!"
347
354
  end
348
- break
349
- when skip(IGNORE)
350
- ;
351
- else
352
- raise ParserError, "unexpected token in object at '#{peek(20)}'!"
353
355
  end
356
+ result
354
357
  end
355
- result
356
358
  end
357
359
  end
358
360
  end
359
- end
360
361
 
361
- module JSON
362
- MAP = {
363
- "\x0" => '\u0000',
364
- "\x1" => '\u0001',
365
- "\x2" => '\u0002',
366
- "\x3" => '\u0003',
367
- "\x4" => '\u0004',
368
- "\x5" => '\u0005',
369
- "\x6" => '\u0006',
370
- "\x7" => '\u0007',
371
- "\b" => '\b',
372
- "\t" => '\t',
373
- "\n" => '\n',
374
- "\xb" => '\u000b',
375
- "\f" => '\f',
376
- "\r" => '\r',
377
- "\xe" => '\u000e',
378
- "\xf" => '\u000f',
379
- "\x10" => '\u0010',
380
- "\x11" => '\u0011',
381
- "\x12" => '\u0012',
382
- "\x13" => '\u0013',
383
- "\x14" => '\u0014',
384
- "\x15" => '\u0015',
385
- "\x16" => '\u0016',
386
- "\x17" => '\u0017',
387
- "\x18" => '\u0018',
388
- "\x19" => '\u0019',
389
- "\x1a" => '\u001a',
390
- "\x1b" => '\u001b',
391
- "\x1c" => '\u001c',
392
- "\x1d" => '\u001d',
393
- "\x1e" => '\u001e',
394
- "\x1f" => '\u001f',
395
- '"' => '\"',
396
- '\\' => '\\\\',
397
- } # :nodoc:
398
-
399
- # Convert a UTF8 encoded Ruby string _string_ to a JSON string, encoded with
400
- # UTF16 big endian characters as \u????, and return it.
401
- if defined?(::Encoding)
402
- def utf8_to_json(string) # :nodoc:
403
- string = string.dup
404
- string << '' # XXX workaround: avoid buffer sharing
405
- string.force_encoding(::Encoding::ASCII_8BIT)
406
- string.gsub!(/["\\\x0-\x1f]/) { MAP[$&] }
407
- string.force_encoding(::Encoding::UTF_8)
408
- string
409
- end
362
+ module JSON
363
+ MAP = {
364
+ "\x0" => '\u0000',
365
+ "\x1" => '\u0001',
366
+ "\x2" => '\u0002',
367
+ "\x3" => '\u0003',
368
+ "\x4" => '\u0004',
369
+ "\x5" => '\u0005',
370
+ "\x6" => '\u0006',
371
+ "\x7" => '\u0007',
372
+ "\b" => '\b',
373
+ "\t" => '\t',
374
+ "\n" => '\n',
375
+ "\xb" => '\u000b',
376
+ "\f" => '\f',
377
+ "\r" => '\r',
378
+ "\xe" => '\u000e',
379
+ "\xf" => '\u000f',
380
+ "\x10" => '\u0010',
381
+ "\x11" => '\u0011',
382
+ "\x12" => '\u0012',
383
+ "\x13" => '\u0013',
384
+ "\x14" => '\u0014',
385
+ "\x15" => '\u0015',
386
+ "\x16" => '\u0016',
387
+ "\x17" => '\u0017',
388
+ "\x18" => '\u0018',
389
+ "\x19" => '\u0019',
390
+ "\x1a" => '\u001a',
391
+ "\x1b" => '\u001b',
392
+ "\x1c" => '\u001c',
393
+ "\x1d" => '\u001d',
394
+ "\x1e" => '\u001e',
395
+ "\x1f" => '\u001f',
396
+ '"' => '\"',
397
+ '\\' => '\\\\',
398
+ } # :nodoc:
399
+
400
+ # Convert a UTF8 encoded Ruby string _string_ to a JSON string, encoded with
401
+ # UTF16 big endian characters as \u????, and return it.
402
+ if defined?(::Encoding)
403
+ def utf8_to_json(string) # :nodoc:
404
+ string = string.dup
405
+ string << '' # XXX workaround: avoid buffer sharing
406
+ string.force_encoding(::Encoding::ASCII_8BIT)
407
+ string.gsub!(/["\\\x0-\x1f]/) { MAP[$&] }
408
+ string.force_encoding(::Encoding::UTF_8)
409
+ string
410
+ end
410
411
 
411
- def utf8_to_json_ascii(string) # :nodoc:
412
- string = string.dup
413
- string << '' # XXX workaround: avoid buffer sharing
414
- string.force_encoding(::Encoding::ASCII_8BIT)
415
- string.gsub!(/["\\\x0-\x1f]/) { MAP[$&] }
416
- string.gsub!(/(
417
- (?:
418
- [\xc2-\xdf][\x80-\xbf] |
419
- [\xe0-\xef][\x80-\xbf]{2} |
420
- [\xf0-\xf4][\x80-\xbf]{3}
421
- )+ |
422
- [\x80-\xc1\xf5-\xff] # invalid
423
- )/nx) { |c|
424
- c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'"
425
- s = JSON.iconv('utf-16be', 'utf-8', c).unpack('H*')[0]
426
- s.gsub!(/.{4}/n, '\\\\u\&')
427
- }
428
- string.force_encoding(::Encoding::UTF_8)
429
- string
430
- rescue => e
431
- raise GeneratorError, "Caught #{e.class}: #{e}"
432
- end
433
- else
434
- def utf8_to_json(string) # :nodoc:
435
- string.gsub(/["\\\x0-\x1f]/) { MAP[$&] }
436
- end
412
+ def utf8_to_json_ascii(string) # :nodoc:
413
+ string = string.dup
414
+ string << '' # XXX workaround: avoid buffer sharing
415
+ string.force_encoding(::Encoding::ASCII_8BIT)
416
+ string.gsub!(/["\\\x0-\x1f]/) { MAP[$&] }
417
+ string.gsub!(/(
418
+ (?:
419
+ [\xc2-\xdf][\x80-\xbf] |
420
+ [\xe0-\xef][\x80-\xbf]{2} |
421
+ [\xf0-\xf4][\x80-\xbf]{3}
422
+ )+ |
423
+ [\x80-\xc1\xf5-\xff] # invalid
424
+ )/nx) { |c|
425
+ c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'"
426
+ s = JSON.iconv('utf-16be', 'utf-8', c).unpack('H*')[0]
427
+ s.gsub!(/.{4}/n, '\\\\u\&')
428
+ }
429
+ string.force_encoding(::Encoding::UTF_8)
430
+ string
431
+ rescue => e
432
+ raise GeneratorError, "Caught #{e.class}: #{e}"
433
+ end
434
+ else
435
+ def utf8_to_json(string) # :nodoc:
436
+ string.gsub(/["\\\x0-\x1f]/) { MAP[$&] }
437
+ end
437
438
 
438
- def utf8_to_json_ascii(string) # :nodoc:
439
- string = string.gsub(/["\\\x0-\x1f]/) { MAP[$&] }
440
- string.gsub!(/(
441
- (?:
442
- [\xc2-\xdf][\x80-\xbf] |
443
- [\xe0-\xef][\x80-\xbf]{2} |
444
- [\xf0-\xf4][\x80-\xbf]{3}
445
- )+ |
446
- [\x80-\xc1\xf5-\xff] # invalid
447
- )/nx) { |c|
448
- c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'"
449
- s = JSON.iconv('utf-16be', 'utf-8', c).unpack('H*')[0]
450
- s.gsub!(/.{4}/n, '\\\\u\&')
451
- }
452
- string
453
- rescue => e
454
- raise GeneratorError, "Caught #{e.class}: #{e}"
439
+ def utf8_to_json_ascii(string) # :nodoc:
440
+ string = string.gsub(/["\\\x0-\x1f]/) { MAP[$&] }
441
+ string.gsub!(/(
442
+ (?:
443
+ [\xc2-\xdf][\x80-\xbf] |
444
+ [\xe0-\xef][\x80-\xbf]{2} |
445
+ [\xf0-\xf4][\x80-\xbf]{3}
446
+ )+ |
447
+ [\x80-\xc1\xf5-\xff] # invalid
448
+ )/nx) { |c|
449
+ c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'"
450
+ s = JSON.iconv('utf-16be', 'utf-8', c).unpack('H*')[0]
451
+ s.gsub!(/.{4}/n, '\\\\u\&')
452
+ }
453
+ string
454
+ rescue => e
455
+ raise GeneratorError, "Caught #{e.class}: #{e}"
456
+ end
455
457
  end
456
- end
457
- module_function :utf8_to_json, :utf8_to_json_ascii
458
-
459
- module Pure
460
- module Generator
461
- # This class is used to create State instances, that are use to hold data
462
- # while generating a JSON text from a Ruby data structure.
463
- class State
464
- # Creates a State object from _opts_, which ought to be Hash to create
465
- # a new State instance configured by _opts_, something else to create
466
- # an unconfigured instance. If _opts_ is a State object, it is just
467
- # returned.
468
- def self.from_state(opts)
469
- case
470
- when self === opts
471
- opts
472
- when opts.respond_to?(:to_hash)
473
- new(opts.to_hash)
474
- when opts.respond_to?(:to_h)
475
- new(opts.to_h)
476
- else
477
- SAFE_STATE_PROTOTYPE.dup
458
+ module_function :utf8_to_json, :utf8_to_json_ascii
459
+
460
+ module Pure
461
+ module Generator
462
+ # This class is used to create State instances, that are use to hold data
463
+ # while generating a JSON text from a Ruby data structure.
464
+ class State
465
+ # Creates a State object from _opts_, which ought to be Hash to create
466
+ # a new State instance configured by _opts_, something else to create
467
+ # an unconfigured instance. If _opts_ is a State object, it is just
468
+ # returned.
469
+ def self.from_state(opts)
470
+ case
471
+ when self === opts
472
+ opts
473
+ when opts.respond_to?(:to_hash)
474
+ new(opts.to_hash)
475
+ when opts.respond_to?(:to_h)
476
+ new(opts.to_h)
477
+ else
478
+ SAFE_STATE_PROTOTYPE.dup
479
+ end
478
480
  end
479
- end
480
481
 
481
- # Instantiates a new State object, configured by _opts_.
482
- #
483
- # _opts_ can have the following keys:
484
- #
485
- # * *indent*: a string used to indent levels (default: ''),
486
- # * *space*: a string that is put after, a : or , delimiter (default: ''),
487
- # * *space_before*: a string that is put before a : pair delimiter (default: ''),
488
- # * *object_nl*: a string that is put at the end of a JSON object (default: ''),
489
- # * *array_nl*: a string that is put at the end of a JSON array (default: ''),
490
- # * *check_circular*: is deprecated now, use the :max_nesting option instead,
491
- # * *max_nesting*: sets the maximum level of data structure nesting in
492
- # the generated JSON, max_nesting = 0 if no maximum should be checked.
493
- # * *allow_nan*: true if NaN, Infinity, and -Infinity should be
494
- # generated, otherwise an exception is thrown, if these values are
495
- # encountered. This options defaults to false.
496
- # * *quirks_mode*: Enables quirks_mode for parser, that is for example
497
- # generating single JSON values instead of documents is possible.
498
- def initialize(opts = {})
499
- @indent = ''
500
- @space = ''
501
- @space_before = ''
502
- @object_nl = ''
503
- @array_nl = ''
504
- @allow_nan = false
505
- @ascii_only = false
506
- @quirks_mode = false
507
- @buffer_initial_length = 1024
508
- configure opts
509
- end
482
+ # Instantiates a new State object, configured by _opts_.
483
+ #
484
+ # _opts_ can have the following keys:
485
+ #
486
+ # * *indent*: a string used to indent levels (default: ''),
487
+ # * *space*: a string that is put after, a : or , delimiter (default: ''),
488
+ # * *space_before*: a string that is put before a : pair delimiter (default: ''),
489
+ # * *object_nl*: a string that is put at the end of a JSON object (default: ''),
490
+ # * *array_nl*: a string that is put at the end of a JSON array (default: ''),
491
+ # * *check_circular*: is deprecated now, use the :max_nesting option instead,
492
+ # * *max_nesting*: sets the maximum level of data structure nesting in
493
+ # the generated JSON, max_nesting = 0 if no maximum should be checked.
494
+ # * *allow_nan*: true if NaN, Infinity, and -Infinity should be
495
+ # generated, otherwise an exception is thrown, if these values are
496
+ # encountered. This options defaults to false.
497
+ # * *quirks_mode*: Enables quirks_mode for parser, that is for example
498
+ # generating single JSON values instead of documents is possible.
499
+ def initialize(opts = {})
500
+ @indent = ''
501
+ @space = ''
502
+ @space_before = ''
503
+ @object_nl = ''
504
+ @array_nl = ''
505
+ @allow_nan = false
506
+ @ascii_only = false
507
+ @quirks_mode = false
508
+ @buffer_initial_length = 1024
509
+ configure opts
510
+ end
510
511
 
511
- # This string is used to indent levels in the JSON text.
512
- attr_accessor :indent
512
+ # This string is used to indent levels in the JSON text.
513
+ attr_accessor :indent
513
514
 
514
- # This string is used to insert a space between the tokens in a JSON
515
- # string.
516
- attr_accessor :space
515
+ # This string is used to insert a space between the tokens in a JSON
516
+ # string.
517
+ attr_accessor :space
517
518
 
518
- # This string is used to insert a space before the ':' in JSON objects.
519
- attr_accessor :space_before
519
+ # This string is used to insert a space before the ':' in JSON objects.
520
+ attr_accessor :space_before
520
521
 
521
- # This string is put at the end of a line that holds a JSON object (or
522
- # Hash).
523
- attr_accessor :object_nl
522
+ # This string is put at the end of a line that holds a JSON object (or
523
+ # Hash).
524
+ attr_accessor :object_nl
524
525
 
525
- # This string is put at the end of a line that holds a JSON array.
526
- attr_accessor :array_nl
526
+ # This string is put at the end of a line that holds a JSON array.
527
+ attr_accessor :array_nl
527
528
 
528
- # This integer returns the maximum level of data structure nesting in
529
- # the generated JSON, max_nesting = 0 if no maximum is checked.
530
- attr_accessor :max_nesting
529
+ # This integer returns the maximum level of data structure nesting in
530
+ # the generated JSON, max_nesting = 0 if no maximum is checked.
531
+ attr_accessor :max_nesting
531
532
 
532
- # If this attribute is set to true, quirks mode is enabled, otherwise
533
- # it's disabled.
534
- attr_accessor :quirks_mode
533
+ # If this attribute is set to true, quirks mode is enabled, otherwise
534
+ # it's disabled.
535
+ attr_accessor :quirks_mode
535
536
 
536
- # :stopdoc:
537
- attr_reader :buffer_initial_length
537
+ # :stopdoc:
538
+ attr_reader :buffer_initial_length
538
539
 
539
- def buffer_initial_length=(length)
540
- if length > 0
541
- @buffer_initial_length = length
540
+ def buffer_initial_length=(length)
541
+ if length > 0
542
+ @buffer_initial_length = length
543
+ end
542
544
  end
543
- end
544
- # :startdoc:
545
+ # :startdoc:
545
546
 
546
- # This integer returns the current depth data structure nesting in the
547
- # generated JSON.
548
- attr_accessor :depth
547
+ # This integer returns the current depth data structure nesting in the
548
+ # generated JSON.
549
+ attr_accessor :depth
549
550
 
550
- def check_max_nesting # :nodoc:
551
- return if @max_nesting.zero?
552
- current_nesting = depth + 1
553
- current_nesting > @max_nesting and
554
- raise NestingError, "nesting of #{current_nesting} is too deep"
555
- end
551
+ def check_max_nesting # :nodoc:
552
+ return if @max_nesting.zero?
553
+ current_nesting = depth + 1
554
+ current_nesting > @max_nesting and
555
+ raise NestingError, "nesting of #{current_nesting} is too deep"
556
+ end
556
557
 
557
- # Returns true, if circular data structures are checked,
558
- # otherwise returns false.
559
- def check_circular?
560
- !@max_nesting.zero?
561
- end
558
+ # Returns true, if circular data structures are checked,
559
+ # otherwise returns false.
560
+ def check_circular?
561
+ !@max_nesting.zero?
562
+ end
562
563
 
563
- # Returns true if NaN, Infinity, and -Infinity should be considered as
564
- # valid JSON and output.
565
- def allow_nan?
566
- @allow_nan
567
- end
564
+ # Returns true if NaN, Infinity, and -Infinity should be considered as
565
+ # valid JSON and output.
566
+ def allow_nan?
567
+ @allow_nan
568
+ end
568
569
 
569
- # Returns true, if only ASCII characters should be generated. Otherwise
570
- # returns false.
571
- def ascii_only?
572
- @ascii_only
573
- end
570
+ # Returns true, if only ASCII characters should be generated. Otherwise
571
+ # returns false.
572
+ def ascii_only?
573
+ @ascii_only
574
+ end
574
575
 
575
- # Returns true, if quirks mode is enabled. Otherwise returns false.
576
- def quirks_mode?
577
- @quirks_mode
578
- end
576
+ # Returns true, if quirks mode is enabled. Otherwise returns false.
577
+ def quirks_mode?
578
+ @quirks_mode
579
+ end
579
580
 
580
- # Configure this State instance with the Hash _opts_, and return
581
- # itself.
582
- def configure(opts)
583
- @indent = opts[:indent] if opts.key?(:indent)
584
- @space = opts[:space] if opts.key?(:space)
585
- @space_before = opts[:space_before] if opts.key?(:space_before)
586
- @object_nl = opts[:object_nl] if opts.key?(:object_nl)
587
- @array_nl = opts[:array_nl] if opts.key?(:array_nl)
588
- @allow_nan = !!opts[:allow_nan] if opts.key?(:allow_nan)
589
- @ascii_only = opts[:ascii_only] if opts.key?(:ascii_only)
590
- @depth = opts[:depth] || 0
591
- @quirks_mode = opts[:quirks_mode] if opts.key?(:quirks_mode)
592
- if !opts.key?(:max_nesting) # defaults to 19
593
- @max_nesting = 19
594
- elsif opts[:max_nesting]
595
- @max_nesting = opts[:max_nesting]
596
- else
597
- @max_nesting = 0
581
+ # Configure this State instance with the Hash _opts_, and return
582
+ # itself.
583
+ def configure(opts)
584
+ @indent = opts[:indent] if opts.key?(:indent)
585
+ @space = opts[:space] if opts.key?(:space)
586
+ @space_before = opts[:space_before] if opts.key?(:space_before)
587
+ @object_nl = opts[:object_nl] if opts.key?(:object_nl)
588
+ @array_nl = opts[:array_nl] if opts.key?(:array_nl)
589
+ @allow_nan = !!opts[:allow_nan] if opts.key?(:allow_nan)
590
+ @ascii_only = opts[:ascii_only] if opts.key?(:ascii_only)
591
+ @depth = opts[:depth] || 0
592
+ @quirks_mode = opts[:quirks_mode] if opts.key?(:quirks_mode)
593
+ if !opts.key?(:max_nesting) # defaults to 19
594
+ @max_nesting = 19
595
+ elsif opts[:max_nesting]
596
+ @max_nesting = opts[:max_nesting]
597
+ else
598
+ @max_nesting = 0
599
+ end
600
+ self
598
601
  end
599
- self
600
- end
601
- alias merge configure
602
-
603
- # Returns the configuration instance variables as a hash, that can be
604
- # passed to the configure method.
605
- def to_h
606
- result = {}
607
- for iv in %w[indent space space_before object_nl array_nl allow_nan max_nesting ascii_only quirks_mode buffer_initial_length depth]
608
- result[iv.intern] = instance_variable_get("@#{iv}")
602
+ alias merge configure
603
+
604
+ # Returns the configuration instance variables as a hash, that can be
605
+ # passed to the configure method.
606
+ def to_h
607
+ result = {}
608
+ for iv in %w[indent space space_before object_nl array_nl allow_nan max_nesting ascii_only quirks_mode buffer_initial_length depth]
609
+ result[iv.intern] = instance_variable_get("@#{iv}")
610
+ end
611
+ result
609
612
  end
610
- result
611
- end
612
613
 
613
- # Generates a valid JSON document from object +obj+ and returns the
614
- # result. If no valid JSON document can be created this method raises a
615
- # GeneratorError exception.
616
- def generate(obj)
617
- result = obj.to_json(self)
618
- unless @quirks_mode
619
- unless result =~ /\A\s*\[/ && result =~ /\]\s*\Z/ ||
620
- result =~ /\A\s*\{/ && result =~ /\}\s*\Z/
621
- then
622
- raise GeneratorError, "only generation of JSON objects or arrays allowed"
614
+ # Generates a valid JSON document from object +obj+ and returns the
615
+ # result. If no valid JSON document can be created this method raises a
616
+ # GeneratorError exception.
617
+ def generate(obj)
618
+ result = obj.to_json(self)
619
+ unless @quirks_mode
620
+ unless result =~ /\A\s*\[/ && result =~ /\]\s*\Z/ ||
621
+ result =~ /\A\s*\{/ && result =~ /\}\s*\Z/
622
+ then
623
+ raise GeneratorError, "only generation of JSON objects or arrays allowed"
624
+ end
623
625
  end
626
+ result
624
627
  end
625
- result
626
- end
627
628
 
628
- # Return the value returned by method +name+.
629
- def [](name)
630
- __send__ name
631
- end
632
- end
633
-
634
- module GeneratorMethods
635
- module Object
636
- # Converts this object to a string (calling #to_s), converts
637
- # it to a JSON string, and returns the result. This is a fallback, if no
638
- # special method #to_json was defined for some object.
639
- def to_json(*) to_s.to_json end
629
+ # Return the value returned by method +name+.
630
+ def [](name)
631
+ __send__ name
632
+ end
640
633
  end
641
634
 
642
- module Hash
643
- # Returns a JSON string containing a JSON object, that is unparsed from
644
- # this Hash instance.
645
- # _state_ is a JSON::State object, that can also be used to configure the
646
- # produced JSON string output further.
647
- # _depth_ is used to find out nesting depth, to indent accordingly.
648
- def to_json(state = nil, *)
649
- state = State.from_state(state)
650
- state.check_max_nesting
651
- json_transform(state)
635
+ module GeneratorMethods
636
+ module Object
637
+ # Converts this object to a string (calling #to_s), converts
638
+ # it to a JSON string, and returns the result. This is a fallback, if no
639
+ # special method #to_json was defined for some object.
640
+ def to_json(*) to_s.to_json end
652
641
  end
653
642
 
654
- private
643
+ module Hash
644
+ # Returns a JSON string containing a JSON object, that is unparsed from
645
+ # this Hash instance.
646
+ # _state_ is a JSON::State object, that can also be used to configure the
647
+ # produced JSON string output further.
648
+ # _depth_ is used to find out nesting depth, to indent accordingly.
649
+ def to_json(state = nil, *)
650
+ state = State.from_state(state)
651
+ state.check_max_nesting
652
+ json_transform(state)
653
+ end
655
654
 
656
- def json_shift(state)
657
- state.object_nl.empty? or return ''
658
- state.indent * state.depth
659
- end
655
+ private
660
656
 
661
- def json_transform(state)
662
- delim = ','
663
- delim << state.object_nl
664
- result = '{'
665
- result << state.object_nl
666
- depth = state.depth += 1
667
- first = true
668
- indent = !state.object_nl.empty?
669
- each { |key,value|
670
- result << delim unless first
671
- result << state.indent * depth if indent
672
- result << key.to_s.to_json(state)
673
- result << state.space_before
674
- result << ':'
675
- result << state.space
676
- result << value.to_json(state)
677
- first = false
678
- }
679
- depth = state.depth -= 1
680
- result << state.object_nl
681
- result << state.indent * depth if indent if indent
682
- result << '}'
683
- result
684
- end
685
- end
657
+ def json_shift(state)
658
+ state.object_nl.empty? or return ''
659
+ state.indent * state.depth
660
+ end
686
661
 
687
- module Array
688
- # Returns a JSON string containing a JSON array, that is unparsed from
689
- # this Array instance.
690
- # _state_ is a JSON::State object, that can also be used to configure the
691
- # produced JSON string output further.
692
- def to_json(state = nil, *)
693
- state = State.from_state(state)
694
- state.check_max_nesting
695
- json_transform(state)
662
+ def json_transform(state)
663
+ delim = ','
664
+ delim << state.object_nl
665
+ result = '{'
666
+ result << state.object_nl
667
+ depth = state.depth += 1
668
+ first = true
669
+ indent = !state.object_nl.empty?
670
+ each { |key,value|
671
+ result << delim unless first
672
+ result << state.indent * depth if indent
673
+ result << key.to_s.to_json(state)
674
+ result << state.space_before
675
+ result << ':'
676
+ result << state.space
677
+ result << value.to_json(state)
678
+ first = false
679
+ }
680
+ depth = state.depth -= 1
681
+ result << state.object_nl
682
+ result << state.indent * depth if indent if indent
683
+ result << '}'
684
+ result
685
+ end
696
686
  end
697
687
 
698
- private
699
-
700
- def json_transform(state)
701
- delim = ','
702
- delim << state.array_nl
703
- result = '['
704
- result << state.array_nl
705
- depth = state.depth += 1
706
- first = true
707
- indent = !state.array_nl.empty?
708
- each { |value|
709
- result << delim unless first
688
+ module Array
689
+ # Returns a JSON string containing a JSON array, that is unparsed from
690
+ # this Array instance.
691
+ # _state_ is a JSON::State object, that can also be used to configure the
692
+ # produced JSON string output further.
693
+ def to_json(state = nil, *)
694
+ state = State.from_state(state)
695
+ state.check_max_nesting
696
+ json_transform(state)
697
+ end
698
+
699
+ private
700
+
701
+ def json_transform(state)
702
+ delim = ','
703
+ delim << state.array_nl
704
+ result = '['
705
+ result << state.array_nl
706
+ depth = state.depth += 1
707
+ first = true
708
+ indent = !state.array_nl.empty?
709
+ each { |value|
710
+ result << delim unless first
711
+ result << state.indent * depth if indent
712
+ result << value.to_json(state)
713
+ first = false
714
+ }
715
+ depth = state.depth -= 1
716
+ result << state.array_nl
710
717
  result << state.indent * depth if indent
711
- result << value.to_json(state)
712
- first = false
713
- }
714
- depth = state.depth -= 1
715
- result << state.array_nl
716
- result << state.indent * depth if indent
717
- result << ']'
718
+ result << ']'
719
+ end
718
720
  end
719
- end
720
721
 
721
- module Integer
722
- # Returns a JSON string representation for this Integer number.
723
- def to_json(*) to_s end
724
- end
722
+ module Integer
723
+ # Returns a JSON string representation for this Integer number.
724
+ def to_json(*) to_s end
725
+ end
725
726
 
726
- module Float
727
- # Returns a JSON string representation for this Float number.
728
- def to_json(state = nil, *)
729
- state = State.from_state(state)
730
- case
731
- when infinite?
732
- if state.allow_nan?
733
- to_s
727
+ module Float
728
+ # Returns a JSON string representation for this Float number.
729
+ def to_json(state = nil, *)
730
+ state = State.from_state(state)
731
+ case
732
+ when infinite?
733
+ if state.allow_nan?
734
+ to_s
735
+ else
736
+ raise GeneratorError, "#{self} not allowed in JSON"
737
+ end
738
+ when nan?
739
+ if state.allow_nan?
740
+ to_s
741
+ else
742
+ raise GeneratorError, "#{self} not allowed in JSON"
743
+ end
734
744
  else
735
- raise GeneratorError, "#{self} not allowed in JSON"
736
- end
737
- when nan?
738
- if state.allow_nan?
739
745
  to_s
740
- else
741
- raise GeneratorError, "#{self} not allowed in JSON"
742
746
  end
743
- else
744
- to_s
745
747
  end
746
748
  end
747
- end
748
749
 
749
- module String
750
- if defined?(::Encoding)
751
- # This string should be encoded with UTF-8 A call to this method
752
- # returns a JSON string encoded with UTF16 big endian characters as
753
- # \u????.
754
- def to_json(state = nil, *args)
755
- state = State.from_state(state)
756
- if encoding == ::Encoding::UTF_8
757
- string = self
758
- else
759
- string = encode(::Encoding::UTF_8)
750
+ module String
751
+ if defined?(::Encoding)
752
+ # This string should be encoded with UTF-8 A call to this method
753
+ # returns a JSON string encoded with UTF16 big endian characters as
754
+ # \u????.
755
+ def to_json(state = nil, *args)
756
+ state = State.from_state(state)
757
+ if encoding == ::Encoding::UTF_8
758
+ string = self
759
+ else
760
+ string = encode(::Encoding::UTF_8)
761
+ end
762
+ if state.ascii_only?
763
+ '"' << JSON.utf8_to_json_ascii(string) << '"'
764
+ else
765
+ '"' << JSON.utf8_to_json(string) << '"'
766
+ end
760
767
  end
761
- if state.ascii_only?
762
- '"' << JSON.utf8_to_json_ascii(string) << '"'
763
- else
764
- '"' << JSON.utf8_to_json(string) << '"'
768
+ else
769
+ # This string should be encoded with UTF-8 A call to this method
770
+ # returns a JSON string encoded with UTF16 big endian characters as
771
+ # \u????.
772
+ def to_json(state = nil, *args)
773
+ state = State.from_state(state)
774
+ if state.ascii_only?
775
+ '"' << JSON.utf8_to_json_ascii(self) << '"'
776
+ else
777
+ '"' << JSON.utf8_to_json(self) << '"'
778
+ end
765
779
  end
766
780
  end
767
- else
768
- # This string should be encoded with UTF-8 A call to this method
769
- # returns a JSON string encoded with UTF16 big endian characters as
770
- # \u????.
771
- def to_json(state = nil, *args)
772
- state = State.from_state(state)
773
- if state.ascii_only?
774
- '"' << JSON.utf8_to_json_ascii(self) << '"'
775
- else
776
- '"' << JSON.utf8_to_json(self) << '"'
781
+
782
+ # Module that holds the extinding methods if, the String module is
783
+ # included.
784
+ module Extend
785
+ # Raw Strings are JSON Objects (the raw bytes are stored in an
786
+ # array for the key "raw"). The Ruby String can be created by this
787
+ # module method.
788
+ def json_create(o)
789
+ o['raw'].pack('C*')
777
790
  end
778
791
  end
779
- end
780
792
 
781
- # Module that holds the extinding methods if, the String module is
782
- # included.
783
- module Extend
784
- # Raw Strings are JSON Objects (the raw bytes are stored in an
785
- # array for the key "raw"). The Ruby String can be created by this
786
- # module method.
787
- def json_create(o)
788
- o['raw'].pack('C*')
793
+ # Extends _modul_ with the String::Extend module.
794
+ def self.included(modul)
795
+ modul.extend Extend
789
796
  end
790
- end
791
797
 
792
- # Extends _modul_ with the String::Extend module.
793
- def self.included(modul)
794
- modul.extend Extend
795
- end
798
+ # This method creates a raw object hash, that can be nested into
799
+ # other data structures and will be unparsed as a raw string. This
800
+ # method should be used, if you want to convert raw strings to JSON
801
+ # instead of UTF-8 strings, e. g. binary data.
802
+ def to_json_raw_object
803
+ {
804
+ JSON.create_id => self.class.name,
805
+ 'raw' => self.unpack('C*'),
806
+ }
807
+ end
796
808
 
797
- # This method creates a raw object hash, that can be nested into
798
- # other data structures and will be unparsed as a raw string. This
799
- # method should be used, if you want to convert raw strings to JSON
800
- # instead of UTF-8 strings, e. g. binary data.
801
- def to_json_raw_object
802
- {
803
- JSON.create_id => self.class.name,
804
- 'raw' => self.unpack('C*'),
805
- }
809
+ # This method creates a JSON text from the result of
810
+ # a call to to_json_raw_object of this String.
811
+ def to_json_raw(*args)
812
+ to_json_raw_object.to_json(*args)
813
+ end
806
814
  end
807
815
 
808
- # This method creates a JSON text from the result of
809
- # a call to to_json_raw_object of this String.
810
- def to_json_raw(*args)
811
- to_json_raw_object.to_json(*args)
816
+ module TrueClass
817
+ # Returns a JSON string for true: 'true'.
818
+ def to_json(*) 'true' end
812
819
  end
813
- end
814
-
815
- module TrueClass
816
- # Returns a JSON string for true: 'true'.
817
- def to_json(*) 'true' end
818
- end
819
820
 
820
- module FalseClass
821
- # Returns a JSON string for false: 'false'.
822
- def to_json(*) 'false' end
823
- end
821
+ module FalseClass
822
+ # Returns a JSON string for false: 'false'.
823
+ def to_json(*) 'false' end
824
+ end
824
825
 
825
- module NilClass
826
- # Returns a JSON string for nil: 'null'.
827
- def to_json(*) 'null' end
826
+ module NilClass
827
+ # Returns a JSON string for nil: 'null'.
828
+ def to_json(*) 'null' end
829
+ end
828
830
  end
829
831
  end
830
832
  end
831
833
  end
832
- end
833
834
 
834
- module JSON
835
- class << self
836
- # If _object_ is string-like, parse the string and return the parsed result
837
- # as a Ruby data structure. Otherwise generate a JSON text from the Ruby
838
- # data structure object and return it.
839
- #
840
- # The _opts_ argument is passed through to generate/parse respectively. See
841
- # generate and parse for their documentation.
842
- def [](object, opts = {})
843
- if object.respond_to? :to_str
844
- JSON.parse(object.to_str, opts)
845
- else
846
- JSON.generate(object, opts)
835
+ module JSON
836
+ class << self
837
+ # If _object_ is string-like, parse the string and return the parsed result
838
+ # as a Ruby data structure. Otherwise generate a JSON text from the Ruby
839
+ # data structure object and return it.
840
+ #
841
+ # The _opts_ argument is passed through to generate/parse respectively. See
842
+ # generate and parse for their documentation.
843
+ def [](object, opts = {})
844
+ if object.respond_to? :to_str
845
+ JSON.parse(object.to_str, opts)
846
+ else
847
+ JSON.generate(object, opts)
848
+ end
847
849
  end
848
- end
849
850
 
850
- # Returns the JSON parser class that is used by JSON. This is either
851
- # JSON::Ext::Parser or JSON::Pure::Parser.
852
- attr_reader :parser
851
+ # Returns the JSON parser class that is used by JSON. This is either
852
+ # JSON::Ext::Parser or JSON::Pure::Parser.
853
+ attr_reader :parser
853
854
 
854
- # Set the JSON parser class _parser_ to be used by JSON.
855
- def parser=(parser) # :nodoc:
856
- @parser = parser
857
- remove_const :Parser if JSON.const_defined_in?(self, :Parser)
858
- const_set :Parser, parser
859
- end
855
+ # Set the JSON parser class _parser_ to be used by JSON.
856
+ def parser=(parser) # :nodoc:
857
+ @parser = parser
858
+ remove_const :Parser if JSON.const_defined_in?(self, :Parser)
859
+ const_set :Parser, parser
860
+ end
860
861
 
861
- # Return the constant located at _path_. The format of _path_ has to be
862
- # either ::A::B::C or A::B::C. In any case, A has to be located at the top
863
- # level (absolute namespace path?). If there doesn't exist a constant at
864
- # the given path, an ArgumentError is raised.
865
- def deep_const_get(path) # :nodoc:
866
- path.to_s.split(/::/).inject(Object) do |p, c|
867
- case
868
- when c.empty? then p
869
- when JSON.const_defined_in?(p, c) then p.const_get(c)
870
- else
871
- begin
872
- p.const_missing(c)
873
- rescue NameError => e
874
- raise ArgumentError, "can't get const #{path}: #{e}"
862
+ # Return the constant located at _path_. The format of _path_ has to be
863
+ # either ::A::B::C or A::B::C. In any case, A has to be located at the top
864
+ # level (absolute namespace path?). If there doesn't exist a constant at
865
+ # the given path, an ArgumentError is raised.
866
+ def deep_const_get(path) # :nodoc:
867
+ path.to_s.split(/::/).inject(Object) do |p, c|
868
+ case
869
+ when c.empty? then p
870
+ when JSON.const_defined_in?(p, c) then p.const_get(c)
871
+ else
872
+ begin
873
+ p.const_missing(c)
874
+ rescue NameError => e
875
+ raise ArgumentError, "can't get const #{path}: #{e}"
876
+ end
875
877
  end
876
878
  end
877
879
  end
878
- end
879
880
 
880
- # Set the module _generator_ to be used by JSON.
881
- def generator=(generator) # :nodoc:
882
- old, $VERBOSE = $VERBOSE, nil
883
- @generator = generator
884
- generator_methods = generator::GeneratorMethods
885
- for const in generator_methods.constants
886
- klass = deep_const_get(const)
887
- modul = generator_methods.const_get(const)
888
- klass.class_eval do
889
- instance_methods(false).each do |m|
890
- m.to_s == 'to_json' and remove_method m
881
+ # Set the module _generator_ to be used by JSON.
882
+ def generator=(generator) # :nodoc:
883
+ old, $VERBOSE = $VERBOSE, nil
884
+ @generator = generator
885
+ generator_methods = generator::GeneratorMethods
886
+ for const in generator_methods.constants
887
+ klass = deep_const_get(const)
888
+ modul = generator_methods.const_get(const)
889
+ klass.class_eval do
890
+ instance_methods(false).each do |m|
891
+ m.to_s == 'to_json' and remove_method m
892
+ end
893
+ include modul
891
894
  end
892
- include modul
893
895
  end
896
+ self.state = generator::State
897
+ const_set :State, self.state
898
+ const_set :SAFE_STATE_PROTOTYPE, State.new
899
+ const_set :FAST_STATE_PROTOTYPE, State.new(
900
+ :indent => '',
901
+ :space => '',
902
+ :object_nl => "",
903
+ :array_nl => "",
904
+ :max_nesting => false
905
+ )
906
+ const_set :PRETTY_STATE_PROTOTYPE, State.new(
907
+ :indent => ' ',
908
+ :space => ' ',
909
+ :object_nl => "\n",
910
+ :array_nl => "\n"
911
+ )
912
+ ensure
913
+ $VERBOSE = old
894
914
  end
895
- self.state = generator::State
896
- const_set :State, self.state
897
- const_set :SAFE_STATE_PROTOTYPE, State.new
898
- const_set :FAST_STATE_PROTOTYPE, State.new(
899
- :indent => '',
900
- :space => '',
901
- :object_nl => "",
902
- :array_nl => "",
903
- :max_nesting => false
904
- )
905
- const_set :PRETTY_STATE_PROTOTYPE, State.new(
906
- :indent => ' ',
907
- :space => ' ',
908
- :object_nl => "\n",
909
- :array_nl => "\n"
910
- )
911
- ensure
912
- $VERBOSE = old
915
+
916
+ # Returns the JSON generator module that is used by JSON. This is
917
+ # either JSON::Ext::Generator or JSON::Pure::Generator.
918
+ attr_reader :generator
919
+
920
+ # Returns the JSON generator state class that is used by JSON. This is
921
+ # either JSON::Ext::Generator::State or JSON::Pure::Generator::State.
922
+ attr_accessor :state
923
+
924
+ # This is create identifier, which is used to decide if the _json_create_
925
+ # hook of a class should be called. It defaults to 'json_class'.
926
+ attr_accessor :create_id
913
927
  end
928
+ self.create_id = 'json_class'
914
929
 
915
- # Returns the JSON generator module that is used by JSON. This is
916
- # either JSON::Ext::Generator or JSON::Pure::Generator.
917
- attr_reader :generator
930
+ NaN = 0.0/0
918
931
 
919
- # Returns the JSON generator state class that is used by JSON. This is
920
- # either JSON::Ext::Generator::State or JSON::Pure::Generator::State.
921
- attr_accessor :state
932
+ Infinity = 1.0/0
922
933
 
923
- # This is create identifier, which is used to decide if the _json_create_
924
- # hook of a class should be called. It defaults to 'json_class'.
925
- attr_accessor :create_id
926
- end
927
- self.create_id = 'json_class'
928
-
929
- NaN = 0.0/0
930
-
931
- Infinity = 1.0/0
932
-
933
- MinusInfinity = -Infinity
934
-
935
- # The base exception for JSON errors.
936
- class JSONError < StandardError; end
937
-
938
- # This exception is raised if a parser error occurs.
939
- class ParserError < JSONError; end
940
-
941
- # This exception is raised if the nesting of parsed data structures is too
942
- # deep.
943
- class NestingError < ParserError; end
944
-
945
- # :stopdoc:
946
- class CircularDatastructure < NestingError; end
947
- # :startdoc:
948
-
949
- # This exception is raised if a generator or unparser error occurs.
950
- class GeneratorError < JSONError; end
951
- # For backwards compatibility
952
- UnparserError = GeneratorError
953
-
954
- # This exception is raised if the required unicode support is missing on the
955
- # system. Usually this means that the iconv library is not installed.
956
- class MissingUnicodeSupport < JSONError; end
957
-
958
- module_function
959
-
960
- # Parse the JSON document _source_ into a Ruby data structure and return it.
961
- #
962
- # _opts_ can have the following
963
- # keys:
964
- # * *max_nesting*: The maximum depth of nesting allowed in the parsed data
965
- # structures. Disable depth checking with :max_nesting => false. It defaults
966
- # to 19.
967
- # * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
968
- # defiance of RFC 4627 to be parsed by the Parser. This option defaults
969
- # to false.
970
- # * *symbolize_names*: If set to true, returns symbols for the names
971
- # (keys) in a JSON object. Otherwise strings are returned. Strings are
972
- # the default.
973
- # * *create_additions*: If set to false, the Parser doesn't create
974
- # additions even if a matching class and create_id was found. This option
975
- # defaults to true.
976
- # * *object_class*: Defaults to Hash
977
- # * *array_class*: Defaults to Array
978
- def parse(source, opts = {})
979
- Parser.new(source, opts).parse
980
- end
934
+ MinusInfinity = -Infinity
981
935
 
982
- # Parse the JSON document _source_ into a Ruby data structure and return it.
983
- # The bang version of the parse method defaults to the more dangerous values
984
- # for the _opts_ hash, so be sure only to parse trusted _source_ documents.
985
- #
986
- # _opts_ can have the following keys:
987
- # * *max_nesting*: The maximum depth of nesting allowed in the parsed data
988
- # structures. Enable depth checking with :max_nesting => anInteger. The parse!
989
- # methods defaults to not doing max depth checking: This can be dangerous
990
- # if someone wants to fill up your stack.
991
- # * *allow_nan*: If set to true, allow NaN, Infinity, and -Infinity in
992
- # defiance of RFC 4627 to be parsed by the Parser. This option defaults
993
- # to true.
994
- # * *create_additions*: If set to false, the Parser doesn't create
995
- # additions even if a matching class and create_id was found. This option
996
- # defaults to true.
997
- def parse!(source, opts = {})
998
- opts = {
999
- :max_nesting => false,
1000
- :allow_nan => true
1001
- }.update(opts)
1002
- Parser.new(source, opts).parse
1003
- end
936
+ # The base exception for JSON errors.
937
+ class JSONError < StandardError; end
1004
938
 
1005
- # Generate a JSON document from the Ruby data structure _obj_ and return
1006
- # it. _state_ is * a JSON::State object,
1007
- # * or a Hash like object (responding to to_hash),
1008
- # * an object convertible into a hash by a to_h method,
1009
- # that is used as or to configure a State object.
1010
- #
1011
- # It defaults to a state object, that creates the shortest possible JSON text
1012
- # in one line, checks for circular data structures and doesn't allow NaN,
1013
- # Infinity, and -Infinity.
1014
- #
1015
- # A _state_ hash can have the following keys:
1016
- # * *indent*: a string used to indent levels (default: ''),
1017
- # * *space*: a string that is put after, a : or , delimiter (default: ''),
1018
- # * *space_before*: a string that is put before a : pair delimiter (default: ''),
1019
- # * *object_nl*: a string that is put at the end of a JSON object (default: ''),
1020
- # * *array_nl*: a string that is put at the end of a JSON array (default: ''),
1021
- # * *allow_nan*: true if NaN, Infinity, and -Infinity should be
1022
- # generated, otherwise an exception is thrown if these values are
1023
- # encountered. This options defaults to false.
1024
- # * *max_nesting*: The maximum depth of nesting allowed in the data
1025
- # structures from which JSON is to be generated. Disable depth checking
1026
- # with :max_nesting => false, it defaults to 19.
1027
- #
1028
- # See also the fast_generate for the fastest creation method with the least
1029
- # amount of sanity checks, and the pretty_generate method for some
1030
- # defaults for pretty output.
1031
- def generate(obj, opts = nil)
1032
- if State === opts
1033
- state, opts = opts, nil
1034
- else
1035
- state = SAFE_STATE_PROTOTYPE.dup
939
+ # This exception is raised if a parser error occurs.
940
+ class ParserError < JSONError; end
941
+
942
+ # This exception is raised if the nesting of parsed data structures is too
943
+ # deep.
944
+ class NestingError < ParserError; end
945
+
946
+ # :stopdoc:
947
+ class CircularDatastructure < NestingError; end
948
+ # :startdoc:
949
+
950
+ # This exception is raised if a generator or unparser error occurs.
951
+ class GeneratorError < JSONError; end
952
+ # For backwards compatibility
953
+ UnparserError = GeneratorError
954
+
955
+ # This exception is raised if the required unicode support is missing on the
956
+ # system. Usually this means that the iconv library is not installed.
957
+ class MissingUnicodeSupport < JSONError; end
958
+
959
+ module_function
960
+
961
+ # Parse the JSON document _source_ into a Ruby data structure and return it.
962
+ #
963
+ # _opts_ can have the following
964
+ # keys:
965
+ # * *max_nesting*: The maximum depth of nesting allowed in the parsed data
966
+ # structures. Disable depth checking with :max_nesting => false. It defaults
967
+ # to 19.
968
+ # * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
969
+ # defiance of RFC 4627 to be parsed by the Parser. This option defaults
970
+ # to false.
971
+ # * *symbolize_names*: If set to true, returns symbols for the names
972
+ # (keys) in a JSON object. Otherwise strings are returned. Strings are
973
+ # the default.
974
+ # * *create_additions*: If set to false, the Parser doesn't create
975
+ # additions even if a matching class and create_id was found. This option
976
+ # defaults to true.
977
+ # * *object_class*: Defaults to Hash
978
+ # * *array_class*: Defaults to Array
979
+ def parse(source, opts = {})
980
+ Parser.new(source, opts).parse
1036
981
  end
1037
- if opts
1038
- if opts.respond_to? :to_hash
1039
- opts = opts.to_hash
1040
- elsif opts.respond_to? :to_h
1041
- opts = opts.to_h
982
+
983
+ # Parse the JSON document _source_ into a Ruby data structure and return it.
984
+ # The bang version of the parse method defaults to the more dangerous values
985
+ # for the _opts_ hash, so be sure only to parse trusted _source_ documents.
986
+ #
987
+ # _opts_ can have the following keys:
988
+ # * *max_nesting*: The maximum depth of nesting allowed in the parsed data
989
+ # structures. Enable depth checking with :max_nesting => anInteger. The parse!
990
+ # methods defaults to not doing max depth checking: This can be dangerous
991
+ # if someone wants to fill up your stack.
992
+ # * *allow_nan*: If set to true, allow NaN, Infinity, and -Infinity in
993
+ # defiance of RFC 4627 to be parsed by the Parser. This option defaults
994
+ # to true.
995
+ # * *create_additions*: If set to false, the Parser doesn't create
996
+ # additions even if a matching class and create_id was found. This option
997
+ # defaults to true.
998
+ def parse!(source, opts = {})
999
+ opts = {
1000
+ :max_nesting => false,
1001
+ :allow_nan => true
1002
+ }.update(opts)
1003
+ Parser.new(source, opts).parse
1004
+ end
1005
+
1006
+ # Generate a JSON document from the Ruby data structure _obj_ and return
1007
+ # it. _state_ is * a JSON::State object,
1008
+ # * or a Hash like object (responding to to_hash),
1009
+ # * an object convertible into a hash by a to_h method,
1010
+ # that is used as or to configure a State object.
1011
+ #
1012
+ # It defaults to a state object, that creates the shortest possible JSON text
1013
+ # in one line, checks for circular data structures and doesn't allow NaN,
1014
+ # Infinity, and -Infinity.
1015
+ #
1016
+ # A _state_ hash can have the following keys:
1017
+ # * *indent*: a string used to indent levels (default: ''),
1018
+ # * *space*: a string that is put after, a : or , delimiter (default: ''),
1019
+ # * *space_before*: a string that is put before a : pair delimiter (default: ''),
1020
+ # * *object_nl*: a string that is put at the end of a JSON object (default: ''),
1021
+ # * *array_nl*: a string that is put at the end of a JSON array (default: ''),
1022
+ # * *allow_nan*: true if NaN, Infinity, and -Infinity should be
1023
+ # generated, otherwise an exception is thrown if these values are
1024
+ # encountered. This options defaults to false.
1025
+ # * *max_nesting*: The maximum depth of nesting allowed in the data
1026
+ # structures from which JSON is to be generated. Disable depth checking
1027
+ # with :max_nesting => false, it defaults to 19.
1028
+ #
1029
+ # See also the fast_generate for the fastest creation method with the least
1030
+ # amount of sanity checks, and the pretty_generate method for some
1031
+ # defaults for pretty output.
1032
+ def generate(obj, opts = nil)
1033
+ if State === opts
1034
+ state, opts = opts, nil
1042
1035
  else
1043
- raise TypeError, "can't convert #{opts.class} into Hash"
1036
+ state = SAFE_STATE_PROTOTYPE.dup
1037
+ end
1038
+ if opts
1039
+ if opts.respond_to? :to_hash
1040
+ opts = opts.to_hash
1041
+ elsif opts.respond_to? :to_h
1042
+ opts = opts.to_h
1043
+ else
1044
+ raise TypeError, "can't convert #{opts.class} into Hash"
1045
+ end
1046
+ state = state.configure(opts)
1044
1047
  end
1045
- state = state.configure(opts)
1048
+ state.generate(obj)
1046
1049
  end
1047
- state.generate(obj)
1048
- end
1049
1050
 
1050
- # :stopdoc:
1051
- # I want to deprecate these later, so I'll first be silent about them, and
1052
- # later delete them.
1053
- alias unparse generate
1054
- module_function :unparse
1055
- # :startdoc:
1056
-
1057
- # Generate a JSON document from the Ruby data structure _obj_ and return it.
1058
- # This method disables the checks for circles in Ruby objects.
1059
- #
1060
- # *WARNING*: Be careful not to pass any Ruby data structures with circles as
1061
- # _obj_ argument because this will cause JSON to go into an infinite loop.
1062
- def fast_generate(obj, opts = nil)
1063
- if State === opts
1064
- state, opts = opts, nil
1065
- else
1066
- state = FAST_STATE_PROTOTYPE.dup
1067
- end
1068
- if opts
1069
- if opts.respond_to? :to_hash
1070
- opts = opts.to_hash
1071
- elsif opts.respond_to? :to_h
1072
- opts = opts.to_h
1051
+ # :stopdoc:
1052
+ # I want to deprecate these later, so I'll first be silent about them, and
1053
+ # later delete them.
1054
+ alias unparse generate
1055
+ module_function :unparse
1056
+ # :startdoc:
1057
+
1058
+ # Generate a JSON document from the Ruby data structure _obj_ and return it.
1059
+ # This method disables the checks for circles in Ruby objects.
1060
+ #
1061
+ # *WARNING*: Be careful not to pass any Ruby data structures with circles as
1062
+ # _obj_ argument because this will cause JSON to go into an infinite loop.
1063
+ def fast_generate(obj, opts = nil)
1064
+ if State === opts
1065
+ state, opts = opts, nil
1073
1066
  else
1074
- raise TypeError, "can't convert #{opts.class} into Hash"
1067
+ state = FAST_STATE_PROTOTYPE.dup
1075
1068
  end
1076
- state.configure(opts)
1069
+ if opts
1070
+ if opts.respond_to? :to_hash
1071
+ opts = opts.to_hash
1072
+ elsif opts.respond_to? :to_h
1073
+ opts = opts.to_h
1074
+ else
1075
+ raise TypeError, "can't convert #{opts.class} into Hash"
1076
+ end
1077
+ state.configure(opts)
1078
+ end
1079
+ state.generate(obj)
1077
1080
  end
1078
- state.generate(obj)
1079
- end
1080
1081
 
1081
- # :stopdoc:
1082
- # I want to deprecate these later, so I'll first be silent about them, and later delete them.
1083
- alias fast_unparse fast_generate
1084
- module_function :fast_unparse
1085
- # :startdoc:
1086
-
1087
- # Generate a JSON document from the Ruby data structure _obj_ and return it.
1088
- # The returned document is a prettier form of the document returned by
1089
- # #unparse.
1090
- #
1091
- # The _opts_ argument can be used to configure the generator. See the
1092
- # generate method for a more detailed explanation.
1093
- def pretty_generate(obj, opts = nil)
1094
- if State === opts
1095
- state, opts = opts, nil
1096
- else
1097
- state = PRETTY_STATE_PROTOTYPE.dup
1098
- end
1099
- if opts
1100
- if opts.respond_to? :to_hash
1101
- opts = opts.to_hash
1102
- elsif opts.respond_to? :to_h
1103
- opts = opts.to_h
1082
+ # :stopdoc:
1083
+ # I want to deprecate these later, so I'll first be silent about them, and later delete them.
1084
+ alias fast_unparse fast_generate
1085
+ module_function :fast_unparse
1086
+ # :startdoc:
1087
+
1088
+ # Generate a JSON document from the Ruby data structure _obj_ and return it.
1089
+ # The returned document is a prettier form of the document returned by
1090
+ # #unparse.
1091
+ #
1092
+ # The _opts_ argument can be used to configure the generator. See the
1093
+ # generate method for a more detailed explanation.
1094
+ def pretty_generate(obj, opts = nil)
1095
+ if State === opts
1096
+ state, opts = opts, nil
1104
1097
  else
1105
- raise TypeError, "can't convert #{opts.class} into Hash"
1098
+ state = PRETTY_STATE_PROTOTYPE.dup
1099
+ end
1100
+ if opts
1101
+ if opts.respond_to? :to_hash
1102
+ opts = opts.to_hash
1103
+ elsif opts.respond_to? :to_h
1104
+ opts = opts.to_h
1105
+ else
1106
+ raise TypeError, "can't convert #{opts.class} into Hash"
1107
+ end
1108
+ state.configure(opts)
1106
1109
  end
1107
- state.configure(opts)
1110
+ state.generate(obj)
1108
1111
  end
1109
- state.generate(obj)
1110
- end
1111
1112
 
1112
- # :stopdoc:
1113
- # I want to deprecate these later, so I'll first be silent about them, and later delete them.
1114
- alias pretty_unparse pretty_generate
1115
- module_function :pretty_unparse
1116
- # :startdoc:
1117
-
1118
- class << self
1119
- # The global default options for the JSON.load method:
1120
- # :max_nesting: false
1121
- # :allow_nan: true
1122
- # :quirks_mode: true
1123
- attr_accessor :load_default_options
1124
- end
1125
- self.load_default_options = {
1126
- :max_nesting => false,
1127
- :allow_nan => true,
1128
- :quirks_mode => true,
1129
- }
1130
-
1131
- # Load a ruby data structure from a JSON _source_ and return it. A source can
1132
- # either be a string-like object, an IO-like object, or an object responding
1133
- # to the read method. If _proc_ was given, it will be called with any nested
1134
- # Ruby object as an argument recursively in depth first order. The default
1135
- # options for the parser can be changed via the load_default_options method.
1136
- #
1137
- # This method is part of the implementation of the load/dump interface of
1138
- # Marshal and YAML.
1139
- def load(source, proc = nil)
1140
- opts = load_default_options
1141
- if source.respond_to? :to_str
1142
- source = source.to_str
1143
- elsif source.respond_to? :to_io
1144
- source = source.to_io.read
1145
- elsif source.respond_to?(:read)
1146
- source = source.read
1113
+ # :stopdoc:
1114
+ # I want to deprecate these later, so I'll first be silent about them, and later delete them.
1115
+ alias pretty_unparse pretty_generate
1116
+ module_function :pretty_unparse
1117
+ # :startdoc:
1118
+
1119
+ class << self
1120
+ # The global default options for the JSON.load method:
1121
+ # :max_nesting: false
1122
+ # :allow_nan: true
1123
+ # :quirks_mode: true
1124
+ attr_accessor :load_default_options
1147
1125
  end
1148
- if opts[:quirks_mode] && (source.nil? || source.empty?)
1149
- source = 'null'
1126
+ self.load_default_options = {
1127
+ :max_nesting => false,
1128
+ :allow_nan => true,
1129
+ :quirks_mode => true,
1130
+ }
1131
+
1132
+ # Load a ruby data structure from a JSON _source_ and return it. A source can
1133
+ # either be a string-like object, an IO-like object, or an object responding
1134
+ # to the read method. If _proc_ was given, it will be called with any nested
1135
+ # Ruby object as an argument recursively in depth first order. The default
1136
+ # options for the parser can be changed via the load_default_options method.
1137
+ #
1138
+ # This method is part of the implementation of the load/dump interface of
1139
+ # Marshal and YAML.
1140
+ def load(source, proc = nil)
1141
+ opts = load_default_options
1142
+ if source.respond_to? :to_str
1143
+ source = source.to_str
1144
+ elsif source.respond_to? :to_io
1145
+ source = source.to_io.read
1146
+ elsif source.respond_to?(:read)
1147
+ source = source.read
1148
+ end
1149
+ if opts[:quirks_mode] && (source.nil? || source.empty?)
1150
+ source = 'null'
1151
+ end
1152
+ result = parse(source, opts)
1153
+ recurse_proc(result, &proc) if proc
1154
+ result
1150
1155
  end
1151
- result = parse(source, opts)
1152
- recurse_proc(result, &proc) if proc
1153
- result
1154
- end
1155
1156
 
1156
- # Recursively calls passed _Proc_ if the parsed data structure is an _Array_ or _Hash_
1157
- def recurse_proc(result, &proc)
1158
- case result
1159
- when Array
1160
- result.each { |x| recurse_proc x, &proc }
1161
- proc.call result
1162
- when Hash
1163
- result.each { |x, y| recurse_proc x, &proc; recurse_proc y, &proc }
1164
- proc.call result
1165
- else
1166
- proc.call result
1157
+ # Recursively calls passed _Proc_ if the parsed data structure is an _Array_ or _Hash_
1158
+ def recurse_proc(result, &proc)
1159
+ case result
1160
+ when Array
1161
+ result.each { |x| recurse_proc x, &proc }
1162
+ proc.call result
1163
+ when Hash
1164
+ result.each { |x, y| recurse_proc x, &proc; recurse_proc y, &proc }
1165
+ proc.call result
1166
+ else
1167
+ proc.call result
1168
+ end
1167
1169
  end
1168
- end
1169
1170
 
1170
- alias restore load
1171
- module_function :restore
1171
+ alias restore load
1172
+ module_function :restore
1172
1173
 
1173
- class << self
1174
- # The global default options for the JSON.dump method:
1175
- # :max_nesting: false
1176
- # :allow_nan: true
1177
- # :quirks_mode: true
1178
- attr_accessor :dump_default_options
1179
- end
1180
- self.dump_default_options = {
1181
- :max_nesting => false,
1182
- :allow_nan => true,
1183
- :quirks_mode => true,
1184
- }
1185
-
1186
- # Dumps _obj_ as a JSON string, i.e. calls generate on the object and returns
1187
- # the result.
1188
- #
1189
- # If anIO (an IO-like object or an object that responds to the write method)
1190
- # was given, the resulting JSON is written to it.
1191
- #
1192
- # If the number of nested arrays or objects exceeds _limit_, an ArgumentError
1193
- # exception is raised. This argument is similar (but not exactly the
1194
- # same!) to the _limit_ argument in Marshal.dump.
1195
- #
1196
- # The default options for the generator can be changed via the
1197
- # dump_default_options method.
1198
- #
1199
- # This method is part of the implementation of the load/dump interface of
1200
- # Marshal and YAML.
1201
- def dump(obj, anIO = nil, limit = nil)
1202
- if anIO and limit.nil?
1203
- anIO = anIO.to_io if anIO.respond_to?(:to_io)
1204
- unless anIO.respond_to?(:write)
1205
- limit = anIO
1206
- anIO = nil
1207
- end
1174
+ class << self
1175
+ # The global default options for the JSON.dump method:
1176
+ # :max_nesting: false
1177
+ # :allow_nan: true
1178
+ # :quirks_mode: true
1179
+ attr_accessor :dump_default_options
1208
1180
  end
1209
- opts = JSON.dump_default_options
1210
- limit and opts.update(:max_nesting => limit)
1211
- result = generate(obj, opts)
1212
- if anIO
1213
- anIO.write result
1214
- anIO
1215
- else
1216
- result
1181
+ self.dump_default_options = {
1182
+ :max_nesting => false,
1183
+ :allow_nan => true,
1184
+ :quirks_mode => true,
1185
+ }
1186
+
1187
+ # Dumps _obj_ as a JSON string, i.e. calls generate on the object and returns
1188
+ # the result.
1189
+ #
1190
+ # If anIO (an IO-like object or an object that responds to the write method)
1191
+ # was given, the resulting JSON is written to it.
1192
+ #
1193
+ # If the number of nested arrays or objects exceeds _limit_, an ArgumentError
1194
+ # exception is raised. This argument is similar (but not exactly the
1195
+ # same!) to the _limit_ argument in Marshal.dump.
1196
+ #
1197
+ # The default options for the generator can be changed via the
1198
+ # dump_default_options method.
1199
+ #
1200
+ # This method is part of the implementation of the load/dump interface of
1201
+ # Marshal and YAML.
1202
+ def dump(obj, anIO = nil, limit = nil)
1203
+ if anIO and limit.nil?
1204
+ anIO = anIO.to_io if anIO.respond_to?(:to_io)
1205
+ unless anIO.respond_to?(:write)
1206
+ limit = anIO
1207
+ anIO = nil
1208
+ end
1209
+ end
1210
+ opts = JSON.dump_default_options
1211
+ limit and opts.update(:max_nesting => limit)
1212
+ result = generate(obj, opts)
1213
+ if anIO
1214
+ anIO.write result
1215
+ anIO
1216
+ else
1217
+ result
1218
+ end
1219
+ rescue JSON::NestingError
1220
+ raise ArgumentError, "exceed depth limit"
1217
1221
  end
1218
- rescue JSON::NestingError
1219
- raise ArgumentError, "exceed depth limit"
1220
- end
1221
1222
 
1222
- # Swap consecutive bytes of _string_ in place.
1223
- def self.swap!(string) # :nodoc:
1224
- 0.upto(string.size / 2) do |i|
1225
- break unless string[2 * i + 1]
1226
- string[2 * i], string[2 * i + 1] = string[2 * i + 1], string[2 * i]
1223
+ # Swap consecutive bytes of _string_ in place.
1224
+ def self.swap!(string) # :nodoc:
1225
+ 0.upto(string.size / 2) do |i|
1226
+ break unless string[2 * i + 1]
1227
+ string[2 * i], string[2 * i + 1] = string[2 * i + 1], string[2 * i]
1228
+ end
1229
+ string
1227
1230
  end
1228
- string
1229
- end
1230
1231
 
1231
- # Shortuct for iconv.
1232
- if ::String.method_defined?(:encode)
1233
- # Encodes string using Ruby's _String.encode_
1234
- def self.iconv(to, from, string)
1235
- string.encode(to, from)
1236
- end
1237
- else
1238
- require 'iconv'
1239
- # Encodes string using _iconv_ library
1240
- def self.iconv(to, from, string)
1241
- Iconv.conv(to, from, string)
1232
+ # Shortuct for iconv.
1233
+ if ::String.method_defined?(:encode)
1234
+ # Encodes string using Ruby's _String.encode_
1235
+ def self.iconv(to, from, string)
1236
+ string.encode(to, from)
1237
+ end
1238
+ else
1239
+ require 'iconv'
1240
+ # Encodes string using _iconv_ library
1241
+ def self.iconv(to, from, string)
1242
+ Iconv.conv(to, from, string)
1243
+ end
1242
1244
  end
1243
- end
1244
1245
 
1245
- if ::Object.method(:const_defined?).arity == 1
1246
- def self.const_defined_in?(modul, constant)
1247
- modul.const_defined?(constant)
1248
- end
1249
- else
1250
- def self.const_defined_in?(modul, constant)
1251
- modul.const_defined?(constant, false)
1246
+ if ::Object.method(:const_defined?).arity == 1
1247
+ def self.const_defined_in?(modul, constant)
1248
+ modul.const_defined?(constant)
1249
+ end
1250
+ else
1251
+ def self.const_defined_in?(modul, constant)
1252
+ modul.const_defined?(constant, false)
1253
+ end
1252
1254
  end
1253
1255
  end
1254
- end
1255
1256
 
1256
- module ::Kernel
1257
- private
1257
+ module ::Kernel
1258
+ private
1258
1259
 
1259
- # Outputs _objs_ to STDOUT as JSON strings in the shortest form, that is in
1260
- # one line.
1261
- def j(*objs)
1262
- objs.each do |obj|
1263
- puts JSON::generate(obj, :allow_nan => true, :max_nesting => false)
1260
+ # Outputs _objs_ to STDOUT as JSON strings in the shortest form, that is in
1261
+ # one line.
1262
+ def j(*objs)
1263
+ objs.each do |obj|
1264
+ puts JSON::generate(obj, :allow_nan => true, :max_nesting => false)
1265
+ end
1266
+ nil
1264
1267
  end
1265
- nil
1266
- end
1267
1268
 
1268
- # Ouputs _objs_ to STDOUT as JSON strings in a pretty format, with
1269
- # indentation and over many lines.
1270
- def jj(*objs)
1271
- objs.each do |obj|
1272
- puts JSON::pretty_generate(obj, :allow_nan => true, :max_nesting => false)
1269
+ # Ouputs _objs_ to STDOUT as JSON strings in a pretty format, with
1270
+ # indentation and over many lines.
1271
+ def jj(*objs)
1272
+ objs.each do |obj|
1273
+ puts JSON::pretty_generate(obj, :allow_nan => true, :max_nesting => false)
1274
+ end
1275
+ nil
1273
1276
  end
1274
- nil
1275
- end
1276
1277
 
1277
- # If _object_ is string-like, parse the string and return the parsed result as
1278
- # a Ruby data structure. Otherwise, generate a JSON text from the Ruby data
1279
- # structure object and return it.
1280
- #
1281
- # The _opts_ argument is passed through to generate/parse respectively. See
1282
- # generate and parse for their documentation.
1283
- def JSON(object, *args)
1284
- if object.respond_to? :to_str
1285
- JSON.parse(object.to_str, args.first)
1286
- else
1287
- JSON.generate(object, args.first)
1278
+ # If _object_ is string-like, parse the string and return the parsed result as
1279
+ # a Ruby data structure. Otherwise, generate a JSON text from the Ruby data
1280
+ # structure object and return it.
1281
+ #
1282
+ # The _opts_ argument is passed through to generate/parse respectively. See
1283
+ # generate and parse for their documentation.
1284
+ def JSON(object, *args)
1285
+ if object.respond_to? :to_str
1286
+ JSON.parse(object.to_str, args.first)
1287
+ else
1288
+ JSON.generate(object, args.first)
1289
+ end
1288
1290
  end
1289
1291
  end
1290
- end
1291
1292
 
1292
- # Extends any Class to include _json_creatable?_ method.
1293
- class ::Class
1294
- # Returns true if this class can be used to create an instance
1295
- # from a serialised JSON string. The class has to implement a class
1296
- # method _json_create_ that expects a hash as first parameter. The hash
1297
- # should include the required data.
1298
- def json_creatable?
1299
- respond_to?(:json_create)
1293
+ # Extends any Class to include _json_creatable?_ method.
1294
+ class ::Class
1295
+ # Returns true if this class can be used to create an instance
1296
+ # from a serialised JSON string. The class has to implement a class
1297
+ # method _json_create_ that expects a hash as first parameter. The hash
1298
+ # should include the required data.
1299
+ def json_creatable?
1300
+ respond_to?(:json_create)
1301
+ end
1300
1302
  end
1301
- end
1302
1303
 
1303
- JSON.generator = JSON::Pure::Generator
1304
- JSON.parser = JSON::Pure::Parser
1304
+ JSON.generator = JSON::Pure::Generator
1305
+ JSON.parser = JSON::Pure::Parser
1306
+ end