dotum 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +5 -0
  3. data/.groc.json +6 -0
  4. data/.rspec +4 -0
  5. data/.simplecov +5 -0
  6. data/.travis.yml +15 -0
  7. data/CONTRIBUTING.md +63 -0
  8. data/Gemfile +59 -0
  9. data/Guardfile +30 -0
  10. data/MIT-LICENSE.md +21 -0
  11. data/README.md +24 -0
  12. data/Rakefile +15 -0
  13. data/bin/dotum +7 -0
  14. data/data/default_rules.dotum +44 -0
  15. data/dotum.gemspec +19 -0
  16. data/extern/json/CHANGES.md +9 -0
  17. data/extern/json/COPYING +58 -0
  18. data/extern/json/README.rdoc +358 -0
  19. data/extern/json/lib/json.rb +62 -0
  20. data/extern/json/lib/json/.DS_Store +0 -0
  21. data/extern/json/lib/json/add/bigdecimal.rb +28 -0
  22. data/extern/json/lib/json/add/complex.rb +22 -0
  23. data/extern/json/lib/json/add/core.rb +11 -0
  24. data/extern/json/lib/json/add/date.rb +34 -0
  25. data/extern/json/lib/json/add/date_time.rb +50 -0
  26. data/extern/json/lib/json/add/exception.rb +31 -0
  27. data/extern/json/lib/json/add/ostruct.rb +31 -0
  28. data/extern/json/lib/json/add/range.rb +29 -0
  29. data/extern/json/lib/json/add/rational.rb +22 -0
  30. data/extern/json/lib/json/add/regexp.rb +30 -0
  31. data/extern/json/lib/json/add/struct.rb +30 -0
  32. data/extern/json/lib/json/add/symbol.rb +25 -0
  33. data/extern/json/lib/json/add/time.rb +38 -0
  34. data/extern/json/lib/json/common.rb +487 -0
  35. data/extern/json/lib/json/generic_object.rb +70 -0
  36. data/extern/json/lib/json/pure.rb +21 -0
  37. data/extern/json/lib/json/pure/generator.rb +522 -0
  38. data/extern/json/lib/json/pure/parser.rb +359 -0
  39. data/extern/json/lib/json/version.rb +8 -0
  40. data/lib/dotum.rb +11 -0
  41. data/lib/dotum/abstract_rules.rb +5 -0
  42. data/lib/dotum/abstract_rules/base.rb +56 -0
  43. data/lib/dotum/abstract_rules/globbable_files.rb +51 -0
  44. data/lib/dotum/abstract_rules/options_base.rb +33 -0
  45. data/lib/dotum/autoload_convention.rb +34 -0
  46. data/lib/dotum/cli.rb +35 -0
  47. data/lib/dotum/context.rb +55 -0
  48. data/lib/dotum/externs/json.rb +9 -0
  49. data/lib/dotum/logger.rb +50 -0
  50. data/lib/dotum/options_context.rb +21 -0
  51. data/lib/dotum/rule_dsl.rb +73 -0
  52. data/lib/dotum/rule_options_dsl.rb +116 -0
  53. data/lib/dotum/rule_runner.rb +16 -0
  54. data/lib/dotum/rules.rb +5 -0
  55. data/lib/dotum/rules/cd.rb +23 -0
  56. data/lib/dotum/rules/download.rb +32 -0
  57. data/lib/dotum/rules/link.rb +22 -0
  58. data/lib/dotum/rules/repo.rb +65 -0
  59. data/lib/dotum/rules/require_extension.rb +42 -0
  60. data/lib/dotum/rules/run.rb +23 -0
  61. data/lib/dotum/rules/use.rb +33 -0
  62. data/lib/dotum/rules/use_repo.rb +58 -0
  63. data/lib/dotum/standard_options.rb +5 -0
  64. data/lib/dotum/standard_options/destination.rb +22 -0
  65. data/lib/dotum/util.rb +5 -0
  66. data/lib/dotum/util/ansi_colors.rb +26 -0
  67. data/lib/dotum/util/path.rb +120 -0
  68. data/lib/dotum/version.rb +5 -0
  69. data/spec/fixtures/autoload_convention/abc_one_two_three.rb +7 -0
  70. data/spec/fixtures/autoload_convention/allcaps.rb +7 -0
  71. data/spec/fixtures/autoload_convention/mismatched.rb +3 -0
  72. data/spec/fixtures/autoload_convention/multi_token.rb +7 -0
  73. data/spec/fixtures/autoload_convention/single.rb +7 -0
  74. data/spec/fixtures/autoload_convention/string.rb +7 -0
  75. data/spec/spec_helper.rb +76 -0
  76. data/spec/unit/dotum/autoload_convention/const_missing_spec.rb +57 -0
  77. data/tasks/console.rake +9 -0
  78. data/tasks/spec.rake +7 -0
  79. data/tasks/spec/ci.rake +16 -0
  80. data/tasks/spec/coverage.rake +19 -0
  81. data/tasks/spec/mutate.rake +71 -0
  82. metadata +123 -0
