brianmario-yajl-ruby 0.4.8 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +21 -0
- data/README.rdoc +13 -0
- data/VERSION.yml +2 -2
- data/benchmark/encode.rb +4 -3
- data/benchmark/encode_json_and_marshal.rb +4 -3
- data/benchmark/encode_json_and_yaml.rb +4 -3
- data/benchmark/parse.rb +5 -4
- data/benchmark/parse_json_and_marshal.rb +4 -3
- data/benchmark/parse_json_and_yaml.rb +4 -3
- data/benchmark/parse_stream.rb +48 -0
- data/benchmark/subjects/twitter_stream.json +430 -0
- data/examples/http/twitter_search_api.rb +15 -0
- data/examples/http/twitter_stream_api.rb +24 -0
- data/examples/parsing/from_file.rb +14 -0
- data/examples/parsing/from_stdin.rb +9 -0
- data/examples/parsing/from_string.rb +15 -0
- data/ext/api/yajl_parse.h +3 -0
- data/ext/extconf.rb +2 -1
- data/ext/yajl.c +5 -0
- data/ext/yajl_ext.c +235 -122
- data/ext/yajl_ext.h +49 -36
- data/ext/yajl_lex.c +7 -0
- data/ext/yajl_lex.h +2 -0
- data/ext/yajl_parser.c +3 -1
- data/lib/yajl.rb +18 -17
- data/lib/yajl/bzip2.rb +1 -1
- data/lib/yajl/bzip2/stream_reader.rb +1 -1
- data/lib/yajl/bzip2/stream_writer.rb +1 -1
- data/lib/yajl/deflate.rb +1 -1
- data/lib/yajl/deflate/stream_reader.rb +1 -1
- data/lib/yajl/deflate/stream_writer.rb +1 -1
- data/lib/yajl/gzip.rb +1 -1
- data/lib/yajl/gzip/stream_reader.rb +1 -1
- data/lib/yajl/gzip/stream_writer.rb +1 -1
- data/lib/yajl/http_stream.rb +21 -5
- data/spec/encoding/encoding_spec.rb +14 -9
- data/spec/http/http_spec.rb +1 -5
- data/spec/parsing/active_support_spec.rb +5 -3
- data/spec/parsing/chunked_spec.rb +72 -0
- data/spec/parsing/fixtures_spec.rb +4 -2
- data/spec/parsing/one_off_spec.rb +2 -1
- data/spec/spec_helper.rb +8 -1
- data/yajl-ruby.gemspec +17 -3
- metadata +16 -2
@@ -0,0 +1,15 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../../lib')
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'yajl/http_stream'
|
6
|
+
require 'uri'
|
7
|
+
|
8
|
+
unless keywords = ARGV[0]
|
9
|
+
puts "\nUsage: ruby examples/http/twitter_search_api.rb keyword\n\n"
|
10
|
+
exit(0)
|
11
|
+
end
|
12
|
+
captured = 0
|
13
|
+
uri = URI.parse("http://search.twitter.com/search.json?q=#{keywords}")
|
14
|
+
|
15
|
+
puts Yajl::HttpStream.get(uri).inspect
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../../lib')
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'yajl/http_stream'
|
6
|
+
require 'uri'
|
7
|
+
|
8
|
+
unless (username = ARGV[0]) && (password = ARGV[1])
|
9
|
+
puts "\nUsage: ruby examples/http/twitter_stream_api.rb username password\n\n"
|
10
|
+
exit(0)
|
11
|
+
end
|
12
|
+
captured = 0
|
13
|
+
uri = URI.parse("http://#{username}:#{password}@stream.twitter.com/spritzer.json")
|
14
|
+
|
15
|
+
trap('INT') {
|
16
|
+
puts "\n\nCaptured #{captured} objects from the stream"
|
17
|
+
puts "CTRL+C caught, later!"
|
18
|
+
exit(0)
|
19
|
+
}
|
20
|
+
|
21
|
+
Yajl::HttpStream.get(uri) do |hash|
|
22
|
+
puts hash.inspect
|
23
|
+
captured += 1
|
24
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'yajl'
|
5
|
+
|
6
|
+
unless file = ARGV[0]
|
7
|
+
puts "\nUsage: ruby examples/from_file.rb benchmark/subjects/item.json\n\n"
|
8
|
+
exit(0)
|
9
|
+
end
|
10
|
+
|
11
|
+
json = File.new(file, 'r')
|
12
|
+
|
13
|
+
hash = Yajl::Parser.new.parse(json)
|
14
|
+
puts hash.inspect
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'yajl'
|
5
|
+
require 'stringio'
|
6
|
+
|
7
|
+
unless string = ARGV[0]
|
8
|
+
puts "\nUsage: ruby examples/from_string.rb '{\"foo\": 1145}'\n\n"
|
9
|
+
exit(0)
|
10
|
+
end
|
11
|
+
|
12
|
+
json = StringIO.new(string)
|
13
|
+
|
14
|
+
hash = Yajl::Parser.new.parse(json)
|
15
|
+
puts hash.inspect
|
data/ext/api/yajl_parse.h
CHANGED
@@ -131,6 +131,9 @@ extern "C" {
|
|
131
131
|
const yajl_parser_config * config,
|
132
132
|
const yajl_alloc_funcs * allocFuncs,
|
133
133
|
void * ctx);
|
134
|
+
|
135
|
+
/** allow resetting of the lexer without the need to realloc a new parser */
|
136
|
+
void yajl_reset_parser(yajl_handle hand);
|
134
137
|
|
135
138
|
/** free a parser handle */
|
136
139
|
void YAJL_API yajl_free(yajl_handle handle);
|
data/ext/extconf.rb
CHANGED
data/ext/yajl.c
CHANGED
data/ext/yajl_ext.c
CHANGED
@@ -1,55 +1,63 @@
|
|
1
1
|
#include "yajl_ext.h"
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
// Helpers for building objects
|
4
|
+
void yajl_check_and_fire_callback(void * ctx) {
|
5
|
+
struct yajl_parser_wrapper * wrapper;
|
6
|
+
GetParser((VALUE)ctx, wrapper);
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
// No need to do any of this if the callback isn't even setup
|
9
|
+
if (wrapper->parse_complete_callback != Qnil) {
|
10
|
+
int len = RARRAY_LEN(wrapper->builderStack);
|
11
|
+
if (len == 1 && wrapper->nestedArrayLevel == 0 && wrapper->nestedHashLevel == 0) {
|
12
|
+
rb_funcall(wrapper->parse_complete_callback, intern_call, 1, rb_ary_pop(wrapper->builderStack));
|
13
|
+
}
|
11
14
|
}
|
12
15
|
}
|
13
16
|
|
14
|
-
void
|
15
|
-
|
17
|
+
void yajl_set_static_value(void * ctx, VALUE val) {
|
18
|
+
struct yajl_parser_wrapper * wrapper;
|
19
|
+
VALUE lastEntry, hash;
|
20
|
+
int len;
|
16
21
|
|
22
|
+
GetParser((VALUE)ctx, wrapper);
|
23
|
+
|
24
|
+
len = RARRAY_LEN(wrapper->builderStack);
|
17
25
|
if (len > 0) {
|
18
|
-
|
19
|
-
VALUE hash;
|
26
|
+
lastEntry = rb_ary_entry(wrapper->builderStack, len-1);
|
20
27
|
switch (TYPE(lastEntry)) {
|
21
28
|
case T_ARRAY:
|
22
29
|
rb_ary_push(lastEntry, val);
|
23
30
|
if (TYPE(val) == T_HASH || TYPE(val) == T_ARRAY) {
|
24
|
-
rb_ary_push(
|
31
|
+
rb_ary_push(wrapper->builderStack, val);
|
25
32
|
}
|
26
33
|
break;
|
27
34
|
case T_HASH:
|
28
35
|
rb_hash_aset(lastEntry, val, Qnil);
|
29
|
-
rb_ary_push(
|
36
|
+
rb_ary_push(wrapper->builderStack, val);
|
30
37
|
break;
|
31
38
|
case T_STRING:
|
32
|
-
hash = rb_ary_entry(
|
39
|
+
hash = rb_ary_entry(wrapper->builderStack, len-2);
|
33
40
|
if (TYPE(hash) == T_HASH) {
|
34
41
|
rb_hash_aset(hash, lastEntry, val);
|
35
|
-
rb_ary_pop(
|
42
|
+
rb_ary_pop(wrapper->builderStack);
|
36
43
|
if (TYPE(val) == T_HASH || TYPE(val) == T_ARRAY) {
|
37
|
-
rb_ary_push(
|
44
|
+
rb_ary_push(wrapper->builderStack, val);
|
38
45
|
}
|
39
46
|
}
|
40
47
|
break;
|
41
48
|
}
|
42
49
|
} else {
|
43
|
-
rb_ary_push(
|
50
|
+
rb_ary_push(wrapper->builderStack, val);
|
44
51
|
}
|
45
52
|
}
|
46
53
|
|
47
|
-
void
|
54
|
+
void yajl_encode_part(yajl_gen hand, VALUE obj, VALUE io) {
|
48
55
|
VALUE str, outBuff, otherObj;
|
49
56
|
int objLen;
|
50
57
|
int idx = 0;
|
51
58
|
const unsigned char * buffer;
|
52
59
|
unsigned int len;
|
60
|
+
|
53
61
|
yajl_gen_get_buf(hand, &buffer, &len);
|
54
62
|
outBuff = rb_str_new((const char *)buffer, len);
|
55
63
|
rb_io_write(io, outBuff);
|
@@ -65,9 +73,9 @@ void encode_part(yajl_gen hand, VALUE obj, VALUE io) {
|
|
65
73
|
for(idx=0; idx<RARRAY_LEN(keys); idx++) {
|
66
74
|
entry = rb_ary_entry(keys, idx);
|
67
75
|
// the key
|
68
|
-
|
76
|
+
yajl_encode_part(hand, entry, io);
|
69
77
|
// the value
|
70
|
-
|
78
|
+
yajl_encode_part(hand, rb_hash_aref(obj, entry), io);
|
71
79
|
}
|
72
80
|
|
73
81
|
yajl_gen_map_close(hand);
|
@@ -76,7 +84,7 @@ void encode_part(yajl_gen hand, VALUE obj, VALUE io) {
|
|
76
84
|
yajl_gen_array_open(hand);
|
77
85
|
for(idx=0; idx<RARRAY_LEN(obj); idx++) {
|
78
86
|
otherObj = rb_ary_entry(obj, idx);
|
79
|
-
|
87
|
+
yajl_encode_part(hand, otherObj, io);
|
80
88
|
}
|
81
89
|
yajl_gen_array_close(hand);
|
82
90
|
break;
|
@@ -104,180 +112,285 @@ void encode_part(yajl_gen hand, VALUE obj, VALUE io) {
|
|
104
112
|
}
|
105
113
|
}
|
106
114
|
|
107
|
-
|
108
|
-
|
109
|
-
|
115
|
+
void yajl_parser_wrapper_free(void * wrapper) {
|
116
|
+
struct yajl_parser_wrapper * w = wrapper;
|
117
|
+
yajl_free(w->parser);
|
118
|
+
free(w);
|
119
|
+
}
|
120
|
+
|
121
|
+
void yajl_parser_wrapper_mark(void * wrapper) {
|
122
|
+
struct yajl_parser_wrapper * w = wrapper;
|
123
|
+
rb_gc_mark(w->builderStack);
|
124
|
+
rb_gc_mark(w->parse_complete_callback);
|
125
|
+
}
|
126
|
+
|
127
|
+
// YAJL Callbacks
|
128
|
+
static int yajl_found_null(void * ctx) {
|
129
|
+
yajl_set_static_value(ctx, Qnil);
|
130
|
+
yajl_check_and_fire_callback(ctx);
|
110
131
|
return 1;
|
111
132
|
}
|
112
133
|
|
113
|
-
static int
|
114
|
-
|
115
|
-
|
134
|
+
static int yajl_found_boolean(void * ctx, int boolean) {
|
135
|
+
yajl_set_static_value(ctx, boolean ? Qtrue : Qfalse);
|
136
|
+
yajl_check_and_fire_callback(ctx);
|
116
137
|
return 1;
|
117
138
|
}
|
118
139
|
|
119
|
-
static int
|
140
|
+
static int yajl_found_number(void * ctx, const char * numberVal, unsigned int numberLen) {
|
120
141
|
VALUE subString = rb_str_new(numberVal, numberLen);
|
121
|
-
|
122
|
-
|
142
|
+
char * cSubString = RSTRING_PTR(subString);
|
143
|
+
|
144
|
+
if (strstr(cSubString, ".") != NULL ||
|
145
|
+
strstr(cSubString, "e") != NULL ||
|
146
|
+
strstr(cSubString, "E") != NULL) {
|
147
|
+
yajl_set_static_value(ctx, rb_Float(subString));
|
123
148
|
} else {
|
124
|
-
|
149
|
+
yajl_set_static_value(ctx, rb_Integer(subString));
|
125
150
|
}
|
126
|
-
|
151
|
+
yajl_check_and_fire_callback(ctx);
|
127
152
|
return 1;
|
128
153
|
}
|
129
154
|
|
130
|
-
static int
|
131
|
-
|
132
|
-
|
155
|
+
static int yajl_found_string(void * ctx, const unsigned char * stringVal, unsigned int stringLen) {
|
156
|
+
yajl_set_static_value(ctx, rb_str_new((const char *)stringVal, stringLen));
|
157
|
+
yajl_check_and_fire_callback(ctx);
|
133
158
|
return 1;
|
134
159
|
}
|
135
160
|
|
136
|
-
static int
|
137
|
-
|
161
|
+
static int yajl_found_hash_key(void * ctx, const unsigned char * stringVal, unsigned int stringLen) {
|
162
|
+
yajl_set_static_value(ctx, rb_str_new((const char *)stringVal, stringLen));
|
163
|
+
yajl_check_and_fire_callback(ctx);
|
138
164
|
return 1;
|
139
165
|
}
|
140
166
|
|
141
|
-
static int
|
142
|
-
|
167
|
+
static int yajl_found_start_hash(void * ctx) {
|
168
|
+
struct yajl_parser_wrapper * wrapper;
|
169
|
+
GetParser((VALUE)ctx, wrapper);
|
170
|
+
wrapper->nestedHashLevel++;
|
171
|
+
yajl_set_static_value(ctx, rb_hash_new());
|
143
172
|
return 1;
|
144
173
|
}
|
145
174
|
|
146
|
-
static int
|
147
|
-
|
148
|
-
|
175
|
+
static int yajl_found_end_hash(void * ctx) {
|
176
|
+
struct yajl_parser_wrapper * wrapper;
|
177
|
+
GetParser((VALUE)ctx, wrapper);
|
178
|
+
wrapper->nestedHashLevel--;
|
179
|
+
if (RARRAY_LEN(wrapper->builderStack) > 1) {
|
180
|
+
rb_ary_pop(wrapper->builderStack);
|
149
181
|
}
|
150
|
-
|
182
|
+
yajl_check_and_fire_callback(ctx);
|
151
183
|
return 1;
|
152
184
|
}
|
153
185
|
|
154
|
-
static int
|
155
|
-
|
186
|
+
static int yajl_found_start_array(void * ctx) {
|
187
|
+
struct yajl_parser_wrapper * wrapper;
|
188
|
+
GetParser((VALUE)ctx, wrapper);
|
189
|
+
wrapper->nestedArrayLevel++;
|
190
|
+
yajl_set_static_value(ctx, rb_ary_new());
|
156
191
|
return 1;
|
157
192
|
}
|
158
193
|
|
159
|
-
static int
|
160
|
-
|
161
|
-
|
194
|
+
static int yajl_found_end_array(void * ctx) {
|
195
|
+
struct yajl_parser_wrapper * wrapper;
|
196
|
+
GetParser((VALUE)ctx, wrapper);
|
197
|
+
wrapper->nestedArrayLevel--;
|
198
|
+
if (RARRAY_LEN(wrapper->builderStack) > 1) {
|
199
|
+
rb_ary_pop(wrapper->builderStack);
|
162
200
|
}
|
163
|
-
|
201
|
+
yajl_check_and_fire_callback(ctx);
|
164
202
|
return 1;
|
165
203
|
}
|
166
204
|
|
167
|
-
static VALUE t_setParseComplete(VALUE self, VALUE callback) {
|
168
|
-
parse_complete_callback = callback;
|
169
|
-
return Qnil;
|
170
|
-
}
|
171
205
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
206
|
+
/** Ruby Interface */
|
207
|
+
|
208
|
+
// Yajl::Parser
|
209
|
+
static VALUE rb_yajl_parser_new(int argc, VALUE * argv, VALUE klass) {
|
210
|
+
struct yajl_parser_wrapper * wrapper;
|
211
|
+
yajl_parser_config cfg;
|
212
|
+
VALUE opts, obj;
|
213
|
+
int allowComments = 1, checkUTF8 = 1;
|
179
214
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
}
|
184
|
-
if (chunkedParser == NULL) {
|
185
|
-
// allocate our parser
|
186
|
-
chunkedParser = yajl_alloc(&callbacks, &cfg, NULL, (void *)context);
|
187
|
-
}
|
215
|
+
// Scan off config vars
|
216
|
+
if (rb_scan_args(argc, argv, "01", &opts) == 1) {
|
217
|
+
Check_Type(opts, T_HASH);
|
188
218
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
219
|
+
if (rb_hash_aref(opts, ID2SYM(sym_allow_comments)) == Qfalse) {
|
220
|
+
allowComments = 0;
|
221
|
+
}
|
222
|
+
if (rb_hash_aref(opts, ID2SYM(sym_check_utf8)) == Qfalse) {
|
223
|
+
checkUTF8 = 0;
|
194
224
|
}
|
195
|
-
} else {
|
196
|
-
rb_raise(cParseError, "%s", "The on_parse_complete callback isn't setup, parsing useless.");
|
197
|
-
}
|
198
|
-
|
199
|
-
if (RARRAY_LEN(context) == 0) {
|
200
|
-
yajl_free(chunkedParser);
|
201
225
|
}
|
226
|
+
cfg = (yajl_parser_config){allowComments, checkUTF8};
|
202
227
|
|
203
|
-
|
228
|
+
obj = Data_Make_Struct(klass, struct yajl_parser_wrapper, yajl_parser_wrapper_mark, yajl_parser_wrapper_free, wrapper);
|
229
|
+
wrapper->parser = yajl_alloc(&callbacks, &cfg, NULL, (void *)obj);
|
230
|
+
wrapper->nestedArrayLevel = 0;
|
231
|
+
wrapper->nestedHashLevel = 0;
|
232
|
+
wrapper->builderStack = rb_ary_new();
|
233
|
+
wrapper->parse_complete_callback = Qnil;
|
234
|
+
rb_obj_call_init(obj, 0, 0);
|
235
|
+
return obj;
|
204
236
|
}
|
205
237
|
|
206
|
-
static VALUE
|
238
|
+
static VALUE rb_yajl_parser_init(int argc, VALUE * argv, VALUE self) {
|
239
|
+
return self;
|
240
|
+
}
|
241
|
+
|
242
|
+
static VALUE rb_yajl_parser_parse(int argc, VALUE * argv, VALUE self) {
|
243
|
+
struct yajl_parser_wrapper * wrapper;
|
207
244
|
yajl_status stat;
|
208
|
-
|
245
|
+
VALUE parsed, rbufsize, io;
|
209
246
|
|
210
|
-
|
211
|
-
|
247
|
+
GetParser(self, wrapper);
|
248
|
+
parsed = rb_str_new2("");
|
212
249
|
|
213
|
-
|
214
|
-
|
250
|
+
// setup our parameters
|
251
|
+
rb_scan_args(argc, argv, "11", &io, &rbufsize);
|
252
|
+
if (NIL_P(rbufsize)) {
|
253
|
+
rbufsize = INT2FIX(READ_BUFSIZE);
|
254
|
+
} else {
|
255
|
+
Check_Type(rbufsize, T_FIXNUM);
|
256
|
+
}
|
215
257
|
|
216
258
|
// now parse from the IO
|
217
259
|
while (rb_funcall(io, intern_eof, 0) != Qtrue) {
|
218
260
|
rb_funcall(io, intern_io_read, 2, rbufsize, parsed);
|
219
261
|
|
220
|
-
stat = yajl_parse(
|
262
|
+
stat = yajl_parse(wrapper->parser, (const unsigned char *)RSTRING_PTR(parsed), RSTRING_LEN(parsed));
|
221
263
|
|
222
264
|
if (stat != yajl_status_ok && stat != yajl_status_insufficient_data) {
|
223
|
-
unsigned char * str = yajl_get_error(
|
265
|
+
unsigned char * str = yajl_get_error(wrapper->parser, 1, (const unsigned char *)RSTRING_PTR(parsed), RSTRING_LEN(parsed));
|
224
266
|
rb_raise(cParseError, "%s", (const char *) str);
|
225
|
-
yajl_free_error(
|
267
|
+
yajl_free_error(wrapper->parser, str);
|
226
268
|
break;
|
227
269
|
}
|
228
270
|
}
|
229
271
|
|
230
272
|
// parse any remaining buffered data
|
231
|
-
stat = yajl_parse_complete(
|
232
|
-
|
273
|
+
stat = yajl_parse_complete(wrapper->parser);
|
274
|
+
|
275
|
+
if (wrapper->parse_complete_callback != Qnil) {
|
276
|
+
yajl_check_and_fire_callback((void *)self);
|
277
|
+
return Qnil;
|
278
|
+
}
|
279
|
+
|
280
|
+
return rb_ary_pop(wrapper->builderStack);
|
281
|
+
}
|
282
|
+
|
283
|
+
static VALUE rb_yajl_parser_parse_chunk(VALUE self, VALUE chunk) {
|
284
|
+
struct yajl_parser_wrapper * wrapper;
|
285
|
+
yajl_status stat;
|
233
286
|
|
234
|
-
|
235
|
-
|
287
|
+
GetParser(self, wrapper);
|
288
|
+
if (NIL_P(chunk)) {
|
289
|
+
rb_raise(cParseError, "Can't parse a nil string.");
|
236
290
|
return Qnil;
|
237
291
|
}
|
292
|
+
|
293
|
+
if (wrapper->parse_complete_callback != Qnil) {
|
294
|
+
stat = yajl_parse(wrapper->parser, (const unsigned char *)RSTRING_PTR(chunk), RSTRING_LEN(chunk));
|
295
|
+
if (stat != yajl_status_ok && stat != yajl_status_insufficient_data) {
|
296
|
+
unsigned char * str = yajl_get_error(wrapper->parser, 1, (const unsigned char *)RSTRING_PTR(chunk), RSTRING_LEN(chunk));
|
297
|
+
rb_raise(cParseError, "%s", (const char *) str);
|
298
|
+
yajl_free_error(wrapper->parser, str);
|
299
|
+
}
|
300
|
+
} else {
|
301
|
+
rb_raise(cParseError, "The on_parse_complete callback isn't setup, parsing useless.");
|
302
|
+
}
|
238
303
|
|
239
|
-
return
|
304
|
+
return Qnil;
|
240
305
|
}
|
241
306
|
|
242
|
-
static VALUE
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
VALUE outBuff;
|
248
|
-
|
249
|
-
hand = yajl_gen_alloc(&conf, NULL);
|
250
|
-
encode_part(hand, obj, io);
|
251
|
-
|
252
|
-
// just make sure we output the remaining buffer
|
253
|
-
yajl_gen_get_buf(hand, &buffer, &len);
|
254
|
-
outBuff = rb_str_new((const char *)buffer, len);
|
255
|
-
rb_io_write(io, outBuff);
|
256
|
-
|
257
|
-
yajl_gen_clear(hand);
|
258
|
-
yajl_gen_free(hand);
|
259
|
-
return Qnil;
|
307
|
+
static VALUE rb_yajl_set_complete_cb(VALUE self, VALUE callback) {
|
308
|
+
struct yajl_parser_wrapper * wrapper;
|
309
|
+
GetParser(self, wrapper);
|
310
|
+
wrapper->parse_complete_callback = callback;
|
311
|
+
return Qnil;
|
260
312
|
}
|
261
313
|
|
262
|
-
|
263
|
-
|
314
|
+
// Yajl::Encoder
|
315
|
+
static VALUE rb_yajl_encoder_new(int argc, VALUE * argv, VALUE klass) {
|
316
|
+
yajl_gen_config cfg;
|
317
|
+
yajl_gen encoder;
|
318
|
+
VALUE opts, obj, indent;
|
319
|
+
const char * indentString = " ";
|
320
|
+
int beautify = 0;
|
264
321
|
|
265
|
-
|
266
|
-
|
267
|
-
|
322
|
+
// Scan off config vars
|
323
|
+
if (rb_scan_args(argc, argv, "01", &opts) == 1) {
|
324
|
+
Check_Type(opts, T_HASH);
|
325
|
+
|
326
|
+
if (rb_hash_aref(opts, ID2SYM(sym_pretty)) == Qtrue) {
|
327
|
+
beautify = 1;
|
328
|
+
indent = rb_hash_aref(opts, ID2SYM(sym_indent));
|
329
|
+
if (indent != Qnil) {
|
330
|
+
Check_Type(indent, T_STRING);
|
331
|
+
indentString = RSTRING_PTR(indent);
|
332
|
+
}
|
333
|
+
}
|
334
|
+
}
|
335
|
+
cfg = (yajl_gen_config){beautify, indentString};
|
268
336
|
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
337
|
+
encoder = yajl_gen_alloc(&cfg, NULL);
|
338
|
+
obj = Data_Wrap_Struct(klass, 0, yajl_gen_free, encoder);
|
339
|
+
rb_obj_call_init(obj, 0, 0);
|
340
|
+
return obj;
|
341
|
+
}
|
342
|
+
|
343
|
+
static VALUE rb_yajl_encoder_init(int argc, VALUE * argv, VALUE self) {
|
344
|
+
return self;
|
345
|
+
}
|
346
|
+
|
347
|
+
static VALUE rb_yajl_encoder_encode(VALUE self, VALUE obj, VALUE io) {
|
348
|
+
yajl_gen encoder;
|
349
|
+
const unsigned char * buffer;
|
350
|
+
unsigned int len;
|
351
|
+
VALUE outBuff;
|
352
|
+
|
353
|
+
GetEncoder(self, encoder);
|
354
|
+
|
355
|
+
// begin encode process
|
356
|
+
yajl_encode_part(encoder, obj, io);
|
357
|
+
|
358
|
+
// just make sure we output the remaining buffer
|
359
|
+
yajl_gen_get_buf(encoder, &buffer, &len);
|
360
|
+
outBuff = rb_str_new((const char *)buffer, len);
|
361
|
+
rb_io_write(io, outBuff);
|
362
|
+
yajl_gen_clear(encoder);
|
363
|
+
|
364
|
+
return Qnil;
|
365
|
+
}
|
366
|
+
|
367
|
+
// Ruby Extension initializer
|
368
|
+
void Init_yajl_ext() {
|
369
|
+
mYajl = rb_define_module("Yajl");
|
273
370
|
|
274
371
|
VALUE rb_cStandardError = rb_const_get(rb_cObject, rb_intern("StandardError"));
|
275
372
|
cParseError = rb_define_class_under(mYajl, "ParseError", rb_cStandardError);
|
276
373
|
|
374
|
+
cParser = rb_define_class_under(mYajl, "Parser", rb_cObject);
|
375
|
+
rb_define_singleton_method(cParser, "new", rb_yajl_parser_new, -1);
|
376
|
+
rb_define_method(cParser, "initialize", rb_yajl_parser_init, -1);
|
377
|
+
rb_define_method(cParser, "parse", rb_yajl_parser_parse, -1);
|
378
|
+
rb_define_method(cParser, "parse_chunk", rb_yajl_parser_parse_chunk, -1);
|
379
|
+
rb_define_method(cParser, "<<", rb_yajl_parser_parse_chunk, 1);
|
380
|
+
rb_define_method(cParser, "on_parse_complete=", rb_yajl_set_complete_cb, 1);
|
381
|
+
|
382
|
+
cEncoder = rb_define_class_under(mYajl, "Encoder", rb_cObject);
|
383
|
+
rb_define_singleton_method(cEncoder, "new", rb_yajl_encoder_new, -1);
|
384
|
+
rb_define_method(cEncoder, "initialize", rb_yajl_encoder_init, -1);
|
385
|
+
rb_define_method(cEncoder, "encode", rb_yajl_encoder_encode, 2);
|
386
|
+
|
277
387
|
intern_io_read = rb_intern("read");
|
278
388
|
intern_eof = rb_intern("eof?");
|
279
|
-
intern_respond_to = rb_intern("respond_to?");
|
280
389
|
intern_call = rb_intern("call");
|
281
390
|
intern_keys = rb_intern("keys");
|
282
391
|
intern_to_s = rb_intern("to_s");
|
392
|
+
sym_allow_comments = rb_intern("allow_comments");
|
393
|
+
sym_check_utf8 = rb_intern("check_utf8");
|
394
|
+
sym_pretty = rb_intern("pretty");
|
395
|
+
sym_indent = rb_intern("indent");
|
283
396
|
}
|