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