* lib/yaml.rb: reworking YAML::Stream to use the new

emitter.

* lib/yaml/stream.rb: ditto.

* lib/yaml/rubytypes.rb: added Object#yaml_new.

* lib/yaml/tag.rb: the tag_subclasses? method now
  shows up in the class.  allow taguri to be set using an accessor.
  continue support of Object#to_yaml_type.

* ext/syck/rubyext.c: new emitter code.  yaml_new and yaml_initialize
  get called, should they be present.  consolidated all the diaspora of internal
  node types into the family below YAML::Syck::Node -- Map,
  Seq, Scalar -- all of whom are SyckNode structs pointing to
  Ruby data.  moved Object#yaml_new into the node_import and made it the
  default behavior.  the target_class is always called wih yaml_new, prepended
  a parameter, which is the klass.  loaded nodes through GenericResolver show their style.
  new Resolver#tagurize converts type ids to taguris.

* ext/syck/implicit.re: were 'y' and 'n' seriously omitted??

* ext/syck/emitter.c: renovated emitter, walks the tree in advance.
  consolidated redundant block_styles struct into
  the scalar_style struct.  (this means loaded nodes can now
  be sent back to emitter and preserve at least its very basic
  formatting.)

* ext/syck/gram.c: headless documents of any kind allowed.

* ext/syck/node.c: new syck_replace_str methods and syck_empty_*
  methods for rewriting node contents, while keeping the ID
  and other setup info.  added syck_seq_assign.

* ext/syck/syck.h: reflect block_styles and new node functions.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9141 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
why 2005-09-13 03:58:33 +00:00
parent 2007d73102
commit f1827a2faf
20 changed files with 4568 additions and 2765 deletions

View File

@ -1,4 +1,4 @@
/* Generated by re2c 0.9.3 on Fri Aug 13 11:47:50 2004 */ /* Generated by re2c 0.9.3 on Tue Apr 12 20:34:14 2005 */
#line 1 "bytecode.re" #line 1 "bytecode.re"
/* /*
* bytecode.re * bytecode.re
@ -89,7 +89,7 @@ char *get_inline( SyckParser *parser );
#define ENSURE_YAML_IOPEN(last_lvl, lvl_type, to_len, reset) \ #define ENSURE_YAML_IOPEN(last_lvl, lvl_type, to_len, reset) \
if ( last_lvl->spaces < to_len ) \ if ( last_lvl->spaces < to_len ) \
{ \ { \
if ( last_lvl->status == syck_lvl_inline ) \ if ( last_lvl->status == syck_lvl_iseq || last_lvl->status == syck_lvl_imap ) \
{ \ { \
goto Document; \ goto Document; \
} \ } \

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/* A Bison parser, made from gram.y, by GNU bison 1.75. */ /* A Bison parser, made by GNU Bison 1.875d. */
/* Skeleton parser for Yacc-like parsing with Bison, /* Skeleton parser for Yacc-like parsing with Bison,
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc. Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -23,9 +23,6 @@
This special exception was added by the Free Software Foundation This special exception was added by the Free Software Foundation
in version 1.24 of Bison. */ in version 1.24 of Bison. */
#ifndef BISON_Y_TAB_H
# define BISON_Y_TAB_H
/* Tokens. */ /* Tokens. */
#ifndef YYTOKENTYPE #ifndef YYTOKENTYPE
# define YYTOKENTYPE # define YYTOKENTYPE
@ -62,20 +59,21 @@
#ifndef YYSTYPE #if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
#line 33 "gram.y" #line 35 "gram.y"
typedef union { typedef union YYSTYPE {
SYMID nodeId; SYMID nodeId;
SyckNode *nodeData; SyckNode *nodeData;
char *name; char *name;
} yystype; } YYSTYPE;
/* Line 1281 of /usr/local/share/bison/yacc.c. */ /* Line 1285 of yacc.c. */
#line 74 "y.tab.h" #line 71 "gram.h"
# define YYSTYPE yystype # define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
# define YYSTYPE_IS_TRIVIAL 1
#endif #endif
#endif /* not BISON_Y_TAB_H */

View File

