mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	* ext/psych/*: importing Psych to trunk
* test/psych/*: ditto * lib/psych/*: ditto git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27079 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
		
							parent
							
								
									a8a99a7379
								
							
						
					
					
						commit
						b9b923ca94
					
				
					 66 changed files with 6056 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -1,3 +1,9 @@
 | 
			
		|||
Mon Mar 29 06:47:25 2010  Aaron Patterson <aaron@tenderlovemaking.com>
 | 
			
		||||
 | 
			
		||||
	* ext/psych/*: importing Psych to trunk
 | 
			
		||||
	* test/psych/*: ditto
 | 
			
		||||
	* lib/psych/*: ditto
 | 
			
		||||
 | 
			
		||||
Sun Mar 28 21:04:21 2010  NARUSE, Yui  <naruse@ruby-lang.org>
 | 
			
		||||
 | 
			
		||||
	* configure.in (ac_cv_func_snprintf, ac_cv_func_vsnprintf):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										413
									
								
								ext/psych/emitter.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										413
									
								
								ext/psych/emitter.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,413 @@
 | 
			
		|||
#include <psych.h>
 | 
			
		||||
 | 
			
		||||
VALUE cPsychEmitter;
 | 
			
		||||
static ID id_write;
 | 
			
		||||
 | 
			
		||||
static void emit(yaml_emitter_t * emitter, yaml_event_t * event)
 | 
			
		||||
{
 | 
			
		||||
    if(!yaml_emitter_emit(emitter, event))
 | 
			
		||||
	rb_raise(rb_eRuntimeError, "%s", emitter->problem);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int writer(void *ctx, unsigned char *buffer, size_t size)
 | 
			
		||||
{
 | 
			
		||||
    VALUE io = (VALUE)ctx;
 | 
			
		||||
    VALUE str = rb_str_new((const char *)buffer, (long)size);
 | 
			
		||||
    VALUE wrote = rb_funcall(io, id_write, 1, str);
 | 
			
		||||
    return (int)NUM2INT(wrote);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void dealloc(yaml_emitter_t * emitter)
 | 
			
		||||
{
 | 
			
		||||
    yaml_emitter_delete(emitter);
 | 
			
		||||
    free(emitter);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static VALUE allocate(VALUE klass)
 | 
			
		||||
{
 | 
			
		||||
    yaml_emitter_t * emitter = malloc(sizeof(yaml_emitter_t));
 | 
			
		||||
    yaml_emitter_initialize(emitter);
 | 
			
		||||
    yaml_emitter_set_unicode(emitter, 1);
 | 
			
		||||
    yaml_emitter_set_indent(emitter, 2);
 | 
			
		||||
 | 
			
		||||
    return Data_Wrap_Struct(klass, 0, dealloc, emitter);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* call-seq: Psych::Emitter.new(io)
 | 
			
		||||
 *
 | 
			
		||||
 * Create a new Psych::Emitter that writes to +io+.
 | 
			
		||||
 */
 | 
			
		||||
