angry_mob 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (125) hide show
  1. data/LICENSE +21 -0
  2. data/README.md +123 -0
  3. data/bin/mob +139 -0
  4. data/lib/angry_mob.rb +28 -0
  5. data/lib/angry_mob/act.rb +111 -0
  6. data/lib/angry_mob/act/scheduler.rb +143 -0
  7. data/lib/angry_mob/action.rb +11 -0
  8. data/lib/angry_mob/builder.rb +115 -0
  9. data/lib/angry_mob/extend.rb +10 -0
  10. data/lib/angry_mob/extend/array.rb +30 -0
  11. data/lib/angry_mob/extend/blank.rb +108 -0
  12. data/lib/angry_mob/extend/blankslate.rb +109 -0
  13. data/lib/angry_mob/extend/dictionary.rb +140 -0
  14. data/lib/angry_mob/extend/hash.rb +67 -0
  15. data/lib/angry_mob/extend/object.rb +21 -0
  16. data/lib/angry_mob/extend/pathname.rb +23 -0
  17. data/lib/angry_mob/extend/string.rb +8 -0
  18. data/lib/angry_mob/log.rb +28 -0
  19. data/lib/angry_mob/mob.rb +77 -0
  20. data/lib/angry_mob/mob_loader.rb +115 -0
  21. data/lib/angry_mob/node.rb +44 -0
  22. data/lib/angry_mob/notifier.rb +76 -0
  23. data/lib/angry_mob/target.rb +257 -0
  24. data/lib/angry_mob/target/arguments.rb +71 -0
  25. data/lib/angry_mob/target/call.rb +57 -0
  26. data/lib/angry_mob/target/default_resource_locator.rb +11 -0
  27. data/lib/angry_mob/target/defaults.rb +23 -0
  28. data/lib/angry_mob/target/mother.rb +66 -0
  29. data/lib/angry_mob/target/notify.rb +57 -0
  30. data/lib/angry_mob/target/tracking.rb +96 -0
  31. data/lib/angry_mob/ui.rb +247 -0
  32. data/lib/angry_mob/util.rb +11 -0
  33. data/lib/angry_mob/vendored.rb +8 -0
  34. data/lib/angry_mob/version.rb +3 -0
  35. data/vendor/angry_hash/Rakefile +17 -0
  36. data/vendor/angry_hash/VERSION +1 -0
  37. data/vendor/angry_hash/angry_hash.gemspec +47 -0
  38. data/vendor/angry_hash/examples/accessors_eg.rb +46 -0
  39. data/vendor/angry_hash/examples/creation_eg.rb +43 -0
  40. data/vendor/angry_hash/examples/dsl.eg.rb +18 -0
  41. data/vendor/angry_hash/examples/dup_eg.rb +86 -0
  42. data/vendor/angry_hash/examples/eg_helper.rb +24 -0
  43. data/vendor/angry_hash/examples/merge_eg.rb +135 -0
  44. data/vendor/angry_hash/lib/angry_hash.rb +215 -0
  45. data/vendor/angry_hash/lib/angry_hash/dsl.rb +44 -0
  46. data/vendor/angry_hash/lib/angry_hash/extension_tracking.rb +12 -0
  47. data/vendor/angry_hash/lib/angry_hash/merge_string.rb +58 -0
  48. data/vendor/json/COPYING +58 -0
  49. data/vendor/json/GPL +340 -0
  50. data/vendor/json/README +360 -0
  51. data/vendor/json/lib/json/common.rb +371 -0
  52. data/vendor/json/lib/json/pure.rb +77 -0
  53. data/vendor/json/lib/json/pure/generator.rb +443 -0
  54. data/vendor/json/lib/json/pure/parser.rb +303 -0
  55. data/vendor/json/lib/json/version.rb +8 -0
  56. data/vendor/thor/CHANGELOG.rdoc +89 -0
  57. data/vendor/thor/LICENSE +20 -0
  58. data/vendor/thor/README.rdoc +297 -0
  59. data/vendor/thor/Thorfile +69 -0
  60. data/vendor/thor/bin/rake2thor +86 -0
  61. data/vendor/thor/bin/thor +6 -0
  62. data/vendor/thor/lib/thor.rb +244 -0
  63. data/vendor/thor/lib/thor/actions.rb +275 -0
  64. data/vendor/thor/lib/thor/actions/create_file.rb +103 -0
  65. data/vendor/thor/lib/thor/actions/directory.rb +91 -0
  66. data/vendor/thor/lib/thor/actions/empty_directory.rb +134 -0
  67. data/vendor/thor/lib/thor/actions/file_manipulation.rb +223 -0
  68. data/vendor/thor/lib/thor/actions/inject_into_file.rb +104 -0
  69. data/vendor/thor/lib/thor/base.rb +540 -0
  70. data/vendor/thor/lib/thor/core_ext/file_binary_read.rb +9 -0
  71. data/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +75 -0
  72. data/vendor/thor/lib/thor/core_ext/ordered_hash.rb +100 -0
  73. data/vendor/thor/lib/thor/error.rb +30 -0
  74. data/vendor/thor/lib/thor/group.rb +271 -0
  75. data/vendor/thor/lib/thor/invocation.rb +180 -0
  76. data/vendor/thor/lib/thor/parser.rb +4 -0
  77. data/vendor/thor/lib/thor/parser/argument.rb +67 -0
  78. data/vendor/thor/lib/thor/parser/arguments.rb +150 -0
  79. data/vendor/thor/lib/thor/parser/option.rb +128 -0
  80. data/vendor/thor/lib/thor/parser/options.rb +169 -0
  81. data/vendor/thor/lib/thor/rake_compat.rb +66 -0
  82. data/vendor/thor/lib/thor/runner.rb +314 -0
  83. data/vendor/thor/lib/thor/shell.rb +83 -0
  84. data/vendor/thor/lib/thor/shell/basic.rb +239 -0
  85. data/vendor/thor/lib/thor/shell/color.rb +108 -0
  86. data/vendor/thor/lib/thor/task.rb +102 -0
  87. data/vendor/thor/lib/thor/util.rb +224 -0
  88. data/vendor/thor/lib/thor/version.rb +3 -0
  89. data/vendor/thor/spec/actions/create_file_spec.rb +170 -0
  90. data/vendor/thor/spec/actions/directory_spec.rb +131 -0
  91. data/vendor/thor/spec/actions/empty_directory_spec.rb +91 -0
  92. data/vendor/thor/spec/actions/file_manipulation_spec.rb +271 -0
  93. data/vendor/thor/spec/actions/inject_into_file_spec.rb +135 -0
  94. data/vendor/thor/spec/actions_spec.rb +292 -0
  95. data/vendor/thor/spec/base_spec.rb +263 -0
  96. data/vendor/thor/spec/core_ext/hash_with_indifferent_access_spec.rb +43 -0
  97. data/vendor/thor/spec/core_ext/ordered_hash_spec.rb +115 -0
  98. data/vendor/thor/spec/fixtures/application.rb +2 -0
  99. data/vendor/thor/spec/fixtures/bundle/execute.rb +6 -0
  100. data/vendor/thor/spec/fixtures/bundle/main.thor +1 -0
  101. data/vendor/thor/spec/fixtures/doc/%file_name%.rb.tt +1 -0
  102. data/vendor/thor/spec/fixtures/doc/README +3 -0
  103. data/vendor/thor/spec/fixtures/doc/config.rb +1 -0
  104. data/vendor/thor/spec/fixtures/group.thor +90 -0
  105. data/vendor/thor/spec/fixtures/invoke.thor +112 -0
  106. data/vendor/thor/spec/fixtures/script.thor +145 -0
  107. data/vendor/thor/spec/fixtures/task.thor +10 -0
  108. data/vendor/thor/spec/group_spec.rb +171 -0
  109. data/vendor/thor/spec/invocation_spec.rb +107 -0
  110. data/vendor/thor/spec/parser/argument_spec.rb +47 -0
  111. data/vendor/thor/spec/parser/arguments_spec.rb +64 -0
  112. data/vendor/thor/spec/parser/option_spec.rb +202 -0
  113. data/vendor/thor/spec/parser/options_spec.rb +292 -0
  114. data/vendor/thor/spec/rake_compat_spec.rb +68 -0
  115. data/vendor/thor/spec/runner_spec.rb +210 -0
  116. data/vendor/thor/spec/shell/basic_spec.rb +205 -0
  117. data/vendor/thor/spec/shell/color_spec.rb +41 -0
  118. data/vendor/thor/spec/shell_spec.rb +34 -0
  119. data/vendor/thor/spec/spec.opts +1 -0
  120. data/vendor/thor/spec/spec_helper.rb +54 -0
  121. data/vendor/thor/spec/task_spec.rb +69 -0
  122. data/vendor/thor/spec/thor_spec.rb +237 -0
  123. data/vendor/thor/spec/util_spec.rb +163 -0
  124. data/vendor/thor/thor.gemspec +120 -0
  125. metadata +199 -0
