scout 5.1.2 → 5.1.3

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.
Files changed (41) hide show
  1. data/CHANGELOG +5 -0
  2. data/lib/scout.rb +1 -1
  3. data/lib/scout/server.rb +4 -1
  4. data/vendor/json_pure/CHANGES +43 -0
  5. data/vendor/json_pure/{RUBY → COPYING} +1 -1
  6. data/vendor/json_pure/GPL +7 -7
  7. data/vendor/json_pure/README +319 -39
  8. data/vendor/json_pure/Rakefile +69 -47
  9. data/vendor/json_pure/VERSION +1 -1
  10. data/vendor/json_pure/benchmarks/generator2_benchmark.rb +222 -0
  11. data/vendor/json_pure/benchmarks/generator_benchmark.rb +64 -5
  12. data/vendor/json_pure/benchmarks/ohai.json +1216 -0
  13. data/vendor/json_pure/benchmarks/ohai.ruby +1 -0
  14. data/vendor/json_pure/benchmarks/parser2_benchmark.rb +251 -0
  15. data/vendor/json_pure/benchmarks/parser_benchmark.rb +67 -5
  16. data/vendor/json_pure/ext/json/ext/generator/extconf.rb +9 -4
  17. data/vendor/json_pure/ext/json/ext/generator/generator.c +831 -409
  18. data/vendor/json_pure/ext/json/ext/generator/generator.h +170 -0
  19. data/vendor/json_pure/ext/json/ext/parser/extconf.rb +8 -4
  20. data/vendor/json_pure/ext/json/ext/parser/parser.c +292 -186
  21. data/vendor/json_pure/ext/json/ext/parser/parser.h +71 -0
  22. data/vendor/json_pure/ext/json/ext/parser/parser.rl +218 -112
  23. data/vendor/json_pure/lib/json/add/core.rb +20 -7
  24. data/vendor/json_pure/lib/json/add/rails.rb +2 -2
  25. data/vendor/json_pure/lib/json/common.rb +85 -42
  26. data/vendor/json_pure/lib/json/pure.rb +3 -3
  27. data/vendor/json_pure/lib/json/pure/generator.rb +112 -90
  28. data/vendor/json_pure/lib/json/pure/parser.rb +42 -4
  29. data/vendor/json_pure/lib/json/version.rb +1 -1
  30. data/vendor/json_pure/tests/test_json.rb +46 -18
  31. data/vendor/json_pure/tests/test_json_addition.rb +4 -6
  32. data/vendor/json_pure/tests/test_json_encoding.rb +68 -0
  33. data/vendor/json_pure/tests/test_json_generate.rb +30 -14
  34. data/vendor/json_pure/tests/test_json_rails.rb +5 -7
  35. data/vendor/json_pure/tests/test_json_unicode.rb +20 -6
  36. metadata +26 -15
  37. data/vendor/json_pure/doc-templates/main.txt +0 -283
  38. data/vendor/json_pure/ext/json/ext/generator/unicode.c +0 -182
  39. data/vendor/json_pure/ext/json/ext/generator/unicode.h +0 -53
  40. data/vendor/json_pure/ext/json/ext/parser/unicode.c +0 -154
  41. data/vendor/json_pure/ext/json/ext/parser/unicode.h +0 -58
