rubysl-yaml 2.0.0 → 2.0.2

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