rubysl-yaml 2.0.0 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+