fiveruns-dash-ruby 0.8.3 → 0.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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