Skip to content
Browse files

ext/ruby/ext/syck/rubyext.c:

- const_find, now locating class constants correctly.
- YAML::Object class for loaded objects which have no corresponding class.
- No anchors on simple strings.
- Outputing of domain and private types and anchors properly.
  • Loading branch information...
1 parent d96d505 commit 5debcaad95cd5d4ba5b35ed2ef5fd674fba10426 _why committed May 19, 2005
Showing with 197 additions and 44 deletions.
  1. +27 −0 CHANGELOG
  2. +36 −2 README.EXT
  3. +83 −19 ext/ruby/ext/syck/rubyext.c
  4. +1 −1 ext/ruby/lib/yaml/basenode.rb
  5. +4 −2 ext/ruby/lib/yaml/rubytypes.rb
  6. +26 −12 ext/ruby/lib/yaml/types.rb
  7. +20 −8 lib/emitter.c
View
27 CHANGELOG
@@ -1,4 +1,31 @@
--- %YAML:1.0
+- version: 0.56
+ date: 2005-05-16
+ changes:
+ ext/ruby/ext/syck/rubyext.c:
+ - const_find, now locating class constants correctly.
+ - YAML::Object class for loaded objects which have no corresponding class.
+ - No anchors on simple strings.
+ - Outputing of domain and private types and anchors properly.
+
+- version: 0.55
+ date: 2005-04-14
+ changes:
+ lib/emitter.c:
+ - output inline collections. ensure proper quoting and no blocks in inline collections.
+ - safe indentation of scalar blocks which include YAML document separators.
+
+ lib/syck.h: styles for every type of node now.
+
+ lib/gram.y: restructuring, trying to fix problem with typed seq-in-map shortcut nodes.
+
+ lib/token.re: fixed parsing of inline seq closing char as closing map char and vice versa.
+
+ ext/ruby/lib/yaml/rubytypes.rb: added styling of collections. to_yaml_style for
+ every object in Ruby.
+
+ ext/ruby/ext/syck/rubyext.c: ditto.
+
- version: 0.54
date: 2005-04-07
changes:
View
38 README.EXT
@@ -5,7 +5,7 @@ This is the documentation for libsyck and describes how to extend it.
= Overview =
Syck is designed to take a YAML stream and a symbol table and move
-data between the two. Simply provide callback functions which
+data between the two. Your job is to simply provide callback functions which
understand the symbol table you are keeping.
Syck also includes a simple symbol table implementation.
@@ -407,4 +407,38 @@ become sort of unnecessary.
to build the document.
4. Call syck_emit_flush() to end the document and push the remaining
- document to the IO stream.
+ document to the IO stream. Or continue to add documents to the output
+ stream with syck_emit().
+
+=== Emitter API ===
+
+ See <syck.h> for the layout of SyckEmitter.
+
+ SyckEmitter *
+ syck_new_emitter()
+
+ Creates a new Syck emitter.
+
+ SYMID
+ syck_emitter_mark_node( SyckEmitter *e, st_data_t node )
+
+ Adds an outgoing node to the symbol table, allocating an anchor
+ for it if it has repeated in the document and scanning the type
+ tag for auto-shortcut.
+
+ void
+ syck_output_handler( SyckEmitter *e, SyckOutputHandler out )
+
+ Assigns a callback as the output handler.
+
+ void *out_handler( SyckEmitter *e, char * ptr, long len );
+
+ Receives the emitter object, pointer to the buffer and a count
+ of bytes which should be read from the buffer.
+
+ void
+ syck_emitter_handler( SyckEmitter *e, SyckEmitterHandler
+
+
+ void
+ syck_free_emitter
View
102 ext/ruby/ext/syck/rubyext.c
@@ -60,7 +60,7 @@ static ID s_tags, s_domain, s_kind, s_name, s_options, s_type_id, s_type_id_set,
static VALUE sym_model, sym_generic, sym_input, sym_bytecode;
static VALUE sym_scalar, sym_seq, sym_map;
static VALUE sym_1quote, sym_2quote, sym_fold, sym_literal, sym_plain, sym_inline;
-static VALUE cDate, cNode, cMap, cSeq, cScalar, cOut, cParser, cResolver, cPrivateType, cDomainType, cBadAlias, cDefaultKey, cMergeKey, cEmitter;
+static VALUE cDate, cNode, cMap, cSeq, cScalar, cOut, cParser, cResolver, cPrivateType, cDomainType, cYObject, cBadAlias, cDefaultKey, cMergeKey, cEmitter;
static VALUE oDefaultResolver, oGenericResolver;
/*
@@ -1040,6 +1040,24 @@ syck_set_ivars( vars, obj )
}
/*
+ * YAML::Syck::Resolver#const_find
+ */
+VALUE
+syck_const_find( const_name )
+ VALUE const_name;
+{
+ VALUE tclass = rb_cObject;
+ VALUE tparts = rb_str_split( const_name, "::" );
+ int i = 0;
+ for ( i = 0; i < RARRAY(tparts)->len; i++ ) {
+ VALUE tpart = rb_to_id( rb_ary_entry( tparts, i ) );
+ if ( !rb_const_defined( tclass, tpart ) ) return Qnil;
+ tclass = rb_const_get( tclass, tpart );
+ }
+ return tclass;
+}
+
+/*
* YAML::Syck::Resolver#transfer
*/
VALUE
@@ -1058,7 +1076,6 @@ syck_resolver_transfer( self, type, val )
VALUE tags = rb_attr_get(self, s_tags);
VALUE target_class = rb_hash_aref( tags, type );
VALUE subclass = target_class;
- VALUE sym_sub = Qnil;
VALUE obj = Qnil;
/*
@@ -1090,16 +1107,22 @@ syck_resolver_transfer( self, type, val )
if ( RARRAY(subclass_parts)->len > 0 && rb_respond_to( target_class, s_tag_subclasses ) &&
RTEST( rb_funcall( target_class, s_tag_subclasses, 0 ) ) )
{
+ VALUE subclass_v;
subclass = rb_ary_join( subclass_parts, colon );
subclass = rb_funcall( target_class, s_tag_read_class, 1, subclass );
- sym_sub = rb_to_id( subclass );
- if ( RTEST( rb_const_defined( rb_cObject, sym_sub ) ) )
+ subclass_v = syck_const_find( subclass );
+
+ if ( subclass_v != Qnil )
{
- subclass = rb_const_get( rb_cObject, sym_sub );
+ subclass = subclass_v;
}
- else
+ else if ( rb_cObject == target_class && subclass_v == Qnil )
{
- subclass = rb_define_class( rb_id2name( sym_sub ), rb_cObject );
+ // StringValue(subclass);
+ // printf( "No class: %s\n", RSTRING(subclass)->ptr );
+ target_class = cYObject;
+ type = subclass;
+ subclass = cYObject;
}
}
break;
@@ -1329,6 +1352,18 @@ syck_domaintype_initialize( self, domain, type_id, val )
}
/*
+ * YAML::Object.initialize
+ */
+VALUE
+syck_yobject_initialize( self, klass, ivars )
+ VALUE self, klass, ivars;
+{
+ rb_iv_set( self, "@class", klass );
+ rb_iv_set( self, "@ivars", ivars );
+ return self;
+}
+
+/*
* YAML::PrivateType.initialize
*/
VALUE
@@ -2077,10 +2112,16 @@ syck_out_initialize( self, emitter )
* YAML::Syck::Out::map
*/
VALUE
-syck_out_map( self, type_id, style )
- VALUE self, type_id, style;
+syck_out_map( argc, argv, self )
+ int argc;
+ VALUE *argv;
+ VALUE self;
{
- VALUE map = rb_funcall( cMap, s_new, 3, type_id, rb_hash_new(), style );
+ VALUE type_id, style, map;
+ if (rb_scan_args(argc, argv, "11", &type_id, &style) == 1) {
+ style = Qnil;
+ }
+ map = rb_funcall( cMap, s_new, 3, type_id, rb_hash_new(), style );
syck_out_mark( rb_ivar_get( self, s_emitter ), map );
rb_yield( map );
return map;
@@ -2090,23 +2131,37 @@ syck_out_map( self, type_id, style )
* YAML::Syck::Out::seq
*/
VALUE
-syck_out_seq( self, type_id, style )
- VALUE self, type_id, style;
+syck_out_seq( argc, argv, self )
+ int argc;
+ VALUE *argv;
+ VALUE self;
{
- VALUE seq = rb_funcall( cSeq, s_new, 3, type_id, rb_ary_new(), style );
+ VALUE type_id, style, seq;
+ if (rb_scan_args(argc, argv, "11", &type_id, &style) == 1) {
+ style = Qnil;
+ }
+ seq = rb_funcall( cSeq, s_new, 3, type_id, rb_ary_new(), style );
syck_out_mark( rb_ivar_get( self, s_emitter ), seq );
rb_yield( seq );
return seq;
}
/*
* YAML::Syck::Out::scalar
- */
-VALUE
syck_out_scalar( self, type_id, str, style )
VALUE self, type_id, str, style;
+ */
+VALUE
+syck_out_scalar( argc, argv, self )
+ int argc;
+ VALUE *argv;
+ VALUE self;
{
- VALUE scalar = rb_funcall( cScalar, s_new, 3, type_id, str, style );
+ VALUE type_id, str, style, scalar;
+ if (rb_scan_args(argc, argv, "21", &type_id, &str, &style) == 2) {
+ style = Qnil;
+ }
+ scalar = rb_funcall( cScalar, s_new, 3, type_id, str, style );
syck_out_mark( rb_ivar_get( self, s_emitter ), scalar );
return scalar;
}
@@ -2276,6 +2331,15 @@ Init_syck()
rb_define_method( cDomainType, "initialize", syck_domaintype_initialize, 3);
/*
+ * Define YAML::Object class
+ */
+ cYObject = rb_define_class_under( rb_yaml, "Object", rb_cObject );
+ rb_define_attr( cYObject, "class", 1, 1 );
+ rb_define_attr( cYObject, "ivars", 1, 1 );
+ rb_define_method( cYObject, "initialize", syck_yobject_initialize, 2);
+ rb_define_method( cYObject, "yaml_initialize", syck_yobject_initialize, 2);
+
+ /*
* Define YAML::Syck::BadAlias class
*/
cBadAlias = rb_define_class_under( rb_syck, "BadAlias", rb_cObject );
@@ -2300,9 +2364,9 @@ Init_syck()
cOut = rb_define_class_under( rb_syck, "Out", rb_cObject );
rb_define_attr( cOut, "emitter", 1, 1 );
rb_define_method( cOut, "initialize", syck_out_initialize, 1 );
- rb_define_method( cOut, "map", syck_out_map, 2 );
- rb_define_method( cOut, "seq", syck_out_seq, 2 );
- rb_define_method( cOut, "scalar", syck_out_scalar, 3 );
+ rb_define_method( cOut, "map", syck_out_map, -1 );
+ rb_define_method( cOut, "seq", syck_out_seq, -1 );
+ rb_define_method( cOut, "scalar", syck_out_scalar, -1 );
/*
* Define YAML::Syck::Emitter class
View
2 ext/ruby/lib/yaml/basenode.rb
@@ -25,7 +25,7 @@ def select( ypath_str )
matches.each { |m|
result.push m.last
}
- self.class.new( 'seq', result )
+ YAML.transfer( 'seq', result )
end
end
View
6 ext/ruby/lib/yaml/rubytypes.rb
@@ -158,6 +158,9 @@ def to_yaml( opts = {} )
class String
tag_as "tag:ruby.yaml.org,2002:string"
tag_as "tag:yaml.org,2002:str"
+ def is_complex_yaml?
+ to_yaml_style or not to_yaml_properties.empty? or self =~ /\n.+/
+ end
def is_binary_data?
( self.count( "^ -~", "^\r\n" ) / self.size > 0.3 || self.count( "\x00" ) > 0 )
end
@@ -175,9 +178,8 @@ def String.yaml_new( klass, tag, val )
raise YAML::TypeError, "Invalid String: " + val.inspect
end
end
- def to_yaml_style; nil; end
def to_yaml( opts = {} )
- YAML::quick_emit( object_id, opts ) do |out|
+ YAML::quick_emit( is_complex_yaml? ? object_id : nil, opts ) do |out|
if to_yaml_properties.empty?
out.scalar( taguri, self, to_yaml_style )
else
View
38 ext/ruby/lib/yaml/types.rb
@@ -13,11 +13,10 @@ def self.tag_subclasses?; false; end
attr_accessor :type_id, :value
def initialize( type, val )
@type_id = type; @value = val
+ @value.taguri = "x-private:#{ @type_id }"
end
def to_yaml( opts = {} )
- value = @value.dup
- value.taguri = "x-private:#{ @type_id }"
- value.to_yaml( opts )
+ @value.to_yaml( opts )
end
end
@@ -29,18 +28,33 @@ def self.tag_subclasses?; false; end
attr_accessor :domain, :type_id, :value
def initialize( domain, type, val )
@domain = domain; @type_id = type; @value = val
+ @value.taguri = "tag:#{ @domain }:#{ @type_id }"
end
def to_yaml( opts = {} )
- value = @value.dup
- value.taguri = "tag:#{ @domain }:#{ @type_id }"
- value.to_yaml( opts )
+ @value.to_yaml( opts )
+ end
+ end
+
+ #
+ # Unresolved objects
+ #
+ class Object
+ def self.tag_subclasses?; false; end
+ def to_yaml( opts = {} )
+ YAML::quick_emit( object_id, opts ) do |out|
+ out.map( "tag:ruby.yaml.org,2002:object:#{ @class }", to_yaml_style ) do |map|
+ @ivars.each do |k,v|
+ map.add( k, v )
+ end
+ end
+ end
end
end
#
# YAML Hash class to support comments and defaults
#
- class SpecialHash < Object::Hash
+ class SpecialHash < ::Hash
attr_accessor :default
def inspect
self.default.to_s
@@ -63,7 +77,7 @@ def to_yaml( opts = {} )
#
# Builtin collection: !omap
#
- class Omap < Array
+ class Omap < ::Array
tag_as "tag:yaml.org,2002:omap"
def yaml_initialize( tag, val )
if Array === val
@@ -106,7 +120,7 @@ def is_complex_yaml?
end
def to_yaml( opts = {} )
YAML::quick_emit( self.object_id, opts ) do |out|
- out.seq( taguri ) do |seq|
+ out.seq( taguri, to_yaml_style ) do |seq|
self.each do |v|
seq.add( Hash[ *v ] )
end
@@ -118,7 +132,7 @@ def to_yaml( opts = {} )
#
# Builtin collection: !pairs
#
- class Pairs < Array
+ class Pairs < ::Array
tag_as "tag:yaml.org,2002:pairs"
def yaml_initialize( tag, val )
if Array === val
@@ -156,7 +170,7 @@ def is_complex_yaml?
end
def to_yaml( opts = {} )
YAML::quick_emit( self.object_id, opts ) do |out|
- out.seq( taguri ) do |seq|
+ out.seq( taguri, to_yaml_style ) do |seq|
self.each do |v|
seq.add( Hash[ *v ] )
end
@@ -168,7 +182,7 @@ def to_yaml( opts = {} )
#
# Builtin collection: !set
#
- class Set < Hash
+ class Set < ::Hash
tag_as "tag:yaml.org,2002:set"
end
end
View
28 lib/emitter.c
@@ -491,12 +491,14 @@ void syck_emit_indent( SyckEmitter *e )
{
int i;
SyckLevel *lvl = syck_emitter_current_level( e );
- char *spcs = S_ALLOC_N( char, lvl->spaces + 2 );
+ if ( lvl->spaces >= 0 ) {
+ char *spcs = S_ALLOC_N( char, lvl->spaces + 2 );
- spcs[0] = '\n'; spcs[lvl->spaces + 1] = '\0';
- for ( i = 0; i < lvl->spaces; i++ ) spcs[i+1] = ' ';
- syck_emitter_write( e, spcs, lvl->spaces + 1 );
- free( spcs );
+ spcs[0] = '\n'; spcs[lvl->spaces + 1] = '\0';
+ for ( i = 0; i < lvl->spaces; i++ ) spcs[i+1] = ' ';
+ syck_emitter_write( e, spcs, lvl->spaces + 1 );
+ free( spcs );
+ }
}
/* Clear the scan */
@@ -527,6 +529,8 @@ void syck_emit_indent( SyckEmitter *e )
#define SCAN_FLOWMAP 2048
/* Contains flow seq indicators */
#define SCAN_FLOWSEQ 4096
+/* Contains a valid doc separator */
+#define SCAN_DOCSEP 8192
/*
* Basic printable test for LATIN-1 characters.
@@ -563,6 +567,10 @@ syck_scan_scalar( int req_width, char *cursor, long len )
flags |= SCAN_MANYNL_E;
}
+ /* opening doc sep */
+ if ( len >= 3 && strncmp( cursor, "---", 3 ) == 0 )
+ flags |= SCAN_DOCSEP;
+
/* scan string */
for ( i = 0; i < len; i++ ) {
@@ -575,6 +583,8 @@ syck_scan_scalar( int req_width, char *cursor, long len )
}
else if ( cursor[i] == '\n' ) {
flags |= SCAN_NEWLINE;
+ if ( len - i >= 3 && strncmp( &cursor[i+1], "---", 3 ) == 0 )
+ flags |= SCAN_DOCSEP;
if ( cursor[i+1] == ' ' || cursor[i+1] == '\t' )
flags |= SCAN_INDENTED;
if ( req_width > 0 && i - start > req_width )
@@ -642,7 +652,7 @@ void syck_emit_scalar( SyckEmitter *e, char *tag, enum scalar_style force_style,
len = 1;
}
- scan = syck_scan_scalar( force_indent, str, len );
+ scan = syck_scan_scalar( force_width, str, len );
implicit = syck_match_implicit( str, len );
/* quote strings which default to implicits */
@@ -690,8 +700,10 @@ void syck_emit_scalar( SyckEmitter *e, char *tag, enum scalar_style force_style,
}
}
- if ( force_indent == 0 ) {
- force_indent = e->indent;
+ if ( force_indent > 0 ) {
+ lvl->spaces = parent->spaces + force_indent;
+ } else if ( scan & SCAN_DOCSEP ) {
+ lvl->spaces = parent->spaces + e->indent;
}
/* For now, all ambiguous keys are going to be double-quoted */

0 comments on commit 5debcaa

Please sign in to comment.
Something went wrong with that request. Please try again.