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.
Files changed (54) hide show
  1. data/.autotest.erb +8 -0
  2. data/.gemtest +0 -0
  3. data/CHANGELOG.rdoc +6 -0
  4. data/Manifest.txt +52 -0
  5. data/README.rdoc +51 -0
  6. data/Rakefile +32 -0
  7. data/ext/syck/bytecode.c +1165 -0
  8. data/ext/syck/emitter.c +1247 -0
  9. data/ext/syck/extconf.h +3 -0
  10. data/ext/syck/extconf.rb +5 -0
  11. data/ext/syck/gram.c +1894 -0
  12. data/ext/syck/gram.h +79 -0
  13. data/ext/syck/handler.c +173 -0
  14. data/ext/syck/implicit.c +2990 -0
  15. data/ext/syck/node.c +407 -0
  16. data/ext/syck/rubyext.c +2328 -0
  17. data/ext/syck/syck.c +524 -0
  18. data/ext/syck/syck.h +453 -0
  19. data/ext/syck/token.c +2724 -0
  20. data/ext/syck/yaml2byte.c +259 -0
  21. data/ext/syck/yamlbyte.h +171 -0
  22. data/lib/syck.bundle +0 -0
  23. data/lib/syck.rb +447 -0
  24. data/lib/syck/baseemitter.rb +242 -0
  25. data/lib/syck/basenode.rb +222 -0
  26. data/lib/syck/constants.rb +45 -0
  27. data/lib/syck/encoding.rb +35 -0
  28. data/lib/syck/error.rb +34 -0
  29. data/lib/syck/loader.rb +14 -0
  30. data/lib/syck/rubytypes.rb +450 -0
  31. data/lib/syck/stream.rb +41 -0
  32. data/lib/syck/stringio.rb +85 -0
  33. data/lib/syck/syck.rb +16 -0
  34. data/lib/syck/tag.rb +95 -0
  35. data/lib/syck/types.rb +192 -0
  36. data/lib/syck/yamlnode.rb +54 -0
  37. data/lib/syck/ypath.rb +54 -0
  38. data/lib/yaml/syck.rb +14 -0
  39. data/test/helper.rb +2 -0
  40. data/test/test_array.rb +13 -0
  41. data/test/test_boolean.rb +36 -0
  42. data/test/test_class.rb +11 -0
  43. data/test/test_exception.rb +45 -0
  44. data/test/test_hash.rb +24 -0
  45. data/test/test_null.rb +19 -0
  46. data/test/test_omap.rb +55 -0
  47. data/test/test_set.rb +30 -0
  48. data/test/test_string.rb +44 -0
  49. data/test/test_struct.rb +32 -0
  50. data/test/test_symbol.rb +21 -0
  51. data/test/test_time.rb +23 -0
  52. data/test/test_yaml.rb +1403 -0
  53. data/test/test_yaml_properties.rb +63 -0
  54. 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
+
@@ -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
Binary file
@@ -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
+