static VALUE initialize(VALUE self, VALUE io)
 | 
			
		||||
{
 | 
			
		||||
    yaml_emitter_t * emitter;
 | 
			
		||||
    Data_Get_Struct(self, yaml_emitter_t, emitter);
 | 
			
		||||
 | 
			
		||||
    yaml_emitter_set_output(emitter, writer, (void *)io);
 | 
			
		||||
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* call-seq: emitter.start_stream(encoding)
 | 
			
		||||
 *
 | 
			
		||||
 * Start a stream emission with +encoding+
 | 
			
		||||
 *
 | 
			
		||||
 * See Psych::Handler#start_stream
 | 
			
		||||
 */
 | 
			
		||||
static VALUE start_stream(VALUE self, VALUE encoding)
 | 
			
		||||
{
 | 
			
		||||
    yaml_emitter_t * emitter;
 | 
			
		||||
    Data_Get_Struct(self, yaml_emitter_t, emitter);
 | 
			
		||||
    Check_Type(encoding, T_FIXNUM);
 | 
			
		||||
 | 
			
		||||
    yaml_event_t event;
 | 
			
		||||
    yaml_stream_start_event_initialize(&event, (yaml_encoding_t)NUM2INT(encoding));
 | 
			
		||||
 | 
			
		||||
    emit(emitter, &event);
 | 
			
		||||
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* call-seq: emitter.end_stream
 | 
			
		||||
 *
 | 
			
		||||
 * End a stream emission
 | 
			
		||||
 *
 | 
			
		||||
 * See Psych::Handler#end_stream
 | 
			
		||||
 */
 | 
			
		||||
static VALUE end_stream(VALUE self)
 | 
			
		||||
{
 | 
			
		||||
    yaml_emitter_t * emitter;
 | 
			
		||||
    Data_Get_Struct(self, yaml_emitter_t, emitter);
 | 
			
		||||
 | 
			
		||||
    yaml_event_t event;
 | 
			
		||||
    yaml_stream_end_event_initialize(&event);
 | 
			
		||||
 | 
			
		||||
    emit(emitter, &event);
 | 
			
		||||
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* call-seq: emitter.start_document(version, tags, implicit)
 | 
			
		||||
 *
 | 
			
		||||
 * Start a document emission with YAML +version+, +tags+, and an +implicit+
 | 
			
		||||
 * start.
 | 
			
		||||
 *
 | 
			
		||||
 * See Psych::Handler#start_document
 | 
			
		||||
 */
 | 
			
		||||
static VALUE start_document(VALUE self, VALUE version, VALUE tags, VALUE imp)
 | 
			
		||||
{
 | 
			
		||||
    yaml_emitter_t * emitter;
 | 
			
		||||
    Data_Get_Struct(self, yaml_emitter_t, emitter);
 | 
			
		||||
 | 
			
		||||
    yaml_version_directive_t version_directive;
 | 
			
		||||
 | 
			
		||||
    Check_Type(version, T_ARRAY);
 | 
			
		||||
 | 
			
		||||
    if(RARRAY_LEN(version) > 0) {
 | 
			
		||||
	VALUE major = rb_ary_entry(version, (long)0);
 | 
			
		||||
	VALUE minor = rb_ary_entry(version, (long)1);
 | 
			
		||||
 | 
			
		||||
	version_directive.major = NUM2INT(major);
 | 
			
		||||
	version_directive.minor = NUM2INT(minor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    yaml_tag_directive_t * head = NULL;
 | 
			
		||||
    yaml_tag_directive_t * tail = NULL;
 | 
			
		||||
 | 
			
		||||
    if(RTEST(tags)) {
 | 
			
		||||
	int i = 0;
 | 
			
		||||
 | 
			
		||||
	Check_Type(tags, T_ARRAY);
 | 
			
		||||
 | 
			
		||||
	head  = xcalloc((size_t)RARRAY_LEN(tags), sizeof(yaml_tag_directive_t));
 | 
			
		||||
	tail  = head;
 | 
			
		||||
 | 
			
		||||
	for(i = 0; i < RARRAY_LEN(tags); i++) {
 | 
			
		||||
	    VALUE tuple = RARRAY_PTR(tags)[i];
 | 
			
		||||
	    Check_Type(tuple, T_ARRAY);
 | 
			
		||||
 | 
			
		||||
	    if(RARRAY_LEN(tuple) < 2) {
 | 
			
		||||
		xfree(head);
 | 
			
		||||
		rb_raise(rb_eRuntimeError, "tag tuple must be of length 2");
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
	    tail->handle = (yaml_char_t *)StringValuePtr(RARRAY_PTR(tuple)[0]);
 | 
			
		||||
	    tail->prefix = (yaml_char_t *)StringValuePtr(RARRAY_PTR(tuple)[1]);
 | 
			
		||||
 | 
			
		||||
	    tail++;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    yaml_event_t event;
 | 
			
		||||
    yaml_document_start_event_initialize(
 | 
			
		||||
	    &event,
 | 
			
		||||
	    (RARRAY_LEN(version) > 0) ? &version_directive : NULL,
 | 
			
		||||
	    head,
 | 
			
		||||
	    tail,
 | 
			
		||||
	    imp ? 1 : 0
 | 
			
		||||
	    );
 | 
			
		||||
 | 
			
		||||
    emit(emitter, &event);
 | 
			
		||||
 | 
			
		||||
    if(head) xfree(head);
 | 
			
		||||
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* call-seq: emitter.end_document(implicit)
 | 
			
		||||
 *
 | 
			
		||||
 * End a document emission with an +implicit+ ending.
 | 
			
		||||
 *
 | 
			
		||||
 * See Psych::Handler#end_document
 | 
			
		||||
 */
 | 
			
		||||
static VALUE end_document(VALUE self, VALUE imp)
 | 
			
		||||
{
 | 
			
		||||
    yaml_emitter_t * emitter;
 | 
			
		||||
    Data_Get_Struct(self, yaml_emitter_t, emitter);
 | 
			
		||||
 | 
			
		||||
    yaml_event_t event;
 | 
			
		||||
    yaml_document_end_event_initialize(&event, imp ? 1 : 0);
 | 
			
		||||
 | 
			
		||||
    emit(emitter, &event);
 | 
			
		||||
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* call-seq: emitter.scalar(value, anchor, tag, plain, quoted, style)
 | 
			
		||||
 *
 | 
			
		||||
 * Emit a scalar with +value+, +anchor+, +tag+, and a +plain+ or +quoted+
 | 
			
		||||
 * string type with +style+.
 | 
			
		||||
 *
 | 
			
		||||
 * See Psych::Handler#scalar
 | 
			
		||||
 */
 | 
			
		||||
static VALUE scalar(
 | 
			
		||||
	VALUE self,
 | 
			
		||||
	VALUE value,
 | 
			
		||||
	VALUE anchor,
 | 
			
		||||
	VALUE tag,
 | 
			
		||||
	VALUE plain,
 | 
			
		||||
	VALUE quoted,
 | 
			
		||||
	VALUE style
 | 
			
		||||
	) {
 | 
			
		||||
    yaml_emitter_t * emitter;
 | 
			
		||||
    Data_Get_Struct(self, yaml_emitter_t, emitter);
 | 
			
		||||
 | 
			
		||||
    Check_Type(value, T_STRING);
 | 
			
		||||
 | 
			
		||||
    yaml_event_t event;
 | 
			
		||||
    yaml_scalar_event_initialize(
 | 
			
		||||
	    &event,
 | 
			
		||||
	    (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValuePtr(anchor)),
 | 
			
		||||
	    (yaml_char_t *)(NIL_P(tag) ? NULL : StringValuePtr(tag)),
 | 
			
		||||
	    (yaml_char_t*)StringValuePtr(value),
 | 
			
		||||
	    (int)RSTRING_LEN(value),
 | 
			
		||||
	    plain ? 1 : 0,
 | 
			
		||||
	    quoted ? 1 : 0,
 | 
			
		||||
	    (yaml_scalar_style_t)NUM2INT(style)
 | 
			
		||||
	    );
 | 
			
		||||
 | 
			
		||||
    emit(emitter, &event);
 | 
			
		||||
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* call-seq: emitter.start_sequence(anchor, tag, implicit, style)
 | 
			
		||||
 *
 | 
			
		||||
 * Start emitting a sequence with +anchor+, a +tag+, +implicit+ sequence
 | 
			
		||||
 * start and end, along with +style+.
 | 
			
		||||
 *
 | 
			
		||||
 * See Psych::Handler#start_sequence
 | 
			
		||||
 */
 | 
			
		||||
static VALUE start_sequence(
 | 
			
		||||
	VALUE self,
 | 
			
		||||
	VALUE anchor,
 | 
			
		||||
	VALUE tag,
 | 
			
		||||
	VALUE implicit,
 | 
			
		||||
	VALUE style
 | 
			
		||||
	) {
 | 
			
		||||
    yaml_emitter_t * emitter;
 | 
			
		||||
    Data_Get_Struct(self, yaml_emitter_t, emitter);
 | 
			
		||||
 | 
			
		||||
    yaml_event_t event;
 | 
			
		||||
    yaml_sequence_start_event_initialize(
 | 
			
		||||
	    &event,
 | 
			
		||||
	    (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValuePtr(anchor)),
 | 
			
		||||
	    (yaml_char_t *)(NIL_P(tag) ? NULL : StringValuePtr(tag)),
 | 
			
		||||
	    implicit ? 1 : 0,
 | 
			
		||||
	    (yaml_sequence_style_t)NUM2INT(style)
 | 
			
		||||
	    );
 | 
			
		||||
 | 
			
		||||
    emit(emitter, &event);
 | 
			
		||||
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* call-seq: emitter.end_sequence
 | 
			
		||||
 *
 | 
			
		||||
 * End sequence emission.
 | 
			
		||||
 *
 | 
			
		||||
 * See Psych::Handler#end_sequence
 | 
			
		||||
 */
 | 
			
		||||
static VALUE end_sequence(VALUE self)
 | 
			
		||||
{
 | 
			
		||||
    yaml_emitter_t * emitter;
 | 
			
		||||
    Data_Get_Struct(self, yaml_emitter_t, emitter);
 | 
			
		||||
 | 
			
		||||
    yaml_event_t event;
 | 
			
		||||
    yaml_sequence_end_event_initialize(&event);
 | 
			
		||||
 | 
			
		||||
    emit(emitter, &event);
 | 
			
		||||
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* call-seq: emitter.start_mapping(anchor, tag, implicit, style)
 | 
			
		||||
 *
 | 
			
		||||
 * Start emitting a YAML map with +anchor+, +tag+, an +implicit+ start
 | 
			
		||||
 * and end, and +style+.
 | 
			
		||||
 *
 | 
			
		||||
 * See Psych::Handler#start_mapping
 | 
			
		||||
 */
 | 
			
		||||
static VALUE start_mapping(
 | 
			
		||||
	VALUE self,
 | 
			
		||||
	VALUE anchor,
 | 
			
		||||
	VALUE tag,
 | 
			
		||||
	VALUE implicit,
 | 
			
		||||
	VALUE style
 | 
			
		||||
	) {
 | 
			
		||||
    yaml_emitter_t * emitter;
 | 
			
		||||
    Data_Get_Struct(self, yaml_emitter_t, emitter);
 | 
			
		||||
 | 
			
		||||
    yaml_event_t event;
 | 
			
		||||
    yaml_mapping_start_event_initialize(
 | 
			
		||||
	    &event,
 | 
			
		||||
	    (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValuePtr(anchor)),
 | 
			
		||||
	    (yaml_char_t *)(NIL_P(tag) ? NULL : StringValuePtr(tag)),
 | 
			
		||||
	    implicit ? 1 : 0,
 | 
			
		||||
	    (yaml_sequence_style_t)NUM2INT(style)
 | 
			
		||||
	    );
 | 
			
		||||
 | 
			
		||||
    emit(emitter, &event);
 | 
			
		||||
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* call-seq: emitter.end_mapping
 | 
			
		||||
 *
 | 
			
		||||
 * Emit the end of a mapping.
 | 
			
		||||
 *
 | 
			
		||||
 * See Psych::Handler#end_mapping
 | 
			
		||||
 */
 | 
			
		||||
static VALUE end_mapping(VALUE self)
 | 
			
		||||
{
 | 
			
		||||
    yaml_emitter_t * emitter;
 | 
			
		||||
    Data_Get_Struct(self, yaml_emitter_t, emitter);
 | 
			
		||||
 | 
			
		||||
    yaml_event_t event;
 | 
			
		||||
    yaml_mapping_end_event_initialize(&event);
 | 
			
		||||
 | 
			
		||||
    emit(emitter, &event);
 | 
			
		||||
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* call-seq: emitter.alias(anchor)
 | 
			
		||||
 *
 | 
			
		||||
 * Emit an alias with +anchor+.
 | 
			
		||||
 *
 | 
			
		||||
 * See Psych::Handler#alias
 | 
			
		||||
 */
 | 
			
		||||
static VALUE alias(VALUE self, VALUE anchor)
 | 
			
		||||
{
 | 
			
		||||
    yaml_emitter_t * emitter;
 | 
			
		||||
    Data_Get_Struct(self, yaml_emitter_t, emitter);
 | 
			
		||||
 | 
			
		||||
    yaml_event_t event;
 | 
			
		||||
    yaml_alias_event_initialize(
 | 
			
		||||
	    &event,
 | 
			
		||||
	    (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValuePtr(anchor))
 | 
			
		||||
	    );
 | 
			
		||||
 | 
			
		||||
    emit(emitter, &event);
 | 
			
		||||
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* call-seq: emitter.canonical = true
 | 
			
		||||
 *
 | 
			
		||||
 * Set the output style to canonical, or not.
 | 
			
		||||
 */
 | 
			
		||||
static VALUE set_canonical(VALUE self, VALUE style)
 | 
			
		||||
{
 | 
			
		||||
    yaml_emitter_t * emitter;
 | 
			
		||||
    Data_Get_Struct(self, yaml_emitter_t, emitter);
 | 
			
		||||
 | 
			
		||||
    yaml_emitter_set_canonical(emitter, Qtrue == style ? 1 : 0);
 | 
			
		||||
 | 
			
		||||
    return style;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* call-seq: emitter.canonical
 | 
			
		||||
 *
 | 
			
		||||
 * Get the output style, canonical or not.
 | 
			
		||||
 */
 | 
			
		||||
static VALUE canonical(VALUE self)
 | 
			
		||||
{
 | 
			
		||||
    yaml_emitter_t * emitter;
 | 
			
		||||
    Data_Get_Struct(self, yaml_emitter_t, emitter);
 | 
			
		||||
 | 
			
		||||
    return (emitter->canonical == 0) ? Qfalse : Qtrue;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* call-seq: emitter.indentation = level
 | 
			
		||||
 *
 | 
			
		||||
 * Set the indentation level to +level+.
 | 
			
		||||
 */
 | 
			
		||||
static VALUE set_indentation(VALUE self, VALUE level)
 | 
			
		||||
{
 | 
			
		||||
    yaml_emitter_t * emitter;
 | 
			
		||||
    Data_Get_Struct(self, yaml_emitter_t, emitter);
 | 
			
		||||
 | 
			
		||||
    yaml_emitter_set_indent(emitter, NUM2INT(level));
 | 
			
		||||
 | 
			
		||||
    return level;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* call-seq: emitter.indentation
 | 
			
		||||
 *
 | 
			
		||||
 * Get the indentation level.
 | 
			
		||||
 */
 | 
			
		||||
static VALUE indentation(VALUE self)
 | 
			
		||||
{
 | 
			
		||||
    yaml_emitter_t * emitter;
 | 
			
		||||
    Data_Get_Struct(self, yaml_emitter_t, emitter);
 | 
			
		||||
 | 
			
		||||
    return INT2NUM(emitter->best_indent);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Init_psych_emitter()
 | 
			
		||||
{
 | 
			
		||||
    VALUE psych     = rb_define_module("Psych");
 | 
			
		||||
    VALUE handler   = rb_define_class_under(psych, "Handler", rb_cObject);
 | 
			
		||||
    cPsychEmitter   = rb_define_class_under(psych, "Emitter", handler);
 | 
			
		||||
 | 
			
		||||
    rb_define_alloc_func(cPsychEmitter, allocate);
 | 
			
		||||
 | 
			
		||||
    rb_define_method(cPsychEmitter, "initialize", initialize, 1);
 | 
			
		||||
    rb_define_method(cPsychEmitter, "start_stream", start_stream, 1);
 | 
			
		||||
    rb_define_method(cPsychEmitter, "end_stream", end_stream, 0);
 | 
			
		||||
    rb_define_method(cPsychEmitter, "start_document", start_document, 3);
 | 
			
		||||
    rb_define_method(cPsychEmitter, "end_document", end_document, 1);
 | 
			
		||||
    rb_define_method(cPsychEmitter, "scalar", scalar, 6);
 | 
			
		||||
    rb_define_method(cPsychEmitter, "start_sequence", start_sequence, 4);
 | 
			
		||||
    rb_define_method(cPsychEmitter, "end_sequence", end_sequence, 0);
 | 
			
		||||
    rb_define_method(cPsychEmitter, "start_mapping", start_mapping, 4);
 | 
			
		||||
    rb_define_method(cPsychEmitter, "end_mapping", end_mapping, 0);
 | 
			
		||||
    rb_define_method(cPsychEmitter, "alias", alias, 1);
 | 
			
		||||
    rb_define_method(cPsychEmitter, "canonical", canonical, 0);
 | 
			
		||||
    rb_define_method(cPsychEmitter, "canonical=", set_canonical, 1);
 | 
			
		||||
    rb_define_method(cPsychEmitter, "indentation", indentation, 0);
 | 
			
		||||
    rb_define_method(cPsychEmitter, "indentation=", set_indentation, 1);
 | 
			
		||||
 | 
			
		||||
    id_write = rb_intern("write");
 | 
			
		||||
}
 | 
			
		||||
/* vim: set noet sws=4 sw=4: */
 | 
			
		||||
							
								
								
									
										8
									
								
								ext/psych/emitter.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								ext/psych/emitter.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,8 @@
 | 
			
		|||
#ifndef PSYCH_EMITTER_H
 | 
			
		||||
#define PSYCH_EMITTER_H
 | 
			
		||||
 | 
			
		||||
#include <psych.h>
 | 
			
		||||
 | 
			
		||||
void Init_psych_emitter();
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										22
									
								
								ext/psych/extconf.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								ext/psych/extconf.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,22 @@
 | 
			
		|||
require 'mkmf'
 | 
			
		||||
 | 
			
		||||
# :stopdoc:
 | 
			
		||||
 | 
			
		||||
RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
 | 
			
		||||
 | 
			
		||||
INCLUDEDIR = Config::CONFIG['includedir']
 | 
			
		||||
LIBDIR     = Config::CONFIG['libdir']
 | 
			
		||||
LIB_DIRS   = ['/opt/local/lib', '/usr/local/lib', LIBDIR, '/usr/lib']
 | 
			
		||||
libyaml    = dir_config 'libyaml', '/opt/local/include', '/opt/local/lib'
 | 
			
		||||
 | 
			
		||||
def asplode missing
 | 
			
		||||
  abort "#{missing} is missing. Try 'port install libyaml +universal' " +
 | 
			
		||||
        "or 'yum install libyaml-devel'"
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
asplode('yaml.h')  unless find_header  'yaml.h'
 | 
			
		||||
asplode('libyaml') unless find_library 'yaml', 'yaml_get_version'
 | 
			
		||||
 | 
			
		||||
create_makefile 'psych/psych'
 | 
			
		||||
 | 
			
		||||
# :startdoc:
 | 
			
		||||
							
								
								
									
										314
									
								
								ext/psych/parser.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										314
									
								
								ext/psych/parser.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,314 @@
 | 
			
		|||
#include <psych.h>
 | 
			
		||||
 | 
			
		||||
VALUE cPsychParser;
 | 
			
		||||
VALUE ePsychSyntaxError;
 | 
			
		||||
 | 
			
		||||
static ID id_read;
 | 
			
		||||
static ID id_empty;
 | 
			
		||||
static ID id_start_stream;
 | 
			
		||||
static ID id_end_stream;
 | 
			
		||||
static ID id_start_document;
 | 
			
		||||
static ID id_end_document;
 | 
			
		||||
static ID id_alias;
 | 
			
		||||
static ID id_scalar;
 | 
			
		||||
static ID id_start_sequence;
 | 
			
		||||
static ID id_end_sequence;
 | 
			
		||||
static ID id_start_mapping;
 | 
			
		||||
static ID id_end_mapping;
 | 
			
		||||
 | 
			
		||||
static int io_reader(void * data, unsigned char *buf, size_t size, size_t *read)
 | 
			
		||||
{
 | 
			
		||||
    VALUE io = (VALUE)data;
 | 
			
		||||
    VALUE string = rb_funcall(io, id_read, 1, INT2NUM(size));
 | 
			
		||||
 | 
			
		||||
    *read = 0;
 | 
			
		||||
 | 
			
		||||
    if(! NIL_P(string)) {
 | 
			
		||||
	void * str = (void *)StringValuePtr(string);
 | 
			
		||||
	*read = (size_t)RSTRING_LEN(string);
 | 
			
		||||
	memcpy(buf, str, *read);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * call-seq:
 | 
			
		||||
 *    parser.parse(yaml)
 | 
			
		||||
 *
 | 
			
		||||
 * Parse the YAML document contained in +yaml+.  Events will be called on
 | 
			
		||||
 * the handler set on the parser instance.
 | 
			
		||||
 *
 | 
			
		||||
 * See Psych::Parser and Psych::Parser#handler
 | 
			
		||||
 */
 | 
			
		||||
static VALUE parse(VALUE self, VALUE yaml)
 | 
			
		||||
{
 | 
			
		||||
    yaml_parser_t parser;
 | 
			
		||||
    yaml_event_t event;
 | 
			
		||||
 | 
			
		||||
    yaml_parser_initialize(&parser);
 | 
			
		||||
 | 
			
		||||
    if(rb_respond_to(yaml, id_read)) {
 | 
			
		||||
	yaml_parser_set_input(&parser, io_reader, (void *)yaml);
 | 
			
		||||
    } else {
 | 
			
		||||
	yaml_parser_set_input_string(
 | 
			
		||||
		&parser,
 | 
			
		||||
		(const unsigned char *)StringValuePtr(yaml),
 | 
			
		||||
		(size_t)RSTRING_LEN(yaml)
 | 
			
		||||
		);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int done = 0;
 | 
			
		||||
#ifdef HAVE_RUBY_ENCODING_H
 | 
			
		||||
    int encoding = rb_enc_find_index("ASCII-8BIT");
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    VALUE handler = rb_iv_get(self, "@handler");
 | 
			
		||||
 | 
			
		||||
    while(!done) {
 | 
			
		||||
	if(!yaml_parser_parse(&parser, &event)) {
 | 
			
		||||
	    size_t line   = parser.mark.line;
 | 
			
		||||
	    size_t column = parser.mark.column;
 | 
			
		||||
 | 
			
		||||
	    yaml_parser_delete(&parser);
 | 
			
		||||
	    rb_raise(ePsychSyntaxError, "couldn't parse YAML at line %d column %d",
 | 
			
		||||
		    (int)line, (int)column);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch(event.type) {
 | 
			
		||||
	    case YAML_STREAM_START_EVENT:
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_RUBY_ENCODING_H
 | 
			
		||||
		switch(event.data.stream_start.encoding) {
 | 
			
		||||
		    case YAML_ANY_ENCODING:
 | 
			
		||||
			break;
 | 
			
		||||
		    case YAML_UTF8_ENCODING:
 | 
			
		||||
			encoding = rb_enc_find_index("UTF-8");
 | 
			
		||||
			break;
 | 
			
		||||
		    case YAML_UTF16LE_ENCODING:
 | 
			
		||||
			encoding = rb_enc_find_index("UTF-16LE");
 | 
			
		||||
			break;
 | 
			
		||||
		    case YAML_UTF16BE_ENCODING:
 | 
			
		||||
			encoding = rb_enc_find_index("UTF-16BE");
 | 
			
		||||
			break;
 | 
			
		||||
		    default:
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		rb_funcall(handler, id_start_stream, 1,
 | 
			
		||||
			INT2NUM((long)event.data.stream_start.encoding)
 | 
			
		||||
	      );
 | 
			
		||||
		break;
 | 
			
		||||
	    case YAML_DOCUMENT_START_EVENT:
 | 
			
		||||
		{
 | 
			
		||||
	// Grab the document version
 | 
			
		||||
	VALUE version = event.data.document_start.version_directive ?
 | 
			
		||||
	    rb_ary_new3(
 | 
			
		||||
		    (long)2,
 | 
			
		||||
		    INT2NUM((long)event.data.document_start.version_directive->major),
 | 
			
		||||
		    INT2NUM((long)event.data.document_start.version_directive->minor)
 | 
			
		||||
		 ) : rb_ary_new();
 | 
			
		||||
 | 
			
		||||
	// Get a list of tag directives (if any)
 | 
			
		||||
	VALUE tag_directives = rb_ary_new();
 | 
			
		||||
	if(event.data.document_start.tag_directives.start) {
 | 
			
		||||
	    yaml_tag_directive_t *start =
 | 
			
		||||
		event.data.document_start.tag_directives.start;
 | 
			
		||||
	    yaml_tag_directive_t *end =
 | 
			
		||||
		event.data.document_start.tag_directives.end;
 | 
			
		||||
	    for(; start != end; start++) {
 | 
			
		||||
		VALUE handle = Qnil;
 | 
			
		||||
		if(start->handle) {
 | 
			
		||||
		    handle = rb_str_new2((const char *)start->handle);
 | 
			
		||||
#ifdef HAVE_RUBY_ENCODING_H
 | 
			
		||||
		    rb_enc_associate_index(handle, encoding);
 | 
			
		||||
#endif
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		VALUE prefix = Qnil;
 | 
			
		||||
		if(start->prefix) {
 | 
			
		||||
		    prefix = rb_str_new2((const char *)start->prefix);
 | 
			
		||||
#ifdef HAVE_RUBY_ENCODING_H
 | 
			
		||||
		    rb_enc_associate_index(prefix, encoding);
 | 
			
		||||
#endif
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		VALUE pair = rb_ary_new3((long)2, handle, prefix);
 | 
			
		||||
		rb_ary_push(tag_directives, pair);
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
	rb_funcall(handler, id_start_document, 3,
 | 
			
		||||
		version, tag_directives,
 | 
			
		||||
		event.data.document_start.implicit == 1 ? Qtrue : Qfalse
 | 
			
		||||
	    );
 | 
			
		||||
    }
 | 
			
		||||
		break;
 | 
			
		||||
	    case YAML_DOCUMENT_END_EVENT:
 | 
			
		||||
		rb_funcall(handler, id_end_document, 1,
 | 
			
		||||
			event.data.document_end.implicit == 1 ? Qtrue : Qfalse
 | 
			
		||||
	      );
 | 
			
		||||
		break;
 | 
			
		||||
	    case YAML_ALIAS_EVENT:
 | 
			
		||||
		{
 | 
			
		||||
	VALUE alias = Qnil;
 | 
			
		||||
	if(event.data.alias.anchor) {
 | 
			
		||||
	    alias = rb_str_new2((const char *)event.data.alias.anchor);
 | 
			
		||||
#ifdef HAVE_RUBY_ENCODING_H
 | 
			
		||||
	    rb_enc_associate_index(alias, encoding);
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rb_funcall(handler, id_alias, 1, alias);
 | 
			
		||||
    }
 | 
			
		||||
		break;
 | 
			
		||||
	    case YAML_SCALAR_EVENT:
 | 
			
		||||
		{
 | 
			
		||||
	VALUE val = rb_str_new(
 | 
			
		||||
		(const char *)event.data.scalar.value,
 | 
			
		||||
		(long)event.data.scalar.length
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_RUBY_ENCODING_H
 | 
			
		||||
	rb_enc_associate_index(val, encoding);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	VALUE anchor = Qnil;
 | 
			
		||||
	if(event.data.scalar.anchor) {
 | 
			
		||||
	    anchor = rb_str_new2((const char *)event.data.scalar.anchor);
 | 
			
		||||
#ifdef HAVE_RUBY_ENCODING_H
 | 
			
		||||
	    rb_enc_associate_index(anchor, encoding);
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	VALUE tag = Qnil;
 | 
			
		||||
	if(event.data.scalar.tag) {
 | 
			
		||||
	    tag = rb_str_new2((const char *)event.data.scalar.tag);
 | 
			
		||||
#ifdef HAVE_RUBY_ENCODING_H
 | 
			
		||||
	    rb_enc_associate_index(tag, encoding);
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	VALUE plain_implicit =
 | 
			
		||||
	    event.data.scalar.plain_implicit == 0 ? Qfalse : Qtrue;
 | 
			
		||||
 | 
			
		||||
	VALUE quoted_implicit =
 | 
			
		||||
	    event.data.scalar.quoted_implicit == 0 ? Qfalse : Qtrue;
 | 
			
		||||
 | 
			
		||||
	VALUE style = INT2NUM((long)event.data.scalar.style);
 | 
			
		||||
 | 
			
		||||
	rb_funcall(handler, id_scalar, 6,
 | 
			
		||||
		val, anchor, tag, plain_implicit, quoted_implicit, style);
 | 
			
		||||
    }
 | 
			
		||||
		break;
 | 
			
		||||
	    case YAML_SEQUENCE_START_EVENT:
 | 
			
		||||
		{
 | 
			
		||||
	VALUE anchor = Qnil;
 | 
			
		||||
	if(event.data.sequence_start.anchor) {
 | 
			
		||||
	    anchor = rb_str_new2((const char *)event.data.sequence_start.anchor);
 | 
			
		||||
#ifdef HAVE_RUBY_ENCODING_H
 | 
			
		||||
	    rb_enc_associate_index(anchor, encoding);
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	VALUE tag = Qnil;
 | 
			
		||||
	if(event.data.sequence_start.tag) {
 | 
			
		||||
	    tag = rb_str_new2((const char *)event.data.sequence_start.tag);
 | 
			
		||||
#ifdef HAVE_RUBY_ENCODING_H
 | 
			
		||||
	    rb_enc_associate_index(tag, encoding);
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	VALUE implicit =
 | 
			
		||||
	    event.data.sequence_start.implicit == 0 ? Qfalse : Qtrue;
 | 
			
		||||
 | 
			
		||||
	VALUE style = INT2NUM((long)event.data.sequence_start.style);
 | 
			
		||||
 | 
			
		||||
	rb_funcall(handler, id_start_sequence, 4,
 | 
			
		||||
		anchor, tag, implicit, style);
 | 
			
		||||
    }
 | 
			
		||||
		break;
 | 
			
		||||
	    case YAML_SEQUENCE_END_EVENT:
 | 
			
		||||
		rb_funcall(handler, id_end_sequence, 0);
 | 
			
		||||
		break;
 | 
			
		||||
	    case YAML_MAPPING_START_EVENT:
 | 
			
		||||
		{
 | 
			
		||||
	VALUE anchor = Qnil;
 | 
			
		||||
	if(event.data.mapping_start.anchor) {
 | 
			
		||||
	    anchor = rb_str_new2((const char *)event.data.mapping_start.anchor);
 | 
			
		||||
#ifdef HAVE_RUBY_ENCODING_H
 | 
			
		||||
	    rb_enc_associate_index(anchor, encoding);
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	VALUE tag = Qnil;
 | 
			
		||||
	if(event.data.mapping_start.tag) {
 | 
			
		||||
	    tag = rb_str_new2((const char *)event.data.mapping_start.tag);
 | 
			
		||||
#ifdef HAVE_RUBY_ENCODING_H
 | 
			
		||||
	    rb_enc_associate_index(tag, encoding);
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	VALUE implicit =
 | 
			
		||||
	    event.data.mapping_start.implicit == 0 ? Qfalse : Qtrue;
 | 
			
		||||
 | 
			
		||||
	VALUE style = INT2NUM((long)event.data.mapping_start.style);
 | 
			
		||||
 | 
			
		||||
	rb_funcall(handler, id_start_mapping, 4,
 | 
			
		||||
		anchor, tag, implicit, style);
 | 
			
		||||
    }
 | 
			
		||||
		break;
 | 
			
		||||
	    case YAML_MAPPING_END_EVENT:
 | 
			
		||||
		rb_funcall(handler, id_end_mapping, 0);
 | 
			
		||||
		break;
 | 
			
		||||
	    case YAML_NO_EVENT:
 | 
			
		||||
		rb_funcall(handler, id_empty, 0);
 | 
			
		||||
		break;
 | 
			
		||||
	    case YAML_STREAM_END_EVENT:
 | 
			
		||||
		rb_funcall(handler, id_end_stream, 0);
 | 
			
		||||
		done = 1;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Init_psych_parser()
 | 
			
		||||
{
 | 
			
		||||
#if 0
 | 
			
		||||
    mPsych = rb_define_module("Psych");
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    cPsychParser = rb_define_class_under(mPsych, "Parser", rb_cObject);
 | 
			
		||||
 | 
			
		||||
    /* Any encoding: Let the parser choose the encoding */
 | 
			
		||||
    rb_define_const(cPsychParser, "ANY", INT2NUM(YAML_ANY_ENCODING));
 | 
			
		||||
 | 
			
		||||
    /* UTF-8 Encoding */
 | 
			
		||||
    rb_define_const(cPsychParser, "UTF8", INT2NUM(YAML_UTF8_ENCODING));
 | 
			
		||||
 | 
			
		||||
    /* UTF-16-LE Encoding with BOM */
 | 
			
		||||
    rb_define_const(cPsychParser, "UTF16LE", INT2NUM(YAML_UTF16LE_ENCODING));
 | 
			
		||||
 | 
			
		||||
    /* UTF-16-BE Encoding with BOM */
 | 
			
		||||
    rb_define_const(cPsychParser, "UTF16BE", INT2NUM(YAML_UTF16BE_ENCODING));
 | 
			
		||||
 | 
			
		||||
    ePsychSyntaxError = rb_define_class_under(mPsych, "SyntaxError", rb_eSyntaxError);
 | 
			
		||||
 | 
			
		||||
    rb_define_method(cPsychParser, "parse", parse, 1);
 | 
			
		||||
 | 
			
		||||
    id_read           = rb_intern("read");
 | 
			
		||||
    id_empty          = rb_intern("empty");
 | 
			
		||||
    id_start_stream   = rb_intern("start_stream");
 | 
			
		||||
    id_end_stream     = rb_intern("end_stream");
 | 
			
		||||
    id_start_document = rb_intern("start_document");
 | 
			
		||||
    id_end_document   = rb_intern("end_document");
 | 
			
		||||
    id_alias          = rb_intern("alias");
 | 
			
		||||
    id_scalar         = rb_intern("scalar");
 | 
			
		||||
    id_start_sequence = rb_intern("start_sequence");
 | 
			
		||||
    id_end_sequence   = rb_intern("end_sequence");
 | 
			
		||||
    id_start_mapping  = rb_intern("start_mapping");
 | 
			
		||||
    id_end_mapping    = rb_intern("end_mapping");
 | 
			
		||||
}
 | 
			
		||||
/* vim: set noet sws=4 sw=4: */
 | 
			
		||||
							
								
								
									
										6
									
								
								ext/psych/parser.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								ext/psych/parser.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,6 @@
 | 
			
		|||
#ifndef PSYCH_PARSER_H
 | 
			
		||||
#define PSYCH_PARSER_H
 | 
			
		||||
 | 
			
		||||
void Init_psych_parser();
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										35
									
								
								ext/psych/psych.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								ext/psych/psych.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,35 @@
 | 
			
		|||
#include <psych.h>
 | 
			
		||||
 | 
			
		||||
/* call-seq: Psych.libyaml_version
 | 
			
		||||
 *
 | 
			
		||||
 * Returns the version of libyaml being used
 | 
			
		||||
 */
 | 
			
		||||
static VALUE libyaml_version(VALUE module)
 | 
			
		||||
{
 | 
			
		||||
    int major, minor, patch;
 | 
			
		||||
 | 
			
		||||
    yaml_get_version(&major, &minor, &patch);
 | 
			
		||||
 | 
			
		||||
    VALUE list[3] = {
 | 
			
		||||
	INT2NUM((long)major),
 | 
			
		||||
	INT2NUM((long)minor),
 | 
			
		||||
	INT2NUM((long)patch)
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    return rb_ary_new4((long)3, list);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE mPsych;
 | 
			
		||||
 | 
			
		||||
void Init_psych()
 | 
			
		||||
{
 | 
			
		||||
    mPsych = rb_define_module("Psych");
 | 
			
		||||
 | 
			
		||||
    rb_define_singleton_method(mPsych, "libyaml_version", libyaml_version, 0);
 | 
			
		||||
 | 
			
		||||
    Init_psych_parser();
 | 
			
		||||
    Init_psych_emitter();
 | 
			
		||||
    Init_psych_to_ruby();
 | 
			
		||||
    Init_psych_yaml_tree();
 | 
			
		||||
}
 | 
			
		||||
/* vim: set noet sws=4 sw=4: */
 | 
			
		||||
							
								
								
									
										20
									
								
								ext/psych/psych.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								ext/psych/psych.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,20 @@
 | 
			
		|||
#ifndef PSYCH_H
 | 
			
		||||
#define PSYCH_H
 | 
			
		||||
 | 
			
		||||
#include <ruby.h>
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_RUBY_ENCODING_H
 | 
			
		||||
#include <ruby/encoding.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <yaml.h>
 | 
			
		||||
 | 
			
		||||
#include <parser.h>
 | 
			
		||||
#include <emitter.h>
 | 
			
		||||
#include <to_ruby.h>
 | 
			
		||||
#include <yaml_tree.h>
 | 
			
		||||
 | 
			
		||||
extern VALUE mPsych;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										41
									
								
								ext/psych/to_ruby.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								ext/psych/to_ruby.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,41 @@
 | 
			
		|||
#include <psych.h>
 | 
			
		||||
 | 
			
		||||
VALUE cPsychVisitorsToRuby;
 | 
			
		||||
 | 
			
		||||
/* call-seq: vis.build_exception(klass, message)
 | 
			
		||||
 *
 | 
			
		||||
 * Create an exception with class +klass+ and +message+
 | 
			
		||||
 */
 | 
			
		||||
static VALUE build_exception(VALUE self, VALUE klass, VALUE mesg)
 | 
			
		||||
{
 | 
			
		||||
    VALUE e = rb_obj_alloc(klass);
 | 
			
		||||
 | 
			
		||||
    rb_iv_set(e, "mesg", mesg);
 | 
			
		||||
 | 
			
		||||
    return e;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* call-seq: vis.path2class(path)
 | 
			
		||||
 *
 | 
			
		||||
 * Convert +path+ string to a class
 | 
			
		||||
 */
 | 
			
		||||
static VALUE path2class(VALUE self, VALUE path)
 | 
			
		||||
{
 | 
			
		||||
#ifdef HAVE_RUBY_ENCODING_H
 | 
			
		||||
    return rb_path_to_class(path);
 | 
			
		||||
#else
 | 
			
		||||
    return rb_path2class(StringValuePtr(path));
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Init_psych_to_ruby(void)
 | 
			
		||||
{
 | 
			
		||||
    VALUE psych     = rb_define_module("Psych");
 | 
			
		||||
    VALUE visitors  = rb_define_module_under(psych, "Visitors");
 | 
			
		||||
    VALUE visitor   = rb_define_class_under(visitors, "Visitor", rb_cObject);
 | 
			
		||||
    cPsychVisitorsToRuby = rb_define_class_under(visitors, "ToRuby", visitor);
 | 
			
		||||
 | 
			
		||||
    rb_define_private_method(cPsychVisitorsToRuby, "build_exception", build_exception, 2);
 | 
			
		||||
    rb_define_private_method(cPsychVisitorsToRuby, "path2class", path2class, 1);
 | 
			
		||||
}
 | 
			
		||||
/* vim: set noet sws=4 sw=4: */
 | 
			
		||||
							
								
								
									
										8
									
								
								ext/psych/to_ruby.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								ext/psych/to_ruby.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,8 @@
 | 
			
		|||
#ifndef PSYCH_TO_RUBY_H
 | 
			
		||||
#define PSYCH_TO_RUBY_H
 | 
			
		||||
 | 
			
		||||
#include <psych.h>
 | 
			
		||||
 | 
			
		||||
void Init_psych_to_ruby(void);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										24
									
								
								ext/psych/yaml_tree.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								ext/psych/yaml_tree.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
#include <psych.h>
 | 
			
		||||
 | 
			
		||||
VALUE cPsychVisitorsYamlTree;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * call-seq: private_iv_get(target, prop)
 | 
			
		||||
 *
 | 
			
		||||
 * Get the private instance variable +prop+ from +target+
 | 
			
		||||
 */
 | 
			
		||||
static VALUE private_iv_get(VALUE self, VALUE target, VALUE prop)
 | 
			
		||||
{
 | 
			
		||||
    return rb_attr_get(target, rb_intern(StringValuePtr(prop)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Init_psych_yaml_tree(void)
 | 
			
		||||
{
 | 
			
		||||
    VALUE psych     = rb_define_module("Psych");
 | 
			
		||||
    VALUE visitors  = rb_define_module_under(psych, "Visitors");
 | 
			
		||||
    VALUE visitor   = rb_define_class_under(visitors, "Visitor", rb_cObject);
 | 
			
		||||
    cPsychVisitorsYamlTree = rb_define_class_under(visitors, "YAMLTree", visitor);
 | 
			
		||||
 | 
			
		||||
    rb_define_private_method(cPsychVisitorsYamlTree, "private_iv_get", private_iv_get, 2);
 | 
			
		||||
}
 | 
			
		||||
/* vim: set noet sws=4 sw=4: */
 | 
			
		||||
							
								
								
									
										8
									
								
								ext/psych/yaml_tree.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								ext/psych/yaml_tree.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,8 @@
 | 
			
		|||
#ifndef PSYCH_YAML_TREE_H
 | 
			
		||||
#define PSYCH_YAML_TREE_H
 | 
			
		||||
 | 
			
		||||
#include <psych.h>
 | 
			
		||||
 | 
			
		||||
void Init_psych_yaml_tree(void);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										236
									
								
								lib/psych.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										236
									
								
								lib/psych.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,236 @@
 | 
			
		|||
require 'psych/psych'
 | 
			
		||||
require 'psych/nodes'
 | 
			
		||||
require 'psych/visitors'
 | 
			
		||||
require 'psych/handler'
 | 
			
		||||
require 'psych/tree_builder'
 | 
			
		||||
require 'psych/parser'
 | 
			
		||||
require 'psych/omap'
 | 
			
		||||
require 'psych/set'
 | 
			
		||||
require 'psych/coder'
 | 
			
		||||
require 'psych/core_ext'
 | 
			
		||||
 | 
			
		||||
###
 | 
			
		||||
# = Overview
 | 
			
		||||
#
 | 
			
		||||
# Psych is a YAML parser and emitter.  Psych leverages
 | 
			
		||||
# libyaml[http://libyaml.org] for it's YAML parsing and emitting capabilities.
 | 
			
		||||
# In addition to wrapping libyaml, Psych also knows how to serialize and
 | 
			
		||||
# de-serialize most Ruby objects to and from the YAML format.
 | 
			
		||||
#
 | 
			
		||||
# = I NEED TO PARSE OR EMIT YAML RIGHT NOW!
 | 
			
		||||
#
 | 
			
		||||
#   # Parse some YAML
 | 
			
		||||
#   Psych.load("--- foo") # => "foo"
 | 
			
		||||
#
 | 
			
		||||
#   # Emit some YAML
 | 
			
		||||
#   Psych.dump("foo")     # => "--- foo\n...\n"
 | 
			
		||||
#   { :a => 'b'}.to_yaml  # => "---\n:a: b\n"
 | 
			
		||||
#
 | 
			
		||||
# Got more time on your hands?  Keep on reading!
 | 
			
		||||
#
 | 
			
		||||
# == YAML Parsing
 | 
			
		||||
#
 | 
			
		||||
# Psych provides a range of interfaces for parsing a YAML document ranging from
 | 
			
		||||
# low level to high level, depending on your parsing needs.  At the lowest
 | 
			
		||||
# level, is an event based parser.  Mid level is access to the raw YAML AST,
 | 
			
		||||
# and at the highest level is the ability to unmarshal YAML to ruby objects.
 | 
			
		||||
#
 | 
			
		||||
# === Low level parsing
 | 
			
		||||
#
 | 
			
		||||
# The lowest level parser should be used when the YAML input is already known,
 | 
			
		||||
# and the developer does not want to pay the price of building an AST or
 | 
			
		||||
# automatic detection and conversion to ruby objects.  See Psych::Parser for
 | 
			
		||||
# more information on using the event based parser.
 | 
			
		||||
#
 | 
			
		||||
# === Mid level parsing
 | 
			
		||||
#
 | 
			
		||||
# Psych provides access to an AST produced from parsing a YAML document.  This
 | 
			
		||||
# tree is built using the Psych::Parser and Psych::TreeBuilder.  The AST can
 | 
			
		||||
# be examined and manipulated freely.  Please see Psych::parse_stream,
 | 
			
		||||
# Psych::Nodes, and Psych::Nodes::Node for more information on dealing with
 | 
			
		||||
# YAML syntax trees.
 | 
			
		||||
#
 | 
			
		||||
# === High level parsing
 | 
			
		||||
#
 | 
			
		||||
# The high level YAML parser provided by Psych simply takes YAML as input and
 | 
			
		||||
# returns a Ruby data structure.  For information on using the high level parser
 | 
			
		||||
# see Psych.load
 | 
			
		||||
#
 | 
			
		||||
# == YAML Emitting
 | 
			
		||||
#
 | 
			
		||||
# Psych provides a range of interfaces ranging from low to high level for
 | 
			
		||||
# producing YAML documents.  Very similar to the YAML parsing interfaces, Psych
 | 
			
		||||
# provides at the lowest level, an event based system, mid-level is building
 | 
			
		||||
# a YAML AST, and the highest level is converting a Ruby object straight to
 | 
			
		||||
# a YAML document.
 | 
			
		||||
#
 | 
			
		||||
# === Low level emitting
 | 
			
		||||
#
 | 
			
		||||
# The lowest level emitter is an event based system.  Events are sent to a
 | 
			
		||||
# Psych::Emitter object.  That object knows how to convert the events to a YAML
 | 
			
		||||
# document.  This interface should be used when document format is known in
 | 
			
		||||
# advance or speed is a concern.  See Psych::Emitter for more information.
 | 
			
		||||
#
 | 
			
		||||
# === Mid level emitting
 | 
			
		||||
#
 | 
			
		||||
# At the mid level is building an AST.  This AST is exactly the same as the AST
 | 
			
		||||
# used when parsing a YAML document.  Users can build an AST by hand and the
 | 
			
		||||
# AST knows how to emit itself as a YAML document.  See Psych::Nodes,
 | 
			
		||||
# Psych::Nodes::Node, and Psych::TreeBuilder for more information on building
 | 
			
		||||
# a YAML AST.
 | 
			
		||||
#
 | 
			
		||||
# === High level emitting
 | 
			
		||||
#
 | 
			
		||||
# The high level emitter has the easiest interface.  Psych simply takes a Ruby
 | 
			
		||||
# data structure and converts it to a YAML document.  See Psych.dump for more
 | 
			
		||||
# information on dumping a Ruby data structure.
 | 
			
		||||
 | 
			
		||||
module Psych
 | 
			
		||||
  # The version is Psych you're using
 | 
			
		||||
  VERSION         = '1.0.0'
 | 
			
		||||
 | 
			
		||||
  # The version of libyaml Psych is using
 | 
			
		||||
  LIBYAML_VERSION = Psych.libyaml_version.join '.'
 | 
			
		||||
 | 
			
		||||
  ###
 | 
			
		||||
  # Load +yaml+ in to a Ruby data structure.  If multiple documents are
 | 
			
		||||
  # provided, the object contained in the first document will be returned.
 | 
			
		||||
  #
 | 
			
		||||
  # Example:
 | 
			
		||||
  #
 | 
			
		||||
  #   Psych.load("--- a")           # => 'a'
 | 
			
		||||
  #   Psych.load("---\n - a\n - b") # => ['a', 'b']
 | 
			
		||||
  def self.load yaml
 | 
			
		||||
    parse(yaml).to_ruby
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  ###
 | 
			
		||||
  # Parse a YAML string in +yaml+.  Returns the first object of a YAML AST.
 | 
			
		||||
  #
 | 
			
		||||
  # Example:
 | 
			
		||||
  #
 | 
			
		||||
  #   Psych.load("---\n - a\n - b") # => #<Psych::Nodes::Sequence:0x00>
 | 
			
		||||
  #
 | 
			
		||||
  # See Psych::Nodes for more information about YAML AST.
 | 
			
		||||
  def self.parse yaml
 | 
			
		||||
    parse_stream(yaml).children.first.children.first
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  ###
 | 
			
		||||
  # Parse a file at +filename+. Returns the YAML AST.
 | 
			
		||||
  def self.parse_file filename
 | 
			
		||||
    File.open filename do |f|
 | 
			
		||||
      parse f
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  ###
 | 
			
		||||
  # Returns a default parser
 | 
			
		||||
  def self.parser
 | 
			
		||||
    Psych::Parser.new(TreeBuilder.new)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  ###
 | 
			
		||||
  # Parse a YAML string in +yaml+.  Returns the full AST for the YAML document.
 | 
			
		||||
  # This method can handle multiple YAML documents contained in +yaml+.
 | 
			
		||||
  #
 | 
			
		||||
  # Example:
 | 
			
		||||
  #
 | 
			
		||||
  #   Psych.load("---\n - a\n - b") # => #<Psych::Nodes::Stream:0x00>
 | 
			
		||||
  #
 | 
			
		||||
  # See Psych::Nodes for more information about YAML AST.
 | 
			
		||||
  def self.parse_stream yaml
 | 
			
		||||
    parser = self.parser
 | 
			
		||||
    parser.parse yaml
 | 
			
		||||
    parser.handler.root
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  ###
 | 
			
		||||
  # Dump Ruby object +o+ to a YAML string using +options+.
 | 
			
		||||
  #
 | 
			
		||||
  # Example:
 | 
			
		||||
  #
 | 
			
		||||
  #   Psych.dump(['a', 'b'])  # => "---\n- a\n- b\n"
 | 
			
		||||
  def self.dump o, options = {}
 | 
			
		||||
    visitor = Psych::Visitors::YAMLTree.new options
 | 
			
		||||
    visitor << o
 | 
			
		||||
    visitor.tree.to_yaml
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  ###
 | 
			
		||||
  # Dump a list of objects as separate documents to a document stream.
 | 
			
		||||
  #
 | 
			
		||||
  # Example:
 | 
			
		||||
  #
 | 
			
		||||
  #   Psych.dump_stream("foo\n  ", {}) # => "--- ! \"foo\\n  \"\n--- {}\n"
 | 
			
		||||
  def self.dump_stream *objects
 | 
			
		||||
    visitor = Psych::Visitors::YAMLTree.new {}
 | 
			
		||||
    objects.each do |o|
 | 
			
		||||
      visitor << o
 | 
			
		||||
    end
 | 
			
		||||
    visitor.tree.to_yaml
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  ###
 | 
			
		||||
  # Dump Ruby object +o+ to a JSON string.
 | 
			
		||||
  def self.to_json o
 | 
			
		||||
    visitor = Psych::Visitors::JSONTree.new(:json => true)
 | 
			
		||||
    visitor << o
 | 
			
		||||
    visitor.tree.to_yaml
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  ###
 | 
			
		||||
  # Load multiple documents given in +yaml+.  Returns the parsed documents
 | 
			
		||||
  # as a list.  For example:
 | 
			
		||||
  #
 | 
			
		||||
  #   Psych.load_documents("--- foo\n...\n--- bar\n...") # => ['foo', 'bar']
 | 
			
		||||
  #
 | 
			
		||||
  def self.load_stream yaml
 | 
			
		||||
    parse_stream(yaml).children.map { |child| child.to_ruby }
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def self.load_documents yaml, &block
 | 
			
		||||
    if $VERBOSE
 | 
			
		||||
      warn "#{caller[0]}: load_documents is deprecated, use load_stream"
 | 
			
		||||
    end
 | 
			
		||||
    list = load_stream yaml
 | 
			
		||||
    return list unless block_given?
 | 
			
		||||
    list.each(&block)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  ###
 | 
			
		||||
  # Load the document contained in +filename+.  Returns the yaml contained in
 | 
			
		||||
  # +filename+ as a ruby object
 | 
			
		||||
  def self.load_file filename
 | 
			
		||||
    self.load File.open(filename)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # :stopdoc:
 | 
			
		||||
  @domain_types = {}
 | 
			
		||||
  def self.add_domain_type domain, type_tag, &block
 | 
			
		||||
    @domain_types[type_tag] = ["http://#{domain}", block]
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def self.add_builtin_type type_tag, &block
 | 
			
		||||
    @domain_types[type_tag] = ['yaml.org', block]
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def self.remove_type type_tag
 | 
			
		||||
    @domain_types.delete type_tag
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  @load_tags = {}
 | 
			
		||||
  @dump_tags = {}
 | 
			
		||||
  def self.add_tag tag, klass
 | 
			
		||||
    @load_tags[tag] = klass
 | 
			
		||||
    @dump_tags[klass] = tag
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  class << self
 | 
			
		||||
    attr_accessor :load_tags
 | 
			
		||||
    attr_accessor :dump_tags
 | 
			
		||||
    attr_accessor :domain_types
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # :startdoc:
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										68
									
								
								lib/psych/coder.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								lib/psych/coder.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,68 @@
 | 
			
		|||
module Psych
 | 
			
		||||
  ###
 | 
			
		||||
  # If an object defines +encode_with+, then an instance of Psych::Coder will
 | 
			
		||||
  # passed to the method when the object is being serialized.  The Coder
 | 
			
		||||
  # automatically assumes a Psych::Nodes::Mapping is being emitted.  Other
 | 
			
		||||
  # objects like Sequence and Scalar may be emitted if +seq=+ or +scalar=+ are
 | 
			
		||||
  # called, respectively.
 | 
			
		||||
  class Coder
 | 
			
		||||
    attr_accessor :tag, :style, :implicit
 | 
			
		||||
    attr_reader   :type, :map, :scalar, :seq
 | 
			
		||||
 | 
			
		||||
    def initialize tag
 | 
			
		||||
      @map        = {}
 | 
			
		||||
      @seq        = []
 | 
			
		||||
      @implicit   = false
 | 
			
		||||
      @type       = :map
 | 
			
		||||
      @tag        = tag
 | 
			
		||||
      @style      = Psych::Nodes::Mapping::BLOCK
 | 
			
		||||
      @scalar     = nil
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Emit a scalar with +value+ and +tag+
 | 
			
		||||
    def represent_scalar tag, value
 | 
			
		||||
      self.tag    = tag
 | 
			
		||||
      self.scalar = value
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Emit a sequence with +list+ and +tag+
 | 
			
		||||
    def represent_seq tag, list
 | 
			
		||||
      @tag = tag
 | 
			
		||||
      self.seq = list
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Emit a sequence with +map+ and +tag+
 | 
			
		||||
    def represent_map tag, map
 | 
			
		||||
      @tag = tag
 | 
			
		||||
      self.map = map
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Emit a scalar with +value+
 | 
			
		||||
    def scalar= value
 | 
			
		||||
      @type   = :scalar
 | 
			
		||||
      @scalar = value
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Emit a map with +value+
 | 
			
		||||
    def map= map
 | 
			
		||||
      @type = :map
 | 
			
		||||
      @map  = map
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def []= k, v
 | 
			
		||||
      @type = :map
 | 
			
		||||
      @map[k] = v
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def [] k
 | 
			
		||||
      @type = :map
 | 
			
		||||
      @map[k]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Emit a sequence of +list+
 | 
			
		||||
    def seq= list
 | 
			
		||||
      @type = :seq
 | 
			
		||||
      @seq  = list
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										22
									
								
								lib/psych/core_ext.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								lib/psych/core_ext.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,22 @@
 | 
			
		|||
class Object
 | 
			
		||||
  def self.yaml_tag url
 | 
			
		||||
    Psych.add_tag(url, self)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # FIXME: rename this to "to_yaml" when syck is removed
 | 
			
		||||
 | 
			
		||||
  ###
 | 
			
		||||
  # call-seq: to_yaml
 | 
			
		||||
  #
 | 
			
		||||
  # Convert an object to YAML
 | 
			
		||||
  def psych_to_yaml options = {}
 | 
			
		||||
    Psych.dump self, options
 | 
			
		||||
  end
 | 
			
		||||
  alias :to_yaml :psych_to_yaml
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
module Kernel
 | 
			
		||||
  def y *objects
 | 
			
		||||
    puts Psych.dump_stream(*objects)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										4
									
								
								lib/psych/emitter.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								lib/psych/emitter.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
module Psych
 | 
			
		||||
  class Emitter < Psych::Handler
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										215
									
								
								lib/psych/handler.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										215
									
								
								lib/psych/handler.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,215 @@
 | 
			
		|||
module Psych
 | 
			
		||||
  ###
 | 
			
		||||
  # Psych::Handler is an abstract base class that defines the events used
 | 
			
		||||
  # when dealing with Psych::Parser.  Clients who want to use Psych::Parser
 | 
			
		||||
  # should implement a class that inherits from Psych::Handler and define
 | 
			
		||||
  # events that they can handle.
 | 
			
		||||
  #
 | 
			
		||||
  # Psych::Handler defines all events that Psych::Parser can possibly send to
 | 
			
		||||
  # event handlers.
 | 
			
		||||
  #
 | 
			
		||||
  # See Psych::Parser for more details
 | 
			
		||||
  class Handler
 | 
			
		||||
    ###
 | 
			
		||||
    # Called with +encoding+ when the YAML stream starts.  This method is
 | 
			
		||||
    # called once per stream.  A stream may contain multiple documents.
 | 
			
		||||
    #
 | 
			
		||||
    # See the constants in Psych::Parser for the possible values of +encoding+.
 | 
			
		||||
    def start_stream encoding
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    ###
 | 
			
		||||
    # Called when the document starts with the declared +version+,
 | 
			
		||||
    # +tag_directives+, if the document is +implicit+.
 | 
			
		||||
    #
 | 
			
		||||
    # +version+ will be an array of integers indicating the YAML version being
 | 
			
		||||
    # dealt with, +tag_directives+ is a list of tuples indicating the prefix
 | 
			
		||||
    # and suffix of each tag, and +implicit+ is a boolean indicating whether
 | 
			
		||||
    # the document is started implicitly.
 | 
			
		||||
    #
 | 
			
		||||
    # === Example
 | 
			
		||||
    #
 | 
			
		||||
    # Given the following YAML:
 | 
			
		||||
    #
 | 
			
		||||
    #   %YAML 1.1
 | 
			
		||||
    #   %TAG ! tag:tenderlovemaking.com,2009:
 | 
			
		||||
    #   --- !squee
 | 
			
		||||
    #
 | 
			
		||||
    # The parameters for start_document must be this:
 | 
			
		||||
    #
 | 
			
		||||
    #   version         # => [1, 1]
 | 
			
		||||
    #   tag_directives  # => [["!", "tag:tenderlovemaking.com,2009:"]]
 | 
			
		||||
    #   implicit        # => false
 | 
			
		||||
    def start_document version, tag_directives, implicit
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    ###
 | 
			
		||||
    # Called with the document ends.  +implicit+ is a boolean value indicating
 | 
			
		||||
    # whether or not the document has an implicit ending.
 | 
			
		||||
    #
 | 
			
		||||
    # === Example
 | 
			
		||||
    #
 | 
			
		||||
    # Given the following YAML:
 | 
			
		||||
    #
 | 
			
		||||
    #   ---
 | 
			
		||||
    #     hello world
 | 
			
		||||
    #
 | 
			
		||||
    # +implicit+ will be true.  Given this YAML:
 | 
			
		||||
    #
 | 
			
		||||
    #   ---
 | 
			
		||||
    #     hello world
 | 
			
		||||
    #   ...
 | 
			
		||||
    #
 | 
			
		||||
    # +implicit+ will be false.
 | 
			
		||||
    def end_document implicit
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    ###
 | 
			
		||||
    # Called when an alias is found to +anchor+.  +anchor+ will be the name
 | 
			
		||||
    # of the anchor found.
 | 
			
		||||
    #
 | 
			
		||||
    # === Example
 | 
			
		||||
    #
 | 
			
		||||
    # Here we have an example of an array that references itself in YAML:
 | 
			
		||||
    #
 | 
			
		||||
    #   --- &ponies
 | 
			
		||||
    #   - first element
 | 
			
		||||
    #   - *ponies
 | 
			
		||||
    #
 | 
			
		||||
    # &ponies is the achor, *ponies is the alias.  In this case, alias is
 | 
			
		||||
    # called with "ponies".
 | 
			
		||||
    def alias anchor
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    ###
 | 
			
		||||
    # Called when a scalar +value+ is found.  The scalar may have an
 | 
			
		||||
    # +anchor+, a +tag+, be implicitly +plain+ or implicitly +quoted+
 | 
			
		||||
    #
 | 
			
		||||
    # +value+ is the string value of the scalar
 | 
			
		||||
    # +anchor+ is an associated anchor or nil
 | 
			
		||||
    # +tag+ is an associated tag or nil
 | 
			
		||||
    # +plain+ is a boolean value
 | 
			
		||||
    # +quoted+ is a boolean value
 | 
			
		||||
    # +style+ is an integer idicating the string style
 | 
			
		||||
    #
 | 
			
		||||
    # See the constants in Psych::Nodes::Scalar for the possible values of
 | 
			
		||||
    # +style+
 | 
			
		||||
    #
 | 
			
		||||
    # === Example
 | 
			
		||||
    #
 | 
			
		||||
    # Here is a YAML document that exercises most of the possible ways this
 | 
			
		||||
    # method can be called:
 | 
			
		||||
    #
 | 
			
		||||
    #   ---
 | 
			
		||||
    #   - !str "foo"
 | 
			
		||||
    #   - &anchor fun
 | 
			
		||||
    #   - many
 | 
			
		||||
    #     lines
 | 
			
		||||
    #   - |
 | 
			
		||||
    #     many
 | 
			
		||||
    #     newlines
 | 
			
		||||
    #
 | 
			
		||||
    # The above YAML document contains a list with four strings.  Here are
 | 
			
		||||
    # the parameters sent to this method in the same order:
 | 
			
		||||
    #
 | 
			
		||||
    #   # value               anchor    tag     plain   quoted  style
 | 
			
		||||
    #   ["foo",               nil,      "!str", false,  false,  3    ]
 | 
			
		||||
    #   ["fun",               "anchor", nil,    true,   false,  1    ]
 | 
			
		||||
    #   ["many lines",        nil,      nil,    true,   false,  1    ]
 | 
			
		||||
    #   ["many\nnewlines\n",  nil,      nil,    false,  true,   4    ]
 | 
			
		||||
    #
 | 
			
		||||
    def scalar value, anchor, tag, plain, quoted, style
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    ###
 | 
			
		||||
    # Called when a sequence is started.
 | 
			
		||||
    #
 | 
			
		||||
    # +anchor+ is the anchor associated with the sequence or nil.
 | 
			
		||||
    # +tag+ is the tag associated with the sequence or nil.
 | 
			
		||||
    # +implicit+ a boolean indicating whether or not the sequence was implicitly
 | 
			
		||||
    # started.
 | 
			
		||||
    # +style+ is an integer indicating the list style.
 | 
			
		||||
    #
 | 
			
		||||
    # See the constants in Psych::Nodes::Sequence for the possible values of
 | 
			
		||||
    # +style+.
 | 
			
		||||
    #
 | 
			
		||||
    # === Example
 | 
			
		||||
    #
 | 
			
		||||
    # Here is a YAML document that exercises most of the possible ways this
 | 
			
		||||
    # method can be called:
 | 
			
		||||
    #
 | 
			
		||||
    #   ---
 | 
			
		||||
    #   - !!seq [
 | 
			
		||||
    #     a
 | 
			
		||||
    #   ]
 | 
			
		||||
    #   - &pewpew
 | 
			
		||||
    #     - b
 | 
			
		||||
    #
 | 
			
		||||
    # The above YAML document consists of three lists, an outer list that
 | 
			
		||||
    # contains two inner lists.  Here is a matrix of the parameters sent
 | 
			
		||||
    # to represent these lists:
 | 
			
		||||
    #
 | 
			
		||||
    #   # anchor    tag                       implicit  style
 | 
			
		||||
    #   [nil,       nil,                      true,     1     ]
 | 
			
		||||
    #   [nil,       "tag:yaml.org,2002:seq",  false,    2     ]
 | 
			
		||||
    #   ["pewpew",  nil,                      true,     1     ]
 | 
			
		||||
 | 
			
		||||
    def start_sequence anchor, tag, implicit, style
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    ###
 | 
			
		||||
    # Called when a sequence ends.
 | 
			
		||||
    def end_sequence
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    ###
 | 
			
		||||
    # Called when a map starts.
 | 
			
		||||
    #
 | 
			
		||||
    # +anchor+ is the anchor associated with the map or +nil+.
 | 
			
		||||
    # +tag+ is the tag associated with the map or +nil+.
 | 
			
		||||
    # +implicit+ is a boolean indicating whether or not the map was implicitly
 | 
			
		||||
    # started.
 | 
			
		||||
    # +style+ is an integer indicating the mapping style.
 | 
			
		||||
    #
 | 
			
		||||
    # See the constants in Psych::Nodes::Mapping for the possible values of
 | 
			
		||||
    # +style+.
 | 
			
		||||
    #
 | 
			
		||||
    # === Example
 | 
			
		||||
    #
 | 
			
		||||
    # Here is a YAML document that exercises most of the possible ways this
 | 
			
		||||
    # method can be called:
 | 
			
		||||
    #
 | 
			
		||||
    #   ---
 | 
			
		||||
    #   k: !!map { hello: world }
 | 
			
		||||
    #   v: &pewpew
 | 
			
		||||
    #     hello: world
 | 
			
		||||
    #
 | 
			
		||||
    # The above YAML document consists of three maps, an outer map that contains
 | 
			
		||||
    # two inner maps.  Below is a matrix of the parameters sent in order to
 | 
			
		||||
    # represent these three maps:
 | 
			
		||||
    #
 | 
			
		||||
    #   # anchor    tag                       implicit  style
 | 
			
		||||
    #   [nil,       nil,                      true,     1     ]
 | 
			
		||||
    #   [nil,       "tag:yaml.org,2002:map",  false,    2     ]
 | 
			
		||||
    #   ["pewpew",  nil,                      true,     1     ]
 | 
			
		||||
 | 
			
		||||
    def start_mapping anchor, tag, implicit, style
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    ###
 | 
			
		||||
    # Called when a map ends
 | 
			
		||||
    def end_mapping
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    ###
 | 
			
		||||
    # Called when an empty event happens. (Which, as far as I can tell, is
 | 
			
		||||
    # never).
 | 
			
		||||
    def empty
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    ###
 | 
			
		||||
    # Called when the YAML stream ends
 | 
			
		||||
    def end_stream
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										77
									
								
								lib/psych/nodes.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								lib/psych/nodes.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,77 @@
 | 
			
		|||
require 'psych/nodes/node'
 | 
			
		||||
require 'psych/nodes/stream'
 | 
			
		||||
require 'psych/nodes/document'
 | 
			
		||||
require 'psych/nodes/sequence'
 | 
			
		||||
require 'psych/nodes/scalar'
 | 
			
		||||
require 'psych/nodes/mapping'
 | 
			
		||||
require 'psych/nodes/alias'
 | 
			
		||||
 | 
			
		||||
module Psych
 | 
			
		||||
  ###
 | 
			
		||||
  # = Overview
 | 
			
		||||
  #
 | 
			
		||||
  # When using Psych.load to deserialize a YAML document, the document is
 | 
			
		||||
  # translated to an intermediary AST.  That intermediary AST is then
 | 
			
		||||
  # translated in to a Ruby object graph.
 | 
			
		||||
  #
 | 
			
		||||
  # In the opposite direction, when using Psych.dump, the Ruby object graph is
 | 
			
		||||
  # translated to an intermediary AST which is then converted to a YAML
 | 
			
		||||
  # document.
 | 
			
		||||
  #
 | 
			
		||||
  # Psych::Nodes contains all of the classes that make up the nodes of a YAML
 | 
			
		||||
  # AST.  You can manually build an AST and use one of the visitors (see
 | 
			
		||||
  # Psych::Visitors) to convert that AST to either a YAML document or to a
 | 
			
		||||
  # Ruby object graph.
 | 
			
		||||
  #
 | 
			
		||||
  # Here is an example of building an AST that represents a list with one
 | 
			
		||||
  # scalar:
 | 
			
		||||
  #
 | 
			
		||||
  #   # Create our nodes
 | 
			
		||||
  #   stream = Psych::Nodes::Stream.new
 | 
			
		||||
  #   doc    = Psych::Nodes::Document.new
 | 
			
		||||
  #   seq    = Psych::Nodes::Sequence.new
 | 
			
		||||
  #   scalar = Psych::Nodes::Scalar.new('foo')
 | 
			
		||||
  #   
 | 
			
		||||
  #   # Build up our tree
 | 
			
		||||
  #   stream.children << doc
 | 
			
		||||
  #   doc.children    << seq
 | 
			
		||||
  #   seq.children    << scalar
 | 
			
		||||
  #
 | 
			
		||||
  # The stream is the root of the tree.  We can then convert the tree to YAML:
 | 
			
		||||
  #
 | 
			
		||||
  #   stream.to_yaml => "---\n- foo\n"
 | 
			
		||||
  #
 | 
			
		||||
  # Or convert it to Ruby:
 | 
			
		||||
  #
 | 
			
		||||
  #   stream.to_ruby => [["foo"]]
 | 
			
		||||
  #
 | 
			
		||||
  # == YAML AST Requirements
 | 
			
		||||
  #
 | 
			
		||||
  # A valid YAML AST *must* have one Psych::Nodes::Stream at the root.  A
 | 
			
		||||
  # Psych::Nodes::Stream node must have 1 or more Psych::Nodes::Document nodes
 | 
			
		||||
  # as children.
 | 
			
		||||
  #
 | 
			
		||||
  # Psych::Nodes::Document nodes must have one and *only* one child.  That child
 | 
			
		||||
  # may be one of:
 | 
			
		||||
  #
 | 
			
		||||
  # * Psych::Nodes::Sequence
 | 
			
		||||
  # * Psych::Nodes::Mapping
 | 
			
		||||
  # * Psych::Nodes::Scalar
 | 
			
		||||
  #
 | 
			
		||||
  # Psych::Nodes::Sequence and Psych::Nodes::Mapping nodes may have many
 | 
			
		||||
  # children, but Psych::Nodes::Mapping nodes should have an even number of
 | 
			
		||||
  # children.
 | 
			
		||||
  #
 | 
			
		||||
  # All of these are valid children for Psych::Nodes::Sequence and
 | 
			
		||||
  # Psych::Nodes::Mapping nodes:
 | 
			
		||||
  #
 | 
			
		||||
  # * Psych::Nodes::Sequence
 | 
			
		||||
  # * Psych::Nodes::Mapping
 | 
			
		||||
  # * Psych::Nodes::Scalar
 | 
			
		||||
  # * Psych::Nodes::Alias
 | 
			
		||||
  #
 | 
			
		||||
  # Psych::Nodes::Scalar and Psych::Nodes::Alias are both terminal nodes and
 | 
			
		||||
  # should not have any children.
 | 
			
		||||
  module Nodes
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										18
									
								
								lib/psych/nodes/alias.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								lib/psych/nodes/alias.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,18 @@
 | 
			
		|||
module Psych
 | 
			
		||||
  module Nodes
 | 
			
		||||
    ###
 | 
			
		||||
    # This class represents a {YAML Alias}[http://yaml.org/spec/1.1/#alias].
 | 
			
		||||
    # It points to an +anchor+.
 | 
			
		||||
    #
 | 
			
		||||
    # A Psych::Nodes::Alias is a terminal node and may have no children.
 | 
			
		||||
    class Alias < Psych::Nodes::Node
 | 
			
		||||
      # The anchor this alias links to
 | 
			
		||||
      attr_accessor :anchor
 | 
			
		||||
 | 
			
		||||
      # Create a new Alias that points to an +anchor+
 | 
			
		||||
      def initialize anchor
 | 
			
		||||
        @anchor = anchor
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										60
									
								
								lib/psych/nodes/document.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								lib/psych/nodes/document.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,60 @@
 | 
			
		|||
module Psych
 | 
			
		||||
  module Nodes
 | 
			
		||||
    ###
 | 
			
		||||
    # This represents a YAML Document.  This node must be a child of
 | 
			
		||||
    # Psych::Nodes::Stream.  A Psych::Nodes::Document must have one child,
 | 
			
		||||
    # and that child may be one of the following:
 | 
			
		||||
    #
 | 
			
		||||
    # * Psych::Nodes::Sequence
 | 
			
		||||
    # * Psych::Nodes::Mapping
 | 
			
		||||
    # * Psych::Nodes::Scalar
 | 
			
		||||
    class Document < Psych::Nodes::Node
 | 
			
		||||
      # The version of the YAML document
 | 
			
		||||
      attr_accessor :version
 | 
			
		||||
 | 
			
		||||
      # A list of tag directives for this document
 | 
			
		||||
      attr_accessor :tag_directives
 | 
			
		||||
 | 
			
		||||
      # Was this document implicitly created?
 | 
			
		||||
      attr_accessor :implicit
 | 
			
		||||
 | 
			
		||||
      # Is the end of the document implicit?
 | 
			
		||||
      attr_accessor :implicit_end
 | 
			
		||||
 | 
			
		||||
      ###
 | 
			
		||||
      # Create a new Psych::Nodes::Document object.
 | 
			
		||||
      #
 | 
			
		||||
      # +version+ is a list indicating the YAML version.
 | 
			
		||||
      # +tags_directives+ is a list of tag directive declarations
 | 
			
		||||
      # +implicit+ is a flag indicating whether the document will be implicitly
 | 
			
		||||
      # started.
 | 
			
		||||
      #
 | 
			
		||||
      # == Example:
 | 
			
		||||
      # This creates a YAML document object that represents a YAML 1.1 document
 | 
			
		||||
      # with one tag directive, and has an implicit start:
 | 
			
		||||
      #
 | 
			
		||||
      #   Psych::Nodes::Document.new(
 | 
			
		||||
      #     [1,1],
 | 
			
		||||
      #     [["!", "tag:tenderlovemaking.com,2009:"]],
 | 
			
		||||
      #     true
 | 
			
		||||
      #   )
 | 
			
		||||
      #
 | 
			
		||||
      # == See Also
 | 
			
		||||
      # See also Psych::Handler#start_document
 | 
			
		||||
      def initialize version = [], tag_directives = [], implicit = false
 | 
			
		||||
        super()
 | 
			
		||||
        @version        = version
 | 
			
		||||
        @tag_directives = tag_directives
 | 
			
		||||
        @implicit       = implicit
 | 
			
		||||
        @implicit_end   = true
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      ###
 | 
			
		||||
      # Returns the root node.  A Document may only have one root node:
 | 
			
		||||
      # http://yaml.org/spec/1.1/#id898031
 | 
			
		||||
      def root
 | 
			
		||||
        children.first
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										56
									
								
								lib/psych/nodes/mapping.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								lib/psych/nodes/mapping.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,56 @@
 | 
			
		|||
module Psych
 | 
			
		||||
  module Nodes
 | 
			
		||||
    ###
 | 
			
		||||
    # This class represents a {YAML Mapping}[http://yaml.org/spec/1.1/#mapping].
 | 
			
		||||
    #
 | 
			
		||||
    # A Psych::Nodes::Mapping node may have 0 or more children, but must have
 | 
			
		||||
    # an even number of children.  Here are the valid children a
 | 
			
		||||
    # Psych::Nodes::Mapping node may have:
 | 
			
		||||
    #
 | 
			
		||||
    # * Psych::Nodes::Sequence
 | 
			
		||||
    # * Psych::Nodes::Mapping
 | 
			
		||||
    # * Psych::Nodes::Scalar
 | 
			
		||||
    # * Psych::Nodes::Alias
 | 
			
		||||
    class Mapping < Psych::Nodes::Node
 | 
			
		||||
      # Any Map Style
 | 
			
		||||
      ANY   = 0
 | 
			
		||||
 | 
			
		||||
      # Block Map Style
 | 
			
		||||
      BLOCK = 1
 | 
			
		||||
 | 
			
		||||
      # Flow Map Style
 | 
			
		||||
      FLOW  = 2
 | 
			
		||||
 | 
			
		||||
      # The optional anchor for this mapping
 | 
			
		||||
      attr_accessor :anchor
 | 
			
		||||
 | 
			
		||||
      # The optional tag for this mapping
 | 
			
		||||
      attr_accessor :tag
 | 
			
		||||
 | 
			
		||||
      # Is this an implicit mapping?
 | 
			
		||||
      attr_accessor :implicit
 | 
			
		||||
 | 
			
		||||
      # The style of this mapping
 | 
			
		||||
      attr_accessor :style
 | 
			
		||||
 | 
			
		||||
      ###
 | 
			
		||||
      # Create a new Psych::Nodes::Mapping object.
 | 
			
		||||
      #
 | 
			
		||||
      # +anchor+ is the anchor associated with the map or +nil+.
 | 
			
		||||
      # +tag+ is the tag associated with the map or +nil+.
 | 
			
		||||
      # +implicit+ is a boolean indicating whether or not the map was implicitly
 | 
			
		||||
      # started.
 | 
			
		||||
      # +style+ is an integer indicating the mapping style.
 | 
			
		||||
      #
 | 
			
		||||
      # == See Also
 | 
			
		||||
      # See also Psych::Handler#start_mapping
 | 
			
		||||
      def initialize anchor = nil, tag = nil, implicit = true, style = BLOCK
 | 
			
		||||
        super()
 | 
			
		||||
        @anchor   = anchor
 | 
			
		||||
        @tag      = tag
 | 
			
		||||
        @implicit = implicit
 | 
			
		||||
        @style    = style
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										40
									
								
								lib/psych/nodes/node.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								lib/psych/nodes/node.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,40 @@
 | 
			
		|||
require 'stringio'
 | 
			
		||||
 | 
			
		||||
module Psych
 | 
			
		||||
  module Nodes
 | 
			
		||||
    ###
 | 
			
		||||
    # The base class for any Node in a YAML parse tree.  This class should
 | 
			
		||||
    # never be instantiated.
 | 
			
		||||
    class Node
 | 
			
		||||
      # The children of this node
 | 
			
		||||
      attr_reader :children
 | 
			
		||||
 | 
			
		||||
      # An associated tag
 | 
			
		||||
      attr_reader :tag
 | 
			
		||||
 | 
			
		||||
      # Create a new Psych::Nodes::Node
 | 
			
		||||
      def initialize
 | 
			
		||||
        @children = []
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      ###
 | 
			
		||||
      # Convert this node to Ruby.
 | 
			
		||||
      #
 | 
			
		||||
      # See also Psych::Visitors::ToRuby
 | 
			
		||||
      def to_ruby
 | 
			
		||||
        Visitors::ToRuby.new.accept self
 | 
			
		||||
      end
 | 
			
		||||
      alias :transform :to_ruby
 | 
			
		||||
 | 
			
		||||
      ###
 | 
			
		||||
      # Convert this node to YAML.
 | 
			
		||||
      #
 | 
			
		||||
      # See also Psych::Visitors::Emitter
 | 
			
		||||
      def to_yaml
 | 
			
		||||
        io = StringIO.new
 | 
			
		||||
        Visitors::Emitter.new(io).accept self
 | 
			
		||||
        io.string
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										67
									
								
								lib/psych/nodes/scalar.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								lib/psych/nodes/scalar.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,67 @@
 | 
			
		|||
module Psych
 | 
			
		||||
  module Nodes
 | 
			
		||||
    ###
 | 
			
		||||
    # This class represents a {YAML Scalar}[http://yaml.org/spec/1.1/#id858081].
 | 
			
		||||
    #
 | 
			
		||||
    # This node type is a terminal node and should not have any children.
 | 
			
		||||
    class Scalar < Psych::Nodes::Node
 | 
			
		||||
      # Any style scalar, the emitter chooses
 | 
			
		||||
      ANY           = 0
 | 
			
		||||
 | 
			
		||||
      # Plain scalar style
 | 
			
		||||
      PLAIN         = 1
 | 
			
		||||
 | 
			
		||||
      # Single quoted style
 | 
			
		||||
      SINGLE_QUOTED = 2
 | 
			
		||||
 | 
			
		||||
      # Double quoted style
 | 
			
		||||
      DOUBLE_QUOTED = 3
 | 
			
		||||
 | 
			
		||||
      # Literal style
 | 
			
		||||
      LITERAL       = 4
 | 
			
		||||
 | 
			
		||||
      # Folded style
 | 
			
		||||
      FOLDED        = 5
 | 
			
		||||
 | 
			
		||||
      # The scalar value
 | 
			
		||||
      attr_accessor :value
 | 
			
		||||
 | 
			
		||||
      # The anchor value (if there is one)
 | 
			
		||||
      attr_accessor :anchor
 | 
			
		||||
 | 
			
		||||
      # The tag value (if there is one)
 | 
			
		||||
      attr_accessor :tag
 | 
			
		||||
 | 
			
		||||
      # Is this a plain scalar?
 | 
			
		||||
      attr_accessor :plain
 | 
			
		||||
 | 
			
		||||
      # Is this scalar quoted?
 | 
			
		||||
      attr_accessor :quoted
 | 
			
		||||
 | 
			
		||||
      # The style of this scalar
 | 
			
		||||
      attr_accessor :style
 | 
			
		||||
 | 
			
		||||
      ###
 | 
			
		||||
      # Create a new Psych::Nodes::Scalar object.
 | 
			
		||||
      #
 | 
			
		||||
      # +value+ is the string value of the scalar
 | 
			
		||||
      # +anchor+ is an associated anchor or nil
 | 
			
		||||
      # +tag+ is an associated tag or nil
 | 
			
		||||
      # +plain+ is a boolean value
 | 
			
		||||
      # +quoted+ is a boolean value
 | 
			
		||||
      # +style+ is an integer idicating the string style
 | 
			
		||||
      #
 | 
			
		||||
      # == See Also
 | 
			
		||||
      #
 | 
			
		||||
      # See also Psych::Handler#scalar
 | 
			
		||||
      def initialize value, anchor = nil, tag = nil, plain = true, quoted = false, style = ANY
 | 
			
		||||
        @value  = value
 | 
			
		||||
        @anchor = anchor
 | 
			
		||||
        @tag    = tag
 | 
			
		||||
        @plain  = plain
 | 
			
		||||
        @quoted = quoted
 | 
			
		||||
        @style  = style
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										81
									
								
								lib/psych/nodes/sequence.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								lib/psych/nodes/sequence.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,81 @@
 | 
			
		|||
module Psych
 | 
			
		||||
  module Nodes
 | 
			
		||||
    ###
 | 
			
		||||
    # This class represents a
 | 
			
		||||
    # {YAML sequence}[http://yaml.org/spec/1.1/#sequence/syntax].
 | 
			
		||||
    #
 | 
			
		||||
    # A YAML sequence is basically a list, and looks like this:
 | 
			
		||||
    #
 | 
			
		||||
    #   %YAML 1.1
 | 
			
		||||
    #   ---
 | 
			
		||||
    #   - I am
 | 
			
		||||
    #   - a Sequence
 | 
			
		||||
    #
 | 
			
		||||
    # A YAML sequence may have an anchor like this:
 | 
			
		||||
    #
 | 
			
		||||
    #   %YAML 1.1
 | 
			
		||||
    #   ---
 | 
			
		||||
    #   &A [
 | 
			
		||||
    #     "This sequence",
 | 
			
		||||
    #     "has an anchor"
 | 
			
		||||
    #   ]
 | 
			
		||||
    #
 | 
			
		||||
    # A YAML sequence may also have a tag like this:
 | 
			
		||||
    #
 | 
			
		||||
    #   %YAML 1.1
 | 
			
		||||
    #   ---
 | 
			
		||||
    #   !!seq [
 | 
			
		||||
    #     "This sequence",
 | 
			
		||||
    #     "has a tag"
 | 
			
		||||
    #   ]
 | 
			
		||||
    #
 | 
			
		||||
    # This class represents a sequence in a YAML document.  A
 | 
			
		||||
    # Psych::Nodes::Sequence node may have 0 or more children.  Valid children
 | 
			
		||||
    # for this node are:
 | 
			
		||||
    #
 | 
			
		||||
    # * Psych::Nodes::Sequence
 | 
			
		||||
    # * Psych::Nodes::Mapping
 | 
			
		||||
    # * Psych::Nodes::Scalar
 | 
			
		||||
    # * Psych::Nodes::Alias
 | 
			
		||||
    class Sequence < Psych::Nodes::Node
 | 
			
		||||
      # Any Styles, emitter chooses
 | 
			
		||||
      ANY   = 0
 | 
			
		||||
 | 
			
		||||
      # Block style sequence
 | 
			
		||||
      BLOCK = 1
 | 
			
		||||
 | 
			
		||||
      # Flow style sequence
 | 
			
		||||
      FLOW  = 2
 | 
			
		||||
 | 
			
		||||
      # The anchor for this sequence (if any)
 | 
			
		||||
      attr_accessor :anchor
 | 
			
		||||
 | 
			
		||||
      # The tag name for this sequence (if any)
 | 
			
		||||
      attr_accessor :tag
 | 
			
		||||
 | 
			
		||||
      # Is this sequence started implicitly?
 | 
			
		||||
      attr_accessor :implicit
 | 
			
		||||
 | 
			
		||||
      # The sequece style used
 | 
			
		||||
      attr_accessor :style
 | 
			
		||||
 | 
			
		||||
      ###
 | 
			
		||||
      # Create a new object representing a YAML sequence.
 | 
			
		||||
      #
 | 
			
		||||
      # +anchor+ is the anchor associated with the sequence or nil.
 | 
			
		||||
      # +tag+ is the tag associated with the sequence or nil.
 | 
			
		||||
      # +implicit+ a boolean indicating whether or not the sequence was
 | 
			
		||||
      # implicitly started.
 | 
			
		||||
      # +style+ is an integer indicating the list style.
 | 
			
		||||
      #
 | 
			
		||||
      # See Psych::Handler#start_sequence
 | 
			
		||||
      def initialize anchor = nil, tag = nil, implicit = true, style = BLOCK
 | 
			
		||||
        super()
 | 
			
		||||
        @anchor   = anchor
 | 
			
		||||
        @tag      = tag
 | 
			
		||||
        @implicit = implicit
 | 
			
		||||
        @style    = style
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										37
									
								
								lib/psych/nodes/stream.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								lib/psych/nodes/stream.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,37 @@
 | 
			
		|||
module Psych
 | 
			
		||||
  module Nodes
 | 
			
		||||
    ###
 | 
			
		||||
    # Represents a YAML stream.  This is the root node for any YAML parse
 | 
			
		||||
    # tree.  This node must have one or more child nodes.  The only valid
 | 
			
		||||
    # child node for a Psych::Nodes::Stream node is Psych::Nodes::Document.
 | 
			
		||||
    class Stream < Psych::Nodes::Node
 | 
			
		||||
 | 
			
		||||
      # Encodings supported by Psych (and libyaml)
 | 
			
		||||
 | 
			
		||||
      # Any encoding
 | 
			
		||||
      ANY     = Psych::Parser::ANY
 | 
			
		||||
 | 
			
		||||
      # UTF-8 encoding
 | 
			
		||||
      UTF8    = Psych::Parser::UTF8
 | 
			
		||||
 | 
			
		||||
      # UTF-16LE encoding
 | 
			
		||||
      UTF16LE = Psych::Parser::UTF16LE
 | 
			
		||||
 | 
			
		||||
      # UTF-16BE encoding
 | 
			
		||||
      UTF16BE = Psych::Parser::UTF16BE
 | 
			
		||||
 | 
			
		||||
      # The encoding used for this stream
 | 
			
		||||
      attr_reader :encoding
 | 
			
		||||
 | 
			
		||||
      ###
 | 
			
		||||
      # Create a new Psych::Nodes::Stream node with an +encoding+ that
 | 
			
		||||
      # defaults to Psych::Nodes::Stream::UTF8.
 | 
			
		||||
      #
 | 
			
		||||
      # See also Psych::Handler#start_stream
 | 
			
		||||
      def initialize encoding = UTF8
 | 
			
		||||
        super()
 | 
			
		||||
        @encoding = encoding
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										4
									
								
								lib/psych/omap.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								lib/psych/omap.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
module Psych
 | 
			
		||||
  class Omap < ::Hash
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										44
									
								
								lib/psych/parser.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								lib/psych/parser.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,44 @@
 | 
			
		|||
module Psych
 | 
			
		||||
  ###
 | 
			
		||||
  # YAML event parser class.  This class parses a YAML document and calls
 | 
			
		||||
  # events on the handler that is passed to the constructor.  The events can
 | 
			
		||||
  # be used for things such as constructing a YAML AST or deserializing YAML
 | 
			
		||||
  # documents.  It can even be fed back to Psych::Emitter to emit the same
 | 
			
		||||
  # document that was parsed.
 | 
			
		||||
  #
 | 
			
		||||
  # See Psych::Handler for documentation on the events that Psych::Parser emits.
 | 
			
		||||
  #
 | 
			
		||||
  # Here is an example that prints out ever scalar found in a YAML document:
 | 
			
		||||
  #
 | 
			
		||||
  #   # Handler for detecting scalar values
 | 
			
		||||
  #   class ScalarHandler < Psych::Handler
 | 
			
		||||
  #     def scalar value, anchor, tag, plain, quoted, style
 | 
			
		||||
  #       puts value
 | 
			
		||||
  #     end
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  #   parser = Psych::Parser.new(ScalarHandler.new)
 | 
			
		||||
  #   parser.parse(yaml_document)
 | 
			
		||||
  #
 | 
			
		||||
  # Here is an example that feeds the parser back in to Psych::Emitter.  The
 | 
			
		||||
  # YAML document is read from STDIN and written back out to STDERR:
 | 
			
		||||
  #
 | 
			
		||||
  #   parser = Psych::Parser.new(Psych::Emitter.new($stderr))
 | 
			
		||||
  #   parser.parse($stdin)
 | 
			
		||||
  #
 | 
			
		||||
  # Psych uses Psych::Parser in combination with Psych::TreeBuilder to
 | 
			
		||||
  # construct an AST of the parsed YAML document.
 | 
			
		||||
 | 
			
		||||
  class Parser
 | 
			
		||||
    # The handler on which events will be called
 | 
			
		||||
    attr_accessor :handler
 | 
			
		||||
 | 
			
		||||
    ###
 | 
			
		||||
    # Creates a new Psych::Parser instance with +handler+.  YAML events will
 | 
			
		||||
    # be called on +handler+.  See Psych::Parser for more details.
 | 
			
		||||
 | 
			
		||||
    def initialize handler = Handler.new
 | 
			
		||||
      @handler = handler
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										90
									
								
								lib/psych/scalar_scanner.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								lib/psych/scalar_scanner.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,90 @@
 | 
			
		|||
require 'strscan'
 | 
			
		||||
 | 
			
		||||
module Psych
 | 
			
		||||
  ###
 | 
			
		||||
  # Scan scalars for built in types
 | 
			
		||||
  class ScalarScanner
 | 
			
		||||
    # Taken from http://yaml.org/type/timestamp.html
 | 
			
		||||
    TIME = /^\d{4}-\d{1,2}-\d{1,2}([Tt]|\s+)\d{1,2}:\d\d:\d\d(\.\d*)?(\s*Z|[-+]\d{1,2}(:\d\d)?)?/
 | 
			
		||||
 | 
			
		||||
    # Create a new scanner
 | 
			
		||||
    def initialize
 | 
			
		||||
      @string_cache = {}
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Tokenize +string+ returning the ruby object
 | 
			
		||||
    def tokenize string
 | 
			
		||||
      return nil if string.empty?
 | 
			
		||||
      return string if @string_cache.key?(string)
 | 
			
		||||
 | 
			
		||||
      case string
 | 
			
		||||
      when /^[A-Za-z~]/
 | 
			
		||||
        if string.length > 5
 | 
			
		||||
          @string_cache[string] = true
 | 
			
		||||
          return string
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        case string
 | 
			
		||||
        when /^[^ytonf~]/i
 | 
			
		||||
          @string_cache[string] = true
 | 
			
		||||
          string
 | 
			
		||||
        when '~', /^null$/i
 | 
			
		||||
          nil
 | 
			
		||||
        when /^(yes|true|on)$/i
 | 
			
		||||
          true
 | 
			
		||||
        when /^(no|false|off)$/i
 | 
			
		||||
          false
 | 
			
		||||
        else
 | 
			
		||||
          @string_cache[string] = true
 | 
			
		||||
          string
 | 
			
		||||
        end
 | 
			
		||||
      when TIME
 | 
			
		||||
        date, time = *(string.split(/[ tT]/, 2))
 | 
			
		||||
        (yy, m, dd) = date.split('-').map { |x| x.to_i }
 | 
			
		||||
        md = time.match(/(\d+:\d+:\d+)(\.\d*)?\s*(Z|[-+]\d+(:\d\d)?)?/)
 | 
			
		||||
 | 
			
		||||
        (hh, mm, ss) = md[1].split(':').map { |x| x.to_i }
 | 
			
		||||
        us = (md[2] ? Rational(md[2].sub(/^\./, '0.')) : 0) * 1000000
 | 
			
		||||
 | 
			
		||||
        time = Time.utc(yy, m, dd, hh, mm, ss, us)
 | 
			
		||||
 | 
			
		||||
        return time if 'Z' == md[3]
 | 
			
		||||
 | 
			
		||||
        tz = md[3] ? Integer(md[3].split(':').first.sub(/([-+])0/, '\1')) : 0
 | 
			
		||||
        Time.at((time - (tz * 3600)).to_i, us)
 | 
			
		||||
      when /^\d{4}-\d{1,2}-\d{1,2}$/
 | 
			
		||||
        require 'date'
 | 
			
		||||
        Date.strptime(string, '%Y-%m-%d')
 | 
			
		||||
      when /^\.inf$/i
 | 
			
		||||
        1 / 0.0
 | 
			
		||||
      when /^-\.inf$/i
 | 
			
		||||
        -1 / 0.0
 | 
			
		||||
      when /^\.nan$/i
 | 
			
		||||
        0.0 / 0.0
 | 
			
		||||
      when /^:./
 | 
			
		||||
        if string =~ /^:(["'])(.*)\1/
 | 
			
		||||
          $2.sub(/^:/, '').to_sym
 | 
			
		||||
        else
 | 
			
		||||
          string.sub(/^:/, '').to_sym
 | 
			
		||||
        end
 | 
			
		||||
      when /^[-+]?[1-9][0-9_]*(:[0-5]?[0-9])+$/
 | 
			
		||||
        i = 0
 | 
			
		||||
        string.split(':').each_with_index do |n,e|
 | 
			
		||||
          i += (n.to_i * 60 ** (e - 2).abs)
 | 
			
		||||
        end
 | 
			
		||||
        i
 | 
			
		||||
      when /^[-+]?[0-9][0-9_]*(:[0-5]?[0-9])+\.[0-9_]*$/
 | 
			
		||||
        i = 0
 | 
			
		||||
        string.split(':').each_with_index do |n,e|
 | 
			
		||||
          i += (n.to_f * 60 ** (e - 2).abs)
 | 
			
		||||
        end
 | 
			
		||||
        i
 | 
			
		||||
      else
 | 
			
		||||
        return Integer(string.gsub(/[,_]/, '')) rescue ArgumentError
 | 
			
		||||
        return Float(string.gsub(/[,_]/, '')) rescue ArgumentError
 | 
			
		||||
        @string_cache[string] = true
 | 
			
		||||
        string
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										4
									
								
								lib/psych/set.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								lib/psych/set.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
module Psych
 | 
			
		||||
  class Set < ::Hash
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										89
									
								
								lib/psych/tree_builder.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								lib/psych/tree_builder.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,89 @@
 | 
			
		|||
require 'psych/handler'
 | 
			
		||||
 | 
			
		||||
module Psych
 | 
			
		||||
  ###
 | 
			
		||||
  # This class works in conjunction with Psych::Parser to build an in-memory
 | 
			
		||||
  # parse tree tree that represents a YAML document.
 | 
			
		||||
  #
 | 
			
		||||
  # == Example
 | 
			
		||||
  #
 | 
			
		||||
  #   parser = Psych::Parser.new Psych::TreeBuilder.new
 | 
			
		||||
  #   parser.parse('--- foo')
 | 
			
		||||
  #   tree = parser.handler.root
 | 
			
		||||
  #
 | 
			
		||||
  # See Psych::Handler for documentation on the event methods used in this
 | 
			
		||||
  # class.
 | 
			
		||||
  class TreeBuilder < Psych::Handler
 | 
			
		||||
    # Create a new TreeBuilder instance
 | 
			
		||||
    def initialize
 | 
			
		||||
      @stack = []
 | 
			
		||||
      @last  = nil
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns the root node for the built tree
 | 
			
		||||
    def root
 | 
			
		||||
      @stack.first
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    %w{
 | 
			
		||||
      Sequence
 | 
			
		||||
      Mapping
 | 
			
		||||
    }.each do |node|
 | 
			
		||||
      class_eval %{
 | 
			
		||||
        def start_#{node.downcase}(anchor, tag, implicit, style)
 | 
			
		||||
          n = Nodes::#{node}.new(anchor, tag, implicit, style)
 | 
			
		||||
          @last.children << n
 | 
			
		||||
          push n
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def end_#{node.downcase}
 | 
			
		||||
          pop
 | 
			
		||||
        end
 | 
			
		||||
      }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    ###
 | 
			
		||||
    # Handles start_document events with +version+, +tag_directives+,
 | 
			
		||||
    # and +implicit+ styling.
 | 
			
		||||
    #
 | 
			
		||||
    # See Psych::Handler#start_document
 | 
			
		||||
    def start_document version, tag_directives, implicit
 | 
			
		||||
      n = Nodes::Document.new(version, tag_directives, implicit)
 | 
			
		||||
      @last.children << n
 | 
			
		||||
      push n
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    ###
 | 
			
		||||
    # Handles end_document events with +version+, +tag_directives+,
 | 
			
		||||
    # and +implicit+ styling.
 | 
			
		||||
    #
 | 
			
		||||
    # See Psych::Handler#start_document
 | 
			
		||||
    def end_document implicit_end
 | 
			
		||||
      @last.implicit_end = implicit_end
 | 
			
		||||
      pop
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def start_stream encoding
 | 
			
		||||
      push Nodes::Stream.new(encoding)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def scalar value, anchor, tag, plain, quoted, style
 | 
			
		||||
      @last.children << Nodes::Scalar.new(value,anchor,tag,plain,quoted,style)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def alias anchor
 | 
			
		||||
      @last.children << Nodes::Alias.new(anchor)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    private
 | 
			
		||||
    def push value
 | 
			
		||||
      @stack.push value
 | 
			
		||||
      @last = value
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def pop
 | 
			
		||||
      @stack.pop
 | 
			
		||||
      @last = @stack.last
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										5
									
								
								lib/psych/visitors.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								lib/psych/visitors.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
require 'psych/visitors/visitor'
 | 
			
		||||
require 'psych/visitors/to_ruby'
 | 
			
		||||
require 'psych/visitors/emitter'
 | 
			
		||||
require 'psych/visitors/yaml_tree'
 | 
			
		||||
require 'psych/visitors/json_tree'
 | 
			
		||||
							
								
								
									
										41
									
								
								lib/psych/visitors/emitter.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								lib/psych/visitors/emitter.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,41 @@
 | 
			
		|||
module Psych
 | 
			
		||||
  module Visitors
 | 
			
		||||
    class Emitter < Psych::Visitors::Visitor
 | 
			
		||||
      def initialize io
 | 
			
		||||
        @handler = Psych::Emitter.new io
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def visit_Psych_Nodes_Stream o
 | 
			
		||||
        @handler.start_stream o.encoding
 | 
			
		||||
        o.children.each { |c| accept c }
 | 
			
		||||
        @handler.end_stream
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def visit_Psych_Nodes_Document o
 | 
			
		||||
        @handler.start_document o.version, o.tag_directives, o.implicit
 | 
			
		||||
        o.children.each { |c| accept c }
 | 
			
		||||
        @handler.end_document o.implicit_end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def visit_Psych_Nodes_Scalar o
 | 
			
		||||
        @handler.scalar o.value, o.anchor, o.tag, o.plain, o.quoted, o.style
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def visit_Psych_Nodes_Sequence o
 | 
			
		||||
        @handler.start_sequence o.anchor, o.tag, o.implicit, o.style
 | 
			
		||||
        o.children.each { |c| accept c }
 | 
			
		||||
        @handler.end_sequence
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def visit_Psych_Nodes_Mapping o
 | 
			
		||||
        @handler.start_mapping o.anchor, o.tag, o.implicit, o.style
 | 
			
		||||
        o.children.each { |c| accept c }
 | 
			
		||||
        @handler.end_mapping
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def visit_Psych_Nodes_Alias o
 | 
			
		||||
        @handler.alias o.anchor
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										37
									
								
								lib/psych/visitors/json_tree.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								lib/psych/visitors/json_tree.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,37 @@
 | 
			
		|||
module Psych
 | 
			
		||||
  module Visitors
 | 
			
		||||
    class JSONTree < YAMLTree
 | 
			
		||||
      def visit_Symbol o
 | 
			
		||||
        append create_scalar o.to_s
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def visit_NilClass o
 | 
			
		||||
        scalar = Nodes::Scalar.new(
 | 
			
		||||
          'null', nil, nil, true, false, Nodes::Scalar::PLAIN)
 | 
			
		||||
        append scalar
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      private
 | 
			
		||||
      def create_document
 | 
			
		||||
        doc = super
 | 
			
		||||
        doc.implicit     = true
 | 
			
		||||
        doc.implicit_end = true
 | 
			
		||||
        doc
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def create_mapping
 | 
			
		||||
        map = super
 | 
			
		||||
        map.style = Nodes::Mapping::FLOW
 | 
			
		||||
        map
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def create_scalar value, anchor = nil, tag = nil, plain = false, quoted = true, style = Nodes::Scalar::ANY
 | 
			
		||||
        super(value, anchor, tag, false, true, style)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def create_sequence anchor = nil, tag = nil, implicit = true, style = Nodes::Sequence::FLOW
 | 
			
		||||
        super
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										252
									
								
								lib/psych/visitors/to_ruby.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										252
									
								
								lib/psych/visitors/to_ruby.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,252 @@
 | 
			
		|||
require 'psych/scalar_scanner'
 | 
			
		||||
 | 
			
		||||
module Psych
 | 
			
		||||
  module Visitors
 | 
			
		||||
    ###
 | 
			
		||||
    # This class walks a YAML AST, converting each node to ruby
 | 
			
		||||
    class ToRuby < Psych::Visitors::Visitor
 | 
			
		||||
      def initialize
 | 
			
		||||
        super
 | 
			
		||||
        @st = {}
 | 
			
		||||
        @ss = ScalarScanner.new
 | 
			
		||||
        @domain_types = Psych.domain_types
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def accept target
 | 
			
		||||
        result = super
 | 
			
		||||
        return result if @domain_types.empty? || !target.tag
 | 
			
		||||
 | 
			
		||||
        short_name = target.tag.sub(/^!/, '').split('/', 2).last
 | 
			
		||||
        if Psych.domain_types.key? short_name
 | 
			
		||||
          url, block = Psych.domain_types[short_name]
 | 
			
		||||
          return block.call "#{url}:#{short_name}", result
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        result
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def visit_Psych_Nodes_Scalar o
 | 
			
		||||
        @st[o.anchor] = o.value if o.anchor
 | 
			
		||||
 | 
			
		||||
        if klass = Psych.load_tags[o.tag]
 | 
			
		||||
          instance = klass.allocate
 | 
			
		||||
 | 
			
		||||
          if instance.respond_to?(:init_with)
 | 
			
		||||
            coder = Psych::Coder.new(o.tag)
 | 
			
		||||
            coder.scalar = o.value
 | 
			
		||||
            instance.init_with coder
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          return instance
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        return o.value if o.quoted
 | 
			
		||||
        return @ss.tokenize(o.value) unless o.tag
 | 
			
		||||
 | 
			
		||||
        case o.tag
 | 
			
		||||
        when '!binary', 'tag:yaml.org,2002:binary'
 | 
			
		||||
          o.value.unpack('m').first
 | 
			
		||||
        when '!str', 'tag:yaml.org,2002:str'
 | 
			
		||||
          o.value
 | 
			
		||||
        when "!ruby/object:Complex"
 | 
			
		||||
          Complex(o.value)
 | 
			
		||||
        when "!ruby/object:Rational"
 | 
			
		||||
          Rational(o.value)
 | 
			
		||||
        when "tag:yaml.org,2002:float", "!float"
 | 
			
		||||
          Float(@ss.tokenize(o.value))
 | 
			
		||||
        when "!ruby/regexp"
 | 
			
		||||
          o.value =~ /^\/(.*)\/([mix]*)$/
 | 
			
		||||
          source  = $1
 | 
			
		||||
          options = 0
 | 
			
		||||
          lang    = nil
 | 
			
		||||
          ($2 || '').split('').each do |option|
 | 
			
		||||
            case option
 | 
			
		||||
            when 'x' then options |= Regexp::EXTENDED
 | 
			
		||||
            when 'i' then options |= Regexp::IGNORECASE
 | 
			
		||||
            when 'm' then options |= Regexp::MULTILINE
 | 
			
		||||
            else lang = option
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
          Regexp.new(*[source, options, lang].compact)
 | 
			
		||||
        when "!ruby/range"
 | 
			
		||||
          args = o.value.split(/([.]{2,3})/, 2).map { |s|
 | 
			
		||||
            accept Nodes::Scalar.new(s)
 | 
			
		||||
          }
 | 
			
		||||
          args.push(args.delete_at(1) == '...')
 | 
			
		||||
          Range.new(*args)
 | 
			
		||||
        when /^!ruby\/sym(bol)?:?(.*)?$/
 | 
			
		||||
          o.value.to_sym
 | 
			
		||||
        else
 | 
			
		||||
          @ss.tokenize o.value
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def visit_Psych_Nodes_Sequence o
 | 
			
		||||
        if klass = Psych.load_tags[o.tag]
 | 
			
		||||
          instance = klass.allocate
 | 
			
		||||
 | 
			
		||||
          if instance.respond_to?(:init_with)
 | 
			
		||||
            coder = Psych::Coder.new(o.tag)
 | 
			
		||||
            coder.seq = o.children.map { |c| accept c }
 | 
			
		||||
            instance.init_with coder
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          return instance
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        case o.tag
 | 
			
		||||
        when '!omap', 'tag:yaml.org,2002:omap'
 | 
			
		||||
          map = Psych::Omap.new
 | 
			
		||||
          @st[o.anchor] = map if o.anchor
 | 
			
		||||
          o.children.each { |a|
 | 
			
		||||
            map[accept(a.children.first)] = accept a.children.last
 | 
			
		||||
          }
 | 
			
		||||
          map
 | 
			
		||||
        else
 | 
			
		||||
          list = []
 | 
			
		||||
          @st[o.anchor] = list if o.anchor
 | 
			
		||||
          o.children.each { |c| list.push accept c }
 | 
			
		||||
          list
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def visit_Psych_Nodes_Mapping o
 | 
			
		||||
        return revive(Psych.load_tags[o.tag], o) if Psych.load_tags[o.tag]
 | 
			
		||||
 | 
			
		||||
        case o.tag
 | 
			
		||||
        when '!str', 'tag:yaml.org,2002:str'
 | 
			
		||||
          members = Hash[*o.children.map { |c| accept c }]
 | 
			
		||||
          string = members.delete 'str'
 | 
			
		||||
          init_with(string, members.map { |k,v| [k.to_s.sub(/^@/, ''),v] }, o)
 | 
			
		||||
        when /^!ruby\/struct:?(.*)?$/
 | 
			
		||||
          klass = resolve_class($1)
 | 
			
		||||
 | 
			
		||||
          if klass
 | 
			
		||||
            s = klass.allocate
 | 
			
		||||
            @st[o.anchor] = s if o.anchor
 | 
			
		||||
 | 
			
		||||
            members = {}
 | 
			
		||||
            struct_members = s.members.map { |x| x.to_sym }
 | 
			
		||||
            o.children.each_slice(2) do |k,v|
 | 
			
		||||
              member = accept(k)
 | 
			
		||||
              value  = accept(v)
 | 
			
		||||
              if struct_members.include?(member.to_sym)
 | 
			
		||||
                s.send("#{member}=", value)
 | 
			
		||||
              else
 | 
			
		||||
                members[member.to_s.sub(/^@/, '')] = value
 | 
			
		||||
              end
 | 
			
		||||
            end
 | 
			
		||||
            init_with(s, members, o)
 | 
			
		||||
          else
 | 
			
		||||
            members = o.children.map { |c| accept c }
 | 
			
		||||
            h = Hash[*members]
 | 
			
		||||
            Struct.new(*h.map { |k,v| k.to_sym }).new(*h.map { |k,v| v })
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
        when '!ruby/range'
 | 
			
		||||
          h = Hash[*o.children.map { |c| accept c }]
 | 
			
		||||
          Range.new(h['begin'], h['end'], h['excl'])
 | 
			
		||||
 | 
			
		||||
        when /^!ruby\/exception:?(.*)?$/
 | 
			
		||||
          h = Hash[*o.children.map { |c| accept c }]
 | 
			
		||||
 | 
			
		||||
          e = build_exception((resolve_class($1) || Exception),
 | 
			
		||||
                              h.delete('message'))
 | 
			
		||||
          init_with(e, h, o)
 | 
			
		||||
 | 
			
		||||
        when '!set', 'tag:yaml.org,2002:set'
 | 
			
		||||
          set = Psych::Set.new
 | 
			
		||||
          @st[o.anchor] = set if o.anchor
 | 
			
		||||
          o.children.each_slice(2) do |k,v|
 | 
			
		||||
            set[accept(k)] = accept(v)
 | 
			
		||||
          end
 | 
			
		||||
          set
 | 
			
		||||
 | 
			
		||||
        when '!ruby/object:Complex'
 | 
			
		||||
          h = Hash[*o.children.map { |c| accept c }]
 | 
			
		||||
          Complex(h['real'], h['image'])
 | 
			
		||||
 | 
			
		||||
        when '!ruby/object:Rational'
 | 
			
		||||
          h = Hash[*o.children.map { |c| accept c }]
 | 
			
		||||
          Rational(h['numerator'], h['denominator'])
 | 
			
		||||
 | 
			
		||||
        when /^!ruby\/object:?(.*)?$/
 | 
			
		||||
          name = $1 || 'Object'
 | 
			
		||||
          obj = revive((resolve_class(name) || Object), o)
 | 
			
		||||
          @st[o.anchor] = obj if o.anchor
 | 
			
		||||
          obj
 | 
			
		||||
        else
 | 
			
		||||
          hash = {}
 | 
			
		||||
          @st[o.anchor] = hash if o.anchor
 | 
			
		||||
 | 
			
		||||
          o.children.each_slice(2) { |k,v|
 | 
			
		||||
            key = accept(k)
 | 
			
		||||
 | 
			
		||||
            if key == '<<' && Nodes::Alias === v
 | 
			
		||||
              # FIXME: remove this when "<<" syntax is deprecated
 | 
			
		||||
              if $VERBOSE
 | 
			
		||||
                where = caller.find { |x| x !~ /psych/ }
 | 
			
		||||
                warn where
 | 
			
		||||
                warn "\"<<: *#{v.anchor}\" is no longer supported, please switch to \"*#{v.anchor}\""
 | 
			
		||||
              end
 | 
			
		||||
              return accept(v)
 | 
			
		||||
            else
 | 
			
		||||
              hash[key] = accept(v)
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
          }
 | 
			
		||||
          hash
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def visit_Psych_Nodes_Document o
 | 
			
		||||
        accept o.root
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def visit_Psych_Nodes_Stream o
 | 
			
		||||
        o.children.map { |c| accept c }
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def visit_Psych_Nodes_Alias o
 | 
			
		||||
        @st[o.anchor]
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      private
 | 
			
		||||
      def revive klass, node
 | 
			
		||||
        s = klass.allocate
 | 
			
		||||
        h = Hash[*node.children.map { |c| accept c }]
 | 
			
		||||
        init_with(s, h, node)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def init_with o, h, node
 | 
			
		||||
        if o.respond_to?(:init_with)
 | 
			
		||||
          c = Psych::Coder.new(node.tag)
 | 
			
		||||
          c.map = h
 | 
			
		||||
          o.init_with c
 | 
			
		||||
        else
 | 
			
		||||
          h.each { |k,v| o.instance_variable_set(:"@#{k}", v) }
 | 
			
		||||
        end
 | 
			
		||||
        o
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Convert +klassname+ to a Class
 | 
			
		||||
      def resolve_class klassname
 | 
			
		||||
        return nil unless klassname and not klassname.empty?
 | 
			
		||||
 | 
			
		||||
        name    = klassname
 | 
			
		||||
        retried = false
 | 
			
		||||
 | 
			
		||||
        begin
 | 
			
		||||
          path2class(name)
 | 
			
		||||
        rescue ArgumentError => ex
 | 
			
		||||
          name    = "Struct::#{name}"
 | 
			
		||||
          unless retried
 | 
			
		||||
            retried = true
 | 
			
		||||
            retry
 | 
			
		||||
          end
 | 
			
		||||
          raise ex
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										18
									
								
								lib/psych/visitors/visitor.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								lib/psych/visitors/visitor.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,18 @@
 | 
			
		|||
module Psych
 | 
			
		||||
  module Visitors
 | 
			
		||||
    class Visitor
 | 
			
		||||
      def accept target
 | 
			
		||||
        case target
 | 
			
		||||
        when Psych::Nodes::Scalar   then visit_Psych_Nodes_Scalar target
 | 
			
		||||
        when Psych::Nodes::Mapping  then visit_Psych_Nodes_Mapping target
 | 
			
		||||
        when Psych::Nodes::Sequence then visit_Psych_Nodes_Sequence target
 | 
			
		||||
        when Psych::Nodes::Alias    then visit_Psych_Nodes_Alias target
 | 
			
		||||
        when Psych::Nodes::Document then visit_Psych_Nodes_Document target
 | 
			
		||||
        when Psych::Nodes::Stream   then visit_Psych_Nodes_Stream target
 | 
			
		||||
        else
 | 
			
		||||
          raise "Can't handle #{target}"
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										312
									
								
								lib/psych/visitors/yaml_tree.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										312
									
								
								lib/psych/visitors/yaml_tree.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,312 @@
 | 
			
		|||
module Psych
 | 
			
		||||
  module Visitors
 | 
			
		||||
    class YAMLTree < Psych::Visitors::Visitor
 | 
			
		||||
      attr_reader :tree
 | 
			
		||||
 | 
			
		||||
      def initialize options = {}
 | 
			
		||||
        super()
 | 
			
		||||
        @json  = options[:json]
 | 
			
		||||
        @tree  = Nodes::Stream.new
 | 
			
		||||
        @stack = []
 | 
			
		||||
        @st    = {}
 | 
			
		||||
        @ss    = ScalarScanner.new
 | 
			
		||||
 | 
			
		||||
        @dispatch_cache = Hash.new do |h,klass|
 | 
			
		||||
          method = "visit_#{(klass.name || '').split('::').join('_')}"
 | 
			
		||||
 | 
			
		||||
          method = respond_to?(method) ? method : h[klass.superclass]
 | 
			
		||||
 | 
			
		||||
          raise(TypeError, "Can't dump #{target.class}") unless method
 | 
			
		||||
 | 
			
		||||
          h[klass] = method
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def << object
 | 
			
		||||
        doc = create_document
 | 
			
		||||
        @stack << doc
 | 
			
		||||
        @tree.children << doc
 | 
			
		||||
        accept object
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def accept target
 | 
			
		||||
        # return any aliases we find
 | 
			
		||||
        if node = @st[target.object_id]
 | 
			
		||||
          node.anchor = target.object_id.to_s
 | 
			
		||||
          return append Nodes::Alias.new target.object_id.to_s
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        if target.respond_to?(:encode_with)
 | 
			
		||||
          dump_coder target
 | 
			
		||||
        else
 | 
			
		||||
          send(@dispatch_cache[target.class], target)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def visit_Psych_Omap o
 | 
			
		||||
        seq = Nodes::Sequence.new(nil, '!omap', false)
 | 
			
		||||
        register(o, seq)
 | 
			
		||||
 | 
			
		||||
        @stack.push append seq
 | 
			
		||||
        o.each { |k,v| visit_Hash k => v }
 | 
			
		||||
        @stack.pop
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def visit_Object o
 | 
			
		||||
        tag = Psych.dump_tags[o.class]
 | 
			
		||||
        unless tag
 | 
			
		||||
          klass = o.class == Object ? nil : o.class.name
 | 
			
		||||
          tag   = ['!ruby/object', klass].compact.join(':')
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        map = append Nodes::Mapping.new(nil, tag, false)
 | 
			
		||||
        register(o, map)
 | 
			
		||||
 | 
			
		||||
        @stack.push map
 | 
			
		||||
        dump_ivars(o, map)
 | 
			
		||||
        @stack.pop
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def visit_Struct o
 | 
			
		||||
        tag = ['!ruby/struct', o.class.name].compact.join(':')
 | 
			
		||||
 | 
			
		||||
        map = register(o, Nodes::Mapping.new(nil, tag, false))
 | 
			
		||||
 | 
			
		||||
        @stack.push append map
 | 
			
		||||
 | 
			
		||||
        o.members.each do |member|
 | 
			
		||||
          map.children <<  Nodes::Scalar.new("#{member}")
 | 
			
		||||
          accept o[member]
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        dump_ivars(o, map)
 | 
			
		||||
 | 
			
		||||
        @stack.pop
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def visit_Exception o
 | 
			
		||||
        tag = ['!ruby/exception', o.class.name].join ':'
 | 
			
		||||
 | 
			
		||||
        map = append Nodes::Mapping.new(nil, tag, false)
 | 
			
		||||
 | 
			
		||||
        @stack.push map
 | 
			
		||||
 | 
			
		||||
        {
 | 
			
		||||
          'message'   => private_iv_get(o, 'mesg'),
 | 
			
		||||
          'backtrace' => private_iv_get(o, 'backtrace'),
 | 
			
		||||
        }.each do |k,v|
 | 
			
		||||
          next unless v
 | 
			
		||||
          map.children << Nodes::Scalar.new(k)
 | 
			
		||||
          accept v
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        dump_ivars(o, map)
 | 
			
		||||
 | 
			
		||||
        @stack.pop
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def visit_Regexp o
 | 
			
		||||
        append Nodes::Scalar.new(o.inspect, nil, '!ruby/regexp', false)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def visit_Time o
 | 
			
		||||
        formatted = o.strftime("%Y-%m-%d %H:%M:%S")
 | 
			
		||||
        if o.utc?
 | 
			
		||||
          formatted += ".%06dZ" % [o.usec]
 | 
			
		||||
        else
 | 
			
		||||
          formatted += ".%06d %+.2d:00" % [o.usec, o.gmt_offset / 3600]
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        append Nodes::Scalar.new formatted
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def visit_Rational o
 | 
			
		||||
        map = append Nodes::Mapping.new(nil, '!ruby/object:Rational', false)
 | 
			
		||||
        [
 | 
			
		||||
          'denominator', o.denominator.to_s,
 | 
			
		||||
          'numerator', o.numerator.to_s
 | 
			
		||||
        ].each do |m|
 | 
			
		||||
          map.children << Nodes::Scalar.new(m)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def visit_Complex o
 | 
			
		||||
        map = append Nodes::Mapping.new(nil, '!ruby/object:Complex', false)
 | 
			
		||||
 | 
			
		||||
        ['real', o.real.to_s, 'image', o.imag.to_s].each do |m|
 | 
			
		||||
          map.children << Nodes::Scalar.new(m)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def visit_Integer o
 | 
			
		||||
        append Nodes::Scalar.new o.to_s
 | 
			
		||||
      end
 | 
			
		||||
      alias :visit_TrueClass :visit_Integer
 | 
			
		||||
      alias :visit_FalseClass :visit_Integer
 | 
			
		||||
      alias :visit_Date :visit_Integer
 | 
			
		||||
 | 
			
		||||
      def visit_Float o
 | 
			
		||||
        if o.nan?
 | 
			
		||||
          append Nodes::Scalar.new '.nan'
 | 
			
		||||
        elsif o.infinite?
 | 
			
		||||
          append Nodes::Scalar.new(o.infinite? > 0 ? '.inf' : '-.inf')
 | 
			
		||||
        else
 | 
			
		||||
          append Nodes::Scalar.new o.to_s
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def visit_String o
 | 
			
		||||
        plain = false
 | 
			
		||||
        quote = false
 | 
			
		||||
 | 
			
		||||
        if o.index("\x00") || o.count("^ -~\t\r\n").fdiv(o.length) > 0.3
 | 
			
		||||
          str   = [o].pack('m').chomp
 | 
			
		||||
          tag   = '!binary'
 | 
			
		||||
        else
 | 
			
		||||
          str   = o
 | 
			
		||||
          tag   = nil
 | 
			
		||||
          quote = !(String === @ss.tokenize(o))
 | 
			
		||||
          plain = !quote
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        ivars = o.respond_to?(:to_yaml_properties) ?
 | 
			
		||||
          o.to_yaml_properties :
 | 
			
		||||
          o.instance_variables
 | 
			
		||||
 | 
			
		||||
        scalar = create_scalar str, nil, tag, plain, quote
 | 
			
		||||
 | 
			
		||||
        if ivars.empty?
 | 
			
		||||
          append scalar
 | 
			
		||||
        else
 | 
			
		||||
          mapping = append Nodes::Mapping.new(nil, '!str', false)
 | 
			
		||||
 | 
			
		||||
          mapping.children << Nodes::Scalar.new('str')
 | 
			
		||||
          mapping.children << scalar
 | 
			
		||||
 | 
			
		||||
          @stack.push mapping
 | 
			
		||||
          dump_ivars o, mapping
 | 
			
		||||
          @stack.pop
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def visit_Class o
 | 
			
		||||
        raise TypeError, "can't dump anonymous class #{o.class}"
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def visit_Range o
 | 
			
		||||
        @stack.push append Nodes::Mapping.new(nil, '!ruby/range', false)
 | 
			
		||||
        ['begin', o.begin, 'end', o.end, 'excl', o.exclude_end?].each do |m|
 | 
			
		||||
          accept m
 | 
			
		||||
        end
 | 
			
		||||
        @stack.pop
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def visit_Hash o
 | 
			
		||||
        @stack.push append register(o, create_mapping)
 | 
			
		||||
 | 
			
		||||
        o.each do |k,v|
 | 
			
		||||
          accept k
 | 
			
		||||
          accept v
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        @stack.pop
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def visit_Psych_Set o
 | 
			
		||||
        @stack.push append register(o, Nodes::Mapping.new(nil, '!set', false))
 | 
			
		||||
 | 
			
		||||
        o.each do |k,v|
 | 
			
		||||
          accept k
 | 
			
		||||
          accept v
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        @stack.pop
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def visit_Array o
 | 
			
		||||
        @stack.push append register(o, create_sequence)
 | 
			
		||||
        o.each { |c| accept c }
 | 
			
		||||
        @stack.pop
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def visit_NilClass o
 | 
			
		||||
        append Nodes::Scalar.new('', nil, 'tag:yaml.org,2002:null', false)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def visit_Symbol o
 | 
			
		||||
        append create_scalar ":#{o}"
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      private
 | 
			
		||||
      def append o
 | 
			
		||||
        @stack.last.children << o
 | 
			
		||||
        o
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def register target, yaml_obj
 | 
			
		||||
        @st[target.object_id] = yaml_obj
 | 
			
		||||
        yaml_obj
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def dump_coder o
 | 
			
		||||
        tag = Psych.dump_tags[o.class]
 | 
			
		||||
        unless tag
 | 
			
		||||
          klass = o.class == Object ? nil : o.class.name
 | 
			
		||||
          tag   = ['!ruby/object', klass].compact.join(':')
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        c = Psych::Coder.new(tag)
 | 
			
		||||
        o.encode_with(c)
 | 
			
		||||
        emit_coder c
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def emit_coder c
 | 
			
		||||
        case c.type
 | 
			
		||||
        when :scalar
 | 
			
		||||
          append create_scalar(c.scalar, nil, c.tag, c.tag.nil?)
 | 
			
		||||
        when :seq
 | 
			
		||||
          @stack.push append create_sequence(nil, c.tag, c.tag.nil?)
 | 
			
		||||
          c.seq.each do |thing|
 | 
			
		||||
            accept thing
 | 
			
		||||
          end
 | 
			
		||||
          @stack.pop
 | 
			
		||||
        when :map
 | 
			
		||||
          map = append Nodes::Mapping.new(nil, c.tag, c.implicit, c.style)
 | 
			
		||||
          @stack.push map
 | 
			
		||||
          c.map.each do |k,v|
 | 
			
		||||
            map.children << create_scalar(k)
 | 
			
		||||
            accept v
 | 
			
		||||
          end
 | 
			
		||||
          @stack.pop
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def dump_ivars target, map
 | 
			
		||||
        ivars = target.respond_to?(:to_yaml_properties) ?
 | 
			
		||||
          target.to_yaml_properties :
 | 
			
		||||
          target.instance_variables
 | 
			
		||||
 | 
			
		||||
        ivars.each do |iv|
 | 
			
		||||
          map.children << create_scalar("#{iv.to_s.sub(/^@/, '')}")
 | 
			
		||||
          accept target.instance_variable_get(iv)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def create_document
 | 
			
		||||
        Nodes::Document.new
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def create_mapping
 | 
			
		||||
        Nodes::Mapping.new
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def create_scalar value, anchor = nil, tag = nil, plain = true, quoted = false, style = Nodes::Scalar::ANY
 | 
			
		||||
        Nodes::Scalar.new(value, anchor, tag, plain, quoted, style)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def create_sequence anchor = nil, tag = nil, implicit = true, style = Nodes::Sequence::BLOCK
 | 
			
		||||
        Nodes::Sequence.new(anchor, tag, implicit, style)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										63
									
								
								test/psych/helper.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								test/psych/helper.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,63 @@
 | 
			
		|||
require 'minitest/autorun'
 | 
			
		||||
require 'stringio'
 | 
			
		||||
require 'tempfile'
 | 
			
		||||
require 'date'
 | 
			
		||||
 | 
			
		||||
module Psych
 | 
			
		||||
  class TestCase < MiniTest::Unit::TestCase
 | 
			
		||||
    #
 | 
			
		||||
    # Convert between Psych and the object to verify correct parsing and
 | 
			
		||||
    # emitting
 | 
			
		||||
    #
 | 
			
		||||
    def assert_to_yaml( obj, yaml )
 | 
			
		||||
      assert_equal( obj, Psych::load( yaml ) )
 | 
			
		||||
      assert_equal( obj, Psych::parse( yaml ).transform )
 | 
			
		||||
      assert_equal( obj, Psych::load( obj.psych_to_yaml ) )
 | 
			
		||||
      assert_equal( obj, Psych::parse( obj.psych_to_yaml ).transform )
 | 
			
		||||
      assert_equal( obj, Psych::load(
 | 
			
		||||
        obj.psych_to_yaml(
 | 
			
		||||
          :UseVersion => true, :UseHeader => true, :SortKeys => true
 | 
			
		||||
        )
 | 
			
		||||
      ))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    #
 | 
			
		||||
    # Test parser only
 | 
			
		||||
    #
 | 
			
		||||
    def assert_parse_only( obj, yaml )
 | 
			
		||||
      assert_equal( obj, Psych::load( yaml ) )
 | 
			
		||||
      assert_equal( obj, Psych::parse( yaml ).transform )
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def assert_cycle( obj )
 | 
			
		||||
      v = Visitors::YAMLTree.new
 | 
			
		||||
      v << obj
 | 
			
		||||
      assert_equal(obj, Psych.load(v.tree.to_yaml))
 | 
			
		||||
      assert_equal( obj, Psych::load(Psych.dump(obj)))
 | 
			
		||||
      assert_equal( obj, Psych::load( obj.psych_to_yaml ) )
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    #
 | 
			
		||||
    # Make a time with the time zone
 | 
			
		||||
    #
 | 
			
		||||
    def mktime( year, mon, day, hour, min, sec, usec, zone = "Z" )
 | 
			
		||||
      usec = Rational(usec.to_s) * 1000000
 | 
			
		||||
      val = Time::utc( year.to_i, mon.to_i, day.to_i, hour.to_i, min.to_i, sec.to_i, usec )
 | 
			
		||||
      if zone != "Z"
 | 
			
		||||
        hour = zone[0,3].to_i * 3600
 | 
			
		||||
        min = zone[3,2].to_i * 60
 | 
			
		||||
        ofs = (hour + min)
 | 
			
		||||
        val = Time.at( val.tv_sec - ofs, val.tv_nsec / 1000.0 )
 | 
			
		||||
      end
 | 
			
		||||
      return val
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
require 'psych'
 | 
			
		||||
 | 
			
		||||
# FIXME: remove this when syck is removed
 | 
			
		||||
o = Object.new
 | 
			
		||||
a = o.method(:psych_to_yaml)
 | 
			
		||||
b = o.method(:to_yaml)
 | 
			
		||||
raise "psych should define to_yaml" unless a == b
 | 
			
		||||
							
								
								
									
										26
									
								
								test/psych/test_alias_and_anchor.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								test/psych/test_alias_and_anchor.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,26 @@
 | 
			
		|||
require 'test/psych/helper'
 | 
			
		||||
 | 
			
		||||
module Psych
 | 
			
		||||
 class TestAliasAndAnchor < TestCase
 | 
			
		||||
   def test_mri_compatibility
 | 
			
		||||
     yaml = <<EOYAML
 | 
			
		||||
---
 | 
			
		||||
- &id001 !ruby/object {}
 | 
			
		||||
 | 
			
		||||
- *id001
 | 
			
		||||
- *id001
 | 
			
		||||
EOYAML
 | 
			
		||||
     result = Psych.load yaml
 | 
			
		||||
     result.each {|el| assert_same(result[0], el) }
 | 
			
		||||
   end
 | 
			
		||||
 | 
			
		||||
   def test_anchor_alias_round_trip
 | 
			
		||||
     o = Object.new
 | 
			
		||||
     original = [o,o,o]
 | 
			
		||||
 | 
			
		||||
     yaml = Psych.dump original
 | 
			
		||||
     result = Psych.load yaml
 | 
			
		||||
     result.each {|el| assert_same(result[0], el) }
 | 
			
		||||
   end
 | 
			
		||||
 end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										19
									
								
								test/psych/test_array.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								test/psych/test_array.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,19 @@
 | 
			
		|||
require 'test/psych/helper'
 | 
			
		||||
 | 
			
		||||
module Psych
 | 
			
		||||
  class TestArray < TestCase
 | 
			
		||||
    def setup
 | 
			
		||||
      super
 | 
			
		||||
      @list = [{ :a => 'b' }, 'foo']
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_self_referential
 | 
			
		||||
      @list << @list
 | 
			
		||||
      assert_cycle(@list)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_cycle
 | 
			
		||||
      assert_cycle(@list)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										36
									
								
								test/psych/test_boolean.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								test/psych/test_boolean.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,36 @@
 | 
			
		|||
require 'test/psych/helper'
 | 
			
		||||
 | 
			
		||||
module Psych
 | 
			
		||||
  ###
 | 
			
		||||
  # Test booleans from YAML spec:
 | 
			
		||||
  # http://yaml.org/type/bool.html
 | 
			
		||||
  class TestBoolean < TestCase
 | 
			
		||||
    %w{ yes Yes YES true True TRUE on On ON }.each do |truth|
 | 
			
		||||
      define_method(:"test_#{truth}") do
 | 
			
		||||
        assert_equal true, Psych.load("--- #{truth}")
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    %w{ no No NO false False FALSE off Off OFF }.each do |truth|
 | 
			
		||||
      define_method(:"test_#{truth}") do
 | 
			
		||||
        assert_equal false, Psych.load("--- #{truth}")
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    ###
 | 
			
		||||
    # YAML spec says "y" and "Y" may be used as true, but Syck treats them
 | 
			
		||||
    # as literal strings
 | 
			
		||||
    def test_y
 | 
			
		||||
      assert_equal "y", Psych.load("--- y")
 | 
			
		||||
      assert_equal "Y", Psych.load("--- Y")
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    ###
 | 
			
		||||
    # YAML spec says "n" and "N" may be used as false, but Syck treats them
 | 
			
		||||
    # as literal strings
 | 
			
		||||
    def test_n
 | 
			
		||||
      assert_equal "n", Psych.load("--- n")
 | 
			
		||||
      assert_equal "N", Psych.load("--- N")
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										17
									
								
								test/psych/test_class.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								test/psych/test_class.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,17 @@
 | 
			
		|||
require 'test/psych/helper'
 | 
			
		||||
 | 
			
		||||
module Psych
 | 
			
		||||
  class TestClass < TestCase
 | 
			
		||||
    def test_cycle
 | 
			
		||||
      assert_raises(::TypeError) do
 | 
			
		||||
        assert_cycle(TestClass)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_dump
 | 
			
		||||
      assert_raises(::TypeError) do
 | 
			
		||||
        Psych.dump TestClass
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										144
									
								
								test/psych/test_coder.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								test/psych/test_coder.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,144 @@
 | 
			
		|||
require 'test/psych/helper'
 | 
			
		||||
 | 
			
		||||
module Psych
 | 
			
		||||
  class TestCoder < TestCase
 | 
			
		||||
    class InitApi
 | 
			
		||||
      attr_accessor :implicit
 | 
			
		||||
      attr_accessor :style
 | 
			
		||||
      attr_accessor :tag
 | 
			
		||||
      attr_accessor :a, :b, :c
 | 
			
		||||
 | 
			
		||||
      def initialize
 | 
			
		||||
        @a = 1
 | 
			
		||||
        @b = 2
 | 
			
		||||
        @c = 3
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def init_with coder
 | 
			
		||||
        @a = coder['aa']
 | 
			
		||||
        @b = coder['bb']
 | 
			
		||||
        @implicit = coder.implicit
 | 
			
		||||
        @tag      = coder.tag
 | 
			
		||||
        @style    = coder.style
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def encode_with coder
 | 
			
		||||
        coder['aa'] = @a
 | 
			
		||||
        coder['bb'] = @b
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    class TaggingCoder < InitApi
 | 
			
		||||
      def encode_with coder
 | 
			
		||||
        super
 | 
			
		||||
        coder.tag       = coder.tag.sub(/!/, '!hello')
 | 
			
		||||
        coder.implicit  = false
 | 
			
		||||
        coder.style     = Psych::Nodes::Mapping::FLOW
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    class ScalarCoder
 | 
			
		||||
      def encode_with coder
 | 
			
		||||
        coder.scalar = "foo"
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    class Represent
 | 
			
		||||
      yaml_tag 'foo'
 | 
			
		||||
      def encode_with coder
 | 
			
		||||
        coder.represent_scalar 'foo', 'bar'
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    class RepresentWithInit
 | 
			
		||||
      yaml_tag name
 | 
			
		||||
      attr_accessor :str
 | 
			
		||||
 | 
			
		||||
      def init_with coder
 | 
			
		||||
        @str = coder.scalar
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def encode_with coder
 | 
			
		||||
        coder.represent_scalar self.class.name, 'bar'
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    class RepresentWithSeq
 | 
			
		||||
      yaml_tag name
 | 
			
		||||
      attr_accessor :seq
 | 
			
		||||
 | 
			
		||||
      def init_with coder
 | 
			
		||||
        @seq = coder.seq
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def encode_with coder
 | 
			
		||||
        coder.represent_seq self.class.name, %w{ foo bar }
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    class RepresentWithMap
 | 
			
		||||
      yaml_tag name
 | 
			
		||||
      attr_accessor :map
 | 
			
		||||
 | 
			
		||||
      def init_with coder
 | 
			
		||||
        @map = coder.map
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def encode_with coder
 | 
			
		||||
        coder.represent_map self.class.name, { 'a' => 'b' }
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_represent_map
 | 
			
		||||
      thing = Psych.load(Psych.dump(RepresentWithMap.new))
 | 
			
		||||
      assert_equal({ 'a' => 'b' }, thing.map)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_represent_sequence
 | 
			
		||||
      thing = Psych.load(Psych.dump(RepresentWithSeq.new))
 | 
			
		||||
      assert_equal %w{ foo bar }, thing.seq
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_represent_with_init
 | 
			
		||||
      thing = Psych.load(Psych.dump(RepresentWithInit.new))
 | 
			
		||||
      assert_equal 'bar', thing.str
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_represent!
 | 
			
		||||
      assert_match(/foo/, Psych.dump(Represent.new))
 | 
			
		||||
      assert_instance_of(Represent, Psych.load(Psych.dump(Represent.new)))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_scalar_coder
 | 
			
		||||
      foo = Psych.load(Psych.dump(ScalarCoder.new))
 | 
			
		||||
      assert_equal 'foo', foo
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_load_dumped_tagging
 | 
			
		||||
      foo = InitApi.new
 | 
			
		||||
      bar = Psych.load(Psych.dump(foo))
 | 
			
		||||
      assert_equal false, bar.implicit
 | 
			
		||||
      assert_equal "!ruby/object:Psych::TestCoder::InitApi", bar.tag
 | 
			
		||||
      assert_equal Psych::Nodes::Mapping::BLOCK, bar.style
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_dump_with_tag
 | 
			
		||||
      foo = TaggingCoder.new
 | 
			
		||||
      assert_match(/hello/, Psych.dump(foo))
 | 
			
		||||
      assert_match(/\{aa/, Psych.dump(foo))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_dump_encode_with
 | 
			
		||||
      foo = InitApi.new
 | 
			
		||||
      assert_match(/aa/, Psych.dump(foo))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_dump_init_with
 | 
			
		||||
      foo = InitApi.new
 | 
			
		||||
      bar = Psych.load(Psych.dump(foo))
 | 
			
		||||
      assert_equal foo.a, bar.a
 | 
			
		||||
      assert_equal foo.b, bar.b
 | 
			
		||||
      assert_nil bar.c
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										46
									
								
								test/psych/test_document.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								test/psych/test_document.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,46 @@
 | 
			
		|||
require 'test/psych/helper'
 | 
			
		||||
 | 
			
		||||
module Psych
 | 
			
		||||
  class TestDocument < TestCase
 | 
			
		||||
    def setup
 | 
			
		||||
      super
 | 
			
		||||
      @stream = Psych.parse_stream(<<-eoyml)
 | 
			
		||||
%YAML 1.1
 | 
			
		||||
%TAG ! tag:tenderlovemaking.com,2009:
 | 
			
		||||
--- !fun
 | 
			
		||||
      eoyml
 | 
			
		||||
      @doc = @stream.children.first
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_parse_tag
 | 
			
		||||
      assert_equal([['!', 'tag:tenderlovemaking.com,2009:']],
 | 
			
		||||
        @doc.tag_directives)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_emit_tag
 | 
			
		||||
      assert_match('%TAG ! tag:tenderlovemaking.com,2009:', @stream.to_yaml)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_emit_multitag
 | 
			
		||||
      @doc.tag_directives << ['!!', 'foo.com,2009:']
 | 
			
		||||
      yaml = @stream.to_yaml
 | 
			
		||||
      assert_match('%TAG ! tag:tenderlovemaking.com,2009:', yaml)
 | 
			
		||||
      assert_match('%TAG !! foo.com,2009:', yaml)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_emit_bad_tag
 | 
			
		||||
      assert_raises(RuntimeError) do
 | 
			
		||||
        @doc.tag_directives = [['!']]
 | 
			
		||||
        @stream.to_yaml
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_parse_version
 | 
			
		||||
      assert_equal([1,1], @doc.version)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_emit_version
 | 
			
		||||
      assert_match('%YAML 1.1', @stream.to_yaml)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										87
									
								
								test/psych/test_emitter.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								test/psych/test_emitter.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,87 @@
 | 
			
		|||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
require 'test/psych/helper'
 | 
			
		||||
 | 
			
		||||
module Psych
 | 
			
		||||
  class TestEmitter < TestCase
 | 
			
		||||
    def setup
 | 
			
		||||
      super
 | 
			
		||||
      @out = StringIO.new
 | 
			
		||||
      @emitter = Psych::Emitter.new @out
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_set_canonical
 | 
			
		||||
      @emitter.canonical = true
 | 
			
		||||
      assert_equal true, @emitter.canonical
 | 
			
		||||
 | 
			
		||||
      @emitter.canonical = false
 | 
			
		||||
      assert_equal false, @emitter.canonical
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_indentation_set
 | 
			
		||||
      assert_equal 2, @emitter.indentation
 | 
			
		||||
      @emitter.indentation = 5
 | 
			
		||||
      assert_equal 5, @emitter.indentation
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_emit_utf_8
 | 
			
		||||
      @emitter.start_stream Psych::Nodes::Stream::UTF8
 | 
			
		||||
      @emitter.start_document [], [], false
 | 
			
		||||
      @emitter.scalar '日本語', nil, nil, false, true, 1
 | 
			
		||||
      @emitter.end_document true
 | 
			
		||||
      @emitter.end_stream
 | 
			
		||||
      assert_match('日本語', @out.string)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_start_stream_arg_error
 | 
			
		||||
      assert_raises(TypeError) do
 | 
			
		||||
        @emitter.start_stream 'asdfasdf'
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_start_doc_arg_error
 | 
			
		||||
      @emitter.start_stream Psych::Nodes::Stream::UTF8
 | 
			
		||||
 | 
			
		||||
      [
 | 
			
		||||
        [nil, [], false],
 | 
			
		||||
        [[nil, nil], [], false],
 | 
			
		||||
        [[], 'foo', false],
 | 
			
		||||
        [[], ['foo'], false],
 | 
			
		||||
        [[], [nil,nil], false],
 | 
			
		||||
      ].each do |args|
 | 
			
		||||
        assert_raises(TypeError) do
 | 
			
		||||
          @emitter.start_document(*args)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_scalar_arg_error
 | 
			
		||||
      @emitter.start_stream Psych::Nodes::Stream::UTF8
 | 
			
		||||
      @emitter.start_document [], [], false
 | 
			
		||||
 | 
			
		||||
      [
 | 
			
		||||
        [:foo, nil, nil, false, true, 1],
 | 
			
		||||
        ['foo', Object.new, nil, false, true, 1],
 | 
			
		||||
        ['foo', nil, Object.new, false, true, 1],
 | 
			
		||||
        ['foo', nil, nil, false, true, :foo],
 | 
			
		||||
      ].each do |args|
 | 
			
		||||
        assert_raises(TypeError) do
 | 
			
		||||
          @emitter.scalar(*args)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_start_sequence_arg_error
 | 
			
		||||
      @emitter.start_stream Psych::Nodes::Stream::UTF8
 | 
			
		||||
      @emitter.start_document [], [], false
 | 
			
		||||
 | 
			
		||||
      assert_raises(TypeError) do
 | 
			
		||||
        @emitter.start_sequence(nil, Object.new, true, 1)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      assert_raises(TypeError) do
 | 
			
		||||
        @emitter.start_sequence(nil, nil, true, :foo)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										91
									
								
								test/psych/test_encoding.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								test/psych/test_encoding.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,91 @@
 | 
			
		|||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
require 'test/psych/helper'
 | 
			
		||||
 | 
			
		||||
module Psych
 | 
			
		||||
  class TestEncoding < TestCase
 | 
			
		||||
    class EncodingCatcher < Handler
 | 
			
		||||
      attr_reader :strings
 | 
			
		||||
      def initialize
 | 
			
		||||
        @strings = []
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      (Handler.instance_methods(true) -
 | 
			
		||||
       Object.instance_methods).each do |m|
 | 
			
		||||
        class_eval %{
 | 
			
		||||
          def #{m} *args
 | 
			
		||||
            @strings += args.flatten.find_all { |a|
 | 
			
		||||
              String === a
 | 
			
		||||
            }
 | 
			
		||||
          end
 | 
			
		||||
        }
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def setup
 | 
			
		||||
      super
 | 
			
		||||
      @handler = EncodingCatcher.new
 | 
			
		||||
      @parser  = Psych::Parser.new @handler
 | 
			
		||||
      @utf8    = Encoding.find('UTF-8')
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_scalar
 | 
			
		||||
      @parser.parse("--- a")
 | 
			
		||||
      assert_encodings @utf8, @handler.strings
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_alias
 | 
			
		||||
      @parser.parse(<<-eoyml)
 | 
			
		||||
%YAML 1.1
 | 
			
		||||
---
 | 
			
		||||
!!seq [
 | 
			
		||||
  !!str "Without properties",
 | 
			
		||||
  &A !!str "Anchored",
 | 
			
		||||
  !!str "Tagged",
 | 
			
		||||
  *A,
 | 
			
		||||
  !!str "",
 | 
			
		||||
]
 | 
			
		||||
      eoyml
 | 
			
		||||
      assert_encodings @utf8, @handler.strings
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_list_anchor
 | 
			
		||||
      list = %w{ a b }
 | 
			
		||||
      list << list
 | 
			
		||||
      @parser.parse(Psych.dump(list))
 | 
			
		||||
      assert_encodings @utf8, @handler.strings
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_map_anchor
 | 
			
		||||
      h = {}
 | 
			
		||||
      h['a'] = h
 | 
			
		||||
      @parser.parse(Psych.dump(h))
 | 
			
		||||
      assert_encodings @utf8, @handler.strings
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_map_tag
 | 
			
		||||
      @parser.parse(<<-eoyml)
 | 
			
		||||
%YAML 1.1
 | 
			
		||||
---
 | 
			
		||||
!!map { a : b }
 | 
			
		||||
      eoyml
 | 
			
		||||
      assert_encodings @utf8, @handler.strings
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_doc_tag
 | 
			
		||||
      @parser.parse(<<-eoyml)
 | 
			
		||||
%YAML 1.1
 | 
			
		||||
%TAG ! tag:tenderlovemaking.com,2009:
 | 
			
		||||
--- !fun
 | 
			
		||||
      eoyml
 | 
			
		||||
      assert_encodings @utf8, @handler.strings
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    private
 | 
			
		||||
    def assert_encodings encoding, strings
 | 
			
		||||
      strings.each do |str|
 | 
			
		||||
        assert_equal encoding, str.encoding, str
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										39
									
								
								test/psych/test_exception.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								test/psych/test_exception.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,39 @@
 | 
			
		|||
require 'test/psych/helper'
 | 
			
		||||
 | 
			
		||||
module Psych
 | 
			
		||||
  class TestException < TestCase
 | 
			
		||||
    class Wups < Exception
 | 
			
		||||
      attr_reader :foo, :bar
 | 
			
		||||
      def initialize *args
 | 
			
		||||
        super
 | 
			
		||||
        @foo = 1
 | 
			
		||||
        @bar = 2
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def setup
 | 
			
		||||
      super
 | 
			
		||||
      @wups = Wups.new
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_convert
 | 
			
		||||
      w = Psych.load(Psych.dump(@wups))
 | 
			
		||||
      assert_equal @wups, w
 | 
			
		||||
      assert_equal 1, w.foo
 | 
			
		||||
      assert_equal 2, w.bar
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_to_yaml_properties
 | 
			
		||||
      class << @wups
 | 
			
		||||
        def to_yaml_properties
 | 
			
		||||
          [:@foo]
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      w = Psych.load(Psych.dump(@wups))
 | 
			
		||||
      assert_equal @wups, w
 | 
			
		||||
      assert_equal 1, w.foo
 | 
			
		||||
      assert_nil w.bar
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										30
									
								
								test/psych/test_hash.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								test/psych/test_hash.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,30 @@
 | 
			
		|||
require 'test/psych/helper'
 | 
			
		||||
 | 
			
		||||
module Psych
 | 
			
		||||
  class TestHash < TestCase
 | 
			
		||||
    def setup
 | 
			
		||||
      super
 | 
			
		||||
      @hash = { :a => 'b' }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_self_referential
 | 
			
		||||
      @hash['self'] = @hash
 | 
			
		||||
      assert_cycle(@hash)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_cycles
 | 
			
		||||
      assert_cycle(@hash)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_ref_append
 | 
			
		||||
      hash = Psych.load(<<-eoyml)
 | 
			
		||||
---
 | 
			
		||||
foo: &foo
 | 
			
		||||
  hello: world
 | 
			
		||||
bar:
 | 
			
		||||
  <<: *foo
 | 
			
		||||
eoyml
 | 
			
		||||
      assert_equal({"foo"=>{"hello"=>"world"}, "bar"=>{"hello"=>"world"}}, hash)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										43
									
								
								test/psych/test_json_tree.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								test/psych/test_json_tree.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,43 @@
 | 
			
		|||
require 'test/psych/helper'
 | 
			
		||||
 | 
			
		||||
module Psych
 | 
			
		||||
  class TestJSONTree < TestCase
 | 
			
		||||
    def test_string
 | 
			
		||||
      assert_match(/(['"])foo\1/, Psych.to_json("foo"))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_symbol
 | 
			
		||||
      assert_match(/(['"])foo\1/, Psych.to_json(:foo))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_nil
 | 
			
		||||
      assert_match(/^null/, Psych.to_json(nil))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_int
 | 
			
		||||
      assert_match(/^10/, Psych.to_json(10))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_float
 | 
			
		||||
      assert_match(/^1.2/, Psych.to_json(1.2))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_hash
 | 
			
		||||
      hash = { 'one' => 'two' }
 | 
			
		||||
      json = Psych.to_json(hash)
 | 
			
		||||
      assert_match(/}$/, json)
 | 
			
		||||
      assert_match(/^\{/, json)
 | 
			
		||||
      assert_match(/['"]one['"]/, json)
 | 
			
		||||
      assert_match(/['"]two['"]/, json)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_list_to_json
 | 
			
		||||
      list = %w{ one two }
 | 
			
		||||
      json = Psych.to_json(list)
 | 
			
		||||
      assert_match(/]$/, json)
 | 
			
		||||
      assert_match(/^\[/, json)
 | 
			
		||||
      assert_match(/['"]one['"]/, json)
 | 
			
		||||
      assert_match(/['"]two['"]/, json)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										19
									
								
								test/psych/test_null.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								test/psych/test_null.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,19 @@
 | 
			
		|||
require 'test/psych/helper'
 | 
			
		||||
 | 
			
		||||
module Psych
 | 
			
		||||
  ###
 | 
			
		||||
  # Test null from YAML spec:
 | 
			
		||||
  # http://yaml.org/type/null.html
 | 
			
		||||
  class TestNull < TestCase
 | 
			
		||||
    def test_null_list
 | 
			
		||||
      assert_equal [nil] * 5, Psych.load(<<-eoyml)
 | 
			
		||||
---
 | 
			
		||||
- ~
 | 
			
		||||
- null
 | 
			
		||||
- 
 | 
			
		||||
- Null
 | 
			
		||||
- NULL
 | 
			
		||||
      eoyml
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										27
									
								
								test/psych/test_object.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								test/psych/test_object.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,27 @@
 | 
			
		|||
require 'test/psych/helper'
 | 
			
		||||
 | 
			
		||||
module Psych
 | 
			
		||||
  class Tagged
 | 
			
		||||
    yaml_tag '!foo'
 | 
			
		||||
 | 
			
		||||
    attr_accessor :baz
 | 
			
		||||
 | 
			
		||||
    def initialize
 | 
			
		||||
      @baz = 'bar'
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  class TestObject < TestCase
 | 
			
		||||
    def test_dump_with_tag
 | 
			
		||||
      tag = Tagged.new
 | 
			
		||||
      assert_match('foo', Psych.dump(tag))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_tag_round_trip
 | 
			
		||||
      tag   = Tagged.new
 | 
			
		||||
      tag2  = Psych.load(Psych.dump(tag))
 | 
			
		||||
      assert_equal tag.baz, tag2.baz
 | 
			
		||||
      assert_instance_of(Tagged, tag2)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										68
									
								
								test/psych/test_omap.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								test/psych/test_omap.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,68 @@
 | 
			
		|||
require 'test/psych/helper'
 | 
			
		||||
 | 
			
		||||
module Psych
 | 
			
		||||
  class TestOmap < TestCase
 | 
			
		||||
    def test_self_referential
 | 
			
		||||
      map = Psych::Omap.new
 | 
			
		||||
      map['foo'] = 'bar'
 | 
			
		||||
      map['self'] = map
 | 
			
		||||
      assert_equal(map, Psych.load(Psych.dump(map)))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_keys
 | 
			
		||||
      map = Psych::Omap.new
 | 
			
		||||
      map['foo'] = 'bar'
 | 
			
		||||
      assert_equal 'bar', map['foo']
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_order
 | 
			
		||||
      map = Psych::Omap.new
 | 
			
		||||
      map['a'] = 'b'
 | 
			
		||||
      map['b'] = 'c'
 | 
			
		||||
      assert_equal [%w{a b}, %w{b c}], map.to_a
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_square
 | 
			
		||||
      list = [["a", "b"], ["b", "c"]]
 | 
			
		||||
      map = Psych::Omap[*list.flatten]
 | 
			
		||||
      assert_equal list, map.to_a
 | 
			
		||||
      assert_equal 'b', map['a']
 | 
			
		||||
      assert_equal 'c', map['b']
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_dump
 | 
			
		||||
      map = Psych::Omap['a', 'b', 'c', 'd']
 | 
			
		||||
      yaml = Psych.dump(map)
 | 
			
		||||
      assert_match('!omap', yaml)
 | 
			
		||||
      assert_match('- a: b', yaml)
 | 
			
		||||
      assert_match('- c: d', yaml)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_round_trip
 | 
			
		||||
      list = [["a", "b"], ["b", "c"]]
 | 
			
		||||
      map = Psych::Omap[*list.flatten]
 | 
			
		||||
      assert_cycle(map)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_load
 | 
			
		||||
      list = [["a", "b"], ["c", "d"]]
 | 
			
		||||
      map = Psych.load(<<-eoyml)
 | 
			
		||||
--- !omap
 | 
			
		||||
- a: b
 | 
			
		||||
- c: d
 | 
			
		||||
      eoyml
 | 
			
		||||
      assert_equal list, map.to_a
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # NOTE: This test will not work with Syck
 | 
			
		||||
    def test_load_shorthand
 | 
			
		||||
      list = [["a", "b"], ["c", "d"]]
 | 
			
		||||
      map = Psych.load(<<-eoyml)
 | 
			
		||||
--- !!omap
 | 
			
		||||
- a: b
 | 
			
		||||
- c: d
 | 
			
		||||
      eoyml
 | 
			
		||||
      assert_equal list, map.to_a
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										188
									
								
								test/psych/test_parser.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										188
									
								
								test/psych/test_parser.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,188 @@
 | 
			
		|||
require 'test/psych/helper'
 | 
			
		||||
 | 
			
		||||
module Psych
 | 
			
		||||
  class TestParser < TestCase
 | 
			
		||||
    class EventCatcher < Handler
 | 
			
		||||
      attr_reader :calls
 | 
			
		||||
      def initialize
 | 
			
		||||
        @calls = []
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      (Handler.instance_methods(true) -
 | 
			
		||||
       Object.instance_methods).each do |m|
 | 
			
		||||
        class_eval %{
 | 
			
		||||
          def #{m} *args
 | 
			
		||||
            super
 | 
			
		||||
            @calls << [:#{m}, args]
 | 
			
		||||
          end
 | 
			
		||||
        }
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def setup
 | 
			
		||||
      super
 | 
			
		||||
      @parser = Psych::Parser.new EventCatcher.new
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_bogus_io
 | 
			
		||||
      o = Object.new
 | 
			
		||||
      def o.read len; self end
 | 
			
		||||
 | 
			
		||||
      assert_raises(TypeError) do
 | 
			
		||||
        @parser.parse o
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_parse_io
 | 
			
		||||
      @parser.parse StringIO.new("--- a")
 | 
			
		||||
      assert_called :start_stream
 | 
			
		||||
      assert_called :scalar
 | 
			
		||||
      assert_called :end_stream
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_syntax_error
 | 
			
		||||
      assert_raises(Psych::SyntaxError) do
 | 
			
		||||
        @parser.parse("---\n\"foo\"\n\"bar\"\n")
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_mapping_end
 | 
			
		||||
      @parser.parse("---\n!!map { key: value }")
 | 
			
		||||
      assert_called :end_mapping
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_mapping_tag
 | 
			
		||||
      @parser.parse("---\n!!map { key: value }")
 | 
			
		||||
      assert_called :start_mapping, ["tag:yaml.org,2002:map", false, Nodes::Mapping::FLOW]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_mapping_anchor
 | 
			
		||||
      @parser.parse("---\n&A { key: value }")
 | 
			
		||||
      assert_called :start_mapping, ['A', true, Nodes::Mapping::FLOW]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_mapping_block
 | 
			
		||||
      @parser.parse("---\n  key: value")
 | 
			
		||||
      assert_called :start_mapping, [true, Nodes::Mapping::BLOCK]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_mapping_start
 | 
			
		||||
      @parser.parse("---\n{ key: value }")
 | 
			
		||||
      assert_called :start_mapping
 | 
			
		||||
      assert_called :start_mapping, [true, Nodes::Mapping::FLOW]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_sequence_end
 | 
			
		||||
      @parser.parse("---\n&A [1, 2]")
 | 
			
		||||
      assert_called :end_sequence
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_sequence_start_anchor
 | 
			
		||||
      @parser.parse("---\n&A [1, 2]")
 | 
			
		||||
      assert_called :start_sequence, ["A", true, Nodes::Sequence::FLOW]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_sequence_start_tag
 | 
			
		||||
      @parser.parse("---\n!!seq [1, 2]")
 | 
			
		||||
      assert_called :start_sequence, ["tag:yaml.org,2002:seq", false, Nodes::Sequence::FLOW]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_sequence_start_flow
 | 
			
		||||
      @parser.parse("---\n[1, 2]")
 | 
			
		||||
      assert_called :start_sequence, [true, Nodes::Sequence::FLOW]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_sequence_start_block
 | 
			
		||||
      @parser.parse("---\n  - 1\n  - 2")
 | 
			
		||||
      assert_called :start_sequence, [true, Nodes::Sequence::BLOCK]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_literal_scalar
 | 
			
		||||
      @parser.parse(<<-eoyml)
 | 
			
		||||
%YAML 1.1
 | 
			
		||||
---
 | 
			
		||||
"literal\n\
 | 
			
		||||
        \ttext\n"
 | 
			
		||||
      eoyml
 | 
			
		||||
      assert_called :scalar, ['literal text ', false, true, Nodes::Scalar::DOUBLE_QUOTED]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_scalar
 | 
			
		||||
      @parser.parse("--- foo\n")
 | 
			
		||||
      assert_called :scalar, ['foo', true, false, Nodes::Scalar::PLAIN]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_scalar_with_tag
 | 
			
		||||
      @parser.parse("---\n!!str foo\n")
 | 
			
		||||
      assert_called :scalar, ['foo', 'tag:yaml.org,2002:str', false, false, Nodes::Scalar::PLAIN]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_scalar_with_anchor
 | 
			
		||||
      @parser.parse("---\n&A foo\n")
 | 
			
		||||
      assert_called :scalar, ['foo', 'A', true, false, Nodes::Scalar::PLAIN]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_scalar_plain_implicit
 | 
			
		||||
      @parser.parse("---\n&A foo\n")
 | 
			
		||||
      assert_called :scalar, ['foo', 'A', true, false, Nodes::Scalar::PLAIN]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_alias
 | 
			
		||||
      @parser.parse(<<-eoyml)
 | 
			
		||||
%YAML 1.1
 | 
			
		||||
---
 | 
			
		||||
!!seq [
 | 
			
		||||
  !!str "Without properties",
 | 
			
		||||
  &A !!str "Anchored",
 | 
			
		||||
  !!str "Tagged",
 | 
			
		||||
  *A,
 | 
			
		||||
  !!str "",
 | 
			
		||||
]
 | 
			
		||||
      eoyml
 | 
			
		||||
      assert_called :alias, ['A']
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_end_stream
 | 
			
		||||
      @parser.parse("--- foo\n")
 | 
			
		||||
      assert_called :end_stream
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_start_stream
 | 
			
		||||
      @parser.parse("--- foo\n")
 | 
			
		||||
      assert_called :start_stream
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_end_document_implicit
 | 
			
		||||
      @parser.parse("\"foo\"\n")
 | 
			
		||||
      assert_called :end_document, [true]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_end_document_explicit
 | 
			
		||||
      @parser.parse("\"foo\"\n...")
 | 
			
		||||
      assert_called :end_document, [false]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_start_document_version
 | 
			
		||||
      @parser.parse("%YAML 1.1\n---\n\"foo\"\n")
 | 
			
		||||
      assert_called :start_document, [[1,1], [], false]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_start_document_tag
 | 
			
		||||
      @parser.parse("%TAG !yaml! tag:yaml.org,2002\n---\n!yaml!str \"foo\"\n")
 | 
			
		||||
      assert_called :start_document, [[], [['!yaml!', 'tag:yaml.org,2002']], false]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def assert_called call, with = nil, parser = @parser
 | 
			
		||||
      if with
 | 
			
		||||
        call = parser.handler.calls.find { |x|
 | 
			
		||||
          x.first == call && x.last.compact == with
 | 
			
		||||
        }
 | 
			
		||||
        assert(call,
 | 
			
		||||
          "#{[call,with].inspect} not in #{parser.handler.calls.inspect}"
 | 
			
		||||
        )
 | 
			
		||||
      else
 | 
			
		||||
        assert parser.handler.calls.any? { |x| x.first == call }
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										69
									
								
								test/psych/test_psych.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								test/psych/test_psych.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,69 @@
 | 
			
		|||
require 'test/psych/helper'
 | 
			
		||||
 | 
			
		||||
class TestPsych < Psych::TestCase
 | 
			
		||||
  def test_dump_stream
 | 
			
		||||
    things = [22, "foo \n", {}]
 | 
			
		||||
    stream = Psych.dump_stream(*things)
 | 
			
		||||
    assert_equal things, Psych.load_stream(stream)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_simple
 | 
			
		||||
    assert_equal 'foo', Psych.load("--- foo\n")
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_libyaml_version
 | 
			
		||||
    assert Psych.libyaml_version
 | 
			
		||||
    assert_equal Psych.libyaml_version.join('.'), Psych::LIBYAML_VERSION
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_load_documents
 | 
			
		||||
    docs = Psych.load_documents("--- foo\n...\n--- bar\n...")
 | 
			
		||||
    assert_equal %w{ foo bar }, docs
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_parse_stream
 | 
			
		||||
    docs = Psych.parse_stream("--- foo\n...\n--- bar\n...")
 | 
			
		||||
    assert_equal %w{ foo bar }, docs.children.map { |x| x.transform }
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_add_builtin_type
 | 
			
		||||
    got = nil
 | 
			
		||||
    Psych.add_builtin_type 'omap', do |type, val|
 | 
			
		||||
      got = val
 | 
			
		||||
    end
 | 
			
		||||
    Psych.load('--- !omap hello')
 | 
			
		||||
    assert_equal 'hello', got
 | 
			
		||||
  ensure
 | 
			
		||||
    Psych.remove_type 'omap'
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_domain_types
 | 
			
		||||
    got = nil
 | 
			
		||||
    Psych.add_domain_type 'foo.bar,2002', 'foo' do |type, val|
 | 
			
		||||
      got = val
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    Psych.load('--- !foo.bar,2002/foo hello')
 | 
			
		||||
    assert_equal 'hello', got
 | 
			
		||||
 | 
			
		||||
    Psych.load("--- !foo.bar,2002/foo\n- hello\n- world")
 | 
			
		||||
    assert_equal %w{ hello world }, got
 | 
			
		||||
 | 
			
		||||
    Psych.load("--- !foo.bar,2002/foo\nhello: world")
 | 
			
		||||
    assert_equal({ 'hello' => 'world' }, got)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_load_file
 | 
			
		||||
    name = File.join(Dir.tmpdir, 'yikes.yml')
 | 
			
		||||
    File.open(name, 'wb') { |f| f.write('--- hello world') }
 | 
			
		||||
 | 
			
		||||
    assert_equal 'hello world', Psych.load_file(name)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_parse_file
 | 
			
		||||
    name = File.join(Dir.tmpdir, 'yikes.yml')
 | 
			
		||||
    File.open(name, 'wb') { |f| f.write('--- hello world') }
 | 
			
		||||
 | 
			
		||||
    assert_equal 'hello world', Psych.parse_file(name).transform
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										11
									
								
								test/psych/test_scalar.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								test/psych/test_scalar.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,11 @@
 | 
			
		|||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
require 'test/psych/helper'
 | 
			
		||||
 | 
			
		||||
module Psych
 | 
			
		||||
  class TestScalar < TestCase
 | 
			
		||||
    def test_utf_8
 | 
			
		||||
      assert_equal "日本語", Psych.load("--- 日本語")
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										70
									
								
								test/psych/test_scalar_scanner.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								test/psych/test_scalar_scanner.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,70 @@
 | 
			
		|||
require 'test/psych/helper'
 | 
			
		||||
 | 
			
		||||
module Psych
 | 
			
		||||
  class TestScalarScanner < TestCase
 | 
			
		||||
    def test_scan_time
 | 
			
		||||
      [ '2001-12-15T02:59:43.1Z',
 | 
			
		||||
        '2001-12-14t21:59:43.10-05:00',
 | 
			
		||||
        '2001-12-14 21:59:43.10 -5',
 | 
			
		||||
        '2010-01-06 00:00:00 -08:00',
 | 
			
		||||
        '2001-12-15 2:59:43.10',
 | 
			
		||||
      ].each do |time|
 | 
			
		||||
        ss = Psych::ScalarScanner.new
 | 
			
		||||
        assert_instance_of Time, ss.tokenize(time)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    attr_reader :ss
 | 
			
		||||
 | 
			
		||||
    def setup
 | 
			
		||||
      super
 | 
			
		||||
      @ss = Psych::ScalarScanner.new
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_scan_date
 | 
			
		||||
      date = '1980-12-16'
 | 
			
		||||
      token = @ss.tokenize date
 | 
			
		||||
      assert_equal 1980, token.year
 | 
			
		||||
      assert_equal 12, token.month
 | 
			
		||||
      assert_equal 16, token.day
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_scan_inf
 | 
			
		||||
      assert_equal(1 / 0.0, ss.tokenize('.inf'))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_scan_minus_inf
 | 
			
		||||
      assert_equal(-1 / 0.0, ss.tokenize('-.inf'))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_scan_nan
 | 
			
		||||
      assert ss.tokenize('.nan').nan?
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_scan_null
 | 
			
		||||
      assert_equal nil, ss.tokenize('null')
 | 
			
		||||
      assert_equal nil, ss.tokenize('~')
 | 
			
		||||
      assert_equal nil, ss.tokenize('')
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_scan_symbol
 | 
			
		||||
      assert_equal :foo, ss.tokenize(':foo')
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_scan_sexagesimal_float
 | 
			
		||||
      assert_equal 685230.15, ss.tokenize('190:20:30.15')
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_scan_sexagesimal_int
 | 
			
		||||
      assert_equal 685230, ss.tokenize('190:20:30')
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_scan_float
 | 
			
		||||
      assert_equal 1.2, ss.tokenize('1.2')
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_scan_true
 | 
			
		||||
      assert_equal true, ss.tokenize('true')
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										38
									
								
								test/psych/test_serialize_subclasses.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								test/psych/test_serialize_subclasses.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,38 @@
 | 
			
		|||
require 'test/psych/helper'
 | 
			
		||||
 | 
			
		||||
module Psych
 | 
			
		||||
  class TestSerializeSubclasses < TestCase
 | 
			
		||||
    class SomeObject
 | 
			
		||||
      def initialize one, two
 | 
			
		||||
        @one = one
 | 
			
		||||
        @two = two
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def == other
 | 
			
		||||
        @one == other.instance_eval { @one } &&
 | 
			
		||||
          @two == other.instance_eval { @two }
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_some_object
 | 
			
		||||
      so = SomeObject.new('foo', [1,2,3])
 | 
			
		||||
      assert_equal so, Psych.load(Psych.dump(so))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    class StructSubclass < Struct.new(:foo)
 | 
			
		||||
      def initialize foo, bar
 | 
			
		||||
        super(foo)
 | 
			
		||||
        @bar = bar
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def == other
 | 
			
		||||
        super(other) && @bar == other.instance_eval{ @bar }
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_struct_subclass
 | 
			
		||||
      so = StructSubclass.new('foo', [1,2,3])
 | 
			
		||||
      assert_equal so, Psych.load(Psych.dump(so))
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										49
									
								
								test/psych/test_set.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								test/psych/test_set.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,49 @@
 | 
			
		|||
require 'test/psych/helper'
 | 
			
		||||
 | 
			
		||||
module Psych
 | 
			
		||||
  class TestSet < TestCase
 | 
			
		||||
    def setup
 | 
			
		||||
      super
 | 
			
		||||
      @set = Psych::Set.new
 | 
			
		||||
      @set['foo'] = 'bar'
 | 
			
		||||
      @set['bar'] = 'baz'
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_dump
 | 
			
		||||
      assert_match(/!set/, Psych.dump(@set))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_roundtrip
 | 
			
		||||
      assert_cycle(@set)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    ###
 | 
			
		||||
    # FIXME: Syck should also support !!set as shorthand
 | 
			
		||||
    def test_load_from_yaml
 | 
			
		||||
      loaded = Psych.load(<<-eoyml)
 | 
			
		||||
--- !set
 | 
			
		||||
foo: bar
 | 
			
		||||
bar: baz
 | 
			
		||||
      eoyml
 | 
			
		||||
      assert_equal(@set, loaded)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_loaded_class
 | 
			
		||||
      assert_instance_of(Psych::Set, Psych.load(Psych.dump(@set)))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_set_shorthand
 | 
			
		||||
      loaded = Psych.load(<<-eoyml)
 | 
			
		||||
--- !!set
 | 
			
		||||
foo: bar
 | 
			
		||||
bar: baz
 | 
			
		||||
      eoyml
 | 
			
		||||
      assert_instance_of(Psych::Set, loaded)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_set_self_reference
 | 
			
		||||
      @set['self'] = @set
 | 
			
		||||
      assert_cycle(@set)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										49
									
								
								test/psych/test_string.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								test/psych/test_string.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,49 @@
 | 
			
		|||
require 'test/psych/helper'
 | 
			
		||||
 | 
			
		||||
module Psych
 | 
			
		||||
  class TestString < TestCase
 | 
			
		||||
    def test_binary_string_null
 | 
			
		||||
      string = "\x00"
 | 
			
		||||
      yml = Psych.dump string
 | 
			
		||||
      assert_match(/binary/, yml)
 | 
			
		||||
      assert_equal string, Psych.load(yml)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_binary_string
 | 
			
		||||
      string = binary_string
 | 
			
		||||
      yml = Psych.dump string
 | 
			
		||||
      assert_match(/binary/, yml)
 | 
			
		||||
      assert_equal string, Psych.load(yml)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_non_binary_string
 | 
			
		||||
      string = binary_string(0.29)
 | 
			
		||||
      yml = Psych.dump string
 | 
			
		||||
      refute_match(/binary/, yml)
 | 
			
		||||
      assert_equal string, Psych.load(yml)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_string_with_ivars
 | 
			
		||||
      food = "is delicious"
 | 
			
		||||
      ivar = "on rock and roll"
 | 
			
		||||
      food.instance_variable_set(:@we_built_this_city, ivar)
 | 
			
		||||
 | 
			
		||||
      str = Psych.load Psych.dump food
 | 
			
		||||
      assert_equal ivar, food.instance_variable_get(:@we_built_this_city)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_binary
 | 
			
		||||
      string = [0, 123,22, 44, 9, 32, 34, 39].pack('C*')
 | 
			
		||||
      assert_cycle string
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def binary_string percentage = 0.31, length = 100
 | 
			
		||||
      string = ''
 | 
			
		||||
      (percentage * length).to_i.times do |i|
 | 
			
		||||
        string << "\b"
 | 
			
		||||
      end
 | 
			
		||||
      string << 'a' * (length - string.length)
 | 
			
		||||
      string
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										51
									
								
								test/psych/test_struct.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								test/psych/test_struct.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,51 @@
 | 
			
		|||
require 'test/psych/helper'
 | 
			
		||||
 | 
			
		||||
class PsychStructWithIvar < Struct.new(:foo)
 | 
			
		||||
  attr_reader :bar
 | 
			
		||||
  def initialize *args
 | 
			
		||||
    super
 | 
			
		||||
    @bar = 'hello'
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
module Psych
 | 
			
		||||
  class TestStruct < TestCase
 | 
			
		||||
    class StructSubclass < Struct.new(:foo)
 | 
			
		||||
      def initialize foo, bar
 | 
			
		||||
        super(foo)
 | 
			
		||||
        @bar = bar
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_self_referential_struct
 | 
			
		||||
      ss = StructSubclass.new(nil, 'foo')
 | 
			
		||||
      ss.foo = ss
 | 
			
		||||
 | 
			
		||||
      loaded = Psych.load(Psych.dump(ss))
 | 
			
		||||
      assert_instance_of(StructSubclass, loaded.foo)
 | 
			
		||||
 | 
			
		||||
      # FIXME: This seems to cause an infinite loop.  wtf.  Must report a bug
 | 
			
		||||
      # in ruby.
 | 
			
		||||
      # assert_equal(ss, loaded)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_roundtrip
 | 
			
		||||
      thing = PsychStructWithIvar.new('bar')
 | 
			
		||||
      struct = Psych.load(Psych.dump(thing))
 | 
			
		||||
 | 
			
		||||
      assert_equal 'hello', struct.bar
 | 
			
		||||
      assert_equal 'bar', struct.foo
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_load
 | 
			
		||||
      obj = Psych.load(<<-eoyml)
 | 
			
		||||
--- !ruby/struct:PsychStructWithIvar 
 | 
			
		||||
:foo: bar
 | 
			
		||||
:@bar: hello
 | 
			
		||||
      eoyml
 | 
			
		||||
 | 
			
		||||
      assert_equal 'hello', obj.bar
 | 
			
		||||
      assert_equal 'bar', obj.foo
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										17
									
								
								test/psych/test_symbol.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								test/psych/test_symbol.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,17 @@
 | 
			
		|||
require 'test/psych/helper'
 | 
			
		||||
 | 
			
		||||
module Psych
 | 
			
		||||
  class TestSymbol < TestCase
 | 
			
		||||
    def test_cycle
 | 
			
		||||
      assert_cycle :a
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_stringy
 | 
			
		||||
      assert_cycle :"1"
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_load_quoted
 | 
			
		||||
      assert_equal :"1", Psych.load("--- :'1'\n")
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										63
									
								
								test/psych/test_to_yaml_properties.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								test/psych/test_to_yaml_properties.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,63 @@
 | 
			
		|||
require 'test/psych/helper'
 | 
			
		||||
 | 
			
		||||
module Psych
 | 
			
		||||
  class TestToYamlProperties < MiniTest::Unit::TestCase
 | 
			
		||||
    class Foo
 | 
			
		||||
      attr_accessor :a, :b, :c
 | 
			
		||||
      def initialize
 | 
			
		||||
        @a = 1
 | 
			
		||||
        @b = 2
 | 
			
		||||
        @c = 3
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def to_yaml_properties
 | 
			
		||||
        [:@a, :@b]
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_object_dump_yaml_properties
 | 
			
		||||
      foo = Psych.load(Psych.dump(Foo.new))
 | 
			
		||||
      assert_equal 1, foo.a
 | 
			
		||||
      assert_equal 2, foo.b
 | 
			
		||||
      assert_nil foo.c
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    class Bar < Struct.new(:foo, :bar)
 | 
			
		||||
      attr_reader :baz
 | 
			
		||||
      def initialize *args
 | 
			
		||||
        super
 | 
			
		||||
        @baz = 'hello'
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def to_yaml_properties
 | 
			
		||||
        []
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_struct_dump_yaml_properties
 | 
			
		||||
      bar = Psych.load(Psych.dump(Bar.new('a', 'b')))
 | 
			
		||||
      assert_equal 'a', bar.foo
 | 
			
		||||
      assert_equal 'b', bar.bar
 | 
			
		||||
      assert_nil bar.baz
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_string_dump
 | 
			
		||||
      string = "okonomiyaki"
 | 
			
		||||
      class << string
 | 
			
		||||
        def to_yaml_properties
 | 
			
		||||
          [:@tastes]
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      string.instance_variable_set(:@tastes, 'delicious')
 | 
			
		||||
      v = Psych.load Psych.dump string
 | 
			
		||||
      assert_equal 'delicious', v.instance_variable_get(:@tastes)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_string_load_syck
 | 
			
		||||
      str = Psych.load("--- !str \nstr: okonomiyaki\n:@tastes: delicious\n")
 | 
			
		||||
      assert_equal 'okonomiyaki', str
 | 
			
		||||
      assert_equal 'delicious', str.instance_variable_get(:@tastes)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										79
									
								
								test/psych/test_tree_builder.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								test/psych/test_tree_builder.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,79 @@
 | 
			
		|||
require 'test/psych/helper'
 | 
			
		||||
 | 
			
		||||
module Psych
 | 
			
		||||
  class TestTreeBuilder < TestCase
 | 
			
		||||
    def setup
 | 
			
		||||
      super
 | 
			
		||||
      @parser = Psych::Parser.new TreeBuilder.new
 | 
			
		||||
      @parser.parse(<<-eoyml)
 | 
			
		||||
%YAML 1.1
 | 
			
		||||
---
 | 
			
		||||
- foo
 | 
			
		||||
- {
 | 
			
		||||
  bar : &A !!str baz,
 | 
			
		||||
  boo : *A
 | 
			
		||||
}
 | 
			
		||||
- *A
 | 
			
		||||
      eoyml
 | 
			
		||||
      @tree = @parser.handler.root
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_stream
 | 
			
		||||
      assert_instance_of Nodes::Stream, @tree
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_documents
 | 
			
		||||
      assert_equal 1, @tree.children.length
 | 
			
		||||
      assert_instance_of Nodes::Document, @tree.children.first
 | 
			
		||||
      doc = @tree.children.first
 | 
			
		||||
 | 
			
		||||
      assert_equal [1,1], doc.version
 | 
			
		||||
      assert_equal [], doc.tag_directives
 | 
			
		||||
      assert_equal false, doc.implicit
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_sequence
 | 
			
		||||
      doc = @tree.children.first
 | 
			
		||||
      assert_equal 1, doc.children.length
 | 
			
		||||
 | 
			
		||||
      seq = doc.children.first
 | 
			
		||||
      assert_instance_of Nodes::Sequence, seq
 | 
			
		||||
      assert_nil seq.anchor
 | 
			
		||||
      assert_nil seq.tag
 | 
			
		||||
      assert_equal true, seq.implicit
 | 
			
		||||
      assert_equal Nodes::Sequence::BLOCK, seq.style
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_scalar
 | 
			
		||||
      doc = @tree.children.first
 | 
			
		||||
      seq = doc.children.first
 | 
			
		||||
 | 
			
		||||
      assert_equal 3, seq.children.length
 | 
			
		||||
      scalar = seq.children.first
 | 
			
		||||
      assert_instance_of Nodes::Scalar, scalar
 | 
			
		||||
      assert_equal 'foo', scalar.value
 | 
			
		||||
      assert_nil scalar.anchor
 | 
			
		||||
      assert_nil scalar.tag
 | 
			
		||||
      assert_equal true, scalar.plain
 | 
			
		||||
      assert_equal false, scalar.quoted
 | 
			
		||||
      assert_equal Nodes::Scalar::PLAIN, scalar.style
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_mapping
 | 
			
		||||
      doc = @tree.children.first
 | 
			
		||||
      seq = doc.children.first
 | 
			
		||||
      map = seq.children[1]
 | 
			
		||||
 | 
			
		||||
      assert_instance_of Nodes::Mapping, map
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_alias
 | 
			
		||||
      doc = @tree.children.first
 | 
			
		||||
      seq = doc.children.first
 | 
			
		||||
      assert_equal 3, seq.children.length
 | 
			
		||||
      al  = seq.children[2]
 | 
			
		||||
      assert_instance_of Nodes::Alias, al
 | 
			
		||||
      assert_equal 'A', al.anchor
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										1248
									
								
								test/psych/test_yaml.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1248
									
								
								test/psych/test_yaml.rb
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										124
									
								
								test/psych/visitors/test_emitter.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								test/psych/visitors/test_emitter.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,124 @@
 | 
			
		|||
require 'test/psych/helper'
 | 
			
		||||
 | 
			
		||||
module Psych
 | 
			
		||||
  module Visitors
 | 
			
		||||
    class TestEmitter < TestCase
 | 
			
		||||
      def setup
 | 
			
		||||
        super
 | 
			
		||||
        @io = StringIO.new
 | 
			
		||||
        @visitor = Visitors::Emitter.new @io
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_stream
 | 
			
		||||
        s = Nodes::Stream.new
 | 
			
		||||
        @visitor.accept s
 | 
			
		||||
        assert_equal '', @io.string
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_document
 | 
			
		||||
        s       = Nodes::Stream.new
 | 
			
		||||
        doc     = Nodes::Document.new [1,1]
 | 
			
		||||
        scalar  = Nodes::Scalar.new 'hello world'
 | 
			
		||||
 | 
			
		||||
        doc.children << scalar
 | 
			
		||||
        s.children << doc
 | 
			
		||||
 | 
			
		||||
        @visitor.accept s
 | 
			
		||||
 | 
			
		||||
        assert_match(/1.1/, @io.string)
 | 
			
		||||
        assert_equal @io.string, s.to_yaml
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_document_implicit_end
 | 
			
		||||
        s       = Nodes::Stream.new
 | 
			
		||||
        doc     = Nodes::Document.new
 | 
			
		||||
        mapping = Nodes::Mapping.new
 | 
			
		||||
        mapping.children << Nodes::Scalar.new('key')
 | 
			
		||||
        mapping.children << Nodes::Scalar.new('value')
 | 
			
		||||
        doc.children << mapping
 | 
			
		||||
        s.children << doc
 | 
			
		||||
 | 
			
		||||
        @visitor.accept s
 | 
			
		||||
 | 
			
		||||
        assert_match(/key: value/, @io.string)
 | 
			
		||||
        assert_equal @io.string, s.to_yaml
 | 
			
		||||
        assert(/\.\.\./ !~ s.to_yaml)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_scalar
 | 
			
		||||
        s       = Nodes::Stream.new
 | 
			
		||||
        doc     = Nodes::Document.new
 | 
			
		||||
        scalar  = Nodes::Scalar.new 'hello world'
 | 
			
		||||
 | 
			
		||||
        doc.children << scalar
 | 
			
		||||
        s.children << doc
 | 
			
		||||
 | 
			
		||||
        @visitor.accept s
 | 
			
		||||
 | 
			
		||||
        assert_match(/hello/, @io.string)
 | 
			
		||||
        assert_equal @io.string, s.to_yaml
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_scalar_with_tag
 | 
			
		||||
        s       = Nodes::Stream.new
 | 
			
		||||
        doc     = Nodes::Document.new
 | 
			
		||||
        scalar  = Nodes::Scalar.new 'hello world', nil, '!str', false, false, 5
 | 
			
		||||
 | 
			
		||||
        doc.children << scalar
 | 
			
		||||
        s.children << doc
 | 
			
		||||
 | 
			
		||||
        @visitor.accept s
 | 
			
		||||
 | 
			
		||||
        assert_match(/str/, @io.string)
 | 
			
		||||
        assert_match(/hello/, @io.string)
 | 
			
		||||
        assert_equal @io.string, s.to_yaml
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_sequence
 | 
			
		||||
        s       = Nodes::Stream.new
 | 
			
		||||
        doc     = Nodes::Document.new
 | 
			
		||||
        scalar  = Nodes::Scalar.new 'hello world'
 | 
			
		||||
        seq     = Nodes::Sequence.new
 | 
			
		||||
 | 
			
		||||
        seq.children << scalar
 | 
			
		||||
        doc.children << seq
 | 
			
		||||
        s.children << doc
 | 
			
		||||
 | 
			
		||||
        @visitor.accept s
 | 
			
		||||
 | 
			
		||||
        assert_match(/- hello/, @io.string)
 | 
			
		||||
        assert_equal @io.string, s.to_yaml
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_mapping
 | 
			
		||||
        s       = Nodes::Stream.new
 | 
			
		||||
        doc     = Nodes::Document.new
 | 
			
		||||
        mapping = Nodes::Mapping.new
 | 
			
		||||
        mapping.children << Nodes::Scalar.new('key')
 | 
			
		||||
        mapping.children << Nodes::Scalar.new('value')
 | 
			
		||||
        doc.children << mapping
 | 
			
		||||
        s.children << doc
 | 
			
		||||
 | 
			
		||||
        @visitor.accept s
 | 
			
		||||
 | 
			
		||||
        assert_match(/key: value/, @io.string)
 | 
			
		||||
        assert_equal @io.string, s.to_yaml
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_alias
 | 
			
		||||
        s       = Nodes::Stream.new
 | 
			
		||||
        doc     = Nodes::Document.new
 | 
			
		||||
        mapping = Nodes::Mapping.new
 | 
			
		||||
        mapping.children << Nodes::Scalar.new('key', 'A')
 | 
			
		||||
        mapping.children << Nodes::Alias.new('A')
 | 
			
		||||
        doc.children << mapping
 | 
			
		||||
        s.children << doc
 | 
			
		||||
 | 
			
		||||
        @visitor.accept s
 | 
			
		||||
 | 
			
		||||
        assert_match(/&A key: \*A/, @io.string)
 | 
			
		||||
        assert_equal @io.string, s.to_yaml
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										323
									
								
								test/psych/visitors/test_to_ruby.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										323
									
								
								test/psych/visitors/test_to_ruby.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,323 @@
 | 
			
		|||
require 'test/psych/helper'
 | 
			
		||||
 | 
			
		||||
module Psych
 | 
			
		||||
  module Visitors
 | 
			
		||||
    class TestToRuby < TestCase
 | 
			
		||||
      def setup
 | 
			
		||||
        super
 | 
			
		||||
        @visitor = ToRuby.new
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_object
 | 
			
		||||
        mapping = Nodes::Mapping.new nil, "!ruby/object"
 | 
			
		||||
        mapping.children << Nodes::Scalar.new('foo')
 | 
			
		||||
        mapping.children << Nodes::Scalar.new('bar')
 | 
			
		||||
 | 
			
		||||
        o = mapping.to_ruby
 | 
			
		||||
        assert_equal 'bar', o.instance_variable_get(:@foo)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_awesome
 | 
			
		||||
        Psych.load('1900-01-01T00:00:00+00:00')
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_legacy_struct
 | 
			
		||||
        foo = Struct.new('AWESOME', :bar)
 | 
			
		||||
        assert_equal foo.new('baz'), Psych.load(<<-eoyml)
 | 
			
		||||
!ruby/struct:AWESOME
 | 
			
		||||
  bar: baz
 | 
			
		||||
        eoyml
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_binary
 | 
			
		||||
        gif = "GIF89a\f\x00\f\x00\x84\x00\x00\xFF\xFF\xF7\xF5\xF5\xEE\xE9\xE9\xE5fff\x00\x00\x00\xE7\xE7\xE7^^^\xF3\xF3\xED\x8E\x8E\x8E\xE0\xE0\xE0\x9F\x9F\x9F\x93\x93\x93\xA7\xA7\xA7\x9E\x9E\x9Eiiiccc\xA3\xA3\xA3\x84\x84\x84\xFF\xFE\xF9\xFF\xFE\xF9\xFF\xFE\xF9\xFF\xFE\xF9\xFF\xFE\xF9\xFF\xFE\xF9\xFF\xFE\xF9\xFF\xFE\xF9\xFF\xFE\xF9\xFF\xFE\xF9\xFF\xFE\xF9\xFF\xFE\xF9\xFF\xFE\xF9\xFF\xFE\xF9!\xFE\x0EMade with GIMP\x00,\x00\x00\x00\x00\f\x00\f\x00\x00\x05,  \x8E\x810\x9E\xE3@\x14\xE8i\x10\xC4\xD1\x8A\b\x1C\xCF\x80M$z\xEF\xFF0\x85p\xB8\xB01f\r\e\xCE\x01\xC3\x01\x1E\x10' \x82\n\x01\x00;"
 | 
			
		||||
 | 
			
		||||
        hash = Psych.load(<<-'eoyaml')
 | 
			
		||||
canonical: !!binary "\
 | 
			
		||||
 R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5\
 | 
			
		||||
 OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+\
 | 
			
		||||
 +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC\
 | 
			
		||||
 AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs="
 | 
			
		||||
generic: !binary |
 | 
			
		||||
 R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5
 | 
			
		||||
 OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+
 | 
			
		||||
 +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC
 | 
			
		||||
 AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs=
 | 
			
		||||
description:
 | 
			
		||||
 The binary value above is a tiny arrow encoded as a gif image.
 | 
			
		||||
        eoyaml
 | 
			
		||||
        assert_equal gif, hash['canonical']
 | 
			
		||||
        assert_equal gif, hash['generic']
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      A = Struct.new(:foo)
 | 
			
		||||
 | 
			
		||||
      def test_struct
 | 
			
		||||
        s = A.new('bar')
 | 
			
		||||
 | 
			
		||||
        mapping = Nodes::Mapping.new nil, "!ruby/struct:#{s.class}"
 | 
			
		||||
        mapping.children << Nodes::Scalar.new('foo')
 | 
			
		||||
        mapping.children << Nodes::Scalar.new('bar')
 | 
			
		||||
 | 
			
		||||
        ruby = mapping.to_ruby
 | 
			
		||||
 | 
			
		||||
        assert_equal s.class, ruby.class
 | 
			
		||||
        assert_equal s.foo, ruby.foo
 | 
			
		||||
        assert_equal s, ruby
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_anon_struct_legacy
 | 
			
		||||
        s = Struct.new(:foo).new('bar')
 | 
			
		||||
 | 
			
		||||
        mapping = Nodes::Mapping.new nil, '!ruby/struct:'
 | 
			
		||||
        mapping.children << Nodes::Scalar.new('foo')
 | 
			
		||||
        mapping.children << Nodes::Scalar.new('bar')
 | 
			
		||||
 | 
			
		||||
        assert_equal s.foo, mapping.to_ruby.foo
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_anon_struct
 | 
			
		||||
        s = Struct.new(:foo).new('bar')
 | 
			
		||||
 | 
			
		||||
        mapping = Nodes::Mapping.new nil, '!ruby/struct'
 | 
			
		||||
        mapping.children << Nodes::Scalar.new('foo')
 | 
			
		||||
        mapping.children << Nodes::Scalar.new('bar')
 | 
			
		||||
 | 
			
		||||
        assert_equal s.foo, mapping.to_ruby.foo
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_exception
 | 
			
		||||
        exc = Exception.new 'hello'
 | 
			
		||||
 | 
			
		||||
        mapping = Nodes::Mapping.new nil, '!ruby/exception'
 | 
			
		||||
        mapping.children << Nodes::Scalar.new('message')
 | 
			
		||||
        mapping.children << Nodes::Scalar.new('hello')
 | 
			
		||||
 | 
			
		||||
        ruby = mapping.to_ruby
 | 
			
		||||
 | 
			
		||||
        assert_equal exc.class, ruby.class
 | 
			
		||||
        assert_equal exc.message, ruby.message
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_regexp
 | 
			
		||||
        node = Nodes::Scalar.new('/foo/', nil, '!ruby/regexp')
 | 
			
		||||
        assert_equal(/foo/, node.to_ruby)
 | 
			
		||||
 | 
			
		||||
        node = Nodes::Scalar.new('/foo/m', nil, '!ruby/regexp')
 | 
			
		||||
        assert_equal(/foo/m, node.to_ruby)
 | 
			
		||||
 | 
			
		||||
        node = Nodes::Scalar.new('/foo/ix', nil, '!ruby/regexp')
 | 
			
		||||
        assert_equal(/foo/ix, node.to_ruby)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_time
 | 
			
		||||
        now = Time.now
 | 
			
		||||
        formatted = now.strftime("%Y-%m-%d %H:%M:%S") +
 | 
			
		||||
          ".%06d %+.2d:00" % [now.usec, now.gmt_offset / 3600]
 | 
			
		||||
 | 
			
		||||
        assert_equal now, Nodes::Scalar.new(formatted).to_ruby
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_time_utc
 | 
			
		||||
        now = Time.now.utc
 | 
			
		||||
        formatted = now.strftime("%Y-%m-%d %H:%M:%S") +
 | 
			
		||||
          ".%06dZ" % [now.usec]
 | 
			
		||||
 | 
			
		||||
        assert_equal now, Nodes::Scalar.new(formatted).to_ruby
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_time_utc_no_z
 | 
			
		||||
        now = Time.now.utc
 | 
			
		||||
        formatted = now.strftime("%Y-%m-%d %H:%M:%S") +
 | 
			
		||||
          ".%06d" % [now.usec]
 | 
			
		||||
 | 
			
		||||
        assert_equal now, Nodes::Scalar.new(formatted).to_ruby
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_date
 | 
			
		||||
        d = '1980-12-16'
 | 
			
		||||
        actual = Date.strptime(d, '%Y-%m-%d')
 | 
			
		||||
 | 
			
		||||
        date = Nodes::Scalar.new(d, nil, 'tag:yaml.org,2002:timestamp', false)
 | 
			
		||||
 | 
			
		||||
        assert_equal actual, date.to_ruby
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_rational
 | 
			
		||||
        mapping = Nodes::Mapping.new nil, '!ruby/object:Rational'
 | 
			
		||||
        mapping.children << Nodes::Scalar.new('denominator')
 | 
			
		||||
        mapping.children << Nodes::Scalar.new('2')
 | 
			
		||||
        mapping.children << Nodes::Scalar.new('numerator')
 | 
			
		||||
        mapping.children << Nodes::Scalar.new('1')
 | 
			
		||||
 | 
			
		||||
        assert_equal Rational(1,2), mapping.to_ruby
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_complex
 | 
			
		||||
        mapping = Nodes::Mapping.new nil, '!ruby/object:Complex'
 | 
			
		||||
        mapping.children << Nodes::Scalar.new('image')
 | 
			
		||||
        mapping.children << Nodes::Scalar.new('2')
 | 
			
		||||
        mapping.children << Nodes::Scalar.new('real')
 | 
			
		||||
        mapping.children << Nodes::Scalar.new('1')
 | 
			
		||||
 | 
			
		||||
        assert_equal Complex(1,2), mapping.to_ruby
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      if RUBY_VERSION >= '1.9'
 | 
			
		||||
        def test_complex_string
 | 
			
		||||
          node = Nodes::Scalar.new '3+4i', nil, "!ruby/object:Complex"
 | 
			
		||||
          assert_equal Complex(3, 4), node.to_ruby
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def test_rational_string
 | 
			
		||||
          node = Nodes::Scalar.new '1/2', nil, "!ruby/object:Rational"
 | 
			
		||||
          assert_equal Rational(1, 2), node.to_ruby
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_range_string
 | 
			
		||||
        node = Nodes::Scalar.new '1..2', nil, "!ruby/range"
 | 
			
		||||
        assert_equal 1..2, node.to_ruby
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_range_string_triple
 | 
			
		||||
        node = Nodes::Scalar.new '1...3', nil, "!ruby/range"
 | 
			
		||||
        assert_equal 1...3, node.to_ruby
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_integer
 | 
			
		||||
        i = Nodes::Scalar.new('1', nil, 'tag:yaml.org,2002:int')
 | 
			
		||||
        assert_equal 1, i.to_ruby
 | 
			
		||||
 | 
			
		||||
        assert_equal 1, Nodes::Scalar.new('1').to_ruby
 | 
			
		||||
 | 
			
		||||
        i = Nodes::Scalar.new('-1', nil, 'tag:yaml.org,2002:int')
 | 
			
		||||
        assert_equal(-1, i.to_ruby)
 | 
			
		||||
 | 
			
		||||
        assert_equal(-1, Nodes::Scalar.new('-1').to_ruby)
 | 
			
		||||
        assert_equal 1, Nodes::Scalar.new('+1').to_ruby
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_int_ignore
 | 
			
		||||
        ['1,000', '1_000'].each do |num|
 | 
			
		||||
          i = Nodes::Scalar.new(num, nil, 'tag:yaml.org,2002:int')
 | 
			
		||||
          assert_equal 1000, i.to_ruby
 | 
			
		||||
 | 
			
		||||
          assert_equal 1000, Nodes::Scalar.new(num).to_ruby
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_float_ignore
 | 
			
		||||
        ['1,000.3', '1_000.3'].each do |num|
 | 
			
		||||
          i = Nodes::Scalar.new(num, nil, 'tag:yaml.org,2002:float')
 | 
			
		||||
          assert_equal 1000.3, i.to_ruby
 | 
			
		||||
 | 
			
		||||
          i = Nodes::Scalar.new(num, nil, '!float')
 | 
			
		||||
          assert_equal 1000.3, i.to_ruby
 | 
			
		||||
 | 
			
		||||
          assert_equal 1000.3, Nodes::Scalar.new(num).to_ruby
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # http://yaml.org/type/bool.html
 | 
			
		||||
      def test_boolean_true
 | 
			
		||||
        %w{ yes Yes YES true True TRUE on On ON }.each do |t|
 | 
			
		||||
          i = Nodes::Scalar.new(t, nil, 'tag:yaml.org,2002:bool')
 | 
			
		||||
          assert_equal true, i.to_ruby
 | 
			
		||||
          assert_equal true, Nodes::Scalar.new(t).to_ruby
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # http://yaml.org/type/bool.html
 | 
			
		||||
      def test_boolean_false
 | 
			
		||||
        %w{ no No NO false False FALSE off Off OFF }.each do |t|
 | 
			
		||||
          i = Nodes::Scalar.new(t, nil, 'tag:yaml.org,2002:bool')
 | 
			
		||||
          assert_equal false, i.to_ruby
 | 
			
		||||
          assert_equal false, Nodes::Scalar.new(t).to_ruby
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_float
 | 
			
		||||
        i = Nodes::Scalar.new('12', nil, 'tag:yaml.org,2002:float')
 | 
			
		||||
        assert_equal 12.0, i.to_ruby
 | 
			
		||||
 | 
			
		||||
        i = Nodes::Scalar.new('1.2', nil, 'tag:yaml.org,2002:float')
 | 
			
		||||
        assert_equal 1.2, i.to_ruby
 | 
			
		||||
 | 
			
		||||
        i = Nodes::Scalar.new('1.2')
 | 
			
		||||
        assert_equal 1.2, i.to_ruby
 | 
			
		||||
 | 
			
		||||
        assert_equal 1, Nodes::Scalar.new('.Inf').to_ruby.infinite?
 | 
			
		||||
        assert_equal 1, Nodes::Scalar.new('.inf').to_ruby.infinite?
 | 
			
		||||
        assert_equal 1, Nodes::Scalar.new('.Inf', nil, 'tag:yaml.org,2002:float').to_ruby.infinite?
 | 
			
		||||
 | 
			
		||||
        assert_equal(-1, Nodes::Scalar.new('-.inf').to_ruby.infinite?)
 | 
			
		||||
        assert_equal(-1, Nodes::Scalar.new('-.Inf').to_ruby.infinite?)
 | 
			
		||||
        assert_equal(-1, Nodes::Scalar.new('-.Inf', nil, 'tag:yaml.org,2002:float').to_ruby.infinite?)
 | 
			
		||||
 | 
			
		||||
        assert Nodes::Scalar.new('.NaN').to_ruby.nan?
 | 
			
		||||
        assert Nodes::Scalar.new('.NaN', nil, 'tag:yaml.org,2002:float').to_ruby.nan?
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_exp_float
 | 
			
		||||
        exp = 1.2e+30
 | 
			
		||||
 | 
			
		||||
        i = Nodes::Scalar.new(exp.to_s, nil, 'tag:yaml.org,2002:float')
 | 
			
		||||
        assert_equal exp, i.to_ruby
 | 
			
		||||
 | 
			
		||||
        assert_equal exp, Nodes::Scalar.new(exp.to_s).to_ruby
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_scalar
 | 
			
		||||
        scalar = Nodes::Scalar.new('foo')
 | 
			
		||||
        assert_equal 'foo', @visitor.accept(scalar)
 | 
			
		||||
        assert_equal 'foo', scalar.to_ruby
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_sequence
 | 
			
		||||
        seq = Nodes::Sequence.new
 | 
			
		||||
        seq.children << Nodes::Scalar.new('foo')
 | 
			
		||||
        seq.children << Nodes::Scalar.new('bar')
 | 
			
		||||
 | 
			
		||||
        assert_equal %w{ foo bar }, seq.to_ruby
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_mapping
 | 
			
		||||
        mapping = Nodes::Mapping.new
 | 
			
		||||
        mapping.children << Nodes::Scalar.new('foo')
 | 
			
		||||
        mapping.children << Nodes::Scalar.new('bar')
 | 
			
		||||
        assert_equal({'foo' => 'bar'}, mapping.to_ruby)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_document
 | 
			
		||||
        doc = Nodes::Document.new
 | 
			
		||||
        doc.children << Nodes::Scalar.new('foo')
 | 
			
		||||
        assert_equal 'foo', doc.to_ruby
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_stream
 | 
			
		||||
        a = Nodes::Document.new
 | 
			
		||||
        a.children << Nodes::Scalar.new('foo')
 | 
			
		||||
 | 
			
		||||
        b = Nodes::Document.new
 | 
			
		||||
        b.children << Nodes::Scalar.new('bar')
 | 
			
		||||
 | 
			
		||||
        stream = Nodes::Stream.new
 | 
			
		||||
        stream.children << a
 | 
			
		||||
        stream.children << b
 | 
			
		||||
 | 
			
		||||
        assert_equal %w{ foo bar }, stream.to_ruby
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_alias
 | 
			
		||||
        seq = Nodes::Sequence.new
 | 
			
		||||
        seq.children << Nodes::Scalar.new('foo', 'A')
 | 
			
		||||
        seq.children << Nodes::Alias.new('A')
 | 
			
		||||
 | 
			
		||||
        list = seq.to_ruby
 | 
			
		||||
        assert_equal %w{ foo foo }, list
 | 
			
		||||
        assert_equal list[0].object_id, list[1].object_id
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										140
									
								
								test/psych/visitors/test_yaml_tree.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								test/psych/visitors/test_yaml_tree.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,140 @@
 | 
			
		|||
require 'test/psych/helper'
 | 
			
		||||
 | 
			
		||||
module Psych
 | 
			
		||||
  module Visitors
 | 
			
		||||
    class TestYAMLTree < TestCase
 | 
			
		||||
      def setup
 | 
			
		||||
        super
 | 
			
		||||
        @v = Visitors::YAMLTree.new
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_object_has_no_class
 | 
			
		||||
        yaml = Psych.dump(Object.new)
 | 
			
		||||
        assert(Psych.dump(Object.new) !~ /Object/, yaml)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_struct_const
 | 
			
		||||
        foo = Struct.new("Foo", :bar)
 | 
			
		||||
        assert_cycle foo.new('bar')
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      A = Struct.new(:foo)
 | 
			
		||||
 | 
			
		||||
      def test_struct
 | 
			
		||||
        assert_cycle A.new('bar')
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_struct_anon
 | 
			
		||||
        s = Struct.new(:foo).new('bar')
 | 
			
		||||
        obj =  Psych.load(Psych.dump(s))
 | 
			
		||||
        assert_equal s.foo, obj.foo
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_exception
 | 
			
		||||
        ex = Exception.new 'foo'
 | 
			
		||||
        loaded = Psych.load(Psych.dump(ex))
 | 
			
		||||
 | 
			
		||||
        assert_equal ex.message, loaded.message
 | 
			
		||||
        assert_equal ex.class, loaded.class
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_regexp
 | 
			
		||||
        assert_cycle(/foo/)
 | 
			
		||||
        assert_cycle(/foo/i)
 | 
			
		||||
        assert_cycle(/foo/mx)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_time
 | 
			
		||||
        assert_cycle Time.now
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_date
 | 
			
		||||
        date = Date.strptime('2002-12-14', '%Y-%m-%d')
 | 
			
		||||
        assert_cycle date
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_rational
 | 
			
		||||
        assert_cycle Rational(1,2)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_complex
 | 
			
		||||
        assert_cycle Complex(1,2)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_scalar
 | 
			
		||||
        assert_cycle 'foo'
 | 
			
		||||
        assert_cycle ':foo'
 | 
			
		||||
        assert_cycle ''
 | 
			
		||||
        assert_cycle ':'
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_boolean
 | 
			
		||||
        assert_cycle true
 | 
			
		||||
        assert_cycle 'true'
 | 
			
		||||
        assert_cycle false
 | 
			
		||||
        assert_cycle 'false'
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_range_inclusive
 | 
			
		||||
        assert_cycle 1..2
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_range_exclusive
 | 
			
		||||
        assert_cycle 1...2
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_anon_class
 | 
			
		||||
        assert_raises(TypeError) do
 | 
			
		||||
          @v.accept Class.new
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        assert_raises(TypeError) do
 | 
			
		||||
          Psych.dump(Class.new)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_hash
 | 
			
		||||
        assert_cycle('a' => 'b')
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_list
 | 
			
		||||
        assert_cycle(%w{ a b })
 | 
			
		||||
        assert_cycle([1, 2.2])
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_symbol
 | 
			
		||||
        assert_cycle :foo
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_int
 | 
			
		||||
        assert_cycle 1
 | 
			
		||||
        assert_cycle(-1)
 | 
			
		||||
        assert_cycle '1'
 | 
			
		||||
        assert_cycle '-1'
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_float
 | 
			
		||||
        assert_cycle 1.2
 | 
			
		||||
        assert_cycle '1.2'
 | 
			
		||||
 | 
			
		||||
        assert Psych.load(Psych.dump(0.0 / 0.0)).nan?
 | 
			
		||||
        assert_equal 1, Psych.load(Psych.dump(1 / 0.0)).infinite?
 | 
			
		||||
        assert_equal(-1, Psych.load(Psych.dump(-1 / 0.0)).infinite?)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # http://yaml.org/type/null.html
 | 
			
		||||
      def test_nil
 | 
			
		||||
        assert_cycle nil
 | 
			
		||||
        assert_equal nil, Psych.load('null')
 | 
			
		||||
        assert_equal nil, Psych.load('Null')
 | 
			
		||||
        assert_equal nil, Psych.load('NULL')
 | 
			
		||||
        assert_equal nil, Psych.load('~')
 | 
			
		||||
        assert_equal({'foo' => nil}, Psych.load('foo: '))
 | 
			
		||||
 | 
			
		||||
        assert_cycle 'null'
 | 
			
		||||
        assert_cycle 'nUll'
 | 
			
		||||
        assert_cycle '~'
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue