json_pure 1.2.4 → 1.4.6

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.
@@ -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,21 +1,74 @@
1
- #include "ruby.h"
2
- #include "unicode.h"
3
- #if HAVE_RE_H
4
- #include "re.h"
5
- #endif
6
-
7
- #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
+ }
8
40
 
9
- #define option_given_p(opts, key) RTEST(rb_funcall((opts), i_key_p, 1, (key)))
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
+ }
10
66
 
11
67
  #ifdef HAVE_RUBY_ENCODING_H
12
- #include "ruby/encoding.h"
13
- #define FORCE_UTF8(obj) rb_enc_associate((obj), rb_utf8_encoding())
14
- static VALUE mEncoding_ASCII_8BIT, mEncoding_UTF_8, mEncoding_UTF_16BE,
15
- mEncoding_UTF_16LE, mEncoding_UTF_32BE, mEncoding_UTF_32LE;
68
+ static VALUE CEncoding_ASCII_8BIT, CEncoding_UTF_8, CEncoding_UTF_16BE,
69
+ CEncoding_UTF_16LE, CEncoding_UTF_32BE, CEncoding_UTF_32LE;
16
70
  static ID i_encoding, i_encode, i_encode_bang, i_force_encoding;
17
71
  #else
18
- #define FORCE_UTF8(obj)
19
72
  static ID i_iconv;
20
73
  #endif
21
74
 
@@ -26,34 +79,6 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
26
79
  i_chr, i_max_nesting, i_allow_nan, i_symbolize_names, i_object_class,
27
80
  i_array_class, i_key_p, i_deep_const_get;
28
81
 
29
- #define MinusInfinity "-Infinity"
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
- static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result);
47
- static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result);
48
- static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result);
49
- static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result);
50
- static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result);
51
- static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result);
52
-
53
- #define GET_STRUCT \
54
- JSON_Parser *json; \
55
- Data_Get_Struct(self, JSON_Parser, json);
56
-
57
82
  %%{
58
83
  machine JSON_common;
59
84
 
@@ -100,8 +125,9 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
100
125
  }
101
126
 
102
127
  action parse_name {
128
+ char *np;
103
129
  json->parsing_name = 1;
104
- char *np = JSON_parse_string(json, fpc, pe, &last_name);
130
+ np = JSON_parse_string(json, fpc, pe, &last_name);
105
131
  json->parsing_name = 0;
106
132
  if (np == NULL) { fhold; fbreak; } else fexec np;
107
133
  }
@@ -348,62 +374,77 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
348
374
  return p + 1;
349
375
  } else {
350
376
  rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
377
+ return NULL;
351
378
  }
352
379
  }
353
380
 
354
- static VALUE json_string_unescape(char *p, char *pe)
381
+ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
355
382
  {
356
- VALUE result = rb_str_buf_new(pe - p + 1);
357
-
358
- while (p < pe) {
359
- if (*p == '\\') {
360
- p++;
361
- if (p >= pe) return Qnil; /* raise an exception later, \ at end */
362
- 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;
363
401
  case '"':
402
+ unescape = (char *) "\"";
403
+ break;
364
404
  case '\\':
365
- rb_str_buf_cat(result, p, 1);
366
- p++;
405
+ unescape = (char *) "\\";
367
406
  break;
368
407
  case 'b':
369
- rb_str_buf_cat2(result, "\b");
370
- p++;
408
+ unescape = (char *) "\b";
371
409
  break;
372
410
  case 'f':
373
- rb_str_buf_cat2(result, "\f");
374
- p++;
375
- break;
376
- case 'n':
377
- rb_str_buf_cat2(result, "\n");
378
- p++;
379
- break;
380
- case 'r':
381
- rb_str_buf_cat2(result, "\r");
382
- p++;
383
- break;
384
- case 't':
385
- rb_str_buf_cat2(result, "\t");
386
- p++;
411
+ unescape = (char *) "\f";
387
412
  break;
388
413
  case 'u':
389
- if (p > pe - 4) {
414
+ if (pe > stringEnd - 4) {
390
415
  return Qnil;
391
416
  } else {
392
- 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;
393
435
  }
394
436
  break;
395
437
  default:
396
- rb_str_buf_cat(result, p, 1);
397
- p++;
398
- break;
438
+ p = pe;
439
+ continue;
399
440
  }
441
+ rb_str_buf_cat(result, unescape, unescape_len);
442
+ p = ++pe;
400
443
  } else {
401
- char *q = p;
402
- while (*q != '\\' && q < pe) q++;
403
- rb_str_buf_cat(result, p, q - p);
404
- p = q;
444
+ pe++;
405
445
  }
406
446
  }
447
+ rb_str_buf_cat(result, p, pe - p);
407
448
  return result;
408
449
  }
