json_pure 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. data/CHANGES +25 -0
  2. data/GPL +340 -0
  3. data/README +77 -0
  4. data/Rakefile +250 -0
  5. data/TODO +1 -0
  6. data/VERSION +1 -0
  7. data/benchmarks/benchmark.txt +133 -0
  8. data/benchmarks/benchmark_generator.rb +44 -0
  9. data/benchmarks/benchmark_parser.rb +22 -0
  10. data/benchmarks/benchmark_rails.rb +26 -0
  11. data/bin/edit_json.rb +11 -0
  12. data/data/example.json +1 -0
  13. data/data/index.html +37 -0
  14. data/data/prototype.js +2515 -0
  15. data/ext/json/ext/generator/Makefile +149 -0
  16. data/ext/json/ext/generator/extconf.rb +9 -0
  17. data/ext/json/ext/generator/generator.c +729 -0
  18. data/ext/json/ext/generator/unicode.c +184 -0
  19. data/ext/json/ext/generator/unicode.h +40 -0
  20. data/ext/json/ext/parser/Makefile +149 -0
  21. data/ext/json/ext/parser/extconf.rb +9 -0
  22. data/ext/json/ext/parser/parser.c +1551 -0
  23. data/ext/json/ext/parser/parser.rl +515 -0
  24. data/ext/json/ext/parser/unicode.c +156 -0
  25. data/ext/json/ext/parser/unicode.h +44 -0
  26. data/install.rb +26 -0
  27. data/lib/json.rb +205 -0
  28. data/lib/json/Array.xpm +21 -0
  29. data/lib/json/FalseClass.xpm +21 -0
  30. data/lib/json/Hash.xpm +21 -0
  31. data/lib/json/Key.xpm +73 -0
  32. data/lib/json/NilClass.xpm +21 -0
  33. data/lib/json/Numeric.xpm +28 -0
  34. data/lib/json/String.xpm +96 -0
  35. data/lib/json/TrueClass.xpm +21 -0
  36. data/lib/json/common.rb +184 -0
  37. data/lib/json/editor.rb +1207 -0
  38. data/lib/json/ext.rb +13 -0
  39. data/lib/json/json.xpm +1499 -0
  40. data/lib/json/pure.rb +75 -0
  41. data/lib/json/pure/generator.rb +321 -0
  42. data/lib/json/pure/parser.rb +210 -0
  43. data/lib/json/version.rb +8 -0
  44. data/tests/fixtures/fail1.json +1 -0
  45. data/tests/fixtures/fail10.json +1 -0
  46. data/tests/fixtures/fail11.json +1 -0
  47. data/tests/fixtures/fail12.json +1 -0
  48. data/tests/fixtures/fail13.json +1 -0
  49. data/tests/fixtures/fail14.json +1 -0
  50. data/tests/fixtures/fail15.json +1 -0
  51. data/tests/fixtures/fail16.json +1 -0
  52. data/tests/fixtures/fail17.json +1 -0
  53. data/tests/fixtures/fail19.json +1 -0
  54. data/tests/fixtures/fail2.json +1 -0
  55. data/tests/fixtures/fail20.json +1 -0
  56. data/tests/fixtures/fail21.json +1 -0
  57. data/tests/fixtures/fail22.json +1 -0
  58. data/tests/fixtures/fail23.json +1 -0
  59. data/tests/fixtures/fail24.json +1 -0
  60. data/tests/fixtures/fail25.json +1 -0
  61. data/tests/fixtures/fail26.json +1 -0
  62. data/tests/fixtures/fail27.json +2 -0
  63. data/tests/fixtures/fail28.json +2 -0
  64. data/tests/fixtures/fail3.json +1 -0
  65. data/tests/fixtures/fail4.json +1 -0
  66. data/tests/fixtures/fail5.json +1 -0
  67. data/tests/fixtures/fail6.json +1 -0
  68. data/tests/fixtures/fail7.json +1 -0
  69. data/tests/fixtures/fail8.json +1 -0
  70. data/tests/fixtures/fail9.json +1 -0
  71. data/tests/fixtures/pass1.json +56 -0
  72. data/tests/fixtures/pass18.json +1 -0
  73. data/tests/fixtures/pass2.json +1 -0
  74. data/tests/fixtures/pass3.json +6 -0
  75. data/tests/runner.rb +24 -0
  76. data/tests/test_json.rb +235 -0
  77. data/tests/test_json_addition.rb +94 -0
  78. data/tests/test_json_fixtures.rb +30 -0
  79. data/tests/test_json_generate.rb +81 -0
  80. data/tests/test_json_unicode.rb +55 -0
  81. data/tools/fuzz.rb +133 -0
  82. data/tools/server.rb +62 -0
  83. metadata +146 -0