@@ -0,0 +1,70 @@
1
+ require 'ostruct'
2
+
3
+ module JSON
4
+ class GenericObject < OpenStruct
5
+ class << self
6
+ alias [] new
7
+
8
+ def json_creatable?
9
+ @json_creatable
10
+ end
11
+
12
+ attr_writer :json_creatable
13
+
14
+ def json_create(data)
15
+ data = data.dup
16
+ data.delete JSON.create_id
17
+ self[data]
18
+ end
19
+
20
+ def from_hash(object)
21
+ case
22
+ when object.respond_to?(:to_hash)
23
+ result = new
24
+ object.to_hash.each do |key, value|
25
+ result[key] = from_hash(value)
26
+ end
27
+ result
28
+ when object.respond_to?(:to_ary)
29
+ object.to_ary.map { |a| from_hash(a) }
30
+ else
31
+ object
32
+ end
33
+ end
34
+
35
+ def load(source, proc = nil, opts = {})
36
+ result = ::JSON.load(source, proc, opts.merge(:object_class => self))
37
+ result.nil? ? new : result
38
+ end
39
+
40
+ def dump(obj, *args)
41
+ ::JSON.dump(obj, *args)
42
+ end
43
+ end
44
+ self.json_creatable = false
45
+
46
+ def to_hash
47
+ table
48
+ end
49
+
50
+ def [](name)
51
+ table[name.to_sym]
52
+ end
53
+
54
+ def []=(name, value)
55
+ __send__ "#{name}=", value
56
+ end
57
+
58
+ def |(other)
59
+ self.class[other.to_hash.merge(to_hash)]
60
+ end
61
+
62
+ def as_json(*)
63
+ { JSON.create_id => self.class.name }.merge to_hash
64
+ end
65
+
66
+ def to_json(*a)
67
+ as_json.to_json(*a)
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,21 @@
1
+ if ENV['SIMPLECOV_COVERAGE'].to_i == 1
2
+ require 'simplecov'
3
+ SimpleCov.start do
4
+ add_filter "/tests/"
5
+ end
6
+ end
7
+ require 'json/common'
8
+ require 'json/pure/parser'
9
+ require 'json/pure/generator'
10
+
11
+ module JSON
12
+ # This module holds all the modules/classes that implement JSON's
13
+ # functionality in pure ruby.
14
+ module Pure
15
+ $DEBUG and warn "Using Pure library for JSON."
16
+ JSON.parser = Parser
17
+ JSON.generator = Generator
18
+ end
19
+
20
+ JSON_LOADED = true unless defined?(::JSON::JSON_LOADED)
21
+ end
@@ -0,0 +1,522 @@
1
+ module JSON
2
+ MAP = {
3
+ "\x0" => '\u0000',
4
+ "\x1" => '\u0001',
5
+ "\x2" => '\u0002',
6
+ "\x3" => '\u0003',
7
+ "\x4" => '\u0004',
8
+ "\x5" => '\u0005',
9
+ "\x6" => '\u0006',
10
+ "\x7" => '\u0007',
11
+ "\b" => '\b',
12
+ "\t" => '\t',
13
+ "\n" => '\n',
14
+ "\xb" => '\u000b',
15
+ "\f" => '\f',
16
+ "\r" => '\r',
17
+ "\xe" => '\u000e',
18
+ "\xf" => '\u000f',
19
+ "\x10" => '\u0010',
20
+ "\x11" => '\u0011',
21
+ "\x12" => '\u0012',
22
+ "\x13" => '\u0013',
23
+ "\x14" => '\u0014',
24
+ "\x15" => '\u0015',
25
+ "\x16" => '\u0016',
26
+ "\x17" => '\u0017',
27
+ "\x18" => '\u0018',
28
+ "\x19" => '\u0019',
29
+ "\x1a" => '\u001a',
30
+ "\x1b" => '\u001b',
31
+ "\x1c" => '\u001c',
32
+ "\x1d" => '\u001d',
33
+ "\x1e" => '\u001e',
34
+ "\x1f" => '\u001f',
35
+ '"' => '\"',
36
+ '\\' => '\\\\',
37
+ } # :nodoc:
38
+
39
+ # Convert a UTF8 encoded Ruby string _string_ to a JSON string, encoded with
40
+ # UTF16 big endian characters as \u????, and return it.
41
+ if defined?(::Encoding)
42
+ def utf8_to_json(string) # :nodoc:
43
+ string = string.dup
44
+ string.force_encoding(::Encoding::ASCII_8BIT)
45
+ string.gsub!(/["\\\x0-\x1f]/) { MAP[$&] }
46
+ string.force_encoding(::Encoding::UTF_8)
47
+ string
48
+ end
49
+
50
+ def utf8_to_json_ascii(string) # :nodoc:
51
+ string = string.dup
52
+ string.force_encoding(::Encoding::ASCII_8BIT)
53
+ string.gsub!(/["\\\x0-\x1f]/n) { MAP[$&] }
54
+ string.gsub!(/(
55
+ (?:
56
+ [\xc2-\xdf][\x80-\xbf] |
57
+ [\xe0-\xef][\x80-\xbf]{2} |
58
+ [\xf0-\xf4][\x80-\xbf]{3}
59
+ )+ |
60
+ [\x80-\xc1\xf5-\xff] # invalid
61
+ )/nx) { |c|
62
+ c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'"
63
+ s = JSON.iconv('utf-16be', 'utf-8', c).unpack('H*')[0]
64
+ s.force_encoding(::Encoding::ASCII_8BIT)
65
+ s.gsub!(/.{4}/n, '\\\\u\&')
66
+ s.force_encoding(::Encoding::UTF_8)
67
+ }
68
+ string.force_encoding(::Encoding::UTF_8)
69
+ string
70
+ rescue => e
71
+ raise GeneratorError.wrap(e)
72
+ end
73
+
74
+ def valid_utf8?(string)
75
+ encoding = string.encoding
76
+ (encoding == Encoding::UTF_8 || encoding == Encoding::ASCII) &&
77
+ string.valid_encoding?
78
+ end
79
+ module_function :valid_utf8?
80
+ else
81
+ def utf8_to_json(string) # :nodoc:
82
+ string.gsub(/["\\\x0-\x1f]/n) { MAP[$&] }
83
+ end
84
+
85
+ def utf8_to_json_ascii(string) # :nodoc:
86
+ string = string.gsub(/["\\\x0-\x1f]/) { MAP[$&] }
87
+ string.gsub!(/(
88
+ (?:
89
+ [\xc2-\xdf][\x80-\xbf] |
90
+ [\xe0-\xef][\x80-\xbf]{2} |
91
+ [\xf0-\xf4][\x80-\xbf]{3}
92
+ )+ |
93
+ [\x80-\xc1\xf5-\xff] # invalid
94
+ )/nx) { |c|
95
+ c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'"
96
+ s = JSON.iconv('utf-16be', 'utf-8', c).unpack('H*')[0]
97
+ s.gsub!(/.{4}/n, '\\\\u\&')
98
+ }
99
+ string
100
+ rescue => e
101
+ raise GeneratorError.wrap(e)
102
+ end
103
+
104
+ def valid_utf8?(string)
105
+ string =~
106
+ /\A( [\x09\x0a\x0d\x20-\x7e] # ASCII
107
+ | [\xc2-\xdf][\x80-\xbf] # non-overlong 2-byte
108
+ | \xe0[\xa0-\xbf][\x80-\xbf] # excluding overlongs
109
+ | [\xe1-\xec\xee\xef][\x80-\xbf]{2} # straight 3-byte
110
+ | \xed[\x80-\x9f][\x80-\xbf] # excluding surrogates
111
+ | \xf0[\x90-\xbf][\x80-\xbf]{2} # planes 1-3
112
+ | [\xf1-\xf3][\x80-\xbf]{3} # planes 4-15
113
+ | \xf4[\x80-\x8f][\x80-\xbf]{2} # plane 16
114
+ )*\z/nx
115
+ end
116
+ end
117
+ module_function :utf8_to_json, :utf8_to_json_ascii, :valid_utf8?
118
+
119
+
120
+ module Pure
121
+ module Generator
122
+ # This class is used to create State instances, that are use to hold data
123
+ # while generating a JSON text from a Ruby data structure.
124
+ class State
125
+ # Creates a State object from _opts_, which ought to be Hash to create
126
+ # a new State instance configured by _opts_, something else to create
127
+ # an unconfigured instance. If _opts_ is a State object, it is just
128
+ # returned.
129
+ def self.from_state(opts)
130
+ case
131
+ when self === opts
132
+ opts
133
+ when opts.respond_to?(:to_hash)
134
+ new(opts.to_hash)
135
+ when opts.respond_to?(:to_h)
136
+ new(opts.to_h)
137
+ else
138
+ SAFE_STATE_PROTOTYPE.dup
139
+ end
140
+ end
141
+
142
+ # Instantiates a new State object, configured by _opts_.
143
+ #
144
+ # _opts_ can have the following keys:
145
+ #
146
+ # * *indent*: a string used to indent levels (default: ''),
147
+ # * *space*: a string that is put after, a : or , delimiter (default: ''),
148
+ # * *space_before*: a string that is put before a : pair delimiter (default: ''),
149
+ # * *object_nl*: a string that is put at the end of a JSON object (default: ''),
150
+ # * *array_nl*: a string that is put at the end of a JSON array (default: ''),
151
+ # * *check_circular*: is deprecated now, use the :max_nesting option instead,
152
+ # * *max_nesting*: sets the maximum level of data structure nesting in
153
+ # the generated JSON, max_nesting = 0 if no maximum should be checked.
154
+ # * *allow_nan*: true if NaN, Infinity, and -Infinity should be
155
+ # generated, otherwise an exception is thrown, if these values are
156
+ # encountered. This options defaults to false.
157
+ # * *quirks_mode*: Enables quirks_mode for parser, that is for example
158
+ # generating single JSON values instead of documents is possible.
159
+ def initialize(opts = {})
160
+ @indent = ''
161
+ @space = ''
162
+ @space_before = ''
163
+ @object_nl = ''
164
+ @array_nl = ''
165
+ @allow_nan = false
166
+ @ascii_only = false
167
+ @quirks_mode = false
168
+ @buffer_initial_length = 1024
169
+ configure opts
170
+ end
171
+
172
+ # This string is used to indent levels in the JSON text.
173
+ attr_accessor :indent
174
+
175
+ # This string is used to insert a space between the tokens in a JSON
176
+ # string.
177
+ attr_accessor :space
178
+
179
+ # This string is used to insert a space before the ':' in JSON objects.
180
+ attr_accessor :space_before
181
+
182
+ # This string is put at the end of a line that holds a JSON object (or
183
+ # Hash).
184
+ attr_accessor :object_nl
185
+
186
+ # This string is put at the end of a line that holds a JSON array.
187
+ attr_accessor :array_nl
188
+
189
+ # This integer returns the maximum level of data structure nesting in
190
+ # the generated JSON, max_nesting = 0 if no maximum is checked.
191
+ attr_accessor :max_nesting
192
+
193
+ # If this attribute is set to true, quirks mode is enabled, otherwise
194
+ # it's disabled.
195
+ attr_accessor :quirks_mode
196
+
197
+ # :stopdoc:
198
+ attr_reader :buffer_initial_length
199
+
200
+ def buffer_initial_length=(length)
201
+ if length > 0
202
+ @buffer_initial_length = length
203
+ end
204
+ end
205
+ # :startdoc:
206
+
207
+ # This integer returns the current depth data structure nesting in the
208
+ # generated JSON.
209
+ attr_accessor :depth
210
+
211
+ def check_max_nesting # :nodoc:
212
+ return if @max_nesting.zero?
213
+ current_nesting = depth + 1
214
+ current_nesting > @max_nesting and
215
+ raise NestingError, "nesting of #{current_nesting} is too deep"
216
+ end
217
+
218
+ # Returns true, if circular data structures are checked,
219
+ # otherwise returns false.
220
+ def check_circular?
221
+ !@max_nesting.zero?
222
+ end
223
+
224
+ # Returns true if NaN, Infinity, and -Infinity should be considered as
225
+ # valid JSON and output.
226
+ def allow_nan?
227
+ @allow_nan
228
+ end
229
+
230
+ # Returns true, if only ASCII characters should be generated. Otherwise
231
+ # returns false.
232
+ def ascii_only?
233
+ @ascii_only
234
+ end
235
+
236
+ # Returns true, if quirks mode is enabled. Otherwise returns false.
237
+ def quirks_mode?
238
+ @quirks_mode
239
+ end
240
+
241
+ # Configure this State instance with the Hash _opts_, and return
242
+ # itself.
243
+ def configure(opts)
244
+ if opts.respond_to?(:to_hash)
245
+ opts = opts.to_hash
246
+ elsif opts.respond_to?(:to_h)
247
+ opts = opts.to_h
248
+ else
249
+ raise TypeError, "can't convert #{opts.class} into Hash"
250
+ end
251
+ for key, value in opts
252
+ instance_variable_set "@#{key}", value
253
+ end
254
+ @indent = opts[:indent] if opts.key?(:indent)
255
+ @space = opts[:space] if opts.key?(:space)
256
+ @space_before = opts[:space_before] if opts.key?(:space_before)
257
+ @object_nl = opts[:object_nl] if opts.key?(:object_nl)
258
+ @array_nl = opts[:array_nl] if opts.key?(:array_nl)
259
+ @allow_nan = !!opts[:allow_nan] if opts.key?(:allow_nan)
260
+ @ascii_only = opts[:ascii_only] if opts.key?(:ascii_only)
261
+ @depth = opts[:depth] || 0
262
+ @quirks_mode = opts[:quirks_mode] if opts.key?(:quirks_mode)
263
+ @buffer_initial_length ||= opts[:buffer_initial_length]
264
+
265
+ if !opts.key?(:max_nesting) # defaults to 100
266
+ @max_nesting = 100
267
+ elsif opts[:max_nesting]
268
+ @max_nesting = opts[:max_nesting]
269
+ else
270
+ @max_nesting = 0
271
+ end
272
+ self
273
+ end
274
+ alias merge configure
275
+
276
+ # Returns the configuration instance variables as a hash, that can be
277
+ # passed to the configure method.
278
+ def to_h
279
+ result = {}
280
+ for iv in instance_variables
281
+ iv = iv.to_s[1..-1]
282
+ result[iv.to_sym] = self[iv]
283
+ end
284
+ result
285
+ end
286
+
287
+ alias to_hash to_h
288
+
289
+ # Generates a valid JSON document from object +obj+ and returns the
290
+ # result. If no valid JSON document can be created this method raises a
291
+ # GeneratorError exception.
292
+ def generate(obj)
293
+ result = obj.to_json(self)
294
+ JSON.valid_utf8?(result) or raise GeneratorError,
295
+ "source sequence #{result.inspect} is illegal/malformed utf-8"
296
+ unless @quirks_mode
297
+ unless result =~ /\A\s*\[/ && result =~ /\]\s*\Z/ ||
298
+ result =~ /\A\s*\{/ && result =~ /\}\s*\Z/
299
+ then
300
+ raise GeneratorError, "only generation of JSON objects or arrays allowed"
301
+ end
302
+ end
303
+ result
304
+ end
305
+
306
+ # Return the value returned by method +name+.
307
+ def [](name)
308
+ if respond_to?(name)
309
+ __send__(name)
310
+ else
311
+ instance_variable_get("@#{name}")
312
+ end
313
+ end
314
+
315
+ def []=(name, value)
316
+ if respond_to?(name_writer = "#{name}=")
317
+ __send__ name_writer, value
318
+ else
319
+ instance_variable_set "@#{name}", value
320
+ end
321
+ end
322
+ end
323
+
324
+ module GeneratorMethods
325
+ module Object
326
+ # Converts this object to a string (calling #to_s), converts
327
+ # it to a JSON string, and returns the result. This is a fallback, if no
328
+ # special method #to_json was defined for some object.
329
+ def to_json(*) to_s.to_json end
330
+ end
331
+
332
+ module Hash
333
+ # Returns a JSON string containing a JSON object, that is unparsed from
334
+ # this Hash instance.
335
+ # _state_ is a JSON::State object, that can also be used to configure the
336
+ # produced JSON string output further.
337
+ # _depth_ is used to find out nesting depth, to indent accordingly.
338
+ def to_json(state = nil, *)
339
+ state = State.from_state(state)
340
+ state.check_max_nesting
341
+ json_transform(state)
342
+ end
343
+
344
+ private
345
+
346
+ def json_shift(state)
347
+ state.object_nl.empty? or return ''
348
+ state.indent * state.depth
349
+ end
350
+
351
+ def json_transform(state)
352
+ delim = ','
353
+ delim << state.object_nl
354
+ result = '{'
355
+ result << state.object_nl
356
+ depth = state.depth += 1
357
+ first = true
358
+ indent = !state.object_nl.empty?
359
+ each { |key,value|
360
+ result << delim unless first
361
+ result << state.indent * depth if indent
362
+ result << key.to_s.to_json(state)
363
+ result << state.space_before
364
+ result << ':'
365
+ result << state.space
366
+ result << value.to_json(state)
367
+ first = false
368
+ }
369
+ depth = state.depth -= 1
370
+ result << state.object_nl
371
+ result << state.indent * depth if indent
372
+ result << '}'
373
+ result
374
+ end
375
+ end
376
+
377
+ module Array
378
+ # Returns a JSON string containing a JSON array, that is unparsed from
379
+ # this Array instance.
380
+ # _state_ is a JSON::State object, that can also be used to configure the
381
+ # produced JSON string output further.
382
+ def to_json(state = nil, *)
383
+ state = State.from_state(state)
384
+ state.check_max_nesting
385
+ json_transform(state)
386
+ end
387
+
388
+ private
389
+
390
+ def json_transform(state)
391
+ delim = ','
392
+ delim << state.array_nl
393
+ result = '['
394
+ result << state.array_nl
395
+ depth = state.depth += 1
396
+ first = true
397
+ indent = !state.array_nl.empty?
398
+ each { |value|
399
+ result << delim unless first
400
+ result << state.indent * depth if indent
401
+ result << value.to_json(state)
402
+ first = false
403
+ }
404
+ depth = state.depth -= 1
405
+ result << state.array_nl
406
+ result << state.indent * depth if indent
407
+ result << ']'
408
+ end
409
+ end
410
+
411
+ module Integer
412
+ # Returns a JSON string representation for this Integer number.
413
+ def to_json(*) to_s end
414
+ end
415
+
416
+ module Float
417
+ # Returns a JSON string representation for this Float number.
418
+ def to_json(state = nil, *)
419
+ state = State.from_state(state)
420
+ case
421
+ when infinite?
422
+ if state.allow_nan?
423
+ to_s
424
+ else
425
+ raise GeneratorError, "#{self} not allowed in JSON"
426
+ end
427
+ when nan?
428
+ if state.allow_nan?
429
+ to_s
430
+ else
431
+ raise GeneratorError, "#{self} not allowed in JSON"
432
+ end
433
+ else
434
+ to_s
435
+ end
436
+ end
437
+ end
438
+
439
+ module String
440
+ if defined?(::Encoding)
441
+ # This string should be encoded with UTF-8 A call to this method
442
+ # returns a JSON string encoded with UTF16 big endian characters as
443
+ # \u????.
444
+ def to_json(state = nil, *args)
445
+ state = State.from_state(state)
446
+ if encoding == ::Encoding::UTF_8
447
+ string = self
448
+ else
449
+ string = encode(::Encoding::UTF_8)
450
+ end
451
+ if state.ascii_only?
452
+ '"' << JSON.utf8_to_json_ascii(string) << '"'
453
+ else
454
+ '"' << JSON.utf8_to_json(string) << '"'
455
+ end
456
+ end
457
+ else
458
+ # This string should be encoded with UTF-8 A call to this method
459
+ # returns a JSON string encoded with UTF16 big endian characters as
460
+ # \u????.
461
+ def to_json(state = nil, *args)
462
+ state = State.from_state(state)
463
+ if state.ascii_only?
464
+ '"' << JSON.utf8_to_json_ascii(self) << '"'
465
+ else
466
+ '"' << JSON.utf8_to_json(self) << '"'
467
+ end
468
+ end
469
+ end
470
+
471
+ # Module that holds the extinding methods if, the String module is
472
+ # included.
473
+ module Extend
474
+ # Raw Strings are JSON Objects (the raw bytes are stored in an
475
+ # array for the key "raw"). The Ruby String can be created by this
476
+ # module method.
477
+ def json_create(o)
478
+ o['raw'].pack('C*')
479
+ end
480
+ end
481
+
482
+ # Extends _modul_ with the String::Extend module.
483
+ def self.included(modul)
484
+ modul.extend Extend
485
+ end
486
+
487
+ # This method creates a raw object hash, that can be nested into
488
+ # other data structures and will be unparsed as a raw string. This
489
+ # method should be used, if you want to convert raw strings to JSON
490
+ # instead of UTF-8 strings, e. g. binary data.
491
+ def to_json_raw_object
492
+ {
493
+ JSON.create_id => self.class.name,
494
+ 'raw' => self.unpack('C*'),
495
+ }
496
+ end
497
+
498
+ # This method creates a JSON text from the result of
499
+ # a call to to_json_raw_object of this String.
500
+ def to_json_raw(*args)
501
+ to_json_raw_object.to_json(*args)
502
+ end
503
+ end
504
+
505
+ module TrueClass
506
+ # Returns a JSON string for true: 'true'.
507
+ def to_json(*) 'true' end
508
+ end
509
+
510
+ module FalseClass
511
+ # Returns a JSON string for false: 'false'.
512
+ def to_json(*) 'false' end
513
+ end
514
+
515
+ module NilClass
516
+ # Returns a JSON string for nil: 'null'.
517
+ def to_json(*) 'null' end
518
+ end
519
+ end
520
+ end
521
+ end
522
+ end