409
450
 
@@ -414,15 +455,15 @@ static VALUE json_string_unescape(char *p, char *pe)
414
455
  write data;
415
456
 
416
457
  action parse_string {
417
- *result = json_string_unescape(json->memo + 1, p);
418
- if (NIL_P(*result)) {
419
- fhold;
420
- fbreak;
421
- } else {
422
- FORCE_UTF8(*result);
423
- fexec p + 1;
424
- }
425
- }
458
+ *result = json_string_unescape(*result, json->memo + 1, p);
459
+ if (NIL_P(*result)) {
460
+ fhold;
461
+ fbreak;
462
+ } else {
463
+ FORCE_UTF8(*result);
464
+ fexec p + 1;
465
+ }
466
+ }
426
467
 
427
468
  action exit { fhold; fbreak; }
428
469
 
@@ -433,7 +474,7 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
433
474
  {
434
475
  int cs = EVIL;
435
476
 
436
- *result = rb_str_new("", 0);
477
+ *result = rb_str_buf_new(0);
437
478
  %% write init;
438
479
  json->memo = p;
439
480
  %% write exec;
@@ -488,7 +529,7 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
488
529
  *
489
530
  */
490
531
 
491
- inline static VALUE convert_encoding(VALUE source)
532
+ static VALUE convert_encoding(VALUE source)
492
533
  {
493
534
  char *ptr = RSTRING_PTR(source);
494
535
  long len = RSTRING_LEN(source);
@@ -498,28 +539,28 @@ inline static VALUE convert_encoding(VALUE source)
498
539
  #ifdef HAVE_RUBY_ENCODING_H
499
540
  {
500
541
  VALUE encoding = rb_funcall(source, i_encoding, 0);
501
- if (encoding == mEncoding_ASCII_8BIT) {
542
+ if (encoding == CEncoding_ASCII_8BIT) {
502
543
  if (len >= 4 && ptr[0] == 0 && ptr[1] == 0 && ptr[2] == 0) {
503
544
  source = rb_str_dup(source);
504
- rb_funcall(source, i_force_encoding, 1, mEncoding_UTF_32BE);
505
- source = rb_funcall(source, i_encode_bang, 1, mEncoding_UTF_8);
545
+ rb_funcall(source, i_force_encoding, 1, CEncoding_UTF_32BE);
546
+ source = rb_funcall(source, i_encode_bang, 1, CEncoding_UTF_8);
506
547
  } else if (len >= 4 && ptr[0] == 0 && ptr[2] == 0) {
507
548
  source = rb_str_dup(source);
508
- rb_funcall(source, i_force_encoding, 1, mEncoding_UTF_16BE);
509
- source = rb_funcall(source, i_encode_bang, 1, mEncoding_UTF_8);
549
+ rb_funcall(source, i_force_encoding, 1, CEncoding_UTF_16BE);
550
+ source = rb_funcall(source, i_encode_bang, 1, CEncoding_UTF_8);
510
551
  } else if (len >= 4 && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 0) {
511
552
  source = rb_str_dup(source);
512
- rb_funcall(source, i_force_encoding, 1, mEncoding_UTF_32LE);
513
- source = rb_funcall(source, i_encode_bang, 1, mEncoding_UTF_8);
553
+ rb_funcall(source, i_force_encoding, 1, CEncoding_UTF_32LE);
554
+ source = rb_funcall(source, i_encode_bang, 1, CEncoding_UTF_8);
514
555
  } else if (len >= 4 && ptr[1] == 0 && ptr[3] == 0) {
515
556
  source = rb_str_dup(source);
516
- rb_funcall(source, i_force_encoding, 1, mEncoding_UTF_16LE);
517
- source = rb_funcall(source, i_encode_bang, 1, mEncoding_UTF_8);
557
+ rb_funcall(source, i_force_encoding, 1, CEncoding_UTF_16LE);
558
+ source = rb_funcall(source, i_encode_bang, 1, CEncoding_UTF_8);
518
559
  } else {
519
- source = rb_funcall(source, i_force_encoding, 1, mEncoding_UTF_8);
560
+ FORCE_UTF8(source);
520
561
  }
521
562
  } else {
522
- source = rb_funcall(source, i_encode, 1, mEncoding_UTF_8);
563
+ source = rb_funcall(source, i_encode, 1, CEncoding_UTF_8);
523
564
  }
524
565
  }
525
566
  #else
@@ -567,7 +608,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
567
608
  char *ptr;
568
609
  long len;
569
610
  VALUE source, opts;
570
- GET_STRUCT;
611
+ GET_PARSER;
571
612
  rb_scan_args(argc, argv, "11", &source, &opts);
572
613
  source = convert_encoding(StringValue(source));
573
614
  ptr = RSTRING_PTR(source);
@@ -652,7 +693,7 @@ static VALUE cParser_parse(VALUE self)
652
693
  char *p, *pe;
653
694
  int cs = EVIL;
654
695
  VALUE result = Qnil;
655
- GET_STRUCT;
696
+ GET_PARSER;
656
697
 
657
698
  %% write init;
658
699
  p = json->source;
@@ -663,10 +704,11 @@ static VALUE cParser_parse(VALUE self)
663
704
  return result;
664
705
  } else {
665
706
  rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
707
+ return Qnil;
666
708
  }
667
709
  }
668
710
 
669
- inline static JSON_Parser *JSON_allocate()
711
+ static JSON_Parser *JSON_allocate()
670
712
  {
671
713
  JSON_Parser *json = ALLOC(JSON_Parser);
672
714
  MEMZERO(json, JSON_Parser, 1);
@@ -700,7 +742,7 @@ static VALUE cJSON_parser_s_allocate(VALUE klass)
700
742
  */
701
743
  static VALUE cParser_source(VALUE self)
702
744
  {
703
- GET_STRUCT;
745
+ GET_PARSER;
704
746
  return rb_str_dup(json->Vsource);
705
747
  }
706
748
 
@@ -734,12 +776,12 @@ void Init_parser()
734
776
  i_key_p = rb_intern("key?");
735
777
  i_deep_const_get = rb_intern("deep_const_get");
736
778
  #ifdef HAVE_RUBY_ENCODING_H
737
- mEncoding_UTF_8 = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-8"));
738
- mEncoding_UTF_16BE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-16be"));
739
- mEncoding_UTF_16LE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-16le"));
740
- mEncoding_UTF_32BE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-32be"));
741
- mEncoding_UTF_32LE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-32le"));
742
- mEncoding_ASCII_8BIT = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("ascii-8bit"));
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"));
743
785
  i_encoding = rb_intern("encoding");
744
786
  i_encode = rb_intern("encode");
745
787
  i_encode_bang = rb_intern("encode!");
data/lib/json/common.rb CHANGED
@@ -11,9 +11,9 @@ module JSON
11
11
  # generate and parse for their documentation.
12
12
  def [](object, opts = {})
13
13
  if object.respond_to? :to_str
14
- JSON.parse(object.to_str, opts => {})
14
+ JSON.parse(object.to_str, opts)
15
15
  else
16
- JSON.generate(object, opts => {})
16
+ JSON.generate(object, opts)
17
17
  end
18
18
  end
19
19
 
@@ -63,6 +63,20 @@ module JSON
63
63
  end
64
64
  self.state = generator::State
65
65
  const_set :State, self.state
66
+ const_set :SAFE_STATE_PROTOTYPE, State.new
67
+ const_set :FAST_STATE_PROTOTYPE, State.new(
68
+ :indent => '',
69
+ :space => '',
70
+ :object_nl => "",
71
+ :array_nl => "",
72
+ :max_nesting => false
73
+ )
74
+ const_set :PRETTY_STATE_PROTOTYPE, State.new(
75
+ :indent => ' ',
76
+ :space => ' ',
77
+ :object_nl => "\n",
78
+ :array_nl => "\n"
79
+ )
66
80
  end
67
81
 
68
82
  # Returns the JSON generator modul, that is used by JSON. This might be
@@ -95,15 +109,15 @@ module JSON
95
109
  # deep.
96
110
  class NestingError < ParserError; end
97
111
 
112
+ # :stopdoc:
113
+ class CircularDatastructure < NestingError; end
114
+ # :startdoc:
115
+
98
116
  # This exception is raised, if a generator or unparser error occurs.
99
117
  class GeneratorError < JSONError; end
100
118
  # For backwards compatibility
101
119
  UnparserError = GeneratorError
102
120
 
103
- # If a circular data structure is encountered while unparsing
104
- # this exception is raised.
105
- class CircularDatastructure < GeneratorError; end
106
-
107
121
  # This exception is raised, if the required unicode support is missing on the
108
122
  # system. Usually this means, that the iconv library is not installed.
109
123
  class MissingUnicodeSupport < JSONError; end
@@ -129,7 +143,7 @@ module JSON
129
143
  # * *object_class*: Defaults to Hash
130
144
  # * *array_class*: Defaults to Array
131
145
  def parse(source, opts = {})
132
- JSON.parser.new(source, opts).parse
146
+ Parser.new(source, opts).parse
133
147
  end
134
148
 
135
149
  # Parse the JSON document _source_ into a Ruby data structure and return it.
@@ -149,10 +163,10 @@ module JSON
149
163
  # defaults to true.
150
164
  def parse!(source, opts = {})
151
165
  opts = {
152
- :max_nesting => false,
153
- :allow_nan => true
166
+ :max_nesting => false,
167
+ :allow_nan => true
154
168
  }.update(opts)
155
- JSON.parser.new(source, opts).parse
169
+ Parser.new(source, opts).parse
156
170
  end
157
171
 
158
172
  # Generate a JSON document from the Ruby data structure _obj_ and return
@@ -171,8 +185,6 @@ module JSON
171
185
  # * *space_before*: a string that is put before a : pair delimiter (default: ''),
172
186
  # * *object_nl*: a string that is put at the end of a JSON object (default: ''),
173
187
  # * *array_nl*: a string that is put at the end of a JSON array (default: ''),
174
- # * *check_circular*: true if checking for circular data structures
175
- # should be done (the default), false otherwise.
176
188
  # * *allow_nan*: true if NaN, Infinity, and -Infinity should be
177
189
  # generated, otherwise an exception is thrown, if these values are
178
190
  # encountered. This options defaults to false.
@@ -183,17 +195,19 @@ module JSON
183
195
  # See also the fast_generate for the fastest creation method with the least
184
196
  # amount of sanity checks, and the pretty_generate method for some
185
197
  # defaults for a pretty output.
186
- def generate(obj, state = nil)
187
- if state
188
- state = State.from_state(state)
189
- else
190
- state = State.new
191
- end
192
- result = obj.to_json(state)
193
- if result !~ /\A\s*(?:\[.*\]|\{.*\})\s*\Z/m
194
- raise GeneratorError, "only generation of JSON objects or arrays allowed"
198
+ def generate(obj, opts = nil)
199
+ state = SAFE_STATE_PROTOTYPE.dup
200
+ if opts
201
+ if opts.respond_to? :to_hash
202
+ opts = opts.to_hash
203
+ elsif opts.respond_to? :to_h
204
+ opts = opts.to_h
205
+ else
206
+ raise TypeError, "can't convert #{opts.class} into Hash"
207
+ end
208
+ state = state.configure(opts)
195
209
  end
196
- result
210
+ state.generate(obj)
197
211
  end
198
212
 
199
213
  # :stopdoc:
@@ -208,12 +222,19 @@ module JSON
208
222
  #
209
223
  # *WARNING*: Be careful not to pass any Ruby data structures with circles as
210
224
  # _obj_ argument, because this will cause JSON to go into an infinite loop.
211
- def fast_generate(obj)
212
- result = obj.to_json(nil)
213
- if result !~ /\A(?:\[.*\]|\{.*\})\Z/
214
- raise GeneratorError, "only generation of JSON objects or arrays allowed"
225
+ def fast_generate(obj, opts = nil)
226
+ state = FAST_STATE_PROTOTYPE.dup
227
+ if opts
228
+ if opts.respond_to? :to_hash
229
+ opts = opts.to_hash
230
+ elsif opts.respond_to? :to_h
231
+ opts = opts.to_h
232
+ else
233
+ raise TypeError, "can't convert #{opts.class} into Hash"
234
+ end
235
+ state.configure(opts)
215
236
  end
216
- result
237
+ state.generate(obj)
217
238
  end
218
239
 
219
240
  # :stopdoc:
@@ -229,13 +250,7 @@ module JSON
229
250
  # The _opts_ argument can be used to configure the generator, see the
230
251
  # generate method for a more detailed explanation.
231
252
  def pretty_generate(obj, opts = nil)
232
- state = JSON.state.new(
233
- :indent => ' ',
234
- :space => ' ',
235
- :object_nl => "\n",
236
- :array_nl => "\n",
237
- :check_circular => true
238
- )
253
+ state = PRETTY_STATE_PROTOTYPE.dup
239
254
  if opts
240
255
  if opts.respond_to? :to_hash
241
256
  opts = opts.to_hash
@@ -246,11 +261,7 @@ module JSON
246
261
  end
247
262
  state.configure(opts)
248
263
  end
249
- result = obj.to_json(state)
250
- if result !~ /\A\s*(?:\[.*\]|\{.*\})\s*\Z/m
251
- raise GeneratorError, "only generation of JSON objects or arrays allowed"
252
- end
253
- result
264
+ state.generate(obj)
254
265
  end
255
266
 
256
267
  # :stopdoc:
@@ -360,11 +371,11 @@ module ::Kernel
360
371
  #
361
372
  # The _opts_ argument is passed through to generate/parse respectively, see
362
373
  # generate and parse for their documentation.
363
- def JSON(object, opts = {})
374
+ def JSON(object, *args)
364
375
  if object.respond_to? :to_str
365
- JSON.parse(object.to_str, opts)
376
+ JSON.parse(object.to_str, args.first)
366
377
  else
367
- JSON.generate(object, opts)
378
+ JSON.generate(object, args.first)
368
379
  end
369
380
  end
370
381
  end