oj 2.0.14 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of oj might be problematic. Click here for more details.

@@ -0,0 +1,166 @@
1
+ /* strict.c
2
+ * Copyright (c) 2012, Peter Ohler
3
+ * All rights reserved.
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * - Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * - Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * - Neither the name of Peter Ohler nor the names of its contributors may be
16
+ * used to endorse or promote products derived from this software without
17
+ * specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ */
30
+
31
+ #include <stdlib.h>
32
+ #include <stdio.h>
33
+ #include <string.h>
34
+ #include <unistd.h>
35
+
36
+ #include "oj.h"
37
+ #include "err.h"
38
+ #include "parse.h"
39
+
40
+ // Workaround in case INFINITY is not defined in math.h or if the OS is CentOS
41
+ #define OJ_INFINITY (1.0/0.0)
42
+
43
+ static void
44
+ noop_end(struct _ParseInfo *pi) {
45
+ }
46
+
47
+ static void
48
+ add_value(ParseInfo pi, VALUE val) {
49
+ pi->stack.head->val = val;
50
+ }
51
+
52
+ static void
53
+ add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
54
+ VALUE rstr = rb_str_new(str, len);
55
+
56
+ #if HAS_ENCODING_SUPPORT
57
+ rb_enc_associate(rstr, oj_utf8_encoding);
58
+ #endif
59
+ pi->stack.head->val = rstr;
60
+ }
61
+
62
+ static void
63
+ add_num(ParseInfo pi, NumInfo ni) {
64
+ pi->stack.head->val = oj_num_as_value(ni);
65
+ }
66
+
67
+ static VALUE
68
+ start_hash(ParseInfo pi) {
69
+ return rb_hash_new();
70
+ }
71
+
72
+ static VALUE
73
+ hash_key(ParseInfo pi, const char *key, size_t klen) {
74
+ VALUE rkey = rb_str_new(key, klen);
75
+
76
+ #if HAS_ENCODING_SUPPORT
77
+ rb_enc_associate(rkey, oj_utf8_encoding);
78
+ #endif
79
+ if (Yes == pi->options.sym_key) {
80
+ rkey = rb_str_intern(rkey);
81
+ }
82
+ return rkey;
83
+ }
84
+
85
+ static void
86
+ hash_set_cstr(ParseInfo pi, const char *key, size_t klen, const char *str, size_t len, const char *orig) {
87
+ VALUE rstr = rb_str_new(str, len);
88
+
89
+ #if HAS_ENCODING_SUPPORT
90
+ rb_enc_associate(rstr, oj_utf8_encoding);
91
+ #endif
92
+ rb_hash_aset(stack_peek(&pi->stack)->val, hash_key(pi, key, klen), rstr);
93
+ }
94
+
95
+ static void
96
+ hash_set_num(struct _ParseInfo *pi, const char *key, size_t klen, NumInfo ni) {
97
+ rb_hash_aset(stack_peek(&pi->stack)->val, hash_key(pi, key, klen), oj_num_as_value(ni));
98
+ }
99
+
100
+ static void
101
+ hash_set_value(ParseInfo pi, const char *key, size_t klen, VALUE value) {
102
+ rb_hash_aset(stack_peek(&pi->stack)->val, hash_key(pi, key, klen), value);
103
+ }
104
+
105
+ static VALUE
106
+ start_array(ParseInfo pi) {
107
+ return rb_ary_new();
108
+ }
109
+
110
+ static void
111
+ array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
112
+ VALUE rstr = rb_str_new(str, len);
113
+
114
+ #if HAS_ENCODING_SUPPORT
115
+ rb_enc_associate(rstr, oj_utf8_encoding);
116
+ #endif
117
+ rb_ary_push(stack_peek(&pi->stack)->val, rstr);
118
+ }
119
+
120
+ static void
121
+ array_append_num(ParseInfo pi, NumInfo ni) {
122
+ rb_ary_push(stack_peek(&pi->stack)->val, oj_num_as_value(ni));
123
+ }
124
+
125
+ static void
126
+ array_append_value(ParseInfo pi, VALUE value) {
127
+ rb_ary_push(stack_peek(&pi->stack)->val, value);
128
+ }
129
+
130
+ void
131
+ oj_set_strict_callbacks(ParseInfo pi) {
132
+ pi->start_hash = start_hash;
133
+ pi->end_hash = noop_end;
134
+ pi->hash_set_cstr = hash_set_cstr;
135
+ pi->hash_set_num = hash_set_num;
136
+ pi->hash_set_value = hash_set_value;
137
+ pi->start_array = start_array;
138
+ pi->end_array = noop_end;
139
+ pi->array_append_cstr = array_append_cstr;
140
+ pi->array_append_num = array_append_num;
141
+ pi->array_append_value = array_append_value;
142
+ pi->add_cstr = add_cstr;
143
+ pi->add_num = add_num;
144
+ pi->add_value = add_value;
145
+ pi->expect_value = 1;
146
+ }
147
+
148
+ VALUE
149
+ oj_strict_parse(int argc, VALUE *argv, VALUE self) {
150
+ struct _ParseInfo pi;
151
+
152
+ pi.options = oj_default_options;
153
+ oj_set_strict_callbacks(&pi);
154
+
155
+ return oj_pi_parse(argc, argv, &pi, 0);
156
+ }
157
+
158
+ VALUE
159
+ oj_strict_parse_cstr(int argc, VALUE *argv, char *json) {
160
+ struct _ParseInfo pi;
161
+
162
+ pi.options = oj_default_options;
163
+ oj_set_strict_callbacks(&pi);
164
+
165
+ return oj_pi_parse(argc, argv, &pi, json);
166
+ }
@@ -0,0 +1,48 @@
1
+ /* val_stack.c
2
+ * Copyright (c) 2011, Peter Ohler
3
+ * All rights reserved.
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * - Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * - Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * - Neither the name of Peter Ohler nor the names of its contributors may be
16
+ * used to endorse or promote products derived from this software without
17
+ * specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ */
30
+
31
+ #include "val_stack.h"
32
+
33
+ const char*
34
+ oj_stack_next_string(ValNext n) {
35
+ switch (n) {
36
+ case NEXT_ARRAY_NEW: return "array element or close";
37
+ case NEXT_ARRAY_ELEMENT: return "array element";
38
+ case NEXT_ARRAY_COMMA: return "comma";
39
+ case NEXT_HASH_NEW: return "hash pair or close";
40
+ case NEXT_HASH_KEY: return "hash key";
41
+ case NEXT_HASH_COLON: return "colon";
42
+ case NEXT_HASH_VALUE: return "hash value";
43
+ case NEXT_HASH_COMMA: return "comma";
44
+ case NEXT_NONE: break;
45
+ default: break;
46
+ }
47
+ return "nothing";
48
+ }
@@ -0,0 +1,167 @@
1
+ /* val_stack.h
2
+ * Copyright (c) 2011, Peter Ohler
3
+ * All rights reserved.
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * - Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * - Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * - Neither the name of Peter Ohler nor the names of its contributors may be
16
+ * used to endorse or promote products derived from this software without
17
+ * specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ */
30
+
31
+ #ifndef __OJ_VAL_STACK_H__
32
+ #define __OJ_VAL_STACK_H__
33
+
34
+ #include "ruby.h"
35
+ #include "odd.h"
36
+
37
+ #define STACK_INC 32
38
+
39
+ typedef enum {
40
+ NEXT_NONE = 0,
41
+ NEXT_ARRAY_NEW = 'a',
42
+ NEXT_ARRAY_ELEMENT = 'e',
43
+ NEXT_ARRAY_COMMA = ',',
44
+ NEXT_HASH_NEW = 'h',
45
+ NEXT_HASH_KEY = 'k',
46
+ NEXT_HASH_COLON = ':',
47
+ NEXT_HASH_VALUE = 'v',
48
+ NEXT_HASH_COMMA = 'n',
49
+ } ValNext;
50
+
51
+ typedef struct _Val {
52
+ VALUE val;
53
+ const char *key;
54
+ union {
55
+ const char *classname;
56
+ OddArgs odd_args;
57
+ };
58
+ uint16_t klen;
59
+ uint16_t clen;
60
+ char next; // ValNext
61
+ char k1; // first original character in the key
62
+ } *Val;
63
+
64
+ typedef struct _ValStack {
65
+ struct _Val base[STACK_INC];
66
+ Val head; // current stack
67
+ Val end; // stack end
68
+ Val tail; // pointer to one past last element name on stack
69
+ } *ValStack;
70
+
71
+ inline static void
72
+ stack_init(ValStack stack) {
73
+ stack->head = stack->base;
74
+ stack->end = stack->base + sizeof(stack->base) / sizeof(struct _Val);
75
+ stack->tail = stack->head;
76
+ stack->head->val = Qundef;
77
+ stack->head->key = 0;
78
+ stack->head->classname = 0;
79
+ stack->head->klen = 0;
80
+ stack->head->clen = 0;
81
+ stack->head->next = NEXT_NONE;
82
+ //stack->head->type = TYPE_NONE;
83
+ }
84
+
85
+ inline static int
86
+ stack_empty(ValStack stack) {
87
+ return (stack->head == stack->tail);
88
+ }
89
+
90
+ inline static void
91
+ stack_cleanup(ValStack stack) {
92
+ if (stack->base != stack->head) {
93
+ xfree(stack->head);
94
+ }
95
+ }
96
+
97
+ inline static void
98
+ stack_push(ValStack stack, VALUE val, ValNext next) {
99
+ if (stack->end <= stack->tail) {
100
+ size_t len = stack->end - stack->head;
101
+ size_t toff = stack->tail - stack->head;
102
+
103
+ if (stack->base == stack->head) {
104
+ stack->head = ALLOC_N(struct _Val, len + STACK_INC);
105
+ memcpy(stack->head, stack->base, sizeof(struct _Val) * len);
106
+ } else {
107
+ REALLOC_N(stack->head, struct _Val, len + STACK_INC);
108
+ }
109
+ stack->tail = stack->head + toff;
110
+ stack->end = stack->head + len + STACK_INC;
111
+ }
112
+ stack->tail->val = val;
113
+ stack->tail->next = next;
114
+ stack->tail->classname = 0;
115
+ stack->tail->key = 0;
116
+ stack->tail->clen = 0;
117
+ stack->tail->klen = 0;
118
+ //stack->tail->type = TYPE_NONE;
119
+ stack->tail++;
120
+ }
121
+
122
+ inline static size_t
123
+ stack_size(ValStack stack) {
124
+ return stack->tail - stack->head;
125
+ }
126
+
127
+ inline static Val
128
+ stack_peek(ValStack stack) {
129
+ if (stack->head < stack->tail) {
130
+ return stack->tail - 1;
131
+ }
132
+ return 0;
133
+ }
134
+
135
+ inline static Val
136
+ stack_peek_up(ValStack stack) {
137
+ if (stack->head < stack->tail - 1) {
138
+ return stack->tail - 2;
139
+ }
140
+ return 0;
141
+ }
142
+
143
+ inline static Val
144
+ stack_prev(ValStack stack) {
145
+ return stack->tail;
146
+ }
147
+
148
+ inline static VALUE
149
+ stack_head_val(ValStack stack) {
150
+ if (Qundef != stack->head->val) {
151
+ return stack->head->val;
152
+ }
153
+ return Qnil;
154
+ }
155
+
156
+ inline static Val
157
+ stack_pop(ValStack stack) {
158
+ if (stack->head < stack->tail) {
159
+ stack->tail--;
160
+ return stack->tail;
161
+ }
162
+ return 0;
163
+ }
164
+
165
+ extern const char* oj_stack_next_string(ValNext n);
166
+
167
+ #endif /* __OJ_VAL_STACK_H__ */
data/lib/oj.rb CHANGED
@@ -29,5 +29,6 @@ require 'oj/bag'
29
29
  require 'oj/error'
