oj 3.10.6 → 3.12.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -1
  3. data/ext/oj/buf.h +36 -68
  4. data/ext/oj/cache8.c +59 -62
  5. data/ext/oj/cache8.h +9 -36
  6. data/ext/oj/circarray.c +36 -42
  7. data/ext/oj/circarray.h +12 -13
  8. data/ext/oj/code.c +172 -179
  9. data/ext/oj/code.h +22 -24
  10. data/ext/oj/compat.c +176 -181
  11. data/ext/oj/custom.c +800 -864
  12. data/ext/oj/dump.c +774 -776
  13. data/ext/oj/dump.h +50 -55
  14. data/ext/oj/dump_compat.c +2 -4
  15. data/ext/oj/dump_leaf.c +118 -162
  16. data/ext/oj/dump_object.c +610 -632
  17. data/ext/oj/dump_strict.c +319 -331
  18. data/ext/oj/encode.h +4 -33
  19. data/ext/oj/err.c +40 -29
  20. data/ext/oj/err.h +25 -44
  21. data/ext/oj/extconf.rb +2 -1
  22. data/ext/oj/fast.c +1054 -1081
  23. data/ext/oj/hash.c +102 -97
  24. data/ext/oj/hash.h +10 -35
  25. data/ext/oj/hash_test.c +451 -472
  26. data/ext/oj/mimic_json.c +415 -402
  27. data/ext/oj/object.c +588 -532
  28. data/ext/oj/odd.c +124 -132
  29. data/ext/oj/odd.h +28 -29
  30. data/ext/oj/oj.c +1186 -906
  31. data/ext/oj/oj.h +289 -298
  32. data/ext/oj/parse.c +946 -870
  33. data/ext/oj/parse.h +81 -79
  34. data/ext/oj/rails.c +837 -842
  35. data/ext/oj/rails.h +8 -11
  36. data/ext/oj/reader.c +139 -147
  37. data/ext/oj/reader.h +68 -84
  38. data/ext/oj/resolve.c +44 -47
  39. data/ext/oj/resolve.h +4 -6
  40. data/ext/oj/rxclass.c +69 -73
  41. data/ext/oj/rxclass.h +13 -14
  42. data/ext/oj/saj.c +453 -484
  43. data/ext/oj/scp.c +88 -113
  44. data/ext/oj/sparse.c +783 -714
  45. data/ext/oj/stream_writer.c +123 -157
  46. data/ext/oj/strict.c +133 -106
  47. data/ext/oj/string_writer.c +199 -247
  48. data/ext/oj/trace.c +34 -41
  49. data/ext/oj/trace.h +15 -15
  50. data/ext/oj/util.c +104 -104
  51. data/ext/oj/util.h +4 -3
  52. data/ext/oj/val_stack.c +48 -76
  53. data/ext/oj/val_stack.h +80 -115
  54. data/ext/oj/wab.c +321 -325
  55. data/lib/oj.rb +0 -8
  56. data/lib/oj/bag.rb +1 -0
  57. data/lib/oj/easy_hash.rb +5 -4
  58. data/lib/oj/mimic.rb +47 -13
  59. data/lib/oj/version.rb +1 -1
  60. data/pages/Modes.md +1 -0
  61. data/pages/Options.md +23 -11
  62. data/test/activerecord/result_test.rb +7 -2
  63. data/test/foo.rb +8 -40
  64. data/test/helper.rb +10 -0
  65. data/test/json_gem/json_common_interface_test.rb +8 -3
  66. data/test/json_gem/json_generator_test.rb +15 -3
  67. data/test/json_gem/test_helper.rb +8 -0
  68. data/test/perf.rb +1 -1
  69. data/test/perf_scp.rb +11 -10
  70. data/test/perf_strict.rb +17 -23
  71. data/test/prec.rb +23 -0
  72. data/test/sample_json.rb +1 -1
  73. data/test/test_compat.rb +16 -3
  74. data/test/test_custom.rb +11 -0
  75. data/test/test_fast.rb +32 -2
  76. data/test/test_generate.rb +21 -0
  77. data/test/test_hash.rb +10 -0
  78. data/test/test_rails.rb +9 -0
  79. data/test/test_scp.rb +1 -1
  80. data/test/test_various.rb +4 -2
  81. metadata +89 -85
data/ext/oj/resolve.c CHANGED
@@ -1,79 +1,76 @@
1
- /* resolve.c
2
- * Copyright (c) 2012, Peter Ohler
3
- * All rights reserved.
4
- */
1
+ // Copyright (c) 2012 Peter Ohler. All rights reserved.
2
+ // Licensed under the MIT License. See LICENSE file in the project root for license details.
5
3
 
6
- #include <stdlib.h>
7
4
  #include <stdio.h>
5
+ #include <stdlib.h>
8
6
  #include <string.h>
9
7
  #ifdef HAVE_PTHREAD_MUTEX_INIT
10
8
  #include <pthread.h>
11
9
  #endif
12
10
 
13
- #include "oj.h"
14
11
  #include "err.h"
15
- #include "parse.h"
16
12
  #include "hash.h"
13
+ #include "oj.h"
14
+ #include "parse.h"
17
15
 