@@ -0,0 +1,360 @@
1
+ == json - JSON Implementation for Ruby
2
+
3
+ === Description
4
+
5
+ This is a implementation of the JSON specification according to RFC 4627
6
+ (http://www.ietf.org/rfc/rfc4627.txt). Starting from version 1.0.0 on there
7
+ will be two variants available:
8
+
9
+ * A pure ruby variant, that relies on the iconv and the stringscan
10
+ extensions, which are both part of the ruby standard library.
11
+ * The quite a bit faster C extension variant, which is in parts implemented
12
+ in C and comes with its own unicode conversion functions and a parser
13
+ generated by the ragel state machine compiler
14
+ (http://www.cs.queensu.ca/~thurston/ragel).
15
+
16
+ Both variants of the JSON generator escape all non-ASCII and control characters
17
+ with \uXXXX escape sequences, and support UTF-16 surrogate pairs in order to be
18
+ able to generate the whole range of unicode code points. This means that
19
+ generated JSON document is encoded as UTF-8 (because ASCII is a subset of
20
+ UTF-8) and at the same time avoids decoding problems for receiving endpoints,
21
+ that don't expect UTF-8 encoded texts. On the negative side this may lead to a
22
+ bit longer strings than necessarry.
23
+
24
+ All strings, that are to be encoded as JSON strings, should be UTF-8 byte
25
+ sequences on the Ruby side. To encode raw binary strings, that aren't UTF-8
26
+ encoded, please use the to_json_raw_object method of String (which produces
27
+ an object, that contains a byte array) and decode the result on the receiving
28
+ endpoint.
29
+
30
+ The JSON parsers can parse UTF-8, UTF-16BE, UTF-16LE, UTF-32BE, and UTF-32LE
31
+ JSON documents under Ruby 1.8. Under Ruby 1.9 they take advantage of Ruby's
32
+ M17n features and can parse all documents which have the correct
33
+ String#encoding set. If a document string has ASCII-8BIT as an encoding the
34
+ parser attempts to figure out which of the UTF encodings from above it is and
35
+ trys to parse it.
36
+
37
+ === Installation
38
+
39
+ It's recommended to use the extension variant of JSON, because it's faster than
40
+ the pure ruby variant. If you cannot build it on your system, you can settle
41
+ for the latter.
42
+
43
+ Just type into the command line as root:
44
+
45
+ # rake install
46
+
47
+ The above command will build the extensions and install them on your system.
48
+
49
+ # rake install_pure
50
+
51
+ or
52
+
53
+ # ruby install.rb
54
+
55
+ will just install the pure ruby implementation of JSON.
56
+
57
+ If you use Rubygems you can type
58
+
59
+ # gem install json
60
+
61
+ instead, to install the newest JSON version.
62
+
63
+ There is also a pure ruby json only variant of the gem, that can be installed
64
+ with:
65
+
66
+ # gem install json_pure
67
+
68
+ === Compiling the extensions yourself
69
+
70
+ If you want to build the extensions yourself you need rake:
71
+
72
+ You can get it from rubyforge:
73
+ http://rubyforge.org/projects/rake
74
+
75
+ or just type
76
+
77
+ # gem install rake
78
+
79
+ for the installation via rubygems.
80
+
81
+ If you want to create the parser.c file from its parser.rl file or draw nice
82
+ graphviz images of the state machines, you need ragel from: http://www.cs.queensu.ca/~thurston/ragel
83
+
84
+
85
+ === Usage
86
+
87
+ To use JSON you can
88
+ require 'json'
89
+ to load the installed variant (either the extension 'json' or the pure
90
+ variant 'json_pure'). If you have installed the extension variant, you can
91
+ pick either the extension variant or the pure variant by typing
92
+ require 'json/ext'
93
+ or
94
+ require 'json/pure'
95
+
96
+ Now you can parse a JSON document into a ruby data structure by calling
97
+
98
+ JSON.parse(document)
99
+
100
+ If you want to generate a JSON document from a ruby data structure call
101
+ JSON.generate(data)
102
+
103
+ You can also use the pretty_generate method (which formats the output more
104
+ verbosely and nicely) or fast_generate (which doesn't do any of the security
105
+ checks generate performs, e. g. nesting deepness checks).
106
+
107
+ To create a valid JSON document you have to make sure, that the output is
108
+ embedded in either a JSON array [] or a JSON object {}. The easiest way to do
109
+ this, is by putting your values in a Ruby Array or Hash instance.
110
+
111
+ There are also the JSON and JSON[] methods which use parse on a String or
112
+ generate a JSON document from an array or hash:
113
+
114
+ document = JSON 'test' => 23 # => "{\"test\":23}"
115
+ document = JSON['test'] => 23 # => "{\"test\":23}"
116
+
117
+ and
118
+
119
+ data = JSON '{"test":23}' # => {"test"=>23}
120
+ data = JSON['{"test":23}'] # => {"test"=>23}
121
+
122
+ You can choose to load a set of common additions to ruby core's objects if
123
+ you
124
+ require 'json/add/core'
125
+
126
+ After requiring this you can, e. g., serialise/deserialise Ruby ranges:
127
+
128
+ JSON JSON(1..10) # => 1..10
129
+
130
+ To find out how to add JSON support to other or your own classes, read the
131
+ section "More Examples" below.
132
+
133
+ To get the best compatibility to rails' JSON implementation, you can
134
+ require 'json/add/rails'
135
+
136
+ Both of the additions attempt to require 'json' (like above) first, if it has
137
+ not been required yet.
138
+
139
+ === More Examples
140
+
141
+ To create a JSON document from a ruby data structure, you can call
142
+ JSON.generate like that:
143
+
144
+ json = JSON.generate [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
145
+ # => "[1,2,{\"a\":3.141},false,true,null,\"4..10\"]"
146
+
147
+ To get back a ruby data structure from a JSON document, you have to call
148
+ JSON.parse on it:
149
+
150
+ JSON.parse json
151
+ # => [1, 2, {"a"=>3.141}, false, true, nil, "4..10"]
152
+
153
+ Note, that the range from the original data structure is a simple
154
+ string now. The reason for this is, that JSON doesn't support ranges
155
+ or arbitrary classes. In this case the json library falls back to call
156
+ Object#to_json, which is the same as #to_s.to_json.
157
+
158
+ It's possible to add JSON support serialization to arbitrary classes by
159
+ simply implementing a more specialized version of the #to_json method, that
160
+ should return a JSON object (a hash converted to JSON with #to_json) like
161
+ this (don't forget the *a for all the arguments):
162
+
163
+ class Range
164
+ def to_json(*a)
165
+ {
166
+ 'json_class' => self.class.name, # = 'Range'
167
+ 'data' => [ first, last, exclude_end? ]
168
+ }.to_json(*a)
169
+ end
170
+ end
171
+
172
+ The hash key 'json_class' is the class, that will be asked to deserialise the
173
+ JSON representation later. In this case it's 'Range', but any namespace of
174
+ the form 'A::B' or '::A::B' will do. All other keys are arbitrary and can be
175
+ used to store the necessary data to configure the object to be deserialised.
176
+
177
+ If a the key 'json_class' is found in a JSON object, the JSON parser checks
178
+ if the given class responds to the json_create class method. If so, it is
179
+ called with the JSON object converted to a Ruby hash. So a range can
180
+ be deserialised by implementing Range.json_create like this:
181
+
182
+ class Range
183
+ def self.json_create(o)
184
+ new(*o['data'])
185
+ end
186
+ end
187
+
188
+ Now it possible to serialise/deserialise ranges as well:
189
+
190
+ json = JSON.generate [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
191
+ # => "[1,2,{\"a\":3.141},false,true,null,{\"json_class\":\"Range\",\"data\":[4,10,false]}]"
192
+ JSON.parse json
193
+ # => [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
194
+
195
+ JSON.generate always creates the shortest possible string representation of a
196
+ ruby data structure in one line. This is good for data storage or network
197
+ protocols, but not so good for humans to read. Fortunately there's also
198
+ JSON.pretty_generate (or JSON.pretty_generate) that creates a more readable
199
+ output:
200
+
201
+ puts JSON.pretty_generate([1, 2, {"a"=>3.141}, false, true, nil, 4..10])
202
+ [
203
+ 1,
204
+ 2,
205
+ {
206
+ "a": 3.141
207
+ },
208
+ false,
209
+ true,
210
+ null,
211
+ {
212
+ "json_class": "Range",
213
+ "data": [
214
+ 4,
215
+ 10,
216
+ false
217
+ ]
218
+ }
219
+ ]
220
+
221
+ There are also the methods Kernel#j for generate, and Kernel#jj for
222
+ pretty_generate output to the console, that work analogous to Core Ruby's p and
223
+ the pp library's pp methods.
224
+
225
+ The script tools/server.rb contains a small example if you want to test, how
226
+ receiving a JSON object from a webrick server in your browser with the
227
+ javasript prototype library (http://www.prototypejs.org) works.
228
+
229
+ === Speed Comparisons
230
+
231
+ I have created some benchmark results (see the benchmarks/data-p4-3Ghz
232
+ subdir of the package) for the JSON-parser to estimate the speed up in the C
233
+ extension:
234
+
235
+ Comparing times (call_time_mean):
236
+ 1 ParserBenchmarkExt#parser 900 repeats:
237
+ 553.922304770 ( real) -> 21.500x
238
+ 0.001805307
239
+ 2 ParserBenchmarkYAML#parser 1000 repeats:
240
+ 224.513358139 ( real) -> 8.714x
241
+ 0.004454078
242
+ 3 ParserBenchmarkPure#parser 1000 repeats:
243
+ 26.755020642 ( real) -> 1.038x
244
+ 0.037376163
245
+ 4 ParserBenchmarkRails#parser 1000 repeats:
246
+ 25.763381731 ( real) -> 1.000x
247
+ 0.038814780
248
+ calls/sec ( time) -> speed covers
249
+ secs/call
250
+
251
+ In the table above 1 is JSON::Ext::Parser, 2 is YAML.load with YAML
252
+ compatbile JSON document, 3 is is JSON::Pure::Parser, and 4 is
253
+ ActiveSupport::JSON.decode. The ActiveSupport JSON-decoder converts the
254
+ input first to YAML and then uses the YAML-parser, the conversion seems to
255
+ slow it down so much that it is only as fast as the JSON::Pure::Parser!
256
+
257
+ If you look at the benchmark data you can see that this is mostly caused by
258
+ the frequent high outliers - the median of the Rails-parser runs is still
259
+ overall smaller than the median of the JSON::Pure::Parser runs:
260
+
261
+ Comparing times (call_time_median):
262
+ 1 ParserBenchmarkExt#parser 900 repeats:
263
+ 800.592479481 ( real) -> 26.936x
264
+ 0.001249075
265
+ 2 ParserBenchmarkYAML#parser 1000 repeats:
266
+ 271.002390644 ( real) -> 9.118x
267
+ 0.003690004
268
+ 3 ParserBenchmarkRails#parser 1000 repeats:
269
+ 30.227910865 ( real) -> 1.017x
270
+ 0.033082008
271
+ 4 ParserBenchmarkPure#parser 1000 repeats:
272
+ 29.722384421 ( real) -> 1.000x
273
+ 0.033644676
274
+ calls/sec ( time) -> speed covers
275
+ secs/call
276
+
277
+ I have benchmarked the JSON-Generator as well. This generated a few more
278
+ values, because there are different modes that also influence the achieved
279
+ speed:
280
+
281
+ Comparing times (call_time_mean):
282
+ 1 GeneratorBenchmarkExt#generator_fast 1000 repeats:
283
+ 547.354332608 ( real) -> 15.090x
284
+ 0.001826970
285
+ 2 GeneratorBenchmarkExt#generator_safe 1000 repeats:
286
+ 443.968212317 ( real) -> 12.240x
287
+ 0.002252414
288
+ 3 GeneratorBenchmarkExt#generator_pretty 900 repeats:
289
+ 375.104545883 ( real) -> 10.341x
290
+ 0.002665923
291
+ 4 GeneratorBenchmarkPure#generator_fast 1000 repeats:
292
+ 49.978706968 ( real) -> 1.378x
293
+ 0.020008521
294
+ 5 GeneratorBenchmarkRails#generator 1000 repeats:
295
+ 38.531868759 ( real) -> 1.062x
296
+ 0.025952543
297
+ 6 GeneratorBenchmarkPure#generator_safe 1000 repeats:
298
+ 36.927649925 ( real) -> 1.018x 7 (>=3859)
299
+ 0.027079979
300
+ 7 GeneratorBenchmarkPure#generator_pretty 1000 repeats:
301
+ 36.272134441 ( real) -> 1.000x 6 (>=3859)
302
+ 0.027569373
303
+ calls/sec ( time) -> speed covers
304
+ secs/call
305
+
306
+ In the table above 1-3 are JSON::Ext::Generator methods. 4, 6, and 7 are
307
+ JSON::Pure::Generator methods and 5 is the Rails JSON generator. It is now a
308
+ bit faster than the generator_safe and generator_pretty methods of the pure
309
+ variant but slower than the others.
310
+
311
+ To achieve the fastest JSON document output, you can use the fast_generate
312
+ method. Beware, that this will disable the checking for circular Ruby data
313
+ structures, which may cause JSON to go into an infinite loop.
314
+
315
+ Here are the median comparisons for completeness' sake:
316
+
317
+ Comparing times (call_time_median):
318
+ 1 GeneratorBenchmarkExt#generator_fast 1000 repeats:
319
+ 708.258020939 ( real) -> 16.547x
320
+ 0.001411915
321
+ 2 GeneratorBenchmarkExt#generator_safe 1000 repeats:
322
+ 569.105020353 ( real) -> 13.296x
323
+ 0.001757145
324
+ 3 GeneratorBenchmarkExt#generator_pretty 900 repeats:
325
+ 482.825371244 ( real) -> 11.280x
326
+ 0.002071142
327
+ 4 GeneratorBenchmarkPure#generator_fast 1000 repeats:
328
+ 62.717626652 ( real) -> 1.465x
329
+ 0.015944481
330
+ 5 GeneratorBenchmarkRails#generator 1000 repeats:
331
+ 43.965681162 ( real) -> 1.027x
332
+ 0.022745013
333
+ 6 GeneratorBenchmarkPure#generator_safe 1000 repeats:
334
+ 43.929073409 ( real) -> 1.026x 7 (>=3859)
335
+ 0.022763968
336
+ 7 GeneratorBenchmarkPure#generator_pretty 1000 repeats:
337
+ 42.802514491 ( real) -> 1.000x 6 (>=3859)
338
+ 0.023363113
339
+ calls/sec ( time) -> speed covers
340
+ secs/call
341
+
342
+ === Author
343
+
344
+ Florian Frank <mailto:flori@ping.de>
345
+
346
+ === License
347
+
348
+ Ruby License, see the COPYING file included in the source distribution. The
349
+ Ruby License includes the GNU General Public License (GPL), Version 2, so see
350
+ the file GPL as well.
351
+
352
+ === Download
353
+
354
+ The latest version of this library can be downloaded at
355
+
356
+ * http://rubyforge.org/frs?group_id=953
357
+
358
+ Online Documentation should be located at
359
+
360
+ * http://json.rubyforge.org
@@ -0,0 +1,371 @@
1
+ require 'json/version'
2
+ require 'iconv'
3
+
4
+ module JSON
5
+ class << self
6
+ # If _object_ is string-like parse the string and return the parsed result
7
+ # as a Ruby data structure. Otherwise generate a JSON text from the Ruby
8
+ # data structure object and return it.
9
+ #
10
+ # The _opts_ argument is passed through to generate/parse respectively, see
11
+ # generate and parse for their documentation.
12
+ def [](object, opts = {})
13
+ if object.respond_to? :to_str
14
+ JSON.parse(object.to_str, opts => {})
15
+ else
16
+ JSON.generate(object, opts => {})
17
+ end
18
+ end
19
+
20
+ # Returns the JSON parser class, that is used by JSON. This might be either
21
+ # JSON::Ext::Parser or JSON::Pure::Parser.
22
+ attr_reader :parser
23
+
24
+ # Set the JSON parser class _parser_ to be used by JSON.
25
+ def parser=(parser) # :nodoc:
26
+ @parser = parser
27
+ remove_const :Parser if const_defined? :Parser
28
+ const_set :Parser, parser
29
+ end
30
+
31
+ # Return the constant located at _path_. The format of _path_ has to be
32
+ # either ::A::B::C or A::B::C. In any case A has to be located at the top
33
+ # level (absolute namespace path?). If there doesn't exist a constant at
34
+ # the given path, an ArgumentError is raised.
35
+ def deep_const_get(path) # :nodoc:
36
+ path = path.to_s
37
+ path.split(/::/).inject(Object) do |p, c|
38
+ case
39
+ when c.empty? then p
40
+ when p.const_defined?(c) then p.const_get(c)
41
+ else raise ArgumentError, "can't find const #{path}"
42
+ end
43
+ end
44
+ end
45
+
46
+ # Set the module _generator_ to be used by JSON.
47
+ def generator=(generator) # :nodoc:
48
+ @generator = generator
49
+ generator_methods = generator::GeneratorMethods
50
+ for const in generator_methods.constants
51
+ klass = deep_const_get(const)
52
+ modul = generator_methods.const_get(const)
53
+ klass.class_eval do
54
+ instance_methods(false).each do |m|
55
+ m.to_s == 'to_json' and remove_method m
56
+ end
57
+ include modul
58
+ end
59
+ end
60
+ self.state = generator::State
61
+ const_set :State, self.state
62
+ end
63
+
64
+ # Returns the JSON generator modul, that is used by JSON. This might be
65
+ # either JSON::Ext::Generator or JSON::Pure::Generator.
66
+ attr_reader :generator
67
+
68
+ # Returns the JSON generator state class, that is used by JSON. This might
69
+ # be either JSON::Ext::Generator::State or JSON::Pure::Generator::State.
70
+ attr_accessor :state
71
+
72
+ # This is create identifier, that is used to decide, if the _json_create_
73
+ # hook of a class should be called. It defaults to 'json_class'.
74
+ attr_accessor :create_id
75
+ end
76
+ self.create_id = 'json_class'
77
+
78
+ NaN = 0.0/0
79
+
80
+ Infinity = 1.0/0
81
+
82
+ MinusInfinity = -Infinity
83
+
84
+ # The base exception for JSON errors.
85
+ class JSONError < StandardError; end
86
+
87
+ # This exception is raised, if a parser error occurs.
88
+ class ParserError < JSONError; end
89
+
90
+ # This exception is raised, if the nesting of parsed datastructures is too
91
+ # deep.
92
+ class NestingError < ParserError; end
93
+
94
+ # This exception is raised, if a generator or unparser error occurs.
95
+ class GeneratorError < JSONError; end
96
+ # For backwards compatibility
97
+ UnparserError = GeneratorError
98
+
99
+ # If a circular data structure is encountered while unparsing
100
+ # this exception is raised.
101
+ class CircularDatastructure < GeneratorError; end
102
+
103
+ # This exception is raised, if the required unicode support is missing on the
104
+ # system. Usually this means, that the iconv library is not installed.
105
+ class MissingUnicodeSupport < JSONError; end
106
+
107
+ module_function
108
+
109
+ # Parse the JSON document _source_ into a Ruby data structure and return it.
110
+ #
111
+ # _opts_ can have the following
112
+ # keys:
113
+ # * *max_nesting*: The maximum depth of nesting allowed in the parsed data
114
+ # structures. Disable depth checking with :max_nesting => false, it defaults
115
+ # to 19.
116
+ # * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
117
+ # defiance of RFC 4627 to be parsed by the Parser. This option defaults
118
+ # to false.
119
+ # * *create_additions*: If set to false, the Parser doesn't create
120
+ # additions even if a matchin class and create_id was found. This option
121
+ # defaults to true.
122
+ def parse(source, opts = {})
123
+ JSON.parser.new(source, opts).parse
124
+ end
125
+
126
+ # Parse the JSON document _source_ into a Ruby data structure and return it.
127
+ # The bang version of the parse method, defaults to the more dangerous values
128
+ # for the _opts_ hash, so be sure only to parse trusted _source_ documents.
129
+ #
130
+ # _opts_ can have the following keys:
131
+ # * *max_nesting*: The maximum depth of nesting allowed in the parsed data
132
+ # structures. Enable depth checking with :max_nesting => anInteger. The parse!
133
+ # methods defaults to not doing max depth checking: This can be dangerous,
134
+ # if someone wants to fill up your stack.
135
+ # * *allow_nan*: If set to true, allow NaN, Infinity, and -Infinity in
136
+ # defiance of RFC 4627 to be parsed by the Parser. This option defaults
137
+ # to true.
138
+ # * *create_additions*: If set to false, the Parser doesn't create
139
+ # additions even if a matchin class and create_id was found. This option
140
+ # defaults to true.
141
+ def parse!(source, opts = {})
142
+ opts = {
143
+ :max_nesting => false,
144
+ :allow_nan => true
145
+ }.update(opts)
146
+ JSON.parser.new(source, opts).parse
147
+ end
148
+
149
+ # Generate a JSON document from the Ruby data structure _obj_ and return
150
+ # it. _state_ is * a JSON::State object,
151
+ # * or a Hash like object (responding to to_hash),
152
+ # * an object convertible into a hash by a to_h method,
153
+ # that is used as or to configure a State object.
154
+ #
155
+ # It defaults to a state object, that creates the shortest possible JSON text
156
+ # in one line, checks for circular data structures and doesn't allow NaN,
157
+ # Infinity, and -Infinity.
158
+ #
159
+ # A _state_ hash can have the following keys:
160
+ # * *indent*: a string used to indent levels (default: ''),
161
+ # * *space*: a string that is put after, a : or , delimiter (default: ''),
162
+ # * *space_before*: a string that is put before a : pair delimiter (default: ''),
163
+ # * *object_nl*: a string that is put at the end of a JSON object (default: ''),
164
+ # * *array_nl*: a string that is put at the end of a JSON array (default: ''),
165
+ # * *check_circular*: true if checking for circular data structures
166
+ # should be done (the default), false otherwise.
167
+ # * *allow_nan*: true if NaN, Infinity, and -Infinity should be
168
+ # generated, otherwise an exception is thrown, if these values are
169
+ # encountered. This options defaults to false.
170
+ # * *max_nesting*: The maximum depth of nesting allowed in the data
171
+ # structures from which JSON is to be generated. Disable depth checking
172
+ # with :max_nesting => false, it defaults to 19.
173
+ #
174
+ # See also the fast_generate for the fastest creation method with the least
175
+ # amount of sanity checks, and the pretty_generate method for some
176
+ # defaults for a pretty output.
177
+ def generate(obj, state = nil)
178
+ if state
179
+ state = State.from_state(state)
180
+ else
181
+ state = State.new
182
+ end
183
+ result = obj.to_json(state)
184
+ if result !~ /\A\s*(?:\[.*\]|\{.*\})\s*\Z/m
185
+ raise GeneratorError, "only generation of JSON objects or arrays allowed"
186
+ end
187
+ result
188
+ end
189
+
190
+ # :stopdoc:
191
+ # I want to deprecate these later, so I'll first be silent about them, and
192
+ # later delete them.
193
+ alias unparse generate
194
+ module_function :unparse
195
+ # :startdoc:
196
+
197
+ # Generate a JSON document from the Ruby data structure _obj_ and return it.
198
+ # This method disables the checks for circles in Ruby objects.
199
+ #
200
+ # *WARNING*: Be careful not to pass any Ruby data structures with circles as
201
+ # _obj_ argument, because this will cause JSON to go into an infinite loop.
202
+ def fast_generate(obj)
203
+ result = obj.to_json(nil)
204
+ if result !~ /\A(?:\[.*\]|\{.*\})\Z/
205
+ raise GeneratorError, "only generation of JSON objects or arrays allowed"
206
+ end
207
+ result
208
+ end
209
+
210
+ # :stopdoc:
211
+ # I want to deprecate these later, so I'll first be silent about them, and later delete them.
212
+ alias fast_unparse fast_generate
213
+ module_function :fast_unparse
214
+ # :startdoc:
215
+
216
+ # Generate a JSON document from the Ruby data structure _obj_ and return it.
217
+ # The returned document is a prettier form of the document returned by
218
+ # #unparse.
219
+ #
220
+ # The _opts_ argument can be used to configure the generator, see the
221
+ # generate method for a more detailed explanation.
222
+ def pretty_generate(obj, opts = nil)
223
+ state = JSON.state.new(
224
+ :indent => ' ',
225
+ :space => ' ',
226
+ :object_nl => "\n",
227
+ :array_nl => "\n",
228
+ :check_circular => true
229
+ )
230
+ if opts
231
+ if opts.respond_to? :to_hash
232
+ opts = opts.to_hash
233
+ elsif opts.respond_to? :to_h
234
+ opts = opts.to_h
235
+ else
236
+ raise TypeError, "can't convert #{opts.class} into Hash"
237
+ end
238
+ state.configure(opts)
239
+ end
240
+ result = obj.to_json(state)
241
+ if result !~ /\A\s*(?:\[.*\]|\{.*\})\s*\Z/m
242
+ raise GeneratorError, "only generation of JSON objects or arrays allowed"
243
+ end
244
+ result
245
+ end
246
+
247
+ # :stopdoc:
248
+ # I want to deprecate these later, so I'll first be silent about them, and later delete them.
249
+ alias pretty_unparse pretty_generate
250
+ module_function :pretty_unparse
251
+ # :startdoc:
252
+
253
+ # Load a ruby data structure from a JSON _source_ and return it. A source can
254
+ # either be a string-like object, an IO like object, or an object responding
255
+ # to the read method. If _proc_ was given, it will be called with any nested
256
+ # Ruby object as an argument recursively in depth first order.
257
+ #
258
+ # This method is part of the implementation of the load/dump interface of
259
+ # Marshal and YAML.
260
+ def load(source, proc = nil)
261
+ if source.respond_to? :to_str
262
+ source = source.to_str
263
+ elsif source.respond_to? :to_io
264
+ source = source.to_io.read
265
+ else
266
+ source = source.read
267
+ end
268
+ result = parse(source, :max_nesting => false, :allow_nan => true)
269
+ recurse_proc(result, &proc) if proc
270
+ result
271
+ end
272
+
273
+ def recurse_proc(result, &proc)
274
+ case result
275
+ when Array
276
+ result.each { |x| recurse_proc x, &proc }
277
+ proc.call result
278
+ when Hash
279
+ result.each { |x, y| recurse_proc x, &proc; recurse_proc y, &proc }
280
+ proc.call result
281
+ else
282
+ proc.call result
283
+ end
284
+ end
285
+
286
+ alias restore load
287
+ module_function :restore
288
+
289
+ # Dumps _obj_ as a JSON string, i.e. calls generate on the object and returns
290
+ # the result.
291
+ #
292
+ # If anIO (an IO like object or an object that responds to the write method)
293
+ # was given, the resulting JSON is written to it.
294
+ #
295
+ # If the number of nested arrays or objects exceeds _limit_ an ArgumentError
296
+ # exception is raised. This argument is similar (but not exactly the
297
+ # same!) to the _limit_ argument in Marshal.dump.
298
+ #
299
+ # This method is part of the implementation of the load/dump interface of
300
+ # Marshal and YAML.
301
+ def dump(obj, anIO = nil, limit = nil)
302
+ if anIO and limit.nil?
303
+ anIO = anIO.to_io if anIO.respond_to?(:to_io)
304
+ unless anIO.respond_to?(:write)
305
+ limit = anIO
306
+ anIO = nil
307
+ end
308
+ end
309
+ limit ||= 0
310
+ result = generate(obj, :allow_nan => true, :max_nesting => limit)
311
+ if anIO
312
+ anIO.write result
313
+ anIO
314
+ else
315
+ result
316
+ end
317
+ rescue JSON::NestingError
318
+ raise ArgumentError, "exceed depth limit"
319
+ end
320
+
321
+ # Shortuct for iconv.
322
+ def self.iconv(to, from, string)
323
+ Iconv.iconv(to, from, string).first
324
+ end
325
+ end
326
+
327
+ module ::Kernel
328
+ private
329
+
330
+ # Outputs _objs_ to STDOUT as JSON strings in the shortest form, that is in
331
+ # one line.
332
+ def j(*objs)
333
+ objs.each do |obj|
334
+ puts JSON::generate(obj, :allow_nan => true, :max_nesting => false)
335
+ end
336
+ nil
337
+ end
338
+
339
+ # Ouputs _objs_ to STDOUT as JSON strings in a pretty format, with
340
+ # indentation and over many lines.
341
+ def jj(*objs)
342
+ objs.each do |obj|
343
+ puts JSON::pretty_generate(obj, :allow_nan => true, :max_nesting => false)
344
+ end
345
+ nil
346
+ end
347
+
348
+ # If _object_ is string-like parse the string and return the parsed result as
349
+ # a Ruby data structure. Otherwise generate a JSON text from the Ruby data
350
+ # structure object and return it.
351
+ #
352
+ # The _opts_ argument is passed through to generate/parse respectively, see
353
+ # generate and parse for their documentation.
354
+ def JSON(object, opts = {})
355
+ if object.respond_to? :to_str
356
+ JSON.parse(object.to_str, opts)
357
+ else
358
+ JSON.generate(object, opts)
359
+ end
360
+ end
361
+ end
362
+
363
+ class ::Class
364
+ # Returns true, if this class can be used to create an instance
365
+ # from a serialised JSON string. The class has to implement a class
366
+ # method _json_create_ that expects a hash as first parameter, which includes
367
+ # the required data.
368
+ def json_creatable?
369
+ respond_to?(:json_create)
370
+ end
371
+ end