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
00037
00038
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
00051
00052
00053
00054
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
00071
00072
00073
00074
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
00090
00091
00092
00093
00094
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
00156
00157
00158
00159
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
00175
00176
00177
00178
00179
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
00213
00214
00215
00216
00217
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
00244
00245
00246
00247
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
00263
00264
00265
00266
00267
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
00294
00295
00296
00297
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
00313
00314
00315
00316
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
00335
00336
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
00349
00350
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
00361
00362
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
00375
00376
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
00413