18
- inline static VALUE
19
- resolve_classname(VALUE mod, const char *classname, int auto_define) {
20
- VALUE clas;
21
- ID ci = rb_intern(classname);
16
+ inline static VALUE resolve_classname(VALUE mod, const char *classname, int auto_define) {
17
+ VALUE clas;
18
+ ID ci = rb_intern(classname);
22
19
 
23
20
  if (rb_const_defined_at(mod, ci)) {
24
- clas = rb_const_get_at(mod, ci);
21
+ clas = rb_const_get_at(mod, ci);
25
22
  } else if (auto_define) {
26
- clas = rb_define_class_under(mod, classname, oj_bag_class);
23
+ clas = rb_define_class_under(mod, classname, oj_bag_class);
27
24
  } else {
28
- clas = Qundef;
25
+ clas = Qundef;
29
26
  }
30
27
  return clas;
31
28
  }
32
29
 
33
30
  static VALUE
34
31
  resolve_classpath(ParseInfo pi, const char *name, size_t len, int auto_define, VALUE error_class) {
35
- char class_name[1024];
36
- VALUE clas;
37
- char *end = class_name + sizeof(class_name) - 1;
38
- char *s;
39
- const char *n = name;
32
+ char class_name[1024];
33
+ VALUE clas;
34
+ char * end = class_name + sizeof(class_name) - 1;
35
+ char * s;
36
+ const char *n = name;
40
37
 
41
38
  clas = rb_cObject;
42
39
  for (s = class_name; 0 < len; n++, len--) {
43
- if (':' == *n) {
44
- *s = '\0';
45
- n++;
46
- len--;
47
- if (':' != *n) {
48
- return Qundef;
49
- }
50
- if (Qundef == (clas = resolve_classname(clas, class_name, auto_define))) {
51
- return Qundef;
52
- }
53
- s = class_name;
54
- } else if (end <= s) {
55
- return Qundef;
56
- } else {
57
- *s++ = *n;
58
- }
40
+ if (':' == *n) {
41
+ *s = '\0';
42
+ n++;
43
+ len--;
44
+ if (':' != *n) {
45
+ return Qundef;
46
+ }
47
+ if (Qundef == (clas = resolve_classname(clas, class_name, auto_define))) {
48
+ return Qundef;
49
+ }
50
+ s = class_name;
51
+ } else if (end <= s) {
52
+ return Qundef;
53
+ } else {
54
+ *s++ = *n;
55
+ }
59
56
  }
60
57
  *s = '\0';
61
58
  if (Qundef == (clas = resolve_classname(clas, class_name, auto_define))) {
62
- oj_set_error_at(pi, error_class, __FILE__, __LINE__, "class %s is not defined", name);
63
- if (Qnil != error_class) {
64
- pi->err_class = error_class;
65
- }
59
+ oj_set_error_at(pi, error_class, __FILE__, __LINE__, "class %s is not defined", name);
60
+ if (Qnil != error_class) {
61
+ pi->err_class = error_class;
62
+ }
66
63
  }
67
64
  return clas;
68
65
  }
69
66
 
70
67
  VALUE
71
68
  oj_name2class(ParseInfo pi, const char *name, size_t len, int auto_define, VALUE error_class) {
72
- VALUE clas;
73
- VALUE *slot;
69
+ VALUE clas;
70
+ VALUE *slot;
74
71
 
75
72
  if (No == pi->options.class_cache) {
76
- return resolve_classpath(pi, name, len, auto_define, error_class);
73
+ return resolve_classpath(pi, name, len, auto_define, error_class);
77
74
  }
78
75
  #ifdef HAVE_PTHREAD_MUTEX_INIT
79
76
  pthread_mutex_lock(&oj_cache_mutex);
@@ -81,9 +78,9 @@ oj_name2class(ParseInfo pi, const char *name, size_t len, int auto_define, VALUE
81
78
  rb_mutex_lock(oj_cache_mutex);
82
79
  #endif
83
80
  if (Qnil == (clas = oj_class_hash_get(name, len, &slot))) {
84
- if (Qundef != (clas = resolve_classpath(pi, name, len, auto_define, error_class))) {
85
- *slot = clas;
86
- }
81
+ if (Qundef != (clas = resolve_classpath(pi, name, len, auto_define, error_class))) {
82
+ *slot = clas;
83
+ }
87
84
  }
88
85
  #ifdef HAVE_PTHREAD_MUTEX_INIT
89
86
  pthread_mutex_unlock(&oj_cache_mutex);
@@ -95,8 +92,8 @@ oj_name2class(ParseInfo pi, const char *name, size_t len, int auto_define, VALUE
95
92
 
96
93
  VALUE
97
94
  oj_name2struct(ParseInfo pi, VALUE nameVal, VALUE error_class) {
98
- size_t len = RSTRING_LEN(nameVal);
99
- const char *str = StringValuePtr(nameVal);
95
+ size_t len = RSTRING_LEN(nameVal);
96
+ const char *str = StringValuePtr(nameVal);
100
97
 
101
98
  return resolve_classpath(pi, str, len, 0, error_class);
102
99
  }
data/ext/oj/resolve.h CHANGED
@@ -1,14 +1,12 @@
1
- /* resolve.h
2
- * Copyright (c) 2011, Peter Ohler
3
- * All rights reserved.
4
- */
1
+ // Copyright (c) 2011 Peter Ohler. All rights reserved.
2
+ // Licensed under the MIT License. See LICENSE file in the project root for license details.
5
3
 
6
4
  #ifndef OJ_RESOLVE_H
7
5
  #define OJ_RESOLVE_H
8
6
 
9
7
  #include "ruby.h"
10
8
 
11
- extern VALUE oj_name2class(ParseInfo pi, const char *name, size_t len, int auto_define, VALUE error_class);
12
- extern VALUE oj_name2struct(ParseInfo pi, VALUE nameVal, VALUE error_class);
9
+ extern VALUE oj_name2class(ParseInfo pi, const char *name, size_t len, int auto_define, VALUE error_class);
10
+ extern VALUE oj_name2struct(ParseInfo pi, VALUE nameVal, VALUE error_class);
13
11
 
14
12
  #endif /* OJ_RESOLVE_H */
data/ext/oj/rxclass.c CHANGED
@@ -1,13 +1,11 @@
1
- /* rxclass.c
2
- * Copyright (c) 2017, Peter Ohler
3
- * All rights reserved.
4
- */
1
+ // Copyright (c) 2017 Peter Ohler. All rights reserved.
2
+ // Licensed under the MIT License. See LICENSE file in the project root for license details.
5
3
 
6
- #include <sys/types.h>
7
- #include <stdlib.h>
8
4
  #include <errno.h>
9
- #include <string.h>
10
5
  #include <stdio.h>
6
+ #include <stdlib.h>
7
+ #include <string.h>
8
+ #include <sys/types.h>
11
9
  #if !IS_WINDOWS
12
10
  #include <regex.h>
13
11
  #endif
@@ -15,65 +13,64 @@
15
13
  #include "rxclass.h"
16
14
 
17
15
  typedef struct _rxC {
18
- struct _rxC *next;
19
- VALUE rrx;
16
+ struct _rxC *next;
17
+ VALUE rrx;
20
18
  #if !IS_WINDOWS
21
- regex_t rx;
19
+ regex_t rx;
22
20
  #endif
23
- VALUE clas;
24
- char src[256];
25
- } *RxC;
21
+ VALUE clas;
22
+ char src[256];
23
+ } * RxC;
26
24
 
27
- void
28
- oj_rxclass_init(RxClass rc) {
25
+ void oj_rxclass_init(RxClass rc) {
29
26
  *rc->err = '\0';
30
27
  rc->head = NULL;
31
28
  rc->tail = NULL;
32
29
  }
33
30
 
34
- void
35
- oj_rxclass_cleanup(RxClass rc) {
36
- RxC rxc;
31
+ void oj_rxclass_cleanup(RxClass rc) {
32
+ RxC rxc;
37
33
 
38
34
  while (NULL != (rxc = rc->head)) {
39
- rc->head = rc->head->next;
35
+ rc->head = rc->head->next;
40
36
  #if !IS_WINDOWS
41
- if (Qnil == rxc->rrx) {
42
- regfree(&rxc->rx);
43
- }
44
- xfree(rxc);
37
+ if (Qnil == rxc->rrx) {
38
+ regfree(&rxc->rx);
39
+ }
40
+ xfree(rxc);
45
41
  #endif
46
42
  }
47
43
  }
48
44
 
49
- void
50
- oj_rxclass_rappend(RxClass rc, VALUE rx, VALUE clas) {
51
- RxC rxc = ALLOC_N(struct _rxC, 1);
45
+ void oj_rxclass_rappend(RxClass rc, VALUE rx, VALUE clas) {
46
+ RxC rxc = ALLOC_N(struct _rxC, 1);
52
47
 
53
48
  memset(rxc, 0, sizeof(struct _rxC));
54
- rxc->rrx = rx;
49
+ rxc->rrx = rx;
55
50
  rxc->clas = clas;
56
51
  if (NULL == rc->tail) {
57
- rc->head = rxc;
52
+ rc->head = rxc;
58
53
  } else {
59
- rc->tail->next = rxc;
54
+ rc->tail->next = rxc;
60
55
  }
61
56
  rc->tail = rxc;
62
57
  }
63
58
 
64
59
  // Attempt to compile the expression. If it fails populate the error code..
65
- int
66
- oj_rxclass_append(RxClass rc, const char *expr, VALUE clas) {
67
- RxC rxc;
60
+ int oj_rxclass_append(RxClass rc, const char *expr, VALUE clas) {
61
+ RxC rxc;
68
62
  #if !IS_WINDOWS
69
- int err;
70
- int flags = 0;
63
+ int err;
64
+ int flags = 0;
71
65
  #endif
72
66
  if (sizeof(rxc->src) <= strlen(expr)) {
73
- snprintf(rc->err, sizeof(rc->err), "expressions must be less than %lu characters", (unsigned long)sizeof(rxc->src));
74
- return EINVAL;
67
+ snprintf(rc->err,
68
+ sizeof(rc->err),
69
+ "expressions must be less than %lu characters",
70
+ (unsigned long)sizeof(rxc->src));
71
+ return EINVAL;
75
72
  }
76
- rxc = ALLOC_N(struct _rxC, 1);
73
+ rxc = ALLOC_N(struct _rxC, 1);
77
74
  rxc->next = 0;
78
75
  rxc->clas = clas;
79
76
 
@@ -82,15 +79,15 @@ oj_rxclass_append(RxClass rc, const char *expr, VALUE clas) {
82
79
  #else
83
80
  rxc->rrx = Qnil;
84
81
  if (0 != (err = regcomp(&rxc->rx, expr, flags))) {
85
- regerror(err, &rxc->rx, rc->err, sizeof(rc->err));
86
- free(rxc);
87
- return err;
82
+ regerror(err, &rxc->rx, rc->err, sizeof(rc->err));
83
+ free(rxc);
84
+ return err;
88
85
  }
89
86
  #endif
90
87
  if (NULL == rc->tail) {
91
- rc->head = rxc;
88
+ rc->head = rxc;
92
89
  } else {
93
- rc->tail->next = rxc;
90
+ rc->tail->next = rxc;
94
91
  }
95
92
  rc->tail = rxc;
96
93
 
@@ -99,49 +96,48 @@ oj_rxclass_append(RxClass rc, const char *expr, VALUE clas) {
99
96
 
100
97
  VALUE
101
98
  oj_rxclass_match(RxClass rc, const char *str, int len) {
102
- RxC rxc;
103
- char buf[4096];
104
-
99
+ RxC rxc;
100
+ char buf[4096];
101
+
105
102
  for (rxc = rc->head; NULL != rxc; rxc = rxc->next) {
106
- if (Qnil != rxc->rrx) {
107
- // Must use a valiabel for this to work.
108
- volatile VALUE rstr = rb_str_new(str, len);
109
-
110
- //if (Qtrue == rb_funcall(rxc->rrx, rb_intern("match?"), 1, rstr)) {
111
- if (Qnil != rb_funcall(rxc->rrx, rb_intern("match"), 1, rstr)) {
112
- return rxc->clas;
113
- }
114
- } else if (len < (int)sizeof(buf)) {
103
+ if (Qnil != rxc->rrx) {
104
+ // Must use a valiabel for this to work.
105
+ volatile VALUE rstr = rb_str_new(str, len);
106
+
107
+ // if (Qtrue == rb_funcall(rxc->rrx, rb_intern("match?"), 1, rstr)) {
108
+ if (Qnil != rb_funcall(rxc->rrx, rb_intern("match"), 1, rstr)) {
109
+ return rxc->clas;
110
+ }
111
+ } else if (len < (int)sizeof(buf)) {
115
112
  #if !IS_WINDOWS
116
- // string is not \0 terminated so copy and atempt a match
117
- memcpy(buf, str, len);
118
- buf[len] = '\0';
119
- if (0 == regexec(&rxc->rx, buf, 0, NULL, 0)) { // match
120
- return rxc->clas;
121
- }
113
+ // string is not \0 terminated so copy and atempt a match
114
+ memcpy(buf, str, len);
115
+ buf[len] = '\0';
116
+ if (0 == regexec(&rxc->rx, buf, 0, NULL, 0)) { // match
117
+ return rxc->clas;
118
+ }
122
119
  #endif
123
- } else {
124
- // TBD allocate a larger buffer and attempt
125
- }
120
+ } else {
121
+ // TBD allocate a larger buffer and attempt
122
+ }
126
123
  }
127
124
  return Qnil;
128
125
  }
129
126
 
130
- void
131
- oj_rxclass_copy(RxClass src, RxClass dest) {
127
+ void oj_rxclass_copy(RxClass src, RxClass dest) {
132
128
  dest->head = NULL;
133
129
  dest->tail = NULL;
134
130
  if (NULL != src->head) {
135
- RxC rxc;
131
+ RxC rxc;
136
132
 
137
- for (rxc = src->head; NULL != rxc; rxc = rxc->next) {
138
- if (Qnil != rxc->rrx) {
139
- oj_rxclass_rappend(dest, rxc->rrx, rxc->clas);
140
- } else {
133
+ for (rxc = src->head; NULL != rxc; rxc = rxc->next) {
134
+ if (Qnil != rxc->rrx) {
135
+ oj_rxclass_rappend(dest, rxc->rrx, rxc->clas);
136
+ } else {
141
137
  #if !IS_WINDOWS
142
- oj_rxclass_append(dest, rxc->src, rxc->clas);
138
+ oj_rxclass_append(dest, rxc->src, rxc->clas);
143
139
  #endif
144
- }
145
- }
140
+ }
141
+ }
146
142
  }
147
143
  }
data/ext/oj/rxclass.h CHANGED
@@ -1,27 +1,26 @@
1
- /* rxclass.h
2
- * Copyright (c) 2017, Peter Ohler
3
- * All rights reserved.
4
- */
1
+ // Copyright (c) 2017 Peter Ohler. All rights reserved.
2
+ // Licensed under the MIT License. See LICENSE file in the project root for license details.
5
3
 
6
4
  #ifndef OJ_RXCLASS_H
7
5
  #define OJ_RXCLASS_H
8
6
 
9
7
  #include <stdbool.h>
8
+
10
9
  #include "ruby.h"
11
10
 
12
11
  struct _rxC;
13
12
 
14
13
  typedef struct _rxClass {
15
- struct _rxC *head;
16
- struct _rxC *tail;
17
- char err[128];
18
- } *RxClass;
14
+ struct _rxC *head;
15
+ struct _rxC *tail;
16
+ char err[128];
17
+ } * RxClass;
19
18
 
20
- extern void oj_rxclass_init(RxClass rc);
21
- extern void oj_rxclass_cleanup(RxClass rc);
22
- extern int oj_rxclass_append(RxClass rc, const char *expr, VALUE clas);
23
- extern VALUE oj_rxclass_match(RxClass rc, const char *str, int len);
24
- extern void oj_rxclass_copy(RxClass src, RxClass dest);
25
- extern void oj_rxclass_rappend(RxClass rc, VALUE rx, VALUE clas);
19
+ extern void oj_rxclass_init(RxClass rc);
20
+ extern void oj_rxclass_cleanup(RxClass rc);
21
+ extern int oj_rxclass_append(RxClass rc, const char *expr, VALUE clas);
22
+ extern VALUE oj_rxclass_match(RxClass rc, const char *str, int len);
23
+ extern void oj_rxclass_copy(RxClass src, RxClass dest);
24
+ extern void oj_rxclass_rappend(RxClass rc, VALUE rx, VALUE clas);
26
25
 
27
26
  #endif /* OJ_RXCLASS_H */
data/ext/oj/saj.c CHANGED
@@ -1,48 +1,46 @@
1
- /* saj.c
2
- * Copyright (c) 2012, Peter Ohler
3
- * All rights reserved.
4
- */
1
+ // Copyright (c) 2012 Peter Ohler. All rights reserved.
2
+ // Licensed under the MIT License. See LICENSE file in the project root for license details.
5
3
 
6
4
  #if !IS_WINDOWS
7
- #include <sys/resource.h> /* for getrlimit() on linux */
5
+ #include <sys/resource.h> /* for getrlimit() on linux */
8
6
  #endif
9
- #include <stdlib.h>
7
+ #include <math.h>
10
8
  #include <stdio.h>
9
+ #include <stdlib.h>
11
10
  #include <string.h>
12
- #include <math.h>
13
11
  #include <sys/types.h>
14
12
  #include <unistd.h>
15
13
 
16
14
  // Workaround in case INFINITY is not defined in math.h or if the OS is CentOS
17
- #define OJ_INFINITY (1.0/0.0)
15
+ #define OJ_INFINITY (1.0 / 0.0)
18
16
 
19
- #include "oj.h"
20
17
  #include "encode.h"
18
+ #include "oj.h"
21
19
 
22
20
  typedef struct _parseInfo {
23
- char *str; /* buffer being read from */
24
- char *s; /* current position in buffer */
25
- void *stack_min;
26
- VALUE handler;
27
- int has_hash_start;
28
- int has_hash_end;
29
- int has_array_start;
30
- int has_array_end;
31
- int has_add_value;
32
- int has_error;
33
- } *ParseInfo;
34
-
35
- static void read_next(ParseInfo pi, const char *key);
36
- static void read_hash(ParseInfo pi, const char *key);
37
- static void read_array(ParseInfo pi, const char *key);
38
- static void read_str(ParseInfo pi, const char *key);
39
- static void read_num(ParseInfo pi, const char *key);
40
- static void read_true(ParseInfo pi, const char *key);
41
- static void read_false(ParseInfo pi, const char *key);
42
- static void read_nil(ParseInfo pi, const char *key);
43
- static void next_non_white(ParseInfo pi);
44
- static char* read_quoted_value(ParseInfo pi);
45
- static void skip_comment(ParseInfo pi);
21
+ char *str; /* buffer being read from */
22
+ char *s; /* current position in buffer */
23
+ void *stack_min;
24
+ VALUE handler;
25
+ int has_hash_start;
26
+ int has_hash_end;
27
+ int has_array_start;
28
+ int has_array_end;
29
+ int has_add_value;
30
+ int has_error;
31
+ } * ParseInfo;
32
+
33
+ static void read_next(ParseInfo pi, const char *key);
34
+ static void read_hash(ParseInfo pi, const char *key);
35
+ static void read_array(ParseInfo pi, const char *key);
36
+ static void read_str(ParseInfo pi, const char *key);
37
+ static void read_num(ParseInfo pi, const char *key);
38
+ static void read_true(ParseInfo pi, const char *key);
39
+ static void read_false(ParseInfo pi, const char *key);
40
+ static void read_nil(ParseInfo pi, const char *key);
41
+ static void next_non_white(ParseInfo pi);
42
+ static char *read_quoted_value(ParseInfo pi);
43
+ static void skip_comment(ParseInfo pi);
46
44
 
47
45
  /* This JSON parser is a single pass, destructive, callback parser. It is a
48
46
  * single pass parse since it only make one pass over the characters in the
@@ -57,126 +55,108 @@ static void skip_comment(ParseInfo pi);
57
55
  * all cases to parse the string.
58
56
  */
59
57
 
60
- inline static void
61
- call_error(const char *msg, ParseInfo pi, const char* file, int line) {
62
- char buf[128];
63
- const char *s = pi->s;
64
- int jline = 1;
65
- int col = 1;
58
+ inline static void call_error(const char *msg, ParseInfo pi, const char *file, int line) {
59
+ char buf[128];
60
+ const char *s = pi->s;
61
+ int jline = 1;
62
+ int col = 1;
66
63
 
67
64
  for (; pi->str < s && '\n' != *s; s--) {
68
- col++;
65
+ col++;
69
66
  }
70
67
  for (; pi->str < s; s--) {
71
- if ('\n' == *s) {
72
- jline++;
73
- }
68
+ if ('\n' == *s) {
69
+ jline++;
70
+ }
74
71
  }
75
72
  sprintf(buf, "%s at line %d, column %d [%s:%d]", msg, jline, col, file, line);
76
73
  rb_funcall(pi->handler, oj_error_id, 3, rb_str_new2(buf), LONG2NUM(jline), LONG2NUM(col));
77
74
  }
78
75
 
79
- inline static void
80
- next_non_white(ParseInfo pi) {
76
+ inline static void next_non_white(ParseInfo pi) {
81
77
  for (; 1; pi->s++) {
82
- switch(*pi->s) {
83
- case ' ':
84
- case '\t':
85
- case '\f':
86
- case '\n':
87
- case '\r':
88
- break;
89
- case '/':
90
- skip_comment(pi);
91
- break;
92
- default:
93
- return;
94
- }
78
+ switch (*pi->s) {
79
+ case ' ':
80
+ case '\t':
81
+ case '\f':
82
+ case '\n':
83
+ case '\r': break;
84
+ case '/': skip_comment(pi); break;
85
+ default: return;
86
+ }
95
87
  }
96
88
  }
97
89
 
98
- inline static void
99
- call_add_value(VALUE handler, VALUE value, const char *key) {
100
- volatile VALUE k;
90
+ inline static void call_add_value(VALUE handler, VALUE value, const char *key) {
91
+ volatile VALUE k;
101
92
 
102
93
  if (0 == key) {
103
- k = Qnil;
94
+ k = Qnil;
104
95
  } else {
105
- k = rb_str_new2(key);
106
- k = oj_encode(k);
96
+ k = rb_str_new2(key);
97
+ k = oj_encode(k);
107
98
  }
108
99
  rb_funcall(handler, oj_add_value_id, 2, value, k);
109
100
  }
110
101
 
111
- inline static void
112
- call_no_value(VALUE handler, ID method, const char *key) {
113
- volatile VALUE k;
102
+ inline static void call_no_value(VALUE handler, ID method, const char *key) {
103
+ volatile VALUE k;
114
104
 
115
105
  if (0 == key) {
116
- k = Qnil;
106
+ k = Qnil;
117
107
  } else {
118
- k = rb_str_new2(key);
119
- k = oj_encode(k);
108
+ k = rb_str_new2(key);
109
+ k = oj_encode(k);
120
110
  }
121
111
  rb_funcall(handler, method, 1, k);
122
112
  }
123
113
 
124
- static void
125
- skip_comment(ParseInfo pi) {
114
+ static void skip_comment(ParseInfo pi) {
126
115
  pi->s++; /* skip first / */
127
116
  if ('*' == *pi->s) {
128
- pi->s++;
129
- for (; '\0' != *pi->s; pi->s++) {
130
- if ('*' == *pi->s && '/' == *(pi->s + 1)) {
131
- pi->s++;
132
- return;
133
- } else if ('\0' == *pi->s) {
134
- if (pi->has_error) {
135
- call_error("comment not terminated", pi, __FILE__, __LINE__);
136
- } else {
137
- raise_error("comment not terminated", pi->str, pi->s);
138
- }
139
- }
140
- }
117
+ pi->s++;
118
+ for (; '\0' != *pi->s; pi->s++) {
119
+ if ('*' == *pi->s && '/' == *(pi->s + 1)) {
120
+ pi->s++;
121
+ return;
122
+ } else if ('\0' == *pi->s) {
123
+ if (pi->has_error) {
124
+ call_error("comment not terminated", pi, __FILE__, __LINE__);
125
+ } else {
126
+ raise_error("comment not terminated", pi->str, pi->s);
127
+ }
128
+ }
129
+ }
141
130
  } else if ('/' == *pi->s) {
142
- for (; 1; pi->s++) {
143
- switch (*pi->s) {
144
- case '\n':
145
- case '\r':
146
- case '\f':
147
- case '\0':
148
- return;
149
- default:
150
- break;
151
- }
152
- }
131
+ for (; 1; pi->s++) {
132
+ switch (*pi->s) {
133
+ case '\n':
134
+ case '\r':
135
+ case '\f':
136
+ case '\0': return;
137
+ default: break;
138
+ }
139
+ }
153
140
  } else {
154
- if (pi->has_error) {
155
- call_error("invalid comment", pi, __FILE__, __LINE__);
156
- } else {
157
- raise_error("invalid comment", pi->str, pi->s);
158
- }
141
+ if (pi->has_error) {
142
+ call_error("invalid comment", pi, __FILE__, __LINE__);
143
+ } else {
144
+ raise_error("invalid comment", pi->str, pi->s);
145
+ }
159
146
  }
160
147
  }
161
148
 
162
- static void
163
- read_next(ParseInfo pi, const char *key) {
164
- VALUE obj;
149
+ static void read_next(ParseInfo pi, const char *key) {
150
+ VALUE obj;
165
151
 
166
- if ((void*)&obj < pi->stack_min) {
167
- rb_raise(rb_eSysStackError, "JSON is too deeply nested");
152
+ if ((void *)&obj < pi->stack_min) {
153
+ rb_raise(rb_eSysStackError, "JSON is too deeply nested");
168
154
  }
169
- next_non_white(pi); /* skip white space */
155
+ next_non_white(pi); /* skip white space */
170
156
  switch (*pi->s) {
171
- case '{':
172
- read_hash(pi, key);
173
- break;
174
- case '[':
175
- read_array(pi, key);
176
- break;
177
- case '"':
178
- read_str(pi, key);
179
- break;
157
+ case '{': read_hash(pi, key); break;
158
+ case '[': read_array(pi, key); break;
159
+ case '"': read_str(pi, key); break;
180
160
  case '+':
181
161
  case '-':
182
162
  case '0':
@@ -188,113 +168,104 @@ read_next(ParseInfo pi, const char *key) {
188
168
  case '6':
189
169
  case '7':
190
170
  case '8':
191
- case '9':
192
- read_num(pi, key);
193
- break;
194
- case 'I':
195
- read_num(pi, key);
196
- break;
197
- case 't':
198
- read_true(pi, key);
199
- break;
200
- case 'f':
201
- read_false(pi, key);
202
- break;
203
- case 'n':
204
- read_nil(pi, key);
205
- break;
206
- case '\0':
207
- return;
208
- default:
209
- return;
171
+ case '9': read_num(pi, key); break;
172
+ case 'I': read_num(pi, key); break;
173
+ case 't': read_true(pi, key); break;
174
+ case 'f': read_false(pi, key); break;
175
+ case 'n': read_nil(pi, key); break;
176
+ case '\0': return;
177
+ default: return;
210
178
  }
211
179
  }
212
180
 
213
- static void
214
- read_hash(ParseInfo pi, const char *key) {
215
- const char *ks;
216
-
181
+ static void read_hash(ParseInfo pi, const char *key) {
182
+ const char *ks;
183
+
217
184
  if (pi->has_hash_start) {
218
- call_no_value(pi->handler, oj_hash_start_id, key);
185
+ call_no_value(pi->handler, oj_hash_start_id, key);
219
186
  }
220
187
  pi->s++;
221
188
  next_non_white(pi);
222
189
  if ('}' == *pi->s) {
223
- pi->s++;
190
+ pi->s++;
224
191
  } else {
225
- while (1) {
226
- next_non_white(pi);
227
- ks = read_quoted_value(pi);
228
- next_non_white(pi);
229
- if (':' == *pi->s) {
230
- pi->s++;
231
- } else {
232
- if (pi->has_error) {
233
- call_error("invalid format, expected :", pi, __FILE__, __LINE__);
234
- }
235
- raise_error("invalid format, expected :", pi->str, pi->s);
236
- }
237
- read_next(pi, ks);
238
- next_non_white(pi);
239
- if ('}' == *pi->s) {
240
- pi->s++;
241
- break;
242
- } else if (',' == *pi->s) {
243
- pi->s++;
244
- } else {
245
- if (pi->has_error) {
246
- call_error("invalid format, expected , or } while in an object", pi, __FILE__, __LINE__);
247
- }
248
- raise_error("invalid format, expected , or } while in an object", pi->str, pi->s);
249
- }
250
- }
192
+ while (1) {
193
+ next_non_white(pi);
194
+ ks = read_quoted_value(pi);
195
+ next_non_white(pi);
196
+ if (':' == *pi->s) {
197
+ pi->s++;
198
+ } else {
199
+ if (pi->has_error) {
200
+ call_error("invalid format, expected :", pi, __FILE__, __LINE__);
201
+ }
202
+ raise_error("invalid format, expected :", pi->str, pi->s);
203
+ }
204
+ read_next(pi, ks);
205
+ next_non_white(pi);
206
+ if ('}' == *pi->s) {
207
+ pi->s++;
208
+ break;
209
+ } else if (',' == *pi->s) {
210
+ pi->s++;
211
+ } else {
212
+ if (pi->has_error) {
213
+ call_error("invalid format, expected , or } while in an object",
214
+ pi,
215
+ __FILE__,
216
+ __LINE__);
217
+ }
218
+ raise_error("invalid format, expected , or } while in an object", pi->str, pi->s);
219
+ }
220
+ }
251
221
  }
252
222
  if (pi->has_hash_end) {
253
- call_no_value(pi->handler, oj_hash_end_id, key);
223
+ call_no_value(pi->handler, oj_hash_end_id, key);
254
224
  }
255
225
  }
256
226
 
257
- static void
258
- read_array(ParseInfo pi, const char *key) {
227
+ static void read_array(ParseInfo pi, const char *key) {
259
228
  if (pi->has_array_start) {
260
- call_no_value(pi->handler, oj_array_start_id, key);
229
+ call_no_value(pi->handler, oj_array_start_id, key);
261
230
  }
262
231
  pi->s++;
263
232
  next_non_white(pi);
264
233
  if (']' == *pi->s) {
265
- pi->s++;
234
+ pi->s++;
266
235
  } else {
267
- while (1) {
268
- read_next(pi, 0);
269
- next_non_white(pi);
270
- if (',' == *pi->s) {
271
- pi->s++;
272
- } else if (']' == *pi->s) {
273
- pi->s++;
274
- break;
275
- } else {
276
- if (pi->has_error) {
277
- call_error("invalid format, expected , or ] while in an array", pi, __FILE__, __LINE__);
278
- }
279
- raise_error("invalid format, expected , or ] while in an array", pi->str, pi->s);
280
- }
281
- }
236
+ while (1) {
237
+ read_next(pi, 0);
238
+ next_non_white(pi);
239
+ if (',' == *pi->s) {
240
+ pi->s++;
241
+ } else if (']' == *pi->s) {
242
+ pi->s++;
243
+ break;
244
+ } else {
245
+ if (pi->has_error) {
246
+ call_error("invalid format, expected , or ] while in an array",
247
+ pi,
248
+ __FILE__,
249
+ __LINE__);
250
+ }
251
+ raise_error("invalid format, expected , or ] while in an array", pi->str, pi->s);
252
+ }
253
+ }
282
254
  }
283
255
  if (pi->has_array_end) {
284
- call_no_value(pi->handler, oj_array_end_id, key);
256
+ call_no_value(pi->handler, oj_array_end_id, key);
285
257
  }
286
258
  }
287
259
 
288
- static void
289
- read_str(ParseInfo pi, const char *key) {
290
- char *text;
260
+ static void read_str(ParseInfo pi, const char *key) {
261
+ char *text;
291
262
 
292
263
  text = read_quoted_value(pi);
293
264
  if (pi->has_add_value) {
294
- VALUE s = rb_str_new2(text);
265
+ VALUE s = rb_str_new2(text);
295
266
 
296
- s = oj_encode(s);
297
- call_add_value(pi->handler, s, key);
267
+ s = oj_encode(s);
268
+ call_add_value(pi->handler, s, key);
298
269
  }
299
270
  }
300
271
 
@@ -304,230 +275,228 @@ read_str(ParseInfo pi, const char *key) {
304
275
  #define NUM_MAX (FIXNUM_MAX >> 8)
305
276
  #endif
306
277
 
307
- static void
308
- read_num(ParseInfo pi, const char *key) {
309
- char *start = pi->s;
310
- int64_t n = 0;
311
- long a = 0;
312
- long div = 1;
313
- long e = 0;
314
- int neg = 0;
315
- int eneg = 0;
316
- int big = 0;
278
+ static void read_num(ParseInfo pi, const char *key) {
279
+ char * start = pi->s;
280
+ int64_t n = 0;
281
+ long a = 0;
282
+ long div = 1;
283
+ long e = 0;
284
+ int neg = 0;
285
+ int eneg = 0;
286
+ int big = 0;
317
287
 
318
288
  if ('-' == *pi->s) {
319
- pi->s++;
320
- neg = 1;
289
+ pi->s++;
290
+ neg = 1;
321
291
  } else if ('+' == *pi->s) {
322
- pi->s++;
292
+ pi->s++;
323
293
  }
324
294
  if ('I' == *pi->s) {
325
- if (0 != strncmp("Infinity", pi->s, 8)) {
326
- if (pi->has_error) {
327
- call_error("number or other value", pi, __FILE__, __LINE__);
328
- }
329
- raise_error("number or other value", pi->str, pi->s);
330
- }
331
- pi->s += 8;
332
- if (neg) {
333
- if (pi->has_add_value) {
334
- call_add_value(pi->handler, rb_float_new(-OJ_INFINITY), key);
335
- }
336
- } else {
337
- if (pi->has_add_value) {
338
- call_add_value(pi->handler, rb_float_new(OJ_INFINITY), key);
339
- }
340
- }
341
- return;
295
+ if (0 != strncmp("Infinity", pi->s, 8)) {
296
+ if (pi->has_error) {
297
+ call_error("number or other value", pi, __FILE__, __LINE__);
298
+ }
299
+ raise_error("number or other value", pi->str, pi->s);
300
+ }
301
+ pi->s += 8;
302
+ if (neg) {
303
+ if (pi->has_add_value) {
304
+ call_add_value(pi->handler, rb_float_new(-OJ_INFINITY), key);
305
+ }
306
+ } else {
307
+ if (pi->has_add_value) {
308
+ call_add_value(pi->handler, rb_float_new(OJ_INFINITY), key);
309
+ }
310
+ }
311
+ return;
342
312
  }
343
313
  for (; '0' <= *pi->s && *pi->s <= '9'; pi->s++) {
344
- if (big) {
345
- big++;
346
- } else {
347
- n = n * 10 + (*pi->s - '0');
348
- if (NUM_MAX <= n) {
349
- big = 1;
350
- }
351
- }
314
+ if (big) {
315
+ big++;
316
+ } else {
317
+ n = n * 10 + (*pi->s - '0');
318
+ if (NUM_MAX <= n) {
319
+ big = 1;
320
+ }
321
+ }
352
322
  }
353
323
  if ('.' == *pi->s) {
354
- pi->s++;
355
- for (; '0' <= *pi->s && *pi->s <= '9'; pi->s++) {
356
- a = a * 10 + (*pi->s - '0');
357
- div *= 10;
358
- if (NUM_MAX <= div) {
359
- big = 1;
360
- }
361
- }
324
+ pi->s++;
325
+ for (; '0' <= *pi->s && *pi->s <= '9'; pi->s++) {
326
+ a = a * 10 + (*pi->s - '0');
327
+ div *= 10;
328
+ if (NUM_MAX <= div) {
329
+ big = 1;
330
+ }
331
+ }
362
332
  }
363
333
  if ('e' == *pi->s || 'E' == *pi->s) {
364
- pi->s++;
365
- if ('-' == *pi->s) {
366
- pi->s++;
367
- eneg = 1;
368
- } else if ('+' == *pi->s) {
369
- pi->s++;
370
- }
371
- for (; '0' <= *pi->s && *pi->s <= '9'; pi->s++) {
372
- e = e * 10 + (*pi->s - '0');
373
- if (NUM_MAX <= e) {
374
- big = 1;
375
- }
376
- }
334
+ pi->s++;
335
+ if ('-' == *pi->s) {
336
+ pi->s++;
337
+ eneg = 1;
338
+ } else if ('+' == *pi->s) {
339
+ pi->s++;
340
+ }
341
+ for (; '0' <= *pi->s && *pi->s <= '9'; pi->s++) {
342
+ e = e * 10 + (*pi->s - '0');
343
+ if (NUM_MAX <= e) {
344
+ big = 1;
345
+ }
346
+ }
377
347
  }
378
348
  if (0 == e && 0 == a && 1 == div) {
379
- if (big) {
380
- char c = *pi->s;
381
-
382
- *pi->s = '\0';
383
- if (pi->has_add_value) {
384
- call_add_value(pi->handler, rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new2(start)), key);
385
- }
386
- *pi->s = c;
387
- } else {
388
- if (neg) {
389
- n = -n;
390
- }
391
- if (pi->has_add_value) {
392
- call_add_value(pi->handler, LONG2NUM(n), key);
393
- }
394
- }
395
- return;
349
+ if (big) {
350
+ char c = *pi->s;
351
+
352
+ *pi->s = '\0';
353
+ if (pi->has_add_value) {
354
+ call_add_value(pi->handler,
355
+ rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new2(start)),
356
+ key);
357
+ }
358
+ *pi->s = c;
359
+ } else {
360
+ if (neg) {
361
+ n = -n;
362
+ }
363
+ if (pi->has_add_value) {
364
+ call_add_value(pi->handler, LONG2NUM(n), key);
365
+ }
366
+ }
367
+ return;
396
368
  } else { /* decimal */
397
- if (big) {
398
- char c = *pi->s;
399
-
400
- *pi->s = '\0';
401
- if (pi->has_add_value) {
402
- call_add_value(pi->handler, rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new2(start)), key);
403
- }
404
- *pi->s = c;
405
- } else {
406
- double d = (double)n + (double)a / (double)div;
407
-
408
- if (neg) {
409
- d = -d;
410
- }
411
- if (1 < big) {
412
- e += big - 1;
413
- }
414
- if (0 != e) {
415
- if (eneg) {
416
- e = -e;
417
- }
418
- d *= pow(10.0, e);
419
- }
420
- if (pi->has_add_value) {
421
- call_add_value(pi->handler, rb_float_new(d), key);
422
- }
423
- }
369
+ if (big) {
370
+ char c = *pi->s;
371
+
372
+ *pi->s = '\0';
373
+ if (pi->has_add_value) {
374
+ call_add_value(pi->handler,
375
+ rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new2(start)),
376
+ key);
377
+ }
378
+ *pi->s = c;
379
+ } else {
380
+ double d = (double)n + (double)a / (double)div;
381
+
382
+ if (neg) {
383
+ d = -d;
384
+ }
385
+ if (1 < big) {
386
+ e += big - 1;
387
+ }
388
+ if (0 != e) {
389
+ if (eneg) {
390
+ e = -e;
391
+ }
392
+ d *= pow(10.0, e);
393
+ }
394
+ if (pi->has_add_value) {
395
+ call_add_value(pi->handler, rb_float_new(d), key);
396
+ }
397
+ }
424
398
  }
425
399
  }
426
400
 
427
- static void
428
- read_true(ParseInfo pi, const char *key) {
401
+ static void read_true(ParseInfo pi, const char *key) {
429
402
  pi->s++;
430
403
  if ('r' != *pi->s || 'u' != *(pi->s + 1) || 'e' != *(pi->s + 2)) {
431
- if (pi->has_error) {
432
- call_error("invalid format, expected 'true'", pi, __FILE__, __LINE__);
433
- }
434
- raise_error("invalid format, expected 'true'", pi->str, pi->s);
404
+ if (pi->has_error) {
405
+ call_error("invalid format, expected 'true'", pi, __FILE__, __LINE__);
406
+ }
407
+ raise_error("invalid format, expected 'true'", pi->str, pi->s);
435
408
  }
436
409
  pi->s += 3;
437
410
  if (pi->has_add_value) {
438
- call_add_value(pi->handler, Qtrue, key);
411
+ call_add_value(pi->handler, Qtrue, key);
439
412
  }
440
413
  }
441
414
 
442
- static void
443
- read_false(ParseInfo pi, const char *key) {
415
+ static void read_false(ParseInfo pi, const char *key) {
444
416
  pi->s++;
445
417
  if ('a' != *pi->s || 'l' != *(pi->s + 1) || 's' != *(pi->s + 2) || 'e' != *(pi->s + 3)) {
446
- if (pi->has_error) {
447
- call_error("invalid format, expected 'false'", pi, __FILE__, __LINE__);
448
- }
449
- raise_error("invalid format, expected 'false'", pi->str, pi->s);
418
+ if (pi->has_error) {
419
+ call_error("invalid format, expected 'false'", pi, __FILE__, __LINE__);
420
+ }
421
+ raise_error("invalid format, expected 'false'", pi->str, pi->s);
450
422
  }
451
423
  pi->s += 4;
452
424
  if (pi->has_add_value) {
453
- call_add_value(pi->handler, Qfalse, key);
425
+ call_add_value(pi->handler, Qfalse, key);
454
426
  }
455
427
  }
456
428
 
457
- static void
458
- read_nil(ParseInfo pi, const char *key) {
429
+ static void read_nil(ParseInfo pi, const char *key) {
459
430
  pi->s++;
460
431
  if ('u' != *pi->s || 'l' != *(pi->s + 1) || 'l' != *(pi->s + 2)) {
461
- if (pi->has_error) {
462
- call_error("invalid format, expected 'null'", pi, __FILE__, __LINE__);
463
- }
464
- raise_error("invalid format, expected 'null'", pi->str, pi->s);
432
+ if (pi->has_error) {
433
+ call_error("invalid format, expected 'null'", pi, __FILE__, __LINE__);
434
+ }
435
+ raise_error("invalid format, expected 'null'", pi->str, pi->s);
465
436
  }
466
437
  pi->s += 3;
467
438
  if (pi->has_add_value) {
468
- call_add_value(pi->handler, Qnil, key);
439
+ call_add_value(pi->handler, Qnil, key);
469
440
  }
470
441
  }
471
442
 
472
- static uint32_t
473
- read_hex(ParseInfo pi, char *h) {
474
- uint32_t b = 0;
475
- int i;
443
+ static uint32_t read_hex(ParseInfo pi, char *h) {
444
+ uint32_t b = 0;
445
+ int i;
476
446
 
477
447
  /* TBD this can be made faster with a table */
478
448
  for (i = 0; i < 4; i++, h++) {
479
- b = b << 4;
480
- if ('0' <= *h && *h <= '9') {
481
- b += *h - '0';
482
- } else if ('A' <= *h && *h <= 'F') {
483
- b += *h - 'A' + 10;
484
- } else if ('a' <= *h && *h <= 'f') {
485
- b += *h - 'a' + 10;
486
- } else {
487
- pi->s = h;
488
- if (pi->has_error) {
489
- call_error("invalid hex character", pi, __FILE__, __LINE__);
490
- }
491
- raise_error("invalid hex character", pi->str, pi->s);
492
- }
449
+ b = b << 4;
450
+ if ('0' <= *h && *h <= '9') {
451
+ b += *h - '0';
452
+ } else if ('A' <= *h && *h <= 'F') {
453
+ b += *h - 'A' + 10;
454
+ } else if ('a' <= *h && *h <= 'f') {
455
+ b += *h - 'a' + 10;
456
+ } else {
457
+ pi->s = h;
458
+ if (pi->has_error) {
459
+ call_error("invalid hex character", pi, __FILE__, __LINE__);
460
+ }
461
+ raise_error("invalid hex character", pi->str, pi->s);
462
+ }
493
463
  }
494
464
  return b;
495
465
  }
496
466
 
497
- static char*
498
- unicode_to_chars(ParseInfo pi, char *t, uint32_t code) {
467
+ static char *unicode_to_chars(ParseInfo pi, char *t, uint32_t code) {
499
468
  if (0x0000007F >= code) {
500
- *t = (char)code;
469
+ *t = (char)code;
501
470
  } else if (0x000007FF >= code) {
502
- *t++ = 0xC0 | (code >> 6);
503
- *t = 0x80 | (0x3F & code);
471
+ *t++ = 0xC0 | (code >> 6);
472
+ *t = 0x80 | (0x3F & code);
504
473
  } else if (0x0000FFFF >= code) {
505
- *t++ = 0xE0 | (code >> 12);
506
- *t++ = 0x80 | ((code >> 6) & 0x3F);
507
- *t = 0x80 | (0x3F & code);
474
+ *t++ = 0xE0 | (code >> 12);
475
+ *t++ = 0x80 | ((code >> 6) & 0x3F);
476
+ *t = 0x80 | (0x3F & code);
508
477
  } else if (0x001FFFFF >= code) {
509
- *t++ = 0xF0 | (code >> 18);
510
- *t++ = 0x80 | ((code >> 12) & 0x3F);
511
- *t++ = 0x80 | ((code >> 6) & 0x3F);
512
- *t = 0x80 | (0x3F & code);
478
+ *t++ = 0xF0 | (code >> 18);
479
+ *t++ = 0x80 | ((code >> 12) & 0x3F);
480
+ *t++ = 0x80 | ((code >> 6) & 0x3F);
481
+ *t = 0x80 | (0x3F & code);
513
482
  } else if (0x03FFFFFF >= code) {
514
- *t++ = 0xF8 | (code >> 24);
515
- *t++ = 0x80 | ((code >> 18) & 0x3F);
516
- *t++ = 0x80 | ((code >> 12) & 0x3F);
517
- *t++ = 0x80 | ((code >> 6) & 0x3F);
518
- *t = 0x80 | (0x3F & code);
483
+ *t++ = 0xF8 | (code >> 24);
484
+ *t++ = 0x80 | ((code >> 18) & 0x3F);
485
+ *t++ = 0x80 | ((code >> 12) & 0x3F);
486
+ *t++ = 0x80 | ((code >> 6) & 0x3F);
487
+ *t = 0x80 | (0x3F & code);
519
488
  } else if (0x7FFFFFFF >= code) {
520
- *t++ = 0xFC | (code >> 30);
521
- *t++ = 0x80 | ((code >> 24) & 0x3F);
522
- *t++ = 0x80 | ((code >> 18) & 0x3F);
523
- *t++ = 0x80 | ((code >> 12) & 0x3F);
524
- *t++ = 0x80 | ((code >> 6) & 0x3F);
525
- *t = 0x80 | (0x3F & code);
489
+ *t++ = 0xFC | (code >> 30);
490
+ *t++ = 0x80 | ((code >> 24) & 0x3F);
491
+ *t++ = 0x80 | ((code >> 18) & 0x3F);
492
+ *t++ = 0x80 | ((code >> 12) & 0x3F);
493
+ *t++ = 0x80 | ((code >> 6) & 0x3F);
494
+ *t = 0x80 | (0x3F & code);
526
495
  } else {
527
- if (pi->has_error) {
528
- call_error("invalid Unicode", pi, __FILE__, __LINE__);
529
- }
530
- raise_error("invalid Unicode", pi->str, pi->s);
496
+ if (pi->has_error) {
497
+ call_error("invalid Unicode", pi, __FILE__, __LINE__);
498
+ }
499
+ raise_error("invalid Unicode", pi->str, pi->s);
531
500
  }
532
501
  return t;
533
502
  }
@@ -535,119 +504,119 @@ unicode_to_chars(ParseInfo pi, char *t, uint32_t code) {
535
504
  /* Assume the value starts immediately and goes until the quote character is
536
505
  * reached again. Do not read the character after the terminating quote.
537
506
  */
538
- static char*
539
- read_quoted_value(ParseInfo pi) {
540
- char *value = 0;
541
- char *h = pi->s; /* head */
542
- char *t = h; /* tail */
543
- uint32_t code;
544
-
545
- h++; /* skip quote character */
507
+ static char *read_quoted_value(ParseInfo pi) {
508
+ char * value = 0;
509
+ char * h = pi->s; /* head */
510
+ char * t = h; /* tail */
511
+ uint32_t code;
512
+
513
+ h++; /* skip quote character */
546
514
  t++;
547
515
  value = h;
548
516
  for (; '"' != *h; h++, t++) {
549
- if ('\0' == *h) {
550
- pi->s = h;
551
- raise_error("quoted string not terminated", pi->str, pi->s);
552
- } else if ('\\' == *h) {
553
- h++;
554
- switch (*h) {
555
- case 'n': *t = '\n'; break;
556
- case 'r': *t = '\r'; break;
557
- case 't': *t = '\t'; break;
558
- case 'f': *t = '\f'; break;
559
- case 'b': *t = '\b'; break;
560
- case '"': *t = '"'; break;
561
- case '/': *t = '/'; break;
562
- case '\\': *t = '\\'; break;
563
- case 'u':
564
- h++;
565
- code = read_hex(pi, h);
566
- h += 3;
567
- if (0x0000D800 <= code && code <= 0x0000DFFF) {
568
- uint32_t c1 = (code - 0x0000D800) & 0x000003FF;
569
- uint32_t c2;
570
-
571
- h++;
572
- if ('\\' != *h || 'u' != *(h + 1)) {
573
- pi->s = h;
574
- if (pi->has_error) {
575
- call_error("invalid escaped character", pi, __FILE__, __LINE__);
576
- }
577
- raise_error("invalid escaped character", pi->str, pi->s);
578
- }
579
- h += 2;
580
- c2 = read_hex(pi, h);
581
- h += 3;
582
- c2 = (c2 - 0x0000DC00) & 0x000003FF;
583
- code = ((c1 << 10) | c2) + 0x00010000;
584
- }
585
- t = unicode_to_chars(pi, t, code);
586
- break;
587
- default:
588
- pi->s = h;
589
- if (pi->has_error) {
590
- call_error("invalid escaped character", pi, __FILE__, __LINE__);
591
- }
592
- raise_error("invalid escaped character", pi->str, pi->s);
593
- break;
594
- }
595
- } else if (t != h) {
596
- *t = *h;
597
- }
598
- }
599
- *t = '\0'; /* terminate value */
517
+ if ('\0' == *h) {
518
+ pi->s = h;
519
+ raise_error("quoted string not terminated", pi->str, pi->s);
520
+ } else if ('\\' == *h) {
521
+ h++;
522
+ switch (*h) {
523
+ case 'n': *t = '\n'; break;
524
+ case 'r': *t = '\r'; break;
525
+ case 't': *t = '\t'; break;
526
+ case 'f': *t = '\f'; break;
527
+ case 'b': *t = '\b'; break;
528
+ case '"': *t = '"'; break;
529
+ case '/': *t = '/'; break;
530
+ case '\\': *t = '\\'; break;
531
+ case 'u':
532
+ h++;
533
+ code = read_hex(pi, h);
534
+ h += 3;
535
+ if (0x0000D800 <= code && code <= 0x0000DFFF) {
536
+ uint32_t c1 = (code - 0x0000D800) & 0x000003FF;
537
+ uint32_t c2;
538
+
539
+ h++;
540
+ if ('\\' != *h || 'u' != *(h + 1)) {
541
+ pi->s = h;
542
+ if (pi->has_error) {
543
+ call_error("invalid escaped character", pi, __FILE__, __LINE__);
544
+ }
545
+ raise_error("invalid escaped character", pi->str, pi->s);
546
+ }
547
+ h += 2;
548
+ c2 = read_hex(pi, h);
549
+ h += 3;
550
+ c2 = (c2 - 0x0000DC00) & 0x000003FF;
551
+ code = ((c1 << 10) | c2) + 0x00010000;
552
+ }
553
+ t = unicode_to_chars(pi, t, code);
554
+ break;
555
+ default:
556
+ pi->s = h;
557
+ if (pi->has_error) {
558
+ call_error("invalid escaped character", pi, __FILE__, __LINE__);
559
+ }
560
+ raise_error("invalid escaped character", pi->str, pi->s);
561
+ break;
562
+ }
563
+ } else if (t != h) {
564
+ *t = *h;
565
+ }
566
+ }
567
+ *t = '\0'; /* terminate value */
600
568
  pi->s = h + 1;
601
569
 
602
570
  return value;
603
571
  }
604
572
 
605
- static void
606
- saj_parse(VALUE handler, char *json) {
607
- volatile VALUE obj = Qnil;
608
- struct _parseInfo pi;
573
+ static void saj_parse(VALUE handler, char *json) {
574
+ volatile VALUE obj = Qnil;
575
+ struct _parseInfo pi;
609
576
 
610
577
  if (0 == json) {
611
- if (pi.has_error) {
612
- call_error("Invalid arg, xml string can not be null", &pi, __FILE__, __LINE__);
613
- }
614
- raise_error("Invalid arg, xml string can not be null", json, 0);
578
+ if (pi.has_error) {
579
+ call_error("Invalid arg, xml string can not be null", &pi, __FILE__, __LINE__);
580
+ }
581
+ raise_error("Invalid arg, xml string can not be null", json, 0);
615
582
  }
616
583
  /* skip UTF-8 BOM if present */
617
584
  if (0xEF == (uint8_t)*json && 0xBB == (uint8_t)json[1] && 0xBF == (uint8_t)json[2]) {
618
- json += 3;
585
+ json += 3;
619
586
  }
620
587
  /* initialize parse info */
621
588
  pi.str = json;
622
- pi.s = json;
589
+ pi.s = json;
623
590
  #if IS_WINDOWS
624
- pi.stack_min = (void*)((char*)&obj - (512 * 1024)); /* assume a 1M stack and give half to ruby */
591
+ pi.stack_min = (void *)((char *)&obj -
592
+ (512 * 1024)); /* assume a 1M stack and give half to ruby */
625
593
  #else
626
594
  {
627
- struct rlimit lim;
595
+ struct rlimit lim;
628
596
 
629
- if (0 == getrlimit(RLIMIT_STACK, &lim) && RLIM_INFINITY != lim.rlim_cur) {
630
- pi.stack_min = (void*)((char*)&obj - (lim.rlim_cur / 4 * 3)); /* let 3/4ths of the stack be used only */
631
- } else {
632
- pi.stack_min = 0; /* indicates not to check stack limit */
633
- }
597
+ if (0 == getrlimit(RLIMIT_STACK, &lim) && RLIM_INFINITY != lim.rlim_cur) {
598
+ pi.stack_min = (void *)((char *)&obj - (lim.rlim_cur / 4 *
599
+ 3)); /* let 3/4ths of the stack be used only */
600
+ } else {
601
+ pi.stack_min = 0; /* indicates not to check stack limit */
602
+ }
634
603
  }
635
604
  #endif
636
- pi.handler = handler;
637
- pi.has_hash_start = rb_respond_to(handler, oj_hash_start_id);
638
- pi.has_hash_end = rb_respond_to(handler, oj_hash_end_id);
605
+ pi.handler = handler;
606
+ pi.has_hash_start = rb_respond_to(handler, oj_hash_start_id);
607
+ pi.has_hash_end = rb_respond_to(handler, oj_hash_end_id);
639
608
  pi.has_array_start = rb_respond_to(handler, oj_array_start_id);
640
- pi.has_array_end = rb_respond_to(handler, oj_array_end_id);
641
- pi.has_add_value = rb_respond_to(handler, oj_add_value_id);
642
- pi.has_error = rb_respond_to(handler, oj_error_id);
609
+ pi.has_array_end = rb_respond_to(handler, oj_array_end_id);
610
+ pi.has_add_value = rb_respond_to(handler, oj_add_value_id);
611
+ pi.has_error = rb_respond_to(handler, oj_error_id);
643
612
  read_next(&pi, 0);
644
613
  next_non_white(&pi);
645
614
  if ('\0' != *pi.s) {
646
- if (pi.has_error) {
647
- call_error("invalid format, extra characters", &pi, __FILE__, __LINE__);
648
- } else {
649
- raise_error("invalid format, extra characters", pi.str, pi.s);
650
- }
615
+ if (pi.has_error) {
616
+ call_error("invalid format, extra characters", &pi, __FILE__, __LINE__);
617
+ } else {
618
+ raise_error("invalid format, extra characters", pi.str, pi.s);
619
+ }
651
620
  }
652
621
  }
653
622
 
@@ -664,48 +633,48 @@ saj_parse(VALUE handler, char *json) {
664
633
  */
665
634
  VALUE
666
635
  oj_saj_parse(int argc, VALUE *argv, VALUE self) {
667
- char *json = 0;
668
- size_t len = 0;
669
- VALUE input = argv[1];
636
+ char * json = 0;
637
+ size_t len = 0;
638
+ VALUE input = argv[1];
670
639
 
671
640
  if (argc < 2) {
672
- rb_raise(rb_eArgError, "Wrong number of arguments to saj_parse.\n");
641
+ rb_raise(rb_eArgError, "Wrong number of arguments to saj_parse.\n");
673
642
  }
674
643
  if (rb_type(input) == T_STRING) {
675
- // the json string gets modified so make a copy of it
676
- len = RSTRING_LEN(input) + 1;
677
- json = ALLOC_N(char, len);
678
- strcpy(json, StringValuePtr(input));
644
+ // the json string gets modified so make a copy of it
645
+ len = RSTRING_LEN(input) + 1;
646
+ json = ALLOC_N(char, len);
647
+ strcpy(json, StringValuePtr(input));
679
648
  } else {
680
- VALUE clas = rb_obj_class(input);
681
- volatile VALUE s;
682
-
683
- if (oj_stringio_class == clas) {
684
- s = rb_funcall2(input, oj_string_id, 0, 0);
685
- len = RSTRING_LEN(s) + 1;
686
- json = ALLOC_N(char, len);
687
- strcpy(json, rb_string_value_cstr((VALUE*)&s));
649
+ VALUE clas = rb_obj_class(input);
650
+ volatile VALUE s;
651
+
652
+ if (oj_stringio_class == clas) {
653
+ s = rb_funcall2(input, oj_string_id, 0, 0);
654
+ len = RSTRING_LEN(s) + 1;
655
+ json = ALLOC_N(char, len);
656
+ strcpy(json, rb_string_value_cstr((VALUE *)&s));
688
657
  #if !IS_WINDOWS
689
- } else if (rb_cFile == clas && 0 == FIX2INT(rb_funcall(input, oj_pos_id, 0))) {
690
- int fd = FIX2INT(rb_funcall(input, oj_fileno_id, 0));
691
- ssize_t cnt;
692
-
693
- len = lseek(fd, 0, SEEK_END);
694
- lseek(fd, 0, SEEK_SET);
695
- json = ALLOC_N(char, len + 1);
696
- if (0 >= (cnt = read(fd, json, len)) || cnt != (ssize_t)len) {
697
- rb_raise(rb_eIOError, "failed to read from IO Object.");
698
- }
699
- json[len] = '\0';
658
+ } else if (rb_cFile == clas && 0 == FIX2INT(rb_funcall(input, oj_pos_id, 0))) {
659
+ int fd = FIX2INT(rb_funcall(input, oj_fileno_id, 0));
660
+ ssize_t cnt;
661
+
662
+ len = lseek(fd, 0, SEEK_END);
663
+ lseek(fd, 0, SEEK_SET);
664
+ json = ALLOC_N(char, len + 1);
665
+ if (0 >= (cnt = read(fd, json, len)) || cnt != (ssize_t)len) {
666
+ rb_raise(rb_eIOError, "failed to read from IO Object.");
667
+ }
668
+ json[len] = '\0';
700
669
  #endif
701
- } else if (rb_respond_to(input, oj_read_id)) {
702
- s = rb_funcall2(input, oj_read_id, 0, 0);
703
- len = RSTRING_LEN(s) + 1;
704
- json = ALLOC_N(char, len);
705
- strcpy(json, rb_string_value_cstr((VALUE*)&s));
706
- } else {
707
- rb_raise(rb_eArgError, "saj_parse() expected a String or IO Object.");
708
- }
670
+ } else if (rb_respond_to(input, oj_read_id)) {
671
+ s = rb_funcall2(input, oj_read_id, 0, 0);
672
+ len = RSTRING_LEN(s) + 1;
673
+ json = ALLOC_N(char, len);
674
+ strcpy(json, rb_string_value_cstr((VALUE *)&s));
675
+ } else {
676
+ rb_raise(rb_eArgError, "saj_parse() expected a String or IO Object.");
677
+ }
709
678
  }
710
679
  saj_parse(*argv, json);
711
680
  xfree(json);