• Main Page
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

ext/psych/emitter.c

Go to the documentation of this file.
00001 #include <psych.h>
00002 
00003 VALUE cPsychEmitter;
00004 static ID id_write;
00005 
00006 static void emit(yaml_emitter_t * emitter, yaml_event_t * event)
00007 {
00008     if(!yaml_emitter_emit(emitter, event))
00009         rb_raise(rb_eRuntimeError, "%s", emitter->problem);
00010 }
00011 
00012 static int writer(void *ctx, unsigned char *buffer, size_t size)
00013 {
00014     VALUE io = (VALUE)ctx;
00015     VALUE str = rb_str_new((const char *)buffer, (long)size);
00016     VALUE wrote = rb_funcall(io, id_write, 1, str);
00017     return (int)NUM2INT(wrote);
00018 }
00019 
00020 static void dealloc(yaml_emitter_t * emitter)
00021 {
00022     yaml_emitter_delete(emitter);
00023     free(emitter);
00024 }
00025 
00026 static VALUE allocate(VALUE klass)
00027 {
00028     yaml_emitter_t * emitter = malloc(sizeof(yaml_emitter_t));
00029     yaml_emitter_initialize(emitter);
00030     yaml_emitter_set_unicode(emitter, 1);
00031     yaml_emitter_set_indent(emitter, 2);
00032 
00033     return Data_Wrap_Struct(klass, 0, dealloc, emitter);
00034 }
00035 
00036 /* call-seq: Psych::Emitter.new(io)
00037  *
00038  * Create a new Psych::Emitter that writes to +io+.
00039  */
00040 static VALUE initialize(VALUE self, VALUE io)
00041 {
00042     yaml_emitter_t * emitter;
00043     Data_Get_Struct(self, yaml_emitter_t, emitter);
00044 
00045     yaml_emitter_set_output(emitter, writer, (void *)io);
00046 
00047     return self;
00048 }
00049 
00050 /* call-seq: emitter.start_stream(encoding)
00051  *
00052  * Start a stream emission with +encoding+
00053  *
00054  * See Psych::Handler#start_stream
00055  */
00056 static VALUE start_stream(VALUE self, VALUE encoding)
00057 {
00058     yaml_emitter_t * emitter;
00059     yaml_event_t event;
00060     Data_Get_Struct(self, yaml_emitter_t, emitter);
00061     Check_Type(encoding, T_FIXNUM);
00062 
00063     yaml_stream_start_event_initialize(&event, (yaml_encoding_t)NUM2INT(encoding));
00064 
00065     emit(emitter, &event);
00066 
00067     return self;
00068 }
00069 
00070 /* call-seq: emitter.end_stream
00071  *
00072  * End a stream emission
00073  *
00074  * See Psych::Handler#end_stream
00075  */
00076 static VALUE end_stream(VALUE self)
00077 {
00078     yaml_emitter_t * emitter;
00079     yaml_event_t event;
00080     Data_Get_Struct(self, yaml_emitter_t, emitter);
00081 
00082     yaml_stream_end_event_initialize(&event);
00083 
00084     emit(emitter, &event);
00085 
00086     return self;
00087 }
00088 
00089 /* call-seq: emitter.start_document(version, tags, implicit)
00090  *
00091  * Start a document emission with YAML +version+, +tags+, and an +implicit+
00092  * start.
00093  *
00094  * See Psych::Handler#start_document
00095  */
00096 static VALUE start_document(VALUE self, VALUE version, VALUE tags, VALUE imp)
00097 {
00098     yaml_emitter_t * emitter;
00099     yaml_tag_directive_t * head = NULL;
00100     yaml_tag_directive_t * tail = NULL;
00101     yaml_event_t event;
00102     yaml_version_directive_t version_directive;
00103     Data_Get_Struct(self, yaml_emitter_t, emitter);
00104 
00105 
00106     Check_Type(version, T_ARRAY);
00107 
00108     if(RARRAY_LEN(version) > 0) {
00109         VALUE major = rb_ary_entry(version, (long)0);
00110         VALUE minor = rb_ary_entry(version, (long)1);
00111 
00112         version_directive.major = NUM2INT(major);
00113         version_directive.minor = NUM2INT(minor);
00114     }
00115 
00116     if(RTEST(tags)) {
00117         int i = 0;
00118 
00119         Check_Type(tags, T_ARRAY);
00120 
00121         head  = xcalloc((size_t)RARRAY_LEN(tags), sizeof(yaml_tag_directive_t));
00122         tail  = head;
00123 
00124         for(i = 0; i < RARRAY_LEN(tags); i++) {
00125             VALUE tuple = RARRAY_PTR(tags)[i];
00126             Check_Type(tuple, T_ARRAY);
00127 
00128             if(RARRAY_LEN(tuple) < 2) {
00129                 xfree(head);
00130                 rb_raise(rb_eRuntimeError, "tag tuple must be of length 2");
00131             }
00132 
00133             tail->handle = (yaml_char_t *)StringValuePtr(RARRAY_PTR(tuple)[0]);
00134             tail->prefix = (yaml_char_t *)StringValuePtr(RARRAY_PTR(tuple)[1]);
00135 
00136             tail++;
00137         }
00138     }
00139 
00140     yaml_document_start_event_initialize(
00141             &event,
00142             (RARRAY_LEN(version) > 0) ? &version_directive : NULL,
00143             head,
00144             tail,
00145             imp ? 1 : 0
00146             );
00147 
00148     emit(emitter, &event);
00149 
00150     if(head) xfree(head);
00151 
00152     return self;
00153 }
00154 
00155 /* call-seq: emitter.end_document(implicit)
00156  *
00157  * End a document emission with an +implicit+ ending.
00158  *
00159  * See Psych::Handler#end_document
00160  */
00161 static VALUE end_document(VALUE self, VALUE imp)
00162 {
00163     yaml_emitter_t * emitter;
00164     yaml_event_t event;
00165     Data_Get_Struct(self, yaml_emitter_t, emitter);
00166 
00167     yaml_document_end_event_initialize(&event, imp ? 1 : 0);
00168 
00169     emit(emitter, &event);
00170 
00171     return self;
00172 }
00173 
00174 /* call-seq: emitter.scalar(value, anchor, tag, plain, quoted, style)
00175  *
00176  * Emit a scalar with +value+, +anchor+, +tag+, and a +plain+ or +quoted+
00177  * string type with +style+.
00178  *
00179  * See Psych::Handler#scalar
00180  */
00181 static VALUE scalar(
00182         VALUE self,
00183         VALUE value,
00184         VALUE anchor,
00185         VALUE tag,
00186         VALUE plain,
00187         VALUE quoted,
00188         VALUE style
00189         ) {
00190     yaml_emitter_t * emitter;
00191     yaml_event_t event;
00192     Data_Get_Struct(self, yaml_emitter_t, emitter);
00193 
00194     Check_Type(value, T_STRING);
00195 
00196     yaml_scalar_event_initialize(
00197             &event,
00198             (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValuePtr(anchor)),
00199             (yaml_char_t *)(NIL_P(tag) ? NULL : StringValuePtr(tag)),
00200             (yaml_char_t*)StringValuePtr(value),
00201             (int)RSTRING_LEN(value),
00202             plain ? 1 : 0,
00203             quoted ? 1 : 0,
00204             (yaml_scalar_style_t)NUM2INT(style)
00205             );
00206 
00207     emit(emitter, &event);
00208 
00209     return self;
00210 }
00211 
00212 /* call-seq: emitter.start_sequence(anchor, tag, implicit, style)
00213  *
00214  * Start emitting a sequence with +anchor+, a +tag+, +implicit+ sequence
00215  * start and end, along with +style+.
00216  *
00217  * See Psych::Handler#start_sequence
00218  */
00219 static VALUE start_sequence(
00220         VALUE self,
00221         VALUE anchor,
00222         VALUE tag,
00223         VALUE implicit,
00224         VALUE style
00225         ) {
00226     yaml_emitter_t * emitter;
00227     yaml_event_t event;
00228     Data_Get_Struct(self, yaml_emitter_t, emitter);
00229 
00230     yaml_sequence_start_event_initialize(
00231             &event,
00232             (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValuePtr(anchor)),
00233             (yaml_char_t *)(NIL_P(tag) ? NULL : StringValuePtr(tag)),
00234             implicit ? 1 : 0,
00235             (yaml_sequence_style_t)NUM2INT(style)
00236             );
00237 
00238     emit(emitter, &event);
00239 
00240     return self;
00241 }
00242 
00243 /* call-seq: emitter.end_sequence
00244  *
00245  * End sequence emission.
00246  *
00247  * See Psych::Handler#end_sequence
00248  */
00249 static VALUE end_sequence(VALUE self)
00250 {
00251     yaml_emitter_t * emitter;
00252     yaml_event_t event;
00253     Data_Get_Struct(self, yaml_emitter_t, emitter);
00254 
00255     yaml_sequence_end_event_initialize(&event);
00256 
00257     emit(emitter, &event);
00258 
00259     return self;
00260 }
00261 
00262 /* call-seq: emitter.start_mapping(anchor, tag, implicit, style)
00263  *
00264  * Start emitting a YAML map with +anchor+, +tag+, an +implicit+ start
00265  * and end, and +style+.
00266  *
00267  * See Psych::Handler#start_mapping
00268  */
00269 static VALUE start_mapping(
00270         VALUE self,
00271         VALUE anchor,
00272         VALUE tag,
00273         VALUE implicit,
00274         VALUE style
00275         ) {
00276     yaml_emitter_t * emitter;
00277     yaml_event_t event;
00278     Data_Get_Struct(self, yaml_emitter_t, emitter);
00279 
00280     yaml_mapping_start_event_initialize(
00281             &event,
00282             (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValuePtr(anchor)),
00283             (yaml_char_t *)(NIL_P(tag) ? NULL : StringValuePtr(tag)),
00284             implicit ? 1 : 0,
00285             (yaml_sequence_style_t)NUM2INT(style)
00286             );
00287 
00288     emit(emitter, &event);
00289 
00290     return self;
00291 }
00292 
00293 /* call-seq: emitter.end_mapping
00294  *
00295  * Emit the end of a mapping.
00296  *
00297  * See Psych::Handler#end_mapping
00298  */
00299 static VALUE end_mapping(VALUE self)
00300 {
00301     yaml_emitter_t * emitter;
00302     yaml_event_t event;
00303     Data_Get_Struct(self, yaml_emitter_t, emitter);
00304 
00305     yaml_mapping_end_event_initialize(&event);
00306 
00307     emit(emitter, &event);
00308 
00309     return self;
00310 }
00311 
00312 /* call-seq: emitter.alias(anchor)
00313  *
00314  * Emit an alias with +anchor+.
00315  *
00316  * See Psych::Handler#alias
00317  */
00318 static VALUE alias(VALUE self, VALUE anchor)
00319 {
00320     yaml_emitter_t * emitter;
00321     yaml_event_t event;
00322     Data_Get_Struct(self, yaml_emitter_t, emitter);
00323 
00324     yaml_alias_event_initialize(
00325             &event,
00326             (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValuePtr(anchor))
00327             );
00328 
00329     emit(emitter, &event);
00330 
00331     return self;
00332 }
00333 
00334 /* call-seq: emitter.canonical = true
00335  *
00336  * Set the output style to canonical, or not.
00337  */
00338 static VALUE set_canonical(VALUE self, VALUE style)
00339 {
00340     yaml_emitter_t * emitter;
00341     Data_Get_Struct(self, yaml_emitter_t, emitter);
00342 
00343     yaml_emitter_set_canonical(emitter, Qtrue == style ? 1 : 0);
00344 
00345     return style;
00346 }
00347 
00348 /* call-seq: emitter.canonical
00349  *
00350  * Get the output style, canonical or not.
00351  */
00352 static VALUE canonical(VALUE self)
00353 {
00354     yaml_emitter_t * emitter;
00355     Data_Get_Struct(self, yaml_emitter_t, emitter);
00356 
00357     return (emitter->canonical == 0) ? Qfalse : Qtrue;
00358 }
00359 
00360 /* call-seq: emitter.indentation = level
00361  *
00362  * Set the indentation level to +level+.
00363  */
00364 static VALUE set_indentation(VALUE self, VALUE level)
00365 {
00366     yaml_emitter_t * emitter;
00367     Data_Get_Struct(self, yaml_emitter_t, emitter);
00368 
00369     yaml_emitter_set_indent(emitter, NUM2INT(level));
00370 
00371     return level;
00372 }
00373 
00374 /* call-seq: emitter.indentation
00375  *
00376  * Get the indentation level.
00377  */
00378 static VALUE indentation(VALUE self)
00379 {
00380     yaml_emitter_t * emitter;
00381     Data_Get_Struct(self, yaml_emitter_t, emitter);
00382 
00383     return INT2NUM(emitter->best_indent);
00384 }
00385 
00386 void Init_psych_emitter()
00387 {
00388     VALUE psych     = rb_define_module("Psych");
00389     VALUE handler   = rb_define_class_under(psych, "Handler", rb_cObject);
00390     cPsychEmitter   = rb_define_class_under(psych, "Emitter", handler);
00391 
00392     rb_define_alloc_func(cPsychEmitter, allocate);
00393 
00394     rb_define_method(cPsychEmitter, "initialize", initialize, 1);
00395     rb_define_method(cPsychEmitter, "start_stream", start_stream, 1);
00396     rb_define_method(cPsychEmitter, "end_stream", end_stream, 0);
00397     rb_define_method(cPsychEmitter, "start_document", start_document, 3);
00398     rb_define_method(cPsychEmitter, "end_document", end_document, 1);
00399     rb_define_method(cPsychEmitter, "scalar", scalar, 6);
00400     rb_define_method(cPsychEmitter, "start_sequence", start_sequence, 4);
00401     rb_define_method(cPsychEmitter, "end_sequence", end_sequence, 0);
00402     rb_define_method(cPsychEmitter, "start_mapping", start_mapping, 4);
00403     rb_define_method(cPsychEmitter, "end_mapping", end_mapping, 0);
00404     rb_define_method(cPsychEmitter, "alias", alias, 1);
00405     rb_define_method(cPsychEmitter, "canonical", canonical, 0);
00406     rb_define_method(cPsychEmitter, "canonical=", set_canonical, 1);
00407     rb_define_method(cPsychEmitter, "indentation", indentation, 0);
00408     rb_define_method(cPsychEmitter, "indentation=", set_indentation, 1);
00409 
00410     id_write = rb_intern("write");
00411 }
00412 /* vim: set noet sws=4 sw=4: */
00413 

Generated on Sat Jul 7 2012 15:29:12 for Ruby by  doxygen 1.7.1