fiveruns-dash-ruby 0.8.3 → 0.8.4

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -18,10 +18,6 @@ See the Ruby support pages, http://support.fiveruns.com/faqs/dash/ruby, for info
18
18
 
19
19
  The FiveRuns Development Team & Dash community
20
20
 
21
- == Dependencies
22
-
23
- * The json gem
24
-
25
21
  == Platforms
26
22
 
27
23
  This library has only been tested on OSX and Linux. The `ruby' recipe (which collects metrics on the Ruby process) currently relies on `ps' -- so will not work on Windows. We're actively looking for contributions to widen the number of platforms we support; please help!
@@ -40,6 +36,11 @@ Please join the dash-users Google group, http://groups.google.com/group/dash-use
40
36
 
41
37
  You can also contact us via Twitter, Campfire, or email; see the main help page, http://support.fiveruns.com, for details.
42
38
 
39
+ == Note
40
+
41
+ This project contains a modified copy of the json_pure gem source code, which is distributed under
42
+ the Ruby license <http://www.ruby-lang.org/en/LICENSE.txt> by Florian Frank <flori@ping.de>.
43
+
43
44
  == License
44
45
 
45
46
  # (The FiveRuns License)
data/Rakefile CHANGED
@@ -19,7 +19,6 @@ begin
19
19
  s.description = "Provides an API to send metrics to the FiveRuns Dash service"
20
20
  s.authors = ["FiveRuns Development Team"]
21
21
  s.files = FileList['README.rdoc', 'Rakefile', 'version.yml', "{lib,test,recipes,examples}/**/*", ]
22
- s.add_dependency 'json'
23
22
  end
24
23
  rescue LoadError
25
24
  puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
@@ -35,4 +34,4 @@ task :coverage do
35
34
  FileUtils.cp_r 'coverage', ccout
36
35
  end
37
36
  system "open coverage/index.html" if PLATFORM['darwin']
38
- end
37
+ end
data/lib/fiveruns/dash.rb CHANGED
@@ -1,5 +1,9 @@
1
1
  require 'rubygems'
2
- require 'json'
2
+
3
+ module Fiveruns; end
4
+
5
+ # Pull in our forked copy of the pure JSON gem
6
+ require 'fiveruns/json'
3
7
 
4
8
  require 'pathname'
5
9
  require 'thread'
@@ -10,9 +14,6 @@ $:.unshift(File.dirname(__FILE__))
10
14
 
11
15
  # NB: Pre-load ALL Dash files here so we do not accidentally
12
16
  # use ActiveSupport's autoloading.
13
-
14
- module Fiveruns; end
15
-
16
17
  require 'dash/version'
17
18
  require 'dash/util'
18
19
  require 'dash/configuration'
@@ -47,8 +47,9 @@ module Fiveruns::Dash
47
47
  Please set the :ar_total_time option when configuring Dash:
48
48
 
49
49
  # Define an application-specific metric cooresponding to the total processing time for this app.
50
+ # You must mark this time so Dash can ignore any AR activity outside of the call stack.
50
51
  Fiveruns::Dash.register_recipe :loader, :url => 'http://dash.fiveruns.com' do |recipe|
51
- recipe.time :total_time, 'Load Time', :method => 'Loader::Engine#load'
52
+ recipe.time :total_time, 'Load Time', :method => 'Loader::Engine#load', :mark => true
52
53
  end
53
54
 
54
55
  # Pass the name of this custom metric to Dash so it will be used in the AR metric calculations.
@@ -51,7 +51,7 @@ module Fiveruns::Dash
51
51
  def send_trace(trace)
52
52
  if trace.data
53
53
  payload = TracePayload.new(trace)
54
- Fiveruns::Dash.logger.debug "Sending trace: #{payload.to_json}"
54
+ Fiveruns::Dash.logger.debug "Sending trace: #{payload.to_fjson}"
55
55
  Thread.new { Update.new(payload).store(*update_locations) }
56
56
  else
57
57
  Fiveruns::Dash.logger.debug "No trace to send"
