oj 3.11.0 → 3.11.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -1
  3. data/ext/oj/buf.h +34 -38
  4. data/ext/oj/cache8.c +59 -62
  5. data/ext/oj/cache8.h +8 -7
  6. data/ext/oj/circarray.c +33 -35
  7. data/ext/oj/circarray.h +11 -9
  8. data/ext/oj/code.c +170 -174
  9. data/ext/oj/code.h +21 -20
  10. data/ext/oj/compat.c +159 -166
  11. data/ext/oj/custom.c +802 -851
  12. data/ext/oj/dump.c +766 -778
  13. data/ext/oj/dump.h +49 -51
  14. data/ext/oj/dump_compat.c +1 -0
  15. data/ext/oj/dump_leaf.c +116 -157
  16. data/ext/oj/dump_object.c +609 -628
  17. data/ext/oj/dump_strict.c +318 -327
  18. data/ext/oj/encode.h +3 -4
  19. data/ext/oj/err.c +39 -25
  20. data/ext/oj/err.h +24 -15
  21. data/ext/oj/extconf.rb +2 -1
  22. data/ext/oj/fast.c +1008 -1038
  23. data/ext/oj/hash.c +62 -66
  24. data/ext/oj/hash.h +7 -6
  25. data/ext/oj/hash_test.c +450 -443
  26. data/ext/oj/mimic_json.c +413 -402
  27. data/ext/oj/object.c +559 -528
  28. data/ext/oj/odd.c +123 -128
  29. data/ext/oj/odd.h +27 -25
  30. data/ext/oj/oj.c +1131 -924
  31. data/ext/oj/oj.h +286 -298
  32. data/ext/oj/parse.c +938 -930
  33. data/ext/oj/parse.h +70 -69
  34. data/ext/oj/rails.c +836 -839
  35. data/ext/oj/rails.h +7 -7
  36. data/ext/oj/reader.c +135 -140
  37. data/ext/oj/reader.h +66 -79
  38. data/ext/oj/resolve.c +43 -43
  39. data/ext/oj/resolve.h +3 -2
  40. data/ext/oj/rxclass.c +67 -68
  41. data/ext/oj/rxclass.h +12 -10
  42. data/ext/oj/saj.c +451 -479
  43. data/ext/oj/scp.c +93 -103
  44. data/ext/oj/sparse.c +770 -730
  45. data/ext/oj/stream_writer.c +120 -149
  46. data/ext/oj/strict.c +71 -86
  47. data/ext/oj/string_writer.c +198 -243
  48. data/ext/oj/trace.c +29 -33
  49. data/ext/oj/trace.h +14 -11
  50. data/ext/oj/util.c +103 -103
  51. data/ext/oj/util.h +3 -2
  52. data/ext/oj/val_stack.c +47 -47
  53. data/ext/oj/val_stack.h +79 -86
  54. data/ext/oj/wab.c +291 -309
  55. data/lib/oj/bag.rb +1 -0
  56. data/lib/oj/easy_hash.rb +5 -4
  57. data/lib/oj/mimic.rb +0 -12
  58. data/lib/oj/version.rb +1 -1
  59. data/test/activerecord/result_test.rb +7 -2
  60. data/test/foo.rb +35 -32
  61. data/test/helper.rb +10 -0
  62. data/test/json_gem/json_generator_test.rb +15 -3
  63. data/test/json_gem/test_helper.rb +8 -0
  64. data/test/test_compat.rb +2 -2
  65. data/test/test_generate.rb +21 -0
  66. data/test/test_hash.rb +10 -0
  67. data/test/test_scp.rb +1 -1
  68. metadata +4 -2
data/ext/oj/encode.h CHANGED
@@ -1,15 +1,14 @@
1
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.
2
3
 
3
4
  #ifndef OJ_ENCODE_H
4
5
  #define OJ_ENCODE_H
5
6
 
7
+ #include "oj.h"
6
8
  #include "ruby.h"
7
9
  #include "ruby/encoding.h"
8
10
 