@ -31,6 +31,9 @@ syck_hdlr_add_node( SyckParser *p, SyckNode *n )
SyckNode * SyckNode *
syck_hdlr_add_anchor( SyckParser *p, char *a, SyckNode *n ) syck_hdlr_add_anchor( SyckParser *p, char *a, SyckNode *n )
{ {
char *atmp = NULL;
SyckNode *ntmp = NULL;
n->anchor = a; n->anchor = a;
if ( p->bad_anchors != NULL ) if ( p->bad_anchors != NULL )
{ {
@ -48,6 +51,13 @@ syck_hdlr_add_anchor( SyckParser *p, char *a, SyckNode *n )
{ {
p->anchors = st_init_strtable(); p->anchors = st_init_strtable();
} }
if ( st_lookup( p->anchors, (st_data_t)a, (st_data_t *)&ntmp ) )
{
if ( ntmp != (void *)1 )
{
syck_free_node( ntmp );
}
}
st_insert( p->anchors, (st_data_t)a, (st_data_t)n ); st_insert( p->anchors, (st_data_t)a, (st_data_t)n );
return n; return n;
} }
@ -55,10 +65,19 @@ syck_hdlr_add_anchor( SyckParser *p, char *a, SyckNode *n )
void void
syck_hdlr_remove_anchor( SyckParser *p, char *a ) syck_hdlr_remove_anchor( SyckParser *p, char *a )
{ {
char *atmp = a;
SyckNode *ntmp;
if ( p->anchors == NULL ) if ( p->anchors == NULL )
{ {
p->anchors = st_init_strtable(); p->anchors = st_init_strtable();
} }
if ( st_delete( p->anchors, (st_data_t *)&atmp, (st_data_t *)&ntmp ) )
{
if ( ntmp != (void *)1 )
{
syck_free_node( ntmp );
}
}
st_insert( p->anchors, (st_data_t)a, (st_data_t)1 ); st_insert( p->anchors, (st_data_t)a, (st_data_t)1 );
} }

View File

@ -1,4 +1,4 @@
/* Generated by re2c 0.9.3 on Fri Aug 13 11:47:51 2004 */ /* Generated by re2c 0.9.3 on Wed Mar 30 08:27:25 2005 */
#line 1 "implicit.re" #line 1 "implicit.re"
/* /*
* implicit.re * implicit.re
@ -36,6 +36,7 @@ try_tag_implicit( SyckNode *n, int taguri )
tid = "map"; tid = "map";
break; break;
} }
if ( n->type_id != NULL ) S_FREE( n->type_id );
if ( taguri == 1 ) if ( taguri == 1 )
{ {
n->type_id = syck_taguri( YAML_DOMAIN, tid, strlen( tid ) ); n->type_id = syck_taguri( YAML_DOMAIN, tid, strlen( tid ) );
@ -94,7 +95,7 @@ yy2: ++YYCURSOR;
if((yych = *YYCURSOR) <= '\000') goto yy6; if((yych = *YYCURSOR) <= '\000') goto yy6;
goto yy3; goto yy3;
yy3: yy3:
#line 122 "implicit.re" #line 123 "implicit.re"
{ return "str"; } { return "str"; }
#line 51 "<stdout>" #line 51 "<stdout>"
yy4: yyaccept = 0; yy4: yyaccept = 0;
@ -115,7 +116,7 @@ yy5: yyaccept = 0;
yy6: ++YYCURSOR; yy6: ++YYCURSOR;
goto yy7; goto yy7;
yy7: yy7:
#line 84 "implicit.re" #line 85 "implicit.re"
{ return "null"; } { return "null"; }
#line 72 "<stdout>" #line 72 "<stdout>"
yy8: yyaccept = 0; yy8: yyaccept = 0;
@ -273,13 +274,13 @@ yy25: YYCURSOR = YYMARKER;
yy26: ++YYCURSOR; yy26: ++YYCURSOR;
goto yy27; goto yy27;
yy27: yy27:
#line 120 "implicit.re" #line 121 "implicit.re"
{ return "merge"; } { return "merge"; }
#line 230 "<stdout>" #line 230 "<stdout>"
yy28: ++YYCURSOR; yy28: ++YYCURSOR;
goto yy29; goto yy29;
yy29: yy29:
#line 118 "implicit.re" #line 119 "implicit.re"
{ return "default"; } { return "default"; }
#line 236 "<stdout>" #line 236 "<stdout>"
yy30: yych = *++YYCURSOR; yy30: yych = *++YYCURSOR;
@ -320,7 +321,7 @@ yy36: yych = *++YYCURSOR;
yy37: ++YYCURSOR; yy37: ++YYCURSOR;
goto yy38; goto yy38;
yy38: yy38:
#line 104 "implicit.re" #line 105 "implicit.re"
{ return "float#inf"; } { return "float#inf"; }
#line 277 "<stdout>" #line 277 "<stdout>"
yy39: yych = *++YYCURSOR; yy39: yych = *++YYCURSOR;
@ -344,7 +345,7 @@ yy42: yych = *++YYCURSOR;
yy43: ++YYCURSOR; yy43: ++YYCURSOR;
goto yy44; goto yy44;
yy44: yy44:
#line 108 "implicit.re" #line 109 "implicit.re"
{ return "float#nan"; } { return "float#nan"; }
#line 301 "<stdout>" #line 301 "<stdout>"
yy45: yych = *++YYCURSOR; yy45: yych = *++YYCURSOR;
@ -426,7 +427,7 @@ yy51: switch(yych){
yy52: ++YYCURSOR; yy52: ++YYCURSOR;
goto yy53; goto yy53;
yy53: yy53:
#line 96 "implicit.re" #line 97 "implicit.re"
{ return "int"; } { return "int"; }
#line 386 "<stdout>" #line 386 "<stdout>"
yy54: ++YYCURSOR; yy54: ++YYCURSOR;
@ -450,7 +451,7 @@ yy55: switch(yych){
yy56: ++YYCURSOR; yy56: ++YYCURSOR;
goto yy57; goto yy57;
yy57: yy57:
#line 98 "implicit.re" #line 99 "implicit.re"
{ return "float#fix"; } { return "float#fix"; }
#line 411 "<stdout>" #line 411 "<stdout>"
yy58: ++YYCURSOR; yy58: ++YYCURSOR;
@ -500,7 +501,7 @@ yy63: switch(yych){
yy64: ++YYCURSOR; yy64: ++YYCURSOR;
goto yy65; goto yy65;
yy65: yy65:
#line 100 "implicit.re" #line 101 "implicit.re"
{ return "float#exp"; } { return "float#exp"; }
#line 463 "<stdout>" #line 463 "<stdout>"
yy66: ++YYCURSOR; yy66: ++YYCURSOR;
@ -552,13 +553,13 @@ yy69: switch(yych){
yy70: ++YYCURSOR; yy70: ++YYCURSOR;
goto yy71; goto yy71;
yy71: yy71:
#line 94 "implicit.re" #line 95 "implicit.re"
{ return "int#base60"; } { return "int#base60"; }
#line 518 "<stdout>" #line 518 "<stdout>"
yy72: ++YYCURSOR; yy72: ++YYCURSOR;
goto yy73; goto yy73;
yy73: yy73:
#line 102 "implicit.re" #line 103 "implicit.re"
{ return "float#base60"; } { return "float#base60"; }
#line 524 "<stdout>" #line 524 "<stdout>"
yy74: yych = *++YYCURSOR; yy74: yych = *++YYCURSOR;
@ -661,7 +662,7 @@ yy81: yych = *++YYCURSOR;
yy82: ++YYCURSOR; yy82: ++YYCURSOR;
goto yy83; goto yy83;
yy83: yy83:
#line 110 "implicit.re" #line 111 "implicit.re"
{ return "timestamp#ymd"; } { return "timestamp#ymd"; }
#line 627 "<stdout>" #line 627 "<stdout>"
yy84: yych = *++YYCURSOR; yy84: yych = *++YYCURSOR;
@ -878,7 +879,7 @@ yy104: yych = *++YYCURSOR;
yy105: ++YYCURSOR; yy105: ++YYCURSOR;
goto yy106; goto yy106;
yy106: yy106:
#line 114 "implicit.re" #line 115 "implicit.re"
{ return "timestamp#spaced"; } { return "timestamp#spaced"; }
#line 847 "<stdout>" #line 847 "<stdout>"
yy107: yych = *++YYCURSOR; yy107: yych = *++YYCURSOR;
@ -1063,7 +1064,7 @@ yy122: yych = *++YYCURSOR;
yy123: ++YYCURSOR; yy123: ++YYCURSOR;
goto yy124; goto yy124;
yy124: yy124:
#line 112 "implicit.re" #line 113 "implicit.re"
{ return "timestamp#iso8601"; } { return "timestamp#iso8601"; }
#line 1033 "<stdout>" #line 1033 "<stdout>"
yy125: yych = *++YYCURSOR; yy125: yych = *++YYCURSOR;
@ -1301,13 +1302,13 @@ yy146: switch(yych){
yy147: ++YYCURSOR; yy147: ++YYCURSOR;
goto yy148; goto yy148;
yy148: yy148:
#line 90 "implicit.re" #line 91 "implicit.re"
{ return "int#hex"; } { return "int#hex"; }
#line 1275 "<stdout>" #line 1275 "<stdout>"
yy149: ++YYCURSOR; yy149: ++YYCURSOR;
goto yy150; goto yy150;
yy150: yy150:
#line 92 "implicit.re" #line 93 "implicit.re"
{ return "int#oct"; } { return "int#oct"; }
#line 1281 "<stdout>" #line 1281 "<stdout>"
yy151: ++YYCURSOR; yy151: ++YYCURSOR;
@ -1406,7 +1407,7 @@ yy163: yych = *++YYCURSOR;
yy164: ++YYCURSOR; yy164: ++YYCURSOR;
goto yy165; goto yy165;
yy165: yy165:
#line 106 "implicit.re" #line 107 "implicit.re"
{ return "float#neginf"; } { return "float#neginf"; }
#line 1381 "<stdout>" #line 1381 "<stdout>"
yy166: yych = *++YYCURSOR; yy166: yych = *++YYCURSOR;
@ -1446,7 +1447,7 @@ yy172: yych = *++YYCURSOR;
yy173: ++YYCURSOR; yy173: ++YYCURSOR;
goto yy174; goto yy174;
yy174: yy174:
#line 88 "implicit.re" #line 89 "implicit.re"
{ return "bool#no"; } { return "bool#no"; }
#line 1421 "<stdout>" #line 1421 "<stdout>"
yy175: yych = *++YYCURSOR; yy175: yych = *++YYCURSOR;
@ -1490,7 +1491,7 @@ yy182: yych = *++YYCURSOR;
yy183: ++YYCURSOR; yy183: ++YYCURSOR;
goto yy184; goto yy184;
yy184: yy184:
#line 86 "implicit.re" #line 87 "implicit.re"
{ return "bool#yes"; } { return "bool#yes"; }
#line 1465 "<stdout>" #line 1465 "<stdout>"
yy185: yych = *++YYCURSOR; yy185: yych = *++YYCURSOR;
@ -1577,11 +1578,36 @@ yy201: ++YYCURSOR;
default: goto yy25; default: goto yy25;
} }
} }
#line 124 "implicit.re" #line 125 "implicit.re"
} }
/* Remove ending fragment and compare types */
int
syck_tagcmp( char *tag1, char *tag2 )
{
if ( tag1 == tag2 ) return 1;
if ( tag1 == NULL || tag2 == NULL ) return 0;
else {
int i;
char *othorpe;
char *tmp1 = syck_strndup( tag1, strlen( tag1 ) );
char *tmp2 = syck_strndup( tag2, strlen( tag2 ) );
othorpe = strstr( tmp1, "#" );
if ( othorpe != NULL ) {
othorpe[0] = '\0';
}
othorpe = strstr( tmp2, "#" );
if ( othorpe != NULL ) {
othorpe[0] = '\0';
}
i = strcmp( tmp1, tmp2 );
S_FREE( tmp1 ); S_FREE( tmp2 );
return i;
}
}
char * char *
syck_type_id_to_uri( char *type_id ) syck_type_id_to_uri( char *type_id )
{ {
@ -1737,7 +1763,7 @@ yy205: yyaccept = 0;
default: goto yy206; default: goto yy206;
} }
yy206: yy206:
#line 176 "implicit.re" #line 202 "implicit.re"
{ return syck_taguri( YAML_DOMAIN, type_id, strlen( type_id ) ); } { return syck_taguri( YAML_DOMAIN, type_id, strlen( type_id ) ); }
#line 1700 "<stdout>" #line 1700 "<stdout>"
yy207: yyaccept = 0; yy207: yyaccept = 0;
@ -1811,7 +1837,7 @@ yy207: yyaccept = 0;
yy208: ++YYCURSOR; yy208: ++YYCURSOR;
goto yy209; goto yy209;
yy209: yy209:
#line 150 "implicit.re" #line 176 "implicit.re"
{ return syck_xprivate( type_id + 1, strlen( type_id ) - 1 ); } { return syck_xprivate( type_id + 1, strlen( type_id ) - 1 ); }
#line 1774 "<stdout>" #line 1774 "<stdout>"
yy210: yyaccept = 0; yy210: yyaccept = 0;
@ -2107,7 +2133,7 @@ yy217: ++YYCURSOR;
yy218: ++YYCURSOR; yy218: ++YYCURSOR;
goto yy219; goto yy219;
yy219: yy219:
#line 152 "implicit.re" #line 178 "implicit.re"
{ char *domain = S_ALLOC_N( char, ( YYCURSOR - type_id ) + 15 ); { char *domain = S_ALLOC_N( char, ( YYCURSOR - type_id ) + 15 );
char *uri; char *uri;
@ -2325,7 +2351,7 @@ yy228: yych = *++YYCURSOR;
yy229: ++YYCURSOR; yy229: ++YYCURSOR;
goto yy230; goto yy230;
yy230: yy230:
#line 165 "implicit.re" #line 191 "implicit.re"
{ char *domain = S_ALLOC_N( char, YYCURSOR - type_id ); { char *domain = S_ALLOC_N( char, YYCURSOR - type_id );
char *uri; char *uri;
@ -2454,7 +2480,7 @@ yy243: yych = *++YYCURSOR;
yy244: ++YYCURSOR; yy244: ++YYCURSOR;
goto yy245; goto yy245;
yy245: yy245:
#line 148 "implicit.re" #line 174 "implicit.re"
{ return type_id; } { return type_id; }
#line 2422 "<stdout>" #line 2422 "<stdout>"
yy246: yych = *++YYCURSOR; yy246: yych = *++YYCURSOR;
@ -2901,7 +2927,7 @@ yy263: yych = *++YYCURSOR;
yy264: ++YYCURSOR; yy264: ++YYCURSOR;
goto yy265; goto yy265;
yy265: yy265:
#line 146 "implicit.re" #line 172 "implicit.re"
{ return type_id; } { return type_id; }
#line 2874 "<stdout>" #line 2874 "<stdout>"
yy266: yych = *++YYCURSOR; yy266: yych = *++YYCURSOR;
@ -2958,8 +2984,7 @@ yy270: ++YYCURSOR;
default: goto yy204; default: goto yy204;
} }
} }
#line 178 "implicit.re" #line 204 "implicit.re"
} }

View File