@@ -81,7 +81,9 @@ module Fiveruns::Dash
81
81
  %w(INT TERM).each do |sym|
82
82
  TRAPS[sym] = Signal.trap(sym) do
83
83
  stop
84
- TRAPS[sym].call if TRAPS[sym]
84
+ if TRAPS[sym] and TRAPS[sym].respond_to?(:call)
85
+ TRAPS[sym].call
86
+ end
85
87
  end
86
88
  end
87
89
  end
@@ -134,7 +136,7 @@ module Fiveruns::Dash
134
136
  def send_info_update
135
137
  @info_update_sent ||= begin
136
138
  payload = InfoPayload.new(@session.info, @started_at)
137
- Fiveruns::Dash.logger.debug "Sending info: #{payload.to_json}"
139
+ Fiveruns::Dash.logger.debug "Sending info: #{payload.to_fjson}"
138
140
  result = Update.new(payload).store(*update_locations)
139
141
  send_fake_info(payload)
140
142
  result
@@ -148,7 +150,7 @@ module Fiveruns::Dash
148
150
  Fiveruns::Dash.logger.debug "No exceptions for this interval"
149
151
  else
150
152
  payload = ExceptionsPayload.new(data)
151
- Fiveruns::Dash.logger.debug "Sending exceptions: #{payload.to_json}"
153
+ Fiveruns::Dash.logger.debug "Sending exceptions: #{payload.to_fjson}"
152
154
  Update.new(payload).store(*update_locations)
153
155
  end
154
156
  else
@@ -162,7 +164,7 @@ module Fiveruns::Dash
162
164
  if @info_update_sent
163
165
  data = @session.data
164
166
  payload = DataPayload.new(data)
165
- Fiveruns::Dash.logger.debug "Sending data: #{payload.to_json}"
167
+ Fiveruns::Dash.logger.debug "Sending data: #{payload.to_fjson}"
166
168
  result = Update.new(payload).store(*update_locations)
167
169
  send_fake_data(payload)
168
170
  result
@@ -184,7 +186,7 @@ module Fiveruns::Dash
184
186
  def send_fake_data(payload)
185
187
  fake_host_count.times do |idx|
186
188
  payload.params[:process_id] = Fiveruns::Dash.process_ids[idx+1]
187
- Fiveruns::Dash.logger.debug "Sending data: #{payload.to_json}"
189
+ Fiveruns::Dash.logger.debug "Sending data: #{payload.to_fjson}"
188
190
  Update.new(payload).store(*update_locations)
189
191
  end
190
192
  end
@@ -194,7 +196,7 @@ module Fiveruns::Dash
194
196
  fake_host_count.times do |idx|
195
197
  payload.params[:mac] += idx.to_s
196
198
  payload.params[:hostname] = host + idx.to_s
197
- Fiveruns::Dash.logger.debug "Sending info: #{payload.to_json}"
199
+ Fiveruns::Dash.logger.debug "Sending info: #{payload.to_fjson}"
198
200
  Update.new(payload).store(*update_locations)
199
201
  end
200
202
  end
@@ -10,7 +10,7 @@ module Fiveruns::Dash::Store
10
10
  end
11
11
 
12
12
  def write_to(path)
13
- ::File.open(path, 'w') { |f| f.write @payload.to_json }
13
+ ::File.open(path, 'w') { |f| f.write @payload.to_fjson }
14
14
  end
15
15
 
16
16
  def filename(directory)
@@ -68,8 +68,8 @@ module Fiveruns::Dash::Store
68
68
  end
69
69
  case response.code.to_i
70
70
  when 201
71
- data = JSON.load(response.body)
72
- set_trace_contexts(data)
71
+ # data = Fiveruns::JSON.load(response.body)
72
+ # set_trace_contexts(data)
73
73
  true
74
74
  when 400..499
75
75
  Fiveruns::Dash.logger.warn "Could not access Dash service (#{response.code.to_i}, #{response.body.inspect})"
