oj 3.10.6 → 3.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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);