yaji 0.3.5-x64-mingw32

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.
@@ -0,0 +1,23 @@
1
+ # encoding: UTF-8
2
+ ENV['RC_ARCHS'] = '' if RUBY_PLATFORM =~ /darwin/
3
+
4
+ require 'mkmf'
5
+ require 'rbconfig'
6
+
7
+ def define(macro, value = nil)
8
+ $defs.push("-D #{[macro.upcase, value].compact.join('=')}")
9
+ end
10
+
11
+ $CFLAGS << " #{ENV["CFLAGS"]}"
12
+ $LDFLAGS << " #{ENV["LDFLAGS"]}"
13
+ $LIBS << " #{ENV["LIBS"]}"
14
+
15
+ $CFLAGS << ' -std=c99 -Wall -funroll-loops -Wextra '
16
+ $CFLAGS << ' -O0 -ggdb3 -pedantic ' if ENV['DEBUG']
17
+
18
+ # have_library('yajl', 'yajl_parse', 'yajl/yajl_parse.h')
19
+
20
+ define("READ_BUFSIZE", "8192")
21
+
22
+ create_header("yaji_config.h")
23
+ create_makefile("parser_ext")
@@ -0,0 +1,509 @@
1
+ /*
2
+ * Author:: Couchbase <info@couchbase.com>
3
+ * Copyright:: 2011 Couchbase, Inc.
4
+ * License:: Apache License, Version 2.0
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+
19
+ #include "parser_ext.h"
20
+
21
+ #define STATUS_CONTINUE 1
22
+
23
+ #define RB_P(OBJ) \
24
+ rb_funcall(rb_stderr, rb_intern("print"), 1, rb_funcall(OBJ, rb_intern("object_id"), 0)); \
25
+ rb_funcall(rb_stderr, rb_intern("print"), 1, rb_str_new2(" ")); \
26
+ rb_funcall(rb_stderr, rb_intern("print"), 1, rb_funcall(OBJ, rb_intern("class"), 0)); \
27
+ rb_funcall(rb_stderr, rb_intern("print"), 1, rb_str_new2(" ")); \
28
+ rb_funcall(rb_stderr, rb_intern("puts"), 1, rb_funcall(OBJ, rb_intern("inspect"), 0));
29
+
30
+ #define RERAISE_PARSER_ERROR(parser) \
31
+ { \
32
+ unsigned char* emsg = yajl_get_error(parser->handle, 1, \
33
+ (const unsigned char*)RSTRING_PTR(p->chunk), \
34
+ RSTRING_LEN(p->chunk)); \
35
+ VALUE errobj = rb_exc_new2(c_parse_error, (const char*) emsg); \
36
+ yajl_free_error(parser->handle, emsg); \
37
+ rb_exc_raise(errobj); \
38
+ }
39
+
40
+ static int yaji_null(void *ctx)
41
+ {
42
+ yaji_parser* p = (yaji_parser*) DATA_PTR(ctx);
43
+ VALUE rv = rb_ary_new3(3, p->path_str, sym_null, Qnil);
44
+ rb_ary_push(p->events, rv);
45
+ return STATUS_CONTINUE;
46
+ }
47
+
48
+ static int yaji_boolean(void *ctx, int val)
49
+ {
50
+ yaji_parser* p = (yaji_parser*) DATA_PTR(ctx);
51
+ VALUE rv = rb_ary_new3(3, p->path_str, sym_boolean, val ? Qtrue : Qfalse);
52
+ rb_ary_push(p->events, rv);
53
+ return STATUS_CONTINUE;
54
+ }
55
+
56
+ static int yaji_number(void *ctx, const char *val, unsigned int len)
57
+ {
58
+ yaji_parser* p = (yaji_parser*) DATA_PTR(ctx);
59
+ char buf[len+1];
60
+ buf[len] = 0;
61
+ memcpy(buf, val, len);
62
+ VALUE rv;
63
+
64
+ if (memchr(buf, '.', len) || memchr(buf, 'e', len) || memchr(buf, 'E', len)) {
65
+ rv = rb_ary_new3(3, p->path_str, sym_number, rb_float_new(strtod(buf, NULL)));
66
+ } else {
67
+ rv = rb_ary_new3(3, p->path_str, sym_number, rb_cstr2inum(buf, 10));
68
+ }
69
+ rb_ary_push(p->events, rv);
70
+ return STATUS_CONTINUE;
71
+ }
72
+
73
+ #ifdef HAVE_RUBY_ENCODING_H
74
+ #define YAJI_TO_STR(val, len, str) \
75
+ str = rb_str_new((const char *)val, len); \
76
+ rb_encoding *default_internal_enc = rb_default_internal_encoding(); \
77
+ rb_enc_associate(str, utf8_encoding); \
78
+ if (default_internal_enc) { \
79
+ str = rb_str_export_to_enc(str, default_internal_enc); \
80
+ }
81
+ #else
82
+ #define YAJI_TO_STR(val, len, str) \
83
+ str = rb_str_new((const char *)val, len);
84
+ #endif
85
+
86
+ static int yaji_string(void *ctx, const unsigned char *val, unsigned int len)
87
+ {
88
+ yaji_parser* p = (yaji_parser*) DATA_PTR(ctx);
89
+ VALUE str, rv;
90
+ YAJI_TO_STR((const char *)val, len, str);
91
+ rv = rb_ary_new3(3, p->path_str, sym_string, str);
92
+ rb_ary_push(p->events, rv);
93
+ return STATUS_CONTINUE;
94
+ }
95
+
96
+ static int yaji_hash_key(void *ctx, const unsigned char *val, unsigned int len)
97
+ {
98
+ yaji_parser* p = (yaji_parser*) DATA_PTR(ctx);
99
+ VALUE key, rv;
100
+ YAJI_TO_STR((const char *)val, len, key);
101
+ key = p->symbolize_keys ? ID2SYM(rb_to_id(key)) : key;
102
+ if (p->key_in_use) {
103
+ rb_ary_pop(p->path);
104
+ } else {
105
+ p->key_in_use = 1;
106
+ }
107
+ p->path_str = rb_ary_join(p->path, rb_str_new2("/"));
108
+ rb_str_freeze(p->path_str);
109
+ rv = rb_ary_new3(3, p->path_str, sym_hash_key, key);
110
+ rb_ary_push(p->events, rv);
111
+ rb_ary_push(p->path, key);
112
+ p->path_str = rb_ary_join(p->path, rb_str_new2("/"));
113
+ rb_str_freeze(p->path_str);
114
+ return STATUS_CONTINUE;
115
+ }
116
+
117
+ static int yaji_start_hash(void *ctx)
118
+ {
119
+ yaji_parser* p = (yaji_parser*) DATA_PTR(ctx);
120
+ p->key_in_use = 0;
121
+ VALUE rv = rb_ary_new3(3, p->path_str, sym_start_hash, Qnil);
122
+ rb_ary_push(p->events, rv);
123
+ return STATUS_CONTINUE;
124
+ }
125
+
126
+ static int yaji_end_hash(void *ctx)
127
+ {
128
+ yaji_parser* p = (yaji_parser*) DATA_PTR(ctx);
129
+ rb_ary_pop(p->path);
130
+ p->path_str = rb_ary_join(p->path, rb_str_new2("/"));
131
+ VALUE rv = rb_ary_new3(3, p->path_str, sym_end_hash, Qnil);
132
+ rb_ary_push(p->events, rv);
133
+ return STATUS_CONTINUE;
134
+ }
135
+
136
+ static int yaji_start_array(void *ctx)
137
+ {
138
+ yaji_parser* p = (yaji_parser*) DATA_PTR(ctx);
139
+ VALUE rv = rb_ary_new3(3, p->path_str, sym_start_array, Qnil);
140
+ rb_ary_push(p->path, rb_str_new2(""));
141
+ p->path_str = rb_ary_join(p->path, rb_str_new2("/"));
142
+ rb_str_freeze(p->path_str);
143
+ rb_ary_push(p->events, rv);
144
+ return STATUS_CONTINUE;
145
+ }
146
+
147
+ static int yaji_end_array(void *ctx)
148
+ {
149
+ yaji_parser* p = (yaji_parser*) DATA_PTR(ctx);
150
+
151
+ rb_ary_pop(p->path);
152
+ p->path_str = rb_ary_join(p->path, rb_str_new2("/"));
153
+
154
+ VALUE rv = rb_ary_new3(3, p->path_str, sym_end_array, Qnil);
155
+ rb_ary_push(p->events, rv);
156
+ return STATUS_CONTINUE;
157
+ }
158
+
159
+ static VALUE rb_yaji_each_iter(VALUE chunk, VALUE parser);
160
+
161
+ static VALUE rb_yaji_parser_parse_chunk(VALUE chunk, VALUE self)
162
+ {
163
+ yajl_status rc;
164
+ yaji_parser* p = (yaji_parser*) DATA_PTR(self);
165
+ const char* buf;
166
+ unsigned int len;
167
+ int i;
168
+
169
+ if (NIL_P(chunk) || (len = RSTRING_LEN(chunk)) == 0) {
170
+ return INT2FIX(0);
171
+ }
172
+ buf = RSTRING_PTR(chunk);
173
+ p->events = rb_ary_new();
174
+ p->chunk = chunk;
175
+ rc = yajl_parse(p->handle, (const unsigned char*)buf, len);
176
+ if (rc == yajl_status_error) {
177
+ RERAISE_PARSER_ERROR(p);
178
+ }
179
+ for (i=0; i<RARRAY_LEN(p->events); i++) {
180
+ if (NIL_P(p->input)) {
181
+ p->effective_proc = p->on_object_cb;
182
+ p->effective_filter = p->filter;
183
+ p->effective_with_path = p->with_path ? Qtrue : Qfalse;
184
+ rb_yaji_each_iter(RARRAY_PTR(p->events)[i], self);
185
+ } else {
186
+ rb_funcall(p->parser_cb, id_call, 1, RARRAY_PTR(p->events)[i]);
187
+ }
188
+ }
189
+ return rb_funcall(chunk, id_bytesize, 0, NULL);
190
+ }
191
+
192
+ static VALUE rb_yaji_parser_new(int argc, VALUE *argv, VALUE klass)
193
+ {
194
+ yaji_parser* p;
195
+ VALUE opts, obj;
196
+
197
+ obj = Data_Make_Struct(klass, yaji_parser, rb_yaji_parser_mark, rb_yaji_parser_free, p);
198
+ p->handle = NULL;
199
+ p->config.allowComments = 1;
200
+ p->config.checkUTF8 = 1;
201
+ p->symbolize_keys = 0;
202
+ p->with_path = 0;
203
+ p->filter = Qnil;
204
+ p->rbufsize = Qnil;
205
+ p->input = Qnil;
206
+ p->parser_cb = Qnil;
207
+ p->on_object_cb = Qnil;
208
+
209
+ rb_scan_args(argc, argv, "02", &p->input, &opts);
210
+ if (NIL_P(opts) && TYPE(p->input) == T_HASH) {
211
+ opts = p->input;
212
+ p->input = Qnil;
213
+ }
214
+ if (!NIL_P(p->input)) {
215
+ if (TYPE(p->input) == T_STRING) {
216
+ p->input = rb_class_new_instance(1, &p->input, c_stringio);
217
+ } else if (rb_respond_to(p->input, id_perform) && rb_respond_to(p->input, id_on_body)) {
218
+ rb_block_call(p->input, id_on_body, 0, NULL, rb_yaji_parser_parse_chunk, obj);
219
+ } else if (!rb_respond_to(p->input, id_read)) {
220
+ rb_raise(c_parse_error, "input must be a String or IO or "
221
+ "something responding to #perform and #on_body e.g. Curl::Easy");
222
+ }
223
+ }
224
+ if (!NIL_P(opts)) {
225
+ Check_Type(opts, T_HASH);
226
+ if (rb_hash_aref(opts, sym_allow_comments) == Qfalse) {
227
+ p->config.allowComments = 0;
228
+ }
229
+ if (rb_hash_aref(opts, sym_check_utf8) == Qfalse) {
230
+ p->config.checkUTF8 = 0;
231
+ }
232
+ if (rb_hash_aref(opts, sym_symbolize_keys) == Qtrue) {
233
+ p->symbolize_keys = 1;
234
+ }
235
+ p->rbufsize = rb_hash_aref(opts, sym_read_buffer_size);
236
+ if (rb_hash_aref(opts, sym_with_path) == Qtrue) {
237
+ p->with_path = 1;
238
+ }
239
+ p->filter = rb_hash_aref(opts, sym_filter);
240
+ }
241
+ if (NIL_P(p->rbufsize)) {
242
+ p->rbufsize = INT2FIX(READ_BUFSIZE);
243
+ } else {
244
+ Check_Type(p->rbufsize, T_FIXNUM);
245
+ }
246
+ p->object_stack = rb_ary_new();
247
+ p->path = rb_ary_new();
248
+ rb_ary_push(p->path, rb_str_new("", 0));
249
+ p->path_str = rb_str_new("", 0);
250
+ p->handle = yajl_alloc(&yaji_callbacks, &p->config, NULL, (void *)obj);
251
+ rb_obj_call_init(obj, 0, 0);
252
+ return obj;
253
+ }
254
+
255
+ static VALUE rb_yaji_parser_init(int argc, VALUE *argv, VALUE self)
256
+ {
257
+ return self;
258
+ (void)argc;
259
+ (void)argv;
260
+ }
261
+
262
+ static VALUE rb_yaji_parser_write(VALUE self, VALUE val)
263
+ {
264
+ yaji_parser* p = (yaji_parser*) DATA_PTR(self);
265
+
266
+ if (NIL_P(p->on_object_cb)) {
267
+ rb_raise(rb_eArgError, "#on_object callback required");
268
+ }
269
+ if (!NIL_P(val)) {
270
+ Check_Type(val, T_STRING);
271
+ }
272
+ return rb_yaji_parser_parse_chunk(val, self);
273
+ }
274
+
275
+ static VALUE rb_yaji_parser_parse(int argc, VALUE* argv, VALUE self)
276
+ {
277
+ yajl_status rc;
278
+ yaji_parser* p = (yaji_parser*) DATA_PTR(self);
279
+ int i;
280
+
281
+ if (NIL_P(p->input)) {
282
+ rb_raise(rb_eArgError, "input object required to use #parse method");
283
+ }
284
+ rb_scan_args(argc, argv, "00&", &p->parser_cb);
285
+ RETURN_ENUMERATOR(self, argc, argv);
286
+
287
+ p->chunk = Qnil;
288
+
289
+ if (rb_respond_to(p->input, id_perform)) {
290
+ rb_funcall(p->input, id_perform, 0);
291
+ } else {
292
+ p->chunk = rb_str_new(NULL, 0);
293
+ while (rb_funcall(p->input, id_read, 2, p->rbufsize, p->chunk) != Qnil) {
294
+ rb_yaji_parser_parse_chunk(p->chunk, self);
295
+ }
296
+ }
297
+
298
+ p->events = rb_ary_new();
299
+ rc = yajl_parse_complete(p->handle);
300
+
301
+ if (rc == yajl_status_error ||
302
+ (rc == yajl_status_insufficient_data && p->chunk != Qnil &&
303
+ RSTRING_LEN(rb_funcall(p->chunk, id_strip, 0)) != 0)) {
304
+ RERAISE_PARSER_ERROR(p);
305
+ }
306
+ for (i=0; i<RARRAY_LEN(p->events); i++) {
307
+ rb_funcall(p->parser_cb, id_call, 1, RARRAY_PTR(p->events)[i]);
308
+ }
309
+
310
+ return Qnil;
311
+ }
312
+
313
+ static int rb_yaji_str_start_with(VALUE str, VALUE filter)
314
+ {
315
+ int i;
316
+ const char *ptr = RSTRING_PTR(str);
317
+ long len = RSTRING_LEN(str);
318
+ VALUE entry;
319
+
320
+ switch(TYPE(filter)) {
321
+ case T_STRING:
322
+ return RSTRING_LEN(filter) <= len && memcmp(RSTRING_PTR(filter), ptr, RSTRING_LEN(filter)) == 0;
323
+ break;
324
+ case T_ARRAY:
325
+ for (i=0; i<RARRAY_LEN(filter); i++) {
326
+ entry = RARRAY_PTR(filter)[i];
327
+ if (RSTRING_LEN(entry) <= len && memcmp(RSTRING_PTR(entry), ptr, RSTRING_LEN(entry)) == 0) {
328
+ return 1;
329
+ }
330
+ }
331
+ break;
332
+ }
333
+ return 0;
334
+ }
335
+
336
+ static VALUE rb_yaji_each_iter(VALUE chunk, VALUE parser)
337
+ {
338
+ yaji_parser* p = (yaji_parser*) DATA_PTR(parser);
339
+ VALUE path = rb_ary_shift(chunk);
340
+ VALUE event = rb_ary_shift(chunk);
341
+ VALUE value = rb_ary_shift(chunk);
342
+ VALUE last_entry, object, container, key, hash;
343
+
344
+ if (NIL_P(p->effective_filter) || rb_yaji_str_start_with(path, p->effective_filter)) {
345
+ if (event == sym_hash_key) {
346
+ rb_ary_push(p->object_stack, value);
347
+ } else if (event == sym_start_hash || event == sym_start_array) {
348
+ container = (event == sym_start_hash) ? rb_hash_new() : rb_ary_new();
349
+ last_entry = rb_ary_entry(p->object_stack, -1);
350
+ switch(TYPE(last_entry)) {
351
+ case T_STRING:
352
+ key = rb_ary_pop(p->object_stack);
353
+ hash = rb_ary_entry(p->object_stack, -1);
354
+ rb_hash_aset(hash, key, container);
355
+ break;
356
+ case T_ARRAY:
357
+ rb_ary_push(last_entry, container);
358
+ }
359
+ rb_ary_push(p->object_stack, container);
360
+ } else if (event == sym_end_hash || event == sym_end_array) {
361
+ object = rb_ary_pop(p->object_stack);
362
+ if (RARRAY_LEN(p->object_stack) == 0) {
363
+ if (RTEST(p->effective_with_path)) {
364
+ rb_funcall(p->effective_proc, id_call, 1, rb_ary_new3(2, path, object));
365
+ } else {
366
+ rb_funcall(p->effective_proc, id_call, 1, object);
367
+ }
368
+ }
369
+ } else {
370
+ last_entry = rb_ary_entry(p->object_stack, -1);
371
+ switch(TYPE(last_entry)) {
372
+ case T_STRING:
373
+ key = rb_ary_pop(p->object_stack);
374
+ hash = rb_ary_entry(p->object_stack, -1);
375
+ rb_hash_aset(hash, key, value);
376
+ break;
377
+ case T_ARRAY:
378
+ rb_ary_push(last_entry, value);
379
+ break;
380
+ case T_NIL:
381
+ if (RTEST(p->effective_with_path)) {
382
+ rb_funcall(p->effective_proc, id_call, 1, rb_ary_new3(2, path, value));
383
+ } else {
384
+ rb_funcall(p->effective_proc, id_call, 1, value);
385
+ }
386
+ break;
387
+ }
388
+ }
389
+ }
390
+ return Qnil;
391
+ }
392
+
393
+ static VALUE rb_yaji_parser_each(int argc, VALUE* argv, VALUE self)
394
+ {
395
+ VALUE filter, proc, options;
396
+ yaji_parser* p = (yaji_parser*) DATA_PTR(self);
397
+
398
+ if (NIL_P(p->input)) {
399
+ rb_raise(rb_eArgError, "input object required to use #each method");
400
+ }
401
+ RETURN_ENUMERATOR(self, argc, argv);
402
+ rb_scan_args(argc, argv, "02&", &filter, &options, &proc);
403
+ p->effective_proc = proc;
404
+ p->object_stack = rb_ary_new();
405
+ if (NIL_P(filter)) {
406
+ p->effective_filter = p->filter;
407
+ } else {
408
+ p->effective_filter = filter;
409
+ }
410
+ p->effective_with_path = p->with_path ? Qtrue : Qfalse;
411
+ if (options != Qnil) {
412
+ VALUE arg;
413
+ Check_Type(options, T_HASH);
414
+ arg = rb_hash_aref(options, sym_with_path);
415
+ if (!NIL_P(arg)) {
416
+ p->effective_with_path = arg;
417
+ }
418
+ }
419
+ rb_block_call(self, id_parse, 0, NULL, rb_yaji_each_iter, self);
420
+ return Qnil;
421
+ }
422
+
423
+ static void rb_yaji_parser_free(void *parser)
424
+ {
425
+ yaji_parser* p = parser;
426
+ if (p) {
427
+ if (p->handle) {
428
+ yajl_free(p->handle);
429
+ }
430
+ free(p);
431
+ }
432
+ }
433
+
434
+ static VALUE rb_yaji_parser_on_object(VALUE self)
435
+ {
436
+ yaji_parser *p = DATA_PTR(self);
437
+
438
+ if (rb_block_given_p()) {
439
+ p->on_object_cb = rb_block_proc();
440
+ }
441
+ return p->on_object_cb;
442
+ }
443
+
444
+ static void rb_yaji_parser_mark(void *parser)
445
+ {
446
+ yaji_parser* p = parser;
447
+ if (p) {
448
+ rb_gc_mark(p->input);
449
+ rb_gc_mark(p->rbufsize);
450
+ rb_gc_mark(p->events);
451
+ rb_gc_mark(p->path);
452
+ rb_gc_mark(p->path_str);
453
+ rb_gc_mark(p->parser_cb);
454
+ rb_gc_mark(p->on_object_cb);
455
+ rb_gc_mark(p->chunk);
456
+ rb_gc_mark(p->object_stack);
457
+ rb_gc_mark(p->effective_filter);
458
+ rb_gc_mark(p->effective_with_path);
459
+ rb_gc_mark(p->effective_proc);
460
+ }
461
+ }
462
+
463
+ /* Ruby Extension initializer */
464
+ void Init_parser_ext() {
465
+ m_yaji = rb_define_module("YAJI");
466
+
467
+ c_parse_error = rb_define_class_under(m_yaji, "ParseError", rb_eStandardError);
468
+
469
+ c_yaji_parser = rb_define_class_under(m_yaji, "Parser", rb_cObject);
470
+ rb_define_const(c_yaji_parser, "READ_BUFFER_SIZE", INT2FIX(READ_BUFSIZE));
471
+ rb_define_singleton_method(c_yaji_parser, "new", rb_yaji_parser_new, -1);
472
+ rb_define_method(c_yaji_parser, "initialize", rb_yaji_parser_init, -1);
473
+ rb_define_method(c_yaji_parser, "parse", rb_yaji_parser_parse, -1);
474
+ rb_define_method(c_yaji_parser, "each", rb_yaji_parser_each, -1);
475
+ rb_define_method(c_yaji_parser, "on_object", rb_yaji_parser_on_object, 0);
476
+ rb_define_method(c_yaji_parser, "write", rb_yaji_parser_write, 1);
477
+ rb_define_alias(c_yaji_parser, "<<", "write");
478
+
479
+ id_call = rb_intern("call");
480
+ id_read = rb_intern("read");
481
+ id_parse = rb_intern("parse");
482
+ id_strip = rb_intern("strip");
483
+ id_perform = rb_intern("perform");
484
+ id_on_body = rb_intern("on_body");
485
+ id_bytesize = rb_intern("bytesize");
486
+
487
+ sym_allow_comments = ID2SYM(rb_intern("allow_comments"));
488
+ sym_check_utf8 = ID2SYM(rb_intern("check_utf8"));
489
+ sym_symbolize_keys = ID2SYM(rb_intern("symbolize_keys"));
490
+ sym_read_buffer_size = ID2SYM(rb_intern("read_buffer_size"));
491
+ sym_with_path = ID2SYM(rb_intern("with_path"));
492
+ sym_filter = ID2SYM(rb_intern("filter"));
493
+ sym_null = ID2SYM(rb_intern("null"));
494
+ sym_boolean = ID2SYM(rb_intern("boolean"));
495
+ sym_number = ID2SYM(rb_intern("number"));
496
+ sym_string = ID2SYM(rb_intern("string"));
497
+ sym_hash_key = ID2SYM(rb_intern("hash_key"));
498
+ sym_start_hash = ID2SYM(rb_intern("start_hash"));
499
+ sym_end_hash = ID2SYM(rb_intern("end_hash"));
500
+ sym_start_array = ID2SYM(rb_intern("start_array"));
501
+ sym_end_array = ID2SYM(rb_intern("end_array"));
502
+
503
+ #ifdef HAVE_RUBY_ENCODING_H
504
+ utf8_encoding = rb_utf8_encoding();
505
+ #endif
506
+
507
+ rb_require("stringio");
508
+ c_stringio = rb_const_get(rb_cObject, rb_intern("StringIO"));
509
+ }