File Coverage

blib/lib/LibYAML/FFI.pm
Criterion Covered Total %
statement 100 118 84.7
branch 45 58 77.5
condition n/a
subroutine 17 19 89.4
pod n/a
total 162 195 83.0


line stmt bran cond sub pod time code
1             # ABSTRACT: FFI binding for C libyaml
2             package LibYAML::FFI;
3              
4 4     4   712827 use strict;
  4         37  
  4         115  
5 4     4   20 use warnings;
  4         9  
  4         121  
6 4     4   1808 use experimental 'signatures';
  4         14195  
  4         21  
7 4     4   4007 use FFI::Platypus 2.00;
  4         32030  
  4         161  
8 4     4   1961 use FFI::C;
  4         12825  
  4         130  
9 4     4   1358 use YAML::PP::Common;
  4         4903  
  4         3295  
10              
11             our $VERSION = 'v0.0.1'; # VERSION
12              
13             my $ffi = FFI::Platypus->new( api => 1 );
14             FFI::C->ffi($ffi);
15              
16             $ffi->bundle;
17              
18             package LibYAML::FFI::YamlEncoding {
19             FFI::C->enum( yaml_encoding_t => [qw/
20             ANY_ENCODING
21             UTF8_ENCODING
22             UTF16LE_ENCODING
23             UTF16BE_ENCODING
24             /],
25             { rev => 'int', prefix => 'YAML_', package => 'LibYAML::FFI::YamlEncoding' }
26             );
27             }
28              
29             package LibYAML::FFI::event_type {
30             FFI::C->enum( yaml_event_type_t => [qw/
31             NO_EVENT
32             STREAM_START_EVENT STREAM_END_EVENT
33             DOCUMENT_START_EVENT DOCUMENT_END_EVENT
34             ALIAS_EVENT SCALAR_EVENT
35             SEQUENCE_START_EVENT SEQUENCE_END_EVENT
36             MAPPING_START_EVENT MAPPING_END_EVENT
37             /],
38             { rev => 'int', prefix => 'YAML_', package => 'LibYAML::FFI::event_type' }
39             );
40             }
41              
42             package LibYAML::FFI::YamlScalarStyle {
43             FFI::C->enum( yaml_scalar_style_t => [qw/
44             ANY_SCALAR_STYLE
45             PLAIN_SCALAR_STYLE
46             SINGLE_QUOTED_SCALAR_STYLE
47             DOUBLE_QUOTED_SCALAR_STYLE
48             LITERAL_SCALAR_STYLE
49             FOLDED_SCALAR_STYLE
50             /],
51             { rev => 'int', prefix => 'YAML_', package => 'LibYAML::FFI::YamlScalarStyle' }
52             );
53             }
54              
55             package LibYAML::FFI::YamlSequenceStyle {
56             FFI::C->enum( yaml_sequence_style_t => [qw/
57             ANY_SEQUENCE_STYLE
58             BLOCK_SEQUENCE_STYLE
59             FLOW_SEQUENCE_STYLE
60             /],
61             { rev => 'int', prefix => 'YAML_', package => 'LibYAML::FFI::YamlSequenceStyle' }
62             );
63             }
64             package LibYAML::FFI::YamlMappingStyle {
65             FFI::C->enum( yaml_mapping_style_t => [qw/
66             ANY_MAPPING_STYLE
67             BLOCK_MAPPING_STYLE
68             FLOW_MAPPING_STYLE
69             /],
70             { rev => 'int', prefix => 'YAML_', package => 'LibYAML::FFI::YamlMappingStyle' }
71             );
72             }
73              
74             package LibYAML::FFI::YamlErrorType {
75             FFI::C->enum( yaml_error_type_t => [qw/
76             NO_ERROR
77             MEMORY_ERROR
78             READER_ERROR
79             SCANNER_ERROR
80             PARSER_ERROR
81             COMPOSER_ERROR
82             WRITER_ERROR
83             EMITTER_ERROR
84             /],
85             { rev => 'int', prefix => 'YAML_', package => 'LibYAML::FFI::YamlErrorType' }
86             );
87             }
88              
89             package LibYAML::FFI::YamlParserState {
90             FFI::C->enum( yaml_parser_state_t => [qw/
91             PARSE_STREAM_START_STATE
92             PARSE_IMPLICIT_DOCUMENT_START_STATE
93             PARSE_DOCUMENT_START_STATE
94             PARSE_DOCUMENT_CONTENT_STATE
95             PARSE_DOCUMENT_END_STATE
96             PARSE_BLOCK_NODE_STATE
97             PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE
98             PARSE_FLOW_NODE_STATE
99             PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE
100             PARSE_BLOCK_SEQUENCE_ENTRY_STATE
101             PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE
102             PARSE_BLOCK_MAPPING_FIRST_KEY_STATE
103             PARSE_BLOCK_MAPPING_KEY_STATE
104             PARSE_BLOCK_MAPPING_VALUE_STATE
105             PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE
106             PARSE_FLOW_SEQUENCE_ENTRY_STATE
107             PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE
108             PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE
109             PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE
110             PARSE_FLOW_MAPPING_FIRST_KEY_STATE
111             PARSE_FLOW_MAPPING_KEY_STATE
112             PARSE_FLOW_MAPPING_VALUE_STATE
113             PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE
114             PARSE_END_STATE
115             /],
116             { rev => 'int', prefix => 'YAML_', package => 'LibYAML::FFI::YamlParserState' }
117             );
118             }
119              
120             package LibYAML::FFI::StreamStart {
121             FFI::C->struct( YAML_StreamStart => [
122             encoding => 'yaml_encoding_t',
123             ]);
124             }
125              
126             package LibYAML::FFI::Scalar {
127             FFI::C->struct( YAML_Scalar => [
128             anchor => 'opaque',
129             tag => 'opaque',
130             value => 'opaque',
131             length => 'size_t',
132             plain_implicit => 'int',
133             quoted_implicit => 'int',
134             style => 'yaml_scalar_style_t',
135             ]);
136 1     1   6747 sub anchor_str ($self) { $ffi->cast('opaque', 'string', $self->anchor) }
  1         3  
  1         1  
  1         6  
137 1     1   1076 sub tag_str ($self) { $ffi->cast('opaque', 'string', $self->tag) }
  1         2  
  1         2  
  1         8  
138 3     3   612 sub value_str ($self) { $ffi->cast('opaque', 'string', $self->value) }
  3         6  
  3         6  
  3         14  
139             }
140              
141             package LibYAML::FFI::Alias {
142             FFI::C->struct( YAML_Alias => [
143             anchor => 'opaque',
144             ]);
145 2     2   105 sub anchor_str ($self) { $ffi->cast('opaque', 'string', $self->anchor) }
  2         5  
  2         2  
  2         20  
146             }
147              
148             package LibYAML::FFI::SequenceStart {
149             FFI::C->struct( YAML_SequenceStart => [
150             anchor => 'opaque',
151             tag => 'opaque',
152             implicit => 'int',
153             style => 'yaml_sequence_style_t',
154             ]);
155 1     1   5114 sub anchor_str ($self) { $ffi->cast('opaque', 'string', $self->anchor) }
  1         3  
  1         2  
  1         5  
156 1     1   600 sub tag_str ($self) { $ffi->cast('opaque', 'string', $self->tag) }
  1         3  
  1         2  
  1         4  
157             }
158              
159             package LibYAML::FFI::MappingStart {
160             FFI::C->struct( YAML_MappingStart => [
161             anchor => 'opaque',
162             tag => 'opaque',
163             implicit => 'int',
164             style => 'yaml_mapping_style_t',
165             ]);
166 0     0   0 sub anchor_str ($self) { $ffi->cast('opaque', 'string', $self->anchor) }
  0         0  
  0         0  
  0         0  
167 0     0   0 sub tag_str ($self) { $ffi->cast('opaque', 'string', $self->tag) }
  0         0  
  0         0  
  0         0  
168             }
169              
170             package LibYAML::FFI::EventData {
171             FFI::C->union( yaml_event_data_t => [
172             stream_start => 'YAML_StreamStart',
173             alias => 'YAML_Alias',
174             scalar => 'YAML_Scalar',
175             sequence_start => 'YAML_SequenceStart',
176             mapping_start => 'YAML_MappingStart',
177             ]);
178             }
179              
180             package LibYAML::FFI::YamlMark {
181             use overload
182 4     4   37 '""' => sub { shift->as_string };
  4     22   17  
  4         30  
  22         765  
183             FFI::C->struct( yaml_mark_t => [
184             index => 'size_t',
185             line =>'size_t',
186             column => 'size_t',
187             ]);
188             sub as_string {
189 22     22   39 my ($self) = @_;
190 22         43 sprintf "(%2d):[L:%2d C:%2d]", $self->index, $self->line, $self->column;
191             }
192             }
193              
194             package LibYAML::FFI::Event {
195             FFI::C->struct( yaml_event_t => [
196             type => 'yaml_event_type_t',
197             data => 'yaml_event_data_t',
198             start_mark => 'yaml_mark_t',
199             end_mark => 'yaml_mark_t',
200             ]);
201              
202             sub to_hash {
203 17     17   29 my ($self) = @_;
204 17         24 my %hash = ();
205 17         51 my $type = $self->yaml_event_type;
206 17 100       268 if ($type == LibYAML::FFI::event_type::YAML_STREAM_START_EVENT()) {
    100          
    100          
    100          
    100          
    100          
    50          
    50          
    100          
    50          
207 1         34 $hash{name} = 'stream_start_event';
208             }
209             elsif ($type == LibYAML::FFI::event_type::YAML_STREAM_END_EVENT()) {
210 1         6 $hash{name} = 'stream_end_event';
211             }
212             elsif ($type == LibYAML::FFI::event_type::YAML_DOCUMENT_START_EVENT()) {
213 1         4 $hash{name} = 'document_start_event';
214             }
215             elsif ($type == LibYAML::FFI::event_type::YAML_DOCUMENT_END_EVENT()) {
216 1         3 $hash{name} = 'document_end_event';
217             }
218             elsif ($type == LibYAML::FFI::event_type::YAML_ALIAS_EVENT()) {
219 1         5 $hash{name} = 'alias_event';
220 1 50       17 if (my $anchor = $self->data->alias->anchor_str) {
221 1         245 $hash{value} = $anchor;
222             }
223             }
224             elsif ($type == LibYAML::FFI::event_type::YAML_SCALAR_EVENT()) {
225 8         28 $hash{name} = 'scalar_event';
226 8         33 my $val = $self->yaml_event_scalar_value;
227 8         87 $hash{value} = $val;
228 8 100       19 if (my $anchor = $self->yaml_event_scalar_anchor) {
229 1         29 $hash{anchor} = $anchor;
230             }
231 8 100       76 if (my $tag = $self->yaml_event_scalar_tag) {
232 1         16 $hash{tag} = $tag;
233             }
234 8         81 $hash{style} = $self->yaml_event_scalar_style;
235             }
236             elsif ($type == LibYAML::FFI::event_type::YAML_SEQUENCE_START_EVENT()) {
237 0         0 $hash{name} = 'sequence_start_event';
238 0 0       0 if (my $anchor = $self->yaml_event_sequence_anchor) {
239 0         0 $hash{anchor} = $anchor;
240             }
241 0 0       0 if (my $tag = $self->yaml_event_sequence_tag) {
242 0         0 $hash{tag} = $tag;
243             }
244 0         0 $hash{style} = $self->yaml_event_sequence_style;
245             }
246             elsif ($type == LibYAML::FFI::event_type::YAML_SEQUENCE_END_EVENT()) {
247 0         0 $hash{name} = 'sequence_end_event';
248             }
249             elsif ($type == LibYAML::FFI::event_type::YAML_MAPPING_START_EVENT()) {
250 2         7 $hash{name} = 'mapping_start_event';
251 2         8 $hash{style} = $self->yaml_event_mapping_style;
252 2 50       30 if (my $anchor = $self->yaml_event_mapping_anchor) {
253 0         0 $hash{anchor} = $anchor;
254             }
255 2 50       26 if (my $tag = $self->yaml_event_mapping_anchor) {
256 0         0 $hash{tag} = $tag;
257             }
258             }
259             elsif ($type == LibYAML::FFI::event_type::YAML_MAPPING_END_EVENT()) {
260 2         6 $hash{name} = 'mapping_end_event';
261             }
262 17         125 return \%hash;
263             }
264             sub as_string {
265 11     11   12596 my ($self) = @_;
266 11         24 my $str = sprintf "(%2d) ",
267             $self->type;
268 11 100       129 if ($self->type == LibYAML::FFI::event_type::YAML_STREAM_START_EVENT()) {
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    50          
269 1         19 $str .= "+STR";
270             }
271             elsif ($self->type == LibYAML::FFI::event_type::YAML_STREAM_END_EVENT()) {
272 1         20 $str .= "-STR";
273             }
274             elsif ($self->type == LibYAML::FFI::event_type::YAML_DOCUMENT_START_EVENT()) {
275 1         46 $str .= "+DOC";
276             }
277             elsif ($self->type == LibYAML::FFI::event_type::YAML_DOCUMENT_END_EVENT()) {
278 1         33 $str .= "-DOC";
279             }
280             elsif ($self->type == LibYAML::FFI::event_type::YAML_ALIAS_EVENT()) {
281 1         40 $str .= "=ALI";
282 1         2 $str .= " " . $self->data->alias->anchor_str;
283             }
284             elsif ($self->type == LibYAML::FFI::event_type::YAML_SCALAR_EVENT()) {
285 2         100 my $scalar = $self->data->scalar;
286 2         80 my $val = $scalar->value_str;
287 2         349 my $anchor = $scalar->anchor;
288 2         24 my $length = $scalar->length;
289 2         23 my $plain_implicit = $scalar->plain_implicit;
290 2         28 $str .= sprintf "=VAL >%s< (%d) plain_implicit: %d", $val, $length, $plain_implicit;
291 2         5 $scalar = $self->data->scalar;
292             }
293             elsif ($self->type == LibYAML::FFI::event_type::YAML_SEQUENCE_START_EVENT()) {
294 1         63 my $style = $self->data->sequence_start->style;
295 1         45 $str .= "+SEQ";
296 1 50       17 if ($style == LibYAML::FFI::YamlSequenceStyle::YAML_FLOW_SEQUENCE_STYLE()) {
297 1         3 $str .= " []";
298             }
299             }
300             elsif ($self->type == LibYAML::FFI::event_type::YAML_SEQUENCE_END_EVENT()) {
301 1         64 $str .= "-SEQ";
302             }
303             elsif ($self->type == LibYAML::FFI::event_type::YAML_MAPPING_START_EVENT()) {
304 1         111 my $style = $self->data->sequence_start->style;
305 1         107 $str .= "+MAP";
306 1 50       24 if ($style == LibYAML::FFI::YamlMappingStyle::YAML_FLOW_MAPPING_STYLE()) {
307 0         0 $str .= " {}";
308             }
309             }
310             elsif ($self->type == LibYAML::FFI::event_type::YAML_MAPPING_END_EVENT()) {
311 1         93 $str .= "-MAP";
312             }
313 11         288 $str = $self->start_mark . ' ' . $self->end_mark . ' ' . $str;
314 11         284 return $str;
315             }
316             $ffi->attach( [ yaml_event_delete => 'DESTROY' ] => [ 'yaml_event_t' ] => 'void' );
317             $ffi->attach( yaml_scalar_event_initialize => [qw/
318             yaml_event_t string string string int int int yaml_scalar_style_t
319             /] => 'int' );
320             $ffi->attach( yaml_sequence_start_event_initialize => [qw/
321             yaml_event_t string string int yaml_scalar_style_t
322             /] => 'int' );
323             $ffi->attach( yaml_stream_start_event_initialize => [qw/
324             yaml_event_t yaml_encoding_t
325             /] => 'int' );
326             $ffi->attach( yaml_event_type => [qw/ yaml_event_t /] => 'yaml_event_type_t' );
327              
328             $ffi->attach( yaml_event_scalar_style => [qw/ yaml_event_t /] => 'yaml_scalar_style_t' );
329             $ffi->attach( yaml_event_scalar_value => [qw/ yaml_event_t /] => 'string' );
330             $ffi->attach( yaml_event_scalar_anchor => [qw/ yaml_event_t /] => 'string' );
331             $ffi->attach( yaml_event_scalar_tag => [qw/ yaml_event_t /] => 'string' );
332              
333             $ffi->attach( yaml_event_mapping_style => [qw/ yaml_event_t /] => 'yaml_mapping_style_t' );
334             $ffi->attach( yaml_event_mapping_anchor => [qw/ yaml_event_t /] => 'string' );
335             $ffi->attach( yaml_event_mapping_tag => [qw/ yaml_event_t /] => 'string' );
336              
337             $ffi->attach( yaml_event_sequence_style => [qw/ yaml_event_t /] => 'yaml_sequence_style_t' );
338             $ffi->attach( yaml_event_sequence_anchor => [qw/ yaml_event_t /] => 'string' );
339             $ffi->attach( yaml_event_sequence_tag => [qw/ yaml_event_t /] => 'string' );
340             }
341              
342             package LibYAML::FFI::ParserInputString {
343             FFI::C->struct( Parser_input_string => [
344             start => 'opaque',
345             end => 'opaque',
346             current => 'opaque',
347             ]);
348             }
349              
350             package LibYAML::FFI::ParserBuffer {
351             FFI::C->struct( Parser_buffer => [
352             start => 'opaque',
353             end => 'opaque',
354             pointer => 'opaque',
355             last => 'opaque',
356             ]);
357             }
358              
359             package LibYAML::FFI::ParserTokens {
360             FFI::C->struct( Parser_tokens => [
361             start => 'opaque',
362             end => 'opaque',
363             head => 'opaque',
364             tail => 'opaque',
365             ]);
366             }
367             package LibYAML::FFI::ParserIndents {
368             FFI::C->struct( Parser_indents => [
369             start => 'opaque',
370             end => 'opaque',
371             top => 'opaque',
372             ]);
373             }
374              
375             package LibYAML::FFI::ParserSimpleKeys {
376             FFI::C->struct( Parser_simple_keys => [
377             start => 'opaque',
378             end => 'opaque',
379             top => 'opaque',
380             ]);
381             }
382              
383             package LibYAML::FFI::ParserInput {
384             FFI::C->union( Parser_input => [
385             string => 'Parser_input_string',
386             file => 'opaque',
387             ]);
388             }
389              
390             package LibYAML::FFI::ParserStates {
391             FFI::C->struct( Parser_states => [
392             start => 'opaque',
393             end => 'opaque',
394             top => 'opaque',
395             ]);
396             }
397              
398             package LibYAML::FFI::ParserMarks {
399             FFI::C->struct( Parser_marks => [
400             start => 'opaque',
401             end => 'opaque',
402             top => 'opaque',
403             ]);
404             }
405              
406             package LibYAML::FFI::ParserTagDirectives {
407             FFI::C->struct( Parser_tag_directives => [
408             start => 'opaque',
409             end => 'opaque',
410             top => 'opaque',
411             ]);
412             }
413              
414             package LibYAML::FFI::ParserAliases {
415             FFI::C->struct( Parser_aliases => [
416             start => 'opaque',
417             end => 'opaque',
418             top => 'opaque',
419             ]);
420             }
421              
422             package LibYAML::FFI::TagDirective {
423             FFI::C->struct( yaml_tag_directive_t => [
424             handle => 'opaque',
425             prefix => 'opaque',
426             ]);
427             }
428              
429             package LibYAML::FFI::VersionDirective {
430             FFI::C->struct( yaml_version_directive_t => [
431             major => 'int',
432             minor => 'int',
433             ]);
434             }
435              
436             package LibYAML::FFI::DocumentTagDirectives {
437             FFI::C->struct( document_tag_directives => [
438             start => 'yaml_tag_directive_t',
439             end => 'yaml_tag_directive_t',
440             ]);
441             }
442              
443             package LibYAML::FFI::YamlDocument {
444             $ffi->type( 'opaque' => 'document_nodes' );
445             FFI::C->struct( yaml_document_t => [
446             nodes => 'document_nodes',
447             version_directive => 'yaml_version_directive_t',
448             tag_directives => 'document_tag_directives',
449             start_implicit => 'int',
450             end_implicit => 'int',
451             start_mark => 'yaml_mark_t',
452             end_mark => 'yaml_mark_t',
453             ]);
454             }
455              
456             package LibYAML::FFI::Parser {
457             $ffi->type( 'opaque' => 'yaml_read_handler_t' );
458             FFI::C->struct( yaml_parser_t => [
459             error => 'yaml_error_type_t',
460             problem => 'opaque',
461             problem_offset => 'size_t',
462             problem_value => 'int',
463             problem_mark => 'yaml_mark_t',
464             context => 'opaque',
465             context_mark => 'yaml_mark_t',
466              
467             read_handler => 'yaml_read_handler_t',
468             read_handler_data => 'opaque',
469              
470             input => 'Parser_input',
471             eof => 'int',
472              
473             buffer => 'Parser_buffer',
474             unread => 'size_t',
475             raw_buffer => 'Parser_buffer',
476              
477             encoding => 'yaml_encoding_t',
478              
479             offset => 'size_t',
480             mark => 'yaml_mark_t',
481              
482             stream_start_produced => 'int',
483             stream_end_produced => 'int',
484             flow_level => 'int',
485              
486             tokens => 'Parser_tokens',
487              
488             tokens_parsed => 'size_t',
489             token_available => 'int',
490              
491             indents => 'Parser_indents',
492             indent => 'int',
493             simple_key_allowed => 'int',
494             simple_keys => 'Parser_simple_keys',
495              
496             states => 'Parser_states',
497             state => 'yaml_parser_state_t',
498             marks => 'Parser_marks',
499              
500             tag_directives => 'Parser_tag_directives',
501              
502             aliases => 'Parser_aliases',
503              
504             document => 'yaml_document_t',
505             ]);
506              
507             $ffi->attach( [ yaml_parser_delete => 'DESTROY' ] => [ 'yaml_parser_t' ] => 'void' );
508              
509             $ffi->attach( yaml_parser_initialize => [qw/
510             yaml_parser_t
511             /] => 'int' );
512             $ffi->attach( yaml_parser_set_input_string => [qw/
513             yaml_parser_t string size_t
514             /] => 'void' );
515             $ffi->attach( yaml_parser_parse => [qw/
516             yaml_parser_t yaml_event_t
517             /] => 'int' );
518             # $ffi->attach( yaml_parser_delete => [qw/ yaml_parser_t /] => 'void' );
519              
520             }
521              
522              
523             1;
524              
525             __END__