@@ -0,0 +1,184 @@
1
+ /* vim: set cin et sw=4 ts=4: */
2
+
3
+ #include "unicode.h"
4
+
5
+ #define unicode_escape(buffer, character) \
6
+ sprintf(buf, "\\u%04x", (unsigned int) (character)); \
7
+ rb_str_buf_cat(buffer, buf, 6);
8
+
9
+ /*
10
+ * Copyright 2001-2004 Unicode, Inc.
11
+ *
12
+ * Disclaimer
13
+ *
14
+ * This source code is provided as is by Unicode, Inc. No claims are
15
+ * made as to fitness for any particular purpose. No warranties of any
16
+ * kind are expressed or implied. The recipient agrees to determine
17
+ * applicability of information provided. If this file has been
18
+ * purchased on magnetic or optical media from Unicode, Inc., the
19
+ * sole remedy for any claim will be exchange of defective media
20
+ * within 90 days of receipt.
21
+ *
22
+ * Limitations on Rights to Redistribute This Code
23
+ *
24
+ * Unicode, Inc. hereby grants the right to freely use the information
25
+ * supplied in this file in the creation of products supporting the
26
+ * Unicode Standard, and to make copies of this file in any form
27
+ * for internal or external distribution as long as this notice
28
+ * remains attached.
29
+ */
30
+
31
+ /*
32
+ * Index into the table below with the first byte of a UTF-8 sequence to
33
+ * get the number of trailing bytes that are supposed to follow it.
34
+ * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is
35
+ * left as-is for anyone who may want to do such conversion, which was
36
+ * allowed in earlier algorithms.
37
+ */
38
+ static const char trailingBytesForUTF8[256] = {
39
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
40
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
41
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
42
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
43
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
44
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
45
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
46
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
47
+ };
48
+
49
+ /*
50
+ * Magic values subtracted from a buffer value during UTF8 conversion.
51
+ * This table contains as many values as there might be trailing bytes
52
+ * in a UTF-8 sequence.
53
+ */
54
+ static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,
55
+ 0x03C82080UL, 0xFA082080UL, 0x82082080UL };
56
+
57
+ /*
58
+ * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
59
+ * into the first byte, depending on how many bytes follow. There are
60
+ * as many entries in this table as there are UTF-8 sequence types.
61
+ * (I.e., one byte sequence, two byte... etc.). Remember that sequencs
62
+ * for *legal* UTF-8 will be 4 or fewer bytes total.
63
+ */
64
+ static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
65
+
66
+ /*
67
+ * Utility routine to tell whether a sequence of bytes is legal UTF-8.
68
+ * This must be called with the length pre-determined by the first byte.
69
+ * If not calling this from ConvertUTF8to*, then the length can be set by:
70
+ * length = trailingBytesForUTF8[*source]+1;
71
+ * and the sequence is illegal right away if there aren't that many bytes
72
+ * available.
73
+ * If presented with a length > 4, this returns 0. The Unicode
74
+ * definition of UTF-8 goes up to 4-byte sequences.
75
+ */
76
+
77
+ inline static unsigned char isLegalUTF8(const UTF8 *source, int length)
78
+ {
79
+ UTF8 a;
80
+ const UTF8 *srcptr = source+length;
81
+ switch (length) {
82
+ default: return 0;
83
+ /* Everything else falls through when "1"... */
84
+ case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0;
85
+ case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0;
86
+ case 2: if ((a = (*--srcptr)) > 0xBF) return 0;
87
+
88
+ switch (*source) {
89
+ /* no fall-through in this inner switch */
90
+ case 0xE0: if (a < 0xA0) return 0; break;
91
+ case 0xED: if (a > 0x9F) return 0; break;
92
+ case 0xF0: if (a < 0x90) return 0; break;
93
+ case 0xF4: if (a > 0x8F) return 0; break;
94
+ default: if (a < 0x80) return 0;
95
+ }
96
+
97
+ case 1: if (*source >= 0x80 && *source < 0xC2) return 0;
98
+ }
99
+ if (*source > 0xF4) return 0;
100
+ return 1;
101
+ }
102
+
103
+ inline void JSON_convert_UTF8_to_JSON(VALUE buffer, VALUE string, ConversionFlags flags)
104
+ {
105
+ char buf[7];
106
+ const UTF8* source = (UTF8 *) RSTRING(string)->ptr;
107
+ const UTF8* sourceEnd = source + RSTRING(string)->len;
108
+
109
+ while (source < sourceEnd) {
110
+ UTF32 ch = 0;
111
+ unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
112
+ if (source + extraBytesToRead >= sourceEnd) {
113
+ rb_raise(rb_path2class("JSON::GeneratorError"),
114
+ "partial character in source, but hit end");
115
+ }
116
+ if (!isLegalUTF8(source, extraBytesToRead+1)) {
117
+ rb_raise(rb_path2class("JSON::GeneratorError"),
118
+ "source sequence is illegal/malformed");
119
+ }
120
+ /*
121
+ * The cases all fall through. See "Note A" below.
122
+ */
123
+ switch (extraBytesToRead) {
124
+ case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
125
+ case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
126
+ case 3: ch += *source++; ch <<= 6;
127
+ case 2: ch += *source++; ch <<= 6;
128
+ case 1: ch += *source++; ch <<= 6;
129
+ case 0: ch += *source++;
130
+ }
131
+ ch -= offsetsFromUTF8[extraBytesToRead];
132
+
133
+ if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
134
+ /* UTF-16 surrogate values are illegal in UTF-32 */
135
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
136
+ if (flags == strictConversion) {
137
+ source -= (extraBytesToRead+1); /* return to the illegal value itself */
138
+ rb_raise(rb_path2class("JSON::GeneratorError"),
139
+ "source sequence is illegal/malformed");
140
+ } else {
141
+ unicode_escape(buffer, UNI_REPLACEMENT_CHAR);
142
+ }
143
+ } else {
144
+ /* normal case */
145
+ if (ch == '"') {
146
+ rb_str_buf_cat2(buffer, "\\\"");
147
+ } else if (ch == '\\') {
148
+ rb_str_buf_cat2(buffer, "\\\\");
149
+ } else if (ch == '/') {
150
+ rb_str_buf_cat2(buffer, "\\/");
151
+ } else if (ch >= 0x20 && ch <= 0x7f) {
152
+ rb_str_buf_cat(buffer, (char *) source - 1, 1);
153
+ } else if (ch == '\n') {
154
+ rb_str_buf_cat2(buffer, "\\n");
155
+ } else if (ch == '\r') {
156
+ rb_str_buf_cat2(buffer, "\\r");
157
+ } else if (ch == '\t') {
158
+ rb_str_buf_cat2(buffer, "\\t");
159
+ } else if (ch == '\f') {
160
+ rb_str_buf_cat2(buffer, "\\f");
161
+ } else if (ch == '\b') {
162
+ rb_str_buf_cat2(buffer, "\\b");
163
+ } else if (ch < 0x20) {
164
+ unicode_escape(buffer, (UTF16) ch);
165
+ } else {
166
+ unicode_escape(buffer, (UTF16) ch);
167
+ }
168
+ }
169
+ } else if (ch > UNI_MAX_UTF16) {
170
+ if (flags == strictConversion) {
171
+ source -= (extraBytesToRead+1); /* return to the start */
172
+ rb_raise(rb_path2class("JSON::GeneratorError"),
173
+ "source sequence is illegal/malformed");
174
+ } else {
175
+ unicode_escape(buffer, UNI_REPLACEMENT_CHAR);
176
+ }
177
+ } else {
178
+ /* target is a character in range 0xFFFF - 0x10FFFF. */
179
+ ch -= halfBase;
180
+ unicode_escape(buffer, (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START));
181
+ unicode_escape(buffer, (UTF16)((ch & halfMask) + UNI_SUR_LOW_START));
182
+ }
183
+ }
184
+ }
@@ -0,0 +1,40 @@
1
+ #include "ruby.h"
2
+
3
+ #ifndef _GENERATOR_UNICODE_H_
4
+ #define _GENERATOR_UNICODE_H_
5
+
6
+ typedef enum {
7
+ conversionOK = 0, /* conversion successful */
8
+ sourceExhausted, /* partial character in source, but hit end */
9
+ targetExhausted, /* insuff. room in target for conversion */
10
+ sourceIllegal /* source sequence is illegal/malformed */
11
+ } ConversionResult;
12
+
13
+ typedef enum {
14
+ strictConversion = 0,
15
+ lenientConversion
16
+ } ConversionFlags;
17
+
18
+ typedef unsigned long UTF32; /* at least 32 bits */
19
+ typedef unsigned short UTF16; /* at least 16 bits */
20
+ typedef unsigned char UTF8; /* typically 8 bits */
21
+
22
+ #define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD
23
+ #define UNI_MAX_BMP (UTF32)0x0000FFFF
24
+ #define UNI_MAX_UTF16 (UTF32)0x0010FFFF
25
+ #define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF
26
+ #define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF
27
+
28
+ #define UNI_SUR_HIGH_START (UTF32)0xD800
29
+ #define UNI_SUR_HIGH_END (UTF32)0xDBFF
30
+ #define UNI_SUR_LOW_START (UTF32)0xDC00
31
+ #define UNI_SUR_LOW_END (UTF32)0xDFFF
32
+
33
+ static const int halfShift = 10; /* used for shifting by 10 bits */
34
+
35
+ static const UTF32 halfBase = 0x0010000UL;
36
+ static const UTF32 halfMask = 0x3FFUL;
37
+
38
+ void JSON_convert_UTF8_to_JSON(VALUE buffer, VALUE string, ConversionFlags flags);
39
+
40
+ #endif
@@ -0,0 +1,149 @@
1
+
2
+ SHELL = /bin/sh
3
+
4
+ #### Start of system configuration section. ####
5
+
6
+ srcdir = .
7
+ topdir = /usr/lib/ruby/1.8/i686-linux
8
+ hdrdir = $(topdir)
9
+ VPATH = $(srcdir):$(topdir):$(hdrdir)
10
+ prefix = $(DESTDIR)/usr
11
+ exec_prefix = $(prefix)
12
+ sitedir = $(DESTDIR)/usr/lib/ruby/site_ruby
13
+ rubylibdir = $(libdir)/ruby/$(ruby_version)
14
+ docdir = $(datarootdir)/doc/$(PACKAGE)
15
+ dvidir = $(docdir)
16
+ datarootdir = $(prefix)/share
17
+ archdir = $(rubylibdir)/$(arch)
18
+ sbindir = $(exec_prefix)/sbin
19
+ psdir = $(docdir)
20
+ localedir = $(datarootdir)/locale
21
+ htmldir = $(docdir)
22
+ datadir = $(DESTDIR)/usr/share
23
+ includedir = $(prefix)/include
24
+ infodir = $(DESTDIR)/usr/share/info
25
+ sysconfdir = $(DESTDIR)/etc
26
+ mandir = $(DESTDIR)/usr/share/man
27
+ libdir = $(exec_prefix)/lib
28
+ sharedstatedir = $(prefix)/com
29
+ oldincludedir = $(DESTDIR)/usr/include
30
+ pdfdir = $(docdir)
31
+ sitearchdir = $(sitelibdir)/$(sitearch)
32
+ bindir = $(exec_prefix)/bin
33
+ localstatedir = $(DESTDIR)/var/lib
34
+ sitelibdir = $(sitedir)/$(ruby_version)
35
+ libexecdir = $(exec_prefix)/libexec
36
+
37
+ CC = i686-pc-linux-gnu-gcc -Wall
38
+ LIBRUBY = $(LIBRUBY_SO)
39
+ LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
40
+ LIBRUBYARG_SHARED = -Wl,-R -Wl,$(libdir) -L$(libdir) -L. -l$(RUBY_SO_NAME)
41
+ LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static
42
+
43
+ RUBY_EXTCONF_H =
44
+ CFLAGS = -fPIC -march=pentium4 -O2 -pipe -ggdb -fPIC
45
+ INCFLAGS = -I. -I$(topdir) -I$(hdrdir) -I$(srcdir)
46
+ CPPFLAGS =
47
+ CXXFLAGS = $(CFLAGS)
48
+ DLDFLAGS =
49
+ LDSHARED = $(CC) -shared
50
+ AR = i686-pc-linux-gnu-ar
51
+ EXEEXT =
52
+
53
+ RUBY_INSTALL_NAME = ruby18
54
+ RUBY_SO_NAME = ruby18
55
+ arch = i686-linux
56
+ sitearch = i686-linux
57
+ ruby_version = 1.8
58
+ ruby = /usr/bin/ruby18
59
+ RUBY = $(ruby)
60
+ RM = rm -f
61
+ MAKEDIRS = mkdir -p
62
+ INSTALL = /bin/install -c
63
+ INSTALL_PROG = $(INSTALL) -m 0755
64
+ INSTALL_DATA = $(INSTALL) -m 644
65
+ COPY = cp
66
+
67
+ #### End of system configuration section. ####
68
+
69
+ preload =
70
+
71
+ libpath = $(libdir)
72
+ LIBPATH = -L'$(libdir)' -Wl,-R'$(libdir)'
73
+ DEFFILE =
74
+
75
+ CLEANFILES =
76
+ DISTCLEANFILES =
77
+
78
+ extout =
79
+ extout_prefix =
80
+ target_prefix =
81
+ LOCAL_LIBS =
82
+ LIBS = $(LIBRUBYARG_SHARED) -ldl -lcrypt -lm -lc
83
+ SRCS = parser.c unicode.c
84
+ OBJS = parser.o unicode.o
85
+ TARGET = parser
86
+ DLLIB = $(TARGET).so
87
+ EXTSTATIC =
88
+ STATIC_LIB =
89
+
90
+ RUBYCOMMONDIR = $(sitedir)$(target_prefix)
91
+ RUBYLIBDIR = $(sitelibdir)$(target_prefix)
92
+ RUBYARCHDIR = $(sitearchdir)$(target_prefix)
93
+
94
+ TARGET_SO = $(DLLIB)
95
+ CLEANLIBS = $(TARGET).so $(TARGET).il? $(TARGET).tds $(TARGET).map
96
+ CLEANOBJS = *.o *.a *.s[ol] *.pdb *.exp *.bak
97
+
98
+ all: $(DLLIB)
99
+ static: $(STATIC_LIB)
100
+
101
+ clean:
102
+ @-$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES)
103
+
104
+ distclean: clean
105
+ @-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
106
+ @-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
107
+
108
+ realclean: distclean
109
+ install: install-so install-rb
110
+
111
+ install-so: $(RUBYARCHDIR)
112
+ install-so: $(RUBYARCHDIR)/$(DLLIB)
113
+ $(RUBYARCHDIR)/$(DLLIB): $(DLLIB)
114
+ $(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)
115
+ install-rb: pre-install-rb install-rb-default
116
+ install-rb-default: pre-install-rb-default
117
+ pre-install-rb: Makefile
118
+ pre-install-rb-default: Makefile
119
+ $(RUBYARCHDIR):
120
+ $(MAKEDIRS) $@
121
+
122
+ site-install: site-install-so site-install-rb
123
+ site-install-so: install-so
124
+ site-install-rb: install-rb
125
+
126
+ .SUFFIXES: .c .m .cc .cxx .cpp .C .o
127
+
128
+ .cc.o:
129
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
130
+
131
+ .cxx.o:
132
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
133
+
134
+ .cpp.o:
135
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
136
+
137
+ .C.o:
138
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
139
+
140
+ .c.o:
141
+ $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) -c $<
142
+
143
+ $(DLLIB): $(OBJS)
144
+ @-$(RM) $@
145
+ $(LDSHARED) $(DLDFLAGS) $(LIBPATH) -o $@ $(OBJS) $(LOCAL_LIBS) $(LIBS)
146
+
147
+
148
+
149
+ $(OBJS): ruby.h defines.h
@@ -0,0 +1,9 @@
1
+ require 'mkmf'
2
+ require 'rbconfig'
3
+
4
+ if CONFIG['CC'] =~ /gcc/
5
+ #CONFIG['CC'] += ' -Wall -ggdb'
6
+ CONFIG['CC'] += ' -Wall'
7
+ end
8
+
9
+ create_makefile 'parser'
@@ -0,0 +1,1551 @@
1
+ #line 1 "parser.rl"
2
+ /* vim: set cin et sw=4 ts=4: */
3
+
4
+ #include "ruby.h"
5
+ #include "re.h"
6
+ #include "unicode.h"
7
+
8
+ #ifndef swap16
9
+ #define swap16(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF))
10
+ #endif
11
+
12
+ #define EVIL 0x666
13
+
14
+ static VALUE mJSON, mExt, cParser, eParserError;
15
+
16
+ static ID i_json_creatable_p, i_json_create, i_create_id, i_chr;
17
+
18
+ typedef struct JSON_ParserStruct {
19
+ VALUE Vsource;
20
+ char *source;
21
+ long len;
22
+ char *memo;
23
+ VALUE create_id;
24
+ } JSON_Parser;
25
+
26
+ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result);
27
+ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result);
28
+ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result);
29
+ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result);
30
+ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result);
31
+ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result);
32
+
33
+ #define GET_STRUCT \
34
+ JSON_Parser *json; \
35
+ Data_Get_Struct(self, JSON_Parser, json);
36
+
37
+ #line 59 "parser.rl"
38
+
39
+
40
+
41
+ #line 42 "parser.c"
42
+ static const int JSON_object_start = 0;
43
+
44
+ static const int JSON_object_first_final = 27;
45
+
46
+ static const int JSON_object_error = 1;
47
+
48
+ #line 92 "parser.rl"
49
+
50
+
51
+ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result)
52
+ {
53
+ int cs = EVIL;
54
+ VALUE last_name = Qnil;
55
+ *result = rb_hash_new();
56
+
57
+
58
+ #line 59 "parser.c"
59
+ {
60
+ cs = JSON_object_start;
61
+ }
62
+ #line 101 "parser.rl"
63
+
64
+ #line 65 "parser.c"
65
+ {
66
+ if ( p == pe )
67
+ goto _out;
68
+ switch ( cs )
69
+ {
70
+ case 0:
71
+ if ( (*p) == 123 )
72
+ goto st2;
73
+ goto st1;
74
+ st1:
75
+ goto _out1;
76
+ st2:
77
+ if ( ++p == pe )
78
+ goto _out2;
79
+ case 2:
80
+ switch( (*p) ) {
81
+ case 13: goto st2;
82
+ case 32: goto st2;
83
+ case 34: goto tr13;
84
+ case 47: goto st23;
85
+ case 125: goto tr10;
86
+ }
87
+ if ( 9 <= (*p) && (*p) <= 10 )
88
+ goto st2;
89
+ goto st1;
90
+ tr13:
91
+ #line 78 "parser.rl"
92
+ {
93
+ char *np = JSON_parse_string(json, p, pe, &last_name);
94
+ if (np == NULL) goto _out3; else {p = (( np))-1;}
95
+ }
96
+ goto st3;
97
+ st3:
98
+ if ( ++p == pe )
99
+ goto _out3;
100
+ case 3:
101
+ #line 102 "parser.c"
102
+ switch( (*p) ) {
103
+ case 13: goto st3;
104
+ case 32: goto st3;
105
+ case 47: goto st4;
106
+ case 58: goto st8;
107
+ }
108
+ if ( 9 <= (*p) && (*p) <= 10 )
109
+ goto st3;
110
+ goto st1;
111
+ st4:
112
+ if ( ++p == pe )
113
+ goto _out4;
114
+ case 4:
115
+ switch( (*p) ) {
116
+ case 42: goto st5;
117
+ case 47: goto st7;
118
+ }
119
+ goto st1;
120
+ st5:
121
+ if ( ++p == pe )
122
+ goto _out5;
123
+ case 5:
124
+ if ( (*p) == 42 )
125
+ goto st6;
126
+ goto st5;
127
+ st6:
128
+ if ( ++p == pe )
129
+ goto _out6;
130
+ case 6:
131
+ switch( (*p) ) {
132
+ case 42: goto st6;
133
+ case 47: goto st3;
134
+ }
135
+ goto st5;
136
+ st7:
137
+ if ( ++p == pe )
138
+ goto _out7;
139
+ case 7:
140
+ if ( (*p) == 10 )
141
+ goto st3;
142
+ goto st7;
143
+ st8:
144
+ if ( ++p == pe )
145
+ goto _out8;
146
+ case 8:
147
+ switch( (*p) ) {
148
+ case 13: goto st8;
149
+ case 32: goto st8;
150
+ case 34: goto tr11;
151
+ case 45: goto tr11;
152
+ case 47: goto st19;
153
+ case 91: goto tr11;
154
+ case 102: goto tr11;
155
+ case 110: goto tr11;
156
+ case 116: goto tr11;
157
+ case 123: goto tr11;
158
+ }
159
+ if ( (*p) > 10 ) {
160
+ if ( 48 <= (*p) && (*p) <= 57 )
161
+ goto tr11;
162
+ } else if ( (*p) >= 9 )
163
+ goto st8;
164
+ goto st1;
165
+ tr11:
166
+ #line 67 "parser.rl"
167
+ {
168
+ VALUE v = Qnil;
169
+ char *np = JSON_parse_value(json, p, pe, &v);
170
+ if (np == NULL) {
171
+ goto _out9;
172
+ } else {
173
+ rb_hash_aset(*result, last_name, v);
174
+ {p = (( np))-1;}
175
+ }
176
+ }
177
+ goto st9;
178
+ st9:
179
+ if ( ++p == pe )
180
+ goto _out9;
181
+ case 9:
182
+ #line 183 "parser.c"
183
+ switch( (*p) ) {
184
+ case 13: goto st9;
185
+ case 32: goto st9;
186
+ case 44: goto st10;
187
+ case 47: goto st15;
188
+ case 125: goto tr10;
189
+ }
190
+ if ( 9 <= (*p) && (*p) <= 10 )
191
+ goto st9;
192
+ goto st1;
193
+ st10:
194
+ if ( ++p == pe )
195
+ goto _out10;
196
+ case 10:
197
+ switch( (*p) ) {
198
+ case 13: goto st10;
199
+ case 32: goto st10;
200
+ case 34: goto tr13;
201
+ case 47: goto st11;
202
+ }
203
+ if ( 9 <= (*p) && (*p) <= 10 )
204
+ goto st10;
205
+ goto st1;
206
+ st11:
207
+ if ( ++p == pe )
208
+ goto _out11;
209
+ case 11:
210
+ switch( (*p) ) {
211
+ case 42: goto st12;
212
+ case 47: goto st14;
213
+ }
214
+ goto st1;
215
+ st12:
216
+ if ( ++p == pe )
217
+ goto _out12;
218
+ case 12:
219
+ if ( (*p) == 42 )
220
+ goto st13;
221
+ goto st12;
222
+ st13:
223
+ if ( ++p == pe )
224
+ goto _out13;
225
+ case 13:
226
+ switch( (*p) ) {
227
+ case 42: goto st13;
228
+ case 47: goto st10;
229
+ }
230
+ goto st12;
231
+ st14:
232
+ if ( ++p == pe )
233
+ goto _out14;
234
+ case 14:
235
+ if ( (*p) == 10 )
236
+ goto st10;
237
+ goto st14;
238
+ st15:
239
+ if ( ++p == pe )
240
+ goto _out15;
241
+ case 15:
242
+ switch( (*p) ) {
243
+ case 42: goto st16;
244
+ case 47: goto st18;
245
+ }
246
+ goto st1;
247
+ st16:
248
+ if ( ++p == pe )
249
+ goto _out16;
250
+ case 16:
251
+ if ( (*p) == 42 )
252
+ goto st17;
253
+ goto st16;
254
+ st17:
255
+ if ( ++p == pe )
256
+ goto _out17;
257
+ case 17:
258
+ switch( (*p) ) {
259
+ case 42: goto st17;
260
+ case 47: goto st9;
261
+ }
262
+ goto st16;
263
+ st18:
264
+ if ( ++p == pe )
265
+ goto _out18;
266
+ case 18:
267
+ if ( (*p) == 10 )
268
+ goto st9;
269
+ goto st18;
270
+ tr10:
271
+ #line 83 "parser.rl"
272
+ { goto _out27; }
273
+ goto st27;
274
+ st27:
275
+ if ( ++p == pe )
276
+ goto _out27;
277
+ case 27:
278
+ #line 279 "parser.c"
279
+ goto st1;
280
+ st19:
281
+ if ( ++p == pe )
282
+ goto _out19;
283
+ case 19:
284
+ switch( (*p) ) {
285
+ case 42: goto st20;
286
+ case 47: goto st22;
287
+ }
288
+ goto st1;
289
+ st20:
290
+ if ( ++p == pe )
291
+ goto _out20;
292
+ case 20:
293
+ if ( (*p) == 42 )
294
+ goto st21;
295
+ goto st20;
296
+ st21:
297
+ if ( ++p == pe )
298
+ goto _out21;
299
+ case 21:
300
+ switch( (*p) ) {
301
+ case 42: goto st21;
302
+ case 47: goto st8;
303
+ }
304
+ goto st20;
305
+ st22:
306
+ if ( ++p == pe )
307
+ goto _out22;
308
+ case 22:
309
+ if ( (*p) == 10 )
310
+ goto st8;
311
+ goto st22;
312
+ st23:
313
+ if ( ++p == pe )
314
+ goto _out23;
315
+ case 23:
316
+ switch( (*p) ) {
317
+ case 42: goto st24;
318
+ case 47: goto st26;
319
+ }
320
+ goto st1;
321
+ st24:
322
+ if ( ++p == pe )
323
+ goto _out24;
324
+ case 24:
325
+ if ( (*p) == 42 )
326
+ goto st25;
327
+ goto st24;
328
+ st25:
329
+ if ( ++p == pe )
330
+ goto _out25;
331
+ case 25:
332
+ switch( (*p) ) {
333
+ case 42: goto st25;
334
+ case 47: goto st2;
335
+ }
336
+ goto st24;
337
+ st26:
338
+ if ( ++p == pe )
339
+ goto _out26;
340
+ case 26:
341
+ if ( (*p) == 10 )
342
+ goto st2;
343
+ goto st26;
344
+ }
345
+ _out1: cs = 1; goto _out;
346
+ _out2: cs = 2; goto _out;
347
+ _out3: cs = 3; goto _out;
348
+ _out4: cs = 4; goto _out;
349
+ _out5: cs = 5; goto _out;
350
+ _out6: cs = 6; goto _out;
351
+ _out7: cs = 7; goto _out;
352
+ _out8: cs = 8; goto _out;
353
+ _out9: cs = 9; goto _out;
354
+ _out10: cs = 10; goto _out;
355
+ _out11: cs = 11; goto _out;
356
+ _out12: cs = 12; goto _out;
357
+ _out13: cs = 13; goto _out;
358
+ _out14: cs = 14; goto _out;
359
+ _out15: cs = 15; goto _out;
360
+ _out16: cs = 16; goto _out;
361
+ _out17: cs = 17; goto _out;
362
+ _out18: cs = 18; goto _out;
363
+ _out27: cs = 27; goto _out;
364
+ _out19: cs = 19; goto _out;
365
+ _out20: cs = 20; goto _out;
366
+ _out21: cs = 21; goto _out;
367
+ _out22: cs = 22; goto _out;
368
+ _out23: cs = 23; goto _out;
369
+ _out24: cs = 24; goto _out;
370
+ _out25: cs = 25; goto _out;
371
+ _out26: cs = 26; goto _out;
372
+
373
+ _out: {}
374
+ }
375
+ #line 102 "parser.rl"
376
+
377
+ if (cs >= JSON_object_first_final) {
378
+ VALUE klassname = rb_hash_aref(*result, json->create_id);
379
+ if (!NIL_P(klassname)) {
380
+ VALUE klass = rb_path2class(StringValueCStr(klassname));
381
+ if RTEST(rb_funcall(klass, i_json_creatable_p, 0)) {
382
+ *result = rb_funcall(klass, i_json_create, 1, *result);
383
+ }
384
+ }
385
+ return p + 1;
386
+ } else {
387
+ return NULL;
388
+ }
389
+ }
390
+
391
+
392
+ #line 393 "parser.c"
393
+ static const int JSON_value_start = 0;
394
+
395
+ static const int JSON_value_first_final = 12;
396
+
397
+ static const int JSON_value_error = 1;
398
+
399
+ #line 167 "parser.rl"
400
+
401
+
402
+ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result)
403
+ {
404
+ int cs = EVIL;
405
+
406
+
407
+ #line 408 "parser.c"
408
+ {
409
+ cs = JSON_value_start;
410
+ }
411
+ #line 174 "parser.rl"
412
+
413
+ #line 414 "parser.c"
414
+ {
415
+ if ( p == pe )
416
+ goto _out;
417
+ switch ( cs )
418
+ {
419
+ case 0:
420
+ switch( (*p) ) {
421
+ case 34: goto tr9;
422
+ case 45: goto tr10;
423
+ case 91: goto tr11;
424
+ case 102: goto st2;
425
+ case 110: goto st6;
426
+ case 116: goto st9;
427
+ case 123: goto tr15;
428
+ }
429
+ if ( 48 <= (*p) && (*p) <= 57 )
430
+ goto tr10;
431
+ goto st1;
432
+ st1:
433
+ goto _out1;
434
+ tr5:
435
+ #line 123 "parser.rl"
436
+ {
437
+ *result = Qnil;
438
+ }
439
+ goto st12;
440
+ tr6:
441
+ #line 126 "parser.rl"
442
+ {
443
+ *result = Qfalse;
444
+ }
445
+ goto st12;
446
+ tr7:
447
+ #line 129 "parser.rl"
448
+ {
449
+ *result = Qtrue;
450
+ }
451
+ goto st12;
452
+ tr9:
453
+ #line 132 "parser.rl"
454
+ {
455
+ char *np = JSON_parse_string(json, p, pe, result);
456
+ if (np == NULL) goto _out12; else {p = (( np))-1;}
457
+ }
458
+ goto st12;
459
+ tr10:
460
+ #line 137 "parser.rl"
461
+ {
462
+ char *np;
463
+ np = JSON_parse_float(json, p, pe, result);
464
+ if (np != NULL) {p = (( np))-1;}
465
+ np = JSON_parse_integer(json, p, pe, result);
466
+ if (np != NULL) {p = (( np))-1;}
467
+ goto _out12;
468
+ }
469
+ goto st12;
470
+ tr11:
471
+ #line 146 "parser.rl"
472
+ {
473
+ char *np = JSON_parse_array(json, p, pe, result);
474
+ if (np == NULL) goto _out12; else {p = (( np))-1;}
475
+ }
476
+ goto st12;
477
+ tr15:
478
+ #line 151 "parser.rl"
479
+ {
480
+ char *np = JSON_parse_object(json, p, pe, result);
481
+ if (np == NULL) goto _out12; else {p = (( np))-1;}
482
+ }
483
+ goto st12;
484
+ st12:
485
+ if ( ++p == pe )
486
+ goto _out12;
487
+ case 12:
488
+ #line 156 "parser.rl"
489
+ { goto _out12; }
490
+ #line 491 "parser.c"
491
+ goto st1;
492
+ st2:
493
+ if ( ++p == pe )
494
+ goto _out2;
495
+ case 2:
496
+ if ( (*p) == 97 )
497
+ goto st3;
498
+ goto st1;
499
+ st3:
500
+ if ( ++p == pe )
501
+ goto _out3;
502
+ case 3:
503
+ if ( (*p) == 108 )
504
+ goto st4;
505
+ goto st1;
506
+ st4:
507
+ if ( ++p == pe )
508
+ goto _out4;
509
+ case 4:
510
+ if ( (*p) == 115 )
511
+ goto st5;
512
+ goto st1;
513
+ st5:
514
+ if ( ++p == pe )
515
+ goto _out5;
516
+ case 5:
517
+ if ( (*p) == 101 )
518
+ goto tr6;
519
+ goto st1;
520
+ st6:
521
+ if ( ++p == pe )
522
+ goto _out6;
523
+ case 6:
524
+ if ( (*p) == 117 )
525
+ goto st7;
526
+ goto st1;
527
+ st7:
528
+ if ( ++p == pe )
529
+ goto _out7;
530
+ case 7:
531
+ if ( (*p) == 108 )
532
+ goto st8;
533
+ goto st1;
534
+ st8:
535
+ if ( ++p == pe )
536
+ goto _out8;
537
+ case 8:
538
+ if ( (*p) == 108 )
539
+ goto tr5;
540
+ goto st1;
541
+ st9:
542
+ if ( ++p == pe )
543
+ goto _out9;
544
+ case 9:
545
+ if ( (*p) == 114 )
546
+ goto st10;
547
+ goto st1;
548
+ st10:
549
+ if ( ++p == pe )
550
+ goto _out10;
551
+ case 10:
552
+ if ( (*p) == 117 )
553
+ goto st11;
554
+ goto st1;
555
+ st11:
556
+ if ( ++p == pe )
557
+ goto _out11;
558
+ case 11:
559
+ if ( (*p) == 101 )
560
+ goto tr7;
561
+ goto st1;
562
+ }
563
+ _out1: cs = 1; goto _out;
564
+ _out12: cs = 12; goto _out;
565
+ _out2: cs = 2; goto _out;
566
+ _out3: cs = 3; goto _out;
567
+ _out4: cs = 4; goto _out;
568
+ _out5: cs = 5; goto _out;
569
+ _out6: cs = 6; goto _out;
570
+ _out7: cs = 7; goto _out;
571
+ _out8: cs = 8; goto _out;
572
+ _out9: cs = 9; goto _out;
573
+ _out10: cs = 10; goto _out;
574
+ _out11: cs = 11; goto _out;
575
+
576
+ _out: {}
577
+ }
578
+ #line 175 "parser.rl"
579
+
580
+ if (cs >= JSON_value_first_final) {
581
+ return p;
582
+ } else {
583
+ return NULL;
584
+ }
585
+ }
586
+
587
+
588
+ #line 589 "parser.c"
589
+ static const int JSON_integer_start = 0;
590
+
591
+ static const int JSON_integer_first_final = 5;
592
+
593
+ static const int JSON_integer_error = 1;
594
+
595
+ #line 191 "parser.rl"
596
+
597
+
598
+ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result)
599
+ {
600
+ int cs = EVIL;
601
+
602
+
603
+ #line 604 "parser.c"
604
+ {
605
+ cs = JSON_integer_start;
606
+ }
607
+ #line 198 "parser.rl"
608
+ json->memo = p;
609
+
610
+ #line 611 "parser.c"
611
+ {
612
+ if ( p == pe )
613
+ goto _out;
614
+ switch ( cs )
615
+ {
616
+ case 0:
617
+ switch( (*p) ) {
618
+ case 45: goto st2;
619
+ case 48: goto st3;
620
+ }
621
+ if ( 49 <= (*p) && (*p) <= 57 )
622
+ goto st4;
623
+ goto st1;
624
+ st1:
625
+ goto _out1;
626
+ st2:
627
+ if ( ++p == pe )
628
+ goto _out2;
629
+ case 2:
630
+ if ( (*p) == 48 )
631
+ goto st3;
632
+ if ( 49 <= (*p) && (*p) <= 57 )
633
+ goto st4;
634
+ goto st1;
635
+ st3:
636
+ if ( ++p == pe )
637
+ goto _out3;
638
+ case 3:
639
+ if ( 48 <= (*p) && (*p) <= 57 )
640
+ goto st1;
641
+ goto tr4;
642
+ tr4:
643
+ #line 188 "parser.rl"
644
+ { goto _out5; }
645
+ goto st5;
646
+ st5:
647
+ if ( ++p == pe )
648
+ goto _out5;
649
+ case 5:
650
+ #line 651 "parser.c"
651
+ goto st1;
652
+ st4:
653
+ if ( ++p == pe )
654
+ goto _out4;
655
+ case 4:
656
+ if ( 48 <= (*p) && (*p) <= 57 )
657
+ goto st4;
658
+ goto tr4;
659
+ }
660
+ _out1: cs = 1; goto _out;
661
+ _out2: cs = 2; goto _out;
662
+ _out3: cs = 3; goto _out;
663
+ _out5: cs = 5; goto _out;
664
+ _out4: cs = 4; goto _out;
665
+
666
+ _out: {}
667
+ }
668
+ #line 200 "parser.rl"
669
+
670
+ if (cs >= JSON_integer_first_final) {
671
+ long len = p - json->memo;
672
+ *result = rb_Integer(rb_str_new(json->memo, len));
673
+ return p + 1;
674
+ } else {
675
+ return NULL;
676
+ }
677
+ }
678
+
679
+
680
+ #line 681 "parser.c"
681
+ static const int JSON_float_start = 0;
682
+
683
+ static const int JSON_float_first_final = 10;
684
+
685
+ static const int JSON_float_error = 1;
686
+
687
+ #line 222 "parser.rl"
688
+
689
+
690
+ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result)
691
+ {
692
+ int cs = EVIL;
693
+
694
+
695
+ #line 696 "parser.c"
696
+ {
697
+ cs = JSON_float_start;
698
+ }
699
+ #line 229 "parser.rl"
700
+ json->memo = p;
701
+
702
+ #line 703 "parser.c"
703
+ {
704
+ if ( p == pe )
705
+ goto _out;
706
+ switch ( cs )
707
+ {
708
+ case 0:
709
+ switch( (*p) ) {
710
+ case 45: goto st2;
711
+ case 48: goto st3;
712
+ }
713
+ if ( 49 <= (*p) && (*p) <= 57 )
714
+ goto st9;
715
+ goto st1;
716
+ st1:
717
+ goto _out1;
718
+ st2:
719
+ if ( ++p == pe )
720
+ goto _out2;
721
+ case 2:
722
+ if ( (*p) == 48 )
723
+ goto st3;
724
+ if ( 49 <= (*p) && (*p) <= 57 )
725
+ goto st9;
726
+ goto st1;
727
+ st3:
728
+ if ( ++p == pe )
729
+ goto _out3;
730
+ case 3:
731
+ if ( (*p) == 46 )
732
+ goto st4;
733
+ goto st1;
734
+ st4:
735
+ if ( ++p == pe )
736
+ goto _out4;
737
+ case 4:
738
+ if ( 48 <= (*p) && (*p) <= 57 )
739
+ goto st5;
740
+ goto st1;
741
+ st5:
742
+ if ( ++p == pe )
743
+ goto _out5;
744
+ case 5:
745
+ switch( (*p) ) {
746
+ case 69: goto st6;
747
+ case 101: goto st6;
748
+ }
749
+ if ( (*p) > 46 ) {
750
+ if ( 48 <= (*p) && (*p) <= 57 )
751
+ goto st5;
752
+ } else if ( (*p) >= 45 )
753
+ goto st1;
754
+ goto tr8;
755
+ tr8:
756
+ #line 216 "parser.rl"
757
+ { goto _out10; }
758
+ goto st10;
759
+ st10:
760
+ if ( ++p == pe )
761
+ goto _out10;
762
+ case 10:
763
+ #line 764 "parser.c"
764
+ goto st1;
765
+ st6:
766
+ if ( ++p == pe )
767
+ goto _out6;
768
+ case 6:
769
+ switch( (*p) ) {
770
+ case 43: goto st7;
771
+ case 45: goto st7;
772
+ }
773
+ if ( 48 <= (*p) && (*p) <= 57 )
774
+ goto st8;
775
+ goto st1;
776
+ st7:
777
+ if ( ++p == pe )
778
+ goto _out7;
779
+ case 7:
780
+ if ( 48 <= (*p) && (*p) <= 57 )
781
+ goto st8;
782
+ goto st1;
783
+ st8:
784
+ if ( ++p == pe )
785
+ goto _out8;
786
+ case 8:
787
+ switch( (*p) ) {
788
+ case 69: goto st1;
789
+ case 101: goto st1;
790
+ }
791
+ if ( (*p) > 46 ) {
792
+ if ( 48 <= (*p) && (*p) <= 57 )
793
+ goto st8;
794
+ } else if ( (*p) >= 45 )
795
+ goto st1;
796
+ goto tr8;
797
+ st9:
798
+ if ( ++p == pe )
799
+ goto _out9;
800
+ case 9:
801
+ switch( (*p) ) {
802
+ case 46: goto st4;
803
+ case 69: goto st6;
804
+ case 101: goto st6;
805
+ }
806
+ if ( 48 <= (*p) && (*p) <= 57 )
807
+ goto st9;
808
+ goto st1;
809
+ }
810
+ _out1: cs = 1; goto _out;
811
+ _out2: cs = 2; goto _out;
812
+ _out3: cs = 3; goto _out;
813
+ _out4: cs = 4; goto _out;
814
+ _out5: cs = 5; goto _out;
815
+ _out10: cs = 10; goto _out;
816
+ _out6: cs = 6; goto _out;
817
+ _out7: cs = 7; goto _out;
818
+ _out8: cs = 8; goto _out;
819
+ _out9: cs = 9; goto _out;
820
+
821
+ _out: {}
822
+ }
823
+ #line 231 "parser.rl"
824
+
825
+ if (cs >= JSON_float_first_final) {
826
+ long len = p - json->memo;
827
+ *result = rb_Float(rb_str_new(json->memo, len));
828
+ return p + 1;
829
+ } else {
830
+ return NULL;
831
+ }
832
+ }
833
+
834
+
835
+
836
+ #line 837 "parser.c"
837
+ static const int JSON_array_start = 0;
838
+
839
+ static const int JSON_array_first_final = 17;
840
+
841
+ static const int JSON_array_error = 1;
842
+
843
+ #line 267 "parser.rl"
844
+
845
+
846
+ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result)
847
+ {
848
+ int cs = EVIL;
849
+ *result = rb_ary_new();
850
+
851
+
852
+ #line 853 "parser.c"
853
+ {
854
+ cs = JSON_array_start;
855
+ }
856
+ #line 275 "parser.rl"
857
+
858
+ #line 859 "parser.c"
859
+ {
860
+ if ( p == pe )
861
+ goto _out;
862
+ switch ( cs )
863
+ {
864
+ case 0:
865
+ if ( (*p) == 91 )
866
+ goto st2;
867
+ goto st1;
868
+ st1:
869
+ goto _out1;
870
+ st2:
871
+ if ( ++p == pe )
872
+ goto _out2;
873
+ case 2:
874
+ switch( (*p) ) {
875
+ case 13: goto st2;
876
+ case 32: goto st2;
877
+ case 34: goto tr8;
878
+ case 45: goto tr8;
879
+ case 47: goto st13;
880
+ case 91: goto tr8;
881
+ case 93: goto tr7;
882
+ case 102: goto tr8;
883
+ case 110: goto tr8;
884
+ case 116: goto tr8;
885
+ case 123: goto tr8;
886
+ }
887
+ if ( (*p) > 10 ) {
888
+ if ( 48 <= (*p) && (*p) <= 57 )
889
+ goto tr8;
890
+ } else if ( (*p) >= 9 )
891
+ goto st2;
892
+ goto st1;
893
+ tr8:
894
+ #line 248 "parser.rl"
895
+ {
896
+ VALUE v = Qnil;
897
+ char *np = JSON_parse_value(json, p, pe, &v);
898
+ if (np == NULL) {
899
+ goto _out3;
900
+ } else {
901
+ rb_ary_push(*result, v);
902
+ {p = (( np))-1;}
903
+ }
904
+ }
905
+ goto st3;
906
+ st3:
907
+ if ( ++p == pe )
908
+ goto _out3;
909
+ case 3:
910
+ #line 911 "parser.c"
911
+ switch( (*p) ) {
912
+ case 13: goto st3;
913
+ case 32: goto st3;
914
+ case 44: goto st4;
915
+ case 47: goto st9;
916
+ case 93: goto tr7;
917
+ }
918
+ if ( 9 <= (*p) && (*p) <= 10 )
919
+ goto st3;
920
+ goto st1;
921
+ st4:
922
+ if ( ++p == pe )
923
+ goto _out4;
924
+ case 4:
925
+ switch( (*p) ) {
926
+ case 13: goto st4;
927
+ case 32: goto st4;
928
+ case 34: goto tr8;
929
+ case 45: goto tr8;
930
+ case 47: goto st5;
931
+ case 91: goto tr8;
932
+ case 102: goto tr8;
933
+ case 110: goto tr8;
934
+ case 116: goto tr8;
935
+ case 123: goto tr8;
936
+ }
937
+ if ( (*p) > 10 ) {
938
+ if ( 48 <= (*p) && (*p) <= 57 )
939
+ goto tr8;
940
+ } else if ( (*p) >= 9 )
941
+ goto st4;
942
+ goto st1;
943
+ st5:
944
+ if ( ++p == pe )
945
+ goto _out5;
946
+ case 5:
947
+ switch( (*p) ) {
948
+ case 42: goto st6;
949
+ case 47: goto st8;
950
+ }
951
+ goto st1;
952
+ st6:
953
+ if ( ++p == pe )
954
+ goto _out6;
955
+ case 6:
956
+ if ( (*p) == 42 )
957
+ goto st7;
958
+ goto st6;
959
+ st7:
960
+ if ( ++p == pe )
961
+ goto _out7;
962
+ case 7:
963
+ switch( (*p) ) {
964
+ case 42: goto st7;
965
+ case 47: goto st4;
966
+ }
967
+ goto st6;
968
+ st8:
969
+ if ( ++p == pe )
970
+ goto _out8;
971
+ case 8:
972
+ if ( (*p) == 10 )
973
+ goto st4;
974
+ goto st8;
975
+ st9:
976
+ if ( ++p == pe )
977
+ goto _out9;
978
+ case 9:
979
+ switch( (*p) ) {
980
+ case 42: goto st10;
981
+ case 47: goto st12;
982
+ }
983
+ goto st1;
984
+ st10:
985
+ if ( ++p == pe )
986
+ goto _out10;
987
+ case 10:
988
+ if ( (*p) == 42 )
989
+ goto st11;
990
+ goto st10;
991
+ st11:
992
+ if ( ++p == pe )
993
+ goto _out11;
994
+ case 11:
995
+ switch( (*p) ) {
996
+ case 42: goto st11;
997
+ case 47: goto st3;
998
+ }
999
+ goto st10;
1000
+ st12:
1001
+ if ( ++p == pe )
1002
+ goto _out12;
1003
+ case 12:
1004
+ if ( (*p) == 10 )
1005
+ goto st3;
1006
+ goto st12;
1007
+ tr7:
1008
+ #line 259 "parser.rl"
1009
+ { goto _out17; }
1010
+ goto st17;
1011
+ st17:
1012
+ if ( ++p == pe )
1013
+ goto _out17;
1014
+ case 17:
1015
+ #line 1016 "parser.c"
1016
+ goto st1;
1017
+ st13:
1018
+ if ( ++p == pe )
1019
+ goto _out13;
1020
+ case 13:
1021
+ switch( (*p) ) {
1022
+ case 42: goto st14;
1023
+ case 47: goto st16;
1024
+ }
1025
+ goto st1;
1026
+ st14:
1027
+ if ( ++p == pe )
1028
+ goto _out14;
1029
+ case 14:
1030
+ if ( (*p) == 42 )
1031
+ goto st15;
1032
+ goto st14;
1033
+ st15:
1034
+ if ( ++p == pe )
1035
+ goto _out15;
1036
+ case 15:
1037
+ switch( (*p) ) {
1038
+ case 42: goto st15;
1039
+ case 47: goto st2;
1040
+ }
1041
+ goto st14;
1042
+ st16:
1043
+ if ( ++p == pe )
1044
+ goto _out16;
1045
+ case 16:
1046
+ if ( (*p) == 10 )
1047
+ goto st2;
1048
+ goto st16;
1049
+ }
1050
+ _out1: cs = 1; goto _out;
1051
+ _out2: cs = 2; goto _out;
1052
+ _out3: cs = 3; goto _out;
1053
+ _out4: cs = 4; goto _out;
1054
+ _out5: cs = 5; goto _out;
1055
+ _out6: cs = 6; goto _out;
1056
+ _out7: cs = 7; goto _out;
1057
+ _out8: cs = 8; goto _out;
1058
+ _out9: cs = 9; goto _out;
1059
+ _out10: cs = 10; goto _out;
1060
+ _out11: cs = 11; goto _out;
1061
+ _out12: cs = 12; goto _out;
1062
+ _out17: cs = 17; goto _out;
1063
+ _out13: cs = 13; goto _out;
1064
+ _out14: cs = 14; goto _out;
1065
+ _out15: cs = 15; goto _out;
1066
+ _out16: cs = 16; goto _out;
1067
+
1068
+ _out: {}
1069
+ }
1070
+ #line 276 "parser.rl"
1071
+
1072
+ if(cs >= JSON_array_first_final) {
1073
+ return p + 1;
1074
+ } else {
1075
+ rb_raise(eParserError, "unexpected token at '%s'", p);
1076
+ }
1077
+ }
1078
+
1079
+ static VALUE json_string_escape(char *p, char *pe)
1080
+ {
1081
+ VALUE result = rb_str_buf_new(pe - p + 1);
1082
+
1083
+ while (p < pe) {
1084
+ if (*p == '\\') {
1085
+ p++;
1086
+ if (p >= pe) return Qnil; /* raise an exception later, \ at end */
1087
+ switch (*p) {
1088
+ case '"':
1089
+ case '\\':
1090
+ rb_str_buf_cat(result, p, 1);
1091
+ p++;
1092
+ break;
1093
+ case 'b':
1094
+ rb_str_buf_cat2(result, "\b");
1095
+ p++;
1096
+ break;
1097
+ case 'f':
1098
+ rb_str_buf_cat2(result, "\f");
1099
+ p++;
1100
+ break;
1101
+ case 'n':
1102
+ rb_str_buf_cat2(result, "\n");
1103
+ p++;
1104
+ break;
1105
+ case 'r':
1106
+ rb_str_buf_cat2(result, "\r");
1107
+ p++;
1108
+ break;
1109
+ case 't':
1110
+ rb_str_buf_cat2(result, "\t");
1111
+ p++;
1112
+ break;
1113
+ case 'u':
1114
+ if (p > pe - 4) {
1115
+ return Qnil;
1116
+ } else {
1117
+ p = JSON_convert_UTF16_to_UTF8(result, p, pe, strictConversion);
1118
+ }
1119
+ break;
1120
+ }
1121
+ } else {
1122
+ char *q = p;
1123
+ while (*q != '\\' && q < pe) q++;
1124
+ rb_str_buf_cat(result, p, q - p);
1125
+ p = q;
1126
+ }
1127
+ }
1128
+ return result;
1129
+ }
1130
+
1131
+
1132
+ #line 1133 "parser.c"
1133
+ static const int JSON_string_start = 0;
1134
+
1135
+ static const int JSON_string_first_final = 8;
1136
+
1137
+ static const int JSON_string_error = 1;
1138
+
1139
+ #line 350 "parser.rl"
1140
+
1141
+
1142
+ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result)
1143
+ {
1144
+ int cs = EVIL;
1145
+
1146
+ *result = rb_str_new("", 0);
1147
+
1148
+ #line 1149 "parser.c"
1149
+ {
1150
+ cs = JSON_string_start;
1151
+ }
1152
+ #line 358 "parser.rl"
1153
+ json->memo = p;
1154
+
1155
+ #line 1156 "parser.c"
1156
+ {
1157
+ if ( p == pe )
1158
+ goto _out;
1159
+ switch ( cs )
1160
+ {
1161
+ case 0:
1162
+ if ( (*p) == 34 )
1163
+ goto st2;
1164
+ goto st1;
1165
+ st1:
1166
+ goto _out1;
1167
+ st2:
1168
+ if ( ++p == pe )
1169
+ goto _out2;
1170
+ case 2:
1171
+ switch( (*p) ) {
1172
+ case 34: goto tr4;
1173
+ case 92: goto st3;
1174
+ }
1175
+ if ( 0 <= (*p) && (*p) <= 31 )
1176
+ goto st1;
1177
+ goto st2;
1178
+ tr4:
1179
+ #line 342 "parser.rl"
1180
+ {
1181
+ *result = json_string_escape(json->memo + 1, p);
1182
+ if (NIL_P(*result)) goto _out8; else {p = (( p + 1))-1;}
1183
+ }
1184
+ #line 347 "parser.rl"
1185
+ { goto _out8; }
1186
+ goto st8;
1187
+ st8:
1188
+ if ( ++p == pe )
1189
+ goto _out8;
1190
+ case 8:
1191
+ #line 1192 "parser.c"
1192
+ goto st1;
1193
+ st3:
1194
+ if ( ++p == pe )
1195
+ goto _out3;
1196
+ case 3:
1197
+ switch( (*p) ) {
1198
+ case 34: goto st2;
1199
+ case 47: goto st2;
1200
+ case 92: goto st2;
1201
+ case 98: goto st2;
1202
+ case 102: goto st2;
1203
+ case 110: goto st2;
1204
+ case 114: goto st2;
1205
+ case 116: goto st2;
1206
+ case 117: goto st4;
1207
+ }
1208
+ goto st1;
1209
+ st4:
1210
+ if ( ++p == pe )
1211
+ goto _out4;
1212
+ case 4:
1213
+ if ( (*p) < 65 ) {
1214
+ if ( 48 <= (*p) && (*p) <= 57 )
1215
+ goto st5;
1216
+ } else if ( (*p) > 70 ) {
1217
+ if ( 97 <= (*p) && (*p) <= 102 )
1218
+ goto st5;
1219
+ } else
1220
+ goto st5;
1221
+ goto st1;
1222
+ st5:
1223
+ if ( ++p == pe )
1224
+ goto _out5;
1225
+ case 5:
1226
+ if ( (*p) < 65 ) {
1227
+ if ( 48 <= (*p) && (*p) <= 57 )
1228
+ goto st6;
1229
+ } else if ( (*p) > 70 ) {
1230
+ if ( 97 <= (*p) && (*p) <= 102 )
1231
+ goto st6;
1232
+ } else
1233
+ goto st6;
1234
+ goto st1;
1235
+ st6:
1236
+ if ( ++p == pe )
1237
+ goto _out6;
1238
+ case 6:
1239
+ if ( (*p) < 65 ) {
1240
+ if ( 48 <= (*p) && (*p) <= 57 )
1241
+ goto st7;
1242
+ } else if ( (*p) > 70 ) {
1243
+ if ( 97 <= (*p) && (*p) <= 102 )
1244
+ goto st7;
1245
+ } else
1246
+ goto st7;
1247
+ goto st1;
1248
+ st7:
1249
+ if ( ++p == pe )
1250
+ goto _out7;
1251
+ case 7:
1252
+ if ( (*p) < 65 ) {
1253
+ if ( 48 <= (*p) && (*p) <= 57 )
1254
+ goto st2;
1255
+ } else if ( (*p) > 70 ) {
1256
+ if ( 97 <= (*p) && (*p) <= 102 )
1257
+ goto st2;
1258
+ } else
1259
+ goto st2;
1260
+ goto st1;
1261
+ }
1262
+ _out1: cs = 1; goto _out;
1263
+ _out2: cs = 2; goto _out;
1264
+ _out8: cs = 8; goto _out;
1265
+ _out3: cs = 3; goto _out;
1266
+ _out4: cs = 4; goto _out;
1267
+ _out5: cs = 5; goto _out;
1268
+ _out6: cs = 6; goto _out;
1269
+ _out7: cs = 7; goto _out;
1270
+
1271
+ _out: {}
1272
+ }
1273
+ #line 360 "parser.rl"
1274
+
1275
+ if (cs >= JSON_string_first_final) {
1276
+ return p + 1;
1277
+ } else {
1278
+ return NULL;
1279
+ }
1280
+ }
1281
+
1282
+
1283
+
1284
+ #line 1285 "parser.c"
1285
+ static const int JSON_start = 0;
1286
+
1287
+ static const int JSON_first_final = 10;
1288
+
1289
+ static const int JSON_error = 1;
1290
+
1291
+ #line 390 "parser.rl"
1292
+
1293
+
1294
+ /*
1295
+ * Document-class: JSON::Ext::Parser
1296
+ *
1297
+ * This is the JSON parser implemented as a C extension. It can be configured
1298
+ * to be used by setting
1299
+ *
1300
+ * JSON.parser = JSON::Ext::Parser
1301
+ *
1302
+ * with the method parser= in JSON.
1303
+ *
1304
+ */
1305
+
1306
+ /*
1307
+ * call-seq: new(source)
1308
+ *
1309
+ * Creates a new JSON::Ext::Parser instance for the string _source_.
1310
+ */
1311
+ static VALUE cParser_initialize(VALUE self, VALUE source)
1312
+ {
1313
+ char *ptr;
1314
+ long len;
1315
+ GET_STRUCT;
1316
+ source = StringValue(source);
1317
+ ptr = RSTRING(source)->ptr;
1318
+ len = RSTRING(source)->len;
1319
+ if (len < 2) {
1320
+ rb_raise(eParserError, "A JSON text must at least contain two octets!");
1321
+ }
1322
+ /*
1323
+ Convert these?
1324
+ if (len >= 4 && ptr[0] == 0 && ptr[1] == 0 && ptr[2] == 0) {
1325
+ rb_raise(eParserError, "Only UTF8 octet streams are supported atm!");
1326
+ } else if (len >= 4 && ptr[0] == 0 && ptr[2] == 0) {
1327
+ rb_raise(eParserError, "Only UTF8 octet streams are supported atm!");
1328
+ } else if (len >= 4 && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 0) {
1329
+ rb_raise(eParserError, "Only UTF8 octet streams are supported atm!");
1330
+ } else if (len >= 4 && ptr[1] == 0 && ptr[3] == 0) {
1331
+ rb_raise(eParserError, "Only UTF8 octet streams are supported atm!");
1332
+ }
1333
+ */
1334
+ json->len = len;
1335
+ json->source = ptr;
1336
+ json->Vsource = source;
1337
+ json->create_id = rb_funcall(mJSON, i_create_id, 0);
1338
+ return self;
1339
+ }
1340
+
1341
+ /*
1342
+ * call-seq: parse()
1343
+ *
1344
+ * Parses the current JSON text _source_ and returns the complete data
1345
+ * structure as a result.
1346
+ */
1347
+ static VALUE cParser_parse(VALUE self)
1348
+ {
1349
+ GET_STRUCT;
1350
+ char *p, *pe;
1351
+ int cs = EVIL;
1352
+ VALUE result = Qnil;
1353
+
1354
+
1355
+ #line 1356 "parser.c"
1356
+ {
1357
+ cs = JSON_start;
1358
+ }
1359
+ #line 453 "parser.rl"
1360
+ p = json->source;
1361
+ pe = p + json->len;
1362
+
1363
+ #line 1364 "parser.c"
1364
+ {
1365
+ if ( p == pe )
1366
+ goto _out;
1367
+ switch ( cs )
1368
+ {
1369
+ st0:
1370
+ if ( ++p == pe )
1371
+ goto _out0;
1372
+ case 0:
1373
+ switch( (*p) ) {
1374
+ case 13: goto st0;
1375
+ case 32: goto st0;
1376
+ case 47: goto st2;
1377
+ case 91: goto tr7;
1378
+ case 123: goto tr8;
1379
+ }
1380
+ if ( 9 <= (*p) && (*p) <= 10 )
1381
+ goto st0;
1382
+ goto st1;
1383
+ st1:
1384
+ goto _out1;
1385
+ st2:
1386
+ if ( ++p == pe )
1387
+ goto _out2;
1388
+ case 2:
1389
+ switch( (*p) ) {
1390
+ case 42: goto st3;
1391
+ case 47: goto st5;
1392
+ }
1393
+ goto st1;
1394
+ st3:
1395
+ if ( ++p == pe )
1396
+ goto _out3;
1397
+ case 3:
1398
+ if ( (*p) == 42 )
1399
+ goto st4;
1400
+ goto st3;
1401
+ st4:
1402
+ if ( ++p == pe )
1403
+ goto _out4;
1404
+ case 4:
1405
+ switch( (*p) ) {
1406
+ case 42: goto st4;
1407
+ case 47: goto st0;
1408
+ }
1409
+ goto st3;
1410
+ st5:
1411
+ if ( ++p == pe )
1412
+ goto _out5;
1413
+ case 5:
1414
+ if ( (*p) == 10 )
1415
+ goto st0;
1416
+ goto st5;
1417
+ tr7:
1418
+ #line 381 "parser.rl"
1419
+ {
1420
+ char *np = JSON_parse_array(json, p, pe, &result);
1421
+ if (np == NULL) goto _out10; else {p = (( np))-1;}
1422
+ }
1423
+ goto st10;
1424
+ tr8:
1425
+ #line 376 "parser.rl"
1426
+ {
1427
+ char *np = JSON_parse_object(json, p, pe, &result);
1428
+ if (np == NULL) goto _out10; else {p = (( np))-1;}
1429
+ }
1430
+ goto st10;
1431
+ st10:
1432
+ if ( ++p == pe )
1433
+ goto _out10;
1434
+ case 10:
1435
+ #line 1436 "parser.c"
1436
+ switch( (*p) ) {
1437
+ case 13: goto st10;
1438
+ case 32: goto st10;
1439
+ case 47: goto st6;
1440
+ }
1441
+ if ( 9 <= (*p) && (*p) <= 10 )
1442
+ goto st10;
1443
+ goto st1;
1444
+ st6:
1445
+ if ( ++p == pe )
1446
+ goto _out6;
1447
+ case 6:
1448
+ switch( (*p) ) {
1449
+ case 42: goto st7;
1450
+ case 47: goto st9;
1451
+ }
1452
+ goto st1;
1453
+ st7:
1454
+ if ( ++p == pe )
1455
+ goto _out7;
1456
+ case 7:
1457
+ if ( (*p) == 42 )
1458
+ goto st8;
1459
+ goto st7;
1460
+ st8:
1461
+ if ( ++p == pe )
1462
+ goto _out8;
1463
+ case 8:
1464
+ switch( (*p) ) {
1465
+ case 42: goto st8;
1466
+ case 47: goto st10;
1467
+ }
1468
+ goto st7;
1469
+ st9:
1470
+ if ( ++p == pe )
1471
+ goto _out9;
1472
+ case 9:
1473
+ if ( (*p) == 10 )
1474
+ goto st10;
1475
+ goto st9;
1476
+ }
1477
+ _out0: cs = 0; goto _out;
1478
+ _out1: cs = 1; goto _out;
1479
+ _out2: cs = 2; goto _out;
1480
+ _out3: cs = 3; goto _out;
1481
+ _out4: cs = 4; goto _out;
1482
+ _out5: cs = 5; goto _out;
1483
+ _out10: cs = 10; goto _out;
1484
+ _out6: cs = 6; goto _out;
1485
+ _out7: cs = 7; goto _out;
1486
+ _out8: cs = 8; goto _out;
1487
+ _out9: cs = 9; goto _out;
1488
+
1489
+ _out: {}
1490
+ }
1491
+ #line 456 "parser.rl"
1492
+
1493
+ if (cs >= JSON_first_final && p == pe) {
1494
+ return result;
1495
+ } else {
1496
+ rb_raise(eParserError, "unexpected token at '%s'", p);
1497
+ }
1498
+ }
1499
+
1500
+ static JSON_Parser *JSON_allocate()
1501
+ {
1502
+ JSON_Parser *json = ALLOC(JSON_Parser);
1503
+ MEMZERO(json, JSON_Parser, 1);
1504
+ return json;
1505
+ }
1506
+
1507
+ static void JSON_mark(JSON_Parser *json)
1508
+ {
1509
+ rb_gc_mark_maybe(json->Vsource);
1510
+ rb_gc_mark_maybe(json->create_id);
1511
+ }
1512
+
1513
+ static void JSON_free(JSON_Parser *json)
1514
+ {
1515
+ free(json);
1516
+ }
1517
+
1518
+ static VALUE cJSON_parser_s_allocate(VALUE klass)
1519
+ {
1520
+ JSON_Parser *json = JSON_allocate();
1521
+ return Data_Wrap_Struct(klass, JSON_mark, JSON_free, json);
1522
+ }
1523
+
1524
+ /*
1525
+ * call-seq: source()
1526
+ *
1527
+ * Returns a copy of the current _source_ string, that was used to construct
1528
+ * this Parser.
1529
+ */
1530
+ static VALUE cParser_source(VALUE self)
1531
+ {
1532
+ GET_STRUCT;
1533
+ return rb_str_dup(json->Vsource);
1534
+ }
1535
+
1536
+ void Init_parser()
1537
+ {
1538
+ mJSON = rb_define_module("JSON");
1539
+ mExt = rb_define_module_under(mJSON, "Ext");
1540
+ cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
1541
+ eParserError = rb_path2class("JSON::ParserError");
1542
+ rb_define_alloc_func(cParser, cJSON_parser_s_allocate);
1543
+ rb_define_method(cParser, "initialize", cParser_initialize, 1);
1544
+ rb_define_method(cParser, "parse", cParser_parse, 0);
1545
+ rb_define_method(cParser, "source", cParser_source, 0);
1546
+
1547
+ i_json_creatable_p = rb_intern("json_creatable?");
1548
+ i_json_create = rb_intern("json_create");
1549
+ i_create_id = rb_intern("create_id");
1550
+ i_chr = rb_intern("chr");
1551
+ }