@ -33,9 +33,15 @@ syck_free_node( SyckNode *n )
{ {
syck_free_members( n ); syck_free_members( n );
if ( n->type_id != NULL ) if ( n->type_id != NULL )
{
S_FREE( n->type_id ); S_FREE( n->type_id );
n->type_id = NULL;
}
if ( n->anchor != NULL ) if ( n->anchor != NULL )
{
S_FREE( n->anchor ); S_FREE( n->anchor );
n->anchor = NULL;
}
S_FREE( n ); S_FREE( n );
} }
@ -46,6 +52,7 @@ syck_alloc_map()
struct SyckMap *m; struct SyckMap *m;
m = S_ALLOC( struct SyckMap ); m = S_ALLOC( struct SyckMap );
m->style = map_none;
m->idx = 0; m->idx = 0;
m->capa = ALLOC_CT; m->capa = ALLOC_CT;
m->keys = S_ALLOC_N( SYMID, m->capa ); m->keys = S_ALLOC_N( SYMID, m->capa );
@ -64,6 +71,7 @@ syck_alloc_seq()
struct SyckSeq *s; struct SyckSeq *s;
s = S_ALLOC( struct SyckSeq ); s = S_ALLOC( struct SyckSeq );
s->style = seq_none;
s->idx = 0; s->idx = 0;
s->capa = ALLOC_CT; s->capa = ALLOC_CT;
s->items = S_ALLOC_N( SYMID, s->capa ); s->items = S_ALLOC_N( SYMID, s->capa );
@ -112,6 +120,28 @@ syck_new_str2( char *str, long len, enum scalar_style style )
return n; return n;
} }
void
syck_replace_str( SyckNode *n, char *str, enum scalar_style style )
{
return syck_replace_str2( n, str, strlen( str ), style );
}
void
syck_replace_str2( SyckNode *n, char *str, long len, enum scalar_style style )
{
if ( n->data.str != NULL )
{
S_FREE( n->data.str->ptr );
n->data.str->ptr = NULL;
n->data.str->len = 0;
}
n->data.str->ptr = S_ALLOC_N( char, len + 1 );
n->data.str->len = len;
n->data.str->style = style;
memcpy( n->data.str->ptr, str, len );
n->data.str->ptr[len] = '\0';
}
void void
syck_str_blow_away_commas( SyckNode *n ) syck_str_blow_away_commas( SyckNode *n )
{ {
@ -148,6 +178,22 @@ syck_new_map( SYMID key, SYMID value )
return n; return n;
} }
void
syck_map_empty( SyckNode *n )
{
struct SyckMap *m;
ASSERT( n != NULL );
ASSERT( n->data.list != NULL );
S_FREE( n->data.pairs->keys );
S_FREE( n->data.pairs->values );
m = n->data.pairs;
m->idx = 0;
m->capa = ALLOC_CT;
m->keys = S_ALLOC_N( SYMID, m->capa );
m->values = S_ALLOC_N( SYMID, m->capa );
}
void void
syck_map_add( SyckNode *map, SYMID key, SYMID value ) syck_map_add( SyckNode *map, SYMID key, SYMID value )
{ {
@ -257,6 +303,20 @@ syck_new_seq( SYMID value )
return n; return n;
} }
void
syck_seq_empty( SyckNode *n )
{
struct SyckSeq *s;
ASSERT( n != NULL );
ASSERT( n->data.list != NULL );
S_FREE( n->data.list->items );
s = n->data.list;
s->idx = 0;
s->capa = ALLOC_CT;
s->items = S_ALLOC_N( SYMID, s->capa );
}
void void
syck_seq_add( SyckNode *arr, SYMID value ) syck_seq_add( SyckNode *arr, SYMID value )
{ {
@ -285,6 +345,17 @@ syck_seq_count( SyckNode *seq )
return seq->data.list->idx; return seq->data.list->idx;
} }
void
syck_seq_assign( SyckNode *seq, long idx, SYMID id )
{
struct SyckSeq *s;
ASSERT( map != NULL );
s = seq->data.list;
ASSERT( m != NULL );
s->items[idx] = id;
}
SYMID SYMID
syck_seq_read( SyckNode *seq, long idx ) syck_seq_read( SyckNode *seq, long idx )
{ {

File diff suppressed because it is too large Load Diff

View File

@ -208,15 +208,6 @@ syck_st_free_nodes( char *key, SyckNode *n, char *arg )
void void
syck_st_free( SyckParser *p ) syck_st_free( SyckParser *p )
{ {
/*
* Free the adhoc symbol table
*/
if ( p->syms != NULL )
{
st_free_table( p->syms );
p->syms = NULL;
}
/* /*
* Free the anchor tables * Free the anchor tables
*/ */
@ -238,6 +229,15 @@ syck_st_free( SyckParser *p )
void void
syck_free_parser( SyckParser *p ) syck_free_parser( SyckParser *p )
{ {
/*
* Free the adhoc symbol table
*/
if ( p->syms != NULL )
{
st_free_table( p->syms );
p->syms = NULL;
}
/* /*
* Free tables, levels * Free tables, levels
*/ */

View File

@ -13,7 +13,7 @@
#define SYCK_YAML_MAJOR 1 #define SYCK_YAML_MAJOR 1
#define SYCK_YAML_MINOR 0 #define SYCK_YAML_MINOR 0
#define SYCK_VERSION "0.45" #define SYCK_VERSION "0.55"
#define YAML_DOMAIN "yaml.org,2002" #define YAML_DOMAIN "yaml.org,2002"
#include <stdio.h> #include <stdio.h>
@ -63,12 +63,16 @@ extern "C" {
#define BLOCK_FOLD 10 #define BLOCK_FOLD 10
#define BLOCK_LIT 20 #define BLOCK_LIT 20
#define BLOCK_PLAIN 30 #define BLOCK_PLAIN 30
#define NL_CHOMP 130 #define NL_CHOMP 40
#define NL_KEEP 140 #define NL_KEEP 50
/* /*
* Node definitions * Node definitions
*/ */
#ifndef ST_DATA_T_DEFINED
typedef long st_data_t;
#endif
#define SYMID unsigned long #define SYMID unsigned long
typedef struct _syck_node SyckNode; typedef struct _syck_node SyckNode;
@ -84,12 +88,23 @@ enum map_part {
map_value map_value
}; };
enum map_style {
map_none,
map_inline
};
enum seq_style {
seq_none,
seq_inline
};
enum scalar_style { enum scalar_style {
scalar_none, scalar_none,
scalar_plain,
scalar_1quote, scalar_1quote,
scalar_2quote, scalar_2quote,
scalar_block scalar_fold,
scalar_literal,
scalar_plain
}; };
/* /*
@ -107,6 +122,7 @@ struct _syck_node {
union { union {
/* Storage for map data */ /* Storage for map data */
struct SyckMap { struct SyckMap {
enum map_style style;
SYMID *keys; SYMID *keys;
SYMID *values; SYMID *values;
long capa; long capa;
@ -114,6 +130,7 @@ struct _syck_node {
} *pairs; } *pairs;
/* Storage for sequence data */ /* Storage for sequence data */
struct SyckSeq { struct SyckSeq {
enum seq_style style;
SYMID *items; SYMID *items;
long capa; long capa;
long idx; long idx;
@ -163,9 +180,13 @@ enum syck_level_status {
syck_lvl_map, syck_lvl_map,
syck_lvl_block, syck_lvl_block,
syck_lvl_str, syck_lvl_str,
syck_lvl_inline, syck_lvl_iseq,
syck_lvl_imap,
syck_lvl_end, syck_lvl_end,
syck_lvl_pause syck_lvl_pause,
syck_lvl_anctag,
syck_lvl_mapx,
syck_lvl_seqx
}; };
/* /*
@ -186,9 +207,16 @@ struct _syck_str {
}; };
struct _syck_level { struct _syck_level {
/* Indent */
int spaces; int spaces;
/* Counts nodes emitted at this level, useful for parsing
* keys and pairs in bytecode */
int ncount; int ncount;
/* Does node have anchors or tags? */
int anctag;
/* Domain prefixing at the given level */
char *domain; char *domain;
/* Keeps a node status */
enum syck_level_status status; enum syck_level_status status;
}; };
@ -231,6 +259,7 @@ struct _syck_parser {
SyckLevel *levels; SyckLevel *levels;
int lvl_idx; int lvl_idx;
int lvl_capa; int lvl_capa;
/* Pointer for extension's use */
void *bonus; void *bonus;
}; };
@ -241,6 +270,7 @@ typedef struct _syck_emitter SyckEmitter;
typedef struct _syck_emitter_node SyckEmitterNode; typedef struct _syck_emitter_node SyckEmitterNode;
typedef void (*SyckOutputHandler)(SyckEmitter *, char *, long); typedef void (*SyckOutputHandler)(SyckEmitter *, char *, long);
typedef void (*SyckEmitterHandler)(SyckEmitter *, st_data_t);
enum doc_stage { enum doc_stage {
doc_open, doc_open,
@ -248,20 +278,12 @@ enum doc_stage {
doc_processing doc_processing
}; };
enum block_styles {
block_arbitrary,
block_fold,
block_literal
};
/* /*
* Emitter struct * Emitter struct
*/ */
struct _syck_emitter { struct _syck_emitter {
/* Headerless doc flag */ /* Headerless doc flag */
int headless; int headless;
/* Sequence map shortcut flag */
int seq_map;
/* Force header? */ /* Force header? */
int use_header; int use_header;
/* Force version? */ /* Force version? */
@ -275,7 +297,7 @@ struct _syck_emitter {
/* Best width on folded scalars */ /* Best width on folded scalars */
int best_width; int best_width;
/* Use literal[1] or folded[2] blocks on all text? */ /* Use literal[1] or folded[2] blocks on all text? */
enum block_styles block_style; enum scalar_style style;
/* Stage of written document */ /* Stage of written document */
enum doc_stage stage; enum doc_stage stage;
/* Level counter */ /* Level counter */
@ -285,15 +307,21 @@ struct _syck_emitter {
/* Object ignore ID */ /* Object ignore ID */
SYMID ignore_id; SYMID ignore_id;
/* Symbol table for anchors */ /* Symbol table for anchors */
st_table *markers, *anchors; st_table *markers, *anchors, *anchored;
/* Custom buffer size */ /* Custom buffer size */
size_t bufsize; size_t bufsize;
/* Buffer */ /* Buffer */
char *buffer, *marker; char *buffer, *marker;
/* Absolute position of the buffer */ /* Absolute position of the buffer */
long bufpos; long bufpos;
/* Handler for emitter nodes */
SyckEmitterHandler emitter_handler;
/* Handler for output */ /* Handler for output */
SyckOutputHandler handler; SyckOutputHandler output_handler;
/* Levels of indentation */
SyckLevel *levels;
int lvl_idx;
int lvl_capa;
/* Pointer for extension's use */ /* Pointer for extension's use */
void *bonus; void *bonus;
}; };
@ -320,6 +348,7 @@ SyckNode *syck_hdlr_get_anchor( SyckParser *, char * );
void syck_add_transfer( char *, SyckNode *, int ); void syck_add_transfer( char *, SyckNode *, int );
char *syck_xprivate( char *, int ); char *syck_xprivate( char *, int );
char *syck_taguri( char *, char *, int ); char *syck_taguri( char *, char *, int );
int syck_tagcmp( char *, char * );
int syck_add_sym( SyckParser *, char * ); int syck_add_sym( SyckParser *, char * );
int syck_lookup_sym( SyckParser *, SYMID, char ** ); int syck_lookup_sym( SyckParser *, SYMID, char ** );
int syck_try_implicit( SyckNode * ); int syck_try_implicit( SyckNode * );
@ -336,20 +365,38 @@ long syck_io_str_read( char *, SyckIoStr *, long, long );
char *syck_base64enc( char *, long ); char *syck_base64enc( char *, long );
char *syck_base64dec( char *, long ); char *syck_base64dec( char *, long );
SyckEmitter *syck_new_emitter(); SyckEmitter *syck_new_emitter();
SYMID syck_emitter_mark_node( SyckEmitter *, st_data_t );
void syck_emitter_ignore_id( SyckEmitter *, SYMID ); void syck_emitter_ignore_id( SyckEmitter *, SYMID );
void syck_emitter_handler( SyckEmitter *, SyckOutputHandler ); void syck_output_handler( SyckEmitter *, SyckOutputHandler );
void syck_emitter_handler( SyckEmitter *, SyckEmitterHandler );
void syck_free_emitter( SyckEmitter * ); void syck_free_emitter( SyckEmitter * );
void syck_emitter_clear( SyckEmitter * ); void syck_emitter_clear( SyckEmitter * );
void syck_emitter_simple( SyckEmitter *, char *, long );
void syck_emitter_write( SyckEmitter *, char *, long ); void syck_emitter_write( SyckEmitter *, char *, long );
void syck_emitter_escape( SyckEmitter *, char *, long );
void syck_emitter_flush( SyckEmitter *, long ); void syck_emitter_flush( SyckEmitter *, long );
char *syck_emitter_start_obj( SyckEmitter *, SYMID ); void syck_emit( SyckEmitter *, st_data_t );
void syck_emitter_end_obj( SyckEmitter * ); void syck_emit_scalar( SyckEmitter *, char *, enum scalar_style, int, int, char, char *, long );
void syck_emit_1quoted( SyckEmitter *, int, char *, long );
void syck_emit_2quoted( SyckEmitter *, int, char *, long );
void syck_emit_folded( SyckEmitter *, int, char, char *, long );
void syck_emit_literal( SyckEmitter *, char, char *, long );
void syck_emit_seq( SyckEmitter *, char *, enum seq_style );
void syck_emit_item( SyckEmitter *, st_data_t );
void syck_emit_map( SyckEmitter *, char *, enum map_style );
void syck_emit_end( SyckEmitter * );
void syck_emit_tag( SyckEmitter *, char *, char * );
void syck_emit_indent( SyckEmitter * );
SyckLevel *syck_emitter_current_level( SyckEmitter * );
SyckLevel *syck_emitter_parent_level( SyckEmitter * );
void syck_emitter_pop_level( SyckEmitter * );
void syck_emitter_add_level( SyckEmitter *, int, enum syck_level_status );
void syck_emitter_reset_levels( SyckEmitter * );
SyckParser *syck_new_parser(); SyckParser *syck_new_parser();
void syck_free_parser( SyckParser * ); void syck_free_parser( SyckParser * );
void syck_parser_set_root_on_error( SyckParser *, SYMID ); void syck_parser_set_root_on_error( SyckParser *, SYMID );
void syck_parser_implicit_typing( SyckParser *, int ); void syck_parser_implicit_typing( SyckParser *, int );
void syck_parser_taguri_expansion( SyckParser *, int ); void syck_parser_taguri_expansion( SyckParser *, int );
int syck_scan_scalar( int, char *, long );
void syck_parser_handler( SyckParser *, SyckNodeHandler ); void syck_parser_handler( SyckParser *, SyckNodeHandler );
void syck_parser_error_handler( SyckParser *, SyckErrorHandler ); void syck_parser_error_handler( SyckParser *, SyckErrorHandler );
void syck_parser_bad_anchor_handler( SyckParser *, SyckBadAnchorHandler ); void syck_parser_bad_anchor_handler( SyckParser *, SyckBadAnchorHandler );
@ -362,7 +409,6 @@ void syck_parser_pop_level( SyckParser * );
void free_any_io( SyckParser * ); void free_any_io( SyckParser * );
long syck_parser_read( SyckParser * ); long syck_parser_read( SyckParser * );
long syck_parser_readlen( SyckParser *, long ); long syck_parser_readlen( SyckParser *, long );
void syck_parser_init( SyckParser *, int );
SYMID syck_parse( SyckParser * ); SYMID syck_parse( SyckParser * );
void syck_default_error_handler( SyckParser *, char * ); void syck_default_error_handler( SyckParser *, char * );
SYMID syck_yaml2byte_handler( SyckParser *, SyckNode * ); SYMID syck_yaml2byte_handler( SyckParser *, SyckNode * );
@ -378,30 +424,29 @@ void syck_free_node( SyckNode * );
void syck_free_members( SyckNode * ); void syck_free_members( SyckNode * );
SyckNode *syck_new_str( char *, enum scalar_style ); SyckNode *syck_new_str( char *, enum scalar_style );
SyckNode *syck_new_str2( char *, long, enum scalar_style ); SyckNode *syck_new_str2( char *, long, enum scalar_style );
void syck_replace_str( SyckNode *, char *, enum scalar_style );
void syck_replace_str2( SyckNode *, char *, long, enum scalar_style );
void syck_str_blow_away_commas( SyckNode * ); void syck_str_blow_away_commas( SyckNode * );
char *syck_str_read( SyckNode * ); char *syck_str_read( SyckNode * );
SyckNode *syck_new_map( SYMID, SYMID ); SyckNode *syck_new_map( SYMID, SYMID );
void syck_map_empty( SyckNode * );
void syck_map_add( SyckNode *, SYMID, SYMID ); void syck_map_add( SyckNode *, SYMID, SYMID );
SYMID syck_map_read( SyckNode *, enum map_part, long ); SYMID syck_map_read( SyckNode *, enum map_part, long );
void syck_map_assign( SyckNode *, enum map_part, long, SYMID ); void syck_map_assign( SyckNode *, enum map_part, long, SYMID );
long syck_map_count( SyckNode * ); long syck_map_count( SyckNode * );
void syck_map_update( SyckNode *, SyckNode * ); void syck_map_update( SyckNode *, SyckNode * );
SyckNode *syck_new_seq( SYMID ); SyckNode *syck_new_seq( SYMID );
void syck_seq_empty( SyckNode * );
void syck_seq_add( SyckNode *, SYMID ); void syck_seq_add( SyckNode *, SYMID );
void syck_seq_assign( SyckNode *, long, SYMID );
SYMID syck_seq_read( SyckNode *, long ); SYMID syck_seq_read( SyckNode *, long );
long syck_seq_count( SyckNode * ); long syck_seq_count( SyckNode * );
void apply_seq_in_map( SyckParser *, SyckNode * );
/* /*
* Lexer prototypes * Lexer prototypes
*/ */
void syckerror( char * ); void syckerror( char * );
#ifndef ST_DATA_T_DEFINED
typedef long st_data_t;
#endif
#if defined(__cplusplus) #if defined(__cplusplus)
} /* extern "C" { */ } /* extern "C" { */
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/* /*
* ybext.c * yaml2byte.c
* *
* $Author$ * $Author$
* $Date$ * $Date$

View File

@ -6,8 +6,10 @@
# Author:: why the lucky stiff # Author:: why the lucky stiff
# #
require 'stringio'
require 'yaml/error'
require 'yaml/syck' require 'yaml/syck'
require 'yaml/loader' require 'yaml/tag'
require 'yaml/stream' require 'yaml/stream'
# == YAML # == YAML
@ -73,7 +75,7 @@ require 'yaml/stream'
# ruby_obj == test_obj # ruby_obj == test_obj
# # => true # # => true
# #
# To register your custom types with the global loader, use +add_domain_type+. # To register your custom types with the global resolver, use +add_domain_type+.
# #
# YAML::add_domain_type( "your-site.com,2004", "widget" ) do |type, val| # YAML::add_domain_type( "your-site.com,2004", "widget" ) do |type, val|
# Widget.new( val ) # Widget.new( val )
@ -81,9 +83,21 @@ require 'yaml/stream'
# #
module YAML module YAML
@@parser = YAML::Syck::Parser Resolver = YAML::Syck::Resolver
@@loader = YAML::Syck::DefaultLoader DefaultResolver = YAML::Syck::DefaultResolver
@@emitter = YAML::Syck::Emitter DefaultResolver.use_types_at( @@tagged_classes )
GenericResolver = YAML::Syck::GenericResolver
Parser = YAML::Syck::Parser
Emitter = YAML::Syck::Emitter
# Returns a new default parser
def YAML.parser; Parser.new.set_resolver( YAML.resolver ); end
# Returns a new generic parser
def YAML.generic_parser; Parser.new.set_resolver( GenericResolver ); end
# Returns the default resolver
def YAML.resolver; DefaultResolver; end
# Returns a new default emitter
def YAML.emitter; Emitter.new.set_resolver( YAML.resolver ); end
# #
# Converts _obj_ to YAML and writes the YAML result to _io_. # Converts _obj_ to YAML and writes the YAML result to _io_.
@ -99,9 +113,8 @@ module YAML
# #=> "--- :locked" # #=> "--- :locked"
# #
def YAML.dump( obj, io = nil ) def YAML.dump( obj, io = nil )
io ||= "" obj.to_yaml( io || io2 = StringIO.new )
io << obj.to_yaml io || ( io2.rewind; io2.read )
io
end end
# #
@ -116,7 +129,7 @@ module YAML
# #=> :locked # #=> :locked
# #
def YAML.load( io ) def YAML.load( io )
yp = @@parser.new.load( io ) yp = parser.load( io )
end end
# #
@ -153,13 +166,13 @@ module YAML
# #
# Can also load from a string. # Can also load from a string.
# #
# YAML.load( "--- :locked" ) # YAML.parse( "--- :locked" )
# #=> #<YAML::Syck::Node:0x82edddc # #=> #<YAML::Syck::Node:0x82edddc
# @type_id="tag:ruby.yaml.org,2002:sym", # @type_id="tag:ruby.yaml.org,2002:sym",
# @value=":locked", @kind=:scalar> # @value=":locked", @kind=:scalar>
# #
def YAML.parse( io ) def YAML.parse( io )
yp = @@parser.new( :Model => :Generic ).load( io ) yp = generic_parser.load( io )
end end
# #
@ -200,7 +213,7 @@ module YAML
# end # end
# #
def YAML.each_document( io, &block ) def YAML.each_document( io, &block )
yp = @@parser.new.load_documents( io, &block ) yp = parser.load_documents( io, &block )
end end
# #
@ -230,7 +243,7 @@ module YAML
# end # end
# #
def YAML.each_node( io, &doc_proc ) def YAML.each_node( io, &doc_proc )
yp = @@parser.new( :Model => :Generic ).load_documents( io, &doc_proc ) yp = generic_parser.load_documents( io, &doc_proc )
end end
# #
@ -254,12 +267,11 @@ module YAML
# loaded documents. # loaded documents.
# #
def YAML.load_stream( io ) def YAML.load_stream( io )
yp = @@parser.new
d = nil d = nil
yp.load_documents( io ) { |doc| parser.load_documents( io ) do |doc|
d = YAML::Stream.new( yp.options ) if not d d = YAML::Stream.new if not d
d.add( doc ) d.add( doc )
} end
return d return d
end end
@ -283,43 +295,50 @@ module YAML
# #
# Add a global handler for a YAML domain type. # Add a global handler for a YAML domain type.
# #
def YAML.add_domain_type( domain, type_re, &transfer_proc ) def YAML.add_domain_type( domain, type_tag, &transfer_proc )
@@loader.add_domain_type( domain, type_re, &transfer_proc ) resolver.add_type( "tag:#{ domain }:#{ type_tag }", transfer_proc )
end end
# #
# Add a transfer method for a builtin type # Add a transfer method for a builtin type
# #
def YAML.add_builtin_type( type_re, &transfer_proc ) def YAML.add_builtin_type( type_tag, &transfer_proc )
@@loader.add_builtin_type( type_re, &transfer_proc ) resolver.add_type( "tag:yaml.org,2002:#{ type_tag }", transfer_proc )
end end
# #
# Add a transfer method for a builtin type # Add a transfer method for a builtin type
# #
def YAML.add_ruby_type( type, &transfer_proc ) def YAML.add_ruby_type( type, &transfer_proc )
@@loader.add_ruby_type( type, &transfer_proc ) resolver.add_type( "tag:ruby.yaml.org,2002:#{ type_tag }", transfer_proc )
end end
# #
# Add a private document type # Add a private document type
# #
def YAML.add_private_type( type_re, &transfer_proc ) def YAML.add_private_type( type_re, &transfer_proc )
@@loader.add_private_type( type_re, &transfer_proc ) resolver.add_type( "x-private:" + type_re, transfer_proc )
end end
# #
# Detect typing of a string # Detect typing of a string
# #
def YAML.detect_implicit( val ) def YAML.detect_implicit( val )
@@loader.detect_implicit( val ) resolver.detect_implicit( val )
end
#
# Convert a type_id to a taguri
#
def YAML.tagurize( val )
resolver.tagurize( val )
end end
# #
# Apply a transfer method to a Ruby object # Apply a transfer method to a Ruby object
# #
def YAML.transfer( type_id, obj ) def YAML.transfer( type_id, obj )
@@loader.transfer( type_id, obj ) resolver.transfer( YAML.tagurize( type_id ), obj )
end end
# #
@ -358,24 +377,13 @@ module YAML
# Allocate an Emitter if needed # Allocate an Emitter if needed
# #
def YAML.quick_emit( oid, opts = {}, &e ) def YAML.quick_emit( oid, opts = {}, &e )
old_opt = nil out =
if opts[:Emitter].is_a? @@emitter if opts.is_a? YAML::Emitter
out = opts.delete( :Emitter ) opts
old_opt = out.options.dup else
out.options.update( opts ) emitter.reset( opts )
else end
out = @@emitter.new( opts ) out.emit( oid, &e )
end
aidx = out.start_object( oid )
if aidx
out.simple( "*#{ aidx }" )
else
e.call( out )
end
if old_opt.is_a? Hash
out.options = old_opt
end
out.end_object
end end
end end
@ -383,7 +391,7 @@ end
require 'yaml/rubytypes' require 'yaml/rubytypes'
require 'yaml/types' require 'yaml/types'
module Kernel module Kernel # :nodoc:
# #
# ryan:: You know how Kernel.p is a really convenient way to dump ruby # ryan:: You know how Kernel.p is a really convenient way to dump ruby
# structures? The only downside is that it's not as legible as # structures? The only downside is that it's not as legible as
@ -400,12 +408,25 @@ module Kernel
# ryan:: Either way, I certainly will have a pony parade. # ryan:: Either way, I certainly will have a pony parade.
# #
def y( o, *x ) # Prints any supplied _objects_ out in YAML. Intended as
x.unshift o # a variation on +Kernel::p+.
puts( if x.length == 1 #
YAML::dump( *x ) # S = Struct.new(:name, :state)
# s = S['dave', 'TX']
# y s
#
# _produces:_
#
# --- !ruby/struct:S
# name: dave
# state: TX
#
def y( object, *objects )
objects.unshift object
puts( if objects.length == 1
YAML::dump( *objects )
else else
YAML::dump_stream( *x ) YAML::dump_stream( *objects )
end ) end )
end end
private :y private :y

View File

@ -25,7 +25,7 @@ module YAML
matches.each { |m| matches.each { |m|
result.push m.last result.push m.last
} }
self.class.new( 'seq', result ) YAML.transfer( 'seq', result )
end end
end end

View File

@ -29,5 +29,6 @@ module YAML
class Error < StandardError; end class Error < StandardError; end
class ParseError < Error; end class ParseError < Error; end
class TypeError < StandardError; end
end end

View File

@ -1,9 +1,9 @@
# -*- mode: ruby; ruby-indent-level: 4; tab-width: 4 -*- vim: sw=4 ts=4 # -*- mode: ruby; ruby-indent-level: 4; tab-width: 4 -*- vim: sw=4 ts=4
require 'date' require 'date'
# #
# Type conversions # Type conversions
# #
class Class class Class
def to_yaml( opts = {} ) def to_yaml( opts = {} )
raise TypeError, "can't dump anonymous class %s" % self.class raise TypeError, "can't dump anonymous class %s" % self.class
@ -11,564 +11,377 @@ class Class
end end
class Object class Object
def is_complex_yaml? yaml_as "tag:ruby.yaml.org,2002:object"
true def to_yaml_style; end
end def to_yaml_properties; instance_variables.sort; end
def to_yaml_type
"!ruby/object:#{self.class}"
end
def to_yaml_properties
instance_variables.sort
end
def to_yaml( opts = {} ) def to_yaml( opts = {} )
YAML::quick_emit( self.object_id, opts ) { |out| YAML::quick_emit( object_id, opts ) do |out|
out.map( self.to_yaml_type ) { |map| out.map( taguri, to_yaml_style ) do |map|
to_yaml_properties.each { |m| to_yaml_properties.each do |m|
map.add( m[1..-1], instance_variable_get( m ) ) map.add( m[1..-1], instance_variable_get( m ) )
} end
} end
} end
end end
end end
YAML.add_ruby_type( /^object/ ) { |type, val|
type, obj_class = YAML.read_type_class( type, Object )
YAML.object_maker( obj_class, val )
}
# #
# Maps: Hash#to_yaml # Maps: Hash#to_yaml
# #
class Hash class Hash
def is_complex_yaml? yaml_as "tag:ruby.yaml.org,2002:hash"
true yaml_as "tag:yaml.org,2002:map"
end def yaml_initialize( tag, val )
def to_yaml_type if Array === val
if self.class == Hash or self.class == YAML::SpecialHash update Hash.[]( *val ) # Convert the map to a sequence
"!map" elsif Hash === val
update val
else else
"!ruby/hash:#{self.class}" raise YAML::TypeError, "Invalid map explicitly tagged #{ tag }: " + val.inspect
end end
end end
def to_yaml( opts = {} ) def to_yaml( opts = {} )
opts[:DocType] = self.class if Hash === opts YAML::quick_emit( object_id, opts ) do |out|
YAML::quick_emit( self.object_id, opts ) { |out| out.map( taguri, to_yaml_style ) do |map|
hash_type = to_yaml_type each do |k, v|
if not out.options(:ExplicitTypes) and hash_type == "!map" map.add( k, v )
hash_type = ""
end
out.map( hash_type ) { |map|
#
# Sort the hash
#
if out.options(:SortKeys)
map.concat( self.sort )
else
map.concat( self.to_a )
end end
}
}
end
end
hash_proc = Proc.new { |type, val|
if Array === val
val = Hash.[]( *val ) # Convert the map to a sequence
elsif Hash === val
type, obj_class = YAML.read_type_class( type, Hash )
if obj_class != Hash
o = obj_class.allocate
o.update( val )
val = o
end
else
raise YAML::Error, "Invalid map explicitly tagged !map: " + val.inspect
end
val
}
YAML.add_ruby_type( /^hash/, &hash_proc )
module YAML
#
# Ruby-specific collection: !ruby/flexhash
#
class FlexHash < Array
def []( k )
self.assoc( k ).to_a[1]
end
def []=( k, *rest )
val, set = rest.reverse
if ( tmp = self.assoc( k ) ) and not set
tmp[1] = val
else
self << [ k, val ]
end end
val
end end
def has_key?( k ) end
self.assoc( k ) ? true : false
end
def is_complex_yaml?
true
end
def to_yaml( opts = {} )
YAML::quick_emit( self.object_id, opts ) { |out|
out.seq( "!ruby/flexhash" ) { |seq|
self.each { |v|
if v[1]
seq.add( Hash.[]( *v ) )
else
seq.add( v[0] )
end
}
}
}
end
end
YAML.add_ruby_type( 'flexhash' ) { |type, val|
if Array === val
p = FlexHash.new
val.each { |v|
if Hash === v
p.concat( v.to_a ) # Convert the map to a sequence
else
p << [ v, nil ]
end
}
p
else
raise YAML::Error, "Invalid !ruby/flexhash: " + val.inspect
end
}
end end
# #
# Structs: export as a !map # Structs: export as a !map
# #
class Struct class Struct
def is_complex_yaml? yaml_as "tag:ruby.yaml.org,2002:struct"
true def self.yaml_tag_class_name; self.name.gsub( "Struct::", "" ); end
def self.yaml_tag_read_class( name ); "Struct::#{ name }"; end
def self.yaml_new( klass, tag, val )
if Hash === val
struct_type = nil
#
# Use existing Struct if it exists
#
props = {}
val.delete_if { |k,v| props[k] = v if k =~ /^@/ }
begin
struct_name, struct_type = YAML.read_type_class( tag, Struct )
rescue NameError
end
if not struct_type
struct_def = [ tag.split( ':', 4 ).last ]
struct_type = Struct.new( *struct_def.concat( val.keys.collect { |k| k.intern } ) )
end
#
# Set the Struct properties
#
st = YAML::object_maker( struct_type, {} )
st.members.each do |m|
st.send( "#{m}=", val[m] )
end
props.each do |k,v|
st.instance_variable_set(k, v)
end
st
else
raise YAML::TypeError, "Invalid Ruby Struct: " + val.inspect
end
end end
def to_yaml( opts = {} ) def to_yaml( opts = {} )
YAML::quick_emit( self.object_id, opts ) { |out| YAML::quick_emit( object_id, opts ) do |out|
# #
# Basic struct is passed as a YAML map # Basic struct is passed as a YAML map
# #
struct_name = self.class.name.gsub( "Struct::", "" ) out.map( taguri, to_yaml_style ) do |map|
out.map( "!ruby/struct:#{struct_name}" ) { |map| self.members.each do |m|
self.members.each { |m|
map.add( m, self[m] ) map.add( m, self[m] )
} end
self.to_yaml_properties.each { |m| self.to_yaml_properties.each do |m|
map.add( m, instance_variable_get( m ) ) map.add( m, instance_variable_get( m ) )
} end
} end
} end
end end
end end
YAML.add_ruby_type( /^struct/ ) { |type, val|
if Hash === val
struct_type = nil
#
# Use existing Struct if it exists
#
props = {}
val.delete_if { |k,v| props[k] = v if k =~ /^@/ }
begin
struct_name, struct_type = YAML.read_type_class( type, Struct )
rescue NameError
end
if not struct_type
struct_def = [ type.split( ':', 4 ).last ]
struct_type = Struct.new( *struct_def.concat( val.keys.collect { |k| k.intern } ) )
end
#
# Set the Struct properties
#
st = YAML::object_maker( struct_type, {} )
st.members.each { |m|
st.send( "#{m}=", val[m] )
}
props.each { |k,v|
st.instance_variable_set(k, v)
}
st
else
raise YAML::Error, "Invalid Ruby Struct: " + val.inspect
end
}
# #
# Sequences: Array#to_yaml # Sequences: Array#to_yaml
# #
class Array class Array
def is_complex_yaml? yaml_as "tag:ruby.yaml.org,2002:array"
true yaml_as "tag:yaml.org,2002:seq"
end def yaml_initialize( tag, val ); concat( val.to_a ); end
def to_yaml_type
if self.class == Array
"!seq"
else
"!ruby/array:#{self.class}"
end
end
def to_yaml( opts = {} ) def to_yaml( opts = {} )
opts[:DocType] = self.class if Hash === opts YAML::quick_emit( object_id, opts ) do |out|
YAML::quick_emit( self.object_id, opts ) { |out| out.seq( taguri, to_yaml_style ) do |seq|
array_type = to_yaml_type each do |x|
if not out.options(:ExplicitTypes) and array_type == "!seq" seq.add( x )
array_type = "" end
end end
end
out.seq( array_type ) { |seq|
seq.concat( self )
}
}
end end
end end
array_proc = Proc.new { |type, val|
if Array === val
type, obj_class = YAML.read_type_class( type, Array )
if obj_class != Array
o = obj_class.allocate
o.concat( val )
val = o
end
val
else
val.to_a
end
}
YAML.add_ruby_type( /^array/, &array_proc )
# #
# Exception#to_yaml # Exception#to_yaml
# #
class Exception class Exception
def is_complex_yaml? yaml_as "tag:ruby.yaml.org,2002:exception"
true def Exception.yaml_new( klass, tag, val )
end o = YAML.object_maker( klass, { 'mesg' => val.delete( 'message' ) } )
def to_yaml_type val.each_pair do |k,v|
"!ruby/exception:#{self.class}" o.instance_variable_set("@#{k}", v)
end
o
end end
def to_yaml( opts = {} ) def to_yaml( opts = {} )
YAML::quick_emit( self.object_id, opts ) { |out| YAML::quick_emit( object_id, opts ) do |out|
out.map( self.to_yaml_type ) { |map| out.map( taguri, to_yaml_style ) do |map|
map.add( 'message', self.message ) map.add( 'message', message )
to_yaml_properties.each { |m| to_yaml_properties.each do |m|
map.add( m[1..-1], instance_variable_get( m ) ) map.add( m[1..-1], instance_variable_get( m ) )
} end
} end
} end
end end
end end
YAML.add_ruby_type( /^exception/ ) { |type, val|
type, obj_class = YAML.read_type_class( type, Exception )
o = YAML.object_maker( obj_class, { 'mesg' => val.delete( 'message' ) } )
val.each_pair { |k,v|
o.instance_variable_set("@#{k}", v)
}
o
}
# #
# String#to_yaml # String#to_yaml
# #
class String class String
yaml_as "tag:ruby.yaml.org,2002:string"
yaml_as "tag:yaml.org,2002:str"
def is_complex_yaml? def is_complex_yaml?
to_yaml_fold or not to_yaml_properties.empty? or self =~ /\n.+/ to_yaml_style or not to_yaml_properties.empty? or self =~ /\n.+/
end end
def is_binary_data? def is_binary_data?
( self.count( "^ -~", "^\r\n" ) / self.size > 0.3 || self.count( "\x00" ) > 0 ) ( self.count( "^ -~", "^\r\n" ) / self.size > 0.3 || self.count( "\x00" ) > 0 ) unless empty?
end end
def to_yaml_type def String.yaml_new( klass, tag, val )
"!ruby/string#{ ":#{ self.class }" if self.class != ::String }" val = { 'str' => val } if String === val
end if Hash === val
def to_yaml_fold s = klass.allocate
nil # Thank you, NaHi
String.instance_method(:initialize).
bind(s).
call( val.delete( 'str' ) )
val.each { |k,v| s.instance_variable_set( k, v ) }
s
else
raise YAML::TypeError, "Invalid String: " + val.inspect
end
end end
def to_yaml( opts = {} ) def to_yaml( opts = {} )
complex = false YAML::quick_emit( is_complex_yaml? ? object_id : nil, opts ) do |out|
if self.is_complex_yaml? if is_binary_data?
complex = true out.scalar( "tag:yaml.org,2002:binary", [self].pack("m"), :literal )
elsif opts[:BestWidth].to_i > 0 elsif to_yaml_properties.empty?
if self.length > opts[:BestWidth] and opts[:UseFold] out.scalar( taguri, self, to_yaml_style )
complex = true else
out.map( taguri, to_yaml_style ) do |map|
map.add( 'str', "#{self}" )
to_yaml_properties.each do |m|
map.add( m, instance_variable_get( m ) )
end
end
end end
end end
YAML::quick_emit( complex ? self.object_id : nil, opts ) { |out|
if complex
if not to_yaml_properties.empty?
out.map( self.to_yaml_type ) { |map|
map.add( 'str', "#{self}" )
to_yaml_properties.each { |m|
map.add( m, instance_variable_get( m ) )
}
}
elsif self.is_binary_data?
out.binary_base64( self )
elsif self =~ /#{YAML::ESCAPE_CHAR}/
out.node_text( self, '"' )
else
out.node_text( self, to_yaml_fold )
end
else
ostr = if out.options(:KeepValue)
self
elsif empty?
"''"
elsif self =~ /^[^#{YAML::WORD_CHAR}\/]| \#|#{YAML::ESCAPE_CHAR}|[#{YAML::SPACE_INDICATORS}]( |$)| $|\n|\'/
out.node_text( self, '"' ); nil
elsif YAML.detect_implicit( self ) != 'str'
out.node_text( self, '"' ); nil
else
self
end
out.simple( ostr ) unless ostr.nil?
end
}
end end
end end
YAML.add_ruby_type( /^string/ ) { |type, val|
type, obj_class = YAML.read_type_class( type, ::String )
if Hash === val
s = YAML::object_maker( obj_class, {} )
# Thank you, NaHi
String.instance_method(:initialize).
bind(s).
call( val.delete( 'str' ) )
val.each { |k,v| s.instance_variable_set( k, v ) }
s
else
raise YAML::Error, "Invalid String: " + val.inspect
end
}
# #
# Symbol#to_yaml # Symbol#to_yaml
# #
class Symbol class Symbol
def is_complex_yaml? yaml_as "tag:ruby.yaml.org,2002:symbol"
false yaml_as "tag:ruby.yaml.org,2002:sym"
# yaml_implicit /^:/, :yaml_new
def Symbol.yaml_new( klass, tag, val )
if String === val
val.intern
else
raise YAML::TypeError, "Invalid Symbol: " + val.inspect
end
end end
def to_yaml( opts = {} ) def to_yaml( opts = {} )
YAML::quick_emit( nil, opts ) { |out| YAML::quick_emit( nil, opts ) do |out|
out << ":" out.scalar( taguri, self.id2name, :plain )
self.id2name.to_yaml( :Emitter => out ) end
}
end end
end end
symbol_proc = Proc.new { |type, val|
if String === val
val = YAML::load( "--- #{val}") if val =~ /^["'].*['"]$/
val.intern
else
raise YAML::Error, "Invalid Symbol: " + val.inspect
end
}
YAML.add_ruby_type( 'symbol', &symbol_proc )
YAML.add_ruby_type( 'sym', &symbol_proc )
# #
# Range#to_yaml # Range#to_yaml
# TODO: Rework the Range as a sequence (simpler)
# #
class Range class Range
def is_complex_yaml? yaml_as "tag:ruby.yaml.org,2002:range"
true def Range.yaml_new( klass, tag, val )
end inr = %r'(\w+|[+-]?\d+(?:\.\d+)?(?:e[+-]\d+)?|"(?:[^\\"]|\\.)*")'
def to_yaml_type opts = {}
"!ruby/range#{ if self.class != ::Range; ":#{ self.class }"; end }" if String === val and val =~ /^#{inr}(\.{2,3})#{inr}$/o
r1, rdots, r2 = $1, $2, $3
opts = {
'begin' => YAML.load( "--- #{r1}" ),
'end' => YAML.load( "--- #{r2}" ),
'excl' => rdots.length == 3
}
val = {}
elsif Hash === val
opts['begin'] = val.delete('begin')
opts['end'] = val.delete('end')
opts['excl'] = val.delete('excl')
end
if Hash === opts
r = YAML::object_maker( klass, {} )
# Thank you, NaHi
Range.instance_method(:initialize).
bind(r).
call( opts['begin'], opts['end'], opts['excl'] )
val.each { |k,v| r.instance_variable_set( k, v ) }
r
else
raise YAML::TypeError, "Invalid Range: " + val.inspect
end
end end
def to_yaml( opts = {} ) def to_yaml( opts = {} )
YAML::quick_emit( self.object_id, opts ) { |out| YAML::quick_emit( object_id, opts ) do |out|
if self.begin.is_complex_yaml? or self.begin.respond_to? :to_str or # if self.begin.is_complex_yaml? or self.begin.respond_to? :to_str or
self.end.is_complex_yaml? or self.end.respond_to? :to_str or # self.end.is_complex_yaml? or self.end.respond_to? :to_str or
not to_yaml_properties.empty? # not to_yaml_properties.empty?
out.map( to_yaml_type ) { |map| out.map( taguri, to_yaml_style ) do |map|
map.add( 'begin', self.begin ) map.add( 'begin', self.begin )
map.add( 'end', self.end ) map.add( 'end', self.end )
map.add( 'excl', self.exclude_end? ) map.add( 'excl', self.exclude_end? )
to_yaml_properties.each { |m| to_yaml_properties.each do |m|
map.add( m, instance_variable_get( m ) ) map.add( m, instance_variable_get( m ) )
} end
} end
else # else
out << "#{ to_yaml_type } '" # out.scalar( taguri ) do |sc|
self.begin.to_yaml(:Emitter => out) # sc.embed( self.begin )
out << ( self.exclude_end? ? "..." : ".." ) # sc.concat( self.exclude_end? ? "..." : ".." )
self.end.to_yaml(:Emitter => out) # sc.embed( self.end )
out << "'" # end
end # end
} end
end end
end end
YAML.add_ruby_type( /^range/ ) { |type, val|
type, obj_class = YAML.read_type_class( type, ::Range )
inr = %r'(\w+|[+-]?\d+(?:\.\d+)?(?:e[+-]\d+)?|"(?:[^\\"]|\\.)*")'
opts = {}
if String === val and val =~ /^#{inr}(\.{2,3})#{inr}$/o
r1, rdots, r2 = $1, $2, $3
opts = {
'begin' => YAML.load( "--- #{r1}" ),
'end' => YAML.load( "--- #{r2}" ),
'excl' => rdots.length == 3
}
val = {}
elsif Hash === val
opts['begin'] = val.delete('begin')
opts['end'] = val.delete('end')
opts['excl'] = val.delete('excl')
end
if Hash === opts
r = YAML::object_maker( obj_class, {} )
# Thank you, NaHi
Range.instance_method(:initialize).
bind(r).
call( opts['begin'], opts['end'], opts['excl'] )
val.each { |k,v| r.instance_variable_set( k, v ) }
r
else
raise YAML::Error, "Invalid Range: " + val.inspect
end
}
# #
# Make an Regexp # Make an Regexp
# #
class Regexp class Regexp
def is_complex_yaml? yaml_as "tag:ruby.yaml.org,2002:regexp"
self.class != Regexp or not to_yaml_properties.empty? def Regexp.yaml_new( klass, tag, val )
end if String === val and val =~ /^\/(.*)\/([mix]*)$/
def to_yaml_type val = { 'regexp' => $1, 'mods' => $2 }
"!ruby/regexp#{ if self.class != ::Regexp; ":#{ self.class }"; end }" end
if Hash === val
mods = nil
unless val['mods'].to_s.empty?
mods = 0x00
mods |= Regexp::EXTENDED if val['mods'].include?( 'x' )
mods |= Regexp::IGNORECASE if val['mods'].include?( 'i' )
mods |= Regexp::MULTILINE if val['mods'].include?( 'm' )
end
val.delete( 'mods' )
r = YAML::object_maker( klass, {} )
Regexp.instance_method(:initialize).
bind(r).
call( val.delete( 'regexp' ), mods )
val.each { |k,v| r.instance_variable_set( k, v ) }
r
else
raise YAML::TypeError, "Invalid Regular expression: " + val.inspect
end
end end
def to_yaml( opts = {} ) def to_yaml( opts = {} )
YAML::quick_emit( nil, opts ) { |out| YAML::quick_emit( nil, opts ) do |out|
if self.is_complex_yaml? if to_yaml_properties.empty?
out.map( self.to_yaml_type ) { |map| out.scalar( taguri, self.inspect, :plain )
else
out.map( taguri, to_yaml_style ) do |map|
src = self.inspect src = self.inspect
if src =~ /\A\/(.*)\/([a-z]*)\Z/ if src =~ /\A\/(.*)\/([a-z]*)\Z/
map.add( 'regexp', $1 ) map.add( 'regexp', $1 )
map.add( 'mods', $2 ) map.add( 'mods', $2 )
else else
raise YAML::Error, "Invalid Regular expression: " + src raise YAML::TypeError, "Invalid Regular expression: " + src
end end
to_yaml_properties.each { |m| to_yaml_properties.each do |m|
map.add( m, instance_variable_get( m ) ) map.add( m, instance_variable_get( m ) )
} end
} end
else
out << "#{ to_yaml_type } "
self.inspect.to_yaml( :Emitter => out )
end end
} end
end end
end end
regexp_proc = Proc.new { |type, val|
type, obj_class = YAML.read_type_class( type, ::Regexp )
if String === val and val =~ /^\/(.*)\/([mix]*)$/
val = { 'regexp' => $1, 'mods' => $2 }
end
if Hash === val
mods = nil
unless val['mods'].to_s.empty?
mods = 0x00
mods |= Regexp::EXTENDED if val['mods'].include?( 'x' )
mods |= Regexp::IGNORECASE if val['mods'].include?( 'i' )
mods |= Regexp::MULTILINE if val['mods'].include?( 'm' )
end
val.delete( 'mods' )
r = YAML::object_maker( obj_class, {} )
Regexp.instance_method(:initialize).
bind(r).
call( val.delete( 'regexp' ), mods )
val.each { |k,v| r.instance_variable_set( k, v ) }
r
else
raise YAML::Error, "Invalid Regular expression: " + val.inspect
end
}
YAML.add_domain_type( "perl.yaml.org,2002", /^regexp/, &regexp_proc )
YAML.add_ruby_type( /^regexp/, &regexp_proc )
# #
# Emit a Time object as an ISO 8601 timestamp # Emit a Time object as an ISO 8601 timestamp
# #
class Time class Time
def is_complex_yaml? yaml_as "tag:ruby.yaml.org,2002:time"
self.class != Time or not to_yaml_properties.empty? yaml_as "tag:yaml.org,2002:timestamp"
end def Time.yaml_new( klass, tag, val )
def to_yaml_type if Hash === val
"!ruby/time#{ if self.class != ::Time; ":#{ self.class }"; end }" t = val.delete( 'at' )
val.each { |k,v| t.instance_variable_set( k, v ) }
t
else
raise YAML::TypeError, "Invalid Time: " + val.inspect
end
end end
def to_yaml( opts = {} ) def to_yaml( opts = {} )
YAML::quick_emit( nil, opts ) { |out| YAML::quick_emit( object_id, opts ) do |out|
if self.is_complex_yaml? tz = "Z"
out.map( self.to_yaml_type ) { |map| # from the tidy Tobias Peters <t-peters@gmx.de> Thanks!
map.add( 'at', ::Time.at( self ) ) unless self.utc?
to_yaml_properties.each { |m| utc_same_instant = self.dup.utc
map.add( m, instance_variable_get( m ) ) utc_same_writing = Time.utc(year,month,day,hour,min,sec,usec)
} difference_to_utc = utc_same_writing - utc_same_instant
} if (difference_to_utc < 0)
else difference_sign = '-'
tz = "Z" absolute_difference = -difference_to_utc
# from the tidy Tobias Peters <t-peters@gmx.de> Thanks! else
unless self.utc? difference_sign = '+'
utc_same_instant = self.dup.utc absolute_difference = difference_to_utc
utc_same_writing = Time.utc(year,month,day,hour,min,sec,usec)
difference_to_utc = utc_same_writing - utc_same_instant
if (difference_to_utc < 0)
difference_sign = '-'
absolute_difference = -difference_to_utc
else
difference_sign = '+'
absolute_difference = difference_to_utc
end
difference_minutes = (absolute_difference/60).round
tz = "%s%02d:%02d" % [ difference_sign, difference_minutes / 60, difference_minutes % 60]
end end
standard = self.strftime( "%Y-%m-%d %H:%M:%S" ) difference_minutes = (absolute_difference/60).round
standard += ".%06d" % [usec] if usec.nonzero? tz = "%s%02d:%02d" % [ difference_sign, difference_minutes / 60, difference_minutes % 60]
standard += " %s" % [tz]
standard.to_yaml( :Emitter => out, :KeepValue => true )
end end
} standard = self.strftime( "%Y-%m-%d %H:%M:%S" )
standard += ".%06d" % [usec] if usec.nonzero?
standard += " %s" % [tz]
if to_yaml_properties.empty?
out.scalar( taguri, standard, :plain )
else
out.map( taguri, to_yaml_style ) do |map|
map.add( 'at', standard )
to_yaml_properties.each do |m|
map.add( m, instance_variable_get( m ) )
end
end
end
end
end end
end end
YAML.add_ruby_type( /^time/ ) { |type, val|
type, obj_class = YAML.read_type_class( type, ::Time )
if Hash === val
t = obj_class.at( val.delete( 'at' ) )
val.each { |k,v| t.instance_variable_set( k, v ) }
t
else
raise YAML::Error, "Invalid Time: " + val.inspect
end
}
# #
# Emit a Date object as a simple implicit # Emit a Date object as a simple implicit
# #
class Date class Date
def is_complex_yaml? yaml_as "tag:yaml.org,2002:timestamp#ymd"
false
end
def to_yaml( opts = {} ) def to_yaml( opts = {} )
opts[:KeepValue] = true YAML::quick_emit( object_id, opts ) do |out|
self.to_s.to_yaml( opts ) out.scalar( "tag:yaml.org,2002:timestamp", self.to_s, :plain )
end
end end
end end
@ -576,50 +389,51 @@ end
# Send Integer, Booleans, NilClass to String # Send Integer, Booleans, NilClass to String
# #
class Numeric class Numeric
def is_complex_yaml?
false
end
def to_yaml( opts = {} ) def to_yaml( opts = {} )
str = self.to_s YAML::quick_emit( nil, opts ) do |out|
if str == "Infinity" str = self.to_s
str = ".Inf" if str == "Infinity"
elsif str == "-Infinity" str = ".Inf"
str = "-.Inf" elsif str == "-Infinity"
elsif str == "NaN" str = "-.Inf"
str = ".NaN" elsif str == "NaN"
end str = ".NaN"
opts[:KeepValue] = true end
str.to_yaml( opts ) out.scalar( taguri, str, :plain )
end
end end
end end
class Fixnum
yaml_as "tag:yaml.org,2002:int"
end
class Float
yaml_as "tag:yaml.org,2002:float"
end
class TrueClass class TrueClass
def is_complex_yaml? yaml_as "tag:yaml.org,2002:bool#yes"
false
end
def to_yaml( opts = {} ) def to_yaml( opts = {} )
opts[:KeepValue] = true YAML::quick_emit( nil, opts ) do |out|
"true".to_yaml( opts ) out.scalar( taguri, "true", :plain )
end
end end
end end
class FalseClass class FalseClass
def is_complex_yaml? yaml_as "tag:yaml.org,2002:bool#no"
false
end
def to_yaml( opts = {} ) def to_yaml( opts = {} )
opts[:KeepValue] = true YAML::quick_emit( nil, opts ) do |out|
"false".to_yaml( opts ) out.scalar( taguri, "false", :plain )
end
end end
end end
class NilClass class NilClass
def is_complex_yaml? yaml_as "tag:yaml.org,2002:null"
false
end
def to_yaml( opts = {} ) def to_yaml( opts = {} )
opts[:KeepValue] = true YAML::quick_emit( nil, opts ) do |out|
"".to_yaml( opts ) out.scalar( taguri, "", :plain )
end
end end
end end

View File

@ -24,19 +24,15 @@ module YAML
@documents[ doc_num ] = doc @documents[ doc_num ] = doc
end end
def emit def emit( io = nil )
opts = @options.dup # opts = @options.dup
opts[:UseHeader] = true if @documents.length > 1 # opts[:UseHeader] = true if @documents.length > 1
ct = 0 out = YAML.emitter
out = YAML::Syck::Emitter.new( opts ) out.reset( io || io2 = StringIO.new )
@documents.each { |v| @documents.each { |v|
if ct > 0 v.to_yaml( out )
out << "\n--- "
end
v.to_yaml( :Emitter => out )
ct += 1
} }
out.end_object io || ( io2.rewind; io2.read )
end end
end end

View File

@ -4,7 +4,6 @@
# #
require 'syck' require 'syck'
require 'yaml/basenode' require 'yaml/basenode'
require 'yaml/baseemitter'
module YAML module YAML
module Syck module Syck
@ -16,12 +15,5 @@ module YAML
include YAML::BaseNode include YAML::BaseNode
end end
#
# Mixin BaseEmitter functionality
#
class Emitter
include YAML::BaseEmitter
end
end end
end end

86
lib/yaml/tag.rb Normal file
View File

@ -0,0 +1,86 @@
# -*- mode: ruby; ruby-indent-level: 4; tab-width: 4 -*- vim: sw=4 ts=4
# $Id$
#
# = yaml/tag.rb: methods for associating a taguri to a class.
#
# Author:: why the lucky stiff
#
module YAML
# A dictionary of taguris which map to
# Ruby classes.
@@tagged_classes = {}
#
# Associates a taguri _tag_ with a Ruby class _cls_. The taguri is used to give types
# to classes when loading YAML. Taguris are of the form:
#
# tag:authorityName,date:specific
#
# The +authorityName+ is a domain name or email address. The +date+ is the date the type
# was issued in YYYY or YYYY-MM or YYYY-MM-DD format. The +specific+ is a name for
# the type being added.
#
# For example, built-in YAML types have 'yaml.org' as the +authorityName+ and '2002' as the
# +date+. The +specific+ is simply the name of the type:
#
# tag:yaml.org,2002:int
# tag:yaml.org,2002:float
# tag:yaml.org,2002:timestamp
#
# The domain must be owned by you on the +date+ declared. If you don't own any domains on the
# date you declare the type, you can simply use an e-mail address.
#
# tag:why@ruby-lang.org,2004:notes/personal
#
def YAML.tag_class( tag, cls )
if @@tagged_classes.has_key? tag
warn "class #{ @@tagged_classes[tag] } held ownership of the #{ tag } tag"
end
@@tagged_classes[tag] = cls
end
# Returns the complete dictionary of taguris, paired with classes. The key for
# the dictionary is the full taguri. The value for each key is the class constant
# associated to that taguri.
#
# YAML.tagged_classes["tag:yaml.org,2002:int"] => Integer
#
def YAML.tagged_classes
@@tagged_classes
end
end
class Module # :nodoc: all
# Adds a taguri _tag_ to a class, used when dumping or loading the class
# in YAML. See YAML::tag_class for detailed information on typing and
# taguris.
def yaml_as( tag, sc = true )
class_eval <<-"end;"
attr_accessor :taguri
def taguri
if respond_to? :to_yaml_type
YAML::tagurize( to_yaml_type[1..-1] )
else
return @taguri if @taguri
tag = #{ tag.dump }
if self.class.yaml_tag_subclasses? and self.class != YAML::tagged_classes[tag]
tag = "\#{ tag }:\#{ self.class.yaml_tag_class_name }"
end
tag
end
end
def self.yaml_tag_subclasses?; #{ sc ? 'true' : 'false' }; end
end;
YAML::tag_class tag, self
end
# Transforms the subclass name into a name suitable for display
# in a subclassed tag.
def yaml_tag_class_name
self.name
end
# Transforms the subclass name found in the tag into a Ruby
# constant name.
def yaml_tag_read_class( name )
name
end
end

View File

@ -8,15 +8,14 @@ module YAML
# Default private type # Default private type
# #
class PrivateType class PrivateType
def self.tag_subclasses?; false; end
attr_accessor :type_id, :value attr_accessor :type_id, :value
def initialize( type, val ) def initialize( type, val )
@type_id = type; @value = val @type_id = type; @value = val
@value.taguri = "x-private:#{ @type_id }"
end end
def to_yaml( opts = {} ) def to_yaml( opts = {} )
YAML::quick_emit( self.object_id, opts ) { |out| @value.to_yaml( opts )
out << " !!#{@type_id}"
value.to_yaml( :Emitter => out )
}
end end
end end
@ -24,29 +23,37 @@ module YAML
# Default domain type # Default domain type
# #
class DomainType class DomainType
def self.tag_subclasses?; false; end
attr_accessor :domain, :type_id, :value attr_accessor :domain, :type_id, :value
def initialize( domain, type, val ) def initialize( domain, type, val )
@domain = domain; @type_id = type; @value = val @domain = domain; @type_id = type; @value = val
@value.taguri = "tag:#{ @domain }:#{ @type_id }"
end end
def to_yaml_type
dom = @domain.dup
if dom =~ /\.yaml\.org,2002$/
dom = $`
end
"#{dom}/#{@type_id}"
end
def to_yaml( opts = {} ) def to_yaml( opts = {} )
YAML::quick_emit( self.object_id, opts ) { |out| @value.to_yaml( opts )
out << " !#{to_yaml_type} " end
value.to_yaml( :Emitter => out ) 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
end end
# #
# YAML Hash class to support comments and defaults # YAML Hash class to support comments and defaults
# #
class SpecialHash < Object::Hash class SpecialHash < ::Hash
attr_accessor :default attr_accessor :default
def inspect def inspect
self.default.to_s self.default.to_s
@ -69,12 +76,27 @@ module YAML
# #
# Builtin collection: !omap # Builtin collection: !omap
# #
class Omap < Array class Omap < ::Array
yaml_as "tag:yaml.org,2002:omap"
def yaml_initialize( tag, val )
if Array === val
val.each do |v|
if Hash === v
concat( v.to_a ) # Convert the map to a sequence
else
raise YAML::Error, "Invalid !omap entry: " + val.inspect
end
end
else
raise YAML::Error, "Invalid !omap: " + val.inspect
end
self
end
def self.[]( *vals ) def self.[]( *vals )
o = Omap.new o = Omap.new
0.step( vals.length - 1, 2 ) { |i| 0.step( vals.length - 1, 2 ) do |i|
o[vals[i]] = vals[i+1] o[vals[i]] = vals[i+1]
} end
o o
end end
def []( k ) def []( k )
@ -96,36 +118,35 @@ module YAML
true true
end end
def to_yaml( opts = {} ) def to_yaml( opts = {} )
YAML::quick_emit( self.object_id, opts ) { |out| YAML::quick_emit( self.object_id, opts ) do |out|
out.seq( "!omap" ) { |seq| out.seq( taguri, to_yaml_style ) do |seq|
self.each { |v| self.each do |v|
seq.add( Hash[ *v ] ) seq.add( Hash[ *v ] )
} end
} end
} end
end end
end end
YAML.add_builtin_type( "omap" ) { |type, val|
if Array === val
p = Omap.new
val.each { |v|
if Hash === v
p.concat( v.to_a ) # Convert the map to a sequence
else
raise YAML::Error, "Invalid !omap entry: " + val.inspect
end
}
else
raise YAML::Error, "Invalid !omap: " + val.inspect
end
p
}
# #
# Builtin collection: !pairs # Builtin collection: !pairs
# #
class Pairs < Array class Pairs < ::Array
yaml_as "tag:yaml.org,2002:pairs"
def yaml_initialize( tag, val )
if Array === val
val.each do |v|
if Hash === v
concat( v.to_a ) # Convert the map to a sequence
else
raise YAML::Error, "Invalid !pairs entry: " + val.inspect
end
end
else
raise YAML::Error, "Invalid !pairs: " + val.inspect
end
self
end
def self.[]( *vals ) def self.[]( *vals )
p = Pairs.new p = Pairs.new
0.step( vals.length - 1, 2 ) { |i| 0.step( vals.length - 1, 2 ) { |i|
@ -147,50 +168,20 @@ module YAML
true true
end end
def to_yaml( opts = {} ) def to_yaml( opts = {} )
YAML::quick_emit( self.object_id, opts ) { |out| YAML::quick_emit( self.object_id, opts ) do |out|
out.seq( "!pairs" ) { |seq| out.seq( taguri, to_yaml_style ) do |seq|
self.each { |v| self.each do |v|
seq.add( Hash[ *v ] ) seq.add( Hash[ *v ] )
} end
} end
} end
end end
end end
YAML.add_builtin_type( "pairs" ) { |type, val|
if Array === val
p = Pairs.new
val.each { |v|
if Hash === v
p.concat( v.to_a ) # Convert the map to a sequence
else
raise YAML::Error, "Invalid !pairs entry: " + val.inspect
end
}
else
raise YAML::Error, "Invalid !pairs: " + val.inspect
end
p
}
# #
# Builtin collection: !set # Builtin collection: !set
# #
class Set < Hash class Set < ::Hash
def to_yaml_type yaml_as "tag:yaml.org,2002:set"
"!set"
end
end end
YAML.add_builtin_type( 'set' ) { |type, val|
if Array === val
val = Set[ *val ]
elsif Hash === val
Set[ val ]
else
raise YAML::Error, "Invalid map explicitly tagged !map: " + val.inspect
end
val
}
end end