|
Ruby 1.9.2p290(2011-07-09revision32553)
|
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
1.7.3