9
- #include "oj.h"
10
-
11
- static inline VALUE
12
- oj_encode(VALUE rstr) {
11
+ static inline VALUE oj_encode(VALUE rstr) {
13
12
  rb_enc_associate(rstr, oj_utf8_encoding);
14
13
  return rstr;
15
14
  }
data/ext/oj/err.c CHANGED
@@ -1,12 +1,12 @@
1
1
  // Copyright (c) 2011 Peter Ohler. All rights reserved.
2
-
3
- #include <stdarg.h>
2
+ // Licensed under the MIT License. See LICENSE file in the project root for license details.
4
3
 
5
4
  #include "err.h"
6
5
 
7
- void
8
- oj_err_set(Err e, VALUE clas, const char *format, ...) {
9
- va_list ap;
6
+ #include <stdarg.h>
7
+
8
+ void oj_err_set(Err e, VALUE clas, const char *format, ...) {
9
+ va_list ap;
10
10
 
11
11
  va_start(ap, format);
12
12
  e->clas = clas;
@@ -14,41 +14,55 @@ oj_err_set(Err e, VALUE clas, const char *format, ...) {
14
14
  va_end(ap);
15
15
  }
16
16
 
17
- void
18
- oj_err_raise(Err e) {
17
+ void oj_err_raise(Err e) {
19
18
  rb_raise(e->clas, "%s", e->msg);
20
19
  }
21
20
 
22
- void
23
- _oj_err_set_with_location(Err err, VALUE eclas, const char *msg, const char *json, const char *current, const char* file, int line) {
24
- int n = 1;
25
- int col = 1;
21
+ void _oj_err_set_with_location(Err err,
22
+ VALUE eclas,
23
+ const char *msg,
24
+ const char *json,
25
+ const char *current,
26
+ const char *file,
27
+ int line) {
28
+ int n = 1;
29
+ int col = 1;
26
30
 
27
31
  for (; json < current && '\n' != *current; current--) {
28
- col++;
32
+ col++;
29
33
  }
30
34
  for (; json < current; current--) {
31
- if ('\n' == *current) {
32
- n++;
33
- }
35
+ if ('\n' == *current) {
36
+ n++;
37
+ }
34
38
  }
35
39
  oj_err_set(err, eclas, "%s at line %d, column %d [%s:%d]", msg, n, col, file, line);
36
40
  }
37
41
 
38
- void
39
- _oj_raise_error(const char *msg, const char *json, const char *current, const char* file, int line) {
40
- struct _err err;
41
- int n = 1;
42
- int col = 1;
42
+ void _oj_raise_error(const char *msg,
43
+ const char *json,
44
+ const char *current,
45
+ const char *file,
46
+ int line) {
47
+ struct _err err;
48
+ int n = 1;
49
+ int col = 1;
43
50
 
44
51
  for (; json < current && '\n' != *current; current--) {
45
- col++;
52
+ col++;
46
53
  }
47
54
  for (; json < current; current--) {
48
- if ('\n' == *current) {
49
- n++;
50
- }
55
+ if ('\n' == *current) {
56
+ n++;
57
+ }
51
58
  }
52
- oj_err_set(&err, oj_parse_error_class, "%s at line %d, column %d [%s:%d]", msg, n, col, file, line);
59
+ oj_err_set(&err,
60
+ oj_parse_error_class,
61
+ "%s at line %d, column %d [%s:%d]",
62
+ msg,
63
+ n,
64
+ col,
65
+ file,
66
+ line);
53
67
  rb_raise(err.clas, "%s", err.msg);
54
68
  }
data/ext/oj/err.h CHANGED
@@ -1,4 +1,5 @@
1
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.
2
3
 
3
4
  #ifndef OJ_ERR_H
4
5
  #define OJ_ERR_H
@@ -6,36 +7,44 @@
6
7
  #include "ruby.h"
7
8
  // Needed to silence 2.4.0 warnings.
8
9
  #ifndef NORETURN
9
- # define NORETURN(x) x
10
+ #define NORETURN(x) x
10
11
  #endif
11
12
 
12
- #define set_error(err, eclas, msg, json, current) _oj_err_set_with_location(err, eclas, msg, json, current, FILE, LINE)
13
+ #define set_error(err, eclas, msg, json, current) \
14
+ _oj_err_set_with_location(err, eclas, msg, json, current, FILE, LINE)
13
15
 
14
16
  typedef struct _err {
15
- VALUE clas;
16
- char msg[128];
17
- } *Err;
17
+ VALUE clas;
18
+ char msg[128];
19
+ } * Err;
18
20
 
19
- extern VALUE oj_parse_error_class;
21
+ extern VALUE oj_parse_error_class;
20
22
 
21
- extern void oj_err_set(Err e, VALUE clas, const char *format, ...);
22
- extern void _oj_err_set_with_location(Err err, VALUE eclas, const char *msg, const char *json, const char *current, const char* file, int line);
23
+ extern void oj_err_set(Err e, VALUE clas, const char *format, ...);
24
+ extern void _oj_err_set_with_location(Err err,
25
+ VALUE eclas,
26
+ const char *msg,
27
+ const char *json,
28
+ const char *current,
29
+ const char *file,
30
+ int line);
23
31
 
24
- NORETURN(extern void oj_err_raise(Err e));
32
+ NORETURN(extern void oj_err_raise(Err e));
25
33
 
26
34
  #define raise_error(msg, json, current) _oj_raise_error(msg, json, current, __FILE__, __LINE__)
27
35
 
28
- NORETURN(extern void _oj_raise_error(const char *msg, const char *json, const char *current, const char* file, int line));
36
+ NORETURN(extern void _oj_raise_error(const char *msg,
37
+ const char *json,
38
+ const char *current,
39
+ const char *file,
40
+ int line));
29
41
 
30
-
31
- inline static void
32
- err_init(Err e) {
42
+ inline static void err_init(Err e) {
33
43
  e->clas = Qnil;
34
44
  *e->msg = '\0';
35
45
  }
36
46
 
37
- inline static int
38
- err_has(Err e) {
47
+ inline static int err_has(Err e) {
39
48
  return (Qnil != e->clas);
40
49
  }
41
50
 
data/ext/oj/extconf.rb CHANGED
@@ -26,8 +26,9 @@ dflags = {
26
26
  have_func('rb_time_timespec')
27
27
  have_func('rb_ivar_count')
28
28
  have_func('rb_ivar_foreach')
29
+ # Support for compaction.
30
+ have_func('rb_gc_mark_movable')
29
31
  have_func('stpcpy')
30
- have_func('rb_data_object_wrap')
31
32
  have_func('pthread_mutex_init')
32
33
 
33
34
  dflags['OJ_DEBUG'] = true unless ENV['OJ_DEBUG'].nil?
data/ext/oj/fast.c CHANGED
@@ -1,98 +1,107 @@
1
1
  // Copyright (c) 2012 Peter Ohler. All rights reserved.
2
+ // Licensed under the MIT License. See LICENSE file in the project root for
3
+ // license details.
2
4
 
3
5
  #if !IS_WINDOWS
4
6
  #include <sys/resource.h> // for getrlimit() on linux
5
7
  #endif
6
- #include <stdlib.h>
8
+ #include <errno.h>
9
+ #include <math.h>
7
10
  #include <stdio.h>
11
+ #include <stdlib.h>
8
12
  #include <string.h>
9
- #include <math.h>
10
- #include <errno.h>
11
13
 
12
- #include "oj.h"
13
14
  #include "encode.h"
15
+ #include "oj.h"
14
16
 
15
17
  // maximum to allocate on the stack, arbitrary limit
16
- #define SMALL_XML 65536
17
- #define MAX_STACK 100
18
+ #define SMALL_JSON 65536
19
+ #define MAX_STACK 100
18
20
  //#define BATCH_SIZE (4096 / sizeof(struct _leaf) - 1)
19
- #define BATCH_SIZE 100
21
+ #define BATCH_SIZE 100
22
+
23
+ // Support for compaction
24
+ #ifdef HAVE_RB_GC_MARK_MOVABLE
25
+ #define mark rb_gc_mark_movable
26
+ #else
27
+ #define mark rb_gc_mark
28
+ #endif
20
29
 
21
30
  typedef struct _batch {
22
- struct _batch *next;
23
- int next_avail;
24
- struct _leaf leaves[BATCH_SIZE];
25
- } *Batch;
31
+ struct _batch *next;
32
+ int next_avail;
33
+ struct _leaf leaves[BATCH_SIZE];
34
+ } * Batch;
26
35
 
27
36
  typedef struct _doc {
28
- Leaf data;
29
- Leaf *where; // points to current location
30
- Leaf where_path[MAX_STACK]; // points to head of path
31
- char *json;
32
- unsigned long size; // number of leaves/branches in the doc
33
- VALUE self;
34
- Batch batches;
35
- struct _batch batch0;
36
- } *Doc;
37
+ Leaf data;
38
+ Leaf * where; // points to current location
39
+ Leaf where_path[MAX_STACK]; // points to head of path
40
+ char * json;
41
+ unsigned long size; // number of leaves/branches in the doc
42
+ VALUE self;
43
+ Batch batches;
44
+ struct _batch batch0;
45
+ } * Doc;
37
46
 
38
47
  typedef struct _parseInfo {
39
- char *str; /* buffer being read from */
40
- char *s; /* current position in buffer */
41
- Doc doc;
42
- void *stack_min;
43
- } *ParseInfo;
44
-
45
- static void leaf_init(Leaf leaf, int type);
46
- static Leaf leaf_new(Doc doc, int type);
47
- static void leaf_append_element(Leaf parent, Leaf element);
48
- static VALUE leaf_value(Doc doc, Leaf leaf);
49
- static void leaf_fixnum_value(Leaf leaf);
50
- static void leaf_float_value(Leaf leaf);
51
- static VALUE leaf_array_value(Doc doc, Leaf leaf);
52
- static VALUE leaf_hash_value(Doc doc, Leaf leaf);
53
-
54
- static Leaf read_next(ParseInfo pi);
55
- static Leaf read_obj(ParseInfo pi);
56
- static Leaf read_array(ParseInfo pi);
57
- static Leaf read_str(ParseInfo pi);
58
- static Leaf read_num(ParseInfo pi);
59
- static Leaf read_true(ParseInfo pi);
60
- static Leaf read_false(ParseInfo pi);
61
- static Leaf read_nil(ParseInfo pi);
62
- static void next_non_white(ParseInfo pi);
63
- static char* read_quoted_value(ParseInfo pi);
64
- static void skip_comment(ParseInfo pi);
65
-
66
- static VALUE protect_open_proc(VALUE x);
67
- static VALUE parse_json(VALUE clas, char *json, bool given, bool allocated);
68
- static void each_leaf(Doc doc, VALUE self);
69
- static int move_step(Doc doc, const char *path, int loc);
70
- static Leaf get_doc_leaf(Doc doc, const char *path);
71
- static Leaf get_leaf(Leaf *stack, Leaf *lp, const char *path);
72
- static void each_value(Doc doc, Leaf leaf);
73
-
74
- static void doc_init(Doc doc);
75
- static void doc_free(Doc doc);
76
- static VALUE doc_open(VALUE clas, VALUE str);
77
- static VALUE doc_open_file(VALUE clas, VALUE filename);
78
- static VALUE doc_where(VALUE self);
79
- static VALUE doc_local_key(VALUE self);
80
- static VALUE doc_home(VALUE self);
81
- static VALUE doc_type(int argc, VALUE *argv, VALUE self);
82
- static VALUE doc_fetch(int argc, VALUE *argv, VALUE self);
83
- static VALUE doc_each_leaf(int argc, VALUE *argv, VALUE self);
84
- static VALUE doc_move(VALUE self, VALUE str);
85
- static VALUE doc_each_child(int argc, VALUE *argv, VALUE self);
86
- static VALUE doc_each_value(int argc, VALUE *argv, VALUE self);
87
- static VALUE doc_dump(int argc, VALUE *argv, VALUE self);
88
- static VALUE doc_size(VALUE self);
89
-
90
- VALUE oj_doc_class = Qundef;
48
+ char *str; // buffer being read from
49
+ char *s; // current position in buffer
50
+ Doc doc;
51
+ void *stack_min;
52
+ } * ParseInfo;
53
+
54
+ static void leaf_init(Leaf leaf, int type);
55
+ static Leaf leaf_new(Doc doc, int type);
56
+ static void leaf_append_element(Leaf parent, Leaf element);
57
+ static VALUE leaf_value(Doc doc, Leaf leaf);
58
+ static void leaf_fixnum_value(Leaf leaf);
59
+ static void leaf_float_value(Leaf leaf);
60
+ static VALUE leaf_array_value(Doc doc, Leaf leaf);
61
+ static VALUE leaf_hash_value(Doc doc, Leaf leaf);
62
+
63
+ static Leaf read_next(ParseInfo pi);
64
+ static Leaf read_obj(ParseInfo pi);
65
+ static Leaf read_array(ParseInfo pi);
66
+ static Leaf read_str(ParseInfo pi);
67
+ static Leaf read_num(ParseInfo pi);
68
+ static Leaf read_true(ParseInfo pi);
69
+ static Leaf read_false(ParseInfo pi);
70
+ static Leaf read_nil(ParseInfo pi);
71
+ static void next_non_white(ParseInfo pi);
72
+ static char *read_quoted_value(ParseInfo pi);
73
+ static void skip_comment(ParseInfo pi);
74
+
75
+ static VALUE protect_open_proc(VALUE x);
76
+ static VALUE parse_json(VALUE clas, char *json, bool given, bool allocated);
77
+ static void each_leaf(Doc doc, VALUE self);
78
+ static int move_step(Doc doc, const char *path, int loc);
79
+ static Leaf get_doc_leaf(Doc doc, const char *path);
80
+ static Leaf get_leaf(Leaf *stack, Leaf *lp, const char *path);
81
+ static void each_value(Doc doc, Leaf leaf);
82
+
83
+ static void doc_init(Doc doc);
84
+ static void doc_free(Doc doc);
85
+ static VALUE doc_open(VALUE clas, VALUE str);
86
+ static VALUE doc_open_file(VALUE clas, VALUE filename);
87
+ static VALUE doc_where(VALUE self);
88
+ static VALUE doc_local_key(VALUE self);
89
+ static VALUE doc_home(VALUE self);
90
+ static VALUE doc_type(int argc, VALUE *argv, VALUE self);
91
+ static VALUE doc_fetch(int argc, VALUE *argv, VALUE self);
92
+ static VALUE doc_each_leaf(int argc, VALUE *argv, VALUE self);
93
+ static VALUE doc_move(VALUE self, VALUE str);
94
+ static VALUE doc_each_child(int argc, VALUE *argv, VALUE self);
95
+ static VALUE doc_each_value(int argc, VALUE *argv, VALUE self);
96
+ static VALUE doc_dump(int argc, VALUE *argv, VALUE self);
97
+ static VALUE doc_size(VALUE self);
98
+
99
+ VALUE oj_doc_class = Qundef;
91
100
 
92
101
  // This is only for CentOS 5.4 with Ruby 1.9.3-p0.
93
102
  #ifndef HAVE_STPCPY
94
103
  char *stpcpy(char *dest, const char *src) {
95
- size_t cnt = strlen(src);
104
+ size_t cnt = strlen(src);
96
105
 
97
106
  strcpy(dest, src);
98
107
 
@@ -100,89 +109,79 @@ char *stpcpy(char *dest, const char *src) {
100
109
  }
101
110
  #endif
102
111
 
103
- inline static void
104
- next_non_white(ParseInfo pi) {
112
+ inline static void next_non_white(ParseInfo pi) {
105
113
  for (; 1; pi->s++) {
106
- switch(*pi->s) {
107
- case ' ':
108
- case '\t':
109
- case '\f':
110
- case '\n':
111
- case '\r':
112
- break;
113
- case '/':
114
- skip_comment(pi);
115
- break;
116
- default:
117
- return;
118
- }
114
+ switch (*pi->s) {
115
+ case ' ':
116
+ case '\t':
117
+ case '\f':
118
+ case '\n':
119
+ case '\r': break;
120
+ case '/': skip_comment(pi); break;
121
+ default: return;
122
+ }
119
123
  }
120
124
  }
121
125
 
122
- inline static char*
123
- ulong_fill(char *s, size_t num) {
124
- char buf[32];
125
- char *b = buf + sizeof(buf) - 1;
126
+ inline static char *ulong_fill(char *s, size_t num) {
127
+ char buf[32];
128
+ char *b = buf + sizeof(buf) - 1;
126
129
 
127
130
  *b-- = '\0';
128
131
  for (; 0 < num; num /= 10, b--) {
129
- *b = (num % 10) + '0';
132
+ *b = (num % 10) + '0';
130
133
  }
131
134
  b++;
132
135
  if ('\0' == *b) {
133
- b--;
134
- *b = '0';
136
+ b--;
137
+ *b = '0';
135
138
  }
136
139
  for (; '\0' != *b; b++, s++) {
137
- *s = *b;
140
+ *s = *b;
138
141
  }
139
142
  return s;
140
143
  }
141
144
 
142
- inline static void
143
- leaf_init(Leaf leaf, int type) {
144
- leaf->next = 0;
145
- leaf->rtype = type;
145
+ inline static void leaf_init(Leaf leaf, int type) {
146
+ leaf->next = 0;
147
+ leaf->rtype = type;
146
148
  leaf->parent_type = T_NONE;
147
149
  switch (type) {
148
150
  case T_ARRAY:
149
151
  case T_HASH:
150
- leaf->elements = 0;
151
- leaf->value_type = COL_VAL;
152
- break;
152
+ leaf->elements = 0;
153
+ leaf->value_type = COL_VAL;
154
+ break;
153
155
  case T_NIL:
154
- leaf->value = Qnil;
155
- leaf->value_type = RUBY_VAL;
156
- break;
156
+ leaf->value = Qnil;
157
+ leaf->value_type = RUBY_VAL;
158
+ break;
157
159
  case T_TRUE:
158
- leaf->value = Qtrue;
159
- leaf->value_type = RUBY_VAL;
160
- break;
160
+ leaf->value = Qtrue;
161
+ leaf->value_type = RUBY_VAL;
162
+ break;
161
163
  case T_FALSE:
162
- leaf->value = Qfalse;
163
- leaf->value_type = RUBY_VAL;
164
- break;
164
+ leaf->value = Qfalse;
165
+ leaf->value_type = RUBY_VAL;
166
+ break;
165
167
  case T_FIXNUM:
166
168
  case T_FLOAT:
167
169
  case T_STRING:
168
- default:
169
- leaf->value_type = STR_VAL;
170
- break;
170
+ default: leaf->value_type = STR_VAL; break;
171
171
  }
172
172
  }
173
173
 
174
- inline static Leaf
175
- leaf_new(Doc doc, int type) {
176
- Leaf leaf;
174
+ inline static Leaf leaf_new(Doc doc, int type) {
175
+ Leaf leaf;
177
176
 
178
177
  if (0 == doc->batches || BATCH_SIZE == doc->batches->next_avail) {
179
- Batch b = ALLOC(struct _batch);
178
+ Batch b = ALLOC(struct _batch);
180
179
 
181
- // Initializes all leaves with a NO_VAL value_type
182
- memset(b, 0, sizeof(struct _batch));
183
- b->next = doc->batches;
184
- doc->batches = b;
185
- b->next_avail = 0;
180
+ // Initializes all leaves with a NO_VAL value_type
181
+ memset(b, 0, sizeof(struct _batch));
182
+ b->next = doc->batches;
183
+ doc->batches = b;
184
+ b->next_avail = 0;
186
185
  }
187
186
  leaf = &doc->batches->leaves[doc->batches->next_avail];
188
187
  doc->batches->next_avail++;
@@ -191,93 +190,73 @@ leaf_new(Doc doc, int type) {
191
190
  return leaf;
192
191
  }
193
192
 
194
- inline static void
195
- leaf_append_element(Leaf parent, Leaf element) {
193
+ inline static void leaf_append_element(Leaf parent, Leaf element) {
196
194
  if (0 == parent->elements) {
197
- parent->elements = element;
198
- element->next = element;
195
+ parent->elements = element;
196
+ element->next = element;
199
197
  } else {
200
- element->next = parent->elements->next;
201
- parent->elements->next = element;
202
- parent->elements = element;
198
+ element->next = parent->elements->next;
199
+ parent->elements->next = element;
200
+ parent->elements = element;
203
201
  }
204
202
  }
205
203
 
206
- static VALUE
207
- leaf_value(Doc doc, Leaf leaf) {
204
+ static VALUE leaf_value(Doc doc, Leaf leaf) {
208
205
  if (RUBY_VAL != leaf->value_type) {
209
- switch (leaf->rtype) {
210
- case T_NIL:
211
- leaf->value = Qnil;
212
- break;
213
- case T_TRUE:
214
- leaf->value = Qtrue;
215
- break;
216
- case T_FALSE:
217
- leaf->value = Qfalse;
218
- break;
219
- case T_FIXNUM:
220
- leaf_fixnum_value(leaf);
221
- break;
222
- case T_FLOAT:
223
- leaf_float_value(leaf);
224
- break;
225
- case T_STRING:
226
- leaf->value = rb_str_new2(leaf->str);
227
- leaf->value = oj_encode(leaf->value);
228
- leaf->value_type = RUBY_VAL;
229
- break;
230
- case T_ARRAY:
231
- return leaf_array_value(doc, leaf);
232
- break;
233
- case T_HASH:
234
- return leaf_hash_value(doc, leaf);
235
- break;
236
- default:
237
- rb_raise(rb_const_get_at(Oj, rb_intern("Error")), "Unexpected type %02x.", leaf->rtype);
238
- break;
239
- }
206
+ switch (leaf->rtype) {
207
+ case T_NIL: leaf->value = Qnil; break;
208
+ case T_TRUE: leaf->value = Qtrue; break;
209
+ case T_FALSE: leaf->value = Qfalse; break;
210
+ case T_FIXNUM: leaf_fixnum_value(leaf); break;
211
+ case T_FLOAT: leaf_float_value(leaf); break;
212
+ case T_STRING:
213
+ leaf->value = rb_str_new2(leaf->str);
214
+ leaf->value = oj_encode(leaf->value);
215
+ leaf->value_type = RUBY_VAL;
216
+ break;
217
+ case T_ARRAY: return leaf_array_value(doc, leaf); break;
218
+ case T_HASH: return leaf_hash_value(doc, leaf); break;
219
+ default:
220
+ rb_raise(rb_const_get_at(Oj, rb_intern("Error")), "Unexpected type %02x.", leaf->rtype);
221
+ break;
222
+ }
240
223
  }
241
224
  return leaf->value;
242
225
  }
243
226
 
244
- inline static Doc
245
- self_doc(VALUE self) {
246
- Doc doc = DATA_PTR(self);
227
+ inline static Doc self_doc(VALUE self) {
228
+ Doc doc = DATA_PTR(self);
247
229
 
248
230
  if (0 == doc) {
249
- rb_raise(rb_eIOError, "Document already closed or not open.");
231
+ rb_raise(rb_eIOError, "Document already closed or not open.");
250
232
  }
251
233
  return doc;
252
234
  }
253
235
 
254
- static void
255
- skip_comment(ParseInfo pi) {
256
- pi->s++; // skip first /
236
+ static void skip_comment(ParseInfo pi) {
237
+ pi->s++; // skip first /
257
238
  if ('*' == *pi->s) {
258
- pi->s++;
259
- for (; '\0' != *pi->s; pi->s++) {
260
- if ('*' == *pi->s && '/' == *(pi->s + 1)) {
261
- pi->s++;
262
- return;
263
- } else if ('\0' == *pi->s) {
264
- raise_error("comment not terminated", pi->str, pi->s);
265
- }
266
- }
239
+ pi->s++;
240
+ for (; '\0' != *pi->s; pi->s++) {
241
+ if ('*' == *pi->s && '/' == *(pi->s + 1)) {
242
+ pi->s++;
243
+ return;
244
+ } else if ('\0' == *pi->s) {
245
+ raise_error("comment not terminated", pi->str, pi->s);
246
+ }
247
+ }
267
248
  } else if ('/' == *pi->s) {
268
- for (; 1; pi->s++) {
269
- switch (*pi->s) {
270
- case '\n':
271
- case '\r':
272
- case '\f':
273
- case '\0':
274
- return;
275
- default:
276
- break;
277
- }
278
- }
249
+ for (; 1; pi->s++) {
250
+ switch (*pi->s) {
251
+ case '\n':
252
+ case '\r':
253
+ case '\f':
254
+ case '\0': return;
255
+ default: break;
256
+ }
257
+ }
279
258
  } else {
280
- raise_error("invalid comment", pi->str, pi->s);
259
+ raise_error("invalid comment", pi->str, pi->s);
281
260
  }
282
261
  }
283
262
 
@@ -287,100 +266,88 @@ skip_comment(ParseInfo pi) {
287
266
  #define NUM_MAX (FIXNUM_MAX >> 8)
288
267
  #endif
289
268
 
290
-
291
- static void
292
- leaf_fixnum_value(Leaf leaf) {
293
- char *s = leaf->str;
294
- int64_t n = 0;
295
- int neg = 0;
296
- int big = 0;
269
+ static void leaf_fixnum_value(Leaf leaf) {
270
+ char * s = leaf->str;
271
+ int64_t n = 0;
272
+ int neg = 0;
273
+ int big = 0;
297
274
 
298
275
  if ('-' == *s) {
299
- s++;
300
- neg = 1;
276
+ s++;
277
+ neg = 1;
301
278
  } else if ('+' == *s) {
302
- s++;
279
+ s++;
303
280
  }
304
281
  for (; '0' <= *s && *s <= '9'; s++) {
305
- n = n * 10 + (*s - '0');
306
- if (NUM_MAX <= n) {
307
- big = 1;
308
- }
282
+ n = n * 10 + (*s - '0');
283
+ if (NUM_MAX <= n) {
284
+ big = 1;
285
+ }
309
286
  }
310
287
  if (big) {
311
- char c = *s;
288
+ char c = *s;
312
289
 
313
- *s = '\0';
314
- leaf->value = rb_cstr_to_inum(leaf->str, 10, 0);
315
- *s = c;
290
+ *s = '\0';
291
+ leaf->value = rb_cstr_to_inum(leaf->str, 10, 0);
292
+ *s = c;
316
293
  } else {
317
- if (neg) {
318
- n = -n;
319
- }
320
- leaf->value = rb_ll2inum(n);
294
+ if (neg) {
295
+ n = -n;
296
+ }
297
+ leaf->value = rb_ll2inum(n);
321
298
  }
322
299
  leaf->value_type = RUBY_VAL;
323
300
  }
324
301
 
325
- static void
326
- leaf_float_value(Leaf leaf) {
327
- leaf->value = rb_float_new(rb_cstr_to_dbl(leaf->str, 1));
302
+ static void leaf_float_value(Leaf leaf) {
303
+ leaf->value = rb_float_new(rb_cstr_to_dbl(leaf->str, 1));
328
304
  leaf->value_type = RUBY_VAL;
329
305
  }
330
306
 
331
- static VALUE
332
- leaf_array_value(Doc doc, Leaf leaf) {
333
- volatile VALUE a = rb_ary_new();
307
+ static VALUE leaf_array_value(Doc doc, Leaf leaf) {
308
+ volatile VALUE a = rb_ary_new();
334
309
 
335
310
  if (0 != leaf->elements) {
336
- Leaf first = leaf->elements->next;
337
- Leaf e = first;
311
+ Leaf first = leaf->elements->next;
312
+ Leaf e = first;
338
313
 
339
- do {
340
- rb_ary_push(a, leaf_value(doc, e));
341
- e = e->next;
342
- } while (e != first);
314
+ do {
315
+ rb_ary_push(a, leaf_value(doc, e));
316
+ e = e->next;
317
+ } while (e != first);
343
318
  }
344
319
  return a;
345
320
  }
346
321
 
347
- static VALUE
348
- leaf_hash_value(Doc doc, Leaf leaf) {
349
- volatile VALUE h = rb_hash_new();
322
+ static VALUE leaf_hash_value(Doc doc, Leaf leaf) {
323
+ volatile VALUE h = rb_hash_new();
350
324
 
351
325
  if (0 != leaf->elements) {
352
- Leaf first = leaf->elements->next;
353
- Leaf e = first;
354
- volatile VALUE key;
326
+ Leaf first = leaf->elements->next;
327
+ Leaf e = first;
328
+ volatile VALUE key;
355
329
 
356
- do {
357
- key = rb_str_new2(e->key);
358
- key = oj_encode(key);
359
- rb_hash_aset(h, key, leaf_value(doc, e));
360
- e = e->next;
361
- } while (e != first);
330
+ do {
331
+ key = rb_str_new2(e->key);
332
+ key = oj_encode(key);
333
+ rb_hash_aset(h, key, leaf_value(doc, e));
334
+ e = e->next;
335
+ } while (e != first);
362
336
  }
363
337
  return h;
364
338
  }
365
339
 
366
- static Leaf
367
- read_next(ParseInfo pi) {
368
- Leaf leaf = 0;
340
+ static Leaf read_next(ParseInfo pi) {
341
+ Leaf leaf = 0;
369
342
 
370
- if ((void*)&leaf < pi->stack_min) {
371
- rb_raise(rb_eSysStackError, "JSON is too deeply nested");
343
+ if ((void *)&leaf < pi->stack_min) {
344
+ rb_raise(rb_eSysStackError, "JSON is too deeply nested");
372
345
  }
373
- next_non_white(pi); // skip white space
346
+ next_non_white(pi); // skip white space
374
347
  switch (*pi->s) {
375
- case '{':
376
- leaf = read_obj(pi);
377
- break;
378
- case '[':
379
- leaf = read_array(pi);
380
- break;
381
- case '"':
382
- leaf = read_str(pi);
383
- break;
348
+ case '{': leaf = read_obj(pi); break;
349
+ case '[': leaf = read_array(pi); break;
350
+ case '"': leaf = read_str(pi); break;
384
351
  case '+':
385
352
  case '-':
386
353
  case '0':
@@ -392,716 +359,727 @@ read_next(ParseInfo pi) {
392
359
  case '6':
393
360
  case '7':
394
361
  case '8':
395
- case '9':
396
- leaf = read_num(pi);
397
- break;
398
- case 't':
399
- leaf = read_true(pi);
400
- break;
401
- case 'f':
402
- leaf = read_false(pi);
403
- break;
404
- case 'n':
405
- leaf = read_nil(pi);
406
- break;
362
+ case '9': leaf = read_num(pi); break;
363
+ case 't': leaf = read_true(pi); break;
364
+ case 'f': leaf = read_false(pi); break;
365
+ case 'n': leaf = read_nil(pi); break;
407
366
  case '\0':
408
- default:
409
- break; // returns 0
367
+ default: break; // returns 0
410
368
  }
411
369
  pi->doc->size++;
412
370
 
413
371
  return leaf;
414
372
  }
415
373
 
416
- static Leaf
417
- read_obj(ParseInfo pi) {
418
- Leaf h = leaf_new(pi->doc, T_HASH);
419
- char *end;
420
- const char *key = 0;
421
- Leaf val = 0;
374
+ static Leaf read_obj(ParseInfo pi) {
375
+ Leaf h = leaf_new(pi->doc, T_HASH);
376
+ char * end;
377
+ const char *key = 0;
378
+ Leaf val = 0;
422
379
 
423
380
  pi->s++;
424
381
  next_non_white(pi);
425
382
  if ('}' == *pi->s) {
426
- pi->s++;
427
- return h;
383
+ pi->s++;
384
+ return h;
428
385
  }
429
386
  while (1) {
430
- next_non_white(pi);
431
- key = 0;
432
- val = 0;
433
- if ('"' != *pi->s || 0 == (key = read_quoted_value(pi))) {
434
- raise_error("unexpected character", pi->str, pi->s);
435
- }
436
- next_non_white(pi);
437
- if (':' == *pi->s) {
438
- pi->s++;
439
- } else {
440
- raise_error("invalid format, expected :", pi->str, pi->s);
441
- }
442
- if (0 == (val = read_next(pi))) {
443
- //printf("*** '%s'\n", pi->s);
444
- raise_error("unexpected character", pi->str, pi->s);
445
- }
446
- end = pi->s;
447
- val->key = key;
448
- val->parent_type = T_HASH;
449
- leaf_append_element(h, val);
450
- next_non_white(pi);
451
- if ('}' == *pi->s) {
452
- pi->s++;
453
- *end = '\0';
454
- break;
455
- } else if (',' == *pi->s) {
456
- pi->s++;
457
- } else {
458
- //printf("*** '%s'\n", pi->s);
459
- raise_error("invalid format, expected , or } while in an object", pi->str, pi->s);
460
- }
461
- *end = '\0';
387
+ next_non_white(pi);
388
+ key = 0;
389
+ val = 0;
390
+ if ('"' != *pi->s || 0 == (key = read_quoted_value(pi))) {
391
+ raise_error("unexpected character", pi->str, pi->s);
392
+ }
393
+ next_non_white(pi);
394
+ if (':' == *pi->s) {
395
+ pi->s++;
396
+ } else {
397
+ raise_error("invalid format, expected :", pi->str, pi->s);
398
+ }
399
+ if (0 == (val = read_next(pi))) {
400
+ // printf("*** '%s'\n", pi->s);
401
+ raise_error("unexpected character", pi->str, pi->s);
402
+ }
403
+ end = pi->s;
404
+ val->key = key;
405
+ val->parent_type = T_HASH;
406
+ leaf_append_element(h, val);
407
+ next_non_white(pi);
408
+ if ('}' == *pi->s) {
409
+ pi->s++;
410
+ *end = '\0';
411
+ break;
412
+ } else if (',' == *pi->s) {
413
+ pi->s++;
414
+ } else {
415
+ // printf("*** '%s'\n", pi->s);
416
+ raise_error("invalid format, expected , or } while in an object", pi->str, pi->s);
417
+ }
418
+ *end = '\0';
462
419
  }
463
420
  return h;
464
421
  }
465
422
 
466
- static Leaf
467
- read_array(ParseInfo pi) {
468
- Leaf a = leaf_new(pi->doc, T_ARRAY);
469
- Leaf e;
470
- char *end;
471
- int cnt = 0;
423
+ static Leaf read_array(ParseInfo pi) {
424
+ Leaf a = leaf_new(pi->doc, T_ARRAY);
425
+ Leaf e;
426
+ char *end;
427
+ int cnt = 0;
472
428
 
473
429
  pi->s++;
474
430
  next_non_white(pi);
475
431
  if (']' == *pi->s) {
476
- pi->s++;
477
- return a;
432
+ pi->s++;
433
+ return a;
478
434
  }
479
435
  while (1) {
480
- next_non_white(pi);
481
- if (0 == (e = read_next(pi))) {
482
- raise_error("unexpected character", pi->str, pi->s);
483
- }
484
- cnt++;
485
- e->index = cnt;
486
- e->parent_type = T_ARRAY;
487
- leaf_append_element(a, e);
488
- end = pi->s;
489
- next_non_white(pi);
490
- if (',' == *pi->s) {
491
- pi->s++;
492
- } else if (']' == *pi->s) {
493
- pi->s++;
494
- *end = '\0';
495
- break;
496
- } else {
497
- raise_error("invalid format, expected , or ] while in an array", pi->str, pi->s);
498
- }
499
- *end = '\0';
436
+ next_non_white(pi);
437
+ if (0 == (e = read_next(pi))) {
438
+ raise_error("unexpected character", pi->str, pi->s);
439
+ }
440
+ cnt++;
441
+ e->index = cnt;
442
+ e->parent_type = T_ARRAY;
443
+ leaf_append_element(a, e);
444
+ end = pi->s;
445
+ next_non_white(pi);
446
+ if (',' == *pi->s) {
447
+ pi->s++;
448
+ } else if (']' == *pi->s) {
449
+ pi->s++;
450
+ *end = '\0';
451
+ break;
452
+ } else {
453
+ raise_error("invalid format, expected , or ] while in an array", pi->str, pi->s);
454
+ }
455
+ *end = '\0';
500
456
  }
501
457
  return a;
502
458
  }
503
459
 
504
- static Leaf
505
- read_str(ParseInfo pi) {
506
- Leaf leaf = leaf_new(pi->doc, T_STRING);
460
+ static Leaf read_str(ParseInfo pi) {
461
+ Leaf leaf = leaf_new(pi->doc, T_STRING);
507
462
 
508
463
  leaf->str = read_quoted_value(pi);
509
464
 
510
465
  return leaf;
511
466
  }
512
467
 
513
- static Leaf
514
- read_num(ParseInfo pi) {
515
- char *start = pi->s;
516
- int type = T_FIXNUM;
517
- Leaf leaf;
468
+ static Leaf read_num(ParseInfo pi) {
469
+ char *start = pi->s;
470
+ int type = T_FIXNUM;
471
+ Leaf leaf;
518
472
 
519
473
  if ('-' == *pi->s) {
520
- pi->s++;
474
+ pi->s++;
521
475
  }
522
476
  // digits
523
477
  for (; '0' <= *pi->s && *pi->s <= '9'; pi->s++) {
524
478
  }
525
479
  if ('.' == *pi->s) {
526
- type = T_FLOAT;
527
- pi->s++;
528
- for (; '0' <= *pi->s && *pi->s <= '9'; pi->s++) {
529
- }
480
+ type = T_FLOAT;
481
+ pi->s++;
482
+ for (; '0' <= *pi->s && *pi->s <= '9'; pi->s++) {
483
+ }
530
484
  }
531
485
  if ('e' == *pi->s || 'E' == *pi->s) {
532
- pi->s++;
533
- if ('-' == *pi->s || '+' == *pi->s) {
534
- pi->s++;
535
- }
536
- for (; '0' <= *pi->s && *pi->s <= '9'; pi->s++) {
537
- }
538
- }
539
- leaf = leaf_new(pi->doc, type);
486
+ pi->s++;
487
+ if ('-' == *pi->s || '+' == *pi->s) {
488
+ pi->s++;
489
+ }
490
+ for (; '0' <= *pi->s && *pi->s <= '9'; pi->s++) {
491
+ }
492
+ }
493
+ leaf = leaf_new(pi->doc, type);
540
494
  leaf->str = start;
541
495
 
542
496
  return leaf;
543
497
  }
544
498
 
545
- static Leaf
546
- read_true(ParseInfo pi) {
547
- Leaf leaf = leaf_new(pi->doc, T_TRUE);
499
+ static Leaf read_true(ParseInfo pi) {
500
+ Leaf leaf = leaf_new(pi->doc, T_TRUE);
548
501
 
549
502
  pi->s++;
550
503
  if ('r' != *pi->s || 'u' != *(pi->s + 1) || 'e' != *(pi->s + 2)) {
551
- raise_error("invalid format, expected 'true'", pi->str, pi->s);
504
+ raise_error("invalid format, expected 'true'", pi->str, pi->s);
552
505
  }
553
506
  pi->s += 3;
554
507
 
555
508
  return leaf;
556
509
  }
557
510
 
558
- static Leaf
559
- read_false(ParseInfo pi) {
560
- Leaf leaf = leaf_new(pi->doc, T_FALSE);
511
+ static Leaf read_false(ParseInfo pi) {
512
+ Leaf leaf = leaf_new(pi->doc, T_FALSE);
561
513
 
562
514
  pi->s++;
563
515
  if ('a' != *pi->s || 'l' != *(pi->s + 1) || 's' != *(pi->s + 2) || 'e' != *(pi->s + 3)) {
564
- raise_error("invalid format, expected 'false'", pi->str, pi->s);
516
+ raise_error("invalid format, expected 'false'", pi->str, pi->s);
565
517
  }
566
518
  pi->s += 4;
567
519
 
568
520
  return leaf;
569
521
  }
570
522
 
571
- static Leaf
572
- read_nil(ParseInfo pi) {
573
- Leaf leaf = leaf_new(pi->doc, T_NIL);
523
+ static Leaf read_nil(ParseInfo pi) {
524
+ Leaf leaf = leaf_new(pi->doc, T_NIL);
574
525
 
575
526
  pi->s++;
576
527
  if ('u' != *pi->s || 'l' != *(pi->s + 1) || 'l' != *(pi->s + 2)) {
577
- raise_error("invalid format, expected 'nil'", pi->str, pi->s);
528
+ raise_error("invalid format, expected 'nil'", pi->str, pi->s);
578
529
  }
579
530
  pi->s += 3;
580
531
 
581
532
  return leaf;
582
533
  }
583
534
 
584
- static uint32_t
585
- read_4hex(ParseInfo pi, const char *h) {
586
- uint32_t b = 0;
587
- int i;
535
+ static uint32_t read_4hex(ParseInfo pi, const char *h) {
536
+ uint32_t b = 0;
537
+ int i;
588
538
 
589
539
  for (i = 0; i < 4; i++, h++) {
590
- b = b << 4;
591
- if ('0' <= *h && *h <= '9') {
592
- b += *h - '0';
593
- } else if ('A' <= *h && *h <= 'F') {
594
- b += *h - 'A' + 10;
595
- } else if ('a' <= *h && *h <= 'f') {
596
- b += *h - 'a' + 10;
597
- } else {
598
- raise_error("invalid hex character", pi->str, pi->s);
599
- }
540
+ b = b << 4;
541
+ if ('0' <= *h && *h <= '9') {
542
+ b += *h - '0';
543
+ } else if ('A' <= *h && *h <= 'F') {
544
+ b += *h - 'A' + 10;
545
+ } else if ('a' <= *h && *h <= 'f') {
546
+ b += *h - 'a' + 10;
547
+ } else {
548
+ raise_error("invalid hex character", pi->str, pi->s);
549
+ }
600
550
  }
601
551
  return b;
602
552
  }
603
553
 
604
- static char*
605
- unicode_to_chars(ParseInfo pi, char *t, uint32_t code) {
554
+ static char *unicode_to_chars(ParseInfo pi, char *t, uint32_t code) {
606
555
  if (0x0000007F >= code) {
607
- *t++ = (char)code;
556
+ *t++ = (char)code;
608
557
  } else if (0x000007FF >= code) {
609
- *t++ = 0xC0 | (code >> 6);
610
- *t++ = 0x80 | (0x3F & code);
558
+ *t++ = 0xC0 | (code >> 6);
559
+ *t++ = 0x80 | (0x3F & code);
611
560
  } else if (0x0000FFFF >= code) {
612
- *t++ = 0xE0 | (code >> 12);
613
- *t++ = 0x80 | ((code >> 6) & 0x3F);
614
- *t++ = 0x80 | (0x3F & code);
561
+ *t++ = 0xE0 | (code >> 12);
562
+ *t++ = 0x80 | ((code >> 6) & 0x3F);
563
+ *t++ = 0x80 | (0x3F & code);
615
564
  } else if (0x001FFFFF >= code) {
616
- *t++ = 0xF0 | (code >> 18);
617
- *t++ = 0x80 | ((code >> 12) & 0x3F);
618
- *t++ = 0x80 | ((code >> 6) & 0x3F);
619
- *t++ = 0x80 | (0x3F & code);
565
+ *t++ = 0xF0 | (code >> 18);
566
+ *t++ = 0x80 | ((code >> 12) & 0x3F);
567
+ *t++ = 0x80 | ((code >> 6) & 0x3F);
568
+ *t++ = 0x80 | (0x3F & code);
620
569
  } else if (0x03FFFFFF >= code) {
621
- *t++ = 0xF8 | (code >> 24);
622
- *t++ = 0x80 | ((code >> 18) & 0x3F);
623
- *t++ = 0x80 | ((code >> 12) & 0x3F);
624
- *t++ = 0x80 | ((code >> 6) & 0x3F);
625
- *t++ = 0x80 | (0x3F & code);
570
+ *t++ = 0xF8 | (code >> 24);
571
+ *t++ = 0x80 | ((code >> 18) & 0x3F);
572
+ *t++ = 0x80 | ((code >> 12) & 0x3F);
573
+ *t++ = 0x80 | ((code >> 6) & 0x3F);
574
+ *t++ = 0x80 | (0x3F & code);
626
575
  } else if (0x7FFFFFFF >= code) {
627
- *t++ = 0xFC | (code >> 30);
628
- *t++ = 0x80 | ((code >> 24) & 0x3F);
629
- *t++ = 0x80 | ((code >> 18) & 0x3F);
630
- *t++ = 0x80 | ((code >> 12) & 0x3F);
631
- *t++ = 0x80 | ((code >> 6) & 0x3F);
632
- *t++ = 0x80 | (0x3F & code);
576
+ *t++ = 0xFC | (code >> 30);
577
+ *t++ = 0x80 | ((code >> 24) & 0x3F);
578
+ *t++ = 0x80 | ((code >> 18) & 0x3F);
579
+ *t++ = 0x80 | ((code >> 12) & 0x3F);
580
+ *t++ = 0x80 | ((code >> 6) & 0x3F);
581
+ *t++ = 0x80 | (0x3F & code);
633
582
  } else {
634
- raise_error("invalid Unicode character", pi->str, pi->s);
583
+ raise_error("invalid Unicode character", pi->str, pi->s);
635
584
  }
636
585
  return t;
637
586
  }
638
587
 
639
- /* Assume the value starts immediately and goes until the quote character is
640
- * reached again. Do not read the character after the terminating quote.
641
- */
642
- static char*
643
- read_quoted_value(ParseInfo pi) {
644
- char *value = 0;
645
- char *h = pi->s; // head
646
- char *t = h; // tail
588
+ // Assume the value starts immediately and goes until the quote character is
589
+ // reached again. Do not read the character after the terminating quote.
590
+ static char *read_quoted_value(ParseInfo pi) {
591
+ char *value = 0;
592
+ char *h = pi->s; // head
593
+ char *t = h; // tail
647
594
 
648
- h++; // skip quote character
595
+ h++; // skip quote character
649
596
  t++;
650
597
  value = h;
651
598
  for (; '"' != *h; h++, t++) {
652
- if ('\0' == *h) {
653
- pi->s = h;
654
- raise_error("quoted string not terminated", pi->str, pi->s);
655
- } else if ('\\' == *h) {
656
- h++;
657
- switch (*h) {
658
- case 'n': *t = '\n'; break;
659
- case 'r': *t = '\r'; break;
660
- case 't': *t = '\t'; break;
661
- case 'f': *t = '\f'; break;
662
- case 'b': *t = '\b'; break;
663
- case '"': *t = '"'; break;
664
- case '/': *t = '/'; break;
665
- case '\\': *t = '\\'; break;
666
- case 'u': {
667
- uint32_t code;
668
-
669
- h++;
670
- code = read_4hex(pi, h);
671
- h += 3;
672
- if (0x0000D800 <= code && code <= 0x0000DFFF) {
673
- uint32_t c1 = (code - 0x0000D800) & 0x000003FF;
674
- uint32_t c2;
675
-
676
- h++;
677
- if ('\\' != *h || 'u' != *(h + 1)) {
678
- pi->s = h;
679
- raise_error("invalid escaped character", pi->str, pi->s);
680
- }
681
- h += 2;
682
- c2 = read_4hex(pi, h);
683
- h += 3;
684
- c2 = (c2 - 0x0000DC00) & 0x000003FF;
685
- code = ((c1 << 10) | c2) + 0x00010000;
686
- }
687
- t = unicode_to_chars(pi, t, code);
688
- t--;
689
- break;
690
- }
691
- default:
692
- pi->s = h;
693
- raise_error("invalid escaped character", pi->str, pi->s);
694
- break;
695
- }
696
- } else if (t != h) {
697
- *t = *h;
698
- }
699
- }
700
- *t = '\0'; // terminate value
599
+ if ('\0' == *h) {
600
+ pi->s = h;
601
+ raise_error("quoted string not terminated", pi->str, pi->s);
602
+ } else if ('\\' == *h) {
603
+ h++;
604
+ switch (*h) {
605
+ case 'n': *t = '\n'; break;
606
+ case 'r': *t = '\r'; break;
607
+ case 't': *t = '\t'; break;
608
+ case 'f': *t = '\f'; break;
609
+ case 'b': *t = '\b'; break;
610
+ case '"': *t = '"'; break;
611
+ case '/': *t = '/'; break;
612
+ case '\\': *t = '\\'; break;
613
+ case 'u': {
614
+ uint32_t code;
615
+
616
+ h++;
617
+ code = read_4hex(pi, h);
618
+ h += 3;
619
+ if (0x0000D800 <= code && code <= 0x0000DFFF) {
620
+ uint32_t c1 = (code - 0x0000D800) & 0x000003FF;
621
+ uint32_t c2;
622
+
623
+ h++;
624
+ if ('\\' != *h || 'u' != *(h + 1)) {
625
+ pi->s = h;
626
+ raise_error("invalid escaped character", pi->str, pi->s);
627
+ }
628
+ h += 2;
629
+ c2 = read_4hex(pi, h);
630
+ h += 3;
631
+ c2 = (c2 - 0x0000DC00) & 0x000003FF;
632
+ code = ((c1 << 10) | c2) + 0x00010000;
633
+ }
634
+ t = unicode_to_chars(pi, t, code);
635
+ t--;
636
+ break;
637
+ }
638
+ default:
639
+ pi->s = h;
640
+ raise_error("invalid escaped character", pi->str, pi->s);
641
+ break;
642
+ }
643
+ } else if (t != h) {
644
+ *t = *h;
645
+ }
646
+ }
647
+ *t = '\0'; // terminate value
701
648
  pi->s = h + 1;
702
649
 
703
650
  return value;
704
651
  }
705
652
 
706
653
  // doc support functions
707
- inline static void
708
- doc_init(Doc doc) {
654
+ inline static void doc_init(Doc doc) {
709
655
  memset(doc, 0, sizeof(struct _doc));
710
- doc->where = doc->where_path;
711
- doc->self = Qundef;
656
+ doc->where = doc->where_path;
657
+ doc->self = Qundef;
712
658
  doc->batches = &doc->batch0;
713
659
  }
714
660
 
715
- static void
716
- doc_free(Doc doc) {
661
+ static void doc_free(Doc doc) {
717
662
  if (0 != doc) {
718
- Batch b;
663
+ Batch b;
719
664
 
720
- while (0 != (b = doc->batches)) {
721
- doc->batches = doc->batches->next;
722
- if (&doc->batch0 != b) {
723
- xfree(b);
724
- }
725
- }
726
- //xfree(f);
665
+ while (0 != (b = doc->batches)) {
666
+ doc->batches = doc->batches->next;
667
+ if (&doc->batch0 != b) {
668
+ xfree(b);
669
+ }
670
+ }
671
+ // xfree(f);
727
672
  }
728
673
  }
729
674
 
730
- static VALUE
731
- protect_open_proc(VALUE x) {
732
- ParseInfo pi = (ParseInfo)x;
675
+ static VALUE protect_open_proc(VALUE x) {
676
+ ParseInfo pi = (ParseInfo)x;
733
677
 
734
- pi->doc->data = read_next(pi); // parse
678
+ pi->doc->data = read_next(pi); // parse
735
679
  *pi->doc->where = pi->doc->data;
736
- pi->doc->where = pi->doc->where_path;
680
+ pi->doc->where = pi->doc->where_path;
737
681
  if (rb_block_given_p()) {
738
- return rb_yield(pi->doc->self); // caller processing
682
+ return rb_yield(pi->doc->self); // caller processing
739
683
  }
740
684
  return Qnil;
741
685
  }
742
686
 
743
- static void
744
- free_doc_cb(void *x) {
745
- Doc doc = (Doc)x;
687
+ static void free_doc_cb(void *x) {
688
+ Doc doc = (Doc)x;
746
689
 
747
690
  if (0 != doc) {
748
- xfree(doc->json);
749
- doc_free(doc);
691
+ xfree(doc->json);
692
+ doc_free(doc);
750
693
  }
751
694
  }
752
695
 
753
- static void
754
- mark_leaf(Leaf leaf) {
696
+ static void mark_leaf(Leaf leaf) {
755
697
  switch (leaf->value_type) {
756
698
  case COL_VAL:
757
- if (NULL != leaf->elements) {
758
- Leaf first = leaf->elements->next;
759
- Leaf e = first;
760
-
761
- do {
762
- mark_leaf(e);
763
- e = e->next;
764
- } while (e != first);
765
- }
766
- break;
767
- case RUBY_VAL:
768
- rb_gc_mark(leaf->value);
769
- break;
770
-
771
- default:
772
- break;
699
+ if (NULL != leaf->elements) {
700
+ Leaf first = leaf->elements->next;
701
+ Leaf e = first;
702
+
703
+ do {
704
+ mark_leaf(e);
705
+ e = e->next;
706
+ } while (e != first);
707
+ }
708
+ break;
709
+ case RUBY_VAL: mark(leaf->value); break;
710
+
711
+ default: break;
773
712
  }
774
713
  }
775
714
 
776
- static void
777
- mark_doc(void *ptr) {
715
+ static void mark_doc(void *ptr) {
778
716
  if (NULL != ptr) {
779
- Doc doc = (Doc)ptr;
717
+ Doc doc = (Doc)ptr;
780
718
 
781
- rb_gc_mark(doc->self);
782
- mark_leaf(doc->data);
719
+ mark(doc->self);
720
+ mark_leaf(doc->data);
721
+ }
722
+ }
723
+ #ifdef HAVE_RB_GC_MARK_MOVABLE
724
+ static void compact_leaf(Leaf leaf) {
725
+ switch (leaf->value_type) {
726
+ case COL_VAL:
727
+ if (NULL != leaf->elements) {
728
+ Leaf first = leaf->elements->next;
729
+ Leaf e = first;
730
+
731
+ do {
732
+ compact_leaf(e);
733
+ e = e->next;
734
+ } while (e != first);
735
+ }
736
+ break;
737
+ case RUBY_VAL: leaf->value = rb_gc_location(leaf->value); break;
738
+
739
+ default: break;
783
740
  }
784
741
  }
785
742
 
786
- static VALUE
787
- parse_json(VALUE clas, char *json, bool given, bool allocated) {
788
- struct _parseInfo pi;
789
- volatile VALUE result = Qnil;
790
- Doc doc;
791
- int ex = 0;
792
- volatile VALUE self;
743
+ static void compact_doc(void *ptr) {
744
+ Doc doc = (Doc)ptr;
745
+
746
+ if (doc) {
747
+ doc->self = rb_gc_location(doc->self);
748
+ compact_leaf(doc->data);
749
+ }
750
+ }
751
+ #endif
752
+
753
+ static const rb_data_type_t oj_doc_type = {
754
+ "Oj/doc",
755
+ {
756
+ mark_doc,
757
+ free_doc_cb,
758
+ NULL,
759
+ #ifdef HAVE_RB_GC_MARK_MOVABLE
760
+ compact_doc,
761
+ #endif
762
+ },
763
+ 0,
764
+ 0,
765
+ };
766
+
767
+ static VALUE parse_json(VALUE clas, char *json, bool given, bool allocated) {
768
+ struct _parseInfo pi;
769
+ volatile VALUE result = Qnil;
770
+ Doc doc;
771
+ int ex = 0;
772
+ volatile VALUE self;
793
773
 
794
774
  // TBD are both needed? is stack allocation ever needed?
795
775
 
796
776
  if (given) {
797
- doc = ALLOCA_N(struct _doc, 1);
777
+ doc = ALLOCA_N(struct _doc, 1);
798
778
  } else {
799
- doc = ALLOC(struct _doc);
779
+ doc = ALLOC(struct _doc);
800
780
  }
801
- /* skip UTF-8 BOM if present */
781
+ // skip UTF-8 BOM if present
802
782
  if (0xEF == (uint8_t)*json && 0xBB == (uint8_t)json[1] && 0xBF == (uint8_t)json[2]) {
803
- pi.str = json + 3;
783
+ pi.str = json + 3;
804
784
  } else {
805
- pi.str = json;
785
+ pi.str = json;
806
786
  }
807
787
  pi.s = pi.str;
808
788
  doc_init(doc);
809
789
  pi.doc = doc;
810
790
  #if IS_WINDOWS
811
- pi.stack_min = (void*)((char*)&pi - (512 * 1024)); // assume a 1M stack and give half to ruby
791
+ // assume a 1M stack and give half to ruby
792
+ pi.stack_min = (void *)((char *)&pi - (512 * 1024));
812
793
  #else
813
794
  {
814
- struct rlimit lim;
795
+ struct rlimit lim;
815
796
 
816
- if (0 == getrlimit(RLIMIT_STACK, &lim) && RLIM_INFINITY != lim.rlim_cur) {
817
- pi.stack_min = (void*)((char*)&lim - (lim.rlim_cur / 4 * 3)); // let 3/4ths of the stack be used only
818
- } else {
819
- pi.stack_min = 0; // indicates not to check stack limit
820
- }
797
+ if (0 == getrlimit(RLIMIT_STACK, &lim) && RLIM_INFINITY != lim.rlim_cur) {
798
+ // let 3/4ths of the stack be used only
799
+ pi.stack_min = (void *)((char *)&lim - (lim.rlim_cur / 4 * 3));
800
+ } else {
801
+ pi.stack_min = 0; // indicates not to check stack limit
802
+ }
821
803
  }
822
804
  #endif
823
- // last arg is free func void* func(void*)
824
- #ifdef HAVE_RB_DATA_OBJECT_WRAP
825
- self = rb_data_object_wrap(clas, doc, mark_doc, free_doc_cb);
826
- #else
827
- self = rb_data_object_alloc(clas, doc, mark_doc, free_doc_cb);
828
- #endif
829
- doc->self = self;
830
- doc->json = json;
805
+ self = TypedData_Wrap_Struct(clas, &oj_doc_type, doc);
806
+ doc->self = self;
807
+ doc->json = json;
831
808
  DATA_PTR(doc->self) = doc;
832
- result = rb_protect(protect_open_proc, (VALUE)&pi, &ex);
809
+ result = rb_protect(protect_open_proc, (VALUE)&pi, &ex);
833
810
  if (given || 0 != ex) {
834
- DATA_PTR(doc->self) = NULL;
835
- doc_free(pi.doc);
836
- if (allocated && 0 != ex) { // will jump so caller will not free
837
- xfree(json);
838
- }
839
- rb_gc_enable();
811
+ DATA_PTR(doc->self) = NULL;
812
+ doc_free(pi.doc);
813
+ if (allocated && 0 != ex) { // will jump so caller will not free
814
+ xfree(json);
815
+ }
816
+ rb_gc_enable();
840
817
  } else {
841
- result = doc->self;
818
+ result = doc->self;
842
819
  }
843
820
  if (0 != ex) {
844
- rb_jump_tag(ex);
821
+ rb_jump_tag(ex);
845
822
  }
846
823
  return result;
847
824
  }
848
825
 
849
- static Leaf
850
- get_doc_leaf(Doc doc, const char *path) {
851
- Leaf leaf = *doc->where;
826
+ static Leaf get_doc_leaf(Doc doc, const char *path) {
827
+ Leaf leaf = *doc->where;
852
828
 
853
829
  if (0 != doc->data && 0 != path) {
854
- Leaf stack[MAX_STACK];
855
- Leaf *lp;
856
-
857
- if ('/' == *path) {
858
- path++;
859
- *stack = doc->data;
860
- lp = stack;
861
- } else if (doc->where == doc->where_path) {
862
- *stack = doc->data;
863
- lp = stack;
864
- } else {
865
- size_t cnt = doc->where - doc->where_path;
866
-
867
- if (MAX_STACK <= cnt) {
868
- rb_raise(rb_const_get_at(Oj, rb_intern("DepthError")), "Path too deep. Limit is %d levels.", MAX_STACK);
869
- }
870
- memcpy(stack, doc->where_path, sizeof(Leaf) * (cnt + 1));
871
- lp = stack + cnt;
872
- }
873
- return get_leaf(stack, lp, path);
830
+ Leaf stack[MAX_STACK];
831
+ Leaf *lp;
832
+
833
+ if ('/' == *path) {
834
+ path++;
835
+ *stack = doc->data;
836
+ lp = stack;
837
+ } else if (doc->where == doc->where_path) {
838
+ *stack = doc->data;
839
+ lp = stack;
840
+ } else {
841
+ size_t cnt = doc->where - doc->where_path;
842
+
843
+ if (MAX_STACK <= cnt) {
844
+ rb_raise(rb_const_get_at(Oj, rb_intern("DepthError")),
845
+ "Path too deep. Limit is %d levels.",
846
+ MAX_STACK);
847
+ }
848
+ memcpy(stack, doc->where_path, sizeof(Leaf) * (cnt + 1));
849
+ lp = stack + cnt;
850
+ }
851
+ return get_leaf(stack, lp, path);
874
852
  }
875
853
  return leaf;
876
854
  }
877
855
 
878
- static const char*
879
- next_slash(const char *s) {
856
+ static const char *next_slash(const char *s) {
880
857
  for (; '\0' != *s; s++) {
881
- if ('\\' == *s) {
882
- s++;
883
- if ('\0' == *s) {
884
- break;
885
- }
886
- } else if ('/' == *s) {
887
- return s;
888
- }
858
+ if ('\\' == *s) {
859
+ s++;
860
+ if ('\0' == *s) {
861
+ break;
862
+ }
863
+ } else if ('/' == *s) {
864
+ return s;
865
+ }
889
866
  }
890
867
  return NULL;
891
868
  }
892
869
 
893
- static bool
894
- key_match(const char *pat, const char *key, int plen) {
870
+ static bool key_match(const char *pat, const char *key, int plen) {
895
871
  for (; 0 < plen; plen--, pat++, key++) {
896
- if ('\\' == *pat) {
897
- plen--;
898
- pat++;
899
- }
900
- if (*pat != *key) {
901
- return false;
902
- }
872
+ if ('\\' == *pat) {
873
+ plen--;
874
+ pat++;
875
+ }
876
+ if (*pat != *key) {
877
+ return false;
878
+ }
903
879
  }
904
880
  return '\0' == *key;
905
881
  }
906
882
 
907
- static Leaf
908
- get_leaf(Leaf *stack, Leaf *lp, const char *path) {
909
- Leaf leaf = *lp;
883
+ static Leaf get_leaf(Leaf *stack, Leaf *lp, const char *path) {
884
+ Leaf leaf = *lp;
910
885
 
911
886
  if (MAX_STACK <= lp - stack) {
912
- rb_raise(rb_const_get_at(Oj, rb_intern("DepthError")), "Path too deep. Limit is %d levels.", MAX_STACK);
887
+ rb_raise(rb_const_get_at(Oj, rb_intern("DepthError")),
888
+ "Path too deep. Limit is %d levels.",
889
+ MAX_STACK);
913
890
  }
914
891
  if ('\0' != *path) {
915
- if ('.' == *path && '.' == *(path + 1)) {
916
- path += 2;
917
- if ('/' == *path) {
918
- path++;
919
- }
920
- if (stack < lp) {
921
- leaf = get_leaf(stack, lp - 1, path);
922
- } else {
923
- return 0;
924
- }
925
- } else if (COL_VAL == leaf->value_type && 0 != leaf->elements) {
926
- Leaf first = leaf->elements->next;
927
- Leaf e = first;
928
- int type = leaf->rtype;
929
-
930
- leaf = 0;
931
- if (T_ARRAY == type) {
932
- int cnt = 0;
933
-
934
- for (; '0' <= *path && *path <= '9'; path++) {
935
- cnt = cnt * 10 + (*path - '0');
936
- }
937
- if ('/' == *path) {
938
- path++;
939
- }
940
- do {
941
- if (1 >= cnt) {
942
- lp++;
943
- *lp = e;
944
- leaf = get_leaf(stack, lp, path);
945
- break;
946
- }
947
- cnt--;
948
- e = e->next;
949
- } while (e != first);
950
- } else if (T_HASH == type) {
951
- const char *key = path;
952
- const char *slash = next_slash(path);
953
- int klen;
954
-
955
- if (0 == slash) {
956
- klen = (int)strlen(key);
957
- path += klen;
958
- } else {
959
- klen = (int)(slash - key);
960
- path += klen + 1;
961
- }
962
- do {
963
- if (key_match(key, e->key, klen)) {
964
- lp++;
965
- *lp = e;
966
- leaf = get_leaf(stack, lp, path);
967
- break;
968
- }
969
- e = e->next;
970
- } while (e != first);
971
- }
972
- }
892
+ if ('.' == *path && '.' == *(path + 1)) {
893
+ path += 2;
894
+ if ('/' == *path) {
895
+ path++;
896
+ }
897
+ if (stack < lp) {
898
+ leaf = get_leaf(stack, lp - 1, path);
899
+ } else {
900
+ return 0;
901
+ }
902
+ } else if (COL_VAL == leaf->value_type && 0 != leaf->elements) {
903
+ Leaf first = leaf->elements->next;
904
+ Leaf e = first;
905
+ int type = leaf->rtype;
906
+
907
+ leaf = 0;
908
+ if (T_ARRAY == type) {
909
+ int cnt = 0;
910
+
911
+ for (; '0' <= *path && *path <= '9'; path++) {
912
+ cnt = cnt * 10 + (*path - '0');
913
+ }
914
+ if ('/' == *path) {
915
+ path++;
916
+ }
917
+ do {
918
+ if (1 >= cnt) {
919
+ lp++;
920
+ *lp = e;
921
+ leaf = get_leaf(stack, lp, path);
922
+ break;
923
+ }
924
+ cnt--;
925
+ e = e->next;
926
+ } while (e != first);
927
+ } else if (T_HASH == type) {
928
+ const char *key = path;
929
+ const char *slash = next_slash(path);
930
+ int klen;
931
+
932
+ if (0 == slash) {
933
+ klen = (int)strlen(key);
934
+ path += klen;
935
+ } else {
936
+ klen = (int)(slash - key);
937
+ path += klen + 1;
938
+ }
939
+ do {
940
+ if (key_match(key, e->key, klen)) {
941
+ lp++;
942
+ *lp = e;
943
+ leaf = get_leaf(stack, lp, path);
944
+ break;
945
+ }
946
+ e = e->next;
947
+ } while (e != first);
948
+ }
949
+ }
973
950
  }
974
951
  return leaf;
975
952
  }
976
953
 
977
- static void
978
- each_leaf(Doc doc, VALUE self) {
954
+ static void each_leaf(Doc doc, VALUE self) {
979
955
  if (COL_VAL == (*doc->where)->value_type) {
980
- if (0 != (*doc->where)->elements) {
981
- Leaf first = (*doc->where)->elements->next;
982
- Leaf e = first;
983
-
984
- doc->where++;
985
- if (MAX_STACK <= doc->where - doc->where_path) {
986
- rb_raise(rb_const_get_at(Oj, rb_intern("DepthError")), "Path too deep. Limit is %d levels.", MAX_STACK);
987
- }
988
- do {
989
- *doc->where = e;
990
- each_leaf(doc, self);
991
- e = e->next;
992
- } while (e != first);
993
- doc->where--;
994
- }
956
+ if (0 != (*doc->where)->elements) {
957
+ Leaf first = (*doc->where)->elements->next;
958
+ Leaf e = first;
959
+
960
+ doc->where++;
961
+ if (MAX_STACK <= doc->where - doc->where_path) {
962
+ rb_raise(rb_const_get_at(Oj, rb_intern("DepthError")),
963
+ "Path too deep. Limit is %d levels.",
964
+ MAX_STACK);
965
+ }
966
+ do {
967
+ *doc->where = e;
968
+ each_leaf(doc, self);
969
+ e = e->next;
970
+ } while (e != first);
971
+ doc->where--;
972
+ }
995
973
  } else {
996
- rb_yield(self);
974
+ rb_yield(self);
997
975
  }
998
976
  }
999
977
 
1000
- static int
1001
- move_step(Doc doc, const char *path, int loc) {
978
+ static int move_step(Doc doc, const char *path, int loc) {
1002
979
  if (MAX_STACK <= doc->where - doc->where_path) {
1003
- rb_raise(rb_const_get_at(Oj, rb_intern("DepthError")), "Path too deep. Limit is %d levels.", MAX_STACK);
980
+ rb_raise(rb_const_get_at(Oj, rb_intern("DepthError")),
981
+ "Path too deep. Limit is %d levels.",
982
+ MAX_STACK);
1004
983
  }
1005
984
  if ('\0' == *path) {
1006
- loc = 0;
985
+ loc = 0;
1007
986
  } else {
1008
- Leaf leaf;
1009
-
1010
- if (0 == doc->where || 0 == (leaf = *doc->where)) {
1011
- printf("*** Internal error at %s\n", path);
1012
- return loc;
1013
- }
1014
- if ('.' == *path && '.' == *(path + 1)) {
1015
- Leaf init = *doc->where;
1016
-
1017
- path += 2;
1018
- if (doc->where == doc->where_path) {
1019
- return loc;
1020
- }
1021
- if ('/' == *path) {
1022
- path++;
1023
- }
1024
- *doc->where = 0;
1025
- doc->where--;
1026
- loc = move_step(doc, path, loc + 1);
1027
- if (0 != loc) {
1028
- *doc->where = init;
1029
- doc->where++;
1030
- }
1031
- } else if (COL_VAL == leaf->value_type && 0 != leaf->elements) {
1032
- Leaf first = leaf->elements->next;
1033
- Leaf e = first;
1034
-
1035
- if (T_ARRAY == leaf->rtype) {
1036
- int cnt = 0;
1037
-
1038
- for (; '0' <= *path && *path <= '9'; path++) {
1039
- cnt = cnt * 10 + (*path - '0');
1040
- }
1041
- if ('/' == *path) {
1042
- path++;
1043
- } else if ('\0' != *path) {
1044
- return loc;
1045
- }
1046
- do {
1047
- if (1 >= cnt) {
1048
- doc->where++;
1049
- *doc->where = e;
1050
- loc = move_step(doc, path, loc + 1);
1051
- if (0 != loc) {
1052
- *doc->where = 0;
1053
- doc->where--;
1054
- }
1055
- break;
1056
- }
1057
- cnt--;
1058
- e = e->next;
1059
- } while (e != first);
1060
- } else if (T_HASH == leaf->rtype) {
1061
- const char *key = path;
1062
- const char *slash = next_slash(path);
1063
- int klen;
1064
-
1065
- if (0 == slash) {
1066
- klen = (int)strlen(key);
1067
- path += klen;
1068
- } else {
1069
- klen = (int)(slash - key);
1070
- path += klen + 1;
1071
- }
1072
- do {
1073
- if (key_match(key, e->key, klen)) {
1074
- doc->where++;
1075
- *doc->where = e;
1076
- loc = move_step(doc, path, loc + 1);
1077
- if (0 != loc) {
1078
- *doc->where = 0;
1079
- doc->where--;
1080
- }
1081
- break;
1082
- }
1083
- e = e->next;
1084
- } while (e != first);
1085
- }
1086
- }
987
+ Leaf leaf;
988
+
989
+ if (0 == doc->where || 0 == (leaf = *doc->where)) {
990
+ printf("*** Internal error at %s\n", path);
991
+ return loc;
992
+ }
993
+ if ('.' == *path && '.' == *(path + 1)) {
994
+ Leaf init = *doc->where;
995
+
996
+ path += 2;
997
+ if (doc->where == doc->where_path) {
998
+ return loc;
999
+ }
1000
+ if ('/' == *path) {
1001
+ path++;
1002
+ }
1003
+ *doc->where = 0;
1004
+ doc->where--;
1005
+ loc = move_step(doc, path, loc + 1);
1006
+ if (0 != loc) {
1007
+ *doc->where = init;
1008
+ doc->where++;
1009
+ }
1010
+ } else if (COL_VAL == leaf->value_type && 0 != leaf->elements) {
1011
+ Leaf first = leaf->elements->next;
1012
+ Leaf e = first;
1013
+
1014
+ if (T_ARRAY == leaf->rtype) {
1015
+ int cnt = 0;
1016
+
1017
+ for (; '0' <= *path && *path <= '9'; path++) {
1018
+ cnt = cnt * 10 + (*path - '0');
1019
+ }
1020
+ if ('/' == *path) {
1021
+ path++;
1022
+ } else if ('\0' != *path) {
1023
+ return loc;
1024
+ }
1025
+ do {
1026
+ if (1 >= cnt) {
1027
+ doc->where++;
1028
+ *doc->where = e;
1029
+ loc = move_step(doc, path, loc + 1);
1030
+ if (0 != loc) {
1031
+ *doc->where = 0;
1032
+ doc->where--;
1033
+ }
1034
+ break;
1035
+ }
1036
+ cnt--;
1037
+ e = e->next;
1038
+ } while (e != first);
1039
+ } else if (T_HASH == leaf->rtype) {
1040
+ const char *key = path;
1041
+ const char *slash = next_slash(path);
1042
+ int klen;
1043
+
1044
+ if (0 == slash) {
1045
+ klen = (int)strlen(key);
1046
+ path += klen;
1047
+ } else {
1048
+ klen = (int)(slash - key);
1049
+ path += klen + 1;
1050
+ }
1051
+ do {
1052
+ if (key_match(key, e->key, klen)) {
1053
+ doc->where++;
1054
+ *doc->where = e;
1055
+ loc = move_step(doc, path, loc + 1);
1056
+ if (0 != loc) {
1057
+ *doc->where = 0;
1058
+ doc->where--;
1059
+ }
1060
+ break;
1061
+ }
1062
+ e = e->next;
1063
+ } while (e != first);
1064
+ }
1065
+ }
1087
1066
  }
1088
1067
  return loc;
1089
1068
  }
1090
1069
 
1091
- static void
1092
- each_value(Doc doc, Leaf leaf) {
1070
+ static void each_value(Doc doc, Leaf leaf) {
1093
1071
  if (COL_VAL == leaf->value_type) {
1094
- if (0 != leaf->elements) {
1095
- Leaf first = leaf->elements->next;
1096
- Leaf e = first;
1097
-
1098
- do {
1099
- each_value(doc, e);
1100
- e = e->next;
1101
- } while (e != first);
1102
- }
1072
+ if (0 != leaf->elements) {
1073
+ Leaf first = leaf->elements->next;
1074
+ Leaf e = first;
1075
+
1076
+ do {
1077
+ each_value(doc, e);
1078
+ e = e->next;
1079
+ } while (e != first);
1080
+ }
1103
1081
  } else {
1104
- rb_yield(leaf_value(doc, leaf));
1082
+ rb_yield(leaf_value(doc, leaf));
1105
1083
  }
1106
1084
  }
1107
1085
 
@@ -1116,7 +1094,8 @@ each_value(Doc doc, Leaf leaf) {
1116
1094
  *
1117
1095
  * @param [String] json JSON document string
1118
1096
  * @yieldparam [Oj::Doc] doc parsed JSON document
1119
- * @yieldreturn [Object] returns the result of the yield as the result of the method call
1097
+ * @yieldreturn [Object] returns the result of the yield as the result of the
1098
+ * method call
1120
1099
  * @example
1121
1100
  * Oj::Doc.open('[1,2,3]') { |doc| doc.size() } #=> 4
1122
1101
  * # or as an alternative
@@ -1124,21 +1103,20 @@ each_value(Doc doc, Leaf leaf) {
1124
1103
  * doc.size() #=> 4
1125
1104
  * doc.close()
1126
1105
  */
1127
- static VALUE
1128
- doc_open(VALUE clas, VALUE str) {
1129
- char *json;
1130
- size_t len;
1131
- volatile VALUE obj;
1132
- int given = rb_block_given_p();
1133
- int allocate;
1106
+ static VALUE doc_open(VALUE clas, VALUE str) {
1107
+ char * json;
1108
+ size_t len;
1109
+ volatile VALUE obj;
1110
+ int given = rb_block_given_p();
1111
+ int allocate;
1134
1112
 
1135
1113
  Check_Type(str, T_STRING);
1136
- len = (int)RSTRING_LEN(str) + 1;
1137
- allocate = (SMALL_XML < len || !given);
1114
+ len = (int)RSTRING_LEN(str) + 1;
1115
+ allocate = (SMALL_JSON < len || !given);
1138
1116
  if (allocate) {
1139
- json = ALLOC_N(char, len);
1117
+ json = ALLOC_N(char, len);
1140
1118
  } else {
1141
- json = ALLOCA_N(char, len);
1119
+ json = ALLOCA_N(char, len);
1142
1120
  }
1143
1121
  // It should not be necessaary to stop GC but if it is not stopped and a
1144
1122
  // large string is parsed that string is corrupted or freed during
@@ -1149,7 +1127,7 @@ doc_open(VALUE clas, VALUE str) {
1149
1127
  obj = parse_json(clas, json, given, allocate);
1150
1128
  rb_gc_enable();
1151
1129
  if (given && allocate) {
1152
- xfree(json);
1130
+ xfree(json);
1153
1131
  }
1154
1132
  return obj;
1155
1133
  }
@@ -1163,7 +1141,8 @@ doc_open(VALUE clas, VALUE str) {
1163
1141
  *
1164
1142
  * @param [String] filename name of file that contains a JSON document
1165
1143
  * @yieldparam [Oj::Doc] doc parsed JSON document
1166
- * @yieldreturn [Object] returns the result of the yield as the result of the method call
1144
+ * @yieldreturn [Object] returns the result of the yield as the result of the
1145
+ * method call
1167
1146
  * @example
1168
1147
  * File.open('array.json', 'w') { |f| f.write('[1,2,3]') }
1169
1148
  * Oj::Doc.open_file(filename) { |doc| doc.size() } #=> 4
@@ -1172,34 +1151,35 @@ doc_open(VALUE clas, VALUE str) {
1172
1151
  * doc.size() #=> 4
1173
1152
  * doc.close()
1174
1153
  */
1175
- static VALUE
1176
- doc_open_file(VALUE clas, VALUE filename) {
1177
- char *path;
1178
- char *json;
1179
- FILE *f;
1180
- size_t len;
1181
- volatile VALUE obj;
1182
- int given = rb_block_given_p();
1183
- int allocate;
1154
+ static VALUE doc_open_file(VALUE clas, VALUE filename) {
1155
+ char * path;
1156
+ char * json;
1157
+ FILE * f;
1158
+ size_t len;
1159
+ volatile VALUE obj;
1160
+ int given = rb_block_given_p();
1161
+ int allocate;
1184
1162
 
1185
1163
  Check_Type(filename, T_STRING);
1186
1164
  path = StringValuePtr(filename);
1187
1165
  if (0 == (f = fopen(path, "r"))) {
1188
- rb_raise(rb_eIOError, "%s", strerror(errno));
1166
+ rb_raise(rb_eIOError, "%s", strerror(errno));
1189
1167
  }
1190
1168
  fseek(f, 0, SEEK_END);
1191
- len = ftell(f);
1192
- allocate = (SMALL_XML < len || !given);
1169
+ len = ftell(f);
1170
+ allocate = (SMALL_JSON < len || !given);
1193
1171
  if (allocate) {
1194
- json = ALLOC_N(char, len + 1);
1172
+ json = ALLOC_N(char, len + 1);
1195
1173
  } else {
1196
- json = ALLOCA_N(char, len + 1);
1174
+ json = ALLOCA_N(char, len + 1);
1197
1175
  }
1198
1176
  fseek(f, 0, SEEK_SET);
1199
1177
  if (len != fread(json, 1, len, f)) {
1200
- fclose(f);
1201
- rb_raise(rb_const_get_at(Oj, rb_intern("LoadError")),
1202
- "Failed to read %lu bytes from %s.", (unsigned long)len, path);
1178
+ fclose(f);
1179
+ rb_raise(rb_const_get_at(Oj, rb_intern("LoadError")),
1180
+ "Failed to read %lu bytes from %s.",
1181
+ (unsigned long)len,
1182
+ path);
1203
1183
  }
1204
1184
  fclose(f);
1205
1185
  json[len] = '\0';
@@ -1207,30 +1187,28 @@ doc_open_file(VALUE clas, VALUE filename) {
1207
1187
  obj = parse_json(clas, json, given, allocate);
1208
1188
  rb_gc_enable();
1209
1189
  if (given && allocate) {
1210
- xfree(json);
1190
+ xfree(json);
1211
1191
  }
1212
1192
  return obj;
1213
1193
  }
1214
1194
 
1215
- static int
1216
- esc_strlen(const char *s) {
1217
- int cnt = 0;
1195
+ static int esc_strlen(const char *s) {
1196
+ int cnt = 0;
1218
1197
 
1219
1198
  for (; '\0' != *s; s++, cnt++) {
1220
- if ('/' == *s) {
1221
- cnt++;
1222
- }
1199
+ if ('/' == *s) {
1200
+ cnt++;
1201
+ }
1223
1202
  }
1224
1203
  return cnt;
1225
1204
  }
1226
1205
 
1227
- static char*
1228
- append_key(char *p, const char *key) {
1206
+ static char *append_key(char *p, const char *key) {
1229
1207
  for (; '\0' != *key; p++, key++) {
1230
- if ('/' == *key) {
1231
- *p++ = '\\';
1232
- }
1233
- *p = *key;
1208
+ if ('/' == *key) {
1209
+ *p++ = '\\';
1210
+ }
1211
+ *p = *key;
1234
1212
  }
1235
1213
  return p;
1236
1214
  }
@@ -1244,41 +1222,40 @@ append_key(char *p, const char *key) {
1244
1222
  * Returns a String that describes the absolute path to the current location
1245
1223
  * in the JSON document.
1246
1224
  */
1247
- static VALUE
1248
- doc_where(VALUE self) {
1249
- Doc doc = self_doc(self);
1225
+ static VALUE doc_where(VALUE self) {
1226
+ Doc doc = self_doc(self);
1250
1227
 
1251
1228
  if (0 == *doc->where_path || doc->where == doc->where_path) {
1252
- return oj_slash_string;
1229
+ return oj_slash_string;
1253
1230
  } else {
1254
- Leaf *lp;
1255
- Leaf leaf;
1256
- size_t size = 3; // leading / and terminating \0
1257
- char *path;
1258
- char *p;
1259
-
1260
- for (lp = doc->where_path; lp <= doc->where; lp++) {
1261
- leaf = *lp;
1262
- if (T_HASH == leaf->parent_type) {
1263
- size += esc_strlen((*lp)->key) + 1;
1264
- } else if (T_ARRAY == leaf->parent_type) {
1265
- size += ((*lp)->index < 100) ? 3 : 11;
1266
- }
1267
- }
1268
- path = ALLOCA_N(char, size);
1269
- p = path;
1270
- for (lp = doc->where_path; lp <= doc->where; lp++) {
1271
- leaf = *lp;
1272
- if (T_HASH == leaf->parent_type) {
1273
- p = append_key(p, (*lp)->key);
1274
- } else if (T_ARRAY == leaf->parent_type) {
1275
- p = ulong_fill(p, (*lp)->index);
1276
- }
1277
- *p++ = '/';
1278
- }
1279
- *--p = '\0';
1280
-
1281
- return rb_str_new(path, p - path);
1231
+ Leaf * lp;
1232
+ Leaf leaf;
1233
+ size_t size = 3; // leading / and terminating \0
1234
+ char * path;
1235
+ char * p;
1236
+
1237
+ for (lp = doc->where_path; lp <= doc->where; lp++) {
1238
+ leaf = *lp;
1239
+ if (T_HASH == leaf->parent_type) {
1240
+ size += esc_strlen((*lp)->key) + 1;
1241
+ } else if (T_ARRAY == leaf->parent_type) {
1242
+ size += ((*lp)->index < 100) ? 3 : 11;
1243
+ }
1244
+ }
1245
+ path = ALLOCA_N(char, size);
1246
+ p = path;
1247
+ for (lp = doc->where_path; lp <= doc->where; lp++) {
1248
+ leaf = *lp;
1249
+ if (T_HASH == leaf->parent_type) {
1250
+ p = append_key(p, (*lp)->key);
1251
+ } else if (T_ARRAY == leaf->parent_type) {
1252
+ p = ulong_fill(p, (*lp)->index);
1253
+ }
1254
+ *p++ = '/';
1255
+ }
1256
+ *--p = '\0';
1257
+
1258
+ return rb_str_new(path, p - path);
1282
1259
  }
1283
1260
  }
1284
1261
 
@@ -1286,21 +1263,21 @@ doc_where(VALUE self) {
1286
1263
  *
1287
1264
  * Returns the final key to the current location.
1288
1265
  * @example
1289
- * Oj::Doc.open('[1,2,3]') { |doc| doc.move('/2'); doc.local_key() } #=> 2
1290
- * Oj::Doc.open('{"one":3}') { |doc| doc.move('/one'); doc.local_key() } #=> "one"
1291
- * Oj::Doc.open('[1,2,3]') { |doc| doc.local_key() } #=> nil
1266
+ * Oj::Doc.open('[1,2,3]') { |doc| doc.move('/2'); doc.local_key() } #=> 2
1267
+ * Oj::Doc.open('{"one":3}') { |doc| doc.move('/one'); doc.local_key() } #=>
1268
+ * "one" Oj::Doc.open('[1,2,3]') { |doc| doc.local_key() }
1269
+ * #=> nil
1292
1270
  */
1293
- static VALUE
1294
- doc_local_key(VALUE self) {
1295
- Doc doc = self_doc(self);
1296
- Leaf leaf = *doc->where;
1297
- volatile VALUE key = Qnil;
1271
+ static VALUE doc_local_key(VALUE self) {
1272
+ Doc doc = self_doc(self);
1273
+ Leaf leaf = *doc->where;
1274
+ volatile VALUE key = Qnil;
1298
1275
 
1299
1276
  if (T_HASH == leaf->parent_type) {
1300
- key = rb_str_new2(leaf->key);
1301
- key = oj_encode(key);
1277
+ key = rb_str_new2(leaf->key);
1278
+ key = oj_encode(key);
1302
1279
  } else if (T_ARRAY == leaf->parent_type) {
1303
- key = LONG2NUM(leaf->index);
1280
+ key = LONG2NUM(leaf->index);
1304
1281
  }
1305
1282
  return key;
1306
1283
  }
@@ -1310,14 +1287,14 @@ doc_local_key(VALUE self) {
1310
1287
  * Moves the document marker or location to the hoot or home position. The
1311
1288
  * same operation can be performed with a Oj::Doc.move('/').
1312
1289
  * @example
1313
- * Oj::Doc.open('[1,2,3]') { |doc| doc.move('/2'); doc.home(); doc.where? } #=> '/'
1290
+ * Oj::Doc.open('[1,2,3]') { |doc| doc.move('/2'); doc.home(); doc.where? }
1291
+ * #=> '/'
1314
1292
  */
1315
- static VALUE
1316
- doc_home(VALUE self) {
1317
- Doc doc = self_doc(self);
1293
+ static VALUE doc_home(VALUE self) {
1294
+ Doc doc = self_doc(self);
1318
1295
 
1319
1296
  *doc->where_path = doc->data;
1320
- doc->where = doc->where_path;
1297
+ doc->where = doc->where_path;
1321
1298
 
1322
1299
  return oj_slash_string;
1323
1300
  }
@@ -1333,38 +1310,38 @@ doc_home(VALUE self) {
1333
1310
  * Oj::Doc.open('[1,2]') { |doc| doc.type() } #=> Array
1334
1311
  * Oj::Doc.open('[1,2]') { |doc| doc.type('/1') } #=> Fixnum
1335
1312
  */
1336
- static VALUE
1337
- doc_type(int argc, VALUE *argv, VALUE self) {
1338
- Doc doc = self_doc(self);
1339
- Leaf leaf;
1340
- const char *path = 0;
1341
- VALUE type = Qnil;
1313
+ static VALUE doc_type(int argc, VALUE *argv, VALUE self) {
1314
+ Doc doc = self_doc(self);
1315
+ Leaf leaf;
1316
+ const char *path = 0;
1317
+ VALUE type = Qnil;
1342
1318
 
1343
1319
  if (1 <= argc) {
1344
- Check_Type(*argv, T_STRING);
1345
- path = StringValuePtr(*argv);
1320
+ Check_Type(*argv, T_STRING);
1321
+ path = StringValuePtr(*argv);
1346
1322
  }
1347
1323
  if (0 != (leaf = get_doc_leaf(doc, path))) {
1348
- switch (leaf->rtype) {
1349
- case T_NIL: type = rb_cNilClass; break;
1350
- case T_TRUE: type = rb_cTrueClass; break;
1351
- case T_FALSE: type = rb_cFalseClass; break;
1352
- case T_STRING: type = rb_cString; break;
1324
+ switch (leaf->rtype) {
1325
+ case T_NIL: type = rb_cNilClass; break;
1326
+ case T_TRUE: type = rb_cTrueClass; break;
1327
+ case T_FALSE: type = rb_cFalseClass; break;
1328
+ case T_STRING: type = rb_cString; break;
1353
1329
  #ifdef RUBY_INTEGER_UNIFICATION
1354
- case T_FIXNUM: type = rb_cInteger; break;
1330
+ case T_FIXNUM: type = rb_cInteger; break;
1355
1331
  #else
1356
- case T_FIXNUM: type = rb_cFixnum; break;
1332
+ case T_FIXNUM: type = rb_cFixnum; break;
1357
1333
  #endif
1358
- case T_FLOAT: type = rb_cFloat; break;
1359
- case T_ARRAY: type = rb_cArray; break;
1360
- case T_HASH: type = rb_cHash; break;
1361
- default: break;
1362
- }
1334
+ case T_FLOAT: type = rb_cFloat; break;
1335
+ case T_ARRAY: type = rb_cArray; break;
1336
+ case T_HASH: type = rb_cHash; break;
1337
+ default: break;
1338
+ }
1363
1339
  }
1364
1340
  return type;
1365
1341
  }
1366
1342
 
1367
- /* @overload fetch(path=nil) => nil, true, false, Fixnum, Float, String, Array, Hash
1343
+ /* @overload fetch(path=nil) => nil, true, false, Fixnum, Float, String, Array,
1344
+ * Hash
1368
1345
  *
1369
1346
  * Returns the value at the location identified by the path or the current
1370
1347
  * location if the path is nil or not provided. This method will create and
@@ -1376,23 +1353,22 @@ doc_type(int argc, VALUE *argv, VALUE self) {
1376
1353
  * Oj::Doc.open('[1,2]') { |doc| doc.fetch() } #=> [1, 2]
1377
1354
  * Oj::Doc.open('[1,2]') { |doc| doc.fetch('/1') } #=> 1
1378
1355
  */
1379
- static VALUE
1380
- doc_fetch(int argc, VALUE *argv, VALUE self) {
1381
- Doc doc;
1382
- Leaf leaf;
1383
- volatile VALUE val = Qnil;
1384
- const char *path = 0;
1356
+ static VALUE doc_fetch(int argc, VALUE *argv, VALUE self) {
1357
+ Doc doc;
1358
+ Leaf leaf;
1359
+ volatile VALUE val = Qnil;
1360
+ const char * path = 0;
1385
1361
 
1386
1362
  doc = self_doc(self);
1387
1363
  if (1 <= argc) {
1388
- Check_Type(*argv, T_STRING);
1389
- path = StringValuePtr(*argv);
1390
- if (2 == argc) {
1391
- val = argv[1];
1392
- }
1364
+ Check_Type(*argv, T_STRING);
1365
+ path = StringValuePtr(*argv);
1366
+ if (2 == argc) {
1367
+ val = argv[1];
1368
+ }
1393
1369
  }
1394
1370
  if (0 != (leaf = get_doc_leaf(doc, path))) {
1395
- val = leaf_value(doc, leaf);
1371
+ val = leaf_value(doc, leaf);
1396
1372
  }
1397
1373
  return val;
1398
1374
  }
@@ -1402,7 +1378,8 @@ doc_fetch(int argc, VALUE *argv, VALUE self) {
1402
1378
  * Yields to the provided block for each leaf node with the identified
1403
1379
  * location of the JSON document as the root. The parameter passed to the
1404
1380
  * block on yield is the Doc instance after moving to the child location.
1405
- * @param [String] path if provided it identified the top of the branch to process the leaves of
1381
+ * @param [String] path if provided it identified the top of the branch to
1382
+ * process the leaves of
1406
1383
  * @yieldparam [Doc] Doc at the child location
1407
1384
  * @example
1408
1385
  * Oj::Doc.open('[3,[2,1]]') { |doc|
@@ -1412,36 +1389,35 @@ doc_fetch(int argc, VALUE *argv, VALUE self) {
1412
1389
  * }
1413
1390
  * #=> ["/1" => 3, "/2/1" => 2, "/2/2" => 1]
1414
1391
  */
1415
- static VALUE
1416
- doc_each_leaf(int argc, VALUE *argv, VALUE self) {
1392
+ static VALUE doc_each_leaf(int argc, VALUE *argv, VALUE self) {
1417
1393
  if (rb_block_given_p()) {
1418
- Leaf save_path[MAX_STACK];
1419
- Doc doc = self_doc(self);
1420
- const char *path = 0;
1421
- size_t wlen;
1422
-
1423
- wlen = doc->where - doc->where_path;
1424
- if (0 < wlen) {
1425
- memcpy(save_path, doc->where_path, sizeof(Leaf) * (wlen + 1));
1426
- }
1427
- if (1 <= argc) {
1428
- Check_Type(*argv, T_STRING);
1429
- path = StringValuePtr(*argv);
1430
- if ('/' == *path) {
1431
- doc->where = doc->where_path;
1432
- path++;
1433
- }
1434
- if (0 != move_step(doc, path, 1)) {
1435
- if (0 < wlen) {
1436
- memcpy(doc->where_path, save_path, sizeof(Leaf) * (wlen + 1));
1437
- }
1438
- return Qnil;
1439
- }
1440
- }
1441
- each_leaf(doc, self);
1442
- if (0 < wlen) {
1443
- memcpy(doc->where_path, save_path, sizeof(Leaf) * (wlen + 1));
1444
- }
1394
+ Leaf save_path[MAX_STACK];
1395
+ Doc doc = self_doc(self);
1396
+ const char *path = 0;
1397
+ size_t wlen;
1398
+
1399
+ wlen = doc->where - doc->where_path;
1400
+ if (0 < wlen) {
1401
+ memcpy(save_path, doc->where_path, sizeof(Leaf) * (wlen + 1));
1402
+ }
1403
+ if (1 <= argc) {
1404
+ Check_Type(*argv, T_STRING);
1405
+ path = StringValuePtr(*argv);
1406
+ if ('/' == *path) {
1407
+ doc->where = doc->where_path;
1408
+ path++;
1409
+ }
1410
+ if (0 != move_step(doc, path, 1)) {
1411
+ if (0 < wlen) {
1412
+ memcpy(doc->where_path, save_path, sizeof(Leaf) * (wlen + 1));
1413
+ }
1414
+ return Qnil;
1415
+ }
1416
+ }
1417
+ each_leaf(doc, self);
1418
+ if (0 < wlen) {
1419
+ memcpy(doc->where_path, save_path, sizeof(Leaf) * (wlen + 1));
1420
+ }
1445
1421
  }
1446
1422
  return Qnil;
1447
1423
  }
@@ -1452,22 +1428,22 @@ doc_each_leaf(int argc, VALUE *argv, VALUE self) {
1452
1428
  * path or a relative path.
1453
1429
  * @param [String] path path to the location to move to
1454
1430
  * @example
1455
- * Oj::Doc.open('{"one":[1,2]') { |doc| doc.move('/one/2'); doc.where? } #=> "/one/2"
1431
+ * Oj::Doc.open('{"one":[1,2]') { |doc| doc.move('/one/2'); doc.where? } #=>
1432
+ * "/one/2"
1456
1433
  */
1457
- static VALUE
1458
- doc_move(VALUE self, VALUE str) {
1459
- Doc doc = self_doc(self);
1460
- const char *path;
1461
- int loc;
1434
+ static VALUE doc_move(VALUE self, VALUE str) {
1435
+ Doc doc = self_doc(self);
1436
+ const char *path;
1437
+ int loc;
1462
1438
 
1463
1439
  Check_Type(str, T_STRING);
1464
1440
  path = StringValuePtr(str);
1465
1441
  if ('/' == *path) {
1466
- doc->where = doc->where_path;
1467
- path++;
1442
+ doc->where = doc->where_path;
1443
+ path++;
1468
1444
  }
1469
1445
  if (0 != (loc = move_step(doc, path, 1))) {
1470
- rb_raise(rb_eArgError, "Failed to locate element %d of the path %s.", loc, path);
1446
+ rb_raise(rb_eArgError, "Failed to locate element %d of the path %s.", loc, path);
1471
1447
  }
1472
1448
  return Qnil;
1473
1449
  }
@@ -1478,7 +1454,8 @@ doc_move(VALUE self, VALUE str) {
1478
1454
  * identified location of the JSON document as the root. The parameter passed
1479
1455
  * to the block on yield is the Doc instance after moving to the child
1480
1456
  * location.
1481
- * @param [String] path if provided it identified the top of the branch to process the chilren of
1457
+ * @param [String] path if provided it identified the top of the branch to
1458
+ * process the chilren of
1482
1459
  * @yieldparam [Doc] Doc at the child location
1483
1460
  * @example
1484
1461
  * Oj::Doc.open('[3,[2,1]]') { |doc|
@@ -1488,46 +1465,45 @@ doc_move(VALUE self, VALUE str) {
1488
1465
  * }
1489
1466
  * #=> ["/2/1", "/2/2"]
1490
1467
  */
1491
- static VALUE
1492
- doc_each_child(int argc, VALUE *argv, VALUE self) {
1468
+ static VALUE doc_each_child(int argc, VALUE *argv, VALUE self) {
1493
1469
  if (rb_block_given_p()) {
1494
- Leaf save_path[MAX_STACK];
1495
- Doc doc = self_doc(self);
1496
- const char *path = 0;
1497
- size_t wlen;
1498
-
1499
- wlen = doc->where - doc->where_path;
1500
- if (0 < wlen) {
1501
- memcpy(save_path, doc->where_path, sizeof(Leaf) * (wlen + 1));
1502
- }
1503
- if (1 <= argc) {
1504
- Check_Type(*argv, T_STRING);
1505
- path = StringValuePtr(*argv);
1506
- if ('/' == *path) {
1507
- doc->where = doc->where_path;
1508
- path++;
1509
- }
1510
- if (0 != move_step(doc, path, 1)) {
1511
- if (0 < wlen) {
1512
- memcpy(doc->where_path, save_path, sizeof(Leaf) * (wlen + 1));
1513
- }
1514
- return Qnil;
1515
- }
1516
- }
1517
- if (COL_VAL == (*doc->where)->value_type && 0 != (*doc->where)->elements) {
1518
- Leaf first = (*doc->where)->elements->next;
1519
- Leaf e = first;
1520
-
1521
- doc->where++;
1522
- do {
1523
- *doc->where = e;
1524
- rb_yield(self);
1525
- e = e->next;
1526
- } while (e != first);
1527
- }
1528
- if (0 < wlen) {
1529
- memcpy(doc->where_path, save_path, sizeof(Leaf) * (wlen + 1));
1530
- }
1470
+ Leaf save_path[MAX_STACK];
1471
+ Doc doc = self_doc(self);
1472
+ const char *path = 0;
1473
+ size_t wlen;
1474
+
1475
+ wlen = doc->where - doc->where_path;
1476
+ if (0 < wlen) {
1477
+ memcpy(save_path, doc->where_path, sizeof(Leaf) * (wlen + 1));
1478
+ }
1479
+ if (1 <= argc) {
1480
+ Check_Type(*argv, T_STRING);
1481
+ path = StringValuePtr(*argv);
1482
+ if ('/' == *path) {
1483
+ doc->where = doc->where_path;
1484
+ path++;
1485
+ }
1486
+ if (0 != move_step(doc, path, 1)) {
1487
+ if (0 < wlen) {
1488
+ memcpy(doc->where_path, save_path, sizeof(Leaf) * (wlen + 1));
1489
+ }
1490
+ return Qnil;
1491
+ }
1492
+ }
1493
+ if (COL_VAL == (*doc->where)->value_type && 0 != (*doc->where)->elements) {
1494
+ Leaf first = (*doc->where)->elements->next;
1495
+ Leaf e = first;
1496
+
1497
+ doc->where++;
1498
+ do {
1499
+ *doc->where = e;
1500
+ rb_yield(self);
1501
+ e = e->next;
1502
+ } while (e != first);
1503
+ }
1504
+ if (0 < wlen) {
1505
+ memcpy(doc->where_path, save_path, sizeof(Leaf) * (wlen + 1));
1506
+ }
1531
1507
  }
1532
1508
  return Qnil;
1533
1509
  }
@@ -1538,7 +1514,8 @@ doc_each_child(int argc, VALUE *argv, VALUE self) {
1538
1514
  * of the JSON document. The parameter passed to the block on yield is the
1539
1515
  * value of the leaf. Only those leaves below the element specified by the
1540
1516
  * path parameter are processed.
1541
- * @param [String] path if provided it identified the top of the branch to process the leaf values of
1517
+ * @param [String] path if provided it identified the top of the branch to
1518
+ * process the leaf values of
1542
1519
  * @yieldparam [Object] val each leaf value
1543
1520
  * @example
1544
1521
  * Oj::Doc.open('[3,[2,1]]') { |doc|
@@ -1555,20 +1532,19 @@ doc_each_child(int argc, VALUE *argv, VALUE self) {
1555
1532
  * }
1556
1533
  * #=> [2, 1]
1557
1534
  */
1558
- static VALUE
1559
- doc_each_value(int argc, VALUE *argv, VALUE self) {
1535
+ static VALUE doc_each_value(int argc, VALUE *argv, VALUE self) {
1560
1536
  if (rb_block_given_p()) {
1561
- Doc doc = self_doc(self);
1562
- const char *path = 0;
1563
- Leaf leaf;
1564
-
1565
- if (1 <= argc) {
1566
- Check_Type(*argv, T_STRING);
1567
- path = StringValuePtr(*argv);
1568
- }
1569
- if (0 != (leaf = get_doc_leaf(doc, path))) {
1570
- each_value(doc, leaf);
1571
- }
1537
+ Doc doc = self_doc(self);
1538
+ const char *path = 0;
1539
+ Leaf leaf;
1540
+
1541
+ if (1 <= argc) {
1542
+ Check_Type(*argv, T_STRING);
1543
+ path = StringValuePtr(*argv);
1544
+ }
1545
+ if (0 != (leaf = get_doc_leaf(doc, path))) {
1546
+ each_value(doc, leaf);
1547
+ }
1572
1548
  }
1573
1549
  return Qnil;
1574
1550
  }
@@ -1577,52 +1553,53 @@ doc_each_value(int argc, VALUE *argv, VALUE self) {
1577
1553
  *
1578
1554
  * Dumps the document or nodes to a new JSON document. It uses the default
1579
1555
  * options for generating the JSON.
1580
- * @param path [String] if provided it identified the top of the branch to dump to JSON
1581
- * @param filename [String] if provided it is the filename to write the output to
1556
+ * @param path [String] if provided it identified the top of the branch to
1557
+ * dump to JSON
1558
+ * @param filename [String] if provided it is the filename to write the output
1559
+ * to
1582
1560
  * @example
1583
1561
  * Oj::Doc.open('[3,[2,1]]') { |doc|
1584
1562
  * doc.dump('/2')
1585
1563
  * }
1586
1564
  * #=> "[2,1]"
1587
1565
  */
1588
- static VALUE
1589
- doc_dump(int argc, VALUE *argv, VALUE self) {
1590
- Doc doc = self_doc(self);
1591
- Leaf leaf;
1592
- const char *path = 0;
1593
- const char *filename = 0;
1566
+ static VALUE doc_dump(int argc, VALUE *argv, VALUE self) {
1567
+ Doc doc = self_doc(self);
1568
+ Leaf leaf;
1569
+ const char *path = 0;
1570
+ const char *filename = 0;
1594
1571
 
1595
1572
  if (1 <= argc) {
1596
- if (Qnil != *argv) {
1597
- Check_Type(*argv, T_STRING);
1598
- path = StringValuePtr(*argv);
1599
- }
1600
- if (2 <= argc) {
1601
- Check_Type(argv[1], T_STRING);
1602
- filename = StringValuePtr(argv[1]);
1603
- }
1573
+ if (Qnil != *argv) {
1574
+ Check_Type(*argv, T_STRING);
1575
+ path = StringValuePtr(*argv);
1576
+ }
1577
+ if (2 <= argc) {
1578
+ Check_Type(argv[1], T_STRING);
1579
+ filename = StringValuePtr(argv[1]);
1580
+ }
1604
1581
  }
1605
1582
  if (0 != (leaf = get_doc_leaf(doc, path))) {
1606
- volatile VALUE rjson;
1607
-
1608
- if (0 == filename) {
1609
- char buf[4096];
1610
- struct _out out;
1611
-
1612
- out.buf = buf;
1613
- out.end = buf + sizeof(buf) - 10;
1614
- out.allocated = false;
1615
- out.omit_nil = oj_default_options.dump_opts.omit_nil;
1616
- oj_dump_leaf_to_json(leaf, &oj_default_options, &out);
1617
- rjson = rb_str_new2(out.buf);
1618
- if (out.allocated) {
1619
- xfree(out.buf);
1620
- }
1621
- } else {
1622
- oj_write_leaf_to_file(leaf, filename, &oj_default_options);
1623
- rjson = Qnil;
1624
- }
1625
- return rjson;
1583
+ volatile VALUE rjson;
1584
+
1585
+ if (0 == filename) {
1586
+ char buf[4096];
1587
+ struct _out out;
1588
+
1589
+ out.buf = buf;
1590
+ out.end = buf + sizeof(buf) - 10;
1591
+ out.allocated = false;
1592
+ out.omit_nil = oj_default_options.dump_opts.omit_nil;
1593
+ oj_dump_leaf_to_json(leaf, &oj_default_options, &out);
1594
+ rjson = rb_str_new2(out.buf);
1595
+ if (out.allocated) {
1596
+ xfree(out.buf);
1597
+ }
1598
+ } else {
1599
+ oj_write_leaf_to_file(leaf, filename, &oj_default_options);
1600
+ rjson = Qnil;
1601
+ }
1602
+ return rjson;
1626
1603
  }
1627
1604
  return Qnil;
1628
1605
  }
@@ -1635,8 +1612,7 @@ doc_dump(int argc, VALUE *argv, VALUE self) {
1635
1612
  * @example
1636
1613
  * Oj::Doc.open('[1,2,3]') { |doc| doc.size() } #=> 4
1637
1614
  */
1638
- static VALUE
1639
- doc_size(VALUE self) {
1615
+ static VALUE doc_size(VALUE self) {
1640
1616
  return ULONG2NUM(((Doc)DATA_PTR(self))->size);
1641
1617
  }
1642
1618
 
@@ -1649,16 +1625,15 @@ doc_size(VALUE self) {
1649
1625
  * doc.size() #=> 4
1650
1626
  * doc.close()
1651
1627
  */
1652
- static VALUE
1653
- doc_close(VALUE self) {
1654
- Doc doc = self_doc(self);
1628
+ static VALUE doc_close(VALUE self) {
1629
+ Doc doc = self_doc(self);
1655
1630
 
1656
1631
  rb_gc_unregister_address(&doc->self);
1657
1632
  DATA_PTR(doc->self) = 0;
1658
1633
  if (0 != doc) {
1659
- xfree(doc->json);
1660
- doc_free(doc);
1661
- xfree(doc);
1634
+ xfree(doc->json);
1635
+ doc_free(doc);
1636
+ xfree(doc);
1662
1637
  }
1663
1638
  return Qnil;
1664
1639
  }
@@ -1667,8 +1642,7 @@ doc_close(VALUE self) {
1667
1642
  Oj = rb_define_module("Oj");
1668
1643
  #endif
1669
1644
 
1670
- static VALUE
1671
- doc_not_implemented(VALUE self) {
1645
+ static VALUE doc_not_implemented(VALUE self) {
1672
1646
  rb_raise(rb_eNotImpError, "Not implemented.");
1673
1647
  return Qnil;
1674
1648
  }
@@ -1709,18 +1683,14 @@ doc_not_implemented(VALUE self) {
1709
1683
  * # move and get value
1710
1684
  * Oj::Doc.open(json) do |doc|
1711
1685
  * doc.move('/1/two')
1712
- * # doc location is now at the 'two' element of the hash that is the first element of the array.
1713
- * doc.fetch()
1714
- * end
1686
+ * # doc location is now at the 'two' element of the hash that is the first
1687
+ * element of the array. doc.fetch() end
1715
1688
  * #=> 2
1716
1689
  *
1717
- * # Now try again using a path to Oj::Doc.fetch() directly and not using a block.
1718
- * doc = Oj::Doc.open(json)
1719
- * doc.fetch('/2/three') #=> 3
1720
- * doc.close()
1690
+ * # Now try again using a path to Oj::Doc.fetch() directly and not using a
1691
+ * block. doc = Oj::Doc.open(json) doc.fetch('/2/three') #=> 3 doc.close()
1721
1692
  */
1722
- void
1723
- oj_init_doc() {
1693
+ void oj_init_doc() {
1724
1694
  oj_doc_class = rb_define_class_under(Oj, "Doc", rb_cObject);
1725
1695
  rb_define_singleton_method(oj_doc_class, "open", doc_open, 1);
1726
1696
  rb_define_singleton_method(oj_doc_class, "open_file", doc_open_file, 1);