syck 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.autotest.erb +8 -0
- data/.gemtest +0 -0
- data/CHANGELOG.rdoc +6 -0
- data/Manifest.txt +52 -0
- data/README.rdoc +51 -0
- data/Rakefile +32 -0
- data/ext/syck/bytecode.c +1165 -0
- data/ext/syck/emitter.c +1247 -0
- data/ext/syck/extconf.h +3 -0
- data/ext/syck/extconf.rb +5 -0
- data/ext/syck/gram.c +1894 -0
- data/ext/syck/gram.h +79 -0
- data/ext/syck/handler.c +173 -0
- data/ext/syck/implicit.c +2990 -0
- data/ext/syck/node.c +407 -0
- data/ext/syck/rubyext.c +2328 -0
- data/ext/syck/syck.c +524 -0
- data/ext/syck/syck.h +453 -0
- data/ext/syck/token.c +2724 -0
- data/ext/syck/yaml2byte.c +259 -0
- data/ext/syck/yamlbyte.h +171 -0
- data/lib/syck.bundle +0 -0
- data/lib/syck.rb +447 -0
- data/lib/syck/baseemitter.rb +242 -0
- data/lib/syck/basenode.rb +222 -0
- data/lib/syck/constants.rb +45 -0
- data/lib/syck/encoding.rb +35 -0
- data/lib/syck/error.rb +34 -0
- data/lib/syck/loader.rb +14 -0
- data/lib/syck/rubytypes.rb +450 -0
- data/lib/syck/stream.rb +41 -0
- data/lib/syck/stringio.rb +85 -0
- data/lib/syck/syck.rb +16 -0
- data/lib/syck/tag.rb +95 -0
- data/lib/syck/types.rb +192 -0
- data/lib/syck/yamlnode.rb +54 -0
- data/lib/syck/ypath.rb +54 -0
- data/lib/yaml/syck.rb +14 -0
- data/test/helper.rb +2 -0
- data/test/test_array.rb +13 -0
- data/test/test_boolean.rb +36 -0
- data/test/test_class.rb +11 -0
- data/test/test_exception.rb +45 -0
- data/test/test_hash.rb +24 -0
- data/test/test_null.rb +19 -0
- data/test/test_omap.rb +55 -0
- data/test/test_set.rb +30 -0
- data/test/test_string.rb +44 -0
- data/test/test_struct.rb +32 -0
- data/test/test_symbol.rb +21 -0
- data/test/test_time.rb +23 -0
- data/test/test_yaml.rb +1403 -0
- data/test/test_yaml_properties.rb +63 -0
- metadata +187 -0
@@ -0,0 +1,259 @@
|
|
1
|
+
/*
|
2
|
+
* yaml2byte.c
|
3
|
+
*
|
4
|
+
* $Author$
|
5
|
+
*
|
6
|
+
* Copyright (C) 2003 why the lucky stiff, clark evans
|
7
|
+
*
|
8
|
+
* WARNING WARNING WARNING --- THIS IS *NOT JUST* PLAYING
|
9
|
+
* ANYMORE! -- WHY HAS EMBRACED THIS AS THE REAL THING!
|
10
|
+
*/
|
11
|
+
#include "ruby/ruby.h"
|
12
|
+
#include <syck.h>
|
13
|
+
#include <assert.h>
|
14
|
+
#define YAMLBYTE_UTF8
|
15
|
+
#include "yamlbyte.h"
|
16
|
+
|
17
|
+
#include <stdio.h>
|
18
|
+
#define TRACE0(a) \
|
19
|
+
do { printf(a); printf("\n"); fflush(stdout); } while(0)
|
20
|
+
#define TRACE1(a,b) \
|
21
|
+
do { printf(a,b); printf("\n"); fflush(stdout); } while(0)
|
22
|
+
#define TRACE2(a,b,c) \
|
23
|
+
do { printf(a,b,c); printf("\n"); fflush(stdout); } while(0)
|
24
|
+
#define TRACE3(a,b,c,d) \
|
25
|
+
do { printf(a,b,c,d); printf("\n"); fflush(stdout); } while(0)
|
26
|
+
|
27
|
+
/* Reinvent the wheel... */
|
28
|
+
#define CHUNKSIZE 64
|
29
|
+
#define HASH ((long)0xCAFECAFE)
|
30
|
+
typedef struct {
|
31
|
+
long hash;
|
32
|
+
char *buffer;
|
33
|
+
long length;
|
34
|
+
long remaining;
|
35
|
+
int printed;
|
36
|
+
} bytestring_t;
|
37
|
+
bytestring_t *bytestring_alloc(void) {
|
38
|
+
bytestring_t *ret;
|
39
|
+
/*TRACE0("bytestring_alloc()");*/
|
40
|
+
ret = S_ALLOC(bytestring_t);
|
41
|
+
ret->hash = HASH;
|
42
|
+
ret->length = CHUNKSIZE;
|
43
|
+
ret->remaining = ret->length;
|
44
|
+
ret->buffer = S_ALLOC_N(char, ret->length + 1 );
|
45
|
+
ret->buffer[0] = 0;
|
46
|
+
ret->printed = 0;
|
47
|
+
return ret;
|
48
|
+
}
|
49
|
+
void bytestring_append(bytestring_t *str, char code,
|
50
|
+
char *start, char *finish)
|
51
|
+
{
|
52
|
+
long grow;
|
53
|
+
long length = 2; /* CODE + LF */
|
54
|
+
char *curr;
|
55
|
+
assert(str && HASH == str->hash);
|
56
|
+
/*TRACE0("bytestring_append()");*/
|
57
|
+
if(start) {
|
58
|
+
if(!finish)
|
59
|
+
finish = start + strlen(start);
|
60
|
+
length += (finish-start);
|
61
|
+
}
|
62
|
+
if(length > str->remaining) {
|
63
|
+
grow = (length - str->remaining) + CHUNKSIZE;
|
64
|
+
str->remaining += grow;
|
65
|
+
str->length += grow;
|
66
|
+
S_REALLOC_N( str->buffer, char, str->length + 1 );
|
67
|
+
assert(str->buffer);
|
68
|
+
}
|
69
|
+
curr = str->buffer + (str->length - str->remaining);
|
70
|
+
*curr = code;
|
71
|
+
curr += 1;
|
72
|
+
if(start)
|
73
|
+
while(start < finish)
|
74
|
+
*curr ++ = *start ++;
|
75
|
+
*curr = '\n';
|
76
|
+
curr += 1;
|
77
|
+
*curr = 0;
|
78
|
+
str->remaining = str->remaining - length;
|
79
|
+
assert( (str->buffer + str->length) - str->remaining );
|
80
|
+
}
|
81
|
+
void bytestring_extend(bytestring_t *str, bytestring_t *ext)
|
82
|
+
{
|
83
|
+
char *from;
|
84
|
+
char *curr;
|
85
|
+
char *stop;
|
86
|
+
long grow;
|
87
|
+
long length;
|
88
|
+
assert(str && HASH == str->hash);
|
89
|
+
assert(ext && HASH == ext->hash);
|
90
|
+
if(ext->printed) {
|
91
|
+
assert(ext->buffer[0] ==YAMLBYTE_ANCHOR);
|
92
|
+
curr = ext->buffer;
|
93
|
+
while( '\n' != *curr)
|
94
|
+
curr++;
|
95
|
+
bytestring_append(str, YAMLBYTE_ALIAS, ext->buffer + 1, curr);
|
96
|
+
} else {
|
97
|
+
ext->printed = 1;
|
98
|
+
length = (ext->length - ext->remaining);
|
99
|
+
if(length > str->remaining) {
|
100
|
+
grow = (length - str->remaining) + CHUNKSIZE;
|
101
|
+
str->remaining += grow;
|
102
|
+
str->length += grow;
|
103
|
+
S_REALLOC_N( str->buffer, char, str->length + 1 );
|
104
|
+
}
|
105
|
+
curr = str->buffer + (str->length - str->remaining);
|
106
|
+
from = ext->buffer;
|
107
|
+
stop = ext->buffer + length;
|
108
|
+
while( from < stop )
|
109
|
+
*curr ++ = *from ++;
|
110
|
+
*curr = 0;
|
111
|
+
str->remaining = str->remaining - length;
|
112
|
+
assert( (str->buffer + str->length) - str->remaining );
|
113
|
+
}
|
114
|
+
}
|
115
|
+
|
116
|
+
/* convert SyckNode into yamlbyte_buffer_t objects */
|
117
|
+
SYMID
|
118
|
+
syck_yaml2byte_handler(p, n)
|
119
|
+
SyckParser *p;
|
120
|
+
SyckNode *n;
|
121
|
+
{
|
122
|
+
SYMID oid;
|
123
|
+
long i;
|
124
|
+
char ch;
|
125
|
+
char nextcode;
|
126
|
+
char *start;
|
127
|
+
char *current;
|
128
|
+
char *finish;
|
129
|
+
bytestring_t *val = NULL;
|
130
|
+
bytestring_t *sav = NULL;
|
131
|
+
void *data;
|
132
|
+
/*TRACE0("syck_yaml2byte_handler()");*/
|
133
|
+
val = bytestring_alloc();
|
134
|
+
if(n->anchor) bytestring_append(val,YAMLBYTE_ANCHOR, n->anchor, NULL);
|
135
|
+
if ( n->type_id )
|
136
|
+
{
|
137
|
+
if ( p->taguri_expansion )
|
138
|
+
{
|
139
|
+
bytestring_append(val,YAMLBYTE_TRANSFER, n->type_id, NULL);
|
140
|
+
}
|
141
|
+
else
|
142
|
+
{
|
143
|
+
char *type_tag = S_ALLOC_N( char, strlen( n->type_id ) + 1 );
|
144
|
+
type_tag[0] = '\0';
|
145
|
+
strcat( type_tag, "!" );
|
146
|
+
strcat( type_tag, n->type_id );
|
147
|
+
bytestring_append( val, YAMLBYTE_TRANSFER, type_tag, NULL);
|
148
|
+
S_FREE(type_tag);
|
149
|
+
}
|
150
|
+
}
|
151
|
+
switch (n->kind)
|
152
|
+
{
|
153
|
+
case syck_str_kind:
|
154
|
+
nextcode = YAMLBYTE_SCALAR;
|
155
|
+
start = n->data.str->ptr;
|
156
|
+
finish = start + n->data.str->len - 1;
|
157
|
+
current = start;
|
158
|
+
/*TRACE2("SCALAR: %s %d", start, n->data.str->len); */
|
159
|
+
while(1) {
|
160
|
+
ch = *current;
|
161
|
+
if('\n' == ch || 0 == ch || current > finish) {
|
162
|
+
if(current >= start) {
|
163
|
+
bytestring_append(val, nextcode, start, current);
|
164
|
+
nextcode = YAMLBYTE_CONTINUE;
|
165
|
+
}
|
166
|
+
start = current + 1;
|
167
|
+
if(current > finish)
|
168
|
+
{
|
169
|
+
break;
|
170
|
+
}
|
171
|
+
else if('\n' == ch )
|
172
|
+
{
|
173
|
+
bytestring_append(val,YAMLBYTE_NEWLINE,NULL,NULL);
|
174
|
+
}
|
175
|
+
else if(0 == ch)
|
176
|
+
{
|
177
|
+
bytestring_append(val,YAMLBYTE_NULLCHAR,NULL,NULL);
|
178
|
+
}
|
179
|
+
else
|
180
|
+
{
|
181
|
+
assert("oops");
|
182
|
+
}
|
183
|
+
}
|
184
|
+
current += 1;
|
185
|
+
}
|
186
|
+
break;
|
187
|
+
case syck_seq_kind:
|
188
|
+
bytestring_append(val,YAMLBYTE_SEQUENCE,NULL,NULL);
|
189
|
+
for ( i = 0; i < n->data.list->idx; i++ )
|
190
|
+
{
|
191
|
+
oid = syck_seq_read( n, i );
|
192
|
+
if (syck_lookup_sym( p, oid, &data )) sav = data;
|
193
|
+
bytestring_extend(val, sav);
|
194
|
+
}
|
195
|
+
bytestring_append(val,YAMLBYTE_END_BRANCH,NULL,NULL);
|
196
|
+
break;
|
197
|
+
case syck_map_kind:
|
198
|
+
bytestring_append(val,YAMLBYTE_MAPPING,NULL,NULL);
|
199
|
+
for ( i = 0; i < n->data.pairs->idx; i++ )
|
200
|
+
{
|
201
|
+
oid = syck_map_read( n, map_key, i );
|
202
|
+
if (syck_lookup_sym( p, oid, &data )) sav = data;
|
203
|
+
bytestring_extend(val, sav);
|
204
|
+
oid = syck_map_read( n, map_value, i );
|
205
|
+
if (syck_lookup_sym( p, oid, &data )) sav = data;
|
206
|
+
bytestring_extend(val, sav);
|
207
|
+
}
|
208
|
+
bytestring_append(val,YAMLBYTE_END_BRANCH,NULL,NULL);
|
209
|
+
break;
|
210
|
+
}
|
211
|
+
oid = syck_add_sym( p, (char *) val );
|
212
|
+
/*TRACE1("Saving: %s", val->buffer );*/
|
213
|
+
return oid;
|
214
|
+
}
|
215
|
+
|
216
|
+
char *
|
217
|
+
syck_yaml2byte(char *yamlstr)
|
218
|
+
{
|
219
|
+
SYMID oid;
|
220
|
+
char *ret;
|
221
|
+
bytestring_t *sav;
|
222
|
+
void *data;
|
223
|
+
|
224
|
+
SyckParser *parser = syck_new_parser();
|
225
|
+
syck_parser_str_auto( parser, yamlstr, NULL );
|
226
|
+
syck_parser_handler( parser, syck_yaml2byte_handler );
|
227
|
+
syck_parser_error_handler( parser, NULL );
|
228
|
+
syck_parser_implicit_typing( parser, 1 );
|
229
|
+
syck_parser_taguri_expansion( parser, 1 );
|
230
|
+
oid = syck_parse( parser );
|
231
|
+
|
232
|
+
if ( syck_lookup_sym( parser, oid, &data ) ) {
|
233
|
+
sav = data;
|
234
|
+
ret = S_ALLOC_N( char, strlen( sav->buffer ) + 3 );
|
235
|
+
ret[0] = '\0';
|
236
|
+
strcat( ret, "D\n" );
|
237
|
+
strcat( ret, sav->buffer );
|
238
|
+
}
|
239
|
+
else
|
240
|
+
{
|
241
|
+
ret = NULL;
|
242
|
+
}
|
243
|
+
|
244
|
+
syck_free_parser( parser );
|
245
|
+
return ret;
|
246
|
+
}
|
247
|
+
|
248
|
+
#ifdef TEST_YBEXT
|
249
|
+
#include <stdio.h>
|
250
|
+
int main() {
|
251
|
+
char *yaml = "test: 1\nand: \"with new\\nline\\n\"\nalso: &3 three\nmore: *3";
|
252
|
+
printf("--- # YAML \n");
|
253
|
+
printf(yaml);
|
254
|
+
printf("\n...\n");
|
255
|
+
printf(syck_yaml2byte(yaml));
|
256
|
+
return 0;
|
257
|
+
}
|
258
|
+
#endif
|
259
|
+
|
data/ext/syck/yamlbyte.h
ADDED
@@ -0,0 +1,171 @@
|
|
1
|
+
/* yamlbyte.h
|
2
|
+
*
|
3
|
+
* The YAML bytecode "C" interface header file. See the YAML bytecode
|
4
|
+
* reference for bytecode sequence rules and for the meaning of each
|
5
|
+
* bytecode.
|
6
|
+
*/
|
7
|
+
|
8
|
+
#ifndef YAMLBYTE_H
|
9
|
+
#define YAMLBYTE_H
|
10
|
+
#include <stddef.h>
|
11
|
+
|
12
|
+
/* define what a character is */
|
13
|
+
typedef unsigned char yamlbyte_utf8_t;
|
14
|
+
typedef unsigned short yamlbyte_utf16_t;
|
15
|
+
#ifdef YAMLBYTE_UTF8
|
16
|
+
#ifdef YAMLBYTE_UTF16
|
17
|
+
#error Must only define YAMLBYTE_UTF8 or YAMLBYTE_UTF16
|
18
|
+
#endif
|
19
|
+
typedef yamlbyte_utf8_t yamlbyte_char_t;
|
20
|
+
#else
|
21
|
+
#ifdef YAMLBYTE_UTF16
|
22
|
+
typedef yamlbyte_utf16_t yamlbyte_char_t;
|
23
|
+
#else
|
24
|
+
#error Must define YAMLBYTE_UTF8 or YAMLBYTE_UTF16
|
25
|
+
#endif
|
26
|
+
#endif
|
27
|
+
|
28
|
+
/* specify list of bytecodes */
|
29
|
+
#define YAMLBYTE_FINISH ((yamlbyte_char_t) 0)
|
30
|
+
#define YAMLBYTE_DOCUMENT ((yamlbyte_char_t)'D')
|
31
|
+
#define YAMLBYTE_DIRECTIVE ((yamlbyte_char_t)'V')
|
32
|
+
#define YAMLBYTE_PAUSE ((yamlbyte_char_t)'P')
|
33
|
+
#define YAMLBYTE_MAPPING ((yamlbyte_char_t)'M')
|
34
|
+
#define YAMLBYTE_SEQUENCE ((yamlbyte_char_t)'Q')
|
35
|
+
#define YAMLBYTE_END_BRANCH ((yamlbyte_char_t)'E')
|
36
|
+
#define YAMLBYTE_SCALAR ((yamlbyte_char_t)'S')
|
37
|
+
#define YAMLBYTE_CONTINUE ((yamlbyte_char_t)'C')
|
38
|
+
#define YAMLBYTE_NEWLINE ((yamlbyte_char_t)'N')
|
39
|
+
#define YAMLBYTE_NULLCHAR ((yamlbyte_char_t)'Z')
|
40
|
+
#define YAMLBYTE_ANCHOR ((yamlbyte_char_t)'A')
|
41
|
+
#define YAMLBYTE_ALIAS ((yamlbyte_char_t)'R')
|
42
|
+
#define YAMLBYTE_TRANSFER ((yamlbyte_char_t)'T')
|
43
|
+
/* formatting bytecodes */
|
44
|
+
#define YAMLBYTE_COMMENT ((yamlbyte_char_t)'c')
|
45
|
+
#define YAMLBYTE_INDENT ((yamlbyte_char_t)'i')
|
46
|
+
#define YAMLBYTE_STYLE ((yamlbyte_char_t)'s')
|
47
|
+
/* other bytecodes */
|
48
|
+
#define YAMLBYTE_LINE_NUMBER ((yamlbyte_char_t)'#')
|
49
|
+
#define YAMLBYTE_WHOLE_SCALAR ((yamlbyte_char_t)'<')
|
50
|
+
#define YAMLBYTE_NOTICE ((yamlbyte_char_t)'!')
|
51
|
+
#define YAMLBYTE_SPAN ((yamlbyte_char_t)')')
|
52
|
+
#define YAMLBYTE_ALLOC ((yamlbyte_char_t)'@')
|
53
|
+
|
54
|
+
/* second level style bytecodes, ie "s>" */
|
55
|
+
#define YAMLBYTE_FLOW ((yamlbyte_char_t)'>')
|
56
|
+
#define YAMLBYTE_LITERAL ((yamlbyte_char_t)'|')
|
57
|
+
#define YAMLBYTE_BLOCK ((yamlbyte_char_t)'b')
|
58
|
+
#define YAMLBYTE_PLAIN ((yamlbyte_char_t)'p')
|
59
|
+
#define YAMLBYTE_INLINE_MAPPING ((yamlbyte_char_t)'{')
|
60
|
+
#define YAMLBYTE_INLINE_SEQUENCE ((yamlbyte_char_t)'[')
|
61
|
+
#define YAMLBYTE_SINGLE_QUOTED ((yamlbyte_char_t)39)
|
62
|
+
#define YAMLBYTE_DOUBLE_QUOTED ((yamlbyte_char_t)'"')
|
63
|
+
|
64
|
+
/*
|
65
|
+
* The "C" API has two variants, one based on instructions,
|
66
|
+
* with events delivered via pointers; and the other one
|
67
|
+
* is character based where one or more instructions are
|
68
|
+
* serialized into a buffer.
|
69
|
+
*
|
70
|
+
* Note: In the instruction based API, WHOLE_SCALAR does
|
71
|
+
* not have the '<here' marshalling stuff.
|
72
|
+
*/
|
73
|
+
|
74
|
+
typedef void * yamlbyte_consumer_t;
|
75
|
+
typedef void * yamlbyte_producer_t;
|
76
|
+
|
77
|
+
/* push and pull APIs need a way to communicate results */
|
78
|
+
typedef enum {
|
79
|
+
YAMLBYTE_OK = 0, /* proceed */
|
80
|
+
YAMLBYTE_E_MEMORY = 'M', /* could not allocate memory */
|
81
|
+
YAMLBYTE_E_READ = 'R', /* input stream read error */
|
82
|
+
YAMLBYTE_E_WRITE = 'W', /* output stream write error */
|
83
|
+
YAMLBYTE_E_OTHER = '?', /* some other error condition */
|
84
|
+
YAMLBYTE_E_PARSE = 'P', /* parse error, check bytecodes */
|
85
|
+
YAMLBYTE_MAX
|
86
|
+
} yamlbyte_result_t;
|
87
|
+
|
88
|
+
typedef const yamlbyte_char_t *yamlbyte_buff_t;
|
89
|
+
|
90
|
+
/*
|
91
|
+
* The "Instruction" API
|
92
|
+
*/
|
93
|
+
|
94
|
+
typedef struct yaml_instruction {
|
95
|
+
yamlbyte_char_t bytecode;
|
96
|
+
yamlbyte_buff_t start;
|
97
|
+
yamlbyte_buff_t finish; /* open range, *finish is _not_ part */
|
98
|
+
} *yamlbyte_inst_t;
|
99
|
+
|
100
|
+
/* producer pushes the instruction with one bytecode event to the
|
101
|
+
* consumer; if the consumer's result is not YAMLBYTE_OK, then
|
102
|
+
* the producer should stop */
|
103
|
+
typedef
|
104
|
+
yamlbyte_result_t
|
105
|
+
(*yamlbyte_push_t)(
|
106
|
+
yamlbyte_consumer_t self,
|
107
|
+
yamlbyte_inst_t inst
|
108
|
+
);
|
109
|
+
|
110
|
+
/* consumer pulls a bytecode instruction from the producer; in this
|
111
|
+
* case the instruction (and is buffer) are owned by the producer and
|
112
|
+
* will remain valid till the pull function is called once again;
|
113
|
+
* if the instruction is NULL, then there are no more results; and
|
114
|
+
* it is important to call the pull function till it returns NULL so
|
115
|
+
* that the producer can clean up its memory allocations */
|
116
|
+
typedef
|
117
|
+
yamlbyte_result_t
|
118
|
+
(*yamlbyte_pull_t)(
|
119
|
+
yamlbyte_producer_t self,
|
120
|
+
yamlbyte_inst_t *inst /* to be filled in by the producer */
|
121
|
+
);
|
122
|
+
|
123
|
+
/*
|
124
|
+
* Buffer based API
|
125
|
+
*/
|
126
|
+
|
127
|
+
/* producer pushes a null terminated buffer filled with one or more
|
128
|
+
* bytecode events to the consumer; if the consumer's result is not
|
129
|
+
* YAMLBYTE_OK, then the producer should stop */
|
130
|
+
typedef
|
131
|
+
yamlbyte_result_t
|
132
|
+
(*yamlbyte_pushbuff_t)(
|
133
|
+
yamlbyte_consumer_t self,
|
134
|
+
yamlbyte_buff_t buff
|
135
|
+
);
|
136
|
+
|
137
|
+
/* consumer pulls bytecode events from the producer; in this case
|
138
|
+
* the buffer is owned by the producer, and will remain valid till
|
139
|
+
* the pull function is called once again; if the buffer pointer
|
140
|
+
* is set to NULL, then there are no more results; it is important
|
141
|
+
* to call the pull function till it returns NULL so that the
|
142
|
+
* producer can clean up its memory allocations */
|
143
|
+
typedef
|
144
|
+
yamlbyte_result_t
|
145
|
+
(*yamlbyte_pullbuff_t)(
|
146
|
+
yamlbyte_producer_t self,
|
147
|
+
yamlbyte_buff_t *buff /* to be filled in by the producer */
|
148
|
+
);
|
149
|
+
|
150
|
+
/* convert a pull interface to a push interface; the reverse process
|
151
|
+
* requires threads and thus is language dependent */
|
152
|
+
#define YAMLBYTE_PULL2PUSH(pull,producer,push,consumer,result) \
|
153
|
+
do { \
|
154
|
+
yamlbyte_pullbuff_t _pull = (pull); \
|
155
|
+
yamlbyte_pushbuff_t _push = (push); \
|
156
|
+
yamlbyte_result_t _result = YAMLBYTE_OK; \
|
157
|
+
yamlbyte_producer_t _producer = (producer); \
|
158
|
+
yamlbyte_consumer_t _consumer = (consumer); \
|
159
|
+
while(1) { \
|
160
|
+
yamlbyte_buff_t buff = NULL; \
|
161
|
+
_result = _pull(_producer,&buff); \
|
162
|
+
if(YAMLBYTE_OK != result || NULL == buff) \
|
163
|
+
break; \
|
164
|
+
_result = _push(_consumer,buff); \
|
165
|
+
if(YAMLBYTE_OK != result) \
|
166
|
+
break; \
|
167
|
+
} \
|
168
|
+
(result) = _result; \
|
169
|
+
} while(0)
|
170
|
+
|
171
|
+
#endif
|
data/lib/syck.bundle
ADDED
Binary file
|
data/lib/syck.rb
ADDED
@@ -0,0 +1,447 @@
|
|
1
|
+
# -*- mode: ruby; ruby-indent-level: 4; tab-width: 4 -*- vim: sw=4 ts=4
|
2
|
+
# $Id$
|
3
|
+
#
|
4
|
+
# = yaml.rb: top-level module with methods for loading and parsing YAML documents
|
5
|
+
#
|
6
|
+
# Author:: why the lucky stiff
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'yaml/syck'
|
10
|
+
|
11
|
+
# == YAML
|
12
|
+
#
|
13
|
+
# YAML(tm) (rhymes with 'camel') is a
|
14
|
+
# straightforward machine parsable data serialization format designed for
|
15
|
+
# human readability and interaction with scripting languages such as Perl
|
16
|
+
# and Python. YAML is optimized for data serialization, formatted
|
17
|
+
# dumping, configuration files, log files, Internet messaging and
|
18
|
+
# filtering. This specification describes the YAML information model and
|
19
|
+
# serialization format. Together with the Unicode standard for characters, it
|
20
|
+
# provides all the information necessary to understand YAML Version 1.0
|
21
|
+
# and construct computer programs to process it.
|
22
|
+
#
|
23
|
+
# See http://yaml.org/ for more information. For a quick tutorial, please
|
24
|
+
# visit YAML In Five Minutes (http://yaml.kwiki.org/?YamlInFiveMinutes).
|
25
|
+
#
|
26
|
+
# == About This Library
|
27
|
+
#
|
28
|
+
# The YAML 1.0 specification outlines four stages of YAML loading and dumping.
|
29
|
+
# This library honors all four of those stages, although data is really only
|
30
|
+
# available to you in three stages.
|
31
|
+
#
|
32
|
+
# The four stages are: native, representation, serialization, and presentation.
|
33
|
+
#
|
34
|
+
# The native stage refers to data which has been loaded completely into Ruby's
|
35
|
+
# own types. (See +YAML::load+.)
|
36
|
+
#
|
37
|
+
# The representation stage means data which has been composed into
|
38
|
+
# +YAML::BaseNode+ objects. In this stage, the document is available as a
|
39
|
+
# tree of node objects. You can perform YPath queries and transformations
|
40
|
+
# at this level. (See +YAML::parse+.)
|
41
|
+
#
|
42
|
+
# The serialization stage happens inside the parser. The YAML parser used in
|
43
|
+
# Ruby is called Syck. Serialized nodes are available in the extension as
|
44
|
+
# SyckNode structs.
|
45
|
+
#
|
46
|
+
# The presentation stage is the YAML document itself. This is accessible
|
47
|
+
# to you as a string. (See +YAML::dump+.)
|
48
|
+
#
|
49
|
+
# For more information about the various information models, see Chapter
|
50
|
+
# 3 of the YAML 1.0 Specification (http://yaml.org/spec/#id2491269).
|
51
|
+
#
|
52
|
+
# The YAML module provides quick access to the most common loading (YAML::load)
|
53
|
+
# and dumping (YAML::dump) tasks. This module also provides an API for registering
|
54
|
+
# global types (YAML::add_domain_type).
|
55
|
+
#
|
56
|
+
# == Example
|
57
|
+
#
|
58
|
+
# A simple round-trip (load and dump) of an object.
|
59
|
+
#
|
60
|
+
# require "yaml"
|
61
|
+
#
|
62
|
+
# test_obj = ["dogs", "cats", "badgers"]
|
63
|
+
#
|
64
|
+
# yaml_obj = YAML::dump( test_obj )
|
65
|
+
# # -> ---
|
66
|
+
# - dogs
|
67
|
+
# - cats
|
68
|
+
# - badgers
|
69
|
+
# ruby_obj = YAML::load( yaml_obj )
|
70
|
+
# # => ["dogs", "cats", "badgers"]
|
71
|
+
# ruby_obj == test_obj
|
72
|
+
# # => true
|
73
|
+
#
|
74
|
+
# To register your custom types with the global resolver, use +add_domain_type+.
|
75
|
+
#
|
76
|
+
# YAML::add_domain_type( "your-site.com,2004", "widget" ) do |type, val|
|
77
|
+
# Widget.new( val )
|
78
|
+
# end
|
79
|
+
#
|
80
|
+
module Syck
|
81
|
+
|
82
|
+
DefaultResolver.use_types_at( @@tagged_classes )
|
83
|
+
|
84
|
+
# Returns a new default parser
|
85
|
+
def self.parser; Parser.new.set_resolver( self.resolver ); end
|
86
|
+
|
87
|
+
# Returns a new generic parser
|
88
|
+
def self.generic_parser
|
89
|
+
warn "#{caller[0]}: YAML.generic_parser is deprecated, switch to psych" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__))
|
90
|
+
Parser.new.set_resolver( GenericResolver )
|
91
|
+
end
|
92
|
+
|
93
|
+
# Returns the default resolver
|
94
|
+
def self.resolver
|
95
|
+
warn "#{caller[0]}: YAML.resolver is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__))
|
96
|
+
DefaultResolver
|
97
|
+
end
|
98
|
+
|
99
|
+
# Returns a new default emitter
|
100
|
+
def self.emitter
|
101
|
+
warn "#{caller[0]}: YAML.emitter is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__))
|
102
|
+
Emitter.new.set_resolver( self.resolver )
|
103
|
+
end
|
104
|
+
|
105
|
+
#
|
106
|
+
# Converts _obj_ to YAML and writes the YAML result to _io_.
|
107
|
+
#
|
108
|
+
# File.open( 'animals.yaml', 'w' ) do |out|
|
109
|
+
# YAML.dump( ['badger', 'elephant', 'tiger'], out )
|
110
|
+
# end
|
111
|
+
#
|
112
|
+
# If no _io_ is provided, a string containing the dumped YAML
|
113
|
+
# is returned.
|
114
|
+
#
|
115
|
+
# YAML.dump( :locked )
|
116
|
+
# #=> "--- :locked"
|
117
|
+
#
|
118
|
+
def self.dump( obj, io = nil )
|
119
|
+
obj.to_yaml( io || io2 = StringIO.new )
|
120
|
+
io || ( io2.rewind; io2.read )
|
121
|
+
end
|
122
|
+
|
123
|
+
#
|
124
|
+
# Load a document from the current _io_ stream.
|
125
|
+
#
|
126
|
+
# File.open( 'animals.yaml' ) { |yf| YAML::load( yf ) }
|
127
|
+
# #=> ['badger', 'elephant', 'tiger']
|
128
|
+
#
|
129
|
+
# Can also load from a string.
|
130
|
+
#
|
131
|
+
# YAML.load( "--- :locked" )
|
132
|
+
# #=> :locked
|
133
|
+
#
|
134
|
+
def self.load( io )
|
135
|
+
parser.load( io )
|
136
|
+
end
|
137
|
+
|
138
|
+
#
|
139
|
+
# Load a document from the file located at _filepath_.
|
140
|
+
#
|
141
|
+
# YAML.load_file( 'animals.yaml' )
|
142
|
+
# #=> ['badger', 'elephant', 'tiger']
|
143
|
+
#
|
144
|
+
def self.load_file( filepath )
|
145
|
+
File.open( filepath ) do |f|
|
146
|
+
load( f )
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
#
|
151
|
+
# Parse the first document from the current _io_ stream
|
152
|
+
#
|
153
|
+
# File.open( 'animals.yaml' ) { |yf| YAML::load( yf ) }
|
154
|
+
# #=> #<YAML::Syck::Node:0x82ccce0
|
155
|
+
# @kind=:seq,
|
156
|
+
# @value=
|
157
|
+
# [#<YAML::Syck::Node:0x82ccd94
|
158
|
+
# @kind=:scalar,
|
159
|
+
# @type_id="str",
|
160
|
+
# @value="badger">,
|
161
|
+
# #<YAML::Syck::Node:0x82ccd58
|
162
|
+
# @kind=:scalar,
|
163
|
+
# @type_id="str",
|
164
|
+
# @value="elephant">,
|
165
|
+
# #<YAML::Syck::Node:0x82ccd1c
|
166
|
+
# @kind=:scalar,
|
167
|
+
# @type_id="str",
|
168
|
+
# @value="tiger">]>
|
169
|
+
#
|
170
|
+
# Can also load from a string.
|
171
|
+
#
|
172
|
+
# YAML.parse( "--- :locked" )
|
173
|
+
# #=> #<YAML::Syck::Node:0x82edddc
|
174
|
+
# @type_id="tag:ruby.yaml.org,2002:sym",
|
175
|
+
# @value=":locked", @kind=:scalar>
|
176
|
+
#
|
177
|
+
def self.parse( io )
|
178
|
+
generic_parser.load( io )
|
179
|
+
end
|
180
|
+
|
181
|
+
#
|
182
|
+
# Parse a document from the file located at _filepath_.
|
183
|
+
#
|
184
|
+
# YAML.parse_file( 'animals.yaml' )
|
185
|
+
# #=> #<YAML::Syck::Node:0x82ccce0
|
186
|
+
# @kind=:seq,
|
187
|
+
# @value=
|
188
|
+
# [#<YAML::Syck::Node:0x82ccd94
|
189
|
+
# @kind=:scalar,
|
190
|
+
# @type_id="str",
|
191
|
+
# @value="badger">,
|
192
|
+
# #<YAML::Syck::Node:0x82ccd58
|
193
|
+
# @kind=:scalar,
|
194
|
+
# @type_id="str",
|
195
|
+
# @value="elephant">,
|
196
|
+
# #<YAML::Syck::Node:0x82ccd1c
|
197
|
+
# @kind=:scalar,
|
198
|
+
# @type_id="str",
|
199
|
+
# @value="tiger">]>
|
200
|
+
#
|
201
|
+
def self.parse_file( filepath )
|
202
|
+
File.open( filepath ) do |f|
|
203
|
+
parse( f )
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
#
|
208
|
+
# Calls _block_ with each consecutive document in the YAML
|
209
|
+
# stream contained in _io_.
|
210
|
+
#
|
211
|
+
# File.open( 'many-docs.yaml' ) do |yf|
|
212
|
+
# YAML.each_document( yf ) do |ydoc|
|
213
|
+
# ## ydoc contains the single object
|
214
|
+
# ## from the YAML document
|
215
|
+
# end
|
216
|
+
# end
|
217
|
+
#
|
218
|
+
def self.each_document( io, &block )
|
219
|
+
warn "#{caller[0]}: YAML.each_document is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__))
|
220
|
+
parser.load_documents( io, &block )
|
221
|
+
end
|
222
|
+
|
223
|
+
#
|
224
|
+
# Calls _block_ with each consecutive document in the YAML
|
225
|
+
# stream contained in _io_.
|
226
|
+
#
|
227
|
+
# File.open( 'many-docs.yaml' ) do |yf|
|
228
|
+
# YAML.load_documents( yf ) do |ydoc|
|
229
|
+
# ## ydoc contains the single object
|
230
|
+
# ## from the YAML document
|
231
|
+
# end
|
232
|
+
# end
|
233
|
+
#
|
234
|
+
def self.load_documents( io, &doc_proc )
|
235
|
+
parser.load_documents( io, &doc_proc )
|
236
|
+
end
|
237
|
+
|
238
|
+
#
|
239
|
+
# Calls _block_ with a tree of +YAML::BaseNodes+, one tree for
|
240
|
+
# each consecutive document in the YAML stream contained in _io_.
|
241
|
+
#
|
242
|
+
# File.open( 'many-docs.yaml' ) do |yf|
|
243
|
+
# YAML.each_node( yf ) do |ydoc|
|
244
|
+
# ## ydoc contains a tree of nodes
|
245
|
+
# ## from the YAML document
|
246
|
+
# end
|
247
|
+
# end
|
248
|
+
#
|
249
|
+
def self.each_node( io, &doc_proc )
|
250
|
+
warn "#{caller[0]}: YAML.each_node is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__))
|
251
|
+
generic_parser.load_documents( io, &doc_proc )
|
252
|
+
end
|
253
|
+
|
254
|
+
#
|
255
|
+
# Calls _block_ with a tree of +YAML::BaseNodes+, one tree for
|
256
|
+
# each consecutive document in the YAML stream contained in _io_.
|
257
|
+
#
|
258
|
+
# File.open( 'many-docs.yaml' ) do |yf|
|
259
|
+
# YAML.parse_documents( yf ) do |ydoc|
|
260
|
+
# ## ydoc contains a tree of nodes
|
261
|
+
# ## from the YAML document
|
262
|
+
# end
|
263
|
+
# end
|
264
|
+
#
|
265
|
+
def self.parse_documents( io, &doc_proc )
|
266
|
+
warn "#{caller[0]}: YAML.parse_documents is deprecated, use load_stream" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__))
|
267
|
+
self.each_node( io, &doc_proc )
|
268
|
+
end
|
269
|
+
|
270
|
+
#
|
271
|
+
# Loads all documents from the current _io_ stream,
|
272
|
+
# returning a +YAML::Stream+ object containing all
|
273
|
+
# loaded documents.
|
274
|
+
#
|
275
|
+
def self.load_stream( io )
|
276
|
+
d = nil
|
277
|
+
parser.load_documents( io ) do |doc|
|
278
|
+
d = Stream.new if not d
|
279
|
+
d.add( doc )
|
280
|
+
end
|
281
|
+
return d
|
282
|
+
end
|
283
|
+
|
284
|
+
#
|
285
|
+
# Returns a YAML stream containing each of the items in +objs+,
|
286
|
+
# each having their own document.
|
287
|
+
#
|
288
|
+
# YAML.dump_stream( 0, [], {} )
|
289
|
+
# #=> --- 0
|
290
|
+
# --- []
|
291
|
+
# --- {}
|
292
|
+
#
|
293
|
+
def self.dump_stream( *objs )
|
294
|
+
d = Stream.new
|
295
|
+
objs.each do |doc|
|
296
|
+
d.add( doc )
|
297
|
+
end
|
298
|
+
d.emit
|
299
|
+
end
|
300
|
+
|
301
|
+
#
|
302
|
+
# Add a global handler for a YAML domain type.
|
303
|
+
#
|
304
|
+
def self.add_domain_type( domain, type_tag, &transfer_proc )
|
305
|
+
resolver.add_type( "tag:#{ domain }:#{ type_tag }", transfer_proc )
|
306
|
+
end
|
307
|
+
|
308
|
+
#
|
309
|
+
# Add a transfer method for a builtin type
|
310
|
+
#
|
311
|
+
def self.add_builtin_type( type_tag, &transfer_proc )
|
312
|
+
resolver.add_type( "tag:yaml.org,2002:#{ type_tag }", transfer_proc )
|
313
|
+
end
|
314
|
+
|
315
|
+
#
|
316
|
+
# Add a transfer method for a builtin type
|
317
|
+
#
|
318
|
+
def self.add_ruby_type( type_tag, &transfer_proc )
|
319
|
+
warn "#{caller[0]}: YAML.add_ruby_type is deprecated, use add_domain_type" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__))
|
320
|
+
resolver.add_type( "tag:ruby.yaml.org,2002:#{ type_tag }", transfer_proc )
|
321
|
+
end
|
322
|
+
|
323
|
+
#
|
324
|
+
# Add a private document type
|
325
|
+
#
|
326
|
+
def self.add_private_type( type_re, &transfer_proc )
|
327
|
+
warn "#{caller[0]}: YAML.add_private_type is deprecated, use add_domain_type" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__))
|
328
|
+
resolver.add_type( "x-private:" + type_re, transfer_proc )
|
329
|
+
end
|
330
|
+
|
331
|
+
#
|
332
|
+
# Detect typing of a string
|
333
|
+
#
|
334
|
+
def self.detect_implicit( val )
|
335
|
+
warn "#{caller[0]}: YAML.detect_implicit is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__))
|
336
|
+
resolver.detect_implicit( val )
|
337
|
+
end
|
338
|
+
|
339
|
+
#
|
340
|
+
# Convert a type_id to a taguri
|
341
|
+
#
|
342
|
+
def self.tagurize( val )
|
343
|
+
warn "#{caller[0]}: YAML.tagurize is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__))
|
344
|
+
resolver.tagurize( val )
|
345
|
+
end
|
346
|
+
|
347
|
+
#
|
348
|
+
# Apply a transfer method to a Ruby object
|
349
|
+
#
|
350
|
+
def self.transfer( type_id, obj )
|
351
|
+
warn "#{caller[0]}: YAML.transfer is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__))
|
352
|
+
resolver.transfer( tagurize( type_id ), obj )
|
353
|
+
end
|
354
|
+
|
355
|
+
#
|
356
|
+
# Apply any implicit a node may qualify for
|
357
|
+
#
|
358
|
+
def self.try_implicit( obj )
|
359
|
+
warn "#{caller[0]}: YAML.try_implicit is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__))
|
360
|
+
transfer( detect_implicit( obj ), obj )
|
361
|
+
end
|
362
|
+
|
363
|
+
#
|
364
|
+
# Method to extract colon-seperated type and class, returning
|
365
|
+
# the type and the constant of the class
|
366
|
+
#
|
367
|
+
def self.read_type_class( type, obj_class )
|
368
|
+
warn "#{caller[0]}: YAML.read_type_class is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__))
|
369
|
+
type, tclass = type.split( ':', 4 ).last(2)
|
370
|
+
tclass.split( "::" ).each { |c| obj_class = obj_class.const_get( c ) } if tclass
|
371
|
+
return [ type, obj_class ]
|
372
|
+
end
|
373
|
+
|
374
|
+
#
|
375
|
+
# Allocate blank object
|
376
|
+
#
|
377
|
+
def self.object_maker( obj_class, val )
|
378
|
+
warn "#{caller[0]}: YAML.object_maker is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__))
|
379
|
+
if Hash === val
|
380
|
+
o = obj_class.allocate
|
381
|
+
val.each_pair { |k,v|
|
382
|
+
o.instance_variable_set("@#{k}", v)
|
383
|
+
}
|
384
|
+
o
|
385
|
+
else
|
386
|
+
raise Error, "Invalid object explicitly tagged !ruby/Object: " + val.inspect
|
387
|
+
end
|
388
|
+
end
|
389
|
+
|
390
|
+
#
|
391
|
+
# Allocate an Emitter if needed
|
392
|
+
#
|
393
|
+
def self.quick_emit( oid, opts = {}, &e )
|
394
|
+
warn "#{caller[0]}: YAML.quick_emit is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__))
|
395
|
+
out =
|
396
|
+
if opts.is_a? Emitter
|
397
|
+
opts
|
398
|
+
else
|
399
|
+
emitter.reset( opts )
|
400
|
+
end
|
401
|
+
out.emit( oid, &e )
|
402
|
+
end
|
403
|
+
|
404
|
+
end
|
405
|
+
|
406
|
+
module Kernel
|
407
|
+
#
|
408
|
+
# ryan:: You know how Kernel.p is a really convenient way to dump ruby
|
409
|
+
# structures? The only downside is that it's not as legible as
|
410
|
+
# YAML.
|
411
|
+
#
|
412
|
+
# _why:: (listening)
|
413
|
+
#
|
414
|
+
# ryan:: I know you don't want to urinate all over your users' namespaces.
|
415
|
+
# But, on the other hand, convenience of dumping for debugging is,
|
416
|
+
# IMO, a big YAML use case.
|
417
|
+
#
|
418
|
+
# _why:: Go nuts! Have a pony parade!
|
419
|
+
#
|
420
|
+
# ryan:: Either way, I certainly will have a pony parade.
|
421
|
+
#
|
422
|
+
|
423
|
+
# Prints any supplied _objects_ out in YAML. Intended as
|
424
|
+
# a variation on +Kernel::p+.
|
425
|
+
#
|
426
|
+
# S = Struct.new(:name, :state)
|
427
|
+
# s = S['dave', 'TX']
|
428
|
+
# y s
|
429
|
+
#
|
430
|
+
# _produces:_
|
431
|
+
#
|
432
|
+
# --- !ruby/struct:S
|
433
|
+
# name: dave
|
434
|
+
# state: TX
|
435
|
+
#
|
436
|
+
def y( object, *objects )
|
437
|
+
objects.unshift object
|
438
|
+
puts( if objects.length == 1
|
439
|
+
Syck.dump( *objects )
|
440
|
+
else
|
441
|
+
Syck.dump_stream( *objects )
|
442
|
+
end )
|
443
|
+
end
|
444
|
+
private :y
|
445
|
+
end
|
446
|
+
|
447
|
+
|