Ruby
2.1.3p242(2014-09-19revision47630)
Main Page
Modules
Data Structures
Files
File List
Globals
ext
psych
psych_emitter.c
Go to the documentation of this file.
1
#include <
psych.h
>
2
3
VALUE
cPsychEmitter
;
4
static
ID
id_write
;
5
static
ID
id_line_width
;
6
static
ID
id_indentation
;
7
static
ID
id_canonical
;
8
9
static
void
emit
(
yaml_emitter_t
* emitter,
yaml_event_t
* event)
10
{
11
if
(!
yaml_emitter_emit
(emitter, event))
12
rb_raise
(
rb_eRuntimeError
,
"%s"
, emitter->
problem
);
13
}
14
15
static
int
writer
(
void
*ctx,
unsigned
char
*buffer,
size_t
size
)
16
{
17
VALUE
io = (
VALUE
)ctx;
18
VALUE
str =
rb_str_new
((
const
char
*)buffer, (
long
)size);
19
VALUE
wrote =
rb_funcall
(io,
id_write
, 1, str);
20
return
(
int
)
NUM2INT
(wrote);
21
}
22
23
static
void
dealloc
(
void
* ptr)
24
{
25
yaml_emitter_t
* emitter;
26
27
emitter = (
yaml_emitter_t
*)ptr;
28
yaml_emitter_delete
(emitter);
29
xfree
(emitter);
30
}
31
32
static
VALUE
allocate
(
VALUE
klass)
33
{
34
yaml_emitter_t
* emitter;
35
36
emitter =
xmalloc
(
sizeof
(
yaml_emitter_t
));
37
38
yaml_emitter_initialize
(emitter);
39
yaml_emitter_set_unicode
(emitter, 1);
40
yaml_emitter_set_indent
(emitter, 2);
41
42
return
Data_Wrap_Struct
(klass, 0,
dealloc
, emitter);
43
}
44
45
/* call-seq: Psych::Emitter.new(io, options = Psych::Emitter::OPTIONS)
46
*
47
* Create a new Psych::Emitter that writes to +io+.
48
*/
49
static
VALUE
initialize
(
int
argc
,
VALUE
*
argv
,
VALUE
self
)
50
{
51
yaml_emitter_t
* emitter;
52
VALUE
io,
options
;
53
VALUE
line_width
;
54
VALUE
indent;
55
VALUE
canonical
;
56
57
Data_Get_Struct
(
self
,
yaml_emitter_t
, emitter);
58
59
if
(
rb_scan_args
(argc, argv,
"11"
, &io, &options) == 2) {
60
line_width =
rb_funcall
(options,
id_line_width
, 0);
61
indent =
rb_funcall
(options,
id_indentation
, 0);
62
canonical =
rb_funcall
(options,
id_canonical
, 0);
63
64
yaml_emitter_set_width
(emitter,
NUM2INT
(line_width));
65
yaml_emitter_set_indent
(emitter,
NUM2INT
(indent));
66
yaml_emitter_set_canonical
(emitter,
Qtrue
== canonical ? 1 : 0);
67
}
68
69
yaml_emitter_set_output
(emitter,
writer
, (
void
*)io);
70
71
return
self
;
72
}
73
74
/* call-seq: emitter.start_stream(encoding)
75
*
76
* Start a stream emission with +encoding+
77
*
78
* See Psych::Handler#start_stream
79
*/
80
static
VALUE
start_stream
(
VALUE
self
,
VALUE
encoding)
81
{
82
yaml_emitter_t
* emitter;
83
yaml_event_t
event;
84
Data_Get_Struct
(
self
,
yaml_emitter_t
, emitter);
85
Check_Type
(encoding,
T_FIXNUM
);
86
87
yaml_stream_start_event_initialize
(&event, (
yaml_encoding_t
)
NUM2INT
(encoding));
88
89
emit
(emitter, &event);
90
91
return
self
;
92
}
93
94
/* call-seq: emitter.end_stream
95
*
96
* End a stream emission
97
*
98
* See Psych::Handler#end_stream
99
*/
100
static
VALUE
end_stream
(
VALUE
self
)
101
{
102
yaml_emitter_t
* emitter;
103
yaml_event_t
event;
104
Data_Get_Struct
(
self
,
yaml_emitter_t
, emitter);
105
106
yaml_stream_end_event_initialize
(&event);
107
108
emit
(emitter, &event);
109
110
return
self
;
111
}
112
113
/* call-seq: emitter.start_document(version, tags, implicit)
114
*
115
* Start a document emission with YAML +version+, +tags+, and an +implicit+
116
* start.
117
*
118
* See Psych::Handler#start_document
119
*/
120
static
VALUE
start_document
(
VALUE
self
,
VALUE
version
,
VALUE
tags,
VALUE
imp)
121
{
122
yaml_emitter_t
* emitter;
123
yaml_tag_directive_t
*
head
=
NULL
;
124
yaml_tag_directive_t
*
tail
=
NULL
;
125
yaml_event_t
event;
126
yaml_version_directive_t
version_directive;
127
Data_Get_Struct
(
self
,
yaml_emitter_t
, emitter);
128
129
130
Check_Type
(version,
T_ARRAY
);
131
132
if
(
RARRAY_LEN
(version) > 0) {
133
VALUE
major
=
rb_ary_entry
(version, (
long
)0);
134
VALUE
minor
=
rb_ary_entry
(version, (
long
)1);
135
136
version_directive.
major
=
NUM2INT
(major);
137
version_directive.
minor
=
NUM2INT
(minor);
138
}
139
140
if
(
RTEST
(tags)) {
141
int
i = 0;
142
#ifdef HAVE_RUBY_ENCODING_H
143
rb_encoding
* encoding =
rb_utf8_encoding
();
144
#endif
145
146
Check_Type
(tags,
T_ARRAY
);
147
148
head =
xcalloc
((
size_t
)
RARRAY_LEN
(tags),
sizeof
(
yaml_tag_directive_t
));
149
tail =
head
;
150
151
for
(i = 0; i <
RARRAY_LEN
(tags); i++) {
152
VALUE
tuple =
RARRAY_PTR
(tags)[i];
153
VALUE
name
;
154
VALUE
value;
155
156
Check_Type
(tuple,
T_ARRAY
);
157
158
if
(RARRAY_LEN(tuple) < 2) {
159
xfree
(head);
160
rb_raise
(
rb_eRuntimeError
,
"tag tuple must be of length 2"
);
161
}
162
name =
RARRAY_PTR
(tuple)[0];
163
value =
RARRAY_PTR
(tuple)[1];
164
#ifdef HAVE_RUBY_ENCODING_H
165
name =
rb_str_export_to_enc
(name, encoding);
166
value =
rb_str_export_to_enc
(value, encoding);
167
#endif
168
169
tail->
handle
= (
yaml_char_t
*)
StringValuePtr
(name);
170
tail->
prefix
= (
yaml_char_t
*)
StringValuePtr
(value);
171
172
tail++;
173
}
174
}
175
176
yaml_document_start_event_initialize
(
177
&event,
178
(
RARRAY_LEN
(version) > 0) ? &version_directive :
NULL
,
179
head,
180
tail,
181
imp ? 1 : 0
182
);
183
184
emit
(emitter, &event);
185
186
if
(head)
xfree
(head);
187
188
return
self
;
189
}
190
191
/* call-seq: emitter.end_document(implicit)
192
*
193
* End a document emission with an +implicit+ ending.
194
*
195
* See Psych::Handler#end_document
196
*/
197
static
VALUE
end_document
(
VALUE
self
,
VALUE
imp)
198
{
199
yaml_emitter_t
* emitter;
200
yaml_event_t
event;
201
Data_Get_Struct
(
self
,
yaml_emitter_t
, emitter);
202
203
yaml_document_end_event_initialize
(&event, imp ? 1 : 0);
204
205
emit
(emitter, &event);
206
207
return
self
;
208
}
209
210
/* call-seq: emitter.scalar(value, anchor, tag, plain, quoted, style)
211
*
212
* Emit a scalar with +value+, +anchor+, +tag+, and a +plain+ or +quoted+
213
* string type with +style+.
214
*
215
* See Psych::Handler#scalar
216
*/
217
static
VALUE
scalar
(
218
VALUE
self
,
219
VALUE
value,
220
VALUE
anchor,
221
VALUE
tag,
222
VALUE
plain,
223
VALUE
quoted,
224
VALUE
style
225
) {
226
yaml_emitter_t
* emitter;
227
yaml_event_t
event;
228
#ifdef HAVE_RUBY_ENCODING_H
229
rb_encoding
*encoding;
230
#endif
231
Data_Get_Struct
(
self
,
yaml_emitter_t
, emitter);
232
233
Check_Type
(value,
T_STRING
);
234
235
#ifdef HAVE_RUBY_ENCODING_H
236
encoding =
rb_utf8_encoding
();
237
238
value =
rb_str_export_to_enc
(value, encoding);
239
240
if
(!
NIL_P
(anchor)) {
241
Check_Type
(anchor,
T_STRING
);
242
anchor =
rb_str_export_to_enc
(anchor, encoding);
243
}
244
245
if
(!
NIL_P
(tag)) {
246
Check_Type
(tag,
T_STRING
);
247
tag =
rb_str_export_to_enc
(tag, encoding);
248
}
249
#endif
250
251
yaml_scalar_event_initialize
(
252
&event,
253
(
yaml_char_t
*)(
NIL_P
(anchor) ?
NULL
:
StringValuePtr
(anchor)),
254
(
yaml_char_t
*)(
NIL_P
(tag) ?
NULL
:
StringValuePtr
(tag)),
255
(
yaml_char_t
*)
StringValuePtr
(value),
256
(
int
)
RSTRING_LEN
(value),
257
plain ? 1 : 0,
258
quoted ? 1 : 0,
259
(
yaml_scalar_style_t
)
NUM2INT
(style)
260
);
261
262
emit
(emitter, &event);
263
264
return
self
;
265
}
266
267
/* call-seq: emitter.start_sequence(anchor, tag, implicit, style)
268
*
269
* Start emitting a sequence with +anchor+, a +tag+, +implicit+ sequence
270
* start and end, along with +style+.
271
*
272
* See Psych::Handler#start_sequence
273
*/
274
static
VALUE
start_sequence
(
275
VALUE
self
,
276
VALUE
anchor,
277
VALUE
tag,
278
VALUE
implicit,
279
VALUE
style
280
) {
281
yaml_emitter_t
* emitter;
282
yaml_event_t
event;
283
284
#ifdef HAVE_RUBY_ENCODING_H
285
rb_encoding
* encoding =
rb_utf8_encoding
();
286
287
if
(!
NIL_P
(anchor)) {
288
Check_Type
(anchor,
T_STRING
);
289
anchor =
rb_str_export_to_enc
(anchor, encoding);
290
}
291
292
if
(!
NIL_P
(tag)) {
293
Check_Type
(tag,
T_STRING
);
294
tag =
rb_str_export_to_enc
(tag, encoding);
295
}
296
#endif
297
298
Data_Get_Struct
(
self
,
yaml_emitter_t
, emitter);
299
300
yaml_sequence_start_event_initialize
(
301
&event,
302
(
yaml_char_t
*)(
NIL_P
(anchor) ?
NULL
:
StringValuePtr
(anchor)),
303
(
yaml_char_t
*)(
NIL_P
(tag) ?
NULL
:
StringValuePtr
(tag)),
304
implicit ? 1 : 0,
305
(
yaml_sequence_style_t
)
NUM2INT
(style)
306
);
307
308
emit
(emitter, &event);
309
310
return
self
;
311
}
312
313
/* call-seq: emitter.end_sequence
314
*
315
* End sequence emission.
316
*
317
* See Psych::Handler#end_sequence
318
*/
319
static
VALUE
end_sequence
(
VALUE
self
)
320
{
321
yaml_emitter_t
* emitter;
322
yaml_event_t
event;
323
Data_Get_Struct
(
self
,
yaml_emitter_t
, emitter);
324
325
yaml_sequence_end_event_initialize
(&event);
326
327
emit
(emitter, &event);
328
329
return
self
;
330
}
331
332
/* call-seq: emitter.start_mapping(anchor, tag, implicit, style)
333
*
334
* Start emitting a YAML map with +anchor+, +tag+, an +implicit+ start
335
* and end, and +style+.
336
*
337
* See Psych::Handler#start_mapping
338
*/
339
static
VALUE
start_mapping
(
340
VALUE
self
,
341
VALUE
anchor,
342
VALUE
tag,
343
VALUE
implicit,
344
VALUE
style
345
) {
346
yaml_emitter_t
* emitter;
347
yaml_event_t
event;
348
#ifdef HAVE_RUBY_ENCODING_H
349
rb_encoding
*encoding;
350
#endif
351
Data_Get_Struct
(
self
,
yaml_emitter_t
, emitter);
352
353
#ifdef HAVE_RUBY_ENCODING_H
354
encoding =
rb_utf8_encoding
();
355
356
if
(!
NIL_P
(anchor)) {
357
Check_Type
(anchor,
T_STRING
);
358
anchor =
rb_str_export_to_enc
(anchor, encoding);
359
}
360
361
if
(!
NIL_P
(tag)) {
362
Check_Type
(tag,
T_STRING
);
363
tag =
rb_str_export_to_enc
(tag, encoding);
364
}
365
#endif
366
367
yaml_mapping_start_event_initialize
(
368
&event,
369
(
yaml_char_t
*)(
NIL_P
(anchor) ?
NULL
:
StringValuePtr
(anchor)),
370
(
yaml_char_t
*)(
NIL_P
(tag) ?
NULL
:
StringValuePtr
(tag)),
371
implicit ? 1 : 0,
372
(
yaml_mapping_style_t
)
NUM2INT
(style)
373
);
374
375
emit
(emitter, &event);
376
377
return
self
;
378
}
379
380
/* call-seq: emitter.end_mapping
381
*
382
* Emit the end of a mapping.
383
*
384
* See Psych::Handler#end_mapping
385
*/
386
static
VALUE
end_mapping
(
VALUE
self
)
387
{
388
yaml_emitter_t
* emitter;
389
yaml_event_t
event;
390
Data_Get_Struct
(
self
,
yaml_emitter_t
, emitter);
391
392
yaml_mapping_end_event_initialize
(&event);
393
394
emit
(emitter, &event);
395
396
return
self
;
397
}
398
399
/* call-seq: emitter.alias(anchor)
400
*
401
* Emit an alias with +anchor+.
402
*
403
* See Psych::Handler#alias
404
*/
405
static
VALUE
alias
(
VALUE
self
,
VALUE
anchor)
406
{
407
yaml_emitter_t
* emitter;
408
yaml_event_t
event;
409
Data_Get_Struct
(
self
,
yaml_emitter_t
, emitter);
410
411
#ifdef HAVE_RUBY_ENCODING_H
412
if
(!
NIL_P
(anchor)) {
413
Check_Type
(anchor,
T_STRING
);
414
anchor =
rb_str_export_to_enc
(anchor,
rb_utf8_encoding
());
415
}
416
#endif
417
418
yaml_alias_event_initialize
(
419
&event,
420
(
yaml_char_t
*)(
NIL_P
(anchor) ?
NULL
:
StringValuePtr
(anchor))
421
);
422
423
emit
(emitter, &event);
424
425
return
self
;
426
}
427
428
/* call-seq: emitter.canonical = true
429
*
430
* Set the output style to canonical, or not.
431
*/
432
static
VALUE
set_canonical
(
VALUE
self
,
VALUE
style)
433
{
434
yaml_emitter_t
* emitter;
435
Data_Get_Struct
(
self
,
yaml_emitter_t
, emitter);
436
437
yaml_emitter_set_canonical
(emitter,
Qtrue
== style ? 1 : 0);
438
439
return
style;
440
}
441
442
/* call-seq: emitter.canonical
443
*
444
* Get the output style, canonical or not.
445
*/
446
static
VALUE
canonical
(
VALUE
self
)
447
{
448
yaml_emitter_t
* emitter;
449
Data_Get_Struct
(
self
,
yaml_emitter_t
, emitter);
450
451
return
(emitter->
canonical
== 0) ?
Qfalse
:
Qtrue
;
452
}
453
454
/* call-seq: emitter.indentation = level
455
*
456
* Set the indentation level to +level+. The level must be less than 10 and
457
* greater than 1.
458
*/
459
static
VALUE
set_indentation
(
VALUE
self
,
VALUE
level)
460
{
461
yaml_emitter_t
* emitter;
462
Data_Get_Struct
(
self
,
yaml_emitter_t
, emitter);
463
464
yaml_emitter_set_indent
(emitter,
NUM2INT
(level));
465
466
return
level;
467
}
468
469
/* call-seq: emitter.indentation
470
*
471
* Get the indentation level.
472
*/
473
static
VALUE
indentation
(
VALUE
self
)
474
{
475
yaml_emitter_t
* emitter;
476
Data_Get_Struct
(
self
,
yaml_emitter_t
, emitter);
477
478
return
INT2NUM
(emitter->
best_indent
);
479
}
480
481
/* call-seq: emitter.line_width
482
*
483
* Get the preferred line width.
484
*/
485
static
VALUE
line_width
(
VALUE
self
)
486
{
487
yaml_emitter_t
* emitter;
488
Data_Get_Struct
(
self
,
yaml_emitter_t
, emitter);
489
490
return
INT2NUM
(emitter->
best_width
);
491
}
492
493
/* call-seq: emitter.line_width = width
494
*
495
* Set the preferred line with to +width+.
496
*/
497
static
VALUE
set_line_width
(
VALUE
self
,
VALUE
width)
498
{
499
yaml_emitter_t
* emitter;
500
Data_Get_Struct
(
self
,
yaml_emitter_t
, emitter);
501
502
yaml_emitter_set_width
(emitter,
NUM2INT
(width));
503
504
return
width;
505
}
506
507
void
Init_psych_emitter
()
508
{
509
VALUE
psych =
rb_define_module
(
"Psych"
);
510
VALUE
handler =
rb_define_class_under
(psych,
"Handler"
,
rb_cObject
);
511
cPsychEmitter
=
rb_define_class_under
(psych,
"Emitter"
, handler);
512
513
rb_define_alloc_func
(
cPsychEmitter
,
allocate
);
514
515
rb_define_method
(
cPsychEmitter
,
"initialize"
,
initialize
, -1);
516
rb_define_method
(
cPsychEmitter
,
"start_stream"
,
start_stream
, 1);
517
rb_define_method
(
cPsychEmitter
,
"end_stream"
,
end_stream
, 0);
518
rb_define_method
(
cPsychEmitter
,
"start_document"
,
start_document
, 3);
519
rb_define_method
(
cPsychEmitter
,
"end_document"
,
end_document
, 1);
520
rb_define_method
(
cPsychEmitter
,
"scalar"
,
scalar
, 6);
521
rb_define_method
(
cPsychEmitter
,
"start_sequence"
,
start_sequence
, 4);
522
rb_define_method
(
cPsychEmitter
,
"end_sequence"
,
end_sequence
, 0);
523
rb_define_method
(
cPsychEmitter
,
"start_mapping"
,
start_mapping
, 4);
524
rb_define_method
(
cPsychEmitter
,
"end_mapping"
,
end_mapping
, 0);
525
rb_define_method
(
cPsychEmitter
,
"alias"
,
alias
, 1);
526
rb_define_method
(
cPsychEmitter
,
"canonical"
,
canonical
, 0);
527
rb_define_method
(
cPsychEmitter
,
"canonical="
,
set_canonical
, 1);
528
rb_define_method
(
cPsychEmitter
,
"indentation"
,
indentation
, 0);
529
rb_define_method
(
cPsychEmitter
,
"indentation="
,
set_indentation
, 1);
530
rb_define_method
(
cPsychEmitter
,
"line_width"
,
line_width
, 0);
531
rb_define_method
(
cPsychEmitter
,
"line_width="
,
set_line_width
, 1);
532
533
id_write
=
rb_intern
(
"write"
);
534
id_line_width
=
rb_intern
(
"line_width"
);
535
id_indentation
=
rb_intern
(
"indentation"
);
536
id_canonical
=
rb_intern
(
"canonical"
);
537
}
538
/* vim: set noet sws=4 sw=4: */
539
Generated on Mon Sep 22 2014 11:05:26 for Ruby by
1.8.2