1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* 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"
/*
* bytecode.re
@ -89,7 +89,7 @@ char *get_inline( SyckParser *parser );
#define ENSURE_YAML_IOPEN(last_lvl, lvl_type, to_len, reset) \
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; \
} \

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,
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
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
in version 1.24 of Bison. */
#ifndef BISON_Y_TAB_H
# define BISON_Y_TAB_H
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
@ -62,20 +59,21 @@
#ifndef YYSTYPE
#line 33 "gram.y"
typedef union {
#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
#line 35 "gram.y"
typedef union YYSTYPE {
SYMID nodeId;
SyckNode *nodeData;
char *name;
} yystype;
/* Line 1281 of /usr/local/share/bison/yacc.c. */
#line 74 "y.tab.h"
# define YYSTYPE yystype
} YYSTYPE;
/* Line 1285 of yacc.c. */
#line 71 "gram.h"
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
# define YYSTYPE_IS_TRIVIAL 1
#endif
#endif /* not BISON_Y_TAB_H */

View file

@ -31,6 +31,9 @@ syck_hdlr_add_node( SyckParser *p, SyckNode *n )
SyckNode *
syck_hdlr_add_anchor( SyckParser *p, char *a, SyckNode *n )
{
char *atmp = NULL;
SyckNode *ntmp = NULL;
n->anchor = a;
if ( p->bad_anchors != NULL )
{
@ -48,6 +51,13 @@ syck_hdlr_add_anchor( SyckParser *p, char *a, SyckNode *n )
{
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 );
return n;
}
@ -55,10 +65,19 @@ syck_hdlr_add_anchor( SyckParser *p, char *a, SyckNode *n )
void
syck_hdlr_remove_anchor( SyckParser *p, char *a )
{
char *atmp = a;
SyckNode *ntmp;
if ( p->anchors == NULL )
{
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 );
}

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"
/*
* implicit.re
@ -36,6 +36,7 @@ try_tag_implicit( SyckNode *n, int taguri )
tid = "map";
break;
}
if ( n->type_id != NULL ) S_FREE( n->type_id );
if ( taguri == 1 )
{
n->type_id = syck_taguri( YAML_DOMAIN, tid, strlen( tid ) );
@ -94,7 +95,7 @@ yy2: ++YYCURSOR;
if((yych = *YYCURSOR) <= '\000') goto yy6;
goto yy3;
yy3:
#line 122 "implicit.re"
#line 123 "implicit.re"
{ return "str"; }
#line 51 "<stdout>"
yy4: yyaccept = 0;
@ -115,7 +116,7 @@ yy5: yyaccept = 0;
yy6: ++YYCURSOR;
goto yy7;
yy7:
#line 84 "implicit.re"
#line 85 "implicit.re"
{ return "null"; }
#line 72 "<stdout>"
yy8: yyaccept = 0;
@ -273,13 +274,13 @@ yy25: YYCURSOR = YYMARKER;
yy26: ++YYCURSOR;
goto yy27;
yy27:
#line 120 "implicit.re"
#line 121 "implicit.re"
{ return "merge"; }
#line 230 "<stdout>"
yy28: ++YYCURSOR;
goto yy29;
yy29:
#line 118 "implicit.re"
#line 119 "implicit.re"
{ return "default"; }
#line 236 "<stdout>"
yy30: yych = *++YYCURSOR;
@ -320,7 +321,7 @@ yy36: yych = *++YYCURSOR;
yy37: ++YYCURSOR;
goto yy38;
yy38:
#line 104 "implicit.re"
#line 105 "implicit.re"
{ return "float#inf"; }
#line 277 "<stdout>"
yy39: yych = *++YYCURSOR;
@ -344,7 +345,7 @@ yy42: yych = *++YYCURSOR;
yy43: ++YYCURSOR;
goto yy44;
yy44:
#line 108 "implicit.re"
#line 109 "implicit.re"
{ return "float#nan"; }
#line 301 "<stdout>"
yy45: yych = *++YYCURSOR;
@ -426,7 +427,7 @@ yy51: switch(yych){
yy52: ++YYCURSOR;
goto yy53;
yy53:
#line 96 "implicit.re"
#line 97 "implicit.re"
{ return "int"; }
#line 386 "<stdout>"
yy54: ++YYCURSOR;
@ -450,7 +451,7 @@ yy55: switch(yych){
yy56: ++YYCURSOR;
goto yy57;
yy57:
#line 98 "implicit.re"
#line 99 "implicit.re"
{ return "float#fix"; }
#line 411 "<stdout>"
yy58: ++YYCURSOR;
@ -500,7 +501,7 @@ yy63: switch(yych){
yy64: ++YYCURSOR;
goto yy65;
yy65:
#line 100 "implicit.re"
#line 101 "implicit.re"
{ return "float#exp"; }
#line 463 "<stdout>"
yy66: ++YYCURSOR;
@ -552,13 +553,13 @@ yy69: switch(yych){
yy70: ++YYCURSOR;
goto yy71;
yy71:
#line 94 "implicit.re"
#line 95 "implicit.re"
{ return "int#base60"; }
#line 518 "<stdout>"
yy72: ++YYCURSOR;
goto yy73;
yy73:
#line 102 "implicit.re"
#line 103 "implicit.re"
{ return "float#base60"; }
#line 524 "<stdout>"
yy74: yych = *++YYCURSOR;
@ -661,7 +662,7 @@ yy81: yych = *++YYCURSOR;
yy82: ++YYCURSOR;
goto yy83;
yy83:
#line 110 "implicit.re"
#line 111 "implicit.re"
{ return "timestamp#ymd"; }
#line 627 "<stdout>"
yy84: yych = *++YYCURSOR;
@ -878,7 +879,7 @@ yy104: yych = *++YYCURSOR;
yy105: ++YYCURSOR;
goto yy106;
yy106:
#line 114 "implicit.re"
#line 115 "implicit.re"
{ return "timestamp#spaced"; }
#line 847 "<stdout>"
yy107: yych = *++YYCURSOR;
@ -1063,7 +1064,7 @@ yy122: yych = *++YYCURSOR;
yy123: ++YYCURSOR;
goto yy124;
yy124:
#line 112 "implicit.re"
#line 113 "implicit.re"
{ return "timestamp#iso8601"; }
#line 1033 "<stdout>"
yy125: yych = *++YYCURSOR;
@ -1301,13 +1302,13 @@ yy146: switch(yych){
yy147: ++YYCURSOR;
goto yy148;
yy148:
#line 90 "implicit.re"
#line 91 "implicit.re"
{ return "int#hex"; }
#line 1275 "<stdout>"
yy149: ++YYCURSOR;
goto yy150;
yy150:
#line 92 "implicit.re"
#line 93 "implicit.re"
{ return "int#oct"; }
#line 1281 "<stdout>"
yy151: ++YYCURSOR;
@ -1406,7 +1407,7 @@ yy163: yych = *++YYCURSOR;
yy164: ++YYCURSOR;
goto yy165;
yy165:
#line 106 "implicit.re"
#line 107 "implicit.re"
{ return "float#neginf"; }
#line 1381 "<stdout>"
yy166: yych = *++YYCURSOR;
@ -1446,7 +1447,7 @@ yy172: yych = *++YYCURSOR;
yy173: ++YYCURSOR;
goto yy174;
yy174:
#line 88 "implicit.re"
#line 89 "implicit.re"
{ return "bool#no"; }
#line 1421 "<stdout>"
yy175: yych = *++YYCURSOR;
@ -1490,7 +1491,7 @@ yy182: yych = *++YYCURSOR;
yy183: ++YYCURSOR;
goto yy184;
yy184:
#line 86 "implicit.re"
#line 87 "implicit.re"
{ return "bool#yes"; }
#line 1465 "<stdout>"
yy185: yych = *++YYCURSOR;
@ -1577,11 +1578,36 @@ yy201: ++YYCURSOR;
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 *
syck_type_id_to_uri( char *type_id )
{
@ -1737,7 +1763,7 @@ yy205: yyaccept = 0;
default: goto yy206;
}
yy206:
#line 176 "implicit.re"
#line 202 "implicit.re"
{ return syck_taguri( YAML_DOMAIN, type_id, strlen( type_id ) ); }
#line 1700 "<stdout>"
yy207: yyaccept = 0;
@ -1811,7 +1837,7 @@ yy207: yyaccept = 0;
yy208: ++YYCURSOR;
goto yy209;
yy209:
#line 150 "implicit.re"
#line 176 "implicit.re"
{ return syck_xprivate( type_id + 1, strlen( type_id ) - 1 ); }
#line 1774 "<stdout>"
yy210: yyaccept = 0;
@ -2107,7 +2133,7 @@ yy217: ++YYCURSOR;
yy218: ++YYCURSOR;
goto yy219;
yy219:
#line 152 "implicit.re"
#line 178 "implicit.re"
{ char *domain = S_ALLOC_N( char, ( YYCURSOR - type_id ) + 15 );
char *uri;
@ -2325,7 +2351,7 @@ yy228: yych = *++YYCURSOR;
yy229: ++YYCURSOR;
goto yy230;
yy230:
#line 165 "implicit.re"
#line 191 "implicit.re"
{ char *domain = S_ALLOC_N( char, YYCURSOR - type_id );
char *uri;
@ -2454,7 +2480,7 @@ yy243: yych = *++YYCURSOR;
yy244: ++YYCURSOR;
goto yy245;
yy245:
#line 148 "implicit.re"
#line 174 "implicit.re"
{ return type_id; }
#line 2422 "<stdout>"
yy246: yych = *++YYCURSOR;
@ -2901,7 +2927,7 @@ yy263: yych = *++YYCURSOR;
yy264: ++YYCURSOR;
goto yy265;
yy265:
#line 146 "implicit.re"
#line 172 "implicit.re"
{ return type_id; }
#line 2874 "<stdout>"
yy266: yych = *++YYCURSOR;
@ -2958,8 +2984,7 @@ yy270: ++YYCURSOR;
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 );
if ( n->type_id != NULL )
{
S_FREE( n->type_id );
n->type_id = NULL;
}
if ( n->anchor != NULL )
{
S_FREE( n->anchor );
n->anchor = NULL;
}
S_FREE( n );
}
@ -46,6 +52,7 @@ syck_alloc_map()
struct SyckMap *m;
m = S_ALLOC( struct SyckMap );
m->style = map_none;
m->idx = 0;
m->capa = ALLOC_CT;
m->keys = S_ALLOC_N( SYMID, m->capa );
@ -64,6 +71,7 @@ syck_alloc_seq()
struct SyckSeq *s;
s = S_ALLOC( struct SyckSeq );
s->style = seq_none;
s->idx = 0;
s->capa = ALLOC_CT;
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;
}
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
syck_str_blow_away_commas( SyckNode *n )
{
@ -148,6 +178,22 @@ syck_new_map( SYMID key, SYMID value )
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
syck_map_add( SyckNode *map, SYMID key, SYMID value )
{
@ -257,6 +303,20 @@ syck_new_seq( SYMID value )
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
syck_seq_add( SyckNode *arr, SYMID value )
{
@ -285,6 +345,17 @@ syck_seq_count( SyckNode *seq )
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
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
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
*/
@ -238,6 +229,15 @@ syck_st_free( SyckParser *p )
void
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
*/

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

@ -6,8 +6,10 @@
# Author:: why the lucky stiff
#
require 'stringio'
require 'yaml/error'
require 'yaml/syck'
require 'yaml/loader'
require 'yaml/tag'
require 'yaml/stream'
# == YAML
@ -73,7 +75,7 @@ require 'yaml/stream'
# ruby_obj == test_obj
# # => 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|
# Widget.new( val )
@ -81,9 +83,21 @@ require 'yaml/stream'
#
module YAML
@@parser = YAML::Syck::Parser
@@loader = YAML::Syck::DefaultLoader
@@emitter = YAML::Syck::Emitter
Resolver = YAML::Syck::Resolver
DefaultResolver = YAML::Syck::DefaultResolver
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_.
@ -99,9 +113,8 @@ module YAML
# #=> "--- :locked"
#
def YAML.dump( obj, io = nil )
io ||= ""
io << obj.to_yaml
io
obj.to_yaml( io || io2 = StringIO.new )
io || ( io2.rewind; io2.read )
end
#
@ -116,7 +129,7 @@ module YAML
# #=> :locked
#
def YAML.load( io )
yp = @@parser.new.load( io )
yp = parser.load( io )
end
#
@ -153,13 +166,13 @@ module YAML
#
# Can also load from a string.
#
# YAML.load( "--- :locked" )
# YAML.parse( "--- :locked" )
# #=> #<YAML::Syck::Node:0x82edddc
# @type_id="tag:ruby.yaml.org,2002:sym",
# @value=":locked", @kind=:scalar>
#
def YAML.parse( io )
yp = @@parser.new( :Model => :Generic ).load( io )
yp = generic_parser.load( io )
end
#
@ -200,7 +213,7 @@ module YAML
# end
#
def YAML.each_document( io, &block )
yp = @@parser.new.load_documents( io, &block )
yp = parser.load_documents( io, &block )
end
#
@ -230,7 +243,7 @@ module YAML
# end
#
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
#
@ -254,12 +267,11 @@ module YAML
# loaded documents.
#
def YAML.load_stream( io )
yp = @@parser.new
d = nil
yp.load_documents( io ) { |doc|
d = YAML::Stream.new( yp.options ) if not d
parser.load_documents( io ) do |doc|
d = YAML::Stream.new if not d
d.add( doc )
}
end
return d
end
@ -283,43 +295,50 @@ module YAML
#
# Add a global handler for a YAML domain type.
#
def YAML.add_domain_type( domain, type_re, &transfer_proc )
@@loader.add_domain_type( domain, type_re, &transfer_proc )
def YAML.add_domain_type( domain, type_tag, &transfer_proc )
resolver.add_type( "tag:#{ domain }:#{ type_tag }", transfer_proc )
end
#
# Add a transfer method for a builtin type
#
def YAML.add_builtin_type( type_re, &transfer_proc )
@@loader.add_builtin_type( type_re, &transfer_proc )
def YAML.add_builtin_type( type_tag, &transfer_proc )
resolver.add_type( "tag:yaml.org,2002:#{ type_tag }", transfer_proc )
end
#
# Add a transfer method for a builtin type
#
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
#
# Add a private document type
#
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
#
# Detect typing of a string
#
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
#
# Apply a transfer method to a Ruby object
#
def YAML.transfer( type_id, obj )
@@loader.transfer( type_id, obj )
resolver.transfer( YAML.tagurize( type_id ), obj )
end
#
@ -358,24 +377,13 @@ module YAML
# Allocate an Emitter if needed
#
def YAML.quick_emit( oid, opts = {}, &e )
old_opt = nil
if opts[:Emitter].is_a? @@emitter
out = opts.delete( :Emitter )
old_opt = out.options.dup
out.options.update( opts )
else
out = @@emitter.new( opts )
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
out =
if opts.is_a? YAML::Emitter
opts
else
emitter.reset( opts )
end
out.emit( oid, &e )
end
end
@ -383,7 +391,7 @@ end
require 'yaml/rubytypes'
require 'yaml/types'
module Kernel
module Kernel # :nodoc:
#
# 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
@ -400,12 +408,25 @@ module Kernel
# ryan:: Either way, I certainly will have a pony parade.
#
def y( o, *x )
x.unshift o
puts( if x.length == 1
YAML::dump( *x )
# Prints any supplied _objects_ out in YAML. Intended as
# a variation on +Kernel::p+.
#
# 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
YAML::dump_stream( *x )
YAML::dump_stream( *objects )
end )
end
private :y

View file

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

View file

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

View file

@ -1,9 +1,9 @@
# -*- mode: ruby; ruby-indent-level: 4; tab-width: 4 -*- vim: sw=4 ts=4
require 'date'
#
# Type conversions
#
class Class
def to_yaml( opts = {} )
raise TypeError, "can't dump anonymous class %s" % self.class
@ -11,564 +11,377 @@ class Class
end
class Object
def is_complex_yaml?
true
end
def to_yaml_type
"!ruby/object:#{self.class}"
end
def to_yaml_properties
instance_variables.sort
end
yaml_as "tag:ruby.yaml.org,2002:object"
def to_yaml_style; end
def to_yaml_properties; instance_variables.sort; end
def to_yaml( opts = {} )
YAML::quick_emit( self.object_id, opts ) { |out|
out.map( self.to_yaml_type ) { |map|
to_yaml_properties.each { |m|
YAML::quick_emit( object_id, opts ) do |out|
out.map( taguri, to_yaml_style ) do |map|
to_yaml_properties.each do |m|
map.add( m[1..-1], instance_variable_get( m ) )
}
}
}
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
#
class Hash
def is_complex_yaml?
true
end
def to_yaml_type
if self.class == Hash or self.class == YAML::SpecialHash
"!map"
yaml_as "tag:ruby.yaml.org,2002:hash"
yaml_as "tag:yaml.org,2002:map"
def yaml_initialize( tag, val )
if Array === val
update Hash.[]( *val ) # Convert the map to a sequence
elsif Hash === val
update val
else
"!ruby/hash:#{self.class}"
raise YAML::TypeError, "Invalid map explicitly tagged #{ tag }: " + val.inspect
end
end
def to_yaml( opts = {} )
opts[:DocType] = self.class if Hash === opts
YAML::quick_emit( self.object_id, opts ) { |out|
hash_type = to_yaml_type
if not out.options(:ExplicitTypes) and hash_type == "!map"
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 )
YAML::quick_emit( object_id, opts ) do |out|
out.map( taguri, to_yaml_style ) do |map|
each do |k, v|
map.add( k, v )
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
val
end
def has_key?( k )
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
#
class Struct
def is_complex_yaml?
true
yaml_as "tag:ruby.yaml.org,2002:struct"
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
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
#
struct_name = self.class.name.gsub( "Struct::", "" )
out.map( "!ruby/struct:#{struct_name}" ) { |map|
self.members.each { |m|
out.map( taguri, to_yaml_style ) do |map|
self.members.each do |m|
map.add( m, self[m] )
}
self.to_yaml_properties.each { |m|
end
self.to_yaml_properties.each do |m|
map.add( m, instance_variable_get( m ) )
}
}
}
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
#
class Array
def is_complex_yaml?
true
end
def to_yaml_type
if self.class == Array
"!seq"
else
"!ruby/array:#{self.class}"
end
end
yaml_as "tag:ruby.yaml.org,2002:array"
yaml_as "tag:yaml.org,2002:seq"
def yaml_initialize( tag, val ); concat( val.to_a ); end
def to_yaml( opts = {} )
opts[:DocType] = self.class if Hash === opts
YAML::quick_emit( self.object_id, opts ) { |out|
array_type = to_yaml_type
if not out.options(:ExplicitTypes) and array_type == "!seq"
array_type = ""
YAML::quick_emit( object_id, opts ) do |out|
out.seq( taguri, to_yaml_style ) do |seq|
each do |x|
seq.add( x )
end
end
out.seq( array_type ) { |seq|
seq.concat( self )
}
}
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
#
class Exception
def is_complex_yaml?
true
end
def to_yaml_type
"!ruby/exception:#{self.class}"
yaml_as "tag:ruby.yaml.org,2002:exception"
def Exception.yaml_new( klass, tag, val )
o = YAML.object_maker( klass, { 'mesg' => val.delete( 'message' ) } )
val.each_pair do |k,v|
o.instance_variable_set("@#{k}", v)
end
o
end
def to_yaml( opts = {} )
YAML::quick_emit( self.object_id, opts ) { |out|
out.map( self.to_yaml_type ) { |map|
map.add( 'message', self.message )
to_yaml_properties.each { |m|
YAML::quick_emit( object_id, opts ) do |out|
out.map( taguri, to_yaml_style ) do |map|
map.add( 'message', message )
to_yaml_properties.each do |m|
map.add( m[1..-1], instance_variable_get( m ) )
}
}
}
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
#
class String
yaml_as "tag:ruby.yaml.org,2002:string"
yaml_as "tag:yaml.org,2002:str"
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
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
def to_yaml_type
"!ruby/string#{ ":#{ self.class }" if self.class != ::String }"
end
def to_yaml_fold
nil
def String.yaml_new( klass, tag, val )
val = { 'str' => val } if String === val
if Hash === val
s = klass.allocate
# 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
def to_yaml( opts = {} )
complex = false
if self.is_complex_yaml?
complex = true
elsif opts[:BestWidth].to_i > 0
if self.length > opts[:BestWidth] and opts[:UseFold]
complex = true
YAML::quick_emit( is_complex_yaml? ? object_id : nil, opts ) do |out|
if is_binary_data?
out.scalar( "tag:yaml.org,2002:binary", [self].pack("m"), :literal )
elsif to_yaml_properties.empty?
out.scalar( taguri, self, to_yaml_style )
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
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
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
#
class Symbol
def is_complex_yaml?
false
yaml_as "tag:ruby.yaml.org,2002:symbol"
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
def to_yaml( opts = {} )
YAML::quick_emit( nil, opts ) { |out|
out << ":"
self.id2name.to_yaml( :Emitter => out )
}
YAML::quick_emit( nil, opts ) do |out|
out.scalar( taguri, self.id2name, :plain )
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
# TODO: Rework the Range as a sequence (simpler)
#
class Range
def is_complex_yaml?
true
end
def to_yaml_type
"!ruby/range#{ if self.class != ::Range; ":#{ self.class }"; end }"
yaml_as "tag:ruby.yaml.org,2002:range"
def Range.yaml_new( klass, tag, val )
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( 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
def to_yaml( opts = {} )
YAML::quick_emit( self.object_id, opts ) { |out|
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
not to_yaml_properties.empty?
out.map( to_yaml_type ) { |map|
YAML::quick_emit( object_id, opts ) do |out|
# 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
# not to_yaml_properties.empty?
out.map( taguri, to_yaml_style ) do |map|
map.add( 'begin', self.begin )
map.add( 'end', self.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 ) )
}
}
else
out << "#{ to_yaml_type } '"
self.begin.to_yaml(:Emitter => out)
out << ( self.exclude_end? ? "..." : ".." )
self.end.to_yaml(:Emitter => out)
out << "'"
end
}
end
end
# else
# out.scalar( taguri ) do |sc|
# sc.embed( self.begin )
# sc.concat( self.exclude_end? ? "..." : ".." )
# sc.embed( self.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
#
class Regexp
def is_complex_yaml?
self.class != Regexp or not to_yaml_properties.empty?
end
def to_yaml_type
"!ruby/regexp#{ if self.class != ::Regexp; ":#{ self.class }"; end }"
yaml_as "tag:ruby.yaml.org,2002:regexp"
def Regexp.yaml_new( klass, tag, val )
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( 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
def to_yaml( opts = {} )
YAML::quick_emit( nil, opts ) { |out|
if self.is_complex_yaml?
out.map( self.to_yaml_type ) { |map|
YAML::quick_emit( nil, opts ) do |out|
if to_yaml_properties.empty?
out.scalar( taguri, self.inspect, :plain )
else
out.map( taguri, to_yaml_style ) do |map|
src = self.inspect
if src =~ /\A\/(.*)\/([a-z]*)\Z/
map.add( 'regexp', $1 )
map.add( 'mods', $2 )
else
raise YAML::Error, "Invalid Regular expression: " + src
raise YAML::TypeError, "Invalid Regular expression: " + src
end
to_yaml_properties.each { |m|
to_yaml_properties.each do |m|
map.add( m, instance_variable_get( m ) )
}
}
else
out << "#{ to_yaml_type } "
self.inspect.to_yaml( :Emitter => out )
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
#
class Time
def is_complex_yaml?
self.class != Time or not to_yaml_properties.empty?
end
def to_yaml_type
"!ruby/time#{ if self.class != ::Time; ":#{ self.class }"; end }"
yaml_as "tag:ruby.yaml.org,2002:time"
yaml_as "tag:yaml.org,2002:timestamp"
def Time.yaml_new( klass, tag, val )
if Hash === val
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
def to_yaml( opts = {} )
YAML::quick_emit( nil, opts ) { |out|
if self.is_complex_yaml?
out.map( self.to_yaml_type ) { |map|
map.add( 'at', ::Time.at( self ) )
to_yaml_properties.each { |m|
map.add( m, instance_variable_get( m ) )
}
}
else
tz = "Z"
# from the tidy Tobias Peters <t-peters@gmx.de> Thanks!
unless self.utc?
utc_same_instant = self.dup.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]
YAML::quick_emit( object_id, opts ) do |out|
tz = "Z"
# from the tidy Tobias Peters <t-peters@gmx.de> Thanks!
unless self.utc?
utc_same_instant = self.dup.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
standard = self.strftime( "%Y-%m-%d %H:%M:%S" )
standard += ".%06d" % [usec] if usec.nonzero?
standard += " %s" % [tz]
standard.to_yaml( :Emitter => out, :KeepValue => true )
difference_minutes = (absolute_difference/60).round
tz = "%s%02d:%02d" % [ difference_sign, difference_minutes / 60, difference_minutes % 60]
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
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
#
class Date
def is_complex_yaml?
false
end
yaml_as "tag:yaml.org,2002:timestamp#ymd"
def to_yaml( opts = {} )
opts[:KeepValue] = true
self.to_s.to_yaml( opts )
YAML::quick_emit( object_id, opts ) do |out|
out.scalar( "tag:yaml.org,2002:timestamp", self.to_s, :plain )
end
end
end
@ -576,50 +389,51 @@ end
# Send Integer, Booleans, NilClass to String
#
class Numeric
def is_complex_yaml?
false
end
def to_yaml( opts = {} )
str = self.to_s
if str == "Infinity"
str = ".Inf"
elsif str == "-Infinity"
str = "-.Inf"
elsif str == "NaN"
str = ".NaN"
end
opts[:KeepValue] = true
str.to_yaml( opts )
YAML::quick_emit( nil, opts ) do |out|
str = self.to_s
if str == "Infinity"
str = ".Inf"
elsif str == "-Infinity"
str = "-.Inf"
elsif str == "NaN"
str = ".NaN"
end
out.scalar( taguri, str, :plain )
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
def is_complex_yaml?
false
end
yaml_as "tag:yaml.org,2002:bool#yes"
def to_yaml( opts = {} )
opts[:KeepValue] = true
"true".to_yaml( opts )
YAML::quick_emit( nil, opts ) do |out|
out.scalar( taguri, "true", :plain )
end
end
end
class FalseClass
def is_complex_yaml?
false
end
yaml_as "tag:yaml.org,2002:bool#no"
def to_yaml( opts = {} )
opts[:KeepValue] = true
"false".to_yaml( opts )
YAML::quick_emit( nil, opts ) do |out|
out.scalar( taguri, "false", :plain )
end
end
end
class NilClass
def is_complex_yaml?
false
end
yaml_as "tag:yaml.org,2002:null"
def to_yaml( opts = {} )
opts[:KeepValue] = true
"".to_yaml( opts )
YAML::quick_emit( nil, opts ) do |out|
out.scalar( taguri, "", :plain )
end
end
end

View file

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

View file

@ -4,7 +4,6 @@
#
require 'syck'
require 'yaml/basenode'
require 'yaml/baseemitter'
module YAML
module Syck
@ -16,12 +15,5 @@ module YAML
include YAML::BaseNode
end
#
# Mixin BaseEmitter functionality
#
class Emitter
include YAML::BaseEmitter
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
#
class PrivateType
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 = {} )
YAML::quick_emit( self.object_id, opts ) { |out|
out << " !!#{@type_id}"
value.to_yaml( :Emitter => out )
}
@value.to_yaml( opts )
end
end
@ -24,29 +23,37 @@ module YAML
# Default domain type
#
class DomainType
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_type
dom = @domain.dup
if dom =~ /\.yaml\.org,2002$/
dom = $`
end
"#{dom}/#{@type_id}"
end
def to_yaml( opts = {} )
YAML::quick_emit( self.object_id, opts ) { |out|
out << " !#{to_yaml_type} "
value.to_yaml( :Emitter => out )
}
@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
@ -69,12 +76,27 @@ module YAML
#
# 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 )
o = Omap.new
0.step( vals.length - 1, 2 ) { |i|
0.step( vals.length - 1, 2 ) do |i|
o[vals[i]] = vals[i+1]
}
end
o
end
def []( k )
@ -96,36 +118,35 @@ module YAML
true
end
def to_yaml( opts = {} )
YAML::quick_emit( self.object_id, opts ) { |out|
out.seq( "!omap" ) { |seq|
self.each { |v|
YAML::quick_emit( self.object_id, opts ) do |out|
out.seq( taguri, to_yaml_style ) do |seq|
self.each do |v|
seq.add( Hash[ *v ] )
}
}
}
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
#
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 )
p = Pairs.new
0.step( vals.length - 1, 2 ) { |i|
@ -147,50 +168,20 @@ module YAML
true
end
def to_yaml( opts = {} )
YAML::quick_emit( self.object_id, opts ) { |out|
out.seq( "!pairs" ) { |seq|
self.each { |v|
YAML::quick_emit( self.object_id, opts ) do |out|
out.seq( taguri, to_yaml_style ) do |seq|
self.each do |v|
seq.add( Hash[ *v ] )
}
}
}
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
#
class Set < Hash
def to_yaml_type
"!set"
end
class Set < ::Hash
yaml_as "tag:yaml.org,2002:set"
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