00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "ruby/ruby.h"
00011 #include "ruby/encoding.h"
00012 #include "syck.h"
00013 #include <sys/types.h>
00014 #include <time.h>
00015
00016 typedef struct RVALUE {
00017 union {
00018 #if 0
00019 struct {
00020 unsigned long flags;
00021 struct RVALUE *next;
00022 } free;
00023 #endif
00024 struct RBasic basic;
00025 struct RObject object;
00026 struct RClass klass;
00027
00028
00029 struct RArray array;
00030
00031 struct RHash hash;
00032
00033 struct RStruct rstruct;
00034
00035
00036 } as;
00037 } RVALUE;
00038
00039 typedef struct {
00040 long hash;
00041 char *buffer;
00042 long length;
00043 long remaining;
00044 int printed;
00045 } bytestring_t;
00046
00047 #define RUBY_DOMAIN "ruby.yaml.org,2002"
00048
00049
00050
00051
00052 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;
00053 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;
00054 static VALUE sym_model, sym_generic, sym_input, sym_bytecode;
00055 static VALUE sym_scalar, sym_seq, sym_map;
00056 static VALUE sym_1quote, sym_2quote, sym_fold, sym_literal, sym_plain, sym_inline;
00057 static VALUE cDate, cNode, cMap, cSeq, cScalar, cOut, cParser, cResolver, cPrivateType, cDomainType, cYObject, cBadAlias, cDefaultKey, cMergeKey, cEmitter, cDateTime;
00058 static VALUE oDefaultResolver, oGenericResolver;
00059
00060
00061
00062
00063 static double S_zero(void) { return 0.0; }
00064 static double S_one(void) { return 1.0; }
00065 static double S_inf(void) { return S_one() / S_zero(); }
00066 static double S_nan(void) { return S_zero() / S_zero(); }
00067
00068 static VALUE syck_node_transform( VALUE );
00069
00070
00071
00072
00073 SYMID rb_syck_load_handler _((SyckParser *, SyckNode *));
00074 void rb_syck_err_handler _((SyckParser *, const char *));
00075 SyckNode * rb_syck_bad_anchor_handler _((SyckParser *, char *));
00076 void rb_syck_output_handler _((SyckEmitter *, char *, long));
00077 void rb_syck_emitter_handler _((SyckEmitter *, st_data_t));
00078 int syck_parser_assign_io _((SyckParser *, VALUE *));
00079 VALUE syck_scalar_alloc _((VALUE class));
00080 VALUE syck_seq_alloc _((VALUE class));
00081 VALUE syck_map_alloc _((VALUE class));
00082
00083 struct parser_xtra {
00084 VALUE data;
00085 VALUE proc;
00086 VALUE resolver;
00087 int taint;
00088 };
00089
00090 struct emitter_xtra {
00091 VALUE oid;
00092 VALUE data;
00093 VALUE port;
00094 };
00095
00096
00097
00098
00099 VALUE
00100 rb_syck_compile(VALUE self, VALUE port)
00101 {
00102 SYMID oid;
00103 int taint;
00104 char *ret;
00105 VALUE bc;
00106 bytestring_t *sav = NULL;
00107 void *data = NULL;
00108
00109 SyckParser *parser = syck_new_parser();
00110 taint = syck_parser_assign_io(parser, &port);
00111 syck_parser_handler( parser, syck_yaml2byte_handler );
00112 syck_parser_error_handler( parser, NULL );
00113 syck_parser_implicit_typing( parser, 0 );
00114 syck_parser_taguri_expansion( parser, 0 );
00115 oid = syck_parse( parser );
00116 if (!syck_lookup_sym( parser, oid, &data )) {
00117 rb_raise(rb_eSyntaxError, "root node <%p> not found", (void *)oid);
00118 }
00119 sav = data;
00120
00121 ret = S_ALLOCA_N( char, strlen( sav->buffer ) + 3 );
00122 ret[0] = '\0';
00123 strcat( ret, "D\n" );
00124 strcat( ret, sav->buffer );
00125
00126 syck_free_parser( parser );
00127
00128 bc = rb_str_new2( ret );
00129 if ( taint ) OBJ_TAINT( bc );
00130 return bc;
00131 }
00132
00133
00134
00135
00136 long
00137 rb_syck_io_str_read( char *buf, SyckIoStr *str, long max_size, long skip )
00138 {
00139 long len = 0;
00140
00141 ASSERT( str != NULL );
00142 max_size -= skip;
00143
00144 if ( max_size <= 0 ) max_size = 0;
00145 else
00146 {
00147
00148
00149
00150 VALUE src = (VALUE)str->ptr;
00151 VALUE n = LONG2NUM(max_size);
00152 VALUE str2 = rb_funcall2(src, s_read, 1, &n);
00153 if (!NIL_P(str2))
00154 {
00155 StringValue(str2);
00156 len = RSTRING_LEN(str2);
00157 memcpy( buf + skip, RSTRING_PTR(str2), len );
00158 }
00159 }
00160 len += skip;
00161 buf[len] = '\0';
00162 return len;
00163 }
00164
00165
00166
00167
00168
00169 int
00170 syck_parser_assign_io(SyckParser *parser, VALUE *pport)
00171 {
00172 int taint = Qtrue;
00173 VALUE tmp, port = *pport;
00174 if (!NIL_P(tmp = rb_check_string_type(port))) {
00175 taint = OBJ_TAINTED(port);
00176 port = tmp;
00177 syck_parser_str( parser, RSTRING_PTR(port), RSTRING_LEN(port), NULL );
00178 }
00179 else if (rb_respond_to(port, s_read)) {
00180 if (rb_respond_to(port, s_binmode)) {
00181 rb_funcall2(port, s_binmode, 0, 0);
00182 }
00183 syck_parser_str( parser, (char *)port, 0, rb_syck_io_str_read );
00184 }
00185 else {
00186 rb_raise(rb_eTypeError, "instance of IO needed");
00187 }
00188 *pport = port;
00189 return taint;
00190 }
00191
00192
00193
00194
00195 VALUE
00196 syck_get_hash_aref(VALUE hsh, VALUE key)
00197 {
00198 VALUE val = rb_hash_aref( hsh, key );
00199 if ( NIL_P( val ) )
00200 {
00201 val = rb_hash_new();
00202 rb_hash_aset(hsh, key, val);
00203 }
00204 return val;
00205 }
00206
00207
00208
00209
00210 struct mktime_arg {
00211 const char *str;
00212 long len;
00213 };
00214
00215 VALUE
00216 mktime_do(VALUE varg)
00217 {
00218 struct mktime_arg *arg = (struct mktime_arg *)varg;
00219 VALUE time;
00220 const char *str = arg->str;
00221 long len = arg->len;
00222 const char *ptr = str;
00223 VALUE year = INT2FIX(0);
00224 VALUE mon = INT2FIX(0);
00225 VALUE day = INT2FIX(0);
00226 VALUE hour = INT2FIX(0);
00227 VALUE min = INT2FIX(0);
00228 VALUE sec = INT2FIX(0);
00229 long usec;
00230
00231
00232 if ( ptr[0] != '\0' && len > 0 ) {
00233 year = INT2FIX(strtol(ptr, NULL, 10));
00234 }
00235
00236
00237 ptr += 4;
00238 if ( ptr[0] != '\0' && len > ptr - str ) {
00239 while ( !ISDIGIT( *ptr ) ) ptr++;
00240 mon = INT2FIX(strtol(ptr, NULL, 10));
00241 }
00242
00243
00244 ptr += 2;
00245 if ( ptr[0] != '\0' && len > ptr - str ) {
00246 while ( !ISDIGIT( *ptr ) ) ptr++;
00247 day = INT2FIX(strtol(ptr, NULL, 10));
00248 }
00249
00250
00251 ptr += 2;
00252 if ( ptr[0] != '\0' && len > ptr - str ) {
00253 while ( !ISDIGIT( *ptr ) ) ptr++;
00254 hour = INT2FIX(strtol(ptr, NULL, 10));
00255 }
00256
00257
00258 ptr += 2;
00259 if ( ptr[0] != '\0' && len > ptr - str ) {
00260 while ( !ISDIGIT( *ptr ) ) ptr++;
00261 min = INT2FIX(strtol(ptr, NULL, 10));
00262 }
00263
00264
00265 ptr += 2;
00266 if ( ptr[0] != '\0' && len > ptr - str ) {
00267 while ( !ISDIGIT( *ptr ) ) ptr++;
00268 sec = INT2FIX(strtol(ptr, NULL, 10));
00269 }
00270
00271
00272 ptr += 2;
00273 if ( len > ptr - str && *ptr == '.' )
00274 {
00275 char padded[] = "000000";
00276 const int padding = (int)(sizeof(padded) - 1);
00277 const char *end = ptr + 1;
00278 const char *begin = end;
00279 ptrdiff_t length;
00280 while ( isdigit( *end ) ) end++;
00281 if ((length = (end - begin)) > padding) length = padding;
00282 MEMCPY(padded, begin, char, length);
00283 usec = strtol(padded, NULL, 10);
00284 }
00285 else
00286 {
00287 usec = 0;
00288 }
00289
00290
00291 while ( len > ptr - str && *ptr != 'Z' && *ptr != '+' && *ptr != '-' && *ptr != '\0' ) ptr++;
00292 if ( len > ptr - str && ( *ptr == '-' || *ptr == '+' ) )
00293 {
00294 time_t tz_offset = strtol(ptr, NULL, 10) * 3600;
00295 VALUE tmp;
00296
00297 while ( *ptr != ':' && *ptr != '\0' ) ptr++;
00298 if ( *ptr == ':' )
00299 {
00300 ptr += 1;
00301 if ( tz_offset < 0 )
00302 {
00303 tz_offset -= strtol(ptr, NULL, 10) * 60;
00304 }
00305 else
00306 {
00307 tz_offset += strtol(ptr, NULL, 10) * 60;
00308 }
00309 }
00310
00311
00312 time = rb_funcall(rb_cTime, s_utc, 6, year, mon, day, hour, min, sec);
00313 tmp = rb_funcall(time, s_to_i, 0);
00314 tmp = rb_funcall(tmp, '-', 1, LONG2FIX(tz_offset));
00315 return rb_funcall(rb_cTime, s_at, 2, tmp, LONG2NUM(usec));
00316 }
00317 else
00318 {
00319
00320 return rb_funcall(rb_cTime, s_utc, 7, year, mon, day, hour, min, sec, LONG2NUM(usec));
00321 }
00322 }
00323
00324 VALUE
00325 mktime_r(VALUE varg)
00326 {
00327 struct mktime_arg *arg = (struct mktime_arg *)varg;
00328
00329 if (!cDateTime) {
00330
00331
00332
00333 rb_require("date");
00334 cDateTime = rb_const_get(rb_cObject, rb_intern("DateTime"));
00335 }
00336 return rb_funcall(cDateTime, s_parse, 1, rb_str_new(arg->str, arg->len));
00337 }
00338
00339 VALUE
00340 rb_syck_mktime(const char *str, long len)
00341 {
00342 struct mktime_arg a;
00343
00344 a.str = str;
00345 a.len = len;
00346 return rb_rescue2(mktime_do, (VALUE)&a, mktime_r, (VALUE)&a, rb_eArgError, NULL);
00347 }
00348
00349
00350
00351
00352
00353 VALUE
00354 syck_merge_i(VALUE entry, VALUE hsh )
00355 {
00356 VALUE tmp;
00357 if ( !NIL_P(tmp = rb_check_convert_type(entry, T_HASH, "Hash", "to_hash")) )
00358 {
00359 entry = tmp;
00360 rb_funcall( hsh, s_update, 1, entry );
00361 }
00362 return Qnil;
00363 }
00364
00365
00366
00367
00368 int
00369 yaml_org_handler( SyckNode *n, VALUE *ref )
00370 {
00371 char *type_id = n->type_id;
00372 int transferred = 0;
00373 long i = 0;
00374 VALUE obj = Qnil;
00375
00376 if ( type_id != NULL && strncmp( type_id, "tag:yaml.org,2002:", 18 ) == 0 )
00377 {
00378 type_id += 18;
00379 }
00380
00381 switch (n->kind)
00382 {
00383 case syck_str_kind:
00384 transferred = 1;
00385 if ( type_id == NULL )
00386 {
00387 obj = rb_str_new( n->data.str->ptr, n->data.str->len );
00388 }
00389 else if ( strcmp( type_id, "null" ) == 0 )
00390 {
00391 obj = Qnil;
00392 }
00393 else if ( strcmp( type_id, "binary" ) == 0 )
00394 {
00395 VALUE arr;
00396 obj = rb_str_new( n->data.str->ptr, n->data.str->len );
00397 rb_funcall( obj, s_tr_bang, 2, rb_str_new2( "\n\t " ), rb_str_new2( "" ) );
00398 arr = rb_funcall( obj, s_unpack, 1, rb_str_new2( "m" ) );
00399 obj = rb_ary_shift( arr );
00400 }
00401 else if ( strcmp( type_id, "bool#yes" ) == 0 )
00402 {
00403 obj = Qtrue;
00404 }
00405 else if ( strcmp( type_id, "bool#no" ) == 0 )
00406 {
00407 obj = Qfalse;
00408 }
00409 else if ( strcmp( type_id, "int#hex" ) == 0 )
00410 {
00411 syck_str_blow_away_commas( n );
00412 obj = rb_cstr2inum( n->data.str->ptr, 16 );
00413 }
00414 else if ( strcmp( type_id, "int#oct" ) == 0 )
00415 {
00416 syck_str_blow_away_commas( n );
00417 obj = rb_cstr2inum( n->data.str->ptr, 8 );
00418 }
00419 else if ( strcmp( type_id, "int#base60" ) == 0 )
00420 {
00421 char *ptr, *end;
00422 long sixty = 1;
00423 long total = 0;
00424 syck_str_blow_away_commas( n );
00425 ptr = n->data.str->ptr;
00426 end = n->data.str->ptr + n->data.str->len;
00427 while ( end > ptr )
00428 {
00429 long bnum = 0;
00430 char *colon = end - 1;
00431 while ( colon >= ptr && *colon != ':' )
00432 {
00433 colon--;
00434 }
00435 if ( colon >= ptr && *colon == ':' ) *colon = '\0';
00436
00437 bnum = strtol( colon + 1, NULL, 10 );
00438 total += bnum * sixty;
00439 sixty *= 60;
00440 end = colon;
00441 }
00442 obj = INT2FIX(total);
00443 }
00444 else if ( strncmp( type_id, "int", 3 ) == 0 )
00445 {
00446 syck_str_blow_away_commas( n );
00447 obj = rb_cstr2inum( n->data.str->ptr, 10 );
00448 }
00449 else if ( strcmp( type_id, "float#base60" ) == 0 )
00450 {
00451 char *ptr, *end;
00452 long sixty = 1;
00453 double total = 0.0;
00454 syck_str_blow_away_commas( n );
00455 ptr = n->data.str->ptr;
00456 end = n->data.str->ptr + n->data.str->len;
00457 while ( end > ptr )
00458 {
00459 double bnum = 0;
00460 char *colon = end - 1;
00461 while ( colon >= ptr && *colon != ':' )
00462 {
00463 colon--;
00464 }
00465 if ( colon >= ptr && *colon == ':' ) *colon = '\0';
00466
00467 bnum = strtod( colon + 1, NULL );
00468 total += bnum * sixty;
00469 sixty *= 60;
00470 end = colon;
00471 }
00472 obj = rb_float_new( total );
00473 }
00474 else if ( strcmp( type_id, "float#nan" ) == 0 )
00475 {
00476 obj = rb_float_new( S_nan() );
00477 }
00478 else if ( strcmp( type_id, "float#inf" ) == 0 )
00479 {
00480 obj = rb_float_new( S_inf() );
00481 }
00482 else if ( strcmp( type_id, "float#neginf" ) == 0 )
00483 {
00484 obj = rb_float_new( -S_inf() );
00485 }
00486 else if ( strncmp( type_id, "float", 5 ) == 0 )
00487 {
00488 double f;
00489 syck_str_blow_away_commas( n );
00490 f = strtod( n->data.str->ptr, NULL );
00491 obj = rb_float_new( f );
00492 }
00493 else if ( strcmp( type_id, "timestamp#iso8601" ) == 0 )
00494 {
00495 obj = rb_syck_mktime( n->data.str->ptr, n->data.str->len );
00496 }
00497 else if ( strcmp( type_id, "timestamp#spaced" ) == 0 )
00498 {
00499 obj = rb_syck_mktime( n->data.str->ptr, n->data.str->len );
00500 }
00501 else if ( strcmp( type_id, "timestamp#ymd" ) == 0 )
00502 {
00503 char *ptr = n->data.str->ptr;
00504 VALUE year, mon, day;
00505
00506
00507 ptr[4] = '\0';
00508 year = INT2FIX(strtol(ptr, NULL, 10));
00509
00510
00511 ptr += 4;
00512 while ( !ISDIGIT( *ptr ) ) ptr++;
00513 mon = INT2FIX(strtol(ptr, NULL, 10));
00514
00515
00516 ptr += 2;
00517 while ( !ISDIGIT( *ptr ) ) ptr++;
00518 day = INT2FIX(strtol(ptr, NULL, 10));
00519
00520 if ( !cDate ) {
00521
00522
00523
00524 rb_require( "date" );
00525 cDate = rb_const_get( rb_cObject, rb_intern("Date") );
00526 }
00527
00528 obj = rb_funcall( cDate, s_new, 3, year, mon, day );
00529 }
00530 else if ( strncmp( type_id, "timestamp", 9 ) == 0 )
00531 {
00532 obj = rb_syck_mktime( n->data.str->ptr, n->data.str->len );
00533 }
00534 else if ( strncmp( type_id, "merge", 5 ) == 0 )
00535 {
00536 obj = rb_funcall( cMergeKey, s_new, 0 );
00537 }
00538 else if ( strncmp( type_id, "default", 7 ) == 0 )
00539 {
00540 obj = rb_funcall( cDefaultKey, s_new, 0 );
00541 }
00542 else if ( n->data.str->style == scalar_plain &&
00543 n->data.str->len > 1 &&
00544 strncmp( n->data.str->ptr, ":", 1 ) == 0 )
00545 {
00546 obj = rb_funcall( oDefaultResolver, s_transfer, 2,
00547 rb_str_new2( "tag:ruby.yaml.org,2002:sym" ),
00548 rb_str_new( n->data.str->ptr + 1, n->data.str->len - 1 ) );
00549 }
00550 else if ( strcmp( type_id, "str" ) == 0 )
00551 {
00552 obj = rb_str_new( n->data.str->ptr, n->data.str->len );
00553 rb_enc_associate(obj, rb_utf8_encoding());
00554 }
00555 else
00556 {
00557 transferred = 0;
00558 obj = rb_str_new( n->data.str->ptr, n->data.str->len );
00559 }
00560 break;
00561
00562 case syck_seq_kind:
00563 if ( type_id == NULL || strcmp( type_id, "seq" ) == 0 )
00564 {
00565 transferred = 1;
00566 }
00567 obj = rb_ary_new2( n->data.list->idx );
00568 for ( i = 0; i < n->data.list->idx; i++ )
00569 {
00570 rb_ary_store( obj, i, syck_seq_read( n, i ) );
00571 }
00572 break;
00573
00574 case syck_map_kind:
00575 if ( type_id == NULL || strcmp( type_id, "map" ) == 0 )
00576 {
00577 transferred = 1;
00578 }
00579 obj = rb_hash_new();
00580 for ( i = 0; i < n->data.pairs->idx; i++ )
00581 {
00582 VALUE k = syck_map_read( n, map_key, i );
00583 VALUE v = syck_map_read( n, map_value, i );
00584 int skip_aset = 0;
00585
00586
00587
00588
00589 if ( rb_obj_is_kind_of( k, cMergeKey ) )
00590 {
00591 VALUE tmp;
00592 if ( !NIL_P(tmp = rb_check_convert_type(v, T_HASH, "Hash", "to_hash")) )
00593 {
00594 VALUE dup = rb_funcall( tmp, s_dup, 0 );
00595 rb_funcall( dup, s_update, 1, obj );
00596 obj = dup;
00597 skip_aset = 1;
00598 }
00599 else if ( !NIL_P(tmp = rb_check_array_type(v)) )
00600 {
00601 VALUE end = rb_ary_pop( tmp );
00602 VALUE tmph = rb_check_convert_type(end, T_HASH, "Hash", "to_hash");
00603 if ( !NIL_P(tmph) )
00604 {
00605 VALUE dup = rb_funcall( tmph, s_dup, 0 );
00606 tmp = rb_ary_reverse( tmp );
00607 rb_ary_push( tmp, obj );
00608 rb_block_call( tmp, s_each, 0, 0, syck_merge_i, dup );
00609 obj = dup;
00610 skip_aset = 1;
00611 }
00612 }
00613 }
00614 else if ( rb_obj_is_kind_of( k, cDefaultKey ) )
00615 {
00616 rb_funcall( obj, s_default_set, 1, v );
00617 skip_aset = 1;
00618 }
00619
00620 if ( ! skip_aset )
00621 {
00622 rb_hash_aset( obj, k, v );
00623 }
00624 }
00625 break;
00626 }
00627
00628 *ref = obj;
00629 return transferred;
00630 }
00631
00632 static void syck_node_mark( SyckNode *n );
00633
00634
00635
00636
00637
00638 SYMID
00639 rb_syck_load_handler(SyckParser *p, SyckNode *n)
00640 {
00641 VALUE obj = Qnil;
00642 struct parser_xtra *bonus = (struct parser_xtra *)p->bonus;
00643 VALUE resolver = bonus->resolver;
00644 if ( NIL_P( resolver ) )
00645 {
00646 resolver = oDefaultResolver;
00647 }
00648
00649
00650
00651
00652 obj = rb_funcall( resolver, s_node_import, 1, Data_Wrap_Struct( cNode, NULL, NULL, n ) );
00653
00654
00655
00656
00657 if (n->id > 0 && !NIL_P(obj))
00658 {
00659 MEMCPY((void *)n->id, (void *)obj, RVALUE, 1);
00660 MEMZERO((void *)obj, RVALUE, 1);
00661 obj = n->id;
00662 }
00663
00664 if ( bonus->taint) OBJ_TAINT( obj );
00665 if ( bonus->proc != 0 ) rb_funcall(bonus->proc, s_call, 1, obj);
00666
00667 rb_hash_aset(bonus->data, INT2FIX(RHASH_SIZE(bonus->data)), obj);
00668 return obj;
00669 }
00670
00671
00672
00673
00674 void
00675 rb_syck_err_handler(SyckParser *p, const char *msg)
00676 {
00677 char *endl = p->cursor;
00678
00679 while ( *endl != '\0' && *endl != '\n' )
00680 endl++;
00681
00682 endl[0] = '\0';
00683 rb_raise(rb_eArgError, "%s on line %d, col %"PRIdPTRDIFF": `%s'",
00684 msg,
00685 p->linect,
00686 p->cursor - p->lineptr,
00687 p->lineptr);
00688 }
00689
00690
00691
00692
00693 SyckNode *
00694 rb_syck_bad_anchor_handler(SyckParser *p, char *a)
00695 {
00696 VALUE anchor_name = rb_str_new2( a );
00697 SyckNode *badanc = syck_new_map( rb_str_new2( "name" ), anchor_name );
00698 badanc->type_id = syck_strndup( "tag:ruby.yaml.org,2002:object:YAML::Syck::BadAlias", 53 );
00699 return badanc;
00700 }
00701
00702
00703
00704
00705 void
00706 syck_set_model(VALUE p, VALUE input, VALUE model)
00707 {
00708 SyckParser *parser;
00709 Data_Get_Struct(p, SyckParser, parser);
00710 syck_parser_handler( parser, rb_syck_load_handler );
00711
00712 if ( model == sym_generic )
00713 {
00714 rb_funcall( p, s_set_resolver, 1, oGenericResolver );
00715 }
00716 syck_parser_implicit_typing( parser, 1 );
00717 syck_parser_taguri_expansion( parser, 1 );
00718
00719 if ( NIL_P( input ) )
00720 {
00721 input = rb_ivar_get( p, s_input );
00722 }
00723 if ( input == sym_bytecode )
00724 {
00725 syck_parser_set_input_type( parser, syck_bytecode_utf8 );
00726 }
00727 else
00728 {
00729 syck_parser_set_input_type( parser, syck_yaml_utf8 );
00730 }
00731 syck_parser_error_handler( parser, rb_syck_err_handler );
00732 syck_parser_bad_anchor_handler( parser, rb_syck_bad_anchor_handler );
00733 }
00734
00735 static int
00736 syck_st_mark_nodes( char *key, SyckNode *n, char *arg )
00737 {
00738 if ( n != (void *)1 ) syck_node_mark( n );
00739 return ST_CONTINUE;
00740 }
00741
00742
00743
00744
00745 static void
00746 syck_mark_parser(SyckParser *parser)
00747 {
00748 struct parser_xtra *bonus = (struct parser_xtra *)parser->bonus;
00749 rb_gc_mark_maybe(parser->root);
00750 rb_gc_mark_maybe(parser->root_on_error);
00751 rb_gc_mark( bonus->data );
00752 rb_gc_mark( bonus->proc );
00753 rb_gc_mark( bonus->resolver );
00754
00755 if ( parser->anchors != NULL )
00756 {
00757 st_foreach( parser->anchors, syck_st_mark_nodes, 0 );
00758 }
00759 if ( parser->bad_anchors != NULL )
00760 {
00761 st_foreach( parser->bad_anchors, syck_st_mark_nodes, 0 );
00762 }
00763 }
00764
00765
00766
00767
00768 void
00769 rb_syck_free_parser(SyckParser *p)
00770 {
00771 S_FREE( p->bonus );
00772 syck_free_parser(p);
00773 }
00774
00775
00776
00777
00778 VALUE syck_parser_s_alloc _((VALUE));
00779 VALUE
00780 syck_parser_s_alloc(VALUE class)
00781 {
00782 VALUE pobj;
00783 SyckParser *parser = syck_new_parser();
00784
00785 parser->bonus = S_ALLOC( struct parser_xtra );
00786 S_MEMZERO( parser->bonus, struct parser_xtra, 1 );
00787
00788 pobj = Data_Wrap_Struct( class, syck_mark_parser, rb_syck_free_parser, parser );
00789
00790 syck_parser_set_root_on_error( parser, Qnil );
00791
00792 return pobj;
00793 }
00794
00795
00796
00797
00798 static VALUE
00799 syck_parser_initialize(int argc, VALUE *argv, VALUE self)
00800 {
00801 VALUE options;
00802 if (rb_scan_args(argc, argv, "01", &options) == 0)
00803 {
00804 options = rb_hash_new();
00805 }
00806 else
00807 {
00808 Check_Type(options, T_HASH);
00809 }
00810 rb_ivar_set(self, s_options, options);
00811 rb_ivar_set(self, s_input, Qnil);
00812 return self;
00813 }
00814
00815
00816
00817
00818 static VALUE
00819 syck_parser_bufsize_set(VALUE self, VALUE size)
00820 {
00821 SyckParser *parser;
00822
00823 if ( rb_respond_to( size, s_to_i ) ) {
00824 int n = NUM2INT(rb_funcall(size, s_to_i, 0));
00825 Data_Get_Struct(self, SyckParser, parser);
00826 parser->bufsize = n;
00827 }
00828 return self;
00829 }
00830
00831
00832
00833
00834 static VALUE
00835 syck_parser_bufsize_get(VALUE self)
00836 {
00837 SyckParser *parser;
00838
00839 Data_Get_Struct(self, SyckParser, parser);
00840 return INT2FIX( parser->bufsize );
00841 }
00842
00843
00844
00845
00846 VALUE
00847 syck_parser_load(int argc, VALUE *argv, VALUE self)
00848 {
00849 VALUE port, proc, model, input;
00850 SyckParser *parser;
00851 struct parser_xtra *bonus;
00852
00853 rb_scan_args(argc, argv, "11", &port, &proc);
00854
00855 input = rb_hash_aref( rb_attr_get( self, s_options ), sym_input );
00856 model = rb_hash_aref( rb_attr_get( self, s_options ), sym_model );
00857 Data_Get_Struct(self, SyckParser, parser);
00858 syck_set_model( self, input, model );
00859
00860 bonus = (struct parser_xtra *)parser->bonus;
00861 bonus->taint = syck_parser_assign_io(parser, &port);
00862 bonus->data = rb_hash_new();
00863 bonus->resolver = rb_attr_get( self, s_resolver );
00864 if ( NIL_P( proc ) ) bonus->proc = 0;
00865 else bonus->proc = proc;
00866
00867 return syck_parse( parser );
00868 }
00869
00870
00871
00872
00873 VALUE
00874 syck_parser_load_documents(int argc, VALUE *argv, VALUE self)
00875 {
00876 VALUE port, proc, v, input, model;
00877 SyckParser *parser;
00878 struct parser_xtra *bonus;
00879
00880 rb_scan_args(argc, argv, "1&", &port, &proc);
00881
00882 input = rb_hash_aref( rb_attr_get( self, s_options ), sym_input );
00883 model = rb_hash_aref( rb_attr_get( self, s_options ), sym_model );
00884 Data_Get_Struct(self, SyckParser, parser);
00885 syck_set_model( self, input, model );
00886
00887 bonus = (struct parser_xtra *)parser->bonus;
00888 bonus->taint = syck_parser_assign_io(parser, &port);
00889 bonus->resolver = rb_attr_get( self, s_resolver );
00890 bonus->proc = 0;
00891
00892 while ( 1 )
00893 {
00894
00895 bonus->data = rb_hash_new();
00896
00897
00898 v = syck_parse( parser );
00899 if ( parser->eof == 1 )
00900 {
00901 break;
00902 }
00903
00904
00905 rb_funcall( proc, s_call, 1, v );
00906 }
00907
00908 return Qnil;
00909 }
00910
00911
00912
00913
00914 VALUE
00915 syck_parser_set_resolver(VALUE self, VALUE resolver)
00916 {
00917 rb_ivar_set( self, s_resolver, resolver );
00918 return self;
00919 }
00920
00921
00922
00923
00924 static VALUE
00925 syck_resolver_initialize(VALUE self)
00926 {
00927 rb_ivar_set(self, s_tags, rb_hash_new());
00928 return self;
00929 }
00930
00931
00932
00933
00934 VALUE
00935 syck_resolver_add_type(VALUE self, VALUE taguri, VALUE cls)
00936 {
00937 VALUE tags = rb_attr_get(self, s_tags);
00938 rb_hash_aset( tags, taguri, cls );
00939 return Qnil;
00940 }
00941
00942
00943
00944
00945 VALUE
00946 syck_resolver_use_types_at(VALUE self, VALUE hsh)
00947 {
00948 rb_ivar_set( self, s_tags, hsh );
00949 return Qnil;
00950 }
00951
00952
00953
00954
00955 VALUE
00956 syck_resolver_detect_implicit(VALUE self, VALUE val)
00957 {
00958 return rb_str_new2( "" );
00959 }
00960
00961
00962
00963
00964 VALUE
00965 syck_resolver_node_import(VALUE self, VALUE node)
00966 {
00967 SyckNode *n;
00968 VALUE obj = Qnil;
00969 int i = 0;
00970 Data_Get_Struct(node, SyckNode, n);
00971
00972 switch (n->kind)
00973 {
00974 case syck_str_kind:
00975 obj = rb_str_new( n->data.str->ptr, n->data.str->len );
00976 break;
00977
00978 case syck_seq_kind:
00979 obj = rb_ary_new2( n->data.list->idx );
00980 for ( i = 0; i < n->data.list->idx; i++ )
00981 {
00982 rb_ary_store( obj, i, syck_seq_read( n, i ) );
00983 }
00984 break;
00985
00986 case syck_map_kind:
00987 obj = rb_hash_new();
00988 for ( i = 0; i < n->data.pairs->idx; i++ )
00989 {
00990 VALUE k = syck_map_read( n, map_key, i );
00991 VALUE v = syck_map_read( n, map_value, i );
00992 int skip_aset = 0;
00993
00994
00995
00996
00997 if ( rb_obj_is_kind_of( k, cMergeKey ) )
00998 {
00999 if ( rb_obj_is_kind_of( v, rb_cHash ) )
01000 {
01001 VALUE dup = rb_funcall( v, s_dup, 0 );
01002 rb_funcall( dup, s_update, 1, obj );
01003 obj = dup;
01004 skip_aset = 1;
01005 }
01006 else if ( rb_obj_is_kind_of( v, rb_cArray ) )
01007 {
01008 VALUE end = rb_ary_pop( v );
01009 if ( rb_obj_is_kind_of( end, rb_cHash ) )
01010 {
01011 VALUE dup = rb_funcall( end, s_dup, 0 );
01012 v = rb_ary_reverse( v );
01013 rb_ary_push( v, obj );
01014 rb_block_call( v, s_each, 0, 0, syck_merge_i, dup );
01015 obj = dup;
01016 skip_aset = 1;
01017 }
01018 }
01019 }
01020 else if ( rb_obj_is_kind_of( k, cDefaultKey ) )
01021 {
01022 rb_funcall( obj, s_default_set, 1, v );
01023 skip_aset = 1;
01024 }
01025
01026 if ( ! skip_aset )
01027 {
01028 rb_hash_aset( obj, k, v );
01029 }
01030 }
01031 break;
01032 }
01033
01034 if ( n->type_id != NULL )
01035 {
01036 obj = rb_funcall( self, s_transfer, 2, rb_str_new2( n->type_id ), obj );
01037 }
01038 return obj;
01039 }
01040
01041
01042
01043
01044 VALUE
01045 syck_set_ivars(VALUE vars, VALUE obj)
01046 {
01047 VALUE ivname = rb_ary_entry( vars, 0 );
01048 char *ivn;
01049 StringValue( ivname );
01050 ivn = S_ALLOCA_N( char, RSTRING_LEN(ivname) + 2 );
01051 ivn[0] = '@';
01052 ivn[1] = '\0';
01053 strncat( ivn, RSTRING_PTR(ivname), RSTRING_LEN(ivname) );
01054 rb_iv_set( obj, ivn, rb_ary_entry( vars, 1 ) );
01055 return Qnil;
01056 }
01057
01058
01059
01060
01061 VALUE
01062 syck_const_find(VALUE const_name)
01063 {
01064 VALUE tclass = rb_cObject;
01065 VALUE tparts = rb_str_split( const_name, "::" );
01066 int i = 0;
01067 for ( i = 0; i < RARRAY_LEN(tparts); i++ ) {
01068 VALUE tpart = rb_to_id( rb_ary_entry( tparts, i ) );
01069 if ( !rb_const_defined( tclass, tpart ) ) return Qnil;
01070 tclass = rb_const_get( tclass, tpart );
01071 }
01072 return tclass;
01073 }
01074
01075
01076
01077
01078 VALUE
01079 syck_resolver_transfer(VALUE self, VALUE type, VALUE val)
01080 {
01081 if (NIL_P(type) || RSTRING_LEN(StringValue(type)) == 0)
01082 {
01083 type = rb_funcall( self, s_detect_implicit, 1, val );
01084 }
01085
01086 if ( ! (NIL_P(type) || RSTRING_LEN(StringValue(type)) == 0) )
01087 {
01088 VALUE str_xprivate = rb_str_new2( "x-private" );
01089 VALUE colon = rb_str_new2( ":" );
01090 VALUE tags = rb_attr_get(self, s_tags);
01091 VALUE target_class = rb_hash_aref( tags, type );
01092 VALUE subclass = target_class;
01093 VALUE obj = Qnil;
01094
01095
01096
01097
01098 if ( NIL_P( target_class ) )
01099 {
01100 VALUE subclass_parts = rb_ary_new();
01101 VALUE parts = rb_str_split( type, ":" );
01102
01103 while ( RARRAY_LEN(parts) > 1 )
01104 {
01105 VALUE partial;
01106 rb_ary_unshift( subclass_parts, rb_ary_pop( parts ) );
01107 partial = rb_ary_join( parts, colon );
01108 target_class = rb_hash_aref( tags, partial );
01109 if ( NIL_P( target_class ) )
01110 {
01111 rb_str_append( partial, colon );
01112 target_class = rb_hash_aref( tags, partial );
01113 }
01114
01115
01116
01117
01118 if ( ! NIL_P( target_class ) )
01119 {
01120 subclass = target_class;
01121 if ( RARRAY_LEN(subclass_parts) > 0 && rb_respond_to( target_class, s_tag_subclasses ) &&
01122 RTEST( rb_funcall( target_class, s_tag_subclasses, 0 ) ) )
01123 {
01124 VALUE subclass_v;
01125 subclass = rb_ary_join( subclass_parts, colon );
01126 subclass = rb_funcall( target_class, s_tag_read_class, 1, subclass );
01127 subclass_v = syck_const_find( subclass );
01128
01129 if ( subclass_v != Qnil )
01130 {
01131 subclass = subclass_v;
01132 }
01133 else if ( rb_cObject == target_class && subclass_v == Qnil )
01134 {
01135 target_class = cYObject;
01136 type = subclass;
01137 subclass = cYObject;
01138 }
01139 else
01140 {
01141 rb_raise( rb_eTypeError, "invalid subclass" );
01142 }
01143 }
01144 break;
01145 }
01146 }
01147 }
01148
01149
01150
01151
01152
01153 if ( rb_respond_to( target_class, s_call ) )
01154 {
01155 obj = rb_funcall( target_class, s_call, 2, type, val );
01156 }
01157 else
01158 {
01159 if ( rb_respond_to( target_class, s_yaml_new ) )
01160 {
01161 obj = rb_funcall( target_class, s_yaml_new, 3, subclass, type, val );
01162 }
01163 else if ( !NIL_P( target_class ) )
01164 {
01165 if ( subclass == rb_cBignum )
01166 {
01167 obj = rb_str2inum( val, 10 );
01168 }
01169 else
01170 {
01171 obj = rb_obj_alloc( subclass );
01172 }
01173
01174 if ( rb_respond_to( obj, s_yaml_initialize ) )
01175 {
01176 rb_funcall( obj, s_yaml_initialize, 2, type, val );
01177 }
01178 else if ( !NIL_P( obj ) && rb_obj_is_instance_of( val, rb_cHash ) )
01179 {
01180 rb_block_call( val, s_each, 0, 0, syck_set_ivars, obj );
01181 }
01182 }
01183 else
01184 {
01185 VALUE parts = rb_str_split( type, ":" );
01186 VALUE scheme = rb_ary_shift( parts );
01187 if ( rb_str_cmp( scheme, str_xprivate ) == 0 )
01188 {
01189 VALUE name = rb_ary_join( parts, colon );
01190 obj = rb_funcall( cPrivateType, s_new, 2, name, val );
01191 }
01192 else
01193 {
01194 VALUE domain = rb_ary_shift( parts );
01195 VALUE name = rb_ary_join( parts, colon );
01196 obj = rb_funcall( cDomainType, s_new, 3, domain, name, val );
01197 }
01198 }
01199 }
01200 val = obj;
01201 }
01202
01203 return val;
01204 }
01205
01206
01207
01208
01209 VALUE
01210 syck_resolver_tagurize(VALUE self, VALUE val)
01211 {
01212 VALUE tmp = rb_check_string_type(val);
01213
01214 if ( !NIL_P(tmp) )
01215 {
01216 char *taguri = syck_type_id_to_uri( RSTRING_PTR(tmp) );
01217 val = rb_str_new2( taguri );
01218 S_FREE( taguri );
01219 }
01220
01221 return val;
01222 }
01223
01224
01225
01226
01227 VALUE
01228 syck_defaultresolver_detect_implicit(VALUE self, VALUE val)
01229 {
01230 const char *type_id;
01231 VALUE tmp = rb_check_string_type(val);
01232
01233 if ( !NIL_P(tmp) )
01234 {
01235 val = tmp;
01236 type_id = syck_match_implicit( RSTRING_PTR(val), RSTRING_LEN(val) );
01237 return rb_str_new2( type_id );
01238 }
01239
01240 return rb_str_new2( "" );
01241 }
01242
01243
01244
01245
01246 VALUE
01247 syck_defaultresolver_node_import(VALUE self, VALUE node)
01248 {
01249 SyckNode *n;
01250 VALUE obj;
01251 Data_Get_Struct( node, SyckNode, n );
01252 if ( !yaml_org_handler( n, &obj ) )
01253 {
01254 obj = rb_funcall( self, s_transfer, 2, rb_str_new2( n->type_id ), obj );
01255 }
01256 return obj;
01257 }
01258
01259
01260
01261
01262 VALUE
01263 syck_genericresolver_node_import(VALUE self, VALUE node)
01264 {
01265 SyckNode *n;
01266 int i = 0;
01267 VALUE t = Qnil, obj = Qnil, v = Qnil, style = Qnil;
01268 Data_Get_Struct(node, SyckNode, n);
01269
01270 if ( n->type_id != NULL )
01271 {
01272 t = rb_str_new2(n->type_id);
01273 }
01274
01275 switch (n->kind)
01276 {
01277 case syck_str_kind:
01278 {
01279 v = rb_str_new( n->data.str->ptr, n->data.str->len );
01280 rb_enc_associate(v, rb_utf8_encoding());
01281 if ( n->data.str->style == scalar_1quote )
01282 {
01283 style = sym_1quote;
01284 }
01285 else if ( n->data.str->style == scalar_2quote )
01286 {
01287 style = sym_2quote;
01288 }
01289 else if ( n->data.str->style == scalar_fold )
01290 {
01291 style = sym_fold;
01292 }
01293 else if ( n->data.str->style == scalar_literal )
01294 {
01295 style = sym_literal;
01296 }
01297 else if ( n->data.str->style == scalar_plain )
01298 {
01299 style = sym_plain;
01300 }
01301 obj = rb_funcall( cScalar, s_new, 3, t, v, style );
01302 }
01303 break;
01304
01305 case syck_seq_kind:
01306 v = rb_ary_new2( syck_seq_count( n ) );
01307 for ( i = 0; i < syck_seq_count( n ); i++ )
01308 {
01309 rb_ary_store( v, i, syck_seq_read( n, i ) );
01310 }
01311 if ( n->data.list->style == seq_inline )
01312 {
01313 style = sym_inline;
01314 }
01315 obj = rb_funcall( cSeq, s_new, 3, t, v, style );
01316 rb_iv_set(obj, "@kind", sym_seq);
01317 break;
01318
01319 case syck_map_kind:
01320 v = rb_hash_new();
01321 for ( i = 0; i < syck_map_count( n ); i++ )
01322 {
01323 rb_hash_aset( v, syck_map_read( n, map_key, i ), syck_map_read( n, map_value, i ) );
01324 }
01325 if ( n->data.pairs->style == map_inline )
01326 {
01327 style = sym_inline;
01328 }
01329 obj = rb_funcall( cMap, s_new, 3, t, v, style );
01330 rb_iv_set(obj, "@kind", sym_map);
01331 break;
01332 }
01333
01334 return obj;
01335 }
01336
01337
01338
01339
01340 VALUE
01341 syck_badalias_initialize(VALUE self, VALUE val)
01342 {
01343 rb_iv_set( self, "@name", val );
01344 return self;
01345 }
01346
01347
01348
01349
01350 VALUE
01351 syck_badalias_cmp(VALUE alias1, VALUE alias2)
01352 {
01353 VALUE str1 = rb_ivar_get( alias1, s_name );
01354 VALUE str2 = rb_ivar_get( alias2, s_name );
01355 VALUE val = rb_funcall( str1, s_cmp, 1, str2 );
01356 return val;
01357 }
01358
01359
01360
01361
01362 VALUE
01363 syck_domaintype_initialize(VALUE self, VALUE domain, VALUE type_id, VALUE val)
01364 {
01365 rb_iv_set( self, "@domain", domain );
01366 rb_iv_set( self, "@type_id", type_id );
01367 rb_iv_set( self, "@value", val );
01368 return self;
01369 }
01370
01371
01372
01373
01374 VALUE
01375 syck_yobject_initialize(VALUE self, VALUE klass, VALUE ivars)
01376 {
01377 rb_iv_set( self, "@class", klass );
01378 rb_iv_set( self, "@ivars", ivars );
01379 return self;
01380 }
01381
01382
01383
01384
01385 VALUE
01386 syck_privatetype_initialize(VALUE self, VALUE type_id, VALUE val)
01387 {
01388 rb_iv_set( self, "@type_id", type_id );
01389 rb_iv_set( self, "@value", val );
01390 return self;
01391 }
01392
01393
01394
01395
01396 static void
01397 syck_node_mark(SyckNode *n)
01398 {
01399 int i;
01400 rb_gc_mark_maybe( n->id );
01401 switch ( n->kind )
01402 {
01403 case syck_seq_kind:
01404 for ( i = 0; i < n->data.list->idx; i++ )
01405 {
01406 rb_gc_mark( syck_seq_read( n, i ) );
01407 }
01408 break;
01409
01410 case syck_map_kind:
01411 for ( i = 0; i < n->data.pairs->idx; i++ )
01412 {
01413 rb_gc_mark( syck_map_read( n, map_key, i ) );
01414 rb_gc_mark( syck_map_read( n, map_value, i ) );
01415 }
01416 break;
01417
01418 case syck_str_kind:
01419 default:
01420
01421 break;
01422 }
01423 #if 0
01424 if ( n->shortcut ) syck_node_mark( n->shortcut );
01425 #endif
01426 }
01427
01428
01429
01430
01431 VALUE
01432 syck_scalar_alloc(VALUE class)
01433 {
01434 SyckNode *node = syck_alloc_str();
01435 VALUE obj = Data_Wrap_Struct( class, syck_node_mark, syck_free_node, node );
01436 node->id = obj;
01437 return obj;
01438 }
01439
01440
01441
01442
01443 VALUE
01444 syck_scalar_initialize(VALUE self, VALUE type_id, VALUE val, VALUE style)
01445 {
01446 rb_iv_set( self, "@kind", sym_scalar );
01447 rb_funcall( self, s_type_id_set, 1, type_id );
01448 rb_funcall( self, s_value_set, 1, val );
01449 rb_funcall( self, s_style_set, 1, style );
01450 return self;
01451 }
01452
01453
01454
01455
01456 VALUE
01457 syck_scalar_style_set(VALUE self, VALUE style)
01458 {
01459 SyckNode *node;
01460 Data_Get_Struct( self, SyckNode, node );
01461
01462 if ( NIL_P( style ) )
01463 {
01464 node->data.str->style = scalar_none;
01465 }
01466 else if ( style == sym_1quote )
01467 {
01468 node->data.str->style = scalar_1quote;
01469 }
01470 else if ( style == sym_2quote )
01471 {
01472 node->data.str->style = scalar_2quote;
01473 }
01474 else if ( style == sym_fold )
01475 {
01476 node->data.str->style = scalar_fold;
01477 }
01478 else if ( style == sym_literal )
01479 {
01480 node->data.str->style = scalar_literal;
01481 }
01482 else if ( style == sym_plain )
01483 {
01484 node->data.str->style = scalar_plain;
01485 }
01486
01487 rb_iv_set( self, "@style", style );
01488 return self;
01489 }
01490
01491
01492
01493
01494 VALUE
01495 syck_scalar_value_set(VALUE self, VALUE val)
01496 {
01497 SyckNode *node;
01498 Data_Get_Struct( self, SyckNode, node );
01499
01500 StringValue( val );
01501 node->data.str->ptr = syck_strndup( RSTRING_PTR(val), RSTRING_LEN(val) );
01502 node->data.str->len = RSTRING_LEN(val);
01503 node->data.str->style = scalar_none;
01504
01505 rb_iv_set( self, "@value", val );
01506 return val;
01507 }
01508
01509
01510
01511
01512 VALUE
01513 syck_seq_alloc(VALUE class)
01514 {
01515 SyckNode *node;
01516 VALUE obj;
01517 node = syck_alloc_seq();
01518 obj = Data_Wrap_Struct( class, syck_node_mark, syck_free_node, node );
01519 node->id = obj;
01520 return obj;
01521 }
01522
01523
01524
01525
01526 VALUE
01527 syck_seq_initialize(VALUE self, VALUE type_id, VALUE val, VALUE style)
01528 {
01529 SyckNode *node;
01530 Data_Get_Struct( self, SyckNode, node );
01531
01532 rb_iv_set( self, "@kind", sym_seq );
01533 rb_funcall( self, s_type_id_set, 1, type_id );
01534 rb_funcall( self, s_value_set, 1, val );
01535 rb_funcall( self, s_style_set, 1, style );
01536 return self;
01537 }
01538
01539
01540
01541
01542 VALUE
01543 syck_seq_value_set(VALUE self, VALUE val)
01544 {
01545 SyckNode *node;
01546 Data_Get_Struct( self, SyckNode, node );
01547
01548 val = rb_check_array_type( val );
01549 if ( !NIL_P( val ) ) {
01550 int i;
01551 syck_seq_empty( node );
01552 for ( i = 0; i < RARRAY_LEN( val ); i++ )
01553 {
01554 syck_seq_add( node, rb_ary_entry(val, i) );
01555 }
01556 }
01557
01558 rb_iv_set( self, "@value", val );
01559 return val;
01560 }
01561
01562
01563
01564
01565 VALUE
01566 syck_seq_add_m(VALUE self, VALUE val)
01567 {
01568 SyckNode *node;
01569 VALUE emitter = rb_ivar_get( self, s_emitter );
01570 Data_Get_Struct( self, SyckNode, node );
01571
01572 if ( rb_respond_to( emitter, s_node_export ) ) {
01573 val = rb_funcall( emitter, s_node_export, 1, val );
01574 }
01575 syck_seq_add( node, val );
01576 rb_ary_push( rb_ivar_get( self, s_value ), val );
01577
01578 return self;
01579 }
01580
01581
01582
01583
01584 VALUE
01585 syck_seq_style_set(VALUE self, VALUE style)
01586 {
01587 SyckNode *node;
01588 Data_Get_Struct( self, SyckNode, node );
01589
01590 if ( style == sym_inline )
01591 {
01592 node->data.list->style = seq_inline;
01593 }
01594 else
01595 {
01596 node->data.list->style = seq_none;
01597 }
01598
01599 rb_iv_set( self, "@style", style );
01600 return self;
01601 }
01602
01603
01604
01605
01606 VALUE
01607 syck_map_alloc(VALUE class)
01608 {
01609 SyckNode *node;
01610 VALUE obj;
01611 node = syck_alloc_map();
01612 obj = Data_Wrap_Struct( class, syck_node_mark, syck_free_node, node );
01613 node->id = obj;
01614 return obj;
01615 }
01616
01617
01618
01619
01620 VALUE
01621 syck_map_initialize(VALUE self, VALUE type_id, VALUE val, VALUE style)
01622 {
01623 SyckNode *node;
01624 Data_Get_Struct( self, SyckNode, node );
01625
01626 if ( !NIL_P( val ) )
01627 {
01628 VALUE hsh = rb_check_convert_type(val, T_HASH, "Hash", "to_hash");
01629 VALUE keys;
01630 int i;
01631 if ( NIL_P(hsh) )
01632 {
01633 rb_raise( rb_eTypeError, "wrong argument type" );
01634 }
01635
01636 keys = rb_funcall( hsh, s_keys, 0 );
01637 for ( i = 0; i < RARRAY_LEN(keys); i++ )
01638 {
01639 VALUE key = rb_ary_entry(keys, i);
01640 syck_map_add( node, key, rb_hash_aref(hsh, key) );
01641 }
01642 }
01643
01644 rb_iv_set( self, "@kind", sym_seq );
01645 rb_funcall( self, s_type_id_set, 1, type_id );
01646 rb_funcall( self, s_value_set, 1, val );
01647 rb_funcall( self, s_style_set, 1, style );
01648 return self;
01649 }
01650
01651
01652
01653
01654 VALUE
01655 syck_map_value_set(VALUE self, VALUE val)
01656 {
01657 SyckNode *node;
01658 Data_Get_Struct( self, SyckNode, node );
01659
01660 if ( !NIL_P( val ) )
01661 {
01662 VALUE hsh = rb_check_convert_type(val, T_HASH, "Hash", "to_hash");
01663 VALUE keys;
01664 int i;
01665 if ( NIL_P(hsh) )
01666 {
01667 rb_raise( rb_eTypeError, "wrong argument type" );
01668 }
01669
01670 syck_map_empty( node );
01671 keys = rb_funcall( hsh, s_keys, 0 );
01672 for ( i = 0; i < RARRAY_LEN(keys); i++ )
01673 {
01674 VALUE key = rb_ary_entry(keys, i);
01675 syck_map_add( node, key, rb_hash_aref(hsh, key) );
01676 }
01677 }
01678
01679 rb_iv_set( self, "@value", val );
01680 return val;
01681 }
01682
01683
01684
01685
01686 VALUE
01687 syck_map_add_m(VALUE self, VALUE key, VALUE val)
01688 {
01689 SyckNode *node;
01690 VALUE emitter = rb_ivar_get( self, s_emitter );
01691 Data_Get_Struct( self, SyckNode, node );
01692
01693 if ( rb_respond_to( emitter, s_node_export ) ) {
01694 key = rb_funcall( emitter, s_node_export, 1, key );
01695 val = rb_funcall( emitter, s_node_export, 1, val );
01696 }
01697 syck_map_add( node, key, val );
01698 rb_hash_aset( rb_ivar_get( self, s_value ), key, val );
01699
01700 return self;
01701 }
01702
01703
01704
01705
01706 VALUE
01707 syck_map_style_set(VALUE self, VALUE style)
01708 {
01709 SyckNode *node;
01710 Data_Get_Struct( self, SyckNode, node );
01711
01712 if ( style == sym_inline )
01713 {
01714 node->data.pairs->style = map_inline;
01715 }
01716 else
01717 {
01718 node->data.pairs->style = map_none;
01719 }
01720
01721 rb_iv_set( self, "@style", style );
01722 return self;
01723 }
01724
01725 #if 0
01726
01727
01728
01729 VALUE
01730 syck_node_init_copy(VALUE copy, VALUE orig)
01731 {
01732 SyckNode *copy_n;
01733 SyckNode *orig_n;
01734
01735 if ( copy == orig )
01736 return copy;
01737
01738 if ( TYPE( orig ) != T_DATA )
01739 {
01740 rb_raise( rb_eTypeError, "wrong argument type" );
01741 }
01742
01743 Data_Get_Struct( orig, SyckNode, orig_n );
01744 Data_Get_Struct( copy, SyckNode, copy_n );
01745 MEMCPY( copy_n, orig_n, SyckNode, 1 );
01746 return copy;
01747 }
01748 #endif
01749
01750
01751
01752
01753 VALUE
01754 syck_node_type_id_set(VALUE self, VALUE type_id)
01755 {
01756 SyckNode *node;
01757 Data_Get_Struct( self, SyckNode, node );
01758
01759 S_FREE( node->type_id );
01760
01761 if ( !NIL_P( type_id ) ) {
01762 StringValue( type_id );
01763 node->type_id = syck_strndup( RSTRING_PTR(type_id), RSTRING_LEN(type_id) );
01764 }
01765
01766 rb_iv_set( self, "@type_id", type_id );
01767 return type_id;
01768 }
01769
01770
01771
01772
01773 VALUE
01774 syck_node_transform(VALUE self)
01775 {
01776 VALUE t;
01777 SyckNode *n = NULL;
01778 SyckNode *orig_n;
01779 Data_Get_Struct(self, SyckNode, orig_n);
01780 t = Data_Wrap_Struct( cNode, syck_node_mark, syck_free_node, 0 );
01781
01782 switch (orig_n->kind)
01783 {
01784 case syck_map_kind:
01785 {
01786 int i;
01787 DATA_PTR(t) = n = syck_alloc_map();
01788 for ( i = 0; i < orig_n->data.pairs->idx; i++ )
01789 {
01790 syck_map_add( n, rb_funcall( syck_map_read( orig_n, map_key, i ), s_transform, 0 ),
01791 rb_funcall( syck_map_read( orig_n, map_value, i ), s_transform, 0 ) );
01792 }
01793 }
01794 break;
01795
01796 case syck_seq_kind:
01797 {
01798 int i;
01799 DATA_PTR(t) = n = syck_alloc_seq();
01800 for ( i = 0; i < orig_n->data.list->idx; i++ )
01801 {
01802 syck_seq_add( n, rb_funcall( syck_seq_read( orig_n, i ), s_transform, 0 ) );
01803 }
01804 }
01805 break;
01806
01807 case syck_str_kind:
01808 DATA_PTR(t) = n = syck_new_str2( orig_n->data.str->ptr, orig_n->data.str->len, orig_n->data.str->style );
01809 break;
01810 }
01811
01812 if ( orig_n->type_id != NULL )
01813 {
01814 n->type_id = syck_strndup( orig_n->type_id, strlen( orig_n->type_id ) );
01815 }
01816 if ( orig_n->anchor != NULL )
01817 {
01818 n->anchor = syck_strndup( orig_n->anchor, strlen( orig_n->anchor ) );
01819 }
01820 n->id = t;
01821 return rb_funcall( oDefaultResolver, s_node_import, 1, t );
01822 }
01823
01824
01825
01826
01827
01828
01829 void
01830 rb_syck_emitter_handler(SyckEmitter *e, st_data_t data)
01831 {
01832 SyckNode *n;
01833 Data_Get_Struct((VALUE)data, SyckNode, n);
01834
01835 switch (n->kind)
01836 {
01837 case syck_map_kind:
01838 {
01839 int i;
01840 syck_emit_map( e, n->type_id, n->data.pairs->style );
01841 for ( i = 0; i < n->data.pairs->idx; i++ )
01842 {
01843 syck_emit_item( e, syck_map_read( n, map_key, i ) );
01844 syck_emit_item( e, syck_map_read( n, map_value, i ) );
01845 }
01846 syck_emit_end( e );
01847 }
01848 break;
01849
01850 case syck_seq_kind:
01851 {
01852 int i;
01853 syck_emit_seq( e, n->type_id, n->data.list->style );
01854 for ( i = 0; i < n->data.list->idx; i++ )
01855 {
01856 syck_emit_item( e, syck_seq_read( n, i ) );
01857 }
01858 syck_emit_end( e );
01859 }
01860 break;
01861
01862 case syck_str_kind:
01863 {
01864 syck_emit_scalar( e, n->type_id, n->data.str->style, 0, 0, 0, n->data.str->ptr, n->data.str->len );
01865 }
01866 break;
01867 }
01868 }
01869
01870
01871
01872
01873 void
01874 rb_syck_output_handler(SyckEmitter * emitter, char *str, long len)
01875 {
01876 struct emitter_xtra *bonus = (struct emitter_xtra *)emitter->bonus;
01877 VALUE dest = bonus->port;
01878 if (TYPE(dest) == T_STRING) {
01879 rb_str_cat( dest, str, len );
01880 } else {
01881 rb_io_write( dest, rb_str_new( str, len ) );
01882 }
01883 }
01884
01885
01886
01887
01888
01889 void
01890 syck_out_mark(VALUE emitter, VALUE node)
01891 {
01892 SyckEmitter *emitterPtr;
01893 struct emitter_xtra *bonus;
01894 Data_Get_Struct(emitter, SyckEmitter, emitterPtr);
01895 bonus = (struct emitter_xtra *)emitterPtr->bonus;
01896 rb_ivar_set( node, s_emitter, emitter );
01897
01898 if ( !NIL_P( bonus->oid ) ) {
01899 rb_hash_aset( bonus->data, bonus->oid, node );
01900 }
01901 }
01902
01903
01904
01905
01906 static void
01907 syck_mark_emitter(SyckEmitter *emitter)
01908 {
01909 struct emitter_xtra *bonus = (struct emitter_xtra *)emitter->bonus;
01910 rb_gc_mark( bonus->oid );
01911 rb_gc_mark( bonus->data );
01912 rb_gc_mark( bonus->port );
01913 }
01914
01915
01916
01917
01918 void
01919 rb_syck_free_emitter(SyckEmitter *e)
01920 {
01921 S_FREE( e->bonus );
01922 syck_free_emitter(e);
01923 }
01924
01925
01926
01927
01928 VALUE syck_emitter_s_alloc _((VALUE));
01929 VALUE
01930 syck_emitter_s_alloc(VALUE class)
01931 {
01932 VALUE pobj;
01933 SyckEmitter *emitter = syck_new_emitter();
01934
01935 emitter->bonus = S_ALLOC( struct emitter_xtra );
01936 S_MEMZERO( emitter->bonus, struct emitter_xtra, 1 );
01937
01938 pobj = Data_Wrap_Struct( class, syck_mark_emitter, rb_syck_free_emitter, emitter );
01939 syck_emitter_handler( emitter, rb_syck_emitter_handler );
01940 syck_output_handler( emitter, rb_syck_output_handler );
01941
01942 rb_ivar_set( pobj, s_out, rb_funcall( cOut, s_new, 1, pobj ) );
01943 return pobj;
01944 }
01945
01946 static VALUE
01947 id_hash_new(void)
01948 {
01949 VALUE hash;
01950 hash = rb_hash_new();
01951 rb_funcall(hash, rb_intern("compare_by_identity"), 0);
01952 return hash;
01953 }
01954
01955
01956
01957
01958 VALUE
01959 syck_emitter_reset(int argc, VALUE *argv, VALUE self)
01960 {
01961 VALUE options, tmp;
01962 SyckEmitter *emitter;
01963 struct emitter_xtra *bonus;
01964
01965 Data_Get_Struct(self, SyckEmitter, emitter);
01966 bonus = (struct emitter_xtra *)emitter->bonus;
01967
01968 bonus->oid = Qnil;
01969 bonus->port = rb_str_new2( "" );
01970 bonus->data = id_hash_new();
01971
01972 if (rb_scan_args(argc, argv, "01", &options) == 0)
01973 {
01974 options = rb_hash_new();
01975 rb_ivar_set(self, s_options, options);
01976 }
01977 else if ( !NIL_P(tmp = rb_check_string_type(options)) )
01978 {
01979 bonus->port = tmp;
01980 }
01981 else if ( rb_respond_to( options, s_write ) )
01982 {
01983 bonus->port = options;
01984 }
01985 else
01986 {
01987 Check_Type(options, T_HASH);
01988 rb_ivar_set(self, s_options, options);
01989 }
01990
01991 emitter->headless = 0;
01992 rb_ivar_set(self, s_level, INT2FIX(0));
01993 rb_ivar_set(self, s_resolver, Qnil);
01994 return self;
01995 }
01996
01997
01998
01999
02000 VALUE
02001 syck_emitter_emit(int argc, VALUE *argv, VALUE self)
02002 {
02003 VALUE oid, proc;
02004 SyckEmitter *emitter;
02005 struct emitter_xtra *bonus;
02006 SYMID symple;
02007 int level = FIX2INT(rb_ivar_get(self, s_level)) + 1;
02008 rb_ivar_set(self, s_level, INT2FIX(level));
02009
02010 rb_scan_args(argc, argv, "1&", &oid, &proc);
02011 Data_Get_Struct(self, SyckEmitter, emitter);
02012 bonus = (struct emitter_xtra *)emitter->bonus;
02013
02014
02015 bonus->oid = oid;
02016 if ( !NIL_P( oid ) && RTEST( rb_funcall( bonus->data, s_haskey, 1, oid ) ) ) {
02017 symple = rb_hash_aref( bonus->data, oid );
02018 } else {
02019 symple = rb_funcall( proc, s_call, 1, rb_ivar_get( self, s_out ) );
02020 }
02021 syck_emitter_mark_node( emitter, (st_data_t)symple );
02022
02023
02024 level -= 1;
02025 rb_ivar_set(self, s_level, INT2FIX(level));
02026 if ( level == 0 )
02027 {
02028 syck_emit(emitter, (st_data_t)symple);
02029 syck_emitter_flush(emitter, 0);
02030
02031 return bonus->port;
02032 }
02033
02034 return symple;
02035 }
02036
02037
02038
02039
02040 VALUE
02041 syck_emitter_node_export(VALUE self, VALUE node)
02042 {
02043 return rb_funcall( node, s_to_yaml, 1, self );
02044 }
02045
02046
02047
02048
02049 VALUE
02050 syck_emitter_set_resolver(VALUE self, VALUE resolver)
02051 {
02052 rb_ivar_set( self, s_resolver, resolver );
02053 return self;
02054 }
02055
02056
02057
02058
02059 VALUE
02060 syck_out_initialize(VALUE self, VALUE emitter)
02061 {
02062 rb_ivar_set( self, s_emitter, emitter );
02063 return self;
02064 }
02065
02066
02067
02068
02069 VALUE
02070 syck_out_map(int argc, VALUE *argv, VALUE self)
02071 {
02072 VALUE type_id, style, map;
02073 if (rb_scan_args(argc, argv, "11", &type_id, &style) == 1) {
02074 style = Qnil;
02075 }
02076 map = rb_funcall( cMap, s_new, 3, type_id, rb_hash_new(), style );
02077 syck_out_mark( rb_ivar_get( self, s_emitter ), map );
02078 rb_yield( map );
02079 return map;
02080 }
02081
02082
02083
02084
02085 VALUE
02086 syck_out_seq(int argc, VALUE *argv, VALUE self)
02087 {
02088 VALUE type_id, style, seq;
02089 if (rb_scan_args(argc, argv, "11", &type_id, &style) == 1) {
02090 style = Qnil;
02091 }
02092 seq = rb_funcall( cSeq, s_new, 3, type_id, rb_ary_new(), style );
02093 syck_out_mark( rb_ivar_get( self, s_emitter ), seq );
02094 rb_yield( seq );
02095 return seq;
02096 }
02097
02098
02099
02100
02101
02102
02103 VALUE
02104 syck_out_scalar(int argc, VALUE *argv, VALUE self)
02105 {
02106 VALUE type_id, str, style, scalar;
02107 rb_scan_args(argc, argv, "21", &type_id, &str, &style);
02108 scalar = rb_funcall( cScalar, s_new, 3, type_id, str, style );
02109 syck_out_mark( rb_ivar_get( self, s_emitter ), scalar );
02110 return scalar;
02111 }
02112
02113
02114
02115
02116 void
02117 Init_syck()
02118 {
02119 VALUE rb_syck = rb_define_module_under( rb_cObject, "Syck" );
02120 rb_define_module_function( rb_syck, "compile", rb_syck_compile, 1 );
02121
02122
02123
02124
02125 s_new = rb_intern("new");
02126 s_utc = rb_intern("utc");
02127 s_at = rb_intern("at");
02128 s_to_f = rb_intern("to_f");
02129 s_to_i = rb_intern("to_i");
02130 s_read = rb_intern("read");
02131 s_binmode = rb_intern("binmode");
02132 s_transfer = rb_intern("transfer");
02133 s_call = rb_intern("call");
02134 s_cmp = rb_intern("<=>");
02135 s_intern = rb_intern("intern");
02136 s_update = rb_intern("update");
02137 s_detect_implicit = rb_intern("detect_implicit");
02138 s_dup = rb_intern("dup");
02139 s_default_set = rb_intern("default=");
02140 s_match = rb_intern("match");
02141 s_push = rb_intern("push");
02142 s_haskey = rb_intern("has_key?");
02143 s_keys = rb_intern("keys");
02144 s_node_import = rb_intern("node_import");
02145 s_tr_bang = rb_intern("tr!");
02146 s_unpack = rb_intern("unpack");
02147 s_write = rb_intern("write");
02148 s_tag_read_class = rb_intern( "yaml_tag_read_class" );
02149 s_tag_subclasses = rb_intern( "yaml_tag_subclasses?" );
02150 s_emitter = rb_intern( "emitter" );
02151 s_set_resolver = rb_intern( "set_resolver" );
02152 s_node_export = rb_intern( "node_export" );
02153 s_to_yaml = rb_intern( "to_yaml" );
02154 s_transform = rb_intern( "transform" );
02155 s_yaml_new = rb_intern("yaml_new");
02156 s_yaml_initialize = rb_intern("yaml_initialize");
02157 s_each = rb_intern("each");
02158 s_parse = rb_intern("parse");
02159
02160 s_tags = rb_intern("@tags");
02161 s_name = rb_intern("@name");
02162 s_options = rb_intern("@options");
02163 s_kind = rb_intern("@kind");
02164 s_type_id = rb_intern("@type_id");
02165 s_type_id_set = rb_intern("type_id=");
02166 s_resolver = rb_intern("@resolver");
02167 s_level = rb_intern( "@level" );
02168 s_style = rb_intern("@style");
02169 s_style_set = rb_intern("style=");
02170 s_value = rb_intern("@value");
02171 s_value_set = rb_intern("value=");
02172 s_out = rb_intern("@out");
02173 s_input = rb_intern("@input");
02174
02175 sym_model = ID2SYM(rb_intern("Model"));
02176 sym_generic = ID2SYM(rb_intern("Generic"));
02177 sym_bytecode = ID2SYM(rb_intern("bytecode"));
02178 sym_map = ID2SYM(rb_intern("map"));
02179 sym_scalar = ID2SYM(rb_intern("scalar"));
02180 sym_seq = ID2SYM(rb_intern("seq"));
02181 sym_1quote = ID2SYM(rb_intern("quote1"));
02182 sym_2quote = ID2SYM(rb_intern("quote2"));
02183 sym_fold = ID2SYM(rb_intern("fold"));
02184 sym_literal = ID2SYM(rb_intern("literal"));
02185 sym_plain = ID2SYM(rb_intern("plain"));
02186 sym_inline = ID2SYM(rb_intern("inline"));
02187
02188
02189
02190
02191 cResolver = rb_define_class_under( rb_syck, "Resolver", rb_cObject );
02192 rb_define_attr( cResolver, "tags", 1, 1 );
02193 rb_define_method( cResolver, "initialize", syck_resolver_initialize, 0 );
02194 rb_define_method( cResolver, "add_type", syck_resolver_add_type, 2 );
02195 rb_define_method( cResolver, "use_types_at", syck_resolver_use_types_at, 1 );
02196 rb_define_method( cResolver, "detect_implicit", syck_resolver_detect_implicit, 1 );
02197 rb_define_method( cResolver, "transfer", syck_resolver_transfer, 2 );
02198 rb_define_method( cResolver, "node_import", syck_resolver_node_import, 1 );
02199 rb_define_method( cResolver, "tagurize", syck_resolver_tagurize, 1 );
02200
02201 rb_global_variable( &oDefaultResolver );
02202 oDefaultResolver = rb_funcall( cResolver, rb_intern( "new" ), 0 );
02203 rb_define_singleton_method( oDefaultResolver, "node_import", syck_defaultresolver_node_import, 1 );
02204 rb_define_singleton_method( oDefaultResolver, "detect_implicit", syck_defaultresolver_detect_implicit, 1 );
02205 rb_define_const( rb_syck, "DefaultResolver", oDefaultResolver );
02206 rb_global_variable( &oGenericResolver );
02207 oGenericResolver = rb_funcall( cResolver, rb_intern( "new" ), 0 );
02208 rb_define_singleton_method( oGenericResolver, "node_import", syck_genericresolver_node_import, 1 );
02209 rb_define_const( rb_syck, "GenericResolver", oGenericResolver );
02210
02211
02212
02213
02214 cParser = rb_define_class_under( rb_syck, "Parser", rb_cObject );
02215 rb_define_attr( cParser, "options", 1, 1 );
02216 rb_define_attr( cParser, "resolver", 1, 1 );
02217 rb_define_attr( cParser, "input", 1, 1 );
02218 rb_define_alloc_func( cParser, syck_parser_s_alloc );
02219 rb_define_method(cParser, "initialize", syck_parser_initialize, -1 );
02220 rb_define_method(cParser, "bufsize=", syck_parser_bufsize_set, 1 );
02221 rb_define_method(cParser, "bufsize", syck_parser_bufsize_get, 0 );
02222 rb_define_method(cParser, "load", syck_parser_load, -1);
02223 rb_define_method(cParser, "load_documents", syck_parser_load_documents, -1);
02224 rb_define_method(cParser, "set_resolver", syck_parser_set_resolver, 1);
02225
02226
02227
02228
02229 cNode = rb_define_class_under( rb_syck, "Node", rb_cObject );
02230 rb_undef( cNode, rb_intern("initialize_copy") );
02231 rb_define_attr( cNode, "emitter", 1, 1 );
02232 rb_define_attr( cNode, "resolver", 1, 1 );
02233 rb_define_attr( cNode, "kind", 1, 0 );
02234 rb_define_attr( cNode, "type_id", 1, 0 );
02235 rb_define_attr( cNode, "value", 1, 0 );
02236 rb_define_method( cNode, "type_id=", syck_node_type_id_set, 1 );
02237 rb_define_method( cNode, "transform", syck_node_transform, 0);
02238
02239
02240
02241
02242
02243 cScalar = rb_define_class_under( rb_syck, "Scalar", cNode );
02244 rb_define_alloc_func( cScalar, syck_scalar_alloc );
02245 rb_define_method( cScalar, "initialize", syck_scalar_initialize, 3 );
02246 rb_define_method( cScalar, "value=", syck_scalar_value_set, 1 );
02247 rb_define_method( cScalar, "style=", syck_scalar_style_set, 1 );
02248 cSeq = rb_define_class_under( rb_syck, "Seq", cNode );
02249 rb_define_alloc_func( cSeq, syck_seq_alloc );
02250 rb_define_method( cSeq, "initialize", syck_seq_initialize, 3 );
02251 rb_define_method( cSeq, "value=", syck_seq_value_set, 1 );
02252 rb_define_method( cSeq, "add", syck_seq_add_m, 1 );
02253 rb_define_method( cSeq, "style=", syck_seq_style_set, 1 );
02254 cMap = rb_define_class_under( rb_syck, "Map", cNode );
02255 rb_define_alloc_func( cMap, syck_map_alloc );
02256 rb_define_method( cMap, "initialize", syck_map_initialize, 3 );
02257 rb_define_method( cMap, "value=", syck_map_value_set, 1 );
02258 rb_define_method( cMap, "add", syck_map_add_m, 2 );
02259 rb_define_method( cMap, "style=", syck_map_style_set, 1 );
02260
02261
02262
02263
02264 cPrivateType = rb_define_class_under( rb_syck, "PrivateType", rb_cObject );
02265 rb_define_attr( cPrivateType, "type_id", 1, 1 );
02266 rb_define_attr( cPrivateType, "value", 1, 1 );
02267 rb_define_method( cPrivateType, "initialize", syck_privatetype_initialize, 2);
02268
02269
02270
02271
02272 cDomainType = rb_define_class_under( rb_syck, "DomainType", rb_cObject );
02273 rb_define_attr( cDomainType, "domain", 1, 1 );
02274 rb_define_attr( cDomainType, "type_id", 1, 1 );
02275 rb_define_attr( cDomainType, "value", 1, 1 );
02276 rb_define_method( cDomainType, "initialize", syck_domaintype_initialize, 3);
02277
02278
02279
02280
02281 cYObject = rb_define_class_under( rb_syck, "Object", rb_cObject );
02282 rb_define_attr( cYObject, "class", 1, 1 );
02283 rb_define_attr( cYObject, "ivars", 1, 1 );
02284 rb_define_method( cYObject, "initialize", syck_yobject_initialize, 2);
02285 rb_define_method( cYObject, "yaml_initialize", syck_yobject_initialize, 2);
02286
02287
02288
02289
02290 cBadAlias = rb_define_class_under( rb_syck, "BadAlias", rb_cObject );
02291 rb_define_attr( cBadAlias, "name", 1, 1 );
02292 rb_define_method( cBadAlias, "initialize", syck_badalias_initialize, 1);
02293 rb_define_method( cBadAlias, "<=>", syck_badalias_cmp, 1);
02294 rb_include_module( cBadAlias, rb_const_get( rb_cObject, rb_intern("Comparable") ) );
02295
02296
02297
02298
02299 cMergeKey = rb_define_class_under( rb_syck, "MergeKey", rb_cObject );
02300
02301
02302
02303
02304 cDefaultKey = rb_define_class_under( rb_syck, "DefaultKey", rb_cObject );
02305
02306
02307
02308
02309 cOut = rb_define_class_under( rb_syck, "Out", rb_cObject );
02310 rb_define_attr( cOut, "emitter", 1, 1 );
02311 rb_define_method( cOut, "initialize", syck_out_initialize, 1 );
02312 rb_define_method( cOut, "map", syck_out_map, -1 );
02313 rb_define_method( cOut, "seq", syck_out_seq, -1 );
02314 rb_define_method( cOut, "scalar", syck_out_scalar, -1 );
02315
02316
02317
02318
02319 cEmitter = rb_define_class_under( rb_syck, "Emitter", rb_cObject );
02320 rb_define_attr( cEmitter, "level", 1, 1 );
02321 rb_define_alloc_func( cEmitter, syck_emitter_s_alloc );
02322 rb_define_method( cEmitter, "initialize", syck_emitter_reset, -1 );
02323 rb_define_method( cEmitter, "reset", syck_emitter_reset, -1 );
02324 rb_define_method( cEmitter, "emit", syck_emitter_emit, -1 );
02325 rb_define_method( cEmitter, "set_resolver", syck_emitter_set_resolver, 1);
02326 rb_define_method( cEmitter, "node_export", syck_emitter_node_export, 1);
02327 }
02328
02329