@@ -78,9 +78,9 @@ module Fiveruns::Dash::Store
78
78
  Fiveruns::Dash.logger.debug "Received unknown response from Dash service (#{response.inspect})"
79
79
  false
80
80
  end
81
- rescue JSON::ParserError => e
81
+ rescue Fiveruns::JSON::ParserError => e
82
82
  puts response.body
83
- Fiveruns::Dash.logger.error "Received non-JSON response (#{response.inspect})"
83
+ Fiveruns::Dash.logger.error "Received non-FiverunsJSON response (#{response.inspect})"
84
84
  false
85
85
  end
86
86
 
@@ -27,10 +27,10 @@ module Fiveruns::Dash
27
27
  end
28
28
  end
29
29
 
30
- def to_json
30
+ def to_fjson
31
31
  { :context => context,
32
32
  :data => (@data || {})
33
- }.to_json
33
+ }.to_fjson
34
34
  end
35
35
 
36
36
  private
@@ -51,11 +51,11 @@ module Fiveruns::Dash
51
51
  @children ||= []
52
52
  end
53
53
 
54
- def to_json
54
+ def to_fjson
55
55
  {
56
56
  :metrics => metrics,
57
57
  :children => children,
58
- }.to_json
58
+ }.to_fjson
59
59
  end
60
60
 
61
61
  end
@@ -27,7 +27,7 @@ module Fiveruns::Dash
27
27
  response = http.post("/apps/#{token}/ping", multipart.to_s, "Content-Type" => multipart.content_type)
28
28
  case response.code.to_i
29
29
  when 201
30
- data = JSON.load(response.body)
30
+ data = ::Fiveruns::JSON.load(response.body)
31
31
  [:success, "Found application '#{data['name']}'"]
32
32
  else
33
33
  # Error message
@@ -133,8 +133,8 @@ module Fiveruns::Dash
133
133
  {}
134
134
  end
135
135
 
136
- def to_json
137
- @data.to_json
136
+ def to_fjson
137
+ @data.to_fjson
138
138
  end
139
139
 
140
140
  #######
@@ -146,7 +146,7 @@ module Fiveruns::Dash
146
146
  end
147
147
 
148
148
  def compressed
149
- Zlib::Deflate.deflate(to_json)
149
+ Zlib::Deflate.deflate(to_fjson)
150
150
  end
151
151
 
152
152
  end
