ghi 0.9.0.20130912 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
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