@@ -0,0 +1,71 @@
1
+ #ifndef _PARSER_H_
2
+ #define _PARSER_H_
3
+
4
+ #include "ruby.h"
5
+
6
+ #if HAVE_RE_H
7
+ #include "re.h"
8
+ #endif
9
+
10
+ #ifdef HAVE_RUBY_ENCODING_H
11
+ #include "ruby/encoding.h"
12
+ #define FORCE_UTF8(obj) rb_enc_associate((obj), rb_utf8_encoding())
13
+ #else
14
+ #define FORCE_UTF8(obj)
15
+ #endif
16
+
17
+ #define option_given_p(opts, key) RTEST(rb_funcall(opts, i_key_p, 1, key))
18
+
19
+ /* unicode */
20
+
21
+ typedef unsigned long UTF32; /* at least 32 bits */
22
+ typedef unsigned short UTF16; /* at least 16 bits */
23
+ typedef unsigned char UTF8; /* typically 8 bits */
24
+
25
+ #define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD
26
+ #define UNI_SUR_HIGH_START (UTF32)0xD800
27
+ #define UNI_SUR_HIGH_END (UTF32)0xDBFF
28
+ #define UNI_SUR_LOW_START (UTF32)0xDC00
29
+ #define UNI_SUR_LOW_END (UTF32)0xDFFF
30
+
31
+ typedef struct JSON_ParserStruct {
32
+ VALUE Vsource;
33
+ char *source;
34
+ long len;
35
+ char *memo;
36
+ VALUE create_id;
37
+ int max_nesting;
38
+ int current_nesting;
39
+ int allow_nan;
40
+ int parsing_name;
41
+ int symbolize_names;
42
+ VALUE object_class;
43
+ VALUE array_class;
44
+ } JSON_Parser;
45
+
46
+ #define GET_PARSER \
47
+ JSON_Parser *json; \
48
+ Data_Get_Struct(self, JSON_Parser, json)
49
+
50
+ #define MinusInfinity "-Infinity"
51
+ #define EVIL 0x666
52
+
53
+ static UTF32 unescape_unicode(const unsigned char *p);
54
+ static int convert_UTF32_to_UTF8(char *buf, UTF32 ch);
55
+ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result);
56
+ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result);
57
+ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result);
58
+ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result);
59
+ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result);
60
+ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd);
61
+ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result);
62
+ static VALUE convert_encoding(VALUE source);
63
+ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self);
64
+ static VALUE cParser_parse(VALUE self);
65
+ static JSON_Parser *JSON_allocate();
66
+ static void JSON_mark(JSON_Parser *json);
67
+ static void JSON_free(JSON_Parser *json);
68
+ static VALUE cJSON_parser_s_allocate(VALUE klass);
69
+ static VALUE cParser_source(VALUE self);
70
+
71
+ #endif
@@ -1,59 +1,83 @@
1
- #include "ruby.h"
2
- #include "unicode.h"
3
- #if HAVE_RE_H
4
- #include "re.h"
5
- #endif
6
- #if HAVE_RUBY_ST_H
7
- #include "ruby/st.h"
8
- #endif
9
- #if HAVE_ST_H
10
- #include "st.h"
11
- #endif
12
-
13
- #define EVIL 0x666
1
+ #include "parser.h"
2
+
3
+ /* unicode */
4
+
5
+ static const char digit_values[256] = {
6
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
7
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
8
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1,
9
+ -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1,
10
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
11
+ 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
12
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
13
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
14
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
15
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
16
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
17
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
18
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
19
+ -1, -1, -1, -1, -1, -1, -1
20
+ };
21
+
22
+ static UTF32 unescape_unicode(const unsigned char *p)
23
+ {
24
+ char b;
25
+ UTF32 result = 0;
26
+ b = digit_values[p[0]];
27
+ if (b < 0) return UNI_REPLACEMENT_CHAR;
28
+ result = (result << 4) | b;
29
+ b = digit_values[p[1]];
30
+ result = (result << 4) | b;
31
+ if (b < 0) return UNI_REPLACEMENT_CHAR;
32
+ b = digit_values[p[2]];
33
+ result = (result << 4) | b;
34
+ if (b < 0) return UNI_REPLACEMENT_CHAR;
35
+ b = digit_values[p[3]];
36
+ result = (result << 4) | b;
37
+ if (b < 0) return UNI_REPLACEMENT_CHAR;
38
+ return result;
39
+ }
14
40
 
