scout 5.1.2 → 5.1.3

Sign up to get free protection for your applications and to get access to all the features.
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
  }