Froze rails gems
[depot.git] / vendor / rails / activesupport / lib / active_support / json / decoding.rb
1 require 'yaml'
2 require 'strscan'
3
4 module ActiveSupport
5 module JSON
6 class ParseError < StandardError
7 end
8
9 class << self
10 # Converts a JSON string into a Ruby object.
11 def decode(json)
12 YAML.load(convert_json_to_yaml(json))
13 rescue ArgumentError => e
14 raise ParseError, "Invalid JSON string"
15 end
16
17 protected
18 # matches YAML-formatted dates
19 DATE_REGEX = /^\d{4}-\d{2}-\d{2}|\d{4}-\d{1,2}-\d{1,2}[ \t]+\d{1,2}:\d{2}:\d{2}(\.[0-9]*)?(([ \t]*)Z|[-+]\d{2}?(:\d{2})?)?$/
20
21 # Ensure that ":" and "," are always followed by a space
22 def convert_json_to_yaml(json) #:nodoc:
23 scanner, quoting, marks, pos, times = StringScanner.new(json), false, [], nil, []
24 while scanner.scan_until(/(\\['"]|['":,\\]|\\.)/)
25 case char = scanner[1]
26 when '"', "'"
27 if !quoting
28 quoting = char
29 pos = scanner.pos
30 elsif quoting == char
31 if json[pos..scanner.pos-2] =~ DATE_REGEX
32 # found a date, track the exact positions of the quotes so we can remove them later.
33 # oh, and increment them for each current mark, each one is an extra padded space that bumps
34 # the position in the final YAML output
35 total_marks = marks.size
36 times << pos+total_marks << scanner.pos+total_marks
37 end
38 quoting = false
39 end
40 when ":",","
41 marks << scanner.pos - 1 unless quoting
42 end
43 end
44
45 if marks.empty?
46 json.gsub(/\\\//, '/')
47 else
48 left_pos = [-1].push(*marks)
49 right_pos = marks << json.length
50 output = []
51 left_pos.each_with_index do |left, i|
52 output << json[left.succ..right_pos[i]]
53 end
54 output = output * " "
55
56 times.each { |i| output[i-1] = ' ' }
57 output.gsub!(/\\\//, '/')
58 output
59 end
60 end
61 end
62 end
63 end