15
- #ifndef RHASH_TBL
16
- #define RHASH_TBL(hsh) (RHASH(hsh)->tbl)
17
- #endif
41
+ static int convert_UTF32_to_UTF8(char *buf, UTF32 ch)
42
+ {
43
+ int len = 1;
44
+ if (ch <= 0x7F) {
45
+ buf[0] = (char) ch;
46
+ } else if (ch <= 0x07FF) {
47
+ buf[0] = (char) ((ch >> 6) | 0xC0);
48
+ buf[1] = (char) ((ch & 0x3F) | 0x80);
49
+ len++;
50
+ } else if (ch <= 0xFFFF) {
51
+ buf[0] = (char) ((ch >> 12) | 0xE0);
52
+ buf[1] = (char) (((ch >> 6) & 0x3F) | 0x80);
53
+ buf[2] = (char) ((ch & 0x3F) | 0x80);
54
+ len += 2;
55
+ } else if (ch <= 0x1fffff) {
56
+ buf[0] =(char) ((ch >> 18) | 0xF0);
57
+ buf[1] =(char) (((ch >> 12) & 0x3F) | 0x80);
58
+ buf[2] =(char) (((ch >> 6) & 0x3F) | 0x80);
59
+ buf[3] =(char) ((ch & 0x3F) | 0x80);
60
+ len += 3;
61
+ } else {
62
+ buf[0] = '?';
63
+ }
64
+ return len;
65
+ }
18
66
 
19
67
  #ifdef HAVE_RUBY_ENCODING_H
20
- #include "ruby/encoding.h"
21
- #define FORCE_UTF8(obj) rb_enc_associate((obj), rb_utf8_encoding())
68
+ static VALUE CEncoding_ASCII_8BIT, CEncoding_UTF_8, CEncoding_UTF_16BE,
69
+ CEncoding_UTF_16LE, CEncoding_UTF_32BE, CEncoding_UTF_32LE;
70
+ static ID i_encoding, i_encode, i_encode_bang, i_force_encoding;
22
71
  #else
23
- #define FORCE_UTF8(obj)
72
+ static ID i_iconv;
24
73
  #endif
25
74
 
26
75
  static VALUE mJSON, mExt, cParser, eParserError, eNestingError;
27
76
  static VALUE CNaN, CInfinity, CMinusInfinity;
28
77
 
29
78
  static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
30
- i_chr, i_max_nesting, i_allow_nan, i_object_class, i_array_class;
31
-
32
- #define MinusInfinity "-Infinity"
33
-
34
- typedef struct JSON_ParserStruct {
35
- VALUE Vsource;
36
- char *source;
37
- long len;
38
- char *memo;
39
- VALUE create_id;
40
- int max_nesting;
41
- int current_nesting;
42
- int allow_nan;
43
- VALUE object_class;
44
- VALUE array_class;
45
- } JSON_Parser;
46
-
47
- static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result);
48
- static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result);
49
- static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result);
50
- static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result);
51
- static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result);
52
- static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result);
53
-
54
- #define GET_STRUCT \
55
- JSON_Parser *json; \
56
- Data_Get_Struct(self, JSON_Parser, json);
79
+ i_chr, i_max_nesting, i_allow_nan, i_symbolize_names, i_object_class,
80
+ i_array_class, i_key_p, i_deep_const_get;
57
81
 
58
82
  %%{
59
83
  machine JSON_common;
@@ -101,7 +125,10 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
101
125
  }
102
126
 
103
127
  action parse_name {
104
- char *np = JSON_parse_string(json, fpc, pe, &last_name);
128
+ char *np;
129
+ json->parsing_name = 1;
130
+ np = JSON_parse_string(json, fpc, pe, &last_name);
131
+ json->parsing_name = 0;
105
132
  if (np == NULL) { fhold; fbreak; } else fexec np;
106
133
  }
107
134
 
@@ -123,7 +150,7 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
123
150
  VALUE object_class = json->object_class;
124
151
 
125
152
  if (json->max_nesting && json->current_nesting > json->max_nesting) {
126
- rb_raise(eNestingError, "nesting of %d is to deep", json->current_nesting);
153
+ rb_raise(eNestingError, "nesting of %d is too deep", json->current_nesting);
127
154
  }
128
155
 
129
156
  *result = NIL_P(object_class) ? rb_hash_new() : rb_class_new_instance(0, 0, object_class);
