syck 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
+