syck 1.0.0

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