summaryrefslogtreecommitdiff
path: root/ext/syck/rubyext.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/syck/rubyext.c')
-rw-r--r--ext/syck/rubyext.c1481
1 files changed, 0 insertions, 1481 deletions
diff --git a/ext/syck/rubyext.c b/ext/syck/rubyext.c
deleted file mode 100644
index 3722babc39..0000000000
--- a/ext/syck/rubyext.c
+++ /dev/null
@@ -1,1481 +0,0 @@
-/*
- * rubyext.c
- *
- * $Author$
- * $Date$
- *
- * Copyright (C) 2003 why the lucky stiff
- */
-
-#include "ruby.h"
-#include "syck.h"
-#include <sys/types.h>
-#include <time.h>
-
-typedef struct RVALUE {
- union {
-#if 0
- struct {
- unsigned long flags; /* always 0 for freed obj */
- struct RVALUE *next;
- } free;
-#endif
- struct RBasic basic;
- struct RObject object;
- struct RClass klass;
- /*struct RFloat flonum;*/
- /*struct RString string;*/
- struct RArray array;
- /*struct RRegexp regexp;*/
- struct RHash hash;
- /*struct RData data;*/
- struct RStruct rstruct;
- /*struct RBignum bignum;*/
- /*struct RFile file;*/
- } as;
-} RVALUE;
-
-typedef struct {
- long hash;
- char *buffer;
- long length;
- long remaining;
- int printed;
-} bytestring_t;
-
-#define RUBY_DOMAIN "ruby.yaml.org,2002"
-
-/*
- * symbols and constants
- */
-static ID s_new, s_utc, s_at, s_to_f, s_to_i, s_read, s_binmode, s_call, s_transfer, s_update, s_dup, s_match, s_keys, s_to_str, s_unpack, s_tr_bang, s_anchors, s_default_set;
-static VALUE sym_model, sym_generic, sym_input, sym_bytecode;
-static VALUE sym_scalar, sym_seq, sym_map;
-VALUE cDate, cParser, cLoader, cNode, cPrivateType, cDomainType, cBadAlias, cDefaultKey, cMergeKey, cEmitter;
-VALUE oDefaultLoader;
-
-/*
- * my private collection of numerical oddities.
- */
-static double S_zero() { return 0.0; }
-static double S_one() { return 1.0; }
-static double S_inf() { return S_one() / S_zero(); }
-static double S_nan() { return S_zero() / S_zero(); }
-
-static VALUE syck_node_transform( VALUE );
-
-/*
- * handler prototypes
- */
-SYMID rb_syck_parse_handler _((SyckParser *, SyckNode *));
-SYMID rb_syck_load_handler _((SyckParser *, SyckNode *));
-void rb_syck_err_handler _((SyckParser *, char *));
-SyckNode * rb_syck_bad_anchor_handler _((SyckParser *, char *));
-void rb_syck_output_handler _((SyckEmitter *, char *, long));
-int syck_parser_assign_io _((SyckParser *, VALUE));
-
-struct parser_xtra {
- VALUE data; /* Borrowed this idea from marshal.c to fix [ruby-core:8067] problem */
- VALUE proc;
- int taint;
-};
-
-/*
- * Convert YAML to bytecode
- */
-VALUE
-rb_syck_compile(self, port)
- VALUE self, port;
-{
- SYMID oid;
- int taint;
- char *ret;
- VALUE bc;
- bytestring_t *sav;
-
- SyckParser *parser = syck_new_parser();
- taint = syck_parser_assign_io(parser, port);
- syck_parser_handler( parser, syck_yaml2byte_handler );
- syck_parser_error_handler( parser, NULL );
- syck_parser_implicit_typing( parser, 0 );
- syck_parser_taguri_expansion( parser, 0 );
- oid = syck_parse( parser );
- syck_lookup_sym( parser, oid, (char **)&sav );
-
- ret = S_ALLOC_N( char, strlen( sav->buffer ) + 3 );
- ret[0] = '\0';
- strcat( ret, "D\n" );
- strcat( ret, sav->buffer );
-
- syck_free_parser( parser );
-
- bc = rb_str_new2( ret );
- if ( taint ) OBJ_TAINT( bc );
- return bc;
-}
-
-/*
- * read from io.
- */
-long
-rb_syck_io_str_read( char *buf, SyckIoStr *str, long max_size, long skip )
-{
- long len = 0;
-
- ASSERT( str != NULL );
- max_size -= skip;
-
- if ( max_size <= 0 ) max_size = 0;
- else
- {
- /*
- * call io#read.
- */
- VALUE src = (VALUE)str->ptr;
- VALUE n = LONG2NUM(max_size);
- VALUE str2 = rb_funcall2(src, s_read, 1, &n);
- if (!NIL_P(str2))
- {
- len = RSTRING(str2)->len;
- memcpy( buf + skip, RSTRING(str2)->ptr, len );
- }
- }
- len += skip;
- buf[len] = '\0';
- return len;
-}
-
-/*
- * determine: are we reading from a string or io?
- * (returns tainted? boolean)
- */
-int
-syck_parser_assign_io(parser, port)
- SyckParser *parser;
- VALUE port;
-{
- int taint = Qtrue;
- if (rb_respond_to(port, s_to_str)) {
- taint = OBJ_TAINTED(port); /* original taintedness */
- StringValue(port); /* possible conversion */
- syck_parser_str( parser, RSTRING(port)->ptr, RSTRING(port)->len, NULL );
- }
- else if (rb_respond_to(port, s_read)) {
- if (rb_respond_to(port, s_binmode)) {
- rb_funcall2(port, s_binmode, 0, 0);
- }
- syck_parser_str( parser, (char *)port, 0, rb_syck_io_str_read );
- }
- else {
- rb_raise(rb_eTypeError, "instance of IO needed");
- }
- return taint;
-}
-
-/*
- * Get value in hash by key, forcing an empty hash if nil.
- */
-VALUE
-syck_get_hash_aref(hsh, key)
- VALUE hsh, key;
-{
- VALUE val = rb_hash_aref( hsh, key );
- if ( NIL_P( val ) )
- {
- val = rb_hash_new();
- rb_hash_aset(hsh, key, val);
- }
- return val;
-}
-
-/*
- * creating timestamps
- */
-SYMID
-rb_syck_mktime(str)
- char *str;
-{
- VALUE time;
- char *ptr = str;
- VALUE year, mon, day, hour, min, sec, usec;
-
- /* Year*/
- ptr[4] = '\0';
- year = INT2FIX(strtol(ptr, NULL, 10));
-
- /* Month*/
- ptr += 4;
- while ( !ISDIGIT( *ptr ) ) ptr++;
- mon = INT2FIX(strtol(ptr, NULL, 10));
-
- /* Day*/
- ptr += 2;
- while ( !ISDIGIT( *ptr ) ) ptr++;
- day = INT2FIX(strtol(ptr, NULL, 10));
-
- /* Hour*/
- ptr += 2;
- while ( !ISDIGIT( *ptr ) ) ptr++;
- hour = INT2FIX(strtol(ptr, NULL, 10));
-
- /* Minute */
- ptr += 2;
- while ( !ISDIGIT( *ptr ) ) ptr++;
- min = INT2FIX(strtol(ptr, NULL, 10));
-
- /* Second */
- ptr += 2;
- while ( !ISDIGIT( *ptr ) ) ptr++;
- sec = INT2FIX(strtol(ptr, NULL, 10));
-
- /* Millisecond */
- ptr += 2;
- if ( *ptr == '.' )
- {
- usec = INT2FIX( strtod( ptr, NULL ) * 1000000 );
- }
- else
- {
- usec = INT2FIX( 0 );
- }
-
- /* Make UTC time*/
- time = rb_funcall(rb_cTime, s_utc, 7, year, mon, day, hour, min, sec, usec);
-
- /* Time Zone*/
- while ( *ptr != 'Z' && *ptr != '+' && *ptr != '-' && *ptr != '\0' ) ptr++;
- if ( *ptr == '-' || *ptr == '+' )
- {
- double tz_offset = 0;
- double utc_time = 0;
- tz_offset += strtod(ptr, NULL) * 3600;
-
- while ( *ptr != ':' && *ptr != '\0' ) ptr++;
- if ( *ptr == ':' )
- {
- ptr += 1;
- if ( tz_offset < 0 )
- {
- tz_offset -= strtod(ptr, NULL) * 60;
- }
- else
- {
- tz_offset += strtod(ptr, NULL) * 60;
- }
- }
-
- /* Make TZ time*/
- utc_time = NUM2DBL(rb_funcall(time, s_to_f, 0));
- utc_time -= tz_offset;
- time = rb_funcall(rb_cTime, s_at, 1, rb_float_new(utc_time));
- }
-
- return time;
-}
-
-/*
- * {generic mode} node handler
- * - Loads data into Node classes
- */
-SYMID
-rb_syck_parse_handler(p, n)
- SyckParser *p;
- SyckNode *n;
-{
- VALUE t, obj, v = Qnil;
- int i;
- struct parser_xtra *bonus;
-
- obj = rb_obj_alloc(cNode);
- if ( n->type_id != NULL )
- {
- t = rb_str_new2(n->type_id);
- rb_iv_set(obj, "@type_id", t);
- }
-
- switch (n->kind)
- {
- case syck_str_kind:
- rb_iv_set(obj, "@kind", sym_scalar);
- v = rb_str_new( n->data.str->ptr, n->data.str->len );
- break;
-
- case syck_seq_kind:
- rb_iv_set(obj, "@kind", sym_seq);
- v = rb_ary_new2( n->data.list->idx );
- for ( i = 0; i < n->data.list->idx; i++ )
- {
- rb_ary_store( v, i, syck_seq_read( n, i ) );
- }
- break;
-
- case syck_map_kind:
- rb_iv_set(obj, "@kind", sym_map);
- v = rb_hash_new();
- for ( i = 0; i < n->data.pairs->idx; i++ )
- {
- VALUE key = syck_node_transform( syck_map_read( n, map_key, i ) );
- VALUE val = rb_ary_new();
- rb_ary_push(val, syck_map_read( n, map_key, i ));
- rb_ary_push(val, syck_map_read( n, map_value, i ));
-
- rb_hash_aset( v, key, val );
- }
- break;
- }
-
- bonus = (struct parser_xtra *)p->bonus;
- if ( bonus->taint) OBJ_TAINT( obj );
- if ( bonus->proc != 0 ) rb_funcall(bonus->proc, s_call, 1, v);
-
- rb_iv_set(obj, "@value", v);
- rb_hash_aset(bonus->data, INT2FIX(RHASH(bonus->data)->tbl->num_entries), obj);
- return obj;
-}
-
-/*
- * handles merging of an array of hashes
- * (see http://www.yaml.org/type/merge/)
- */
-VALUE
-syck_merge_i( entry, hsh )
- VALUE entry, hsh;
-{
- if ( rb_obj_is_kind_of( entry, rb_cHash ) )
- {
- rb_funcall( hsh, s_update, 1, entry );
- }
- return Qnil;
-}
-
-/*
- * build a syck node from a Ruby VALUE
- */
-SyckNode *
-rb_new_syck_node( obj, type_id )
- VALUE obj, type_id;
-{
- long i = 0;
- SyckNode *n = NULL;
-
- if (rb_respond_to(obj, s_to_str))
- {
- StringValue(obj); /* possible conversion */
- n = syck_alloc_str();
- n->data.str->ptr = RSTRING(obj)->ptr;
- n->data.str->len = RSTRING(obj)->len;
- }
- else if ( rb_obj_is_kind_of( obj, rb_cArray ) )
- {
- n = syck_alloc_seq();
- for ( i = 0; i < RARRAY(obj)->len; i++ )
- {
- syck_seq_add(n, rb_ary_entry(obj, i));
- }
- }
- else if ( rb_obj_is_kind_of( obj, rb_cHash ) )
- {
- VALUE keys;
- n = syck_alloc_map();
- keys = rb_funcall( obj, s_keys, 0 );
- for ( i = 0; i < RARRAY(keys)->len; i++ )
- {
- VALUE key = rb_ary_entry(keys, i);
- syck_map_add(n, key, rb_hash_aref(obj, key));
- }
- }
-
- if ( n!= NULL && rb_respond_to( type_id, s_to_str ) )
- {
- StringValue(type_id);
- n->type_id = syck_strndup( RSTRING(type_id)->ptr, RSTRING(type_id)->len );
- }
-
- return n;
-}
-
-/*
- * default handler for ruby.yaml.org types
- */
-int
-yaml_org_handler( n, ref )
- SyckNode *n;
- VALUE *ref;
-{
- char *type_id = n->type_id;
- int transferred = 0;
- long i = 0;
- VALUE obj = Qnil;
-
- switch (n->kind)
- {
- case syck_str_kind:
- transferred = 1;
- if ( type_id == NULL || strcmp( type_id, "str" ) == 0 )
- {
- obj = rb_str_new( n->data.str->ptr, n->data.str->len );
- }
- else if ( strcmp( type_id, "null" ) == 0 )
- {
- obj = Qnil;
- }
- else if ( strcmp( type_id, "binary" ) == 0 )
- {
- VALUE arr;
- obj = rb_str_new( n->data.str->ptr, n->data.str->len );
- rb_funcall( obj, s_tr_bang, 2, rb_str_new2( "\n\t " ), rb_str_new2( "" ) );
- arr = rb_funcall( obj, s_unpack, 1, rb_str_new2( "m" ) );
- obj = rb_ary_shift( arr );
- }
- else if ( strcmp( type_id, "bool#yes" ) == 0 )
- {
- obj = Qtrue;
- }
- else if ( strcmp( type_id, "bool#no" ) == 0 )
- {
- obj = Qfalse;
- }
- else if ( strcmp( type_id, "int#hex" ) == 0 )
- {
- obj = rb_cstr2inum( n->data.str->ptr, 16 );
- }
- else if ( strcmp( type_id, "int#oct" ) == 0 )
- {
- obj = rb_cstr2inum( n->data.str->ptr, 8 );
- }
- else if ( strncmp( type_id, "int", 3 ) == 0 )
- {
- syck_str_blow_away_commas( n );
- obj = rb_cstr2inum( n->data.str->ptr, 10 );
- }
- else if ( strcmp( type_id, "float#nan" ) == 0 )
- {
- obj = rb_float_new( S_nan() );
- }
- else if ( strcmp( type_id, "float#inf" ) == 0 )
- {
- obj = rb_float_new( S_inf() );
- }
- else if ( strcmp( type_id, "float#neginf" ) == 0 )
- {
- obj = rb_float_new( -S_inf() );
- }
- else if ( strncmp( type_id, "float", 5 ) == 0 )
- {
- double f;
- syck_str_blow_away_commas( n );
- f = strtod( n->data.str->ptr, NULL );
- obj = rb_float_new( f );
- }
- else if ( strcmp( type_id, "timestamp#iso8601" ) == 0 )
- {
- obj = rb_syck_mktime( n->data.str->ptr );
- }
- else if ( strcmp( type_id, "timestamp#spaced" ) == 0 )
- {
- obj = rb_syck_mktime( n->data.str->ptr );
- }
- else if ( strcmp( type_id, "timestamp#ymd" ) == 0 )
- {
- char *ptr = n->data.str->ptr;
- VALUE year, mon, day;
-
- /* Year*/
- ptr[4] = '\0';
- year = INT2FIX(strtol(ptr, NULL, 10));
-
- /* Month*/
- ptr += 4;
- while ( !ISDIGIT( *ptr ) ) ptr++;
- mon = INT2FIX(strtol(ptr, NULL, 10));
-
- /* Day*/
- ptr += 2;
- while ( !ISDIGIT( *ptr ) ) ptr++;
- day = INT2FIX(strtol(ptr, NULL, 10));
-
- obj = rb_funcall( cDate, s_new, 3, year, mon, day );
- }
- else if ( strncmp( type_id, "timestamp", 9 ) == 0 )
- {
- obj = rb_syck_mktime( n->data.str->ptr );
- }
- else if ( strncmp( type_id, "merge", 5 ) == 0 )
- {
- obj = rb_funcall( cMergeKey, s_new, 0 );
- }
- else if ( strncmp( type_id, "default", 7 ) == 0 )
- {
- obj = rb_funcall( cDefaultKey, s_new, 0 );
- }
- else
- {
- transferred = 0;
- obj = rb_str_new( n->data.str->ptr, n->data.str->len );
- }
- break;
-
- case syck_seq_kind:
- if ( type_id == NULL || strcmp( type_id, "seq" ) == 0 )
- {
- transferred = 1;
- }
- obj = rb_ary_new2( n->data.list->idx );
- for ( i = 0; i < n->data.list->idx; i++ )
- {
- rb_ary_store( obj, i, syck_seq_read( n, i ) );
- }
- break;
-
- case syck_map_kind:
- if ( type_id == NULL || strcmp( type_id, "map" ) == 0 )
- {
- transferred = 1;
- }
- obj = rb_hash_new();
- for ( i = 0; i < n->data.pairs->idx; i++ )
- {
- VALUE k = syck_map_read( n, map_key, i );
- VALUE v = syck_map_read( n, map_value, i );
- int skip_aset = 0;
-
- /*
- * Handle merge keys
- */
- if ( rb_obj_is_kind_of( k, cMergeKey ) )
- {
- if ( rb_obj_is_kind_of( v, rb_cHash ) )
- {
- VALUE dup = rb_funcall( v, s_dup, 0 );
- rb_funcall( dup, s_update, 1, obj );
- obj = dup;
- skip_aset = 1;
- }
- else if ( rb_obj_is_kind_of( v, rb_cArray ) )
- {
- VALUE end = rb_ary_pop( v );
- if ( rb_obj_is_kind_of( end, rb_cHash ) )
- {
- VALUE dup = rb_funcall( end, s_dup, 0 );
- v = rb_ary_reverse( v );
- rb_ary_push( v, obj );
- rb_iterate( rb_each, v, syck_merge_i, dup );
- obj = dup;
- skip_aset = 1;
- }
- }
- }
- else if ( rb_obj_is_kind_of( k, cDefaultKey ) )
- {
- rb_funcall( obj, s_default_set, 1, v );
- skip_aset = 1;
- }
-
- if ( ! skip_aset )
- {
- rb_hash_aset( obj, k, v );
- }
- }
- break;
- }
-
- *ref = obj;
- return transferred;
-}
-
-/*
- * {native mode} node handler
- * - Converts data into native Ruby types
- */
-SYMID
-rb_syck_load_handler(p, n)
- SyckParser *p;
- SyckNode *n;
-{
- VALUE obj = Qnil;
- struct parser_xtra *bonus;
-
- /*
- * Attempt common transfers
- */
- int transferred = yaml_org_handler(n, &obj);
- if ( transferred == 0 && n->type_id != NULL )
- {
- obj = rb_funcall( oDefaultLoader, s_transfer, 2, rb_str_new2( n->type_id ), obj );
- }
-
- /*
- * ID already set, let's alter the symbol table to accept the new object
- */
- if (n->id > 0)
- {
- MEMCPY((void *)n->id, (void *)obj, RVALUE, 1);
- MEMZERO((void *)obj, RVALUE, 1);
- obj = n->id;
- }
-
- bonus = (struct parser_xtra *)p->bonus;
- if ( bonus->taint) OBJ_TAINT( obj );
- if ( bonus->proc != 0 ) rb_funcall(bonus->proc, s_call, 1, obj);
-
- rb_hash_aset(bonus->data, INT2FIX(RHASH(bonus->data)->tbl->num_entries), obj);
- return obj;
-}
-
-/*
- * friendly errors.
- */
-void
-rb_syck_err_handler(p, msg)
- SyckParser *p;
- char *msg;
-{
- char *endl = p->cursor;
-
- while ( *endl != '\0' && *endl != '\n' )
- endl++;
-
- endl[0] = '\0';
- rb_raise(rb_eArgError, "%s on line %d, col %d: `%s'",
- msg,
- p->linect,
- p->cursor - p->lineptr,
- p->lineptr);
-}
-
-/*
- * provide bad anchor object to the parser.
- */
-SyckNode *
-rb_syck_bad_anchor_handler(p, a)
- SyckParser *p;
- char *a;
-{
- VALUE anchor_name = rb_str_new2( a );
- SyckNode *badanc = syck_new_map( rb_str_new2( "name" ), anchor_name );
- badanc->type_id = syck_strndup( "tag:ruby.yaml.org,2002:object:YAML::Syck::BadAlias", 53 );
- return badanc;
-}
-
-/*
- * data loaded based on the model requested.
- */
-void
-syck_set_model( parser, input, model )
- SyckParser *parser;
- VALUE input, model;
-{
- if ( model == sym_generic )
- {
- syck_parser_handler( parser, rb_syck_parse_handler );
- syck_parser_implicit_typing( parser, 1 );
- syck_parser_taguri_expansion( parser, 1 );
- }
- else
- {
- syck_parser_handler( parser, rb_syck_load_handler );
- syck_parser_implicit_typing( parser, 1 );
- syck_parser_taguri_expansion( parser, 0 );
- }
- if ( input == sym_bytecode )
- {
- syck_parser_set_input_type( parser, syck_bytecode_utf8 );
- }
- syck_parser_error_handler( parser, rb_syck_err_handler );
- syck_parser_bad_anchor_handler( parser, rb_syck_bad_anchor_handler );
-}
-
-/*
- * mark parser nodes
- */
-static void
-syck_mark_parser(parser)
- SyckParser *parser;
-{
- rb_gc_mark(parser->root);
- rb_gc_mark(parser->root_on_error);
-}
-
-/*
- * YAML::Syck::Parser.new
- */
-VALUE
-syck_parser_new(argc, argv, class)
- int argc;
- VALUE *argv;
- VALUE class;
-{
- VALUE pobj, options, init_argv[1];
- SyckParser *parser = syck_new_parser();
-
- rb_scan_args(argc, argv, "01", &options);
- pobj = Data_Wrap_Struct( class, syck_mark_parser, syck_free_parser, parser );
-
- syck_parser_set_root_on_error( parser, Qnil );
-
- if ( ! rb_obj_is_instance_of( options, rb_cHash ) )
- {
- options = rb_hash_new();
- }
- init_argv[0] = options;
- rb_obj_call_init(pobj, 1, init_argv);
- return pobj;
-}
-
-/*
- * YAML::Syck::Parser.initialize( options )
- */
-static VALUE
-syck_parser_initialize( self, options )
- VALUE self, options;
-{
- rb_iv_set(self, "@options", options);
- return self;
-}
-
-/*
- * YAML::Syck::Parser.bufsize = Integer
- */
-static VALUE
-syck_parser_bufsize_set( self, size )
- VALUE self, size;
-{
- SyckParser *parser;
-
- Data_Get_Struct(self, SyckParser, parser);
- if ( rb_respond_to( size, s_to_i ) ) {
- parser->bufsize = NUM2INT(rb_funcall(size, s_to_i, 0));
- }
- return self;
-}
-
-/*
- * YAML::Syck::Parser.bufsize => Integer
- */
-static VALUE
-syck_parser_bufsize_get( self )
- VALUE self;
-{
- SyckParser *parser;
-
- Data_Get_Struct(self, SyckParser, parser);
- return INT2FIX( parser->bufsize );
-}
-
-/*
- * YAML::Syck::Parser.load( IO or String )
- */
-VALUE
-syck_parser_load(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE port, proc, model, input;
- SyckParser *parser;
- struct parser_xtra bonus;
- volatile VALUE hash; /* protect from GC */
-
- rb_scan_args(argc, argv, "11", &port, &proc);
- Data_Get_Struct(self, SyckParser, parser);
-
- input = rb_hash_aref( rb_iv_get( self, "@options" ), sym_input );
- model = rb_hash_aref( rb_iv_get( self, "@options" ), sym_model );
- syck_set_model( parser, input, model );
-
- bonus.taint = syck_parser_assign_io(parser, port);
- bonus.data = hash = rb_hash_new();
- if ( NIL_P( proc ) ) bonus.proc = 0;
- else bonus.proc = proc;
-
- parser->bonus = (void *)&bonus;
-
- return syck_parse( parser );
-}
-
-/*
- * YAML::Syck::Parser.load_documents( IO or String ) { |doc| }
- */
-VALUE
-syck_parser_load_documents(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE port, proc, v, input, model;
- SyckParser *parser;
- struct parser_xtra bonus;
- volatile VALUE hash;
-
- rb_scan_args(argc, argv, "1&", &port, &proc);
- Data_Get_Struct(self, SyckParser, parser);
-
- input = rb_hash_aref( rb_iv_get( self, "@options" ), sym_input );
- model = rb_hash_aref( rb_iv_get( self, "@options" ), sym_model );
- syck_set_model( parser, input, model );
-
- bonus.taint = syck_parser_assign_io(parser, port);
- while ( 1 )
- {
- /* Reset hash for tracking nodes */
- bonus.data = hash = rb_hash_new();
- bonus.proc = 0;
- parser->bonus = (void *)&bonus;
-
- /* Parse a document */
- v = syck_parse( parser );
- if ( parser->eof == 1 )
- {
- break;
- }
-
- /* Pass document to block */
- rb_funcall( proc, s_call, 1, v );
- }
-
- return Qnil;
-}
-
-/*
- * YAML::Syck::Loader.initialize
- */
-static VALUE
-syck_loader_initialize( self )
- VALUE self;
-{
- VALUE families;
-
- rb_iv_set(self, "@families", rb_hash_new() );
- rb_iv_set(self, "@private_types", rb_hash_new() );
- rb_iv_set(self, "@anchors", rb_hash_new() );
- families = rb_iv_get(self, "@families");
-
- rb_hash_aset(families, rb_str_new2( YAML_DOMAIN ), rb_hash_new());
- rb_hash_aset(families, rb_str_new2( RUBY_DOMAIN ), rb_hash_new());
-
- return self;
-}
-
-/*
- * Add type family, used by add_*_type methods.
- */
-VALUE
-syck_loader_add_type_family( self, domain, type_re, proc )
- VALUE self, domain, type_re, proc;
-{
- VALUE families, domain_types;
-
- families = rb_iv_get(self, "@families");
- domain_types = syck_get_hash_aref(families, domain);
- rb_hash_aset( domain_types, type_re, proc );
- return Qnil;
-}
-
-/*
- * YAML::Syck::Loader.add_domain_type
- */
-VALUE
-syck_loader_add_domain_type( argc, argv, self )
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE domain, type_re, proc;
-
- rb_scan_args(argc, argv, "2&", &domain, &type_re, &proc);
- syck_loader_add_type_family( self, domain, type_re, proc );
- return Qnil;
-}
-
-
-/*
- * YAML::Syck::Loader.add_builtin_type
- */
-VALUE
-syck_loader_add_builtin_type( argc, argv, self )
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE type_re, proc;
-
- rb_scan_args(argc, argv, "1&", &type_re, &proc);
- syck_loader_add_type_family( self, rb_str_new2( YAML_DOMAIN ), type_re, proc );
- return Qnil;
-}
-
-/*
- * YAML::Syck::Loader.add_ruby_type
- */
-VALUE
-syck_loader_add_ruby_type( argc, argv, self )
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE type_re, proc;
-
- rb_scan_args(argc, argv, "1&", &type_re, &proc);
- syck_loader_add_type_family( self, rb_str_new2( RUBY_DOMAIN ), type_re, proc );
- return Qnil;
-}
-
-/*
- * YAML::Syck::Loader.add_private_type
- */
-VALUE
-syck_loader_add_private_type( argc, argv, self )
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE type_re, proc, priv_types;
-
- rb_scan_args(argc, argv, "1&", &type_re, &proc);
-
- priv_types = rb_iv_get(self, "@private_types");
- rb_hash_aset( priv_types, type_re, proc );
- return Qnil;
-}
-
-/*
- * YAML::Syck::Loader#detect
- */
-VALUE
-syck_loader_detect_implicit( self, val )
- VALUE self, val;
-{
- char *type_id;
-
- if ( TYPE(val) == T_STRING )
- {
- type_id = syck_match_implicit( RSTRING(val)->ptr, RSTRING(val)->len );
- return rb_str_new2( type_id );
- }
-
- return rb_str_new2( "" );
-}
-
-/*
- * iterator to search a type hash for a match.
- */
-static VALUE
-transfer_find_i(entry, col)
- VALUE entry, col;
-{
- VALUE key = rb_ary_entry( entry, 0 );
- VALUE tid = rb_ary_entry( col, 0 );
- if ( rb_respond_to( key, s_match ) )
- {
- VALUE match = rb_funcall( key, rb_intern("match"), 1, tid );
- if ( ! NIL_P( match ) )
- {
- rb_ary_push( col, rb_ary_entry( entry, 1 ) );
- rb_iter_break();
- }
- }
- return Qnil;
-}
-
-/*
- * YAML::Syck::Loader#transfer
- */
-VALUE
-syck_loader_transfer( self, type, val )
- VALUE self, type, val;
-{
- char *taguri = NULL;
-
- if (NIL_P(type) || !RSTRING(type)->ptr || RSTRING(type)->len == 0)
- {
- /*
- * Empty transfer, detect type
- */
- if ( TYPE(val) == T_STRING )
- {
- StringValue(val);
- taguri = syck_match_implicit( RSTRING(val)->ptr, RSTRING(val)->len );
- taguri = syck_taguri( YAML_DOMAIN, taguri, strlen( taguri ) );
- }
- }
- else
- {
- taguri = syck_type_id_to_uri( RSTRING(type)->ptr );
- }
-
- if ( taguri != NULL )
- {
- int transferred = 0;
- VALUE scheme, name, type_hash, domain = Qnil, type_proc = Qnil;
- VALUE type_uri = rb_str_new2( taguri );
- VALUE str_taguri = rb_str_new2("tag");
- VALUE str_xprivate = rb_str_new2("x-private");
- VALUE str_yaml_domain = rb_str_new2(YAML_DOMAIN);
- VALUE parts = rb_str_split( type_uri, ":" );
-
- scheme = rb_ary_shift( parts );
-
- if ( rb_str_cmp( scheme, str_xprivate ) == 0 )
- {
- name = rb_ary_join( parts, rb_str_new2( ":" ) );
- type_hash = rb_iv_get(self, "@private_types");
- }
- else if ( rb_str_cmp( scheme, str_taguri ) == 0 )
- {
- domain = rb_ary_shift( parts );
- name = rb_ary_join( parts, rb_str_new2( ":" ) );
- type_hash = rb_iv_get(self, "@families");
- type_hash = rb_hash_aref(type_hash, domain);
-
- /*
- * Route yaml.org types through the transfer
- * method here in this extension
- */
- if ( rb_str_cmp( domain, str_yaml_domain ) == 0 )
- {
- SyckNode *n = rb_new_syck_node(val, name);
- if ( n != NULL )
- {
- transferred = yaml_org_handler(n, &val);
- S_FREE( n );
- }
- }
-
- }
- else
- {
- rb_raise(rb_eTypeError, "invalid typing scheme: %s given",
- scheme);
- }
-
- if ( ! transferred )
- {
- if ( rb_obj_is_instance_of( type_hash, rb_cHash ) )
- {
- type_proc = rb_hash_aref( type_hash, name );
- if ( NIL_P( type_proc ) )
- {
- VALUE col = rb_ary_new();
- rb_ary_push( col, name );
- rb_iterate(rb_each, type_hash, transfer_find_i, col );
- name = rb_ary_shift( col );
- type_proc = rb_ary_shift( col );
- }
- }
-
- if ( rb_respond_to( type_proc, s_call ) )
- {
- val = rb_funcall(type_proc, s_call, 2, type_uri, val);
- }
- else if ( rb_str_cmp( scheme, str_xprivate ) == 0 )
- {
- val = rb_funcall(cPrivateType, s_new, 2, name, val);
- }
- else
- {
- val = rb_funcall(cDomainType, s_new, 3, domain, name, val);
- }
- transferred = 1;
- }
- }
-
- return val;
-}
-
-/*
- * YAML::Syck::BadAlias.initialize
- */
-VALUE
-syck_badalias_initialize( self, val )
- VALUE self, val;
-{
- rb_iv_set( self, "@name", val );
- return self;
-}
-
-/*
- * YAML::Syck::DomainType.initialize
- */
-VALUE
-syck_domaintype_initialize( self, domain, type_id, val )
- VALUE self, type_id, val;
-{
- rb_iv_set( self, "@domain", domain );
- rb_iv_set( self, "@type_id", type_id );
- rb_iv_set( self, "@value", val );
- return self;
-}
-
-/*
- * YAML::Syck::PrivateType.initialize
- */
-VALUE
-syck_privatetype_initialize( self, type_id, val )
- VALUE self, type_id, val;
-{
- rb_iv_set( self, "@type_id", type_id );
- rb_iv_set( self, "@value", val );
- return self;
-}
-
-/*
- * YAML::Syck::Node.initialize
- */
-VALUE
-syck_node_initialize( self, type_id, val )
- VALUE self, type_id, val;
-{
- rb_iv_set( self, "@type_id", type_id );
- rb_iv_set( self, "@value", val );
- return self;
-}
-
-VALUE
-syck_node_thash( entry, t )
- VALUE entry, t;
-{
- VALUE key, val;
- key = rb_ary_entry( entry, 0 );
- val = syck_node_transform( rb_ary_entry( rb_ary_entry( entry, 1 ), 1 ) );
- rb_hash_aset( t, key, val );
- return Qnil;
-}
-
-VALUE
-syck_node_ahash( entry, t )
- VALUE entry, t;
-{
- VALUE val = syck_node_transform( entry );
- rb_ary_push( t, val );
- return Qnil;
-}
-
-/*
- * YAML::Syck::Node.transform
- */
-VALUE
-syck_node_transform( self )
- VALUE self;
-{
- VALUE t = Qnil;
- VALUE type_id = rb_iv_get( self, "@type_id" );
- VALUE val = rb_iv_get( self, "@value" );
- if ( rb_obj_is_instance_of( val, rb_cHash ) )
- {
- t = rb_hash_new();
- rb_iterate( rb_each, val, syck_node_thash, t );
- }
- else if ( rb_obj_is_instance_of( val, rb_cArray ) )
- {
- t = rb_ary_new();
- rb_iterate( rb_each, val, syck_node_ahash, t );
- }
- else
- {
- t = val;
- }
- return rb_funcall( oDefaultLoader, s_transfer, 2, type_id, t );
-}
-
-/*
- * Handle output from the emitter
- */
-void
-rb_syck_output_handler( emitter, str, len )
- SyckEmitter *emitter;
- char *str;
- long len;
-{
- VALUE dest = (VALUE)emitter->bonus;
- if ( rb_respond_to( dest, s_to_str ) ) {
- rb_str_cat( dest, str, len );
- } else {
- rb_io_write( dest, rb_str_new( str, len ) );
- }
-}
-
-/*
- * Mark emitter values.
- */
-static void
-syck_mark_emitter(emitter)
- SyckEmitter *emitter;
-{
- rb_gc_mark(emitter->ignore_id);
- if ( emitter->bonus != NULL )
- {
- rb_gc_mark( (VALUE)emitter->bonus );
- }
-}
-
-/*
- * YAML::Syck::Emitter.new
- */
-VALUE
-syck_emitter_new(argc, argv, class)
- int argc;
- VALUE *argv;
- VALUE class;
-{
- VALUE pobj, options, init_argv[1];
- SyckEmitter *emitter = syck_new_emitter();
- syck_emitter_ignore_id( emitter, Qnil );
- syck_emitter_handler( emitter, rb_syck_output_handler );
-
- emitter->bonus = (void *)rb_str_new2( "" );
-
- rb_scan_args(argc, argv, "01", &options);
- pobj = Data_Wrap_Struct( class, syck_mark_emitter, syck_free_emitter, emitter );
-
- if ( ! rb_obj_is_instance_of( options, rb_cHash ) )
- {
- options = rb_hash_new();
- }
- init_argv[0] = options;
- rb_obj_call_init(pobj, 1, init_argv);
- return pobj;
-}
-
-/*
- * YAML::Syck::Emitter.initialize( options )
- */
-static VALUE
-syck_emitter_initialize( self, options )
- VALUE self, options;
-{
- rb_iv_set(self, "@options", options);
- return self;
-}
-
-/*
- * YAML::Syck::Emitter.level
- */
-VALUE
-syck_emitter_level_m( self )
- VALUE self;
-{
- SyckEmitter *emitter;
-
- Data_Get_Struct(self, SyckEmitter, emitter);
- return LONG2NUM( emitter->level );
-}
-
-/*
- * YAML::Syck::Emitter.flush
- */
-VALUE
-syck_emitter_flush_m( self )
- VALUE self;
-{
- SyckEmitter *emitter;
-
- Data_Get_Struct(self, SyckEmitter, emitter);
- syck_emitter_flush( emitter, 0 );
- return self;
-}
-
-/*
- * YAML::Syck::Emitter.write( str )
- */
-VALUE
-syck_emitter_write_m( self, str )
- VALUE self, str;
-{
- SyckEmitter *emitter;
-
- Data_Get_Struct(self, SyckEmitter, emitter);
- syck_emitter_write( emitter, RSTRING(str)->ptr, RSTRING(str)->len );
- return self;
-}
-
-/*
- * YAML::Syck::Emitter.simple( str )
- */
-VALUE
-syck_emitter_simple_write( self, str )
- VALUE self, str;
-{
- SyckEmitter *emitter;
-
- Data_Get_Struct(self, SyckEmitter, emitter);
- syck_emitter_simple( emitter, RSTRING(str)->ptr, RSTRING(str)->len );
- return self;
-}
-
-/*
- * YAML::Syck::Emitter.start_object( object_id )
- */
-VALUE
-syck_emitter_start_object( self, oid )
- VALUE self, oid;
-{
- char *anchor_name;
- SyckEmitter *emitter;
-
- Data_Get_Struct(self, SyckEmitter, emitter);
- anchor_name = syck_emitter_start_obj( emitter, oid );
-
- if ( anchor_name == NULL )
- {
- return Qnil;
- }
-
- return rb_str_new2( anchor_name );
-}
-
-/*
- * YAML::Syck::Emitter.end_object( object_id )
- */
-VALUE
-syck_emitter_end_object( self, oid )
- VALUE self, oid;
-{
- SyckEmitter *emitter;
-
- Data_Get_Struct(self, SyckEmitter, emitter);
- syck_emitter_end_obj( emitter );
-
- if ( emitter->level < 0 )
- {
- syck_emitter_flush( emitter, 0 );
- }
- return (VALUE)emitter->bonus;
-}
-
-/*
- * Initialize Syck extension
- */
-void
-Init_syck()
-{
- VALUE rb_yaml = rb_define_module( "YAML" );
- VALUE rb_syck = rb_define_module_under( rb_yaml, "Syck" );
- rb_define_const( rb_syck, "VERSION", rb_str_new2( SYCK_VERSION ) );
- rb_define_module_function( rb_syck, "compile", rb_syck_compile, 1 );
-
- /*
- * Global symbols
- */
- s_new = rb_intern("new");
- s_utc = rb_intern("utc");
- s_at = rb_intern("at");
- s_to_f = rb_intern("to_f");
- s_to_i = rb_intern("to_i");
- s_read = rb_intern("read");
- s_anchors = rb_intern("anchors");
- s_binmode = rb_intern("binmode");
- s_transfer = rb_intern("transfer");
- s_call = rb_intern("call");
- s_update = rb_intern("update");
- s_dup = rb_intern("dup");
- s_default_set = rb_intern("default=");
- s_match = rb_intern("match");
- s_keys = rb_intern("keys");
- s_to_str = rb_intern("to_str");
- s_tr_bang = rb_intern("tr!");
- s_unpack = rb_intern("unpack");
-
- sym_model = ID2SYM(rb_intern("Model"));
- sym_generic = ID2SYM(rb_intern("Generic"));
- sym_input = ID2SYM(rb_intern("Input"));
- sym_bytecode = ID2SYM(rb_intern("Bytecode"));
- sym_map = ID2SYM(rb_intern("map"));
- sym_scalar = ID2SYM(rb_intern("scalar"));
- sym_seq = ID2SYM(rb_intern("seq"));
-
- /*
- * Load Date module
- */
- rb_require( "date" );
- cDate = rb_funcall( rb_cObject, rb_intern("const_get"), 1, rb_str_new2("Date") );
-
- /*
- * Define YAML::Syck::Loader class
- */
- cLoader = rb_define_class_under( rb_syck, "Loader", rb_cObject );
- rb_define_attr( cLoader, "families", 1, 1 );
- rb_define_attr( cLoader, "private_types", 1, 1 );
- rb_define_attr( cLoader, "anchors", 1, 1 );
- rb_define_method( cLoader, "initialize", syck_loader_initialize, 0 );
- rb_define_method( cLoader, "add_domain_type", syck_loader_add_domain_type, -1 );
- rb_define_method( cLoader, "add_builtin_type", syck_loader_add_builtin_type, -1 );
- rb_define_method( cLoader, "add_ruby_type", syck_loader_add_ruby_type, -1 );
- rb_define_method( cLoader, "add_private_type", syck_loader_add_private_type, -1 );
- rb_define_method( cLoader, "bufsize=", syck_parser_bufsize_set, 1 );
- rb_define_method( cLoader, "bufsize", syck_parser_bufsize_get, 0 );
- rb_define_method( cLoader, "detect_implicit", syck_loader_detect_implicit, 1 );
- rb_define_method( cLoader, "transfer", syck_loader_transfer, 2 );
-
- oDefaultLoader = rb_funcall( cLoader, rb_intern( "new" ), 0 );
- rb_define_const( rb_syck, "DefaultLoader", oDefaultLoader );
-
- /*
- * Define YAML::Syck::Parser class
- */
- cParser = rb_define_class_under( rb_syck, "Parser", rb_cObject );
- rb_define_attr( cParser, "options", 1, 1 );
- rb_define_singleton_method( cParser, "new", syck_parser_new, -1 );
- rb_define_method(cParser, "initialize", syck_parser_initialize, 1);
- rb_define_method(cParser, "load", syck_parser_load, -1);
- rb_define_method(cParser, "load_documents", syck_parser_load_documents, -1);
-
- /*
- * Define YAML::Syck::Node class
- */
- cNode = rb_define_class_under( rb_syck, "Node", rb_cObject );
- rb_define_attr( cNode, "kind", 1, 1 );
- rb_define_attr( cNode, "type_id", 1, 1 );
- rb_define_attr( cNode, "value", 1, 1 );
- rb_define_attr( cNode, "anchor", 1, 1 );
- rb_define_method( cNode, "initialize", syck_node_initialize, 2);
- rb_define_method( cNode, "transform", syck_node_transform, 0);
-
- /*
- * Define YAML::Syck::PrivateType class
- */
- cPrivateType = rb_define_class_under( rb_syck, "PrivateType", rb_cObject );
- rb_define_attr( cPrivateType, "type_id", 1, 1 );
- rb_define_attr( cPrivateType, "value", 1, 1 );
- rb_define_method( cPrivateType, "initialize", syck_privatetype_initialize, 2);
-
- /*
- * Define YAML::Syck::DomainType class
- */
- cDomainType = rb_define_class_under( rb_syck, "DomainType", rb_cObject );
- rb_define_attr( cDomainType, "domain", 1, 1 );
- rb_define_attr( cDomainType, "type_id", 1, 1 );
- rb_define_attr( cDomainType, "value", 1, 1 );
- rb_define_method( cDomainType, "initialize", syck_domaintype_initialize, 3);
-
- /*
- * Define YAML::Syck::BadAlias class
- */
- cBadAlias = rb_define_class_under( rb_syck, "BadAlias", rb_cObject );
- rb_define_attr( cBadAlias, "name", 1, 1 );
- rb_define_method( cBadAlias, "initialize", syck_badalias_initialize, 1);
-
- /*
- * Define YAML::Syck::MergeKey class
- */
- cMergeKey = rb_define_class_under( rb_syck, "MergeKey", rb_cObject );
-
- /*
- * Define YAML::Syck::DefaultKey class
- */
- cDefaultKey = rb_define_class_under( rb_syck, "DefaultKey", rb_cObject );
-
- /*
- * Define YAML::Syck::Emitter class
- */
- cEmitter = rb_define_class_under( rb_syck, "Emitter", rb_cObject );
- rb_define_singleton_method( cEmitter, "new", syck_emitter_new, -1 );
- rb_define_method( cEmitter, "initialize", syck_emitter_initialize, 1 );
- rb_define_method( cEmitter, "level", syck_emitter_level_m, 0 );
- rb_define_method( cEmitter, "write", syck_emitter_write_m, 1 );
- rb_define_method( cEmitter, "<<", syck_emitter_write_m, 1 );
- rb_define_method( cEmitter, "simple", syck_emitter_simple_write, 1 );
- rb_define_method( cEmitter, "flush", syck_emitter_flush_m, 0 );
- rb_define_method( cEmitter, "start_object", syck_emitter_start_object, 1 );
- rb_define_method( cEmitter, "end_object", syck_emitter_end_object, 0 );
-}
-