syck 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/.autotest.erb +8 -0
  2. data/.gemtest +0 -0
  3. data/CHANGELOG.rdoc +6 -0
  4. data/Manifest.txt +52 -0
  5. data/README.rdoc +51 -0
  6. data/Rakefile +32 -0
  7. data/ext/syck/bytecode.c +1165 -0
  8. data/ext/syck/emitter.c +1247 -0
  9. data/ext/syck/extconf.h +3 -0
  10. data/ext/syck/extconf.rb +5 -0
  11. data/ext/syck/gram.c +1894 -0
  12. data/ext/syck/gram.h +79 -0
  13. data/ext/syck/handler.c +173 -0
  14. data/ext/syck/implicit.c +2990 -0
  15. data/ext/syck/node.c +407 -0
  16. data/ext/syck/rubyext.c +2328 -0
  17. data/ext/syck/syck.c +524 -0
  18. data/ext/syck/syck.h +453 -0
  19. data/ext/syck/token.c +2724 -0
  20. data/ext/syck/yaml2byte.c +259 -0
  21. data/ext/syck/yamlbyte.h +171 -0
  22. data/lib/syck.bundle +0 -0
  23. data/lib/syck.rb +447 -0
  24. data/lib/syck/baseemitter.rb +242 -0
  25. data/lib/syck/basenode.rb +222 -0
  26. data/lib/syck/constants.rb +45 -0
  27. data/lib/syck/encoding.rb +35 -0
  28. data/lib/syck/error.rb +34 -0
  29. data/lib/syck/loader.rb +14 -0
  30. data/lib/syck/rubytypes.rb +450 -0
  31. data/lib/syck/stream.rb +41 -0
  32. data/lib/syck/stringio.rb +85 -0
  33. data/lib/syck/syck.rb +16 -0
  34. data/lib/syck/tag.rb +95 -0
  35. data/lib/syck/types.rb +192 -0
  36. data/lib/syck/yamlnode.rb +54 -0
  37. data/lib/syck/ypath.rb +54 -0
  38. data/lib/yaml/syck.rb +14 -0
  39. data/test/helper.rb +2 -0
  40. data/test/test_array.rb +13 -0
  41. data/test/test_boolean.rb +36 -0
  42. data/test/test_class.rb +11 -0
  43. data/test/test_exception.rb +45 -0
  44. data/test/test_hash.rb +24 -0
  45. data/test/test_null.rb +19 -0
  46. data/test/test_omap.rb +55 -0
  47. data/test/test_set.rb +30 -0
  48. data/test/test_string.rb +44 -0
  49. data/test/test_struct.rb +32 -0
  50. data/test/test_symbol.rb +21 -0
  51. data/test/test_time.rb +23 -0
  52. data/test/test_yaml.rb +1403 -0
  53. data/test/test_yaml_properties.rb +63 -0
  54. metadata +187 -0
