summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/psych/emitter.c56
-rw-r--r--ext/psych/emitter.h8
-rw-r--r--ext/psych/psych.c1
-rw-r--r--ext/psych/psych.h1
-rw-r--r--lib/psych/emitter.rb4
-rw-r--r--lib/psych/visitors.rb1
-rw-r--r--lib/psych/visitors/emitter.rb15
7 files changed, 86 insertions, 0 deletions
diff --git a/ext/psych/emitter.c b/ext/psych/emitter.c
new file mode 100644
index 0000000..c48a8b5
--- /dev/null
+++ b/ext/psych/emitter.c
@@ -0,0 +1,56 @@
+#include <psych.h>
+
+VALUE cPsychEmitter;
+
+static int writer(void *ctx, unsigned char *buffer, size_t size)
+{
+ VALUE io = (VALUE)ctx;
+ VALUE str = rb_str_new(buffer, size);
+ VALUE wrote = rb_funcall(io, rb_intern("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);
+ Data_Wrap_Struct(cPsychEmitter, 0, dealloc, emitter);
+}
+
+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;
+}
+
+static VALUE start_stream(VALUE self, VALUE encoding)
+{
+ yaml_emitter_t * emitter;
+ Data_Get_Struct(self, yaml_emitter_t, emitter);
+
+ yaml_event_t event;
+ yaml_stream_start_event_initialize(&event, NUM2INT(encoding));
+ return self;
+}
+
+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);
+}
diff --git a/ext/psych/emitter.h b/ext/psych/emitter.h
new file mode 100644
index 0000000..560451e
--- /dev/null
+++ b/ext/psych/emitter.h
@@ -0,0 +1,8 @@
+#ifndef PSYCH_EMITTER_H
+#define PSYCH_EMITTER_H
+
+#include <psych.h>
+
+void Init_psych_emitter();
+
+#endif
diff --git a/ext/psych/psych.c b/ext/psych/psych.c
index dfba7eb..9d40fe3 100644
--- a/ext/psych/psych.c
+++ b/ext/psych/psych.c
@@ -24,4 +24,5 @@ void Init_psych()
rb_define_singleton_method(mPsych, "libyaml_version", libyaml_version, 0);
Init_psych_parser();
+ Init_psych_emitter();
}
diff --git a/ext/psych/psych.h b/ext/psych/psych.h
index 656bc73..eea82f8 100644
--- a/ext/psych/psych.h
+++ b/ext/psych/psych.h
@@ -5,6 +5,7 @@
#include <yaml.h>
#include <parser.h>
+#include <emitter.h>
extern VALUE mPsych;
diff --git a/lib/psych/emitter.rb b/lib/psych/emitter.rb
new file mode 100644
index 0000000..b06ad3a
--- /dev/null
+++ b/lib/psych/emitter.rb
@@ -0,0 +1,4 @@
+module Psych
+ class Emitter < Psych::Handler
+ end
+end
diff --git a/lib/psych/visitors.rb b/lib/psych/visitors.rb
index 45b4b58..df58e2e 100644
--- a/lib/psych/visitors.rb
+++ b/lib/psych/visitors.rb
@@ -1,2 +1,3 @@
require 'psych/visitors/visitor'
require 'psych/visitors/to_ruby'
+require 'psych/visitors/emitter'
diff --git a/lib/psych/visitors/emitter.rb b/lib/psych/visitors/emitter.rb
new file mode 100644
index 0000000..ff3832b
--- /dev/null
+++ b/lib/psych/visitors/emitter.rb
@@ -0,0 +1,15 @@
+module Psych
+ module Visitors
+ class Emitter < Psych::Visitors::Visitor
+ def initialize io
+ @handler = Psych::Emitter.new io
+ end
+
+ visitor_for(Nodes::Stream) do |o|
+ @handler.start_stream o.encoding
+ o.children.each { |c| c.accept self }
+ @handler.end_stream
+ end
+ end
+ end
+end