@@ -135,7 +162,7 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
135
162
  if (RTEST(json->create_id)) {
136
163
  VALUE klassname = rb_hash_aref(*result, json->create_id);
137
164
  if (!NIL_P(klassname)) {
138
- VALUE klass = rb_path2class(StringValueCStr(klassname));
165
+ VALUE klass = rb_funcall(mJSON, i_deep_const_get, 1, klassname);
139
166
  if RTEST(rb_funcall(klass, i_json_creatable_p, 0)) {
140
167
  *result = rb_funcall(klass, i_json_create, 1, *result);
141
168
  }
@@ -336,7 +363,7 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
336
363
  VALUE array_class = json->array_class;
337
364
 
338
365
  if (json->max_nesting && json->current_nesting > json->max_nesting) {
339
- rb_raise(eNestingError, "nesting of %d is to deep", json->current_nesting);
366
+ rb_raise(eNestingError, "nesting of %d is too deep", json->current_nesting);
340
367
  }
341
368
  *result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class);
342
369
 
@@ -347,62 +374,77 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
347
374
  return p + 1;
348
375
  } else {
349
376
  rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
377
+ return NULL;
350
378
  }
351
379
  }
352
380
 
353
- static VALUE json_string_unescape(char *p, char *pe)
381
+ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
354
382
  {
355
- VALUE result = rb_str_buf_new(pe - p + 1);
356
-
357
- while (p < pe) {
358
- if (*p == '\\') {
359
- p++;
360
- if (p >= pe) return Qnil; /* raise an exception later, \ at end */
361
- switch (*p) {
383
+ char *p = string, *pe = string, *unescape;
384
+ int unescape_len;
385
+
386
+ while (pe < stringEnd) {
387
+ if (*pe == '\\') {
388
+ unescape = (char *) "?";
389
+ unescape_len = 1;
390
+ if (pe > p) rb_str_buf_cat(result, p, pe - p);
391
+ switch (*++pe) {
392
+ case 'n':
393
+ unescape = (char *) "\n";
394
+ break;
395
+ case 'r':
396
+ unescape = (char *) "\r";
397
+ break;
398
+ case 't':
399
+ unescape = (char *) "\t";
400
+ break;
362
401
  case '"':
402
+ unescape = (char *) "\"";
403
+ break;
363
404
  case '\\':
364
- rb_str_buf_cat(result, p, 1);
365
- p++;
405
+ unescape = (char *) "\\";
366
406
  break;
367
407
  case 'b':
368
- rb_str_buf_cat2(result, "\b");
369
- p++;
408
+ unescape = (char *) "\b";
370
409
  break;
371
410
  case 'f':
372
- rb_str_buf_cat2(result, "\f");
373
- p++;
374
- break;
375
- case 'n':
376
- rb_str_buf_cat2(result, "\n");
377
- p++;
378
- break;
379
- case 'r':
380
- rb_str_buf_cat2(result, "\r");
381
- p++;
382
- break;
383
- case 't':
384
- rb_str_buf_cat2(result, "\t");
385
- p++;
411
+ unescape = (char *) "\f";
386
412
  break;
387
413
  case 'u':
388
- if (p > pe - 4) {
414
+ if (pe > stringEnd - 4) {
389
415
  return Qnil;
390
416
  } else {
391
- p = JSON_convert_UTF16_to_UTF8(result, p, pe, strictConversion);
417
+ char buf[4];
418
+ UTF32 ch = unescape_unicode((unsigned char *) ++pe);
419
+ pe += 3;
420
+ if (UNI_SUR_HIGH_START == (ch & 0xFC00)) {
421
+ pe++;
422
+ if (pe > stringEnd - 6) return Qnil;
423
+ if (pe[0] == '\\' && pe[1] == 'u') {
424
+ UTF32 sur = unescape_unicode((unsigned char *) pe + 2);
425
+ ch = (((ch & 0x3F) << 10) | ((((ch >> 6) & 0xF) + 1) << 16)
426
+ | (sur & 0x3FF));
427
+ pe += 5;
428
+ } else {
429
+ unescape = (char *) "?";
430
+ break;
431
+ }
432
+ }
433
+ unescape_len = convert_UTF32_to_UTF8(buf, ch);
434
+ unescape = buf;
392
435
  }
393
436
  break;
394
437
  default:
395
- rb_str_buf_cat(result, p, 1);
396
- p++;
397
- break;
438
+ p = pe;
439
+ continue;
398
440
  }
441
+ rb_str_buf_cat(result, unescape, unescape_len);
442
+ p = ++pe;
399
443
  } else {
400
- char *q = p;
401
- while (*q != '\\' && q < pe) q++;
402
- rb_str_buf_cat(result, p, q - p);
403
- p = q;
444
+ pe++;
404
445
  }
405
446
  }
447
+ rb_str_buf_cat(result, p, pe - p);
406
448
  return result;
407
449
  }
408
450
 
@@ -413,7 +455,7 @@ static VALUE json_string_unescape(char *p, char *pe)
413
455
  write data;
414
456
 
415
457
  action parse_string {
416
- *result = json_string_unescape(json->memo + 1, p);
458
+ *result = json_string_unescape(*result, json->memo + 1, p);
417
459
  if (NIL_P(*result)) {
418
460
  fhold;
419
461
  fbreak;
@@ -432,11 +474,14 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
432
474
  {
433
475
  int cs = EVIL;
434
476
 
435
- *result = rb_str_new("", 0);
477
+ *result = rb_str_buf_new(0);
436
478
  %% write init;
437
479
  json->memo = p;
438
480
  %% write exec;
439
481
 
482
+ if (json->symbolize_names && json->parsing_name) {
483
+ *result = rb_str_intern(*result);
484
+ }
440
485
  if (cs >= JSON_string_first_final) {
441
486
  return p + 1;
442
487
  } else {
@@ -484,6 +529,54 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
484
529
  *
485
530
  */
486
531
 
532
+ static VALUE convert_encoding(VALUE source)
533
+ {
534
+ char *ptr = RSTRING_PTR(source);
535
+ long len = RSTRING_LEN(source);
536
+ if (len < 2) {
537
+ rb_raise(eParserError, "A JSON text must at least contain two octets!");
538
+ }
539
+ #ifdef HAVE_RUBY_ENCODING_H
540
+ {
541
+ VALUE encoding = rb_funcall(source, i_encoding, 0);
542
+ if (encoding == CEncoding_ASCII_8BIT) {
543
+ if (len >= 4 && ptr[0] == 0 && ptr[1] == 0 && ptr[2] == 0) {
544
+ source = rb_str_dup(source);
545
+ rb_funcall(source, i_force_encoding, 1, CEncoding_UTF_32BE);
546
+ source = rb_funcall(source, i_encode_bang, 1, CEncoding_UTF_8);
547
+ } else if (len >= 4 && ptr[0] == 0 && ptr[2] == 0) {
548
+ source = rb_str_dup(source);
549
+ rb_funcall(source, i_force_encoding, 1, CEncoding_UTF_16BE);
550
+ source = rb_funcall(source, i_encode_bang, 1, CEncoding_UTF_8);
551
+ } else if (len >= 4 && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 0) {
552
+ source = rb_str_dup(source);
553
+ rb_funcall(source, i_force_encoding, 1, CEncoding_UTF_32LE);
554
+ source = rb_funcall(source, i_encode_bang, 1, CEncoding_UTF_8);
555
+ } else if (len >= 4 && ptr[1] == 0 && ptr[3] == 0) {
556
+ source = rb_str_dup(source);
557
+ rb_funcall(source, i_force_encoding, 1, CEncoding_UTF_16LE);
558
+ source = rb_funcall(source, i_encode_bang, 1, CEncoding_UTF_8);
559
+ } else {
560
+ FORCE_UTF8(source);
561
+ }
562
+ } else {
563
+ source = rb_funcall(source, i_encode, 1, CEncoding_UTF_8);
564
+ }
565
+ }
566
+ #else
567
+ if (len >= 4 && ptr[0] == 0 && ptr[1] == 0 && ptr[2] == 0) {
568
+ source = rb_funcall(mJSON, i_iconv, 3, rb_str_new2("utf-8"), rb_str_new2("utf-32be"), source);
569
+ } else if (len >= 4 && ptr[0] == 0 && ptr[2] == 0) {
570
+ source = rb_funcall(mJSON, i_iconv, 3, rb_str_new2("utf-8"), rb_str_new2("utf-16be"), source);
571
+ } else if (len >= 4 && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 0) {
572
+ source = rb_funcall(mJSON, i_iconv, 3, rb_str_new2("utf-8"), rb_str_new2("utf-32le"), source);
573
+ } else if (len >= 4 && ptr[1] == 0 && ptr[3] == 0) {
574
+ source = rb_funcall(mJSON, i_iconv, 3, rb_str_new2("utf-8"), rb_str_new2("utf-16le"), source);
575
+ }
576
+ #endif
577
+ return source;
578
+ }
579
+
487
580
  /*
488
581
  * call-seq: new(source, opts => {})
489
582
  *
@@ -501,6 +594,9 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
501
594
  * * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
502
595
  * defiance of RFC 4627 to be parsed by the Parser. This option defaults to
503
596
  * false.
597
+ * * *symbolize_names*: If set to true, returns symbols for the names
598
+ * (keys) in a JSON object. Otherwise strings are returned, which is also
599
+ * the default.
504
600
  * * *create_additions*: If set to false, the Parser doesn't create
505
601
  * additions even if a matchin class and create_id was found. This option
506
602
  * defaults to true.
@@ -512,21 +608,18 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
512
608
  char *ptr;
513
609
  long len;
514
610
  VALUE source, opts;
515
- GET_STRUCT;
611
+ GET_PARSER;
516
612
  rb_scan_args(argc, argv, "11", &source, &opts);
517
- source = StringValue(source);
613
+ source = convert_encoding(StringValue(source));
518
614
  ptr = RSTRING_PTR(source);
519
615
  len = RSTRING_LEN(source);
520
- if (len < 2) {
521
- rb_raise(eParserError, "A JSON text must at least contain two octets!");
522
- }
523
616
  if (!NIL_P(opts)) {
524
617
  opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash");
525
618
  if (NIL_P(opts)) {
526
619
  rb_raise(rb_eArgError, "opts needs to be like a hash");
527
620
  } else {
528
621
  VALUE tmp = ID2SYM(i_max_nesting);
529
- if (st_lookup(RHASH_TBL(opts), tmp, 0)) {
622
+ if (option_given_p(opts, tmp)) {
530
623
  VALUE max_nesting = rb_hash_aref(opts, tmp);
531
624
  if (RTEST(max_nesting)) {
532
625
  Check_Type(max_nesting, T_FIXNUM);
@@ -538,14 +631,21 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
538
631
  json->max_nesting = 19;
539
632
  }
540
633
  tmp = ID2SYM(i_allow_nan);
541
- if (st_lookup(RHASH_TBL(opts), tmp, 0)) {
634
+ if (option_given_p(opts, tmp)) {
542
635
  VALUE allow_nan = rb_hash_aref(opts, tmp);
543
636
  json->allow_nan = RTEST(allow_nan) ? 1 : 0;
544
637
  } else {
545
638
  json->allow_nan = 0;
546
639
  }
640
+ tmp = ID2SYM(i_symbolize_names);
641
+ if (option_given_p(opts, tmp)) {
642
+ VALUE symbolize_names = rb_hash_aref(opts, tmp);
643
+ json->symbolize_names = RTEST(symbolize_names) ? 1 : 0;
644
+ } else {
645
+ json->symbolize_names = 0;
646
+ }
547
647
  tmp = ID2SYM(i_create_additions);
548
- if (st_lookup(RHASH_TBL(opts), tmp, 0)) {
648
+ if (option_given_p(opts, tmp)) {
549
649
  VALUE create_additions = rb_hash_aref(opts, tmp);
550
650
  if (RTEST(create_additions)) {
551
651
  json->create_id = rb_funcall(mJSON, i_create_id, 0);
@@ -556,13 +656,13 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
556
656
  json->create_id = rb_funcall(mJSON, i_create_id, 0);
557
657
  }
558
658
  tmp = ID2SYM(i_object_class);
559
- if (st_lookup(RHASH_TBL(opts), tmp, 0)) {
659
+ if (option_given_p(opts, tmp)) {
560
660
  json->object_class = rb_hash_aref(opts, tmp);
561
661
  } else {
562
662
  json->object_class = Qnil;
563
663
  }
564
664
  tmp = ID2SYM(i_array_class);
565
- if (st_lookup(RHASH_TBL(opts), tmp, 0)) {
665
+ if (option_given_p(opts, tmp)) {
566
666
  json->array_class = rb_hash_aref(opts, tmp);
567
667
  } else {
568
668
  json->array_class = Qnil;
@@ -576,18 +676,6 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
576
676
  json->array_class = Qnil;
577
677
  }
578
678
  json->current_nesting = 0;
579
- /*
580
- Convert these?
581
- if (len >= 4 && ptr[0] == 0 && ptr[1] == 0 && ptr[2] == 0) {
582
- rb_raise(eParserError, "Only UTF8 octet streams are supported atm!");
583
- } else if (len >= 4 && ptr[0] == 0 && ptr[2] == 0) {
584
- rb_raise(eParserError, "Only UTF8 octet streams are supported atm!");
585
- } else if (len >= 4 && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 0) {
586
- rb_raise(eParserError, "Only UTF8 octet streams are supported atm!");
587
- } else if (len >= 4 && ptr[1] == 0 && ptr[3] == 0) {
588
- rb_raise(eParserError, "Only UTF8 octet streams are supported atm!");
589
- }
590
- */
591
679
  json->len = len;
592
680
  json->source = ptr;
593
681
  json->Vsource = source;
@@ -605,7 +693,7 @@ static VALUE cParser_parse(VALUE self)
605
693
  char *p, *pe;
606
694
  int cs = EVIL;
607
695
  VALUE result = Qnil;
608
- GET_STRUCT;
696
+ GET_PARSER;
609
697
 
610
698
  %% write init;
611
699
  p = json->source;
@@ -616,10 +704,11 @@ static VALUE cParser_parse(VALUE self)
616
704
  return result;
617
705
  } else {
618
706
  rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
707
+ return Qnil;
619
708
  }
620
709
  }
621
710
 
622
- inline static JSON_Parser *JSON_allocate()
711
+ static JSON_Parser *JSON_allocate()
623
712
  {
624
713
  JSON_Parser *json = ALLOC(JSON_Parser);
625
714
  MEMZERO(json, JSON_Parser, 1);
@@ -653,7 +742,7 @@ static VALUE cJSON_parser_s_allocate(VALUE klass)
653
742
  */
654
743
  static VALUE cParser_source(VALUE self)
655
744
  {
656
- GET_STRUCT;
745
+ GET_PARSER;
657
746
  return rb_str_dup(json->Vsource);
658
747
  }
659
748
 
@@ -681,6 +770,23 @@ void Init_parser()
681
770
  i_chr = rb_intern("chr");
682
771
  i_max_nesting = rb_intern("max_nesting");
683
772
  i_allow_nan = rb_intern("allow_nan");
773
+ i_symbolize_names = rb_intern("symbolize_names");
684
774
  i_object_class = rb_intern("object_class");
685
775
  i_array_class = rb_intern("array_class");
776
+ i_key_p = rb_intern("key?");
777
+ i_deep_const_get = rb_intern("deep_const_get");
778
+ #ifdef HAVE_RUBY_ENCODING_H
779
+ CEncoding_UTF_8 = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-8"));
780
+ CEncoding_UTF_16BE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-16be"));
781
+ CEncoding_UTF_16LE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-16le"));
782
+ CEncoding_UTF_32BE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-32be"));
783
+ CEncoding_UTF_32LE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-32le"));
784
+ CEncoding_ASCII_8BIT = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("ascii-8bit"));
785
+ i_encoding = rb_intern("encoding");
786
+ i_encode = rb_intern("encode");
787
+ i_encode_bang = rb_intern("encode!");
788
+ i_force_encoding = rb_intern("force_encoding");
789
+ #else
790
+ i_iconv = rb_intern("iconv");
791
+ #endif
686
792
  }