@@ -0,0 +1,15 @@
1
+ # Private copy of JSON for FiveRuns Dash as the current state of JSON/Ruby is
2
+ # nightmarish for library authors. ActiveSupport and JSON have incompatability
3
+ # issues and supporting/fixing them is not worth it.
4
+ #
5
+ # == Authors
6
+ #
7
+ # Florian Frank <mailto:flori@ping.de>
8
+ # FiveRuns Development Team
9
+
10
+ require 'fiveruns/json/version'
11
+ require 'fiveruns/json/common'
12
+ require 'fiveruns/json/generator'
13
+ require 'fiveruns/json/pure'
14
+ require 'fiveruns/json/add/core'
15
+ require 'fiveruns/json/add/rails'
@@ -0,0 +1,131 @@
1
+ # This file contains implementations of ruby core's custom objects for
2
+ # serialisation/deserialisation.
3
+
4
+ require 'date'
5
+
6
+ class Time
7
+ def self.fjson_create(object)
8
+ if usec = object.delete('u') # used to be tv_usec -> tv_nsec
9
+ object['n'] = usec * 1000
10
+ end
11
+ if respond_to?(:tv_nsec)
12
+ at(*object.values_at('s', 'n'))
13
+ else
14
+ at(object['s'], object['n'] / 1000)
15
+ end
16
+ end
17
+
18
+ def to_fjson(*args)
19
+ {
20
+ 'json_class' => self.class.name,
21
+ 's' => tv_sec,
22
+ 'n' => respond_to?(:tv_nsec) ? tv_nsec : tv_usec * 1000
23
+ }.to_fjson(*args)
24
+ end
25
+ end
26
+
27
+ class Date
28
+ def self.fjson_create(object)
29
+ civil(*object.values_at('y', 'm', 'd', 'sg'))
30
+ end
31
+
32
+ alias start sg unless method_defined?(:start)
33
+
34
+ def to_fjson(*args)
35
+ {
36
+ 'json_class' => self.class.name,
37
+ 'y' => year,
38
+ 'm' => month,
39
+ 'd' => day,
40
+ 'sg' => start,
41
+ }.to_fjson(*args)
42
+ end
43
+ end
44
+
45
+ class DateTime
46
+ def self.fjson_create(object)
47
+ args = object.values_at('y', 'm', 'd', 'H', 'M', 'S')
48
+ of_a, of_b = object['of'].split('/')
49
+ if of_b and of_b != '0'
50
+ args << Rational(of_a.to_i, of_b.to_i)
51
+ else
52
+ args << of_a
53
+ end
54
+ args << object['sg']
55
+ civil(*args)
56
+ end
57
+
58
+ alias start sg unless method_defined?(:start)
59
+
60
+ def to_fjson(*args)
61
+ {
62
+ 'json_class' => self.class.name,
63
+ 'y' => year,
64
+ 'm' => month,
65
+ 'd' => day,
66
+ 'H' => hour,
67
+ 'M' => min,
68
+ 'S' => sec,
69
+ 'of' => offset.to_s,
70
+ 'sg' => start,
71
+ }.to_fjson(*args)
72
+ end
73
+ end
74
+
75
+ class Range
76
+ def self.fjson_create(object)
77
+ new(*object['a'])
78
+ end
79
+
80
+ def to_fjson(*args)
81
+ {
82
+ 'json_class' => self.class.name,
83
+ 'a' => [ first, last, exclude_end? ]
84
+ }.to_fjson(*args)
85
+ end
86
+ end
87
+
88
+ class Struct
89
+ def self.fjson_create(object)
90
+ new(*object['v'])
91
+ end
92
+
93
+ def to_fjson(*args)
94
+ klass = self.class.name
95
+ klass.empty? and raise Fiveruns::JSON::JSONError, "Only named structs are supported!"
96
+ {
97
+ 'json_class' => klass,
98
+ 'v' => values,
99
+ }.to_fjson(*args)
100
+ end
101
+ end
102
+
103
+ class Exception
104
+ def self.fjson_create(object)
105
+ result = new(object['m'])
106
+ result.set_backtrace object['b']
107
+ result
108
+ end
109
+
110
+ def to_fjson(*args)
111
+ {
112
+ 'json_class' => self.class.name,
113
+ 'm' => message,
114
+ 'b' => backtrace,
115
+ }.to_fjson(*args)
116
+ end
117
+ end
118
+
119
+ class Regexp
120
+ def self.fjson_create(object)
121
+ new(object['s'], object['o'])
122
+ end
123
+
124
+ def to_fjson(*)
125
+ {
126
+ 'json_class' => self.class.name,
127
+ 'o' => options,
128
+ 's' => source,
129
+ }.to_fjson
130
+ end
131
+ end
@@ -0,0 +1,55 @@
1
+ # This file contains implementations of rails custom objects for
2
+ # serialisation/deserialisation.
3
+
4
+ require 'fiveruns/json'
5
+
6
+ class Object
7
+ def self.fjson_create(object)
8
+ obj = new
9
+ for key, value in object
10
+ next if key == 'json_class'
11
+ instance_variable_set "@#{key}", value
12
+ end
13
+ obj
14
+ end
15
+
16
+ def to_fjson(*a)
17
+ result = {
18
+ 'json_class' => self.class.name
19
+ }
20
+ instance_variables.inject(result) do |r, name|
21
+ r[name[1..-1]] = instance_variable_get name
22
+ r
23
+ end
24
+ result.to_fjson(*a)
25
+ end
26
+ end
27
+
28
+ class Symbol
29
+ def to_fjson(*a)
30
+ to_s.to_fjson(*a)
31
+ end
32
+ end
33
+
34
+ module Enumerable
35
+ def to_fjson(*a)
36
+ to_a.to_fjson(*a)
37
+ end
38
+ end
39
+
40
+ # class Regexp
41
+ # def to_json(*)
42
+ # inspect
43
+ # end
44
+ # end
45
+ #
46
+ # The above rails definition has some problems:
47
+ #
48
+ # 1. { 'foo' => /bar/ }.to_json # => "{foo: /bar/}"
49
+ # This isn't valid FiverunsJSON, because the regular expression syntax is not
50
+ # defined in RFC 4627. (And unquoted strings are disallowed there, too.)
51
+ # Though it is valid Javascript.
52
+ #
53
+ # 2. { 'foo' => /bar/mix }.to_json # => "{foo: /bar/mix}"
54
+ # This isn't even valid Javascript.
55
+
@@ -0,0 +1,352 @@
1
+ module Fiveruns::JSON
2
+ class << self
3
+ # If _object_ is string-like parse the string and return the parsed result
4
+ # as a Ruby data structure. Otherwise generate a FiverunsJSON text from the Ruby
5
+ # data structure object and return it.
6
+ #
7
+ # The _opts_ argument is passed through to generate/parse respectively, see
8
+ # generate and parse for their documentation.
9
+ def [](object, opts = {})
10
+ if object.respond_to? :to_str
11
+ ::Fiveruns::JSON.parse(object.to_str, opts => {})
12
+ else
13
+ ::Fiveruns::JSON.generate(object, opts => {})
14
+ end
15
+ end
16
+
17
+ # Returns the FiverunsJSON parser class, that is used by FiverunsJSON. This might be either
18
+ # FiverunsJSON::Ext::Parser or FiverunsJSON::Pure::Parser.
19
+ attr_reader :parser
20
+
21
+ # Set the FiverunsJSON parser class _parser_ to be used by FiverunsJSON.
22
+ # def parser=(parser) # :nodoc:
23
+ # @parser = parser
24
+ # remove_const :Parser if const_defined? :Parser
25
+ # const_set :Parser, parser
26
+ # end
27
+
28
+ # Return the constant located at _path_. The format of _path_ has to be
29
+ # either ::A::B::C or A::B::C. In any case A has to be located at the top
30
+ # level (absolute namespace path?). If there doesn't exist a constant at
31
+ # the given path, an ArgumentError is raised.
32
+ def deep_const_get(path) # :nodoc:
33
+ path = path.to_s
34
+ path.split(/::/).inject(Object) do |p, c|
35
+ case
36
+ when c.empty? then p
37
+ when p.const_defined?(c) then p.const_get(c)
38
+ else raise ArgumentError, "can't find const #{path}"
39
+ end
40
+ end
41
+ end
42
+
43
+ # Set the module _generator_ to be used by FiverunsJSON.
44
+ def generator=(generator) # :nodoc:
45
+ @generator = generator
46
+ generator_methods = generator::GeneratorMethods
47
+ for const in generator_methods.constants
48
+ klass = deep_const_get(const)
49
+ modul = generator_methods.const_get(const)
50
+ klass.class_eval do
51
+ instance_methods(false).each do |m|
52
+ m.to_s == 'to_fjson' and remove_method m
53
+ end
54
+ include modul
55
+ end
56
+ end
57
+ self.state = generator::State
58
+ const_set :State, self.state
59
+ end
60
+
61
+ # Returns the FiverunsJSON generator modul, that is used by FiverunsJSON. This might be
62
+ # either FiverunsJSON::Ext::Generator or FiverunsJSON::Pure::Generator.
63
+ attr_reader :generator
64
+
65
+ # Returns the FiverunsJSON generator state class, that is used by FiverunsJSON. This might
66
+ # be either FiverunsJSON::Ext::Generator::State or FiverunsJSON::Pure::Generator::State.
67
+ attr_accessor :state
68
+
69
+ # This is create identifier, that is used to decide, if the _json_create_
70
+ # hook of a class should be called. It defaults to 'json_class'.
71
+ attr_accessor :create_id
72
+ end
73
+ self.create_id = 'json_class'
74
+
75
+ NaN = (-1.0) ** 0.5
76
+
77
+ Infinity = 1.0/0
78
+
79
+ MinusInfinity = -Infinity
80
+
81
+ # The base exception for FiverunsJSON errors.
82
+ class JSONError < StandardError; end
83
+
84
+ # This exception is raised, if a parser error occurs.
85
+ class ParserError < ::Fiveruns::JSON::JSONError; end
86
+
87
+ # This exception is raised, if the nesting of parsed datastructures is too
88
+ # deep.
89
+ class NestingError < ParserError; end
90
+
91
+ # This exception is raised, if a generator or unparser error occurs.
92
+ class GeneratorError < ::Fiveruns::JSON::JSONError; end
93
+ # For backwards compatibility
94
+ UnparserError = GeneratorError
95
+
96
+ # If a circular data structure is encountered while unparsing
97
+ # this exception is raised.
98
+ class CircularDatastructure < GeneratorError; end
99
+
100
+ # This exception is raised, if the required unicode support is missing on the
101
+ # system. Usually this means, that the iconv library is not installed.
102
+ class MissingUnicodeSupport < ::Fiveruns::JSON::JSONError; end
103
+
104
+ module_function
105
+
106
+ # Parse the FiverunsJSON string _source_ into a Ruby data structure and return it.
107
+ #
108
+ # _opts_ can have the following
109
+ # keys:
110
+ # * *max_nesting*: The maximum depth of nesting allowed in the parsed data
111
+ # structures. Disable depth checking with :max_nesting => false, it defaults
112
+ # to 19.
113
+ # * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
114
+ # defiance of RFC 4627 to be parsed by the Parser. This option defaults
115
+ # to false.
116
+ # * *create_additions*: If set to false, the Parser doesn't create
117
+ # additions even if a matchin class and create_id was found. This option
118
+ # defaults to true.
119
+ # def parse(source, opts = {})
120
+ # ::Fiveruns::JSON.parser.new(source, opts).parse
121
+ # end
122
+
123
+ # Parse the FiverunsJSON string _source_ into a Ruby data structure and return it.
124
+ # The bang version of the parse method, defaults to the more dangerous values
125
+ # for the _opts_ hash, so be sure only to parse trusted _source_ strings.
126
+ #
127
+ # _opts_ can have the following keys:
128
+ # * *max_nesting*: The maximum depth of nesting allowed in the parsed data
129
+ # structures. Enable depth checking with :max_nesting => anInteger. The parse!
130
+ # methods defaults to not doing max depth checking: This can be dangerous,
131
+ # if someone wants to fill up your stack.
132
+ # * *allow_nan*: If set to true, allow NaN, Infinity, and -Infinity in
133
+ # defiance of RFC 4627 to be parsed by the Parser. This option defaults
134
+ # to true.
135
+ # * *create_additions*: If set to false, the Parser doesn't create
136
+ # additions even if a matchin class and create_id was found. This option
137
+ # defaults to true.
138
+ # def parse!(source, opts = {})
139
+ # opts = {
140
+ # :max_nesting => false,
141
+ # :allow_nan => true
142
+ # }.update(opts)
143
+ # ::Fiveruns::JSON.parser.new(source, opts).parse
144
+ # end
145
+
146
+ # Unparse the Ruby data structure _obj_ into a single line FiverunsJSON string and
147
+ # return it. _state_ is
148
+ # * a FiverunsJSON::State object,
149
+ # * or a Hash like object (responding to to_hash),
150
+ # * an object convertible into a hash by a to_h method,
151
+ # that is used as or to configure a State object.
152
+ #
153
+ # It defaults to a state object, that creates the shortest possible FiverunsJSON text
154
+ # in one line, checks for circular data structures and doesn't allow NaN,
155
+ # Infinity, and -Infinity.
156
+ #
157
+ # A _state_ hash can have the following keys:
158
+ # * *indent*: a string used to indent levels (default: ''),
159
+ # * *space*: a string that is put after, a : or , delimiter (default: ''),
160
+ # * *space_before*: a string that is put before a : pair delimiter (default: ''),
161
+ # * *object_nl*: a string that is put at the end of a FiverunsJSON object (default: ''),
162
+ # * *array_nl*: a string that is put at the end of a FiverunsJSON array (default: ''),
163
+ # * *check_circular*: true if checking for circular data structures
164
+ # should be done (the default), false otherwise.
165
+ # * *allow_nan*: true if NaN, Infinity, and -Infinity should be
166
+ # generated, otherwise an exception is thrown, if these values are
167
+ # encountered. This options defaults to false.
168
+ # * *max_nesting*: The maximum depth of nesting allowed in the data
169
+ # structures from which FiverunsJSON is to be generated. Disable depth checking
170
+ # with :max_nesting => false, it defaults to 19.
171
+ #
172
+ # See also the fast_generate for the fastest creation method with the least
173
+ # amount of sanity checks, and the pretty_generate method for some
174
+ # defaults for a pretty output.
175
+ def generate(obj, state = nil)
176
+ if state
177
+ state = State.from_state(state)
178
+ else
179
+ state = State.new
180
+ end
181
+ obj.to_fjson(state)
182
+ end
183
+
184
+ # :stopdoc:
185
+ # I want to deprecate these later, so I'll first be silent about them, and
186
+ # later delete them.
187
+ alias unparse generate
188
+ module_function :unparse
189
+ # :startdoc:
190
+
191
+ # Unparse the Ruby data structure _obj_ into a single line FiverunsJSON string and
192
+ # return it. This method disables the checks for circles in Ruby objects, and
193
+ # also generates NaN, Infinity, and, -Infinity float values.
194
+ #
195
+ # *WARNING*: Be careful not to pass any Ruby data structures with circles as
196
+ # _obj_ argument, because this will cause FiverunsJSON to go into an infinite loop.
197
+ def fast_generate(obj)
198
+ obj.to_fjson(nil)
199
+ end
200
+
201
+ # :stopdoc:
202
+ # I want to deprecate these later, so I'll first be silent about them, and later delete them.
203
+ alias fast_unparse fast_generate
204
+ module_function :fast_unparse
205
+ # :startdoc:
206
+
207
+ # Unparse the Ruby data structure _obj_ into a FiverunsJSON string and return it. The
208
+ # returned string is a prettier form of the string returned by #unparse.
209
+ #
210
+ # The _opts_ argument can be used to configure the generator, see the
211
+ # generate method for a more detailed explanation.
212
+ def pretty_generate(obj, opts = nil)
213
+ state = ::Fiveruns::JSON.state.new(
214
+ :indent => ' ',
215
+ :space => ' ',
216
+ :object_nl => "\n",
217
+ :array_nl => "\n",
218
+ :check_circular => true
219
+ )
220
+ if opts
221
+ if opts.respond_to? :to_hash
222
+ opts = opts.to_hash
223
+ elsif opts.respond_to? :to_h
224
+ opts = opts.to_h
225
+ else
226
+ raise TypeError, "can't convert #{opts.class} into Hash"
227
+ end
228
+ state.configure(opts)
229
+ end
230
+ obj.to_fjson(state)
231
+ end
232
+
233
+ # :stopdoc:
234
+ # I want to deprecate these later, so I'll first be silent about them, and later delete them.
235
+ alias pretty_unparse pretty_generate
236
+ module_function :pretty_unparse
237
+ # :startdoc:
238
+
239
+ # Load a ruby data structure from a FiverunsJSON _source_ and return it. A source can
240
+ # either be a string-like object, an IO like object, or an object responding
241
+ # to the read method. If _proc_ was given, it will be called with any nested
242
+ # Ruby object as an argument recursively in depth first order.
243
+ #
244
+ # This method is part of the implementation of the load/dump interface of
245
+ # Marshal and YAML.
246
+ def load(source, proc = nil)
247
+ if source.respond_to? :to_str
248
+ source = source.to_str
249
+ elsif source.respond_to? :to_io
250
+ source = source.to_io.read
251
+ else
252
+ source = source.read
253
+ end
254
+ result = parse(source, :max_nesting => false, :allow_nan => true)
255
+ recurse_proc(result, &proc) if proc
256
+ result
257
+ end
258
+
259
+ def recurse_proc(result, &proc)
260
+ case result
261
+ when Array
262
+ result.each { |x| recurse_proc x, &proc }
263
+ proc.call result
264
+ when Hash
265
+ result.each { |x, y| recurse_proc x, &proc; recurse_proc y, &proc }
266
+ proc.call result
267
+ else
268
+ proc.call result
269
+ end
270
+ end
271
+ private :recurse_proc
272
+ module_function :recurse_proc
273
+
274
+ alias restore load
275
+ module_function :restore
276
+
277
+ # Dumps _obj_ as a FiverunsJSON string, i.e. calls generate on the object and returns
278
+ # the result.
279
+ #
280
+ # If anIO (an IO like object or an object that responds to the write method)
281
+ # was given, the resulting FiverunsJSON is written to it.
282
+ #
283
+ # If the number of nested arrays or objects exceeds _limit_ an ArgumentError
284
+ # exception is raised. This argument is similar (but not exactly the
285
+ # same!) to the _limit_ argument in Marshal.dump.
286
+ #
287
+ # This method is part of the implementation of the load/dump interface of
288
+ # Marshal and YAML.
289
+ def dump(obj, anIO = nil, limit = nil)
290
+ if anIO and limit.nil?
291
+ anIO = anIO.to_io if anIO.respond_to?(:to_io)
292
+ unless anIO.respond_to?(:write)
293
+ limit = anIO
294
+ anIO = nil
295
+ end
296
+ end
297
+ limit ||= 0
298
+ result = generate(obj, :allow_nan => true, :max_nesting => limit)
299
+ if anIO
300
+ anIO.write result
301
+ anIO
302
+ else
303
+ result
304
+ end
305
+ rescue ::Fiveruns::JSON::NestingError
306
+ raise ArgumentError, "exceed depth limit"
307
+ end
308
+ end
309
+
310
+ module ::Kernel
311
+ # Outputs _objs_ to STDOUT as FiverunsJSON strings in the shortest form, that is in
312
+ # one line.
313
+ def fj(*objs)
314
+ objs.each do |obj|
315
+ puts ::Fiveruns::JSON::generate(obj, :allow_nan => true, :max_nesting => false)
316
+ end
317
+ nil
318
+ end
319
+
320
+ # Ouputs _objs_ to STDOUT as FiverunsJSON strings in a pretty format, with
321
+ # indentation and over many lines.
322
+ def fjj(*objs)
323
+ objs.each do |obj|
324
+ puts ::Fiveruns::JSON::pretty_generate(obj, :allow_nan => true, :max_nesting => false)
325
+ end
326
+ nil
327
+ end
328
+
329
+ # If _object_ is string-like parse the string and return the parsed result as
330
+ # a Ruby data structure. Otherwise generate a FiverunsJSON text from the Ruby data
331
+ # structure object and return it.
332
+ #
333
+ # The _opts_ argument is passed through to generate/parse respectively, see
334
+ # generate and parse for their documentation.
335
+ def FJSON(object, opts = {})
336
+ # if object.respond_to? :to_str
337
+ # ::Fiveruns::JSON.parse(object.to_str, opts)
338
+ # else
339
+ ::Fiveruns::JSON.generate(object, opts)
340
+ # end
341
+ end
342
+ end
343
+
344
+ class ::Class
345
+ # Returns true, if this class can be used to create an instance
346
+ # from a serialised FiverunsJSON string. The class has to implement a class
347
+ # method _json_create_ that expects a hash as first parameter, which includes
348
+ # the required data.
349
+ def fjson_creatable?
350
+ respond_to?(:fjson_create)
351
+ end
352
+ end