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.c160
1 files changed, 144 insertions, 16 deletions
diff --git a/ext/syck/rubyext.c b/ext/syck/rubyext.c
index c260009897..98f1bfb58f 100644
--- a/ext/syck/rubyext.c
+++ b/ext/syck/rubyext.c
@@ -12,12 +12,23 @@
#include <sys/types.h>
#include <time.h>
+typedef struct RVALUE {
+ union {
+ struct RBasic basic;
+ struct RObject object;
+ struct RClass klass;
+ struct RArray array;
+ struct RHash hash;
+ struct RStruct rstruct;
+ } as;
+} RVALUE;
+
#define RUBY_DOMAIN "ruby.yaml.org,2002"
-static ID s_utc, s_at, s_to_f, s_read, s_binmode;
+static ID s_new, s_utc, s_at, s_to_f, s_read, s_binmode, s_call, s_transfer;
static VALUE sym_model, sym_generic;
static VALUE sym_scalar, sym_seq, sym_map;
-VALUE cParser, cLoader, cNode, oDefaultLoader;
+VALUE cDate, cParser, cLoader, cNode, cPrivateType, cDomainType, cBadAlias, oDefaultLoader;
/*
* my private collection of numerical oddities.
@@ -32,6 +43,7 @@ static VALUE syck_node_transform( VALUE );
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 *));
struct parser_xtra {
VALUE data; // Borrowed this idea from marshal.c to fix [ruby-dev:8067] problem
@@ -249,7 +261,7 @@ rb_syck_parse_handler(p, n)
bonus = (struct parser_xtra *)p->bonus;
if ( bonus->proc != 0 )
{
- rb_funcall(bonus->proc, rb_intern("call"), 1, v);
+ rb_funcall(bonus->proc, s_call, 1, v);
}
rb_iv_set(obj, "@value", v);
@@ -333,9 +345,28 @@ rb_syck_load_handler(p, n)
}
else if ( strcmp( n->type_id, "timestamp#ymd" ) == 0 )
{
- S_REALLOC_N( n->data.str->ptr, char, 22 );
- strcat( n->data.str->ptr, "t00:00:00Z" );
- obj = rb_syck_mktime( n->data.str->ptr );
+ 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 );
+
+ // S_REALLOC_N( n->data.str->ptr, char, 22 );
+ // strcat( n->data.str->ptr, "t00:00:00Z" );
+ // obj = rb_syck_mktime( n->data.str->ptr );
}
else if ( strncmp( n->type_id, "timestamp", 9 ) == 0 )
{
@@ -367,15 +398,25 @@ rb_syck_load_handler(p, n)
break;
}
+ //
+ // 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->proc != 0 )
{
- rb_funcall(bonus->proc, rb_intern("call"), 1, obj);
+ rb_funcall(bonus->proc, s_call, 1, obj);
}
if ( check_transfers == 1 && n->type_id != NULL )
{
- obj = rb_funcall( oDefaultLoader, rb_intern( "transfer" ), 2, rb_str_new2( n->type_id ), obj );
+ obj = rb_funcall( oDefaultLoader, s_transfer, 2, rb_str_new2( n->type_id ), obj );
}
rb_hash_aset(bonus->data, INT2FIX(RHASH(bonus->data)->tbl->num_entries), obj);
@@ -403,6 +444,16 @@ rb_syck_err_handler(p, msg)
p->lineptr);
}
+SyckNode *
+rb_syck_bad_anchor_handler(p, a)
+ SyckParser *p;
+ char *a;
+{
+ SyckNode *badanc = syck_new_map( rb_str_new2( "name" ), rb_str_new2( a ) );
+ badanc->type_id = syck_strndup( "taguri:ruby.yaml.org,2002:object:YAML::Syck::BadAlias", 53 );
+ return badanc;
+}
+
/*
* data loaded based on the model requested.
*/
@@ -414,17 +465,17 @@ syck_set_model( parser, model )
if ( model == sym_generic )
{
syck_parser_handler( parser, rb_syck_parse_handler );
- syck_parser_error_handler( parser, rb_syck_err_handler );
syck_parser_implicit_typing( parser, 1 );
syck_parser_taguri_expansion( parser, 1 );
}
else
{
syck_parser_handler( parser, rb_syck_load_handler );
- syck_parser_error_handler( parser, rb_syck_err_handler );
syck_parser_implicit_typing( parser, 1 );
syck_parser_taguri_expansion( parser, 0 );
}
+ syck_parser_error_handler( parser, rb_syck_err_handler );
+ syck_parser_bad_anchor_handler( parser, rb_syck_bad_anchor_handler );
}
/*
@@ -561,7 +612,7 @@ syck_parser_load_documents(argc, argv, self)
}
/* Pass document to block */
- rb_funcall( proc, rb_intern("call"), 1, v );
+ rb_funcall( proc, s_call, 1, v );
}
return Qnil;
@@ -732,7 +783,7 @@ syck_loader_transfer( self, type, val )
if ( taguri != NULL )
{
- VALUE scheme, name, type_hash, type_proc;
+ VALUE scheme, domain, name, type_hash, type_proc = Qnil;
VALUE type_uri = rb_str_new2( taguri );
VALUE str_taguri = rb_str_new2("taguri");
VALUE str_xprivate = rb_str_new2("x-private");
@@ -748,7 +799,7 @@ syck_loader_transfer( self, type, val )
}
else if ( rb_str_cmp( scheme, str_taguri ) == 0 )
{
- VALUE domain = rb_ary_shift( parts );
+ 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);
@@ -773,9 +824,17 @@ syck_loader_transfer( self, type, val )
// rb_funcall(rb_mKernel, rb_intern("p"), 2, name, type_proc);
}
- if ( rb_respond_to( type_proc, rb_intern("call") ) )
+ if ( rb_respond_to( type_proc, s_call ) )
{
- val = rb_funcall(type_proc, rb_intern("call"), 2, type_uri, val);
+ 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);
}
}
@@ -783,6 +842,42 @@ syck_loader_transfer( self, type, 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
@@ -838,7 +933,7 @@ syck_node_transform( self )
{
t = val;
}
- return rb_funcall( oDefaultLoader, rb_intern( "transfer" ), 2, type_id, t );
+ return rb_funcall( oDefaultLoader, s_transfer, 2, type_id, t );
}
/*
@@ -854,17 +949,26 @@ Init_syck()
//
// 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_read = rb_intern("read");
s_binmode = rb_intern("binmode");
+ s_transfer = rb_intern("transfer");
+ s_call = rb_intern("call");
sym_model = ID2SYM(rb_intern("Model"));
sym_generic = ID2SYM(rb_intern("Generic"));
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
//
@@ -902,5 +1006,29 @@ Init_syck()
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);
}