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(void * ptr)
00021 {
00022 yaml_emitter_t * emitter;
00023
00024 emitter = (yaml_emitter_t *)ptr;
00025 yaml_emitter_delete(emitter);
00026 xfree(emitter);
00027 }
00028
00029 static VALUE allocate(VALUE klass)
00030 {
00031 yaml_emitter_t * emitter;
00032
00033 emitter = xmalloc(sizeof(yaml_emitter_t));
00034
00035 yaml_emitter_initialize(emitter);
00036 yaml_emitter_set_unicode(emitter, 1);
00037 yaml_emitter_set_indent(emitter, 2);
00038
00039 return Data_Wrap_Struct(klass, 0, dealloc, emitter);
00040 }
00041
00042
00043
00044
00045
00046 static VALUE initialize(VALUE self, VALUE io)
00047 {
00048 yaml_emitter_t * emitter;
00049 Data_Get_Struct(self, yaml_emitter_t, emitter);
00050
00051 yaml_emitter_set_output(emitter, writer, (void *)io);
00052
00053 return self;
00054 }
00055
00056
00057
00058
00059
00060
00061
00062 static VALUE start_stream(VALUE self, VALUE encoding)
00063 {
00064 yaml_emitter_t * emitter;
00065 yaml_event_t event;
00066 Data_Get_Struct(self, yaml_emitter_t, emitter);
00067 Check_Type(encoding, T_FIXNUM);
00068
00069 yaml_stream_start_event_initialize(&event, (yaml_encoding_t)NUM2INT(encoding));
00070
00071 emit(emitter, &event);
00072
00073 return self;
00074 }
00075
00076
00077
00078
00079
00080
00081
00082 static VALUE end_stream(VALUE self)
00083 {
00084 yaml_emitter_t * emitter;
00085 yaml_event_t event;
00086 Data_Get_Struct(self, yaml_emitter_t, emitter);
00087
00088 yaml_stream_end_event_initialize(&event);
00089
00090 emit(emitter, &event);
00091
00092 return self;
00093 }
00094
00095
00096
00097
00098
00099
00100
00101
00102 static VALUE start_document(VALUE self, VALUE version, VALUE tags, VALUE imp)
00103 {
00104 yaml_emitter_t * emitter;
00105 yaml_tag_directive_t * head = NULL;
00106 yaml_tag_directive_t * tail = NULL;
00107 yaml_event_t event;
00108 yaml_version_directive_t version_directive;
00109 Data_Get_Struct(self, yaml_emitter_t, emitter);
00110
00111
00112 Check_Type(version, T_ARRAY);
00113
00114 if(RARRAY_LEN(version) > 0) {
00115 VALUE major = rb_ary_entry(version, (long)0);
00116 VALUE minor = rb_ary_entry(version, (long)1);
00117
00118 version_directive.major = NUM2INT(major);
00119 version_directive.minor = NUM2INT(minor);
00120 }
00121
00122 if(RTEST(tags)) {
00123 int i = 0;
00124 #ifdef HAVE_RUBY_ENCODING_H
00125 rb_encoding * encoding = rb_utf8_encoding();
00126 #endif
00127
00128 Check_Type(tags, T_ARRAY);
00129
00130 head = xcalloc((size_t)RARRAY_LEN(tags), sizeof(yaml_tag_directive_t));
00131 tail = head;
00132
00133 for(i = 0; i < RARRAY_LEN(tags); i++) {
00134 VALUE tuple = RARRAY_PTR(tags)[i];
00135 VALUE name;
00136 VALUE value;
00137
00138 Check_Type(tuple, T_ARRAY);
00139
00140 if(RARRAY_LEN(tuple) < 2) {
00141 xfree(head);
00142 rb_raise(rb_eRuntimeError, "tag tuple must be of length 2");
00143 }
00144 name = RARRAY_PTR(tuple)[0];
00145 value = RARRAY_PTR(tuple)[1];
00146 #ifdef HAVE_RUBY_ENCODING_H
00147 name = rb_str_export_to_enc(name, encoding);
00148 value = rb_str_export_to_enc(value, encoding);
00149 #endif
00150
00151 tail->handle = (yaml_char_t *)StringValuePtr(name);
00152 tail->prefix = (yaml_char_t *)StringValuePtr(value);
00153
00154 tail++;
00155 }
00156 }
00157
00158 yaml_document_start_event_initialize(
00159 &event,
00160 (RARRAY_LEN(version) > 0) ? &version_directive : NULL,
00161 head,
00162 tail,
00163 imp ? 1 : 0
00164 );
00165
00166 emit(emitter, &event);
00167
00168 if(head) xfree(head);
00169
00170 return self;
00171 }
00172
00173
00174
00175
00176
00177
00178
00179 static VALUE end_document(VALUE self, VALUE imp)
00180 {
00181 yaml_emitter_t * emitter;
00182 yaml_event_t event;
00183 Data_Get_Struct(self, yaml_emitter_t, emitter);
00184
00185 yaml_document_end_event_initialize(&event, imp ? 1 : 0);
00186
00187 emit(emitter, &event);
00188
00189 return self;
00190 }
00191
00192
00193
00194
00195
00196
00197
00198
00199 static VALUE scalar(
00200 VALUE self,
00201 VALUE value,
00202 VALUE anchor,
00203 VALUE tag,
00204 VALUE plain,
00205 VALUE quoted,
00206 VALUE style
00207 ) {
00208 yaml_emitter_t * emitter;
00209 yaml_event_t event;
00210 #ifdef HAVE_RUBY_ENCODING_H
00211 rb_encoding *encoding;
00212 #endif
00213 Data_Get_Struct(self, yaml_emitter_t, emitter);
00214
00215 Check_Type(value, T_STRING);
00216
00217 #ifdef HAVE_RUBY_ENCODING_H
00218 encoding = rb_utf8_encoding();
00219
00220 value = rb_str_export_to_enc(value, encoding);
00221
00222 if(!NIL_P(anchor)) {
00223 Check_Type(anchor, T_STRING);
00224 anchor = rb_str_export_to_enc(anchor, encoding);
00225 }
00226
00227 if(!NIL_P(tag)) {
00228 Check_Type(tag, T_STRING);
00229 tag = rb_str_export_to_enc(tag, encoding);
00230 }
00231 #endif
00232
00233 yaml_scalar_event_initialize(
00234 &event,
00235 (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValuePtr(anchor)),
00236 (yaml_char_t *)(NIL_P(tag) ? NULL : StringValuePtr(tag)),
00237 (yaml_char_t*)StringValuePtr(value),
00238 (int)RSTRING_LEN(value),
00239 plain ? 1 : 0,
00240 quoted ? 1 : 0,
00241 (yaml_scalar_style_t)NUM2INT(style)
00242 );
00243
00244 emit(emitter, &event);
00245
00246 return self;
00247 }
00248
00249
00250
00251
00252
00253
00254
00255
00256 static VALUE start_sequence(
00257 VALUE self,
00258 VALUE anchor,
00259 VALUE tag,
00260 VALUE implicit,
00261 VALUE style
00262 ) {
00263 yaml_emitter_t * emitter;
00264 yaml_event_t event;
00265
00266 #ifdef HAVE_RUBY_ENCODING_H
00267 rb_encoding * encoding = rb_utf8_encoding();
00268
00269 if(!NIL_P(anchor)) {
00270 Check_Type(anchor, T_STRING);
00271 anchor = rb_str_export_to_enc(anchor, encoding);
00272 }
00273
00274 if(!NIL_P(tag)) {
00275 Check_Type(tag, T_STRING);
00276 tag = rb_str_export_to_enc(tag, encoding);
00277 }
00278 #endif
00279
00280 Data_Get_Struct(self, yaml_emitter_t, emitter);
00281
00282 yaml_sequence_start_event_initialize(
00283 &event,
00284 (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValuePtr(anchor)),
00285 (yaml_char_t *)(NIL_P(tag) ? NULL : StringValuePtr(tag)),
00286 implicit ? 1 : 0,
00287 (yaml_sequence_style_t)NUM2INT(style)
00288 );
00289
00290 emit(emitter, &event);
00291
00292 return self;
00293 }
00294
00295
00296
00297
00298
00299
00300
00301 static VALUE end_sequence(VALUE self)
00302 {
00303 yaml_emitter_t * emitter;
00304 yaml_event_t event;
00305 Data_Get_Struct(self, yaml_emitter_t, emitter);
00306
00307 yaml_sequence_end_event_initialize(&event);
00308
00309 emit(emitter, &event);
00310
00311 return self;
00312 }
00313
00314
00315
00316
00317
00318
00319
00320
00321 static VALUE start_mapping(
00322 VALUE self,
00323 VALUE anchor,
00324 VALUE tag,
00325 VALUE implicit,
00326 VALUE style
00327 ) {
00328 yaml_emitter_t * emitter;
00329 yaml_event_t event;
00330 #ifdef HAVE_RUBY_ENCODING_H
00331 rb_encoding *encoding;
00332 #endif
00333 Data_Get_Struct(self, yaml_emitter_t, emitter);
00334
00335 #ifdef HAVE_RUBY_ENCODING_H
00336 encoding = rb_utf8_encoding();
00337
00338 if(!NIL_P(anchor)) {
00339 Check_Type(anchor, T_STRING);
00340 anchor = rb_str_export_to_enc(anchor, encoding);
00341 }
00342
00343 if(!NIL_P(tag)) {
00344 Check_Type(tag, T_STRING);
00345 tag = rb_str_export_to_enc(tag, encoding);
00346 }
00347 #endif
00348
00349 yaml_mapping_start_event_initialize(
00350 &event,
00351 (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValuePtr(anchor)),
00352 (yaml_char_t *)(NIL_P(tag) ? NULL : StringValuePtr(tag)),
00353 implicit ? 1 : 0,
00354 (yaml_mapping_style_t)NUM2INT(style)
00355 );
00356
00357 emit(emitter, &event);
00358
00359 return self;
00360 }
00361
00362
00363
00364
00365
00366
00367
00368 static VALUE end_mapping(VALUE self)
00369 {
00370 yaml_emitter_t * emitter;
00371 yaml_event_t event;
00372 Data_Get_Struct(self, yaml_emitter_t, emitter);
00373
00374 yaml_mapping_end_event_initialize(&event);
00375
00376 emit(emitter, &event);
00377
00378 return self;
00379 }
00380
00381
00382
00383
00384
00385
00386
00387 static VALUE alias(VALUE self, VALUE anchor)
00388 {
00389 yaml_emitter_t * emitter;
00390 yaml_event_t event;
00391 Data_Get_Struct(self, yaml_emitter_t, emitter);
00392
00393 #ifdef HAVE_RUBY_ENCODING_H
00394 if(!NIL_P(anchor)) {
00395 Check_Type(anchor, T_STRING);
00396 anchor = rb_str_export_to_enc(anchor, rb_utf8_encoding());
00397 }
00398 #endif
00399
00400 yaml_alias_event_initialize(
00401 &event,
00402 (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValuePtr(anchor))
00403 );
00404
00405 emit(emitter, &event);
00406
00407 return self;
00408 }
00409
00410
00411
00412
00413
00414 static VALUE set_canonical(VALUE self, VALUE style)
00415 {
00416 yaml_emitter_t * emitter;
00417 Data_Get_Struct(self, yaml_emitter_t, emitter);
00418
00419 yaml_emitter_set_canonical(emitter, Qtrue == style ? 1 : 0);
00420
00421 return style;
00422 }
00423
00424
00425
00426
00427
00428 static VALUE canonical(VALUE self)
00429 {
00430 yaml_emitter_t * emitter;
00431 Data_Get_Struct(self, yaml_emitter_t, emitter);
00432
00433 return (emitter->canonical == 0) ? Qfalse : Qtrue;
00434 }
00435
00436
00437
00438
00439
00440
00441 static VALUE set_indentation(VALUE self, VALUE level)
00442 {
00443 yaml_emitter_t * emitter;
00444 Data_Get_Struct(self, yaml_emitter_t, emitter);
00445
00446 yaml_emitter_set_indent(emitter, NUM2INT(level));
00447
00448 return level;
00449 }
00450
00451
00452
00453
00454
00455 static VALUE indentation(VALUE self)
00456 {
00457 yaml_emitter_t * emitter;
00458 Data_Get_Struct(self, yaml_emitter_t, emitter);
00459
00460 return INT2NUM(emitter->best_indent);
00461 }
00462
00463
00464
00465
00466
00467 static VALUE line_width(VALUE self)
00468 {
00469 yaml_emitter_t * emitter;
00470 Data_Get_Struct(self, yaml_emitter_t, emitter);
00471
00472 return INT2NUM(emitter->best_width);
00473 }
00474
00475
00476
00477
00478
00479 static VALUE set_line_width(VALUE self, VALUE width)
00480 {
00481 yaml_emitter_t * emitter;
00482 Data_Get_Struct(self, yaml_emitter_t, emitter);
00483
00484 yaml_emitter_set_width(emitter, NUM2INT(width));
00485
00486 return width;
00487 }
00488
00489 void Init_psych_emitter()
00490 {
00491 VALUE psych = rb_define_module("Psych");
00492 VALUE handler = rb_define_class_under(psych, "Handler", rb_cObject);
00493 cPsychEmitter = rb_define_class_under(psych, "Emitter", handler);
00494
00495 rb_define_alloc_func(cPsychEmitter, allocate);
00496
00497 rb_define_method(cPsychEmitter, "initialize", initialize, 1);
00498 rb_define_method(cPsychEmitter, "start_stream", start_stream, 1);
00499 rb_define_method(cPsychEmitter, "end_stream", end_stream, 0);
00500 rb_define_method(cPsychEmitter, "start_document", start_document, 3);
00501 rb_define_method(cPsychEmitter, "end_document", end_document, 1);
00502 rb_define_method(cPsychEmitter, "scalar", scalar, 6);
00503 rb_define_method(cPsychEmitter, "start_sequence", start_sequence, 4);
00504 rb_define_method(cPsychEmitter, "end_sequence", end_sequence, 0);
00505 rb_define_method(cPsychEmitter, "start_mapping", start_mapping, 4);
00506 rb_define_method(cPsychEmitter, "end_mapping", end_mapping, 0);
00507 rb_define_method(cPsychEmitter, "alias", alias, 1);
00508 rb_define_method(cPsychEmitter, "canonical", canonical, 0);
00509 rb_define_method(cPsychEmitter, "canonical=", set_canonical, 1);
00510 rb_define_method(cPsychEmitter, "indentation", indentation, 0);
00511 rb_define_method(cPsychEmitter, "indentation=", set_indentation, 1);
00512 rb_define_method(cPsychEmitter, "line_width", line_width, 0);
00513 rb_define_method(cPsychEmitter, "line_width=", set_line_width, 1);
00514
00515 id_write = rb_intern("write");
00516 }
00517
00518