From b9b923ca942096ddb1062be2deb9e6de9a65f346 Mon Sep 17 00:00:00 2001 From: tenderlove Date: Sun, 28 Mar 2010 21:49:37 +0000 Subject: * 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 --- ext/psych/emitter.c | 413 ++++++++++++++++++++++++++++++++++++++++++++++++++ ext/psych/emitter.h | 8 + ext/psych/extconf.rb | 22 +++ ext/psych/parser.c | 314 ++++++++++++++++++++++++++++++++++++++ ext/psych/parser.h | 6 + ext/psych/psych.c | 35 +++++ ext/psych/psych.h | 20 +++ ext/psych/to_ruby.c | 41 +++++ ext/psych/to_ruby.h | 8 + ext/psych/yaml_tree.c | 24 +++ ext/psych/yaml_tree.h | 8 + 11 files changed, 899 insertions(+) create mode 100644 ext/psych/emitter.c create mode 100644 ext/psych/emitter.h create mode 100644 ext/psych/extconf.rb create mode 100644 ext/psych/parser.c create mode 100644 ext/psych/parser.h create mode 100644 ext/psych/psych.c create mode 100644 ext/psych/psych.h create mode 100644 ext/psych/to_ruby.c create mode 100644 ext/psych/to_ruby.h create mode 100644 ext/psych/yaml_tree.c create mode 100644 ext/psych/yaml_tree.h (limited to 'ext') diff --git a/ext/psych/emitter.c b/ext/psych/emitter.c new file mode 100644 index 0000000000..74f91f22bc --- /dev/null +++ b/ext/psych/emitter.c @@ -0,0 +1,413 @@ +#include + +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: */ diff --git a/ext/psych/emitter.h b/ext/psych/emitter.h new file mode 100644 index 0000000000..560451ef31 --- /dev/null +++ b/ext/psych/emitter.h @@ -0,0 +1,8 @@ +#ifndef PSYCH_EMITTER_H +#define PSYCH_EMITTER_H + +#include + +void Init_psych_emitter(); + +#endif diff --git a/ext/psych/extconf.rb b/ext/psych/extconf.rb new file mode 100644 index 0000000000..673b950a63 --- /dev/null +++ b/ext/psych/extconf.rb @@ -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: diff --git a/ext/psych/parser.c b/ext/psych/parser.c new file mode 100644 index 0000000000..2bad49fc70 --- /dev/null +++ b/ext/psych/parser.c @@ -0,0 +1,314 @@ +#include + +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: */ diff --git a/ext/psych/parser.h b/ext/psych/parser.h new file mode 100644 index 0000000000..25e896f01d --- /dev/null +++ b/ext/psych/parser.h @@ -0,0 +1,6 @@ +#ifndef PSYCH_PARSER_H +#define PSYCH_PARSER_H + +void Init_psych_parser(); + +#endif diff --git a/ext/psych/psych.c b/ext/psych/psych.c new file mode 100644 index 0000000000..ff035af705 --- /dev/null +++ b/ext/psych/psych.c @@ -0,0 +1,35 @@ +#include + +/* 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: */ diff --git a/ext/psych/psych.h b/ext/psych/psych.h new file mode 100644 index 0000000000..9f1be449a2 --- /dev/null +++ b/ext/psych/psych.h @@ -0,0 +1,20 @@ +#ifndef PSYCH_H +#define PSYCH_H + +#include + +#ifdef HAVE_RUBY_ENCODING_H +#include +#endif + +#include + +#include +#include +#include +#include + +extern VALUE mPsych; + + +#endif diff --git a/ext/psych/to_ruby.c b/ext/psych/to_ruby.c new file mode 100644 index 0000000000..ed5245e12e --- /dev/null +++ b/ext/psych/to_ruby.c @@ -0,0 +1,41 @@ +#include + +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: */ diff --git a/ext/psych/to_ruby.h b/ext/psych/to_ruby.h new file mode 100644 index 0000000000..7b8e757a45 --- /dev/null +++ b/ext/psych/to_ruby.h @@ -0,0 +1,8 @@ +#ifndef PSYCH_TO_RUBY_H +#define PSYCH_TO_RUBY_H + +#include + +void Init_psych_to_ruby(void); + +#endif diff --git a/ext/psych/yaml_tree.c b/ext/psych/yaml_tree.c new file mode 100644 index 0000000000..bcf24d2070 --- /dev/null +++ b/ext/psych/yaml_tree.c @@ -0,0 +1,24 @@ +#include + +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: */ diff --git a/ext/psych/yaml_tree.h b/ext/psych/yaml_tree.h new file mode 100644 index 0000000000..4628a69d71 --- /dev/null +++ b/ext/psych/yaml_tree.h @@ -0,0 +1,8 @@ +#ifndef PSYCH_YAML_TREE_H +#define PSYCH_YAML_TREE_H + +#include + +void Init_psych_yaml_tree(void); + +#endif -- cgit v1.2.3