30
30
  require 'oj/mimic'
31
31
  require 'oj/saj'
32
+ require 'oj/schandler'
32
33
 
33
34
  require 'oj/oj' # C extension
@@ -1,7 +1,9 @@
1
1
  module Oj
2
- # A SAX style parse handler for JSON hence the acronym SAJ for Simple API for JSON. The Oj::Saj handler class should be subclassed
3
- # and then used with the Oj.saj_parse() method. The Saj methods will then be
4
- # called as the file is parsed.
2
+ # A SAX style parse handler for JSON hence the acronym SAJ for Simple API for
3
+ # JSON. The Oj::Saj handler class should be subclassed and then used with
4
+ # the Oj.sajkey_parse() method. The Saj methods will then be called as the
5
+ # file is parsed.
6
+ #
5
7
  # @example
6
8
  #
7
9
  # require 'oj'
@@ -21,8 +23,9 @@ module Oj
21
23
  # Oj.saj_parse(cnt, f)
22
24
  # end
23
25
  #
24
- # To make the desired methods active while parsing the desired method should be made public in the subclasses. If the
25
- # methods remain private they will not be called during parsing.
26
+ # To make the desired methods active while parsing the desired method should
27
+ # be made public in the subclasses. If the methods remain private they will
28
+ # not be called during parsing.
26
29
  #
27
30
  # def hash_start(key); end
28
31
  # def hash_end(key); end
@@ -36,9 +39,9 @@ module Oj
36
39
  def initialize()
37
40
  end
38
41
 
39
- # To make the desired methods active while parsing the desired method
40
- # should be made public in the subclasses. If the methods remain private
41
- # they will not be called during parsing.
42
+ # To make the desired methods active while parsing the desired method should
43
+ # be made public in the subclasses. If the methods remain private they will
44
+ # not be called during parsing.
42
45
  private
43
46
 
44
47
  def hash_start(key)
@@ -0,0 +1,70 @@
1
+ module Oj
2
+ # A Simple Callback Parser (SCP) for JSON. The Oj::ScHandler class should be
3
+ # subclassed and then used with the Oj.sc_parse() method. The Scp methods will
4
+ # then be called as the file is parsed. The handler does not have to be a
5
+ # subclass of the ScHandler class as long as it responds to the desired
6
+ # methods.
7
+ #
8
+ # @example
9
+ #
10
+ # require 'oj'
11
+ #
12
+ # class MyHandler < ::Oj::ScHandler
13
+ # def initialize()
14
+ # @hash_cnt = 0
15
+ # end
16
+ #
17
+ # def start_hash()
18
+ # @hash_cnt += 1
19
+ # end
20
+ # end
21
+ #
22
+ # cnt = MyHandler.new()
23
+ # File.open('any.json', 'r') do |f|
24
+ # Oj.sc_parse(cnt, f)
25
+ # end
26
+ #
27
+ # To make the desired methods active while parsing the desired method should
28
+ # be made public in the subclasses. If the methods remain private they will
29
+ # not be called during parsing.
30
+ #
31
+ # def hash_start(); end
32
+ # def hash_end(); end
33
+ # def array_start(); end
34
+ # def array_end(); end
35
+ # def add_value(value); end
36
+ # def error(message, line, column); end
37
+ #
38
+ class ScHandler
39
+ # Create a new instance of the ScHandler class.
40
+ def initialize()
41
+ end
42
+
43
+ # To make the desired methods active while parsing the desired method should
44
+ # be made public in the subclasses. If the methods remain private they will
45
+ # not be called during parsing.
46
+ private
47
+
48
+ def hash_start()
49
+ end
50
+
51
+ def hash_end()
52
+ end
53
+
54
+ def array_start()
55
+ end
56
+
57
+ def array_end()
58
+ end
59
+
60
+ def add_value(value)
61
+ end
62
+
63
+ def hash_set(h, key, value)
64
+ end
65
+
66
+ def array_append(a, value)
67
+ end
68
+
69
+ end # ScHandler
70
+ end # Oj