@@ -0,0 +1,407 @@
1
+ /*
2
+ * node.c
3
+ *
4
+ * $Author$
5
+ *
6
+ * Copyright (C) 2003 why the lucky stiff
7
+ */
8
+
9
+ #include "ruby/ruby.h"
10
+ #include "syck.h"
11
+
12
+ /*
13
+ * Node allocation functions
14
+ */
15
+ SyckNode *
16
+ syck_alloc_node( enum syck_kind_tag type )
17
+ {
18
+ SyckNode *s;
19
+
20
+ s = S_ALLOC( SyckNode );
21
+ s->kind = type;
22
+ s->id = 0;
23
+ s->type_id = NULL;
24
+ s->anchor = NULL;
25
+ s->shortcut = NULL;
26
+
27
+ return s;
28
+ }
29
+
30
+ void
31
+ syck_free_node( SyckNode *n )
32
+ {
33
+ syck_free_members( n );
34
+ if ( n->type_id != NULL )
35
+ {
36
+ S_FREE( n->type_id );
37
+ n->type_id = NULL;
38
+ }
39
+ if ( n->anchor != NULL )
40
+ {
41
+ S_FREE( n->anchor );
42
+ n->anchor = NULL;
43
+ }
44
+ S_FREE( n );
45
+ }
46
+
47
+ SyckNode *
48
+ syck_alloc_map(void)
49
+ {
50
+ SyckNode *n;
51
+ struct SyckMap *m;
52
+
53
+ m = S_ALLOC( struct SyckMap );
54
+ m->style = map_none;
55
+ m->idx = 0;
56
+ m->capa = ALLOC_CT;
57
+ m->keys = S_ALLOC_N( SYMID, m->capa );
58
+ m->values = S_ALLOC_N( SYMID, m->capa );
59
+
60
+ n = syck_alloc_node( syck_map_kind );
61
+ n->data.pairs = m;
62
+
63
+ return n;
64
+ }
65
+
66
+ SyckNode *
67
+ syck_alloc_seq(void)
68
+ {
69
+ SyckNode *n;
70
+ struct SyckSeq *s;
71
+
72
+ s = S_ALLOC( struct SyckSeq );
73
+ s->style = seq_none;
74
+ s->idx = 0;
75
+ s->capa = ALLOC_CT;
76
+ s->items = S_ALLOC_N( SYMID, s->capa );
77
+
78
+ n = syck_alloc_node( syck_seq_kind );
79
+ n->data.list = s;
80
+
81
+ return n;
82
+ }
83
+
84
+ SyckNode *
85
+ syck_alloc_str(void)
86
+ {
87
+ SyckNode *n;
88
+ struct SyckStr *s;
89
+
90
+ s = S_ALLOC( struct SyckStr );
91
+ s->len = 0;
92
+ s->ptr = NULL;
93
+ s->style = scalar_none;
94
+
95
+ n = syck_alloc_node( syck_str_kind );
96
+ n->data.str = s;
97
+
98
+ return n;
99
+ }
100
+
101
+ SyckNode *
102
+ syck_new_str( const char *str, enum scalar_style style )
103
+ {
104
+ return syck_new_str2( str, strlen( str ), style );
105
+ }
106
+
107
+ SyckNode *
108
+ syck_new_str2( const char *str, long len, enum scalar_style style )
109
+ {
110
+ SyckNode *n;
111
+
112
+ n = syck_alloc_str();
113
+ n->data.str->ptr = S_ALLOC_N( char, len + 1 );
114
+ n->data.str->len = len;
115
+ n->data.str->style = style;
116
+ memcpy( n->data.str->ptr, str, len );
117
+ n->data.str->ptr[len] = '\0';
118
+
119
+ return n;
120
+ }
121
+
122
+ void
123
+ syck_replace_str( SyckNode *n, char *str, enum scalar_style style )
124
+ {
125
+ syck_replace_str2( n, str, strlen( str ), style );
126
+ }
127
+
128
+ void
129
+ syck_replace_str2( SyckNode *n, char *str, long len, enum scalar_style style )
130
+ {
131
+ if ( n->data.str->ptr != NULL )
132
+ {
133
+ S_FREE( n->data.str->ptr );
134
+ n->data.str->ptr = NULL;
135
+ n->data.str->len = 0;
136
+ }
137
+ n->data.str->ptr = S_ALLOC_N( char, len + 1 );
138
+ n->data.str->len = len;
139
+ n->data.str->style = style;
140
+ memcpy( n->data.str->ptr, str, len );
141
+ n->data.str->ptr[len] = '\0';
142
+ }
143
+
144
+ void
145
+ syck_str_blow_away_commas( SyckNode *n )
146
+ {
147
+ char *go, *end;
148
+
149
+ go = n->data.str->ptr;
150
+ end = go + n->data.str->len;
151
+ while ( *(++go) != '\0' )
152
+ {
153
+ if ( *go == ',' )
154
+ {
155
+ n->data.str->len -= 1;
156
+ memmove( go, go + 1, end - go );
157
+ end -= 1;
158
+ }
159
+ }
160
+ }
161
+
162
+ char *
163
+ syck_str_read( SyckNode *n )
164
+ {
165
+ ASSERT( n != NULL );
166
+ return n->data.str->ptr;
167
+ }
168
+
169
+ SyckNode *
170
+ syck_new_map( SYMID key, SYMID value )
171
+ {
172
+ SyckNode *n;
173
+
174
+ n = syck_alloc_map();
175
+ syck_map_add( n, key, value );
176
+
177
+ return n;
178
+ }
179
+
180
+ void
181
+ syck_map_empty( SyckNode *n )
182
+ {
183
+ struct SyckMap *m;
184
+ ASSERT( n != NULL );
185
+ ASSERT( n->data.list != NULL );
186
+
187
+ S_FREE( n->data.pairs->keys );
188
+ S_FREE( n->data.pairs->values );
189
+ m = n->data.pairs;
190
+ m->idx = 0;
191
+ m->capa = ALLOC_CT;
192
+ m->keys = S_ALLOC_N( SYMID, m->capa );
193
+ m->values = S_ALLOC_N( SYMID, m->capa );
194
+ }
195
+
196
+ void
197
+ syck_map_add( SyckNode *map, SYMID key, SYMID value )
198
+ {
199
+ struct SyckMap *m;
200
+ long idx;
201
+
202
+ ASSERT( map != NULL );
203
+ ASSERT( map->data.pairs != NULL );
204
+
205
+ m = map->data.pairs;
206
+ idx = m->idx;
207
+ m->idx += 1;
208
+ if ( m->idx > m->capa )
209
+ {
210
+ m->capa += ALLOC_CT;
211
+ S_REALLOC_N( m->keys, SYMID, m->capa );
212
+ S_REALLOC_N( m->values, SYMID, m->capa );
213
+ }
214
+ m->keys[idx] = key;
215
+ m->values[idx] = value;
216
+ }
217
+
218
+ void
219
+ syck_map_update( SyckNode *map1, SyckNode *map2 )
220
+ {
221
+ struct SyckMap *m1, *m2;
222
+ long new_idx, new_capa;
223
+ ASSERT( map1 != NULL );
224
+ ASSERT( map2 != NULL );
225
+
226
+ m1 = map1->data.pairs;
227
+ m2 = map2->data.pairs;
228
+ if ( m2->idx < 1 ) return;
229
+
230
+ new_idx = m1->idx;
231
+ new_idx += m2->idx;
232
+ new_capa = m1->capa;
233
+ while ( new_idx > new_capa )
234
+ {
235
+ new_capa += ALLOC_CT;
236
+ }
237
+ if ( new_capa > m1->capa )
238
+ {
239
+ m1->capa = new_capa;
240
+ S_REALLOC_N( m1->keys, SYMID, m1->capa );
241
+ S_REALLOC_N( m1->values, SYMID, m1->capa );
242
+ }
243
+ for ( new_idx = 0; new_idx < m2->idx; m1->idx++, new_idx++ )
244
+ {
245
+ m1->keys[m1->idx] = m2->keys[new_idx];
246
+ m1->values[m1->idx] = m2->values[new_idx];
247
+ }
248
+ }
249
+
250
+ long
251
+ syck_map_count( SyckNode *map )
252
+ {
253
+ ASSERT( map != NULL );
254
+ ASSERT( map->data.pairs != NULL );
255
+ return map->data.pairs->idx;
256
+ }
257
+
258
+ void
259
+ syck_map_assign( SyckNode *map, enum map_part p, long idx, SYMID id )
260
+ {
261
+ struct SyckMap *m;
262
+
263
+ ASSERT( map != NULL );
264
+ m = map->data.pairs;
265
+ ASSERT( m != NULL );
266
+ if ( p == map_key )
267
+ {
268
+ m->keys[idx] = id;
269
+ }
270
+ else
271
+ {
272
+ m->values[idx] = id;
273
+ }
274
+ }
275
+
276
+ SYMID
277
+ syck_map_read( SyckNode *map, enum map_part p, long idx )
278
+ {
279
+ struct SyckMap *m;
280
+
281
+ ASSERT( map != NULL );
282
+ m = map->data.pairs;
283
+ ASSERT( m != NULL );
284
+ if ( p == map_key )
285
+ {
286
+ return m->keys[idx];
287
+ }
288
+ else
289
+ {
290
+ return m->values[idx];
291
+ }
292
+ }
293
+
294
+ SyckNode *
295
+ syck_new_seq( SYMID value )
296
+ {
297
+ SyckNode *n;
298
+
299
+ n = syck_alloc_seq();
300
+ syck_seq_add( n, value );
301
+
302
+ return n;
303
+ }
304
+
305
+ void
306
+ syck_seq_empty( SyckNode *n )
307
+ {
308
+ struct SyckSeq *s;
309
+ ASSERT( n != NULL );
310
+ ASSERT( n->data.list != NULL );
311
+
312
+ S_FREE( n->data.list->items );
313
+ s = n->data.list;
314
+ s->idx = 0;
315
+ s->capa = ALLOC_CT;
316
+ s->items = S_ALLOC_N( SYMID, s->capa );
317
+ }
318
+
319
+ void
320
+ syck_seq_add( SyckNode *arr, SYMID value )
321
+ {
322
+ struct SyckSeq *s;
323
+ long idx;
324
+
325
+ ASSERT( arr != NULL );
326
+ ASSERT( arr->data.list != NULL );
327
+
328
+ s = arr->data.list;
329
+ idx = s->idx;
330
+ s->idx += 1;
331
+ if ( s->idx > s->capa )
332
+ {
333
+ s->capa += ALLOC_CT;
334
+ S_REALLOC_N( s->items, SYMID, s->capa );
335
+ }
336
+ s->items[idx] = value;
337
+ }
338
+
339
+ long
340
+ syck_seq_count( SyckNode *seq )
341
+ {
342
+ ASSERT( seq != NULL );
343
+ ASSERT( seq->data.list != NULL );
344
+ return seq->data.list->idx;
345
+ }
346
+
347
+ void
348
+ syck_seq_assign( SyckNode *seq, long idx, SYMID id )
349
+ {
350
+ struct SyckSeq *s;
351
+
352
+ ASSERT( map != NULL );
353
+ s = seq->data.list;
354
+ ASSERT( m != NULL );
355
+ s->items[idx] = id;
356
+ }
357
+
358
+ SYMID
359
+ syck_seq_read( SyckNode *seq, long idx )
360
+ {
361
+ struct SyckSeq *s;
362
+
363
+ ASSERT( seq != NULL );
364
+ s = seq->data.list;
365
+ ASSERT( s != NULL );
366
+ return s->items[idx];
367
+ }
368
+
369
+ void
370
+ syck_free_members( SyckNode *n )
371
+ {
372
+ if ( n == NULL ) return;
373
+
374
+ switch ( n->kind )
375
+ {
376
+ case syck_str_kind:
377
+ if ( n->data.str != NULL )
378
+ {
379
+ S_FREE( n->data.str->ptr );
380
+ n->data.str->ptr = NULL;
381
+ n->data.str->len = 0;
382
+ S_FREE( n->data.str );
383
+ n->data.str = NULL;
384
+ }
385
+ break;
386
+
387
+ case syck_seq_kind:
388
+ if ( n->data.list != NULL )
389
+ {
390
+ S_FREE( n->data.list->items );
391
+ S_FREE( n->data.list );
392
+ n->data.list = NULL;
393
+ }
394
+ break;
395
+
396
+ case syck_map_kind:
397
+ if ( n->data.pairs != NULL )
398
+ {
399
+ S_FREE( n->data.pairs->keys );
400
+ S_FREE( n->data.pairs->values );
401
+ S_FREE( n->data.pairs );
402
+ n->data.pairs = NULL;
403
+ }
404
+ break;
405
+ }
406
+ }
407
+
@@ -0,0 +1,2328 @@
1
+ /* -*- indent-tabs-mode: nil -*- */
2
+ /*
3
+ * rubyext.c
4
+ *
5
+ * $Author$
6
+ *
7
+ * Copyright (C) 2003-2005 why the lucky stiff
8
+ */
9
+
10
+ #include "ruby/ruby.h"
11
+ #include "ruby/encoding.h"
12
+ #include "syck.h"
13
+ #include <sys/types.h>
14
+ #include <time.h>
15
+
16
+ typedef struct RVALUE {
17
+ union {
18
+ #if 0
19
+ struct {
20
+ unsigned long flags; /* always 0 for freed obj */
21
+ struct RVALUE *next;
22
+ } free;
23
+ #endif
24
+ struct RBasic basic;
25
+ struct RObject object;
26
+ struct RClass klass;
27
+ /*struct RFloat flonum;*/
28
+ /*struct RString string;*/
29
+ struct RArray array;
30
+ /*struct RRegexp regexp;*/
31
+ struct RHash hash;
32
+ /*struct RData data;*/
33
+ struct RStruct rstruct;
34
+ /*struct RBignum bignum;*/
35
+ /*struct RFile file;*/
36
+ } as;
37
+ } RVALUE;
38
+
39
+ typedef struct {
40
+ long hash;
41
+ char *buffer;
42
+ long length;
43
+ long remaining;
44
+ int printed;
45
+ } bytestring_t;
46
+
47
+ #define RUBY_DOMAIN "ruby.yaml.org,2002"
48
+
49
+ /*
50
+ * symbols and constants
51
+ */
52
+ static ID s_new, s_utc, s_at, s_to_f, s_to_i, s_read, s_binmode, s_call, s_cmp, s_transfer, s_update, s_dup, s_haskey, s_match, s_keys, s_unpack, s_tr_bang, s_default_set, s_tag_read_class, s_tag_subclasses, s_resolver, s_push, s_emitter, s_level, s_detect_implicit, s_node_import, s_out, s_input, s_intern, s_transform, s_yaml_new, s_yaml_initialize, s_node_export, s_to_yaml, s_write, s_set_resolver, s_each;
53
+ static ID s_tags, s_kind, s_name, s_options, s_type_id, s_type_id_set, s_style, s_style_set, s_value, s_value_set, s_parse;
54
+ static VALUE sym_model, sym_generic, sym_input, sym_bytecode;
55
+ static VALUE sym_scalar, sym_seq, sym_map;
56
+ static VALUE sym_1quote, sym_2quote, sym_fold, sym_literal, sym_plain, sym_inline;
57
+ static VALUE cDate, cNode, cMap, cSeq, cScalar, cOut, cParser, cResolver, cPrivateType, cDomainType, cYObject, cBadAlias, cDefaultKey, cMergeKey, cEmitter, cDateTime;
58
+ static VALUE oDefaultResolver, oGenericResolver;
59
+
60
+ /*
61
+ * my private collection of numerical oddities.
62
+ */
63
+ static double S_zero(void) { return 0.0; }
64
+ static double S_one(void) { return 1.0; }
65
+ static double S_inf(void) { return S_one() / S_zero(); }
66
+ static double S_nan(void) { return S_zero() / S_zero(); }
67
+
68
+ static VALUE syck_node_transform( VALUE );
69
+
70
+ /*
71
+ * handler prototypes
72
+ */
73
+ SYMID rb_syck_load_handler _((SyckParser *, SyckNode *));
74
+ void rb_syck_err_handler _((SyckParser *, const char *));
75
+ SyckNode * rb_syck_bad_anchor_handler _((SyckParser *, char *));
76
+ void rb_syck_output_handler _((SyckEmitter *, char *, long));
77
+ void rb_syck_emitter_handler _((SyckEmitter *, st_data_t));
78
+ int syck_parser_assign_io _((SyckParser *, VALUE *));
79
+ VALUE syck_scalar_alloc _((VALUE class));
80
+ VALUE syck_seq_alloc _((VALUE class));
81
+ VALUE syck_map_alloc _((VALUE class));
82
+
83
+ struct parser_xtra {
84
+ VALUE data; /* Borrowed this idea from marshal.c to fix [ruby-core:8067] problem */
85
+ VALUE proc;
86
+ VALUE resolver;
87
+ int taint;
88
+ };
89
+
90
+ struct emitter_xtra {
91
+ VALUE oid;
92
+ VALUE data;
93
+ VALUE port;
94
+ };
95
+
96
+ /*
97
+ * Convert YAML to bytecode
98
+ */
99
+ VALUE
100
+ rb_syck_compile(VALUE self, VALUE port)
101
+ {
102
+ SYMID oid;
103
+ int taint;
104
+ char *ret;
105
+ VALUE bc;
106
+ bytestring_t *sav = NULL;
107
+ void *data = NULL;
108
+
109
+ SyckParser *parser = syck_new_parser();
110
+ taint = syck_parser_assign_io(parser, &port);
111
+ syck_parser_handler( parser, syck_yaml2byte_handler );
112
+ syck_parser_error_handler( parser, NULL );
113
+ syck_parser_implicit_typing( parser, 0 );
114
+ syck_parser_taguri_expansion( parser, 0 );
115
+ oid = syck_parse( parser );
116
+ if (!syck_lookup_sym( parser, oid, &data )) {
117
+ rb_raise(rb_eSyntaxError, "root node <%p> not found", (void *)oid);
118
+ }
119
+ sav = data;
120
+
121
+ ret = S_ALLOCA_N( char, strlen( sav->buffer ) + 3 );
122
+ ret[0] = '\0';
123
+ strcat( ret, "D\n" );
124
+ strcat( ret, sav->buffer );
125
+
126
+ syck_free_parser( parser );
127
+
128
+ bc = rb_str_new2( ret );
129
+ if ( taint ) OBJ_TAINT( bc );
130
+ return bc;
131
+ }
132
+
133
+ /*
134
+ * read from io.
135
+ */
136
+ long
137
+ rb_syck_io_str_read( char *buf, SyckIoStr *str, long max_size, long skip )
138
+ {
139
+ long len = 0;
140
+
141
+ ASSERT( str != NULL );
142
+ max_size -= skip;
143
+
144
+ if ( max_size <= 0 ) max_size = 0;
145
+ else
146
+ {
147
+ /*
148
+ * call io#read.
149
+ */
150
+ VALUE src = (VALUE)str->ptr;
151
+ VALUE n = LONG2NUM(max_size);
152
+ VALUE str2 = rb_funcall2(src, s_read, 1, &n);
153
+ if (!NIL_P(str2))
154
+ {
155
+ StringValue(str2);
156
+ len = RSTRING_LEN(str2);
157
+ memcpy( buf + skip, RSTRING_PTR(str2), len );
158
+ }
159
+ }
160
+ len += skip;
161
+ buf[len] = '\0';
162
+ return len;
163
+ }
164
+
165
+ /*
166
+ * determine: are we reading from a string or io?
167
+ * (returns tainted? boolean)
168
+ */
169
+ int
170
+ syck_parser_assign_io(SyckParser *parser, VALUE *pport)
171
+ {
172
+ int taint = Qtrue;
173
+ VALUE tmp, port = *pport;
174
+ if (!NIL_P(tmp = rb_check_string_type(port))) {
175
+ taint = OBJ_TAINTED(port); /* original taintedness */
176
+ port = tmp;
177
+ syck_parser_str( parser, RSTRING_PTR(port), RSTRING_LEN(port), NULL );
178
+ }
179
+ else if (rb_respond_to(port, s_read)) {
180
+ if (rb_respond_to(port, s_binmode)) {
181
+ rb_funcall2(port, s_binmode, 0, 0);
182
+ }
183
+ syck_parser_str( parser, (char *)port, 0, rb_syck_io_str_read );
184
+ }
185
+ else {
186
+ rb_raise(rb_eTypeError, "instance of IO needed");
187
+ }
188
+ *pport = port;
189
+ return taint;
190
+ }
191
+
192
+ /*
193
+ * Get value in hash by key, forcing an empty hash if nil.
194
+ */
195
+ VALUE
196
+ syck_get_hash_aref(VALUE hsh, VALUE key)
197
+ {
198
+ VALUE val = rb_hash_aref( hsh, key );
199
+ if ( NIL_P( val ) )
200
+ {
201
+ val = rb_hash_new();
202
+ rb_hash_aset(hsh, key, val);
203
+ }
204
+ return val;
205
+ }
206
+
207
+ /*
208
+ * creating timestamps
209
+ */
210
+ struct mktime_arg {
211
+ const char *str;
212
+ long len;
213
+ };
214
+
215
+ VALUE
216
+ mktime_do(VALUE varg)
217
+ {
218
+ struct mktime_arg *arg = (struct mktime_arg *)varg;
219
+ VALUE time;
220
+ const char *str = arg->str;
221
+ long len = arg->len;
222
+ const char *ptr = str;
223
+ VALUE year = INT2FIX(0);
224
+ VALUE mon = INT2FIX(0);
225
+ VALUE day = INT2FIX(0);
226
+ VALUE hour = INT2FIX(0);
227
+ VALUE min = INT2FIX(0);
228
+ VALUE sec = INT2FIX(0);
229
+ long usec;
230
+
231
+ /* Year*/
232
+ if ( ptr[0] != '\0' && len > 0 ) {
233
+ year = INT2FIX(strtol(ptr, NULL, 10));
234
+ }
235
+
236
+ /* Month*/
237
+ ptr += 4;
238
+ if ( ptr[0] != '\0' && len > ptr - str ) {
239
+ while ( !ISDIGIT( *ptr ) ) ptr++;
240
+ mon = INT2FIX(strtol(ptr, NULL, 10));
241
+ }
242
+
243
+ /* Day*/
244
+ ptr += 2;
245
+ if ( ptr[0] != '\0' && len > ptr - str ) {
246
+ while ( !ISDIGIT( *ptr ) ) ptr++;
247
+ day = INT2FIX(strtol(ptr, NULL, 10));
248
+ }
249
+
250
+ /* Hour*/
251
+ ptr += 2;
252
+ if ( ptr[0] != '\0' && len > ptr - str ) {
253
+ while ( !ISDIGIT( *ptr ) ) ptr++;
254
+ hour = INT2FIX(strtol(ptr, NULL, 10));
255
+ }
256
+
257
+ /* Minute */
258
+ ptr += 2;
259
+ if ( ptr[0] != '\0' && len > ptr - str ) {
260
+ while ( !ISDIGIT( *ptr ) ) ptr++;
261
+ min = INT2FIX(strtol(ptr, NULL, 10));
262
+ }
263
+
264
+ /* Second */
265
+ ptr += 2;
266
+ if ( ptr[0] != '\0' && len > ptr - str ) {
267
+ while ( !ISDIGIT( *ptr ) ) ptr++;
268
+ sec = INT2FIX(strtol(ptr, NULL, 10));
269
+ }
270
+
271
+ /* Millisecond */
272
+ ptr += 2;
273
+ if ( len > ptr - str && *ptr == '.' )
274
+ {
275
+ char padded[] = "000000";
276
+ const int padding = (int)(sizeof(padded) - 1);
277
+ const char *end = ptr + 1;
278
+ const char *begin = end;
279
+ ptrdiff_t length;
280
+ while ( ISDIGIT( *end ) ) end++;
281
+ if ((length = (end - begin)) > padding) length = padding;
282
+ MEMCPY(padded, begin, char, length);
283
+ usec = strtol(padded, NULL, 10);
284
+ }
285
+ else
286
+ {
287
+ usec = 0;
288
+ }
289
+
290
+ /* Time Zone*/
291
+ while ( len > ptr - str && *ptr != 'Z' && *ptr != '+' && *ptr != '-' && *ptr != '\0' ) ptr++;
292
+ if ( len > ptr - str && ( *ptr == '-' || *ptr == '+' ) )
293
+ {
294
+ time_t tz_offset = strtol(ptr, NULL, 10) * 3600;
295
+ VALUE tmp;
296
+
297
+ while ( *ptr != ':' && *ptr != '\0' ) ptr++;
298
+ if ( *ptr == ':' )
299
+ {
300
+ ptr += 1;
301
+ if ( tz_offset < 0 )
302
+ {
303
+ tz_offset -= strtol(ptr, NULL, 10) * 60;
304
+ }
305
+ else
306
+ {
307
+ tz_offset += strtol(ptr, NULL, 10) * 60;
308
+ }
309
+ }
310
+
311
+ /* Make TZ time*/
312
+ time = rb_funcall(rb_cTime, s_utc, 6, year, mon, day, hour, min, sec);
313
+ tmp = rb_funcall(time, s_to_i, 0);
314
+ tmp = rb_funcall(tmp, '-', 1, LONG2FIX(tz_offset));
315
+ return rb_funcall(rb_cTime, s_at, 2, tmp, LONG2NUM(usec));
316
+ }
317
+ else
318
+ {
319
+ /* Make UTC time*/
320
+ return rb_funcall(rb_cTime, s_utc, 7, year, mon, day, hour, min, sec, LONG2NUM(usec));
321
+ }
322
+ }
323
+
324
+ VALUE
325
+ mktime_r(VALUE varg)
326
+ {
327
+ struct mktime_arg *arg = (struct mktime_arg *)varg;
328
+
329
+ if (!cDateTime) {
330
+ /*
331
+ * Load Date module
332
+ */
333
+ rb_require("date");
334
+ cDateTime = rb_const_get(rb_cObject, rb_intern("DateTime"));
335
+ }
336
+ return rb_funcall(cDateTime, s_parse, 1, rb_str_new(arg->str, arg->len));
337
+ }
338
+
339
+ VALUE
340
+ rb_syck_mktime(const char *str, long len)
341
+ {
342
+ struct mktime_arg a;
343
+
344
+ a.str = str;
345
+ a.len = len;
346
+ return rb_rescue2(mktime_do, (VALUE)&a, mktime_r, (VALUE)&a, rb_eArgError, NULL);
347
+ }
348
+
349
+ /*
350
+ * handles merging of an array of hashes
351
+ * (see http://www.yaml.org/type/merge/)
352
+ */
353
+ VALUE
354
+ syck_merge_i(VALUE entry, VALUE hsh )
355
+ {
356
+ VALUE tmp;
357
+ if ( !NIL_P(tmp = rb_check_convert_type(entry, T_HASH, "Hash", "to_hash")) )
358
+ {
359
+ entry = tmp;
360
+ rb_funcall( hsh, s_update, 1, entry );
361
+ }
362
+ return Qnil;
363
+ }
364
+
365
+ /*
366
+ * default handler for ruby.yaml.org types
367
+ */
368
+ int
369
+ yaml_org_handler( SyckNode *n, VALUE *ref )
370
+ {
371
+ char *type_id = n->type_id;
372
+ int transferred = 0;
373
+ long i = 0;
374
+ VALUE obj = Qnil;
375
+
376
+ if ( type_id != NULL && strncmp( type_id, "tag:yaml.org,2002:", 18 ) == 0 )
377
+ {
378
+ type_id += 18;
379
+ }
380
+
381
+ switch (n->kind)
382
+ {
383
+ case syck_str_kind:
384
+ transferred = 1;
385
+ if ( type_id == NULL )
386
+ {
387
+ obj = rb_str_new( n->data.str->ptr, n->data.str->len );
388
+ }
389
+ else if ( strcmp( type_id, "null" ) == 0 )
390
+ {
391
+ obj = Qnil;
392
+ }
393
+ else if ( strcmp( type_id, "binary" ) == 0 )
394
+ {
395
+ VALUE arr;
396
+ obj = rb_str_new( n->data.str->ptr, n->data.str->len );
397
+ rb_funcall( obj, s_tr_bang, 2, rb_str_new2( "\n\t " ), rb_str_new2( "" ) );
398
+ arr = rb_funcall( obj, s_unpack, 1, rb_str_new2( "m" ) );
399
+ obj = rb_ary_shift( arr );
400
+ }
401
+ else if ( strcmp( type_id, "bool#yes" ) == 0 )
402
+ {
403
+ obj = Qtrue;
404
+ }
405
+ else if ( strcmp( type_id, "bool#no" ) == 0 )
406
+ {
407
+ obj = Qfalse;
408
+ }
409
+ else if ( strcmp( type_id, "int#hex" ) == 0 )
410
+ {
411
+ syck_str_blow_away_commas( n );
412
+ obj = rb_cstr2inum( n->data.str->ptr, 16 );
413
+ }
414
+ else if ( strcmp( type_id, "int#oct" ) == 0 )
415
+ {
416
+ syck_str_blow_away_commas( n );
417
+ obj = rb_cstr2inum( n->data.str->ptr, 8 );
418
+ }
419
+ else if ( strcmp( type_id, "int#base60" ) == 0 )
420
+ {
421
+ char *ptr, *end;
422
+ long sixty = 1;
423
+ long total = 0;
424
+ syck_str_blow_away_commas( n );
425
+ ptr = n->data.str->ptr;
426
+ end = n->data.str->ptr + n->data.str->len;
427
+ while ( end > ptr )
428
+ {
429
+ long bnum = 0;
430
+ char *colon = end - 1;
431
+ while ( colon >= ptr && *colon != ':' )
432
+ {
433
+ colon--;
434
+ }
435
+ if ( colon >= ptr && *colon == ':' ) *colon = '\0';
436
+
437
+ bnum = strtol( colon + 1, NULL, 10 );
438
+ total += bnum * sixty;
439
+ sixty *= 60;
440
+ end = colon;
441
+ }
442
+ obj = INT2FIX(total);
443
+ }
444
+ else if ( strncmp( type_id, "int", 3 ) == 0 )
445
+ {
446
+ syck_str_blow_away_commas( n );
447
+ obj = rb_cstr2inum( n->data.str->ptr, 10 );
448
+ }
449
+ else if ( strcmp( type_id, "float#base60" ) == 0 )
450
+ {
451
+ char *ptr, *end;
452
+ long sixty = 1;
453
+ double total = 0.0;
454
+ syck_str_blow_away_commas( n );
455
+ ptr = n->data.str->ptr;
456
+ end = n->data.str->ptr + n->data.str->len;
457
+ while ( end > ptr )
458
+ {
459
+ double bnum = 0;
460
+ char *colon = end - 1;
461
+ while ( colon >= ptr && *colon != ':' )
462
+ {
463
+ colon--;
464
+ }
465
+ if ( colon >= ptr && *colon == ':' ) *colon = '\0';
466
+
467
+ bnum = strtod( colon + 1, NULL );
468
+ total += bnum * sixty;
469
+ sixty *= 60;
470
+ end = colon;
471
+ }
472
+ obj = rb_float_new( total );
473
+ }
474
+ else if ( strcmp( type_id, "float#nan" ) == 0 )
475
+ {
476
+ obj = rb_float_new( S_nan() );
477
+ }
478
+ else if ( strcmp( type_id, "float#inf" ) == 0 )
479
+ {
480
+ obj = rb_float_new( S_inf() );
481
+ }
482
+ else if ( strcmp( type_id, "float#neginf" ) == 0 )
483
+ {
484
+ obj = rb_float_new( -S_inf() );
485
+ }
486
+ else if ( strncmp( type_id, "float", 5 ) == 0 )
487
+ {
488
+ double f;
489
+ syck_str_blow_away_commas( n );
490
+ f = strtod( n->data.str->ptr, NULL );
491
+ obj = rb_float_new( f );
492
+ }
493
+ else if ( strcmp( type_id, "timestamp#iso8601" ) == 0 )
494
+ {
495
+ obj = rb_syck_mktime( n->data.str->ptr, n->data.str->len );
496
+ }
497
+ else if ( strcmp( type_id, "timestamp#spaced" ) == 0 )
498
+ {
499
+ obj = rb_syck_mktime( n->data.str->ptr, n->data.str->len );
500
+ }
501
+ else if ( strcmp( type_id, "timestamp#ymd" ) == 0 )
502
+ {
503
+ char *ptr = n->data.str->ptr;
504
+ VALUE year, mon, day;
505
+
506
+ /* Year*/
507
+ ptr[4] = '\0';
508
+ year = INT2FIX(strtol(ptr, NULL, 10));
509
+
510
+ /* Month*/
511
+ ptr += 4;
512
+ while ( !ISDIGIT( *ptr ) ) ptr++;
513
+ mon = INT2FIX(strtol(ptr, NULL, 10));
514
+
515
+ /* Day*/
516
+ ptr += 2;
517
+ while ( !ISDIGIT( *ptr ) ) ptr++;
518
+ day = INT2FIX(strtol(ptr, NULL, 10));
519
+
520
+ if ( !cDate ) {
521
+ /*
522
+ * Load Date module
523
+ */
524
+ rb_require( "date" );
525
+ cDate = rb_const_get( rb_cObject, rb_intern("Date") );
526
+ }
527
+
528
+ obj = rb_funcall( cDate, s_new, 3, year, mon, day );
529
+ }
530
+ else if ( strncmp( type_id, "timestamp", 9 ) == 0 )
531
+ {
532
+ obj = rb_syck_mktime( n->data.str->ptr, n->data.str->len );
533
+ }
534
+ else if ( strncmp( type_id, "merge", 5 ) == 0 )
535
+ {
536
+ obj = rb_funcall( cMergeKey, s_new, 0 );
537
+ }
538
+ else if ( strncmp( type_id, "default", 7 ) == 0 )
539
+ {
540
+ obj = rb_funcall( cDefaultKey, s_new, 0 );
541
+ }
542
+ else if ( n->data.str->style == scalar_plain &&
543
+ n->data.str->len > 1 &&
544
+ strncmp( n->data.str->ptr, ":", 1 ) == 0 )
545
+ {
546
+ obj = rb_funcall( oDefaultResolver, s_transfer, 2,
547
+ rb_str_new2( "tag:ruby.yaml.org,2002:sym" ),
548
+ rb_str_new( n->data.str->ptr + 1, n->data.str->len - 1 ) );
549
+ }
550
+ else if ( strcmp( type_id, "str" ) == 0 )
551
+ {
552
+ obj = rb_str_new( n->data.str->ptr, n->data.str->len );
553
+ rb_enc_associate(obj, rb_utf8_encoding());
554
+ }
555
+ else
556
+ {
557
+ transferred = 0;
558
+ obj = rb_str_new( n->data.str->ptr, n->data.str->len );
559
+ }
560
+ break;
561
+
562
+ case syck_seq_kind:
563
+ if ( type_id == NULL || strcmp( type_id, "seq" ) == 0 )
564
+ {
565
+ transferred = 1;
566
+ }
567
+ obj = rb_ary_new2( n->data.list->idx );
568
+ for ( i = 0; i < n->data.list->idx; i++ )
569
+ {
570
+ rb_ary_store( obj, i, syck_seq_read( n, i ) );
571
+ }
572
+ break;
573
+
574
+ case syck_map_kind:
575
+ if ( type_id == NULL || strcmp( type_id, "map" ) == 0 )
576
+ {
577
+ transferred = 1;
578
+ }
579
+ obj = rb_hash_new();
580
+ for ( i = 0; i < n->data.pairs->idx; i++ )
581
+ {
582
+ VALUE k = syck_map_read( n, map_key, i );
583
+ VALUE v = syck_map_read( n, map_value, i );
584
+ int skip_aset = 0;
585
+
586
+ /*
587
+ * Handle merge keys
588
+ */
589
+ if ( rb_obj_is_kind_of( k, cMergeKey ) )
590
+ {
591
+ VALUE tmp;
592
+ if ( !NIL_P(tmp = rb_check_convert_type(v, T_HASH, "Hash", "to_hash")) )
593
+ {
594
+ VALUE dup = rb_funcall( tmp, s_dup, 0 );
595
+ rb_funcall( dup, s_update, 1, obj );
596
+ obj = dup;
597
+ skip_aset = 1;
598
+ }
599
+ else if ( !NIL_P(tmp = rb_check_array_type(v)) )
600
+ {
601
+ VALUE end = rb_ary_pop( tmp );
602
+ VALUE tmph = rb_check_convert_type(end, T_HASH, "Hash", "to_hash");
603
+ if ( !NIL_P(tmph) )
604
+ {
605
+ VALUE dup = rb_funcall( tmph, s_dup, 0 );
606
+ tmp = rb_ary_reverse( tmp );
607
+ rb_ary_push( tmp, obj );
608
+ rb_block_call( tmp, s_each, 0, 0, syck_merge_i, dup );
609
+ obj = dup;
610
+ skip_aset = 1;
611
+ }
612
+ }
613
+ }
614
+ else if ( rb_obj_is_kind_of( k, cDefaultKey ) )
615
+ {
616
+ rb_funcall( obj, s_default_set, 1, v );
617
+ skip_aset = 1;
618
+ }
619
+
620
+ if ( ! skip_aset )
621
+ {
622
+ rb_hash_aset( obj, k, v );
623
+ }
624
+ }
625
+ break;
626
+ }
627
+
628
+ *ref = obj;
629
+ return transferred;
630
+ }
631
+
632
+ static void syck_node_mark( SyckNode *n );
633
+
634
+ /*
635
+ * {native mode} node handler
636
+ * - Converts data into native Ruby types
637
+ */
638
+ SYMID
639
+ rb_syck_load_handler(SyckParser *p, SyckNode *n)
640
+ {
641
+ VALUE obj = Qnil;
642
+ struct parser_xtra *bonus = (struct parser_xtra *)p->bonus;
643
+ VALUE resolver = bonus->resolver;
644
+ if ( NIL_P( resolver ) )
645
+ {
646
+ resolver = oDefaultResolver;
647
+ }
648
+
649
+ /*
650
+ * Create node,
651
+ */
652
+ obj = rb_funcall( resolver, s_node_import, 1, Data_Wrap_Struct( cNode, NULL, NULL, n ) );
653
+
654
+ /*
655
+ * ID already set, let's alter the symbol table to accept the new object
656
+ */
657
+ if (n->id > 0 && !NIL_P(obj))
658
+ {
659
+ MEMCPY((void *)n->id, (void *)obj, RVALUE, 1);
660
+ MEMZERO((void *)obj, RVALUE, 1);
661
+ obj = n->id;
662
+ }
663
+
664
+ if ( bonus->taint) OBJ_TAINT( obj );
665
+ if ( bonus->proc != 0 ) rb_funcall(bonus->proc, s_call, 1, obj);
666
+
667
+ rb_hash_aset(bonus->data, INT2FIX(RHASH_SIZE(bonus->data)), obj);
668
+ return obj;
669
+ }
670
+
671
+ /*
672
+ * friendly errors.
673
+ */
674
+ void
675
+ rb_syck_err_handler(SyckParser *p, const char *msg)
676
+ {
677
+ char *endl = p->cursor;
678
+
679
+ while ( *endl != '\0' && *endl != '\n' )
680
+ endl++;
681
+
682
+ endl[0] = '\0';
683
+ rb_raise(rb_eArgError, "%s on line %d, col %"PRIdPTRDIFF": `%s'",
684
+ msg,
685
+ p->linect,
686
+ p->cursor - p->lineptr,
687
+ p->lineptr);
688
+ }
689
+
690
+ /*
691
+ * provide bad anchor object to the parser.
692
+ */
693
+ SyckNode *
694
+ rb_syck_bad_anchor_handler(SyckParser *p, char *a)
695
+ {
696
+ VALUE anchor_name = rb_str_new2( a );
697
+ SyckNode *badanc = syck_new_map( rb_str_new2( "name" ), anchor_name );
698
+ badanc->type_id = syck_strndup( "tag:ruby.yaml.org,2002:object:YAML::Syck::BadAlias", 53 );
699
+ return badanc;
700
+ }
701
+
702
+ /*
703
+ * data loaded based on the model requested.
704
+ */
705
+ void
706
+ syck_set_model(VALUE p, VALUE input, VALUE model)
707
+ {
708
+ SyckParser *parser;
709
+ Data_Get_Struct(p, SyckParser, parser);
710
+ syck_parser_handler( parser, rb_syck_load_handler );
711
+ /* WARN: gonna be obsoleted soon!! */
712
+ if ( model == sym_generic )
713
+ {
714
+ rb_funcall( p, s_set_resolver, 1, oGenericResolver );
715
+ }
716
+ syck_parser_implicit_typing( parser, 1 );
717
+ syck_parser_taguri_expansion( parser, 1 );
718
+
719
+ if ( NIL_P( input ) )
720
+ {
721
+ input = rb_ivar_get( p, s_input );
722
+ }
723
+ if ( input == sym_bytecode )
724
+ {
725
+ syck_parser_set_input_type( parser, syck_bytecode_utf8 );
726
+ }
727
+ else
728
+ {
729
+ syck_parser_set_input_type( parser, syck_yaml_utf8 );
730
+ }
731
+ syck_parser_error_handler( parser, rb_syck_err_handler );
732
+ syck_parser_bad_anchor_handler( parser, rb_syck_bad_anchor_handler );
733
+ }
734
+
735
+ static int
736
+ syck_st_mark_nodes( char *key, SyckNode *n, char *arg )
737
+ {
738
+ if ( n != (void *)1 ) syck_node_mark( n );
739
+ return ST_CONTINUE;
740
+ }
741
+
742
+ /*
743
+ * mark parser nodes
744
+ */
745
+ static void
746
+ syck_mark_parser(SyckParser *parser)
747
+ {
748
+ struct parser_xtra *bonus = (struct parser_xtra *)parser->bonus;
749
+ rb_gc_mark_maybe(parser->root);
750
+ rb_gc_mark_maybe(parser->root_on_error);
751
+ rb_gc_mark( bonus->data );
752
+ rb_gc_mark( bonus->proc );
753
+ rb_gc_mark( bonus->resolver );
754
+
755
+ if ( parser->anchors != NULL )
756
+ {
757
+ st_foreach( parser->anchors, syck_st_mark_nodes, 0 );
758
+ }
759
+ if ( parser->bad_anchors != NULL )
760
+ {
761
+ st_foreach( parser->bad_anchors, syck_st_mark_nodes, 0 );
762
+ }
763
+ }
764
+
765
+ /*
766
+ * Free the parser and any bonus attachment.
767
+ */
768
+ void
769
+ rb_syck_free_parser(SyckParser *p)
770
+ {
771
+ S_FREE( p->bonus );
772
+ syck_free_parser(p);
773
+ }
774
+
775
+ /*
776
+ * YAML::Syck::Parser.allocate
777
+ */
778
+ VALUE syck_parser_s_alloc _((VALUE));
779
+ VALUE
780
+ syck_parser_s_alloc(VALUE class)
781
+ {
782
+ VALUE pobj;
783
+ SyckParser *parser = syck_new_parser();
784
+
785
+ parser->bonus = S_ALLOC( struct parser_xtra );
786
+ S_MEMZERO( parser->bonus, struct parser_xtra, 1 );
787
+
788
+ pobj = Data_Wrap_Struct( class, syck_mark_parser, rb_syck_free_parser, parser );
789
+
790
+ syck_parser_set_root_on_error( parser, Qnil );
791
+
792
+ return pobj;
793
+ }
794
+
795
+ /*
796
+ * YAML::Syck::Parser.initialize( resolver, options )
797
+ */
798
+ static VALUE
799
+ syck_parser_initialize(int argc, VALUE *argv, VALUE self)
800
+ {
801
+ VALUE options;
802
+ if (rb_scan_args(argc, argv, "01", &options) == 0)
803
+ {
804
+ options = rb_hash_new();
805
+ }
806
+ else
807
+ {
808
+ Check_Type(options, T_HASH);
809
+ }
810
+ rb_ivar_set(self, s_options, options);
811
+ rb_ivar_set(self, s_input, Qnil);
812
+ return self;
813
+ }
814
+
815
+ /*
816
+ * YAML::Syck::Parser.bufsize = Integer
817
+ */
818
+ static VALUE
819
+ syck_parser_bufsize_set(VALUE self, VALUE size)
820
+ {
821
+ SyckParser *parser;
822
+
823
+ if ( rb_respond_to( size, s_to_i ) ) {
824
+ int n = NUM2INT(rb_funcall(size, s_to_i, 0));
825
+ Data_Get_Struct(self, SyckParser, parser);
826
+ parser->bufsize = n;
827
+ }
828
+ return self;
829
+ }
830
+
831
+ /*
832
+ * YAML::Syck::Parser.bufsize => Integer
833
+ */
834
+ static VALUE
835
+ syck_parser_bufsize_get(VALUE self)
836
+ {
837
+ SyckParser *parser;
838
+
839
+ Data_Get_Struct(self, SyckParser, parser);
840
+ return INT2FIX( parser->bufsize );
841
+ }
842
+
843
+ /*
844
+ * YAML::Syck::Parser.load( IO or String )
845
+ */
846
+ VALUE
847
+ syck_parser_load(int argc, VALUE *argv, VALUE self)
848
+ {
849
+ VALUE port, proc, model, input;
850
+ SyckParser *parser;
851
+ struct parser_xtra *bonus;
852
+
853
+ rb_scan_args(argc, argv, "11", &port, &proc);
854
+
855
+ input = rb_hash_aref( rb_attr_get( self, s_options ), sym_input );
856
+ model = rb_hash_aref( rb_attr_get( self, s_options ), sym_model );
857
+ Data_Get_Struct(self, SyckParser, parser);
858
+ syck_set_model( self, input, model );
859
+
860
+ bonus = (struct parser_xtra *)parser->bonus;
861
+ bonus->taint = syck_parser_assign_io(parser, &port);
862
+ bonus->data = rb_hash_new();
863
+ bonus->resolver = rb_attr_get( self, s_resolver );
864
+ if ( NIL_P( proc ) ) bonus->proc = 0;
865
+ else bonus->proc = proc;
866
+
867
+ return syck_parse( parser );
868
+ }
869
+
870
+ /*
871
+ * YAML::Syck::Parser.load_documents( IO or String ) { |doc| }
872
+ */
873
+ VALUE
874
+ syck_parser_load_documents(int argc, VALUE *argv, VALUE self)
875
+ {
876
+ VALUE port, proc, v, input, model;
877
+ SyckParser *parser;
878
+ struct parser_xtra *bonus;
879
+
880
+ rb_scan_args(argc, argv, "1&", &port, &proc);
881
+
882
+ input = rb_hash_aref( rb_attr_get( self, s_options ), sym_input );
883
+ model = rb_hash_aref( rb_attr_get( self, s_options ), sym_model );
884
+ Data_Get_Struct(self, SyckParser, parser);
885
+ syck_set_model( self, input, model );
886
+
887
+ bonus = (struct parser_xtra *)parser->bonus;
888
+ bonus->taint = syck_parser_assign_io(parser, &port);
889
+ bonus->resolver = rb_attr_get( self, s_resolver );
890
+ bonus->proc = 0;
891
+
892
+ while ( 1 )
893
+ {
894
+ /* Reset hash for tracking nodes */
895
+ bonus->data = rb_hash_new();
896
+
897
+ /* Parse a document */
898
+ v = syck_parse( parser );
899
+ if ( parser->eof == 1 )
900
+ {
901
+ break;
902
+ }
903
+
904
+ /* Pass document to block */
905
+ rb_funcall( proc, s_call, 1, v );
906
+ }
907
+
908
+ return Qnil;
909
+ }
910
+
911
+ /*
912
+ * YAML::Syck::Parser#set_resolver
913
+ */
914
+ VALUE
915
+ syck_parser_set_resolver(VALUE self, VALUE resolver)
916
+ {
917
+ rb_ivar_set( self, s_resolver, resolver );
918
+ return self;
919
+ }
920
+
921
+ /*
922
+ * YAML::Syck::Resolver.initialize
923
+ */
924
+ static VALUE
925
+ syck_resolver_initialize(VALUE self)
926
+ {
927
+ rb_ivar_set(self, s_tags, rb_hash_new());
928
+ return self;
929
+ }
930
+
931
+ /*
932
+ * YAML::Syck::Resolver#add_type
933
+ */
934
+ VALUE
935
+ syck_resolver_add_type(VALUE self, VALUE taguri, VALUE cls)
936
+ {
937
+ VALUE tags = rb_attr_get(self, s_tags);
938
+ rb_hash_aset( tags, taguri, cls );
939
+ return Qnil;
940
+ }
941
+
942
+ /*
943
+ * YAML::Syck::Resolver#use_types_at
944
+ */
945
+ VALUE
946
+ syck_resolver_use_types_at(VALUE self, VALUE hsh)
947
+ {
948
+ rb_ivar_set( self, s_tags, hsh );
949
+ return Qnil;
950
+ }
951
+
952
+ /*
953
+ * YAML::Syck::Resolver#detect_implicit
954
+ */
955
+ VALUE
956
+ syck_resolver_detect_implicit(VALUE self, VALUE val)
957
+ {
958
+ return rb_str_new2( "" );
959
+ }
960
+
961
+ /*
962
+ * YAML::Syck::Resolver#node_import
963
+ */
964
+ VALUE
965
+ syck_resolver_node_import(VALUE self, VALUE node)
966
+ {
967
+ SyckNode *n;
968
+ VALUE obj = Qnil;
969
+ int i = 0;
970
+ Data_Get_Struct(node, SyckNode, n);
971
+
972
+ switch (n->kind)
973
+ {
974
+ case syck_str_kind:
975
+ obj = rb_str_new( n->data.str->ptr, n->data.str->len );
976
+ break;
977
+
978
+ case syck_seq_kind:
979
+ obj = rb_ary_new2( n->data.list->idx );
980
+ for ( i = 0; i < n->data.list->idx; i++ )
981
+ {
982
+ rb_ary_store( obj, i, syck_seq_read( n, i ) );
983
+ }
984
+ break;
985
+
986
+ case syck_map_kind:
987
+ obj = rb_hash_new();
988
+ for ( i = 0; i < n->data.pairs->idx; i++ )
989
+ {
990
+ VALUE k = syck_map_read( n, map_key, i );
991
+ VALUE v = syck_map_read( n, map_value, i );
992
+ int skip_aset = 0;
993
+
994
+ /*
995
+ * Handle merge keys
996
+ */
997
+ if ( rb_obj_is_kind_of( k, cMergeKey ) )
998
+ {
999
+ if ( rb_obj_is_kind_of( v, rb_cHash ) )
1000
+ {
1001
+ VALUE dup = rb_funcall( v, s_dup, 0 );
1002
+ rb_funcall( dup, s_update, 1, obj );
1003
+ obj = dup;
1004
+ skip_aset = 1;
1005
+ }
1006
+ else if ( rb_obj_is_kind_of( v, rb_cArray ) )
1007
+ {
1008
+ VALUE end = rb_ary_pop( v );
1009
+ if ( rb_obj_is_kind_of( end, rb_cHash ) )
1010
+ {
1011
+ VALUE dup = rb_funcall( end, s_dup, 0 );
1012
+ v = rb_ary_reverse( v );
1013
+ rb_ary_push( v, obj );
1014
+ rb_block_call( v, s_each, 0, 0, syck_merge_i, dup );
1015
+ obj = dup;
1016
+ skip_aset = 1;
1017
+ }
1018
+ }
1019
+ }
1020
+ else if ( rb_obj_is_kind_of( k, cDefaultKey ) )
1021
+ {
1022
+ rb_funcall( obj, s_default_set, 1, v );
1023
+ skip_aset = 1;
1024
+ }
1025
+
1026
+ if ( ! skip_aset )
1027
+ {
1028
+ rb_hash_aset( obj, k, v );
1029
+ }
1030
+ }
1031
+ break;
1032
+ }
1033
+
1034
+ if ( n->type_id != NULL )
1035
+ {
1036
+ obj = rb_funcall( self, s_transfer, 2, rb_str_new2( n->type_id ), obj );
1037
+ }
1038
+ return obj;
1039
+ }
1040
+
1041
+ /*
1042
+ * Set instance variables
1043
+ */
1044
+ VALUE
1045
+ syck_set_ivars(VALUE vars, VALUE obj)
1046
+ {
1047
+ VALUE ivname = rb_ary_entry( vars, 0 );
1048
+ char *ivn;
1049
+ StringValue( ivname );
1050
+ ivn = S_ALLOCA_N( char, RSTRING_LEN(ivname) + 2 );
1051
+ ivn[0] = '@';
1052
+ ivn[1] = '\0';
1053
+ strncat( ivn, RSTRING_PTR(ivname), RSTRING_LEN(ivname) );
1054
+ rb_iv_set( obj, ivn, rb_ary_entry( vars, 1 ) );
1055
+ return Qnil;
1056
+ }
1057
+
1058
+ /*
1059
+ * YAML::Syck::Resolver#const_find
1060
+ */
1061
+ VALUE
1062
+ syck_const_find(VALUE const_name)
1063
+ {
1064
+ VALUE tclass = rb_cObject;
1065
+ VALUE tparts = rb_str_split( const_name, "::" );
1066
+ int i = 0;
1067
+ for ( i = 0; i < RARRAY_LEN(tparts); i++ ) {
1068
+ VALUE tpart = rb_to_id( rb_ary_entry( tparts, i ) );
1069
+ if ( !rb_const_defined( tclass, tpart ) ) return Qnil;
1070
+ tclass = rb_const_get( tclass, tpart );
1071
+ }
1072
+ return tclass;
1073
+ }
1074
+
1075
+ /*
1076
+ * YAML::Syck::Resolver#transfer
1077
+ */
1078
+ VALUE
1079
+ syck_resolver_transfer(VALUE self, VALUE type, VALUE val)
1080
+ {
1081
+ if (NIL_P(type) || RSTRING_LEN(StringValue(type)) == 0)
1082
+ {
1083
+ type = rb_funcall( self, s_detect_implicit, 1, val );
1084
+ }
1085
+
1086
+ if ( ! (NIL_P(type) || RSTRING_LEN(StringValue(type)) == 0) )
1087
+ {
1088
+ VALUE str_xprivate = rb_str_new2( "x-private" );
1089
+ VALUE colon = rb_str_new2( ":" );
1090
+ VALUE tags = rb_attr_get(self, s_tags);
1091
+ VALUE target_class = rb_hash_aref( tags, type );
1092
+ VALUE subclass = target_class;
1093
+ VALUE obj = Qnil;
1094
+
1095
+ /*
1096
+ * Should no tag match exactly, check for subclass format
1097
+ */
1098
+ if ( NIL_P( target_class ) )
1099
+ {
1100
+ VALUE subclass_parts = rb_ary_new();
1101
+ VALUE parts = rb_str_split( type, ":" );
1102
+
1103
+ while ( RARRAY_LEN(parts) > 1 )
1104
+ {
1105
+ VALUE partial;
1106
+ rb_ary_unshift( subclass_parts, rb_ary_pop( parts ) );
1107
+ partial = rb_ary_join( parts, colon );
1108
+ target_class = rb_hash_aref( tags, partial );
1109
+ if ( NIL_P( target_class ) )
1110
+ {
1111
+ rb_str_append( partial, colon );
1112
+ target_class = rb_hash_aref( tags, partial );
1113
+ }
1114
+
1115
+ /*
1116
+ * Possible subclass found, see if it supports subclassing
1117
+ */
1118
+ if ( ! NIL_P( target_class ) )
1119
+ {
1120
+ subclass = target_class;
1121
+ if ( RARRAY_LEN(subclass_parts) > 0 && rb_respond_to( target_class, s_tag_subclasses ) &&
1122
+ RTEST( rb_funcall( target_class, s_tag_subclasses, 0 ) ) )
1123
+ {
1124
+ VALUE subclass_v;
1125
+ subclass = rb_ary_join( subclass_parts, colon );
1126
+ subclass = rb_funcall( target_class, s_tag_read_class, 1, subclass );
1127
+ subclass_v = syck_const_find( subclass );
1128
+
1129
+ if ( subclass_v != Qnil )
1130
+ {
1131
+ subclass = subclass_v;
1132
+ }
1133
+ else if ( rb_cObject == target_class && subclass_v == Qnil )
1134
+ {
1135
+ target_class = cYObject;
1136
+ type = subclass;
1137
+ subclass = cYObject;
1138
+ }
1139
+ else /* workaround for SEGV. real fix please */
1140
+ {
1141
+ rb_raise( rb_eTypeError, "invalid subclass" );
1142
+ }
1143
+ }
1144
+ break;
1145
+ }
1146
+ }
1147
+ }
1148
+
1149
+ /* rb_raise(rb_eTypeError, "invalid typing scheme: %s given",
1150
+ * scheme);
1151
+ */
1152
+
1153
+ if ( rb_respond_to( target_class, s_call ) )
1154
+ {
1155
+ obj = rb_funcall( target_class, s_call, 2, type, val );
1156
+ }
1157
+ else
1158
+ {
1159
+ if ( rb_respond_to( target_class, s_yaml_new ) )
1160
+ {
1161
+ obj = rb_funcall( target_class, s_yaml_new, 3, subclass, type, val );
1162
+ }
1163
+ else if ( !NIL_P( target_class ) )
1164
+ {
1165
+ if ( subclass == rb_cBignum )
1166
+ {
1167
+ obj = rb_str2inum( val, 10 ); /* for yaml dumped by 1.8.3 [ruby-core:6159] */
1168
+ }
1169
+ else
1170
+ {
1171
+ obj = rb_obj_alloc( subclass );
1172
+ }
1173
+
1174
+ if ( rb_respond_to( obj, s_yaml_initialize ) )
1175
+ {
1176
+ rb_funcall( obj, s_yaml_initialize, 2, type, val );
1177
+ }
1178
+ else if ( !NIL_P( obj ) && rb_obj_is_instance_of( val, rb_cHash ) )
1179
+ {
1180
+ rb_block_call( val, s_each, 0, 0, syck_set_ivars, obj );
1181
+ }
1182
+ }
1183
+ else
1184
+ {
1185
+ VALUE parts = rb_str_split( type, ":" );
1186
+ VALUE scheme = rb_ary_shift( parts );
1187
+ if ( rb_str_cmp( scheme, str_xprivate ) == 0 )
1188
+ {
1189
+ VALUE name = rb_ary_join( parts, colon );
1190
+ obj = rb_funcall( cPrivateType, s_new, 2, name, val );
1191
+ }
1192
+ else
1193
+ {
1194
+ VALUE domain = rb_ary_shift( parts );
1195
+ VALUE name = rb_ary_join( parts, colon );
1196
+ obj = rb_funcall( cDomainType, s_new, 3, domain, name, val );
1197
+ }
1198
+ }
1199
+ }
1200
+ val = obj;
1201
+ }
1202
+
1203
+ return val;
1204
+ }
1205
+
1206
+ /*
1207
+ * YAML::Syck::Resolver#tagurize
1208
+ */
1209
+ VALUE
1210
+ syck_resolver_tagurize(VALUE self, VALUE val)
1211
+ {
1212
+ VALUE tmp = rb_check_string_type(val);
1213
+
1214
+ if ( !NIL_P(tmp) )
1215
+ {
1216
+ char *taguri = syck_type_id_to_uri( RSTRING_PTR(tmp) );
1217
+ val = rb_str_new2( taguri );
1218
+ S_FREE( taguri );
1219
+ }
1220
+
1221
+ return val;
1222
+ }
1223
+
1224
+ /*
1225
+ * YAML::Syck::DefaultResolver#detect_implicit
1226
+ */
1227
+ VALUE
1228
+ syck_defaultresolver_detect_implicit(VALUE self, VALUE val)
1229
+ {
1230
+ const char *type_id;
1231
+ VALUE tmp = rb_check_string_type(val);
1232
+
1233
+ if ( !NIL_P(tmp) )
1234
+ {
1235
+ val = tmp;
1236
+ type_id = syck_match_implicit( RSTRING_PTR(val), RSTRING_LEN(val) );
1237
+ return rb_str_new2( type_id );
1238
+ }
1239
+
1240
+ return rb_str_new2( "" );
1241
+ }
1242
+
1243
+ /*
1244
+ * YAML::Syck::DefaultResolver#node_import
1245
+ */
1246
+ VALUE
1247
+ syck_defaultresolver_node_import(VALUE self, VALUE node)
1248
+ {
1249
+ SyckNode *n;
1250
+ VALUE obj;
1251
+ Data_Get_Struct( node, SyckNode, n );
1252
+ if ( !yaml_org_handler( n, &obj ) )
1253
+ {
1254
+ obj = rb_funcall( self, s_transfer, 2, rb_str_new2( n->type_id ), obj );
1255
+ }
1256
+ return obj;
1257
+ }
1258
+
1259
+ /*
1260
+ * YAML::Syck::GenericResolver#node_import
1261
+ */
1262
+ VALUE
1263
+ syck_genericresolver_node_import(VALUE self, VALUE node)
1264
+ {
1265
+ SyckNode *n;
1266
+ int i = 0;
1267
+ VALUE t = Qnil, obj = Qnil, v = Qnil, style = Qnil;
1268
+ Data_Get_Struct(node, SyckNode, n);
1269
+
1270
+ if ( n->type_id != NULL )
1271
+ {
1272
+ t = rb_str_new2(n->type_id);
1273
+ }
1274
+
1275
+ switch (n->kind)
1276
+ {
1277
+ case syck_str_kind:
1278
+ {
1279
+ v = rb_str_new( n->data.str->ptr, n->data.str->len );
1280
+ rb_enc_associate(v, rb_utf8_encoding());
1281
+ if ( n->data.str->style == scalar_1quote )
1282
+ {
1283
+ style = sym_1quote;
1284
+ }
1285
+ else if ( n->data.str->style == scalar_2quote )
1286
+ {
1287
+ style = sym_2quote;
1288
+ }
1289
+ else if ( n->data.str->style == scalar_fold )
1290
+ {
1291
+ style = sym_fold;
1292
+ }
1293
+ else if ( n->data.str->style == scalar_literal )
1294
+ {
1295
+ style = sym_literal;
1296
+ }
1297
+ else if ( n->data.str->style == scalar_plain )
1298
+ {
1299
+ style = sym_plain;
1300
+ }
1301
+ obj = rb_funcall( cScalar, s_new, 3, t, v, style );
1302
+ }
1303
+ break;
1304
+
1305
+ case syck_seq_kind:
1306
+ v = rb_ary_new2( syck_seq_count( n ) );
1307
+ for ( i = 0; i < syck_seq_count( n ); i++ )
1308
+ {
1309
+ rb_ary_store( v, i, syck_seq_read( n, i ) );
1310
+ }
1311
+ if ( n->data.list->style == seq_inline )
1312
+ {
1313
+ style = sym_inline;
1314
+ }
1315
+ obj = rb_funcall( cSeq, s_new, 3, t, v, style );
1316
+ rb_iv_set(obj, "@kind", sym_seq);
1317
+ break;
1318
+
1319
+ case syck_map_kind:
1320
+ v = rb_hash_new();
1321
+ for ( i = 0; i < syck_map_count( n ); i++ )
1322
+ {
1323
+ rb_hash_aset( v, syck_map_read( n, map_key, i ), syck_map_read( n, map_value, i ) );
1324
+ }
1325
+ if ( n->data.pairs->style == map_inline )
1326
+ {
1327
+ style = sym_inline;
1328
+ }
1329
+ obj = rb_funcall( cMap, s_new, 3, t, v, style );
1330
+ rb_iv_set(obj, "@kind", sym_map);
1331
+ break;
1332
+ }
1333
+
1334
+ return obj;
1335
+ }
1336
+
1337
+ /*
1338
+ * YAML::Syck::BadAlias.initialize
1339
+ */
1340
+ VALUE
1341
+ syck_badalias_initialize(VALUE self, VALUE val)
1342
+ {
1343
+ rb_iv_set( self, "@name", val );
1344
+ return self;
1345
+ }
1346
+
1347
+ /*
1348
+ * YAML::Syck::BadAlias.<=>
1349
+ */
1350
+ VALUE
1351
+ syck_badalias_cmp(VALUE alias1, VALUE alias2)
1352
+ {
1353
+ VALUE str1 = rb_ivar_get( alias1, s_name );
1354
+ VALUE str2 = rb_ivar_get( alias2, s_name );
1355
+ VALUE val = rb_funcall( str1, s_cmp, 1, str2 );
1356
+ return val;
1357
+ }
1358
+
1359
+ /*
1360
+ * YAML::DomainType.initialize
1361
+ */
1362
+ VALUE
1363
+ syck_domaintype_initialize(VALUE self, VALUE domain, VALUE type_id, VALUE val)
1364
+ {
1365
+ rb_iv_set( self, "@domain", domain );
1366
+ rb_iv_set( self, "@type_id", type_id );
1367
+ rb_iv_set( self, "@value", val );
1368
+ return self;
1369
+ }
1370
+
1371
+ /*
1372
+ * YAML::Object.initialize
1373
+ */
1374
+ VALUE
1375
+ syck_yobject_initialize(VALUE self, VALUE klass, VALUE ivars)
1376
+ {
1377
+ rb_iv_set( self, "@class", klass );
1378
+ rb_iv_set( self, "@ivars", ivars );
1379
+ return self;
1380
+ }
1381
+
1382
+ /*
1383
+ * YAML::PrivateType.initialize
1384
+ */
1385
+ VALUE
1386
+ syck_privatetype_initialize(VALUE self, VALUE type_id, VALUE val)
1387
+ {
1388
+ rb_iv_set( self, "@type_id", type_id );
1389
+ rb_iv_set( self, "@value", val );
1390
+ return self;
1391
+ }
1392
+
1393
+ /*
1394
+ * Mark node contents.
1395
+ */
1396
+ static void
1397
+ syck_node_mark(SyckNode *n)
1398
+ {
1399
+ int i;
1400
+ rb_gc_mark_maybe( n->id );
1401
+ switch ( n->kind )
1402
+ {
1403
+ case syck_seq_kind:
1404
+ for ( i = 0; i < n->data.list->idx; i++ )
1405
+ {
1406
+ rb_gc_mark( syck_seq_read( n, i ) );
1407
+ }
1408
+ break;
1409
+
1410
+ case syck_map_kind:
1411
+ for ( i = 0; i < n->data.pairs->idx; i++ )
1412
+ {
1413
+ rb_gc_mark( syck_map_read( n, map_key, i ) );
1414
+ rb_gc_mark( syck_map_read( n, map_value, i ) );
1415
+ }
1416
+ break;
1417
+
1418
+ case syck_str_kind:
1419
+ default:
1420
+ /* nothing */
1421
+ break;
1422
+ }
1423
+ #if 0 /* maybe needed */
1424
+ if ( n->shortcut ) syck_node_mark( n->shortcut ); /* caution: maybe cyclic */
1425
+ #endif
1426
+ }
1427
+
1428
+ /*
1429
+ * YAML::Syck::Scalar.allocate
1430
+ */
1431
+ VALUE
1432
+ syck_scalar_alloc(VALUE class)
1433
+ {
1434
+ SyckNode *node = syck_alloc_str();
1435
+ VALUE obj = Data_Wrap_Struct( class, syck_node_mark, syck_free_node, node );
1436
+ node->id = obj;
1437
+ return obj;
1438
+ }
1439
+
1440
+ /*
1441
+ * YAML::Syck::Scalar.initialize
1442
+ */
1443
+ VALUE
1444
+ syck_scalar_initialize(VALUE self, VALUE type_id, VALUE val, VALUE style)
1445
+ {
1446
+ rb_iv_set( self, "@kind", sym_scalar );
1447
+ rb_funcall( self, s_type_id_set, 1, type_id );
1448
+ rb_funcall( self, s_value_set, 1, val );
1449
+ rb_funcall( self, s_style_set, 1, style );
1450
+ return self;
1451
+ }
1452
+
1453
+ /*
1454
+ * YAML::Syck::Scalar.style=
1455
+ */
1456
+ VALUE
1457
+ syck_scalar_style_set(VALUE self, VALUE style)
1458
+ {
1459
+ SyckNode *node;
1460
+ Data_Get_Struct( self, SyckNode, node );
1461
+
1462
+ if ( NIL_P( style ) )
1463
+ {
1464
+ node->data.str->style = scalar_none;
1465
+ }
1466
+ else if ( style == sym_1quote )
1467
+ {
1468
+ node->data.str->style = scalar_1quote;
1469
+ }
1470
+ else if ( style == sym_2quote )
1471
+ {
1472
+ node->data.str->style = scalar_2quote;
1473
+ }
1474
+ else if ( style == sym_fold )
1475
+ {
1476
+ node->data.str->style = scalar_fold;
1477
+ }
1478
+ else if ( style == sym_literal )
1479
+ {
1480
+ node->data.str->style = scalar_literal;
1481
+ }
1482
+ else if ( style == sym_plain )
1483
+ {
1484
+ node->data.str->style = scalar_plain;
1485
+ }
1486
+
1487
+ rb_iv_set( self, "@style", style );
1488
+ return self;
1489
+ }
1490
+
1491
+ /*
1492
+ * YAML::Syck::Scalar.value=
1493
+ */
1494
+ VALUE
1495
+ syck_scalar_value_set(VALUE self, VALUE val)
1496
+ {
1497
+ SyckNode *node;
1498
+ Data_Get_Struct( self, SyckNode, node );
1499
+
1500
+ StringValue( val );
1501
+ node->data.str->ptr = syck_strndup( RSTRING_PTR(val), RSTRING_LEN(val) );
1502
+ node->data.str->len = RSTRING_LEN(val);
1503
+ node->data.str->style = scalar_none;
1504
+
1505
+ rb_iv_set( self, "@value", val );
1506
+ return val;
1507
+ }
1508
+
1509
+ /*
1510
+ * YAML::Syck::Seq.allocate
1511
+ */
1512
+ VALUE
1513
+ syck_seq_alloc(VALUE class)
1514
+ {
1515
+ SyckNode *node;
1516
+ VALUE obj;
1517
+ node = syck_alloc_seq();
1518
+ obj = Data_Wrap_Struct( class, syck_node_mark, syck_free_node, node );
1519
+ node->id = obj;
1520
+ return obj;
1521
+ }
1522
+
1523
+ /*
1524
+ * YAML::Syck::Seq.initialize
1525
+ */
1526
+ VALUE
1527
+ syck_seq_initialize(VALUE self, VALUE type_id, VALUE val, VALUE style)
1528
+ {
1529
+ SyckNode *node;
1530
+ Data_Get_Struct( self, SyckNode, node );
1531
+
1532
+ rb_iv_set( self, "@kind", sym_seq );
1533
+ rb_funcall( self, s_type_id_set, 1, type_id );
1534
+ rb_funcall( self, s_value_set, 1, val );
1535
+ rb_funcall( self, s_style_set, 1, style );
1536
+ return self;
1537
+ }
1538
+
1539
+ /*
1540
+ * YAML::Syck::Seq.value=
1541
+ */
1542
+ VALUE
1543
+ syck_seq_value_set(VALUE self, VALUE val)
1544
+ {
1545
+ SyckNode *node;
1546
+ Data_Get_Struct( self, SyckNode, node );
1547
+
1548
+ val = rb_check_array_type( val );
1549
+ if ( !NIL_P( val ) ) {
1550
+ int i;
1551
+ syck_seq_empty( node );
1552
+ for ( i = 0; i < RARRAY_LEN( val ); i++ )
1553
+ {
1554
+ syck_seq_add( node, rb_ary_entry(val, i) );
1555
+ }
1556
+ }
1557
+
1558
+ rb_iv_set( self, "@value", val );
1559
+ return val;
1560
+ }
1561
+
1562
+ /*
1563
+ * YAML::Syck::Seq.add
1564
+ */
1565
+ VALUE
1566
+ syck_seq_add_m(VALUE self, VALUE val)
1567
+ {
1568
+ SyckNode *node;
1569
+ VALUE emitter = rb_ivar_get( self, s_emitter );
1570
+ Data_Get_Struct( self, SyckNode, node );
1571
+
1572
+ if ( rb_respond_to( emitter, s_node_export ) ) {
1573
+ val = rb_funcall( emitter, s_node_export, 1, val );
1574
+ }
1575
+ syck_seq_add( node, val );
1576
+ rb_ary_push( rb_ivar_get( self, s_value ), val );
1577
+
1578
+ return self;
1579
+ }
1580
+
1581
+ /*
1582
+ * YAML::Syck::Seq.style=
1583
+ */
1584
+ VALUE
1585
+ syck_seq_style_set(VALUE self, VALUE style)
1586
+ {
1587
+ SyckNode *node;
1588
+ Data_Get_Struct( self, SyckNode, node );
1589
+
1590
+ if ( style == sym_inline )
1591
+ {
1592
+ node->data.list->style = seq_inline;
1593
+ }
1594
+ else
1595
+ {
1596
+ node->data.list->style = seq_none;
1597
+ }
1598
+
1599
+ rb_iv_set( self, "@style", style );
1600
+ return self;
1601
+ }
1602
+
1603
+ /*
1604
+ * YAML::Syck::Map.allocate
1605
+ */
1606
+ VALUE
1607
+ syck_map_alloc(VALUE class)
1608
+ {
1609
+ SyckNode *node;
1610
+ VALUE obj;
1611
+ node = syck_alloc_map();
1612
+ obj = Data_Wrap_Struct( class, syck_node_mark, syck_free_node, node );
1613
+ node->id = obj;
1614
+ return obj;
1615
+ }
1616
+
1617
+ /*
1618
+ * YAML::Syck::Map.initialize
1619
+ */
1620
+ VALUE
1621
+ syck_map_initialize(VALUE self, VALUE type_id, VALUE val, VALUE style)
1622
+ {
1623
+ SyckNode *node;
1624
+ Data_Get_Struct( self, SyckNode, node );
1625
+
1626
+ if ( !NIL_P( val ) )
1627
+ {
1628
+ VALUE hsh = rb_check_convert_type(val, T_HASH, "Hash", "to_hash");
1629
+ VALUE keys;
1630
+ int i;
1631
+ if ( NIL_P(hsh) )
1632
+ {
1633
+ rb_raise( rb_eTypeError, "wrong argument type" );
1634
+ }
1635
+
1636
+ keys = rb_funcall( hsh, s_keys, 0 );
1637
+ for ( i = 0; i < RARRAY_LEN(keys); i++ )
1638
+ {
1639
+ VALUE key = rb_ary_entry(keys, i);
1640
+ syck_map_add( node, key, rb_hash_aref(hsh, key) );
1641
+ }
1642
+ }
1643
+
1644
+ rb_iv_set( self, "@kind", sym_seq );
1645
+ rb_funcall( self, s_type_id_set, 1, type_id );
1646
+ rb_funcall( self, s_value_set, 1, val );
1647
+ rb_funcall( self, s_style_set, 1, style );
1648
+ return self;
1649
+ }
1650
+
1651
+ /*
1652
+ * YAML::Syck::Map.value=
1653
+ */
1654
+ VALUE
1655
+ syck_map_value_set(VALUE self, VALUE val)
1656
+ {
1657
+ SyckNode *node;
1658
+ Data_Get_Struct( self, SyckNode, node );
1659
+
1660
+ if ( !NIL_P( val ) )
1661
+ {
1662
+ VALUE hsh = rb_check_convert_type(val, T_HASH, "Hash", "to_hash");
1663
+ VALUE keys;
1664
+ int i;
1665
+ if ( NIL_P(hsh) )
1666
+ {
1667
+ rb_raise( rb_eTypeError, "wrong argument type" );
1668
+ }
1669
+
1670
+ syck_map_empty( node );
1671
+ keys = rb_funcall( hsh, s_keys, 0 );
1672
+ for ( i = 0; i < RARRAY_LEN(keys); i++ )
1673
+ {
1674
+ VALUE key = rb_ary_entry(keys, i);
1675
+ syck_map_add( node, key, rb_hash_aref(hsh, key) );
1676
+ }
1677
+ }
1678
+
1679
+ rb_iv_set( self, "@value", val );
1680
+ return val;
1681
+ }
1682
+
1683
+ /*
1684
+ * YAML::Syck::Map.add
1685
+ */
1686
+ VALUE
1687
+ syck_map_add_m(VALUE self, VALUE key, VALUE val)
1688
+ {
1689
+ SyckNode *node;
1690
+ VALUE emitter = rb_ivar_get( self, s_emitter );
1691
+ Data_Get_Struct( self, SyckNode, node );
1692
+
1693
+ if ( rb_respond_to( emitter, s_node_export ) ) {
1694
+ key = rb_funcall( emitter, s_node_export, 1, key );
1695
+ val = rb_funcall( emitter, s_node_export, 1, val );
1696
+ }
1697
+ syck_map_add( node, key, val );
1698
+ rb_hash_aset( rb_ivar_get( self, s_value ), key, val );
1699
+
1700
+ return self;
1701
+ }
1702
+
1703
+ /*
1704
+ * YAML::Syck::Map.style=
1705
+ */
1706
+ VALUE
1707
+ syck_map_style_set(VALUE self, VALUE style)
1708
+ {
1709
+ SyckNode *node;
1710
+ Data_Get_Struct( self, SyckNode, node );
1711
+
1712
+ if ( style == sym_inline )
1713
+ {
1714
+ node->data.pairs->style = map_inline;
1715
+ }
1716
+ else
1717
+ {
1718
+ node->data.pairs->style = map_none;
1719
+ }
1720
+
1721
+ rb_iv_set( self, "@style", style );
1722
+ return self;
1723
+ }
1724
+
1725
+ #if 0
1726
+ /*
1727
+ * Cloning method for all node types
1728
+ */
1729
+ VALUE
1730
+ syck_node_init_copy(VALUE copy, VALUE orig)
1731
+ {
1732
+ SyckNode *copy_n;
1733
+ SyckNode *orig_n;
1734
+
1735
+ if ( copy == orig )
1736
+ return copy;
1737
+
1738
+ if ( TYPE( orig ) != T_DATA )
1739
+ {
1740
+ rb_raise( rb_eTypeError, "wrong argument type" );
1741
+ }
1742
+
1743
+ Data_Get_Struct( orig, SyckNode, orig_n );
1744
+ Data_Get_Struct( copy, SyckNode, copy_n );
1745
+ MEMCPY( copy_n, orig_n, SyckNode, 1 );
1746
+ return copy;
1747
+ }
1748
+ #endif
1749
+
1750
+ /*
1751
+ * YAML::Syck::Node#type_id=
1752
+ */
1753
+ VALUE
1754
+ syck_node_type_id_set(VALUE self, VALUE type_id)
1755
+ {
1756
+ SyckNode *node;
1757
+ Data_Get_Struct( self, SyckNode, node );
1758
+
1759
+ S_FREE( node->type_id );
1760
+
1761
+ if ( !NIL_P( type_id ) ) {
1762
+ StringValue( type_id );
1763
+ node->type_id = syck_strndup( RSTRING_PTR(type_id), RSTRING_LEN(type_id) );
1764
+ }
1765
+
1766
+ rb_iv_set( self, "@type_id", type_id );
1767
+ return type_id;
1768
+ }
1769
+
1770
+ /*
1771
+ * YAML::Syck::Node.transform
1772
+ */
1773
+ VALUE
1774
+ syck_node_transform(VALUE self)
1775
+ {
1776
+ VALUE t;
1777
+ SyckNode *n = NULL;
1778
+ SyckNode *orig_n;
1779
+ Data_Get_Struct(self, SyckNode, orig_n);
1780
+ t = Data_Wrap_Struct( cNode, syck_node_mark, syck_free_node, 0 );
1781
+
1782
+ switch (orig_n->kind)
1783
+ {
1784
+ case syck_map_kind:
1785
+ {
1786
+ int i;
1787
+ DATA_PTR(t) = n = syck_alloc_map();
1788
+ for ( i = 0; i < orig_n->data.pairs->idx; i++ )
1789
+ {
1790
+ syck_map_add( n, rb_funcall( syck_map_read( orig_n, map_key, i ), s_transform, 0 ),
1791
+ rb_funcall( syck_map_read( orig_n, map_value, i ), s_transform, 0 ) );
1792
+ }
1793
+ }
1794
+ break;
1795
+
1796
+ case syck_seq_kind:
1797
+ {
1798
+ int i;
1799
+ DATA_PTR(t) = n = syck_alloc_seq();
1800
+ for ( i = 0; i < orig_n->data.list->idx; i++ )
1801
+ {
1802
+ syck_seq_add( n, rb_funcall( syck_seq_read( orig_n, i ), s_transform, 0 ) );
1803
+ }
1804
+ }
1805
+ break;
1806
+
1807
+ case syck_str_kind:
1808
+ DATA_PTR(t) = n = syck_new_str2( orig_n->data.str->ptr, orig_n->data.str->len, orig_n->data.str->style );
1809
+ break;
1810
+ }
1811
+
1812
+ if ( orig_n->type_id != NULL )
1813
+ {
1814
+ n->type_id = syck_strndup( orig_n->type_id, strlen( orig_n->type_id ) );
1815
+ }
1816
+ if ( orig_n->anchor != NULL )
1817
+ {
1818
+ n->anchor = syck_strndup( orig_n->anchor, strlen( orig_n->anchor ) );
1819
+ }
1820
+ n->id = t;
1821
+ return rb_funcall( oDefaultResolver, s_node_import, 1, t );
1822
+ }
1823
+
1824
+ /*
1825
+ * Emitter callback: assembles YAML document events from
1826
+ * Ruby symbols. This is a brilliant way to do it.
1827
+ * No one could possibly object.
1828
+ */
1829
+ void
1830
+ rb_syck_emitter_handler(SyckEmitter *e, st_data_t data)
1831
+ {
1832
+ SyckNode *n;
1833
+ Data_Get_Struct((VALUE)data, SyckNode, n);
1834
+
1835
+ switch (n->kind)
1836
+ {
1837
+ case syck_map_kind:
1838
+ {
1839
+ int i;
1840
+ syck_emit_map( e, n->type_id, n->data.pairs->style );
1841
+ for ( i = 0; i < n->data.pairs->idx; i++ )
1842
+ {
1843
+ syck_emit_item( e, syck_map_read( n, map_key, i ) );
1844
+ syck_emit_item( e, syck_map_read( n, map_value, i ) );
1845
+ }
1846
+ syck_emit_end( e );
1847
+ }
1848
+ break;
1849
+
1850
+ case syck_seq_kind:
1851
+ {
1852
+ int i;
1853
+ syck_emit_seq( e, n->type_id, n->data.list->style );
1854
+ for ( i = 0; i < n->data.list->idx; i++ )
1855
+ {
1856
+ syck_emit_item( e, syck_seq_read( n, i ) );
1857
+ }
1858
+ syck_emit_end( e );
1859
+ }
1860
+ break;
1861
+
1862
+ case syck_str_kind:
1863
+ {
1864
+ syck_emit_scalar( e, n->type_id, n->data.str->style, 0, 0, 0, n->data.str->ptr, n->data.str->len );
1865
+ }
1866
+ break;
1867
+ }
1868
+ }
1869
+
1870
+ /*
1871
+ * Handle output from the emitter
1872
+ */
1873
+ void
1874
+ rb_syck_output_handler(SyckEmitter * emitter, char *str, long len)
1875
+ {
1876
+ struct emitter_xtra *bonus = (struct emitter_xtra *)emitter->bonus;
1877
+ VALUE dest = bonus->port;
1878
+ if (TYPE(dest) == T_STRING) {
1879
+ rb_str_cat( dest, str, len );
1880
+ } else {
1881
+ rb_io_write( dest, rb_str_new( str, len ) );
1882
+ }
1883
+ }
1884
+
1885
+ /*
1886
+ * Helper function for marking nodes in the anchor
1887
+ * symbol table.
1888
+ */
1889
+ void
1890
+ syck_out_mark(VALUE emitter, VALUE node)
1891
+ {
1892
+ SyckEmitter *emitterPtr;
1893
+ struct emitter_xtra *bonus;
1894
+ Data_Get_Struct(emitter, SyckEmitter, emitterPtr);
1895
+ bonus = (struct emitter_xtra *)emitterPtr->bonus;
1896
+ rb_ivar_set( node, s_emitter, emitter );
1897
+ /* syck_emitter_mark_node( emitterPtr, (st_data_t)node ); */
1898
+ if ( !NIL_P( bonus->oid ) ) {
1899
+ rb_hash_aset( bonus->data, bonus->oid, node );
1900
+ }
1901
+ }
1902
+
1903
+ /*
1904
+ * Mark emitter values.
1905
+ */
1906
+ static void
1907
+ syck_mark_emitter(SyckEmitter *emitter)
1908
+ {
1909
+ struct emitter_xtra *bonus = (struct emitter_xtra *)emitter->bonus;
1910
+ rb_gc_mark( bonus->oid );
1911
+ rb_gc_mark( bonus->data );
1912
+ rb_gc_mark( bonus->port );
1913
+ }
1914
+
1915
+ /*
1916
+ * Free the emitter and any bonus attachment.
1917
+ */
1918
+ void
1919
+ rb_syck_free_emitter(SyckEmitter *e)
1920
+ {
1921
+ S_FREE( e->bonus );
1922
+ syck_free_emitter(e);
1923
+ }
1924
+
1925
+ /*
1926
+ * YAML::Syck::Emitter.allocate
1927
+ */
1928
+ VALUE syck_emitter_s_alloc _((VALUE));
1929
+ VALUE
1930
+ syck_emitter_s_alloc(VALUE class)
1931
+ {
1932
+ VALUE pobj;
1933
+ SyckEmitter *emitter = syck_new_emitter();
1934
+
1935
+ emitter->bonus = S_ALLOC( struct emitter_xtra );
1936
+ S_MEMZERO( emitter->bonus, struct emitter_xtra, 1 );
1937
+
1938
+ pobj = Data_Wrap_Struct( class, syck_mark_emitter, rb_syck_free_emitter, emitter );
1939
+ syck_emitter_handler( emitter, rb_syck_emitter_handler );
1940
+ syck_output_handler( emitter, rb_syck_output_handler );
1941
+
1942
+ rb_ivar_set( pobj, s_out, rb_funcall( cOut, s_new, 1, pobj ) );
1943
+ return pobj;
1944
+ }
1945
+
1946
+ static VALUE
1947
+ id_hash_new(void)
1948
+ {
1949
+ VALUE hash;
1950
+ hash = rb_hash_new();
1951
+ rb_funcall(hash, rb_intern("compare_by_identity"), 0);
1952
+ return hash;
1953
+ }
1954
+
1955
+ /*
1956
+ * YAML::Syck::Emitter.reset( options )
1957
+ */
1958
+ VALUE
1959
+ syck_emitter_reset(int argc, VALUE *argv, VALUE self)
1960
+ {
1961
+ VALUE options, tmp;
1962
+ SyckEmitter *emitter;
1963
+ struct emitter_xtra *bonus;
1964
+
1965
+ Data_Get_Struct(self, SyckEmitter, emitter);
1966
+ bonus = (struct emitter_xtra *)emitter->bonus;
1967
+
1968
+ bonus->oid = Qnil;
1969
+ bonus->port = rb_str_new2( "" );
1970
+ bonus->data = id_hash_new();
1971
+
1972
+ if (rb_scan_args(argc, argv, "01", &options) == 0)
1973
+ {
1974
+ options = rb_hash_new();
1975
+ rb_ivar_set(self, s_options, options);
1976
+ }
1977
+ else if ( !NIL_P(tmp = rb_check_string_type(options)) )
1978
+ {
1979
+ bonus->port = tmp;
1980
+ }
1981
+ else if ( rb_respond_to( options, s_write ) )
1982
+ {
1983
+ bonus->port = options;
1984
+ }
1985
+ else
1986
+ {
1987
+ Check_Type(options, T_HASH);
1988
+ rb_ivar_set(self, s_options, options);
1989
+ }
1990
+
1991
+ emitter->headless = 0;
1992
+ rb_ivar_set(self, s_level, INT2FIX(0));
1993
+ rb_ivar_set(self, s_resolver, Qnil);
1994
+ return self;
1995
+ }
1996
+
1997
+ /*
1998
+ * YAML::Syck::Emitter.emit( object_id ) { |out| ... }
1999
+ */
2000
+ VALUE
2001
+ syck_emitter_emit(int argc, VALUE *argv, VALUE self)
2002
+ {
2003
+ VALUE oid, proc;
2004
+ SyckEmitter *emitter;
2005
+ struct emitter_xtra *bonus;
2006
+ SYMID symple;
2007
+ int level = FIX2INT(rb_ivar_get(self, s_level)) + 1;
2008
+ rb_ivar_set(self, s_level, INT2FIX(level));
2009
+
2010
+ rb_scan_args(argc, argv, "1&", &oid, &proc);
2011
+ Data_Get_Struct(self, SyckEmitter, emitter);
2012
+ bonus = (struct emitter_xtra *)emitter->bonus;
2013
+
2014
+ /* Calculate anchors, normalize nodes, build a simpler symbol table */
2015
+ bonus->oid = oid;
2016
+ if ( !NIL_P( oid ) && RTEST( rb_funcall( bonus->data, s_haskey, 1, oid ) ) ) {
2017
+ symple = rb_hash_aref( bonus->data, oid );
2018
+ } else {
2019
+ symple = rb_funcall( proc, s_call, 1, rb_ivar_get( self, s_out ) );
2020
+ }
2021
+ syck_emitter_mark_node( emitter, (st_data_t)symple );
2022
+
2023
+ /* Second pass, build emitted string */
2024
+ level -= 1;
2025
+ rb_ivar_set(self, s_level, INT2FIX(level));
2026
+ if ( level == 0 )
2027
+ {
2028
+ syck_emit(emitter, (st_data_t)symple);
2029
+ syck_emitter_flush(emitter, 0);
2030
+
2031
+ return bonus->port;
2032
+ }
2033
+
2034
+ return symple;
2035
+ }
2036
+
2037
+ /*
2038
+ * YAML::Syck::Emitter#node_export
2039
+ */
2040
+ VALUE
2041
+ syck_emitter_node_export(VALUE self, VALUE node)
2042
+ {
2043
+ return rb_funcall( node, s_to_yaml, 1, self );
2044
+ }
2045
+
2046
+ /*
2047
+ * YAML::Syck::Emitter#set_resolver
2048
+ */
2049
+ VALUE
2050
+ syck_emitter_set_resolver(VALUE self, VALUE resolver)
2051
+ {
2052
+ rb_ivar_set( self, s_resolver, resolver );
2053
+ return self;
2054
+ }
2055
+
2056
+ /*
2057
+ * YAML::Syck::Out::initialize
2058
+ */
2059
+ VALUE
2060
+ syck_out_initialize(VALUE self, VALUE emitter)
2061
+ {
2062
+ rb_ivar_set( self, s_emitter, emitter );
2063
+ return self;
2064
+ }
2065
+
2066
+ /*
2067
+ * YAML::Syck::Out::map
2068
+ */
2069
+ VALUE
2070
+ syck_out_map(int argc, VALUE *argv, VALUE self)
2071
+ {
2072
+ VALUE type_id, style, map;
2073
+ if (rb_scan_args(argc, argv, "11", &type_id, &style) == 1) {
2074
+ style = Qnil;
2075
+ }
2076
+ map = rb_funcall( cMap, s_new, 3, type_id, rb_hash_new(), style );
2077
+ syck_out_mark( rb_ivar_get( self, s_emitter ), map );
2078
+ rb_yield( map );
2079
+ return map;
2080
+ }
2081
+
2082
+ /*
2083
+ * YAML::Syck::Out::seq
2084
+ */
2085
+ VALUE
2086
+ syck_out_seq(int argc, VALUE *argv, VALUE self)
2087
+ {
2088
+ VALUE type_id, style, seq;
2089
+ if (rb_scan_args(argc, argv, "11", &type_id, &style) == 1) {
2090
+ style = Qnil;
2091
+ }
2092
+ seq = rb_funcall( cSeq, s_new, 3, type_id, rb_ary_new(), style );
2093
+ syck_out_mark( rb_ivar_get( self, s_emitter ), seq );
2094
+ rb_yield( seq );
2095
+ return seq;
2096
+ }
2097
+
2098
+ /*
2099
+ * YAML::Syck::Out::scalar
2100
+ syck_out_scalar( self, type_id, str, style )
2101
+ VALUE self, type_id, str, style;
2102
+ */
2103
+ VALUE
2104
+ syck_out_scalar(int argc, VALUE *argv, VALUE self)
2105
+ {
2106
+ VALUE type_id, str, style, scalar;
2107
+ rb_scan_args(argc, argv, "21", &type_id, &str, &style);
2108
+ scalar = rb_funcall( cScalar, s_new, 3, type_id, str, style );
2109
+ syck_out_mark( rb_ivar_get( self, s_emitter ), scalar );
2110
+ return scalar;
2111
+ }
2112
+
2113
+ /*
2114
+ * Initialize Syck extension
2115
+ */
2116
+ void
2117
+ Init_syck()
2118
+ {
2119
+ VALUE rb_syck = rb_define_module_under( rb_cObject, "Syck" );
2120
+ rb_define_module_function( rb_syck, "compile", rb_syck_compile, 1 );
2121
+
2122
+ /*
2123
+ * Global symbols
2124
+ */
2125
+ s_new = rb_intern("new");
2126
+ s_utc = rb_intern("utc");
2127
+ s_at = rb_intern("at");
2128
+ s_to_f = rb_intern("to_f");
2129
+ s_to_i = rb_intern("to_i");
2130
+ s_read = rb_intern("read");
2131
+ s_binmode = rb_intern("binmode");
2132
+ s_transfer = rb_intern("transfer");
2133
+ s_call = rb_intern("call");
2134
+ s_cmp = rb_intern("<=>");
2135
+ s_intern = rb_intern("intern");
2136
+ s_update = rb_intern("update");
2137
+ s_detect_implicit = rb_intern("detect_implicit");
2138
+ s_dup = rb_intern("dup");
2139
+ s_default_set = rb_intern("default=");
2140
+ s_match = rb_intern("match");
2141
+ s_push = rb_intern("push");
2142
+ s_haskey = rb_intern("has_key?");
2143
+ s_keys = rb_intern("keys");
2144
+ s_node_import = rb_intern("node_import");
2145
+ s_tr_bang = rb_intern("tr!");
2146
+ s_unpack = rb_intern("unpack");
2147
+ s_write = rb_intern("write");
2148
+ s_tag_read_class = rb_intern( "yaml_tag_read_class" );
2149
+ s_tag_subclasses = rb_intern( "yaml_tag_subclasses?" );
2150
+ s_emitter = rb_intern( "emitter" );
2151
+ s_set_resolver = rb_intern( "set_resolver" );
2152
+ s_node_export = rb_intern( "node_export" );
2153
+ s_to_yaml = rb_intern( "to_yaml" );
2154
+ s_transform = rb_intern( "transform" );
2155
+ s_yaml_new = rb_intern("yaml_new");
2156
+ s_yaml_initialize = rb_intern("yaml_initialize");
2157
+ s_each = rb_intern("each");
2158
+ s_parse = rb_intern("parse");
2159
+
2160
+ s_tags = rb_intern("@tags");
2161
+ s_name = rb_intern("@name");
2162
+ s_options = rb_intern("@options");
2163
+ s_kind = rb_intern("@kind");
2164
+ s_type_id = rb_intern("@type_id");
2165
+ s_type_id_set = rb_intern("type_id=");
2166
+ s_resolver = rb_intern("@resolver");
2167
+ s_level = rb_intern( "@level" );
2168
+ s_style = rb_intern("@style");
2169
+ s_style_set = rb_intern("style=");
2170
+ s_value = rb_intern("@value");
2171
+ s_value_set = rb_intern("value=");
2172
+ s_out = rb_intern("@out");
2173
+ s_input = rb_intern("@input");
2174
+
2175
+ sym_model = ID2SYM(rb_intern("Model"));
2176
+ sym_generic = ID2SYM(rb_intern("Generic"));
2177
+ sym_bytecode = ID2SYM(rb_intern("bytecode"));
2178
+ sym_map = ID2SYM(rb_intern("map"));
2179
+ sym_scalar = ID2SYM(rb_intern("scalar"));
2180
+ sym_seq = ID2SYM(rb_intern("seq"));
2181
+ sym_1quote = ID2SYM(rb_intern("quote1"));
2182
+ sym_2quote = ID2SYM(rb_intern("quote2"));
2183
+ sym_fold = ID2SYM(rb_intern("fold"));
2184
+ sym_literal = ID2SYM(rb_intern("literal"));
2185
+ sym_plain = ID2SYM(rb_intern("plain"));
2186
+ sym_inline = ID2SYM(rb_intern("inline"));
2187
+
2188
+ /*
2189
+ * Define YAML::Syck::Resolver class
2190
+ */
2191
+ cResolver = rb_define_class_under( rb_syck, "Resolver", rb_cObject );
2192
+ rb_define_attr( cResolver, "tags", 1, 1 );
2193
+ rb_define_method( cResolver, "initialize", syck_resolver_initialize, 0 );
2194
+ rb_define_method( cResolver, "add_type", syck_resolver_add_type, 2 );
2195
+ rb_define_method( cResolver, "use_types_at", syck_resolver_use_types_at, 1 );
2196
+ rb_define_method( cResolver, "detect_implicit", syck_resolver_detect_implicit, 1 );
2197
+ rb_define_method( cResolver, "transfer", syck_resolver_transfer, 2 );
2198
+ rb_define_method( cResolver, "node_import", syck_resolver_node_import, 1 );
2199
+ rb_define_method( cResolver, "tagurize", syck_resolver_tagurize, 1 );
2200
+
2201
+ rb_global_variable( &oDefaultResolver );
2202
+ oDefaultResolver = rb_funcall( cResolver, rb_intern( "new" ), 0 );
2203
+ rb_define_singleton_method( oDefaultResolver, "node_import", syck_defaultresolver_node_import, 1 );
2204
+ rb_define_singleton_method( oDefaultResolver, "detect_implicit", syck_defaultresolver_detect_implicit, 1 );
2205
+ rb_define_const( rb_syck, "DefaultResolver", oDefaultResolver );
2206
+ rb_global_variable( &oGenericResolver );
2207
+ oGenericResolver = rb_funcall( cResolver, rb_intern( "new" ), 0 );
2208
+ rb_define_singleton_method( oGenericResolver, "node_import", syck_genericresolver_node_import, 1 );
2209
+ rb_define_const( rb_syck, "GenericResolver", oGenericResolver );
2210
+
2211
+ /*
2212
+ * Define YAML::Syck::Parser class
2213
+ */
2214
+ cParser = rb_define_class_under( rb_syck, "Parser", rb_cObject );
2215
+ rb_define_attr( cParser, "options", 1, 1 );
2216
+ rb_define_attr( cParser, "resolver", 1, 1 );
2217
+ rb_define_attr( cParser, "input", 1, 1 );
2218
+ rb_define_alloc_func( cParser, syck_parser_s_alloc );
2219
+ rb_define_method(cParser, "initialize", syck_parser_initialize, -1 );
2220
+ rb_define_method(cParser, "bufsize=", syck_parser_bufsize_set, 1 );
2221
+ rb_define_method(cParser, "bufsize", syck_parser_bufsize_get, 0 );
2222
+ rb_define_method(cParser, "load", syck_parser_load, -1);
2223
+ rb_define_method(cParser, "load_documents", syck_parser_load_documents, -1);
2224
+ rb_define_method(cParser, "set_resolver", syck_parser_set_resolver, 1);
2225
+
2226
+ /*
2227
+ * Define YAML::Syck::Node class
2228
+ */
2229
+ cNode = rb_define_class_under( rb_syck, "Node", rb_cObject );
2230
+ rb_undef( cNode, rb_intern("initialize_copy") );
2231
+ rb_define_attr( cNode, "emitter", 1, 1 );
2232
+ rb_define_attr( cNode, "resolver", 1, 1 );
2233
+ rb_define_attr( cNode, "kind", 1, 0 );
2234
+ rb_define_attr( cNode, "type_id", 1, 0 );
2235
+ rb_define_attr( cNode, "value", 1, 0 );
2236
+ rb_define_method( cNode, "type_id=", syck_node_type_id_set, 1 );
2237
+ rb_define_method( cNode, "transform", syck_node_transform, 0);
2238
+
2239
+ /*
2240
+ * Define YAML::Syck::Scalar, YAML::Syck::Seq, YAML::Syck::Map --
2241
+ * all are the publicly usable variants of YAML::Syck::Node
2242
+ */
2243
+ cScalar = rb_define_class_under( rb_syck, "Scalar", cNode );
2244
+ rb_define_alloc_func( cScalar, syck_scalar_alloc );
2245
+ rb_define_method( cScalar, "initialize", syck_scalar_initialize, 3 );
2246
+ rb_define_method( cScalar, "value=", syck_scalar_value_set, 1 );
2247
+ rb_define_method( cScalar, "style=", syck_scalar_style_set, 1 );
2248
+ cSeq = rb_define_class_under( rb_syck, "Seq", cNode );
2249
+ rb_define_alloc_func( cSeq, syck_seq_alloc );
2250
+ rb_define_method( cSeq, "initialize", syck_seq_initialize, 3 );
2251
+ rb_define_method( cSeq, "value=", syck_seq_value_set, 1 );
2252
+ rb_define_method( cSeq, "add", syck_seq_add_m, 1 );
2253
+ rb_define_method( cSeq, "style=", syck_seq_style_set, 1 );
2254
+ cMap = rb_define_class_under( rb_syck, "Map", cNode );
2255
+ rb_define_alloc_func( cMap, syck_map_alloc );
2256
+ rb_define_method( cMap, "initialize", syck_map_initialize, 3 );
2257
+ rb_define_method( cMap, "value=", syck_map_value_set, 1 );
2258
+ rb_define_method( cMap, "add", syck_map_add_m, 2 );
2259
+ rb_define_method( cMap, "style=", syck_map_style_set, 1 );
2260
+
2261
+ /*
2262
+ * Define YAML::PrivateType class
2263
+ */
2264
+ cPrivateType = rb_define_class_under( rb_syck, "PrivateType", rb_cObject );
2265
+ rb_define_attr( cPrivateType, "type_id", 1, 1 );
2266
+ rb_define_attr( cPrivateType, "value", 1, 1 );
2267
+ rb_define_method( cPrivateType, "initialize", syck_privatetype_initialize, 2);
2268
+
2269
+ /*
2270
+ * Define YAML::DomainType class
2271
+ */
2272
+ cDomainType = rb_define_class_under( rb_syck, "DomainType", rb_cObject );
2273
+ rb_define_attr( cDomainType, "domain", 1, 1 );
2274
+ rb_define_attr( cDomainType, "type_id", 1, 1 );
2275
+ rb_define_attr( cDomainType, "value", 1, 1 );
2276
+ rb_define_method( cDomainType, "initialize", syck_domaintype_initialize, 3);
2277
+
2278
+ /*
2279
+ * Define YAML::Object class
2280
+ */
2281
+ cYObject = rb_define_class_under( rb_syck, "Object", rb_cObject );
2282
+ rb_define_attr( cYObject, "class", 1, 1 );
2283
+ rb_define_attr( cYObject, "ivars", 1, 1 );
2284
+ rb_define_method( cYObject, "initialize", syck_yobject_initialize, 2);
2285
+ rb_define_method( cYObject, "yaml_initialize", syck_yobject_initialize, 2);
2286
+
2287
+ /*
2288
+ * Define YAML::Syck::BadAlias class
2289
+ */
2290
+ cBadAlias = rb_define_class_under( rb_syck, "BadAlias", rb_cObject );
2291
+ rb_define_attr( cBadAlias, "name", 1, 1 );
2292
+ rb_define_method( cBadAlias, "initialize", syck_badalias_initialize, 1);
2293
+ rb_define_method( cBadAlias, "<=>", syck_badalias_cmp, 1);
2294
+ rb_include_module( cBadAlias, rb_const_get( rb_cObject, rb_intern("Comparable") ) );
2295
+
2296
+ /*
2297
+ * Define YAML::Syck::MergeKey class
2298
+ */
2299
+ cMergeKey = rb_define_class_under( rb_syck, "MergeKey", rb_cObject );
2300
+
2301
+ /*
2302
+ * Define YAML::Syck::DefaultKey class
2303
+ */
2304
+ cDefaultKey = rb_define_class_under( rb_syck, "DefaultKey", rb_cObject );
2305
+
2306
+ /*
2307
+ * Define YAML::Syck::Out classes
2308
+ */
2309
+ cOut = rb_define_class_under( rb_syck, "Out", rb_cObject );
2310
+ rb_define_attr( cOut, "emitter", 1, 1 );
2311
+ rb_define_method( cOut, "initialize", syck_out_initialize, 1 );
2312
+ rb_define_method( cOut, "map", syck_out_map, -1 );
2313
+ rb_define_method( cOut, "seq", syck_out_seq, -1 );
2314
+ rb_define_method( cOut, "scalar", syck_out_scalar, -1 );
2315
+
2316
+ /*
2317
+ * Define YAML::Syck::Emitter class
2318
+ */
2319
+ cEmitter = rb_define_class_under( rb_syck, "Emitter", rb_cObject );
2320
+ rb_define_attr( cEmitter, "level", 1, 1 );
2321
+ rb_define_alloc_func( cEmitter, syck_emitter_s_alloc );
2322
+ rb_define_method( cEmitter, "initialize", syck_emitter_reset, -1 );
2323
+ rb_define_method( cEmitter, "reset", syck_emitter_reset, -1 );
2324
+ rb_define_method( cEmitter, "emit", syck_emitter_emit, -1 );
2325
+ rb_define_method( cEmitter, "set_resolver", syck_emitter_set_resolver, 1);
2326
+ rb_define_method( cEmitter, "node_export", syck_emitter_node_export, 1);
2327
+ }
2328
+