root/pyyaml/trunk/ext/_yaml.pyx

Revision 257, 55.8 kB (checked in by xi, 3 years ago)

Fixed _yaml.pyx to work with the latest Pyrex.

Line 
1
2 import yaml
3
4 def get_version_string():
5     return yaml_get_version_string()
6
7 def get_version():
8     cdef int major, minor, patch
9     yaml_get_version(&major, &minor, &patch)
10     return (major, minor, patch)
11
12 #Mark = yaml.error.Mark
13 YAMLError = yaml.error.YAMLError
14 ReaderError = yaml.reader.ReaderError
15 ScannerError = yaml.scanner.ScannerError
16 ParserError = yaml.parser.ParserError
17 ComposerError = yaml.composer.ComposerError
18 ConstructorError = yaml.constructor.ConstructorError
19 EmitterError = yaml.emitter.EmitterError
20 SerializerError = yaml.serializer.SerializerError
21 RepresenterError = yaml.representer.RepresenterError
22
23 StreamStartToken = yaml.tokens.StreamStartToken
24 StreamEndToken = yaml.tokens.StreamEndToken
25 DirectiveToken = yaml.tokens.DirectiveToken
26 DocumentStartToken = yaml.tokens.DocumentStartToken
27 DocumentEndToken = yaml.tokens.DocumentEndToken
28 BlockSequenceStartToken = yaml.tokens.BlockSequenceStartToken
29 BlockMappingStartToken = yaml.tokens.BlockMappingStartToken
30 BlockEndToken = yaml.tokens.BlockEndToken
31 FlowSequenceStartToken = yaml.tokens.FlowSequenceStartToken
32 FlowMappingStartToken = yaml.tokens.FlowMappingStartToken
33 FlowSequenceEndToken = yaml.tokens.FlowSequenceEndToken
34 FlowMappingEndToken = yaml.tokens.FlowMappingEndToken
35 KeyToken = yaml.tokens.KeyToken
36 ValueToken = yaml.tokens.ValueToken
37 BlockEntryToken = yaml.tokens.BlockEntryToken
38 FlowEntryToken = yaml.tokens.FlowEntryToken
39 AliasToken = yaml.tokens.AliasToken
40 AnchorToken = yaml.tokens.AnchorToken
41 TagToken = yaml.tokens.TagToken
42 ScalarToken = yaml.tokens.ScalarToken
43
44 StreamStartEvent = yaml.events.StreamStartEvent
45 StreamEndEvent = yaml.events.StreamEndEvent
46 DocumentStartEvent = yaml.events.DocumentStartEvent
47 DocumentEndEvent = yaml.events.DocumentEndEvent
48 AliasEvent = yaml.events.AliasEvent
49 ScalarEvent = yaml.events.ScalarEvent
50 SequenceStartEvent = yaml.events.SequenceStartEvent
51 SequenceEndEvent = yaml.events.SequenceEndEvent
52 MappingStartEvent = yaml.events.MappingStartEvent
53 MappingEndEvent = yaml.events.MappingEndEvent
54
55 ScalarNode = yaml.nodes.ScalarNode
56 SequenceNode = yaml.nodes.SequenceNode
57 MappingNode = yaml.nodes.MappingNode
58
59 cdef class Mark:
60     cdef readonly object name
61     cdef readonly int index
62     cdef readonly int line
63     cdef readonly int column
64     cdef readonly buffer
65     cdef readonly pointer
66
67     def __init__(self, object name, int index, int line, int column,
68             object buffer, object pointer):
69         self.name = name
70         self.index = index
71         self.line = line
72         self.column = column
73         self.buffer = buffer
74         self.pointer = pointer
75
76     def get_snippet(self):
77         return None
78
79     def __str__(self):
80         where = "  in \"%s\", line %d, column %d"   \
81                 % (self.name, self.line+1, self.column+1)
82         return where
83
84 #class YAMLError(Exception):
85 #    pass
86 #
87 #class MarkedYAMLError(YAMLError):
88 #
89 #    def __init__(self, context=None, context_mark=None,
90 #            problem=None, problem_mark=None, note=None):
91 #        self.context = context
92 #        self.context_mark = context_mark
93 #        self.problem = problem
94 #        self.problem_mark = problem_mark
95 #        self.note = note
96 #
97 #    def __str__(self):
98 #        lines = []
99 #        if self.context is not None:
100 #            lines.append(self.context)
101 #        if self.context_mark is not None  \
102 #            and (self.problem is None or self.problem_mark is None
103 #                    or self.context_mark.name != self.problem_mark.name
104 #                    or self.context_mark.line != self.problem_mark.line
105 #                    or self.context_mark.column != self.problem_mark.column):
106 #            lines.append(str(self.context_mark))
107 #        if self.problem is not None:
108 #            lines.append(self.problem)
109 #        if self.problem_mark is not None:
110 #            lines.append(str(self.problem_mark))
111 #        if self.note is not None:
112 #            lines.append(self.note)
113 #        return '\n'.join(lines)
114 #
115 #class ReaderError(YAMLError):
116 #
117 #    def __init__(self, name, position, character, encoding, reason):
118 #        self.name = name
119 #        self.character = character
120 #        self.position = position
121 #        self.encoding = encoding
122 #        self.reason = reason
123 #
124 #    def __str__(self):
125 #        if isinstance(self.character, str):
126 #            return "'%s' codec can't decode byte #x%02x: %s\n"  \
127 #                    "  in \"%s\", position %d"    \
128 #                    % (self.encoding, ord(self.character), self.reason,
129 #                            self.name, self.position)
130 #        else:
131 #            return "unacceptable character #x%04x: %s\n"    \
132 #                    "  in \"%s\", position %d"    \
133 #                    % (ord(self.character), self.reason,
134 #                            self.name, self.position)
135 #
136 #class ScannerError(MarkedYAMLError):
137 #    pass
138 #
139 #class ParserError(MarkedYAMLError):
140 #    pass
141 #
142 #class EmitterError(YAMLError):
143 #    pass
144 #
145 #cdef class Token:
146 #    cdef readonly Mark start_mark
147 #    cdef readonly Mark end_mark
148 #    def __init__(self, Mark start_mark, Mark end_mark):
149 #        self.start_mark = start_mark
150 #        self.end_mark = end_mark
151 #
152 #cdef class StreamStartToken(Token):
153 #    cdef readonly object encoding
154 #    def __init__(self, Mark start_mark, Mark end_mark, encoding):
155 #        self.start_mark = start_mark
156 #        self.end_mark = end_mark
157 #        self.encoding = encoding
158 #
159 #cdef class StreamEndToken(Token):
160 #    pass
161 #
162 #cdef class DirectiveToken(Token):
163 #    cdef readonly object name
164 #    cdef readonly object value
165 #    def __init__(self, name, value, Mark start_mark, Mark end_mark):
166 #        self.name = name
167 #        self.value = value
168 #        self.start_mark = start_mark
169 #        self.end_mark = end_mark
170 #
171 #cdef class DocumentStartToken(Token):
172 #    pass
173 #
174 #cdef class DocumentEndToken(Token):
175 #    pass
176 #
177 #cdef class BlockSequenceStartToken(Token):
178 #    pass
179 #
180 #cdef class BlockMappingStartToken(Token):
181 #    pass
182 #
183 #cdef class BlockEndToken(Token):
184 #    pass
185 #
186 #cdef class FlowSequenceStartToken(Token):
187 #    pass
188 #
189 #cdef class FlowMappingStartToken(Token):
190 #    pass
191 #
192 #cdef class FlowSequenceEndToken(Token):
193 #    pass
194 #
195 #cdef class FlowMappingEndToken(Token):
196 #    pass
197 #
198 #cdef class KeyToken(Token):
199 #    pass
200 #
201 #cdef class ValueToken(Token):
202 #    pass
203 #
204 #cdef class BlockEntryToken(Token):
205 #    pass
206 #
207 #cdef class FlowEntryToken(Token):
208 #    pass
209 #
210 #cdef class AliasToken(Token):
211 #    cdef readonly object value
212 #    def __init__(self, value, Mark start_mark, Mark end_mark):
213 #        self.value = value
214 #        self.start_mark = start_mark
215 #        self.end_mark = end_mark
216 #
217 #cdef class AnchorToken(Token):
218 #    cdef readonly object value
219 #    def __init__(self, value, Mark start_mark, Mark end_mark):
220 #        self.value = value
221 #        self.start_mark = start_mark
222 #        self.end_mark = end_mark
223 #
224 #cdef class TagToken(Token):
225 #    cdef readonly object value
226 #    def __init__(self, value, Mark start_mark, Mark end_mark):
227 #        self.value = value
228 #        self.start_mark = start_mark
229 #        self.end_mark = end_mark
230 #
231 #cdef class ScalarToken(Token):
232 #    cdef readonly object value
233 #    cdef readonly object plain
234 #    cdef readonly object style
235 #    def __init__(self, value, plain, Mark start_mark, Mark end_mark, style=None):
236 #        self.value = value
237 #        self.plain = plain
238 #        self.start_mark = start_mark
239 #        self.end_mark = end_mark
240 #        self.style = style
241
242 cdef class CParser:
243
244     cdef yaml_parser_t parser
245     cdef yaml_event_t parsed_event
246
247     cdef object stream
248     cdef object stream_name
249     cdef object current_token
250     cdef object current_event
251     cdef object anchors
252
253     def __init__(self, stream):
254         if yaml_parser_initialize(&self.parser) == 0:
255             raise MemoryError
256         self.parsed_event.type = YAML_NO_EVENT
257         if hasattr(stream, 'read'):
258             self.stream = stream
259             try:
260                 self.stream_name = stream.name
261             except AttributeError:
262                 self.stream_name = '<file>'
263             yaml_parser_set_input(&self.parser, input_handler, <void *>self)
264         else:
265             if PyUnicode_CheckExact(stream) != 0:
266                 stream = PyUnicode_AsUTF8String(stream)
267                 self.stream_name = '<unicode string>'
268             else:
269                 self.stream_name = '<string>'
270             if PyString_CheckExact(stream) == 0:
271                 raise TypeError("a string or stream input is required")
272             self.stream = stream
273             yaml_parser_set_input_string(&self.parser, PyString_AS_STRING(stream), PyString_GET_SIZE(stream))
274         self.current_token = None
275         self.current_event = None
276         self.anchors = {}
277
278     def __dealloc__(self):
279         yaml_parser_delete(&self.parser)
280         yaml_event_delete(&self.parsed_event)
281
282     cdef object _parser_error(self):
283         if self.parser.error == YAML_MEMORY_ERROR:
284             return MemoryError
285         elif self.parser.error == YAML_READER_ERROR:
286             return ReaderError(self.stream_name, self.parser.problem_offset,
287                     self.parser.problem_value, '?', self.parser.problem)
288         elif self.parser.error == YAML_SCANNER_ERROR    \
289                 or self.parser.error == YAML_PARSER_ERROR:
290             context_mark = None
291             problem_mark = None
292             if self.parser.context != NULL:
293                 context_mark = Mark(self.stream_name,
294                         self.parser.context_mark.index,
295                         self.parser.context_mark.line,
296                         self.parser.context_mark.column, None, None)
297             if self.parser.problem != NULL:
298                 problem_mark = Mark(self.stream_name,
299                         self.parser.problem_mark.index,
300                         self.parser.problem_mark.line,
301                         self.parser.problem_mark.column, None, None)
302             if self.parser.error == YAML_SCANNER_ERROR:
303                 if self.parser.context != NULL:
304                     return ScannerError(self.parser.context, context_mark,
305                             self.parser.problem, problem_mark)
306                 else:
307                     return ScannerError(None, None,
308                             self.parser.problem, problem_mark)
309             else:
310                 if self.parser.context != NULL:
311                     return ParserError(self.parser.context, context_mark,
312                             self.parser.problem, problem_mark)
313                 else:
314                     return ParserError(None, None,
315                             self.parser.problem, problem_mark)
316         raise ValueError("no parser error")
317
318     def raw_scan(self):
319         cdef yaml_token_t token
320         cdef int done
321         cdef int count
322         count = 0
323         done = 0
324         while done == 0:
325             if yaml_parser_scan(&self.parser, &token) == 0:
326                 error = self._parser_error()
327                 raise error
328             if token.type == YAML_NO_TOKEN:
329                 done = 1
330             else:
331                 count = count+1
332             yaml_token_delete(&token)
333         return count
334
335     cdef object _scan(self):
336         cdef yaml_token_t token
337         if yaml_parser_scan(&self.parser, &token) == 0:
338             error = self._parser_error()
339             raise error
340         token_object = self._token_to_object(&token)
341         yaml_token_delete(&token)
342         return token_object
343
344     cdef object _token_to_object(self, yaml_token_t *token):
345         start_mark = Mark(self.stream_name,
346                 token.start_mark.index,
347                 token.start_mark.line,
348                 token.start_mark.column,
349                 None, None)
350         end_mark = Mark(self.stream_name,
351                 token.end_mark.index,
352                 token.end_mark.line,
353                 token.end_mark.column,
354                 None, None)
355         if token.type == YAML_NO_TOKEN:
356             return None
357         elif token.type == YAML_STREAM_START_TOKEN:
358             encoding = None
359             if token.data.stream_start.encoding == YAML_UTF8_ENCODING:
360                 encoding = "utf-8"
361             elif token.data.stream_start.encoding == YAML_UTF16LE_ENCODING:
362                 encoding = "utf-16-le"
363             elif token.data.stream_start.encoding == YAML_UTF16BE_ENCODING:
364                 encoding = "utf-16-be"
365             return StreamStartToken(start_mark, end_mark, encoding)
366         elif token.type == YAML_STREAM_END_TOKEN:
367             return StreamEndToken(start_mark, end_mark)
368         elif token.type == YAML_VERSION_DIRECTIVE_TOKEN:
369             return DirectiveToken("YAML",
370                     (token.data.version_directive.major,
371                         token.data.version_directive.minor),
372                     start_mark, end_mark)
373         elif token.type == YAML_TAG_DIRECTIVE_TOKEN:
374             return DirectiveToken("TAG",
375                     (token.data.tag_directive.handle,
376                         token.data.tag_directive.prefix),
377                     start_mark, end_mark)
378         elif token.type == YAML_DOCUMENT_START_TOKEN:
379             return DocumentStartToken(start_mark, end_mark)
380         elif token.type == YAML_DOCUMENT_END_TOKEN:
381             return DocumentEndToken(start_mark, end_mark)
382         elif token.type == YAML_BLOCK_SEQUENCE_START_TOKEN:
383             return BlockSequenceStartToken(start_mark, end_mark)
384         elif token.type == YAML_BLOCK_MAPPING_START_TOKEN:
385             return BlockMappingStartToken(start_mark, end_mark)
386         elif token.type == YAML_BLOCK_END_TOKEN:
387             return BlockEndToken(start_mark, end_mark)
388         elif token.type == YAML_FLOW_SEQUENCE_START_TOKEN:
389             return FlowSequenceStartToken(start_mark, end_mark)
390         elif token.type == YAML_FLOW_SEQUENCE_END_TOKEN:
391             return FlowSequenceEndToken(start_mark, end_mark)
392         elif token.type == YAML_FLOW_MAPPING_START_TOKEN:
393             return FlowMappingStartToken(start_mark, end_mark)
394         elif token.type == YAML_FLOW_MAPPING_END_TOKEN:
395             return FlowMappingEndToken(start_mark, end_mark)
396         elif token.type == YAML_BLOCK_ENTRY_TOKEN:
397             return BlockEntryToken(start_mark, end_mark)
398         elif token.type == YAML_FLOW_ENTRY_TOKEN:
399             return FlowEntryToken(start_mark, end_mark)
400         elif token.type == YAML_KEY_TOKEN:
401             return KeyToken(start_mark, end_mark)
402         elif token.type == YAML_VALUE_TOKEN:
403             return ValueToken(start_mark, end_mark)
404         elif token.type == YAML_ALIAS_TOKEN:
405             value = PyUnicode_DecodeUTF8(token.data.alias.value,
406                     strlen(token.data.alias.value), 'strict')
407             return AliasToken(value, start_mark, end_mark)
408         elif token.type == YAML_ANCHOR_TOKEN:
409             value = PyUnicode_DecodeUTF8(token.data.anchor.value,
410                     strlen(token.data.anchor.value), 'strict')
411             return AnchorToken(value, start_mark, end_mark)
412         elif token.type == YAML_TAG_TOKEN:
413             handle = PyUnicode_DecodeUTF8(token.data.tag.handle,
414                     strlen(token.data.tag.handle), 'strict')
415             suffix = PyUnicode_DecodeUTF8(token.data.tag.suffix,
416                     strlen(token.data.tag.suffix), 'strict')
417             if not handle:
418                 handle = None
419             return TagToken((handle, suffix), start_mark, end_mark)
420         elif token.type == YAML_SCALAR_TOKEN:
421             value = PyUnicode_DecodeUTF8(token.data.scalar.value,
422                     token.data.scalar.length, 'strict')
423             plain = False
424             style = None
425             if token.data.scalar.style == YAML_PLAIN_SCALAR_STYLE:
426                 plain = True
427                 style = ''
428             elif token.data.scalar.style == YAML_SINGLE_QUOTED_SCALAR_STYLE:
429                 style = '\''
430             elif token.data.scalar.style == YAML_DOUBLE_QUOTED_SCALAR_STYLE:
431                 style = '"'
432             elif token.data.scalar.style == YAML_LITERAL_SCALAR_STYLE:
433                 style = '|'
434             elif token.data.scalar.style == YAML_FOLDED_SCALAR_STYLE:
435                 style = '>'
436             return ScalarToken(value, plain,
437                     start_mark, end_mark, style)
438         else:
439             raise ValueError("unknown token type")
440
441     def get_token(self):
442         if self.current_token is not None:
443             value = self.current_token
444             self.current_token = None
445         else:
446             value = self._scan()
447         return value
448
449     def peek_token(self):
450         if self.current_token is None:
451             self.current_token = self._scan()
452         return self.current_token
453
454     def check_token(self, *choices):
455         if self.current_token is None:
456             self.current_token = self._scan()
457         if self.current_token is None:
458             return False
459         if not choices:
460             return True
461         token_class = self.current_token.__class__
462         for choice in choices:
463             if token_class is choice:
464                 return True
465         return False
466
467     def raw_parse(self):
468         cdef yaml_event_t event
469         cdef int done
470         cdef int count
471         count = 0
472         done = 0
473         while done == 0:
474             if yaml_parser_parse(&self.parser, &event) == 0:
475                 error = self._parser_error()
476                 raise error
477             if event.type == YAML_NO_EVENT:
478                 done = 1
479             else:
480                 count = count+1
481             yaml_event_delete(&event)
482         return count
483
484     cdef object _parse(self):
485         cdef yaml_event_t event
486         if yaml_parser_parse(&self.parser, &event) == 0:
487             error = self._parser_error()
488             raise error
489         event_object = self._event_to_object(&event)
490         yaml_event_delete(&event)
491         return event_object
492
493     cdef object _event_to_object(self, yaml_event_t *event):
494         cdef yaml_tag_directive_t *tag_directive
495         start_mark = Mark(self.stream_name,
496                 event.start_mark.index,
497                 event.start_mark.line,
498                 event.start_mark.column,
499                 None, None)
500         end_mark = Mark(self.stream_name,
501                 event.end_mark.index,
502                 event.end_mark.line,
503                 event.end_mark.column,
504                 None, None)
505         if event.type == YAML_NO_EVENT:
506             return None
507         elif event.type == YAML_STREAM_START_EVENT:
508             encoding = None
509             if event.data.stream_start.encoding == YAML_UTF8_ENCODING:
510                 encoding = "utf-8"
511             elif event.data.stream_start.encoding == YAML_UTF16LE_ENCODING:
512                 encoding = "utf-16-le"
513             elif event.data.stream_start.encoding == YAML_UTF16BE_ENCODING:
514                 encoding = "utf-16-be"
515             return StreamStartEvent(start_mark, end_mark, encoding)
516         elif event.type == YAML_STREAM_END_EVENT:
517             return StreamEndEvent(start_mark, end_mark)
518
519         elif event.type == YAML_DOCUMENT_START_EVENT:
520             explicit = False
521             if event.data.document_start.implicit == 0:
522                 explicit = True
523             version = None
524             if event.data.document_start.version_directive != NULL:
525                 version = (event.data.document_start.version_directive.major,
526                         event.data.document_start.version_directive.minor)
527             tags = None
528             if event.data.document_start.tag_directives.start != NULL:
529                 tags = {}
530                 tag_directive = event.data.document_start.tag_directives.start
531                 while tag_directive != event.data.document_start.tag_directives.end:
532                     handle = PyUnicode_DecodeUTF8(tag_directive.handle,
533                             strlen(tag_directive.handle), 'strict')
534                     prefix = PyUnicode_DecodeUTF8(tag_directive.prefix,
535                             strlen(tag_directive.prefix), 'strict')
536                     tags[handle] = prefix
537                     tag_directive = tag_directive+1
538             return DocumentStartEvent(start_mark, end_mark,
539                     explicit, version, tags)
540         elif event.type == YAML_DOCUMENT_END_EVENT:
541             explicit = False
542             if event.data.document_end.implicit == 0:
543                 explicit = True
544             return DocumentEndEvent(start_mark, end_mark, explicit)
545         elif event.type == YAML_ALIAS_EVENT:
546             anchor = PyUnicode_DecodeUTF8(event.data.alias.anchor,
547                     strlen(event.data.alias.anchor), 'strict')
548             return AliasEvent(anchor, start_mark, end_mark)
549         elif event.type == YAML_SCALAR_EVENT:
550             anchor = None
551             if event.data.scalar.anchor != NULL:
552                 anchor = PyUnicode_DecodeUTF8(event.data.scalar.anchor,
553                         strlen(event.data.scalar.anchor), 'strict')
554             tag = None
555             if event.data.scalar.tag != NULL:
556                 tag = PyUnicode_DecodeUTF8(event.data.scalar.tag,
557                         strlen(event.data.scalar.tag), 'strict')
558             value = PyUnicode_DecodeUTF8(event.data.scalar.value,
559                     event.data.scalar.length, 'strict')
560             plain_implicit = False
561             if event.data.scalar.plain_implicit == 1:
562                 plain_implicit = True
563             quoted_implicit = False
564             if event.data.scalar.quoted_implicit == 1:
565                 quoted_implicit = True
566             style = None
567             if event.data.scalar.style == YAML_PLAIN_SCALAR_STYLE:
568                 style = ''
569             elif event.data.scalar.style == YAML_SINGLE_QUOTED_SCALAR_STYLE:
570                 style = '\''
571             elif event.data.scalar.style == YAML_DOUBLE_QUOTED_SCALAR_STYLE:
572                 style = '"'
573             elif event.data.scalar.style == YAML_LITERAL_SCALAR_STYLE:
574                 style = '|'
575             elif event.data.scalar.style == YAML_FOLDED_SCALAR_STYLE:
576                 style = '>'
577             return ScalarEvent(anchor, tag,
578                     (plain_implicit, quoted_implicit),
579                     value, start_mark, end_mark, style)
580         elif event.type == YAML_SEQUENCE_START_EVENT:
581             anchor = None
582             if event.data.sequence_start.anchor != NULL:
583                 anchor = PyUnicode_DecodeUTF8(event.data.sequence_start.anchor,
584                         strlen(event.data.sequence_start.anchor), 'strict')
585             tag = None
586             if event.data.sequence_start.tag != NULL:
587                 tag = PyUnicode_DecodeUTF8(event.data.sequence_start.tag,
588                         strlen(event.data.sequence_start.tag), 'strict')
589             implicit = False
590             if event.data.sequence_start.implicit == 1:
591                 implicit = True
592             flow_style = None
593             if event.data.sequence_start.style == YAML_FLOW_SEQUENCE_STYLE:
594                 flow_style = True
595             elif event.data.sequence_start.style == YAML_BLOCK_SEQUENCE_STYLE:
596                 flow_style = False
597             return SequenceStartEvent(anchor, tag, implicit,
598                     start_mark, end_mark, flow_style)
599         elif event.type == YAML_MAPPING_START_EVENT:
600             anchor = None
601             if event.data.mapping_start.anchor != NULL:
602                 anchor = PyUnicode_DecodeUTF8(event.data.mapping_start.anchor,
603                         strlen(event.data.mapping_start.anchor), 'strict')
604             tag = None
605             if event.data.mapping_start.tag != NULL:
606                 tag = PyUnicode_DecodeUTF8(event.data.mapping_start.tag,
607                         strlen(event.data.mapping_start.tag), 'strict')
608             implicit = False
609             if event.data.mapping_start.implicit == 1:
610                 implicit = True
611             flow_style = None
612             if event.data.mapping_start.style == YAML_FLOW_MAPPING_STYLE:
613                 flow_style = True
614             elif event.data.mapping_start.style == YAML_BLOCK_MAPPING_STYLE:
615                 flow_style = False
616             return MappingStartEvent(anchor, tag, implicit,
617                     start_mark, end_mark, flow_style)
618         elif event.type == YAML_SEQUENCE_END_EVENT:
619             return SequenceEndEvent(start_mark, end_mark)
620         elif event.type == YAML_MAPPING_END_EVENT:
621             return MappingEndEvent(start_mark, end_mark)
622
623         else:
624             raise ValueError("unknown token type")
625
626     def get_event(self):
627         if self.current_event is not None:
628             value = self.current_event
629             self.current_event = None
630         else:
631             value = self._parse()
632         return value
633
634     def peek_event(self):
635         if self.current_event is None:
636             self.current_event = self._parse()
637         return self.current_event
638
639     def check_event(self, *choices):
640         if self.current_event is None:
641             self.current_event = self._parse()
642         if self.current_event is None:
643             return False
644         if not choices:
645             return True
646         event_class = self.current_event.__class__
647         for choice in choices:
648             if event_class is choice:
649                 return True
650         return False
651
652     def check_node(self):
653         self._parse_next_event()
654         if self.parsed_event.type == YAML_STREAM_START_EVENT:
655             yaml_event_delete(&self.parsed_event)
656             self._parse_next_event()
657         if self.parsed_event.type != YAML_STREAM_END_EVENT:
658             return True
659         return False
660
661     def get_node(self):
662         self._parse_next_event()
663         if self.parsed_event.type != YAML_STREAM_END_EVENT:
664             return self._compose_document()
665
666     cdef object _compose_document(self):
667         yaml_event_delete(&self.parsed_event)
668         node = self._compose_node(None, None)
669         self._parse_next_event()
670         yaml_event_delete(&self.parsed_event)
671         self.anchors = {}
672         return node
673
674     cdef object _compose_node(self, object parent, object index):
675         self._parse_next_event()
676         if self.parsed_event.type == YAML_ALIAS_EVENT:
677             anchor = PyUnicode_DecodeUTF8(self.parsed_event.data.alias.anchor,
678                     strlen(self.parsed_event.data.alias.anchor), 'strict')
679             if anchor not in self.anchors:
680                 mark = Mark(self.stream_name,
681                         self.parsed_event.start_mark.index,
682                         self.parsed_event.start_mark.line,
683                         self.parsed_event.start_mark.column,
684                         None, None)
685                 raise ComposerError(None, None, "found undefined alias", mark)
686             yaml_event_delete(&self.parsed_event)
687             return self.anchors[anchor]
688         anchor = None
689         if self.parsed_event.type == YAML_SCALAR_EVENT  \
690                 and self.parsed_event.data.scalar.anchor != NULL:
691             anchor = PyUnicode_DecodeUTF8(self.parsed_event.data.scalar.anchor,
692                     strlen(self.parsed_event.data.scalar.anchor), 'strict')
693         elif self.parsed_event.type == YAML_SEQUENCE_START_EVENT    \
694                 and self.parsed_event.data.sequence_start.anchor != NULL:
695             anchor = PyUnicode_DecodeUTF8(self.parsed_event.data.sequence_start.anchor,
696                     strlen(self.parsed_event.data.sequence_start.anchor), 'strict')
697         elif self.parsed_event.type == YAML_MAPPING_START_EVENT    \
698                 and self.parsed_event.data.mapping_start.anchor != NULL:
699             anchor = PyUnicode_DecodeUTF8(self.parsed_event.data.mapping_start.anchor,
700                     strlen(self.parsed_event.data.mapping_start.anchor), 'strict')
701         if anchor is not None:
702             if anchor in self.anchors:
703                 mark = Mark(self.stream_name,
704                         self.parsed_event.start_mark.index,
705                         self.parsed_event.start_mark.line,
706                         self.parsed_event.start_mark.column,
707                         None, None)
708                 raise ComposerError("found duplicate anchor; first occurence",
709                         self.anchors[anchor].start_mark, "second occurence", mark)
710         self.descend_resolver(parent, index)
711         if self.parsed_event.type == YAML_SCALAR_EVENT:
712             node = self._compose_scalar_node(anchor)
713         elif self.parsed_event.type == YAML_SEQUENCE_START_EVENT:
714             node = self._compose_sequence_node(anchor)
715         elif self.parsed_event.type == YAML_MAPPING_START_EVENT:
716             node = self._compose_mapping_node(anchor)
717         self.ascend_resolver()
718         return node
719
720     cdef _compose_scalar_node(self, object anchor):
721         start_mark = Mark(self.stream_name,
722                 self.parsed_event.start_mark.index,
723                 self.parsed_event.start_mark.line,
724                 self.parsed_event.start_mark.column,
725                 None, None)
726         end_mark = Mark(self.stream_name,
727                 self.parsed_event.end_mark.index,
728                 self.parsed_event.end_mark.line,
729                 self.parsed_event.end_mark.column,
730                 None, None)
731         value = PyUnicode_DecodeUTF8(self.parsed_event.data.scalar.value,
732                 self.parsed_event.data.scalar.length, 'strict')
733         plain_implicit = False
734         if self.parsed_event.data.scalar.plain_implicit == 1:
735             plain_implicit = True
736         quoted_implicit = False
737         if self.parsed_event.data.scalar.quoted_implicit == 1:
738             quoted_implicit = True
739         if self.parsed_event.data.scalar.tag == NULL    \
740                 or (self.parsed_event.data.scalar.tag[0] == c'!'
741                         and self.parsed_event.data.scalar.tag[1] == c'\0'):
742             tag = self.resolve(ScalarNode, value, (plain_implicit, quoted_implicit))
743         else:
744             tag = PyUnicode_DecodeUTF8(self.parsed_event.data.scalar.tag,
745                     strlen(self.parsed_event.data.scalar.tag), 'strict')
746         style = None
747         if self.parsed_event.data.scalar.style == YAML_PLAIN_SCALAR_STYLE:
748             style = ''
749         elif self.parsed_event.data.scalar.style == YAML_SINGLE_QUOTED_SCALAR_STYLE:
750             style = '\''
751         elif self.parsed_event.data.scalar.style == YAML_DOUBLE_QUOTED_SCALAR_STYLE:
752             style = '"'
753         elif self.parsed_event.data.scalar.style == YAML_LITERAL_SCALAR_STYLE:
754             style = '|'
755         elif self.parsed_event.data.scalar.style == YAML_FOLDED_SCALAR_STYLE:
756             style = '>'
757         node = ScalarNode(tag, value, start_mark, end_mark, style)
758         if anchor is not None:
759             self.anchors[anchor] = node
760         yaml_event_delete(&self.parsed_event)
761         return node
762
763     cdef _compose_sequence_node(self, object anchor):
764         cdef int index
765         start_mark = Mark(self.stream_name,
766                 self.parsed_event.start_mark.index,
767                 self.parsed_event.start_mark.line,
768                 self.parsed_event.start_mark.column,
769                 None, None)
770         implicit = False
771         if self.parsed_event.data.sequence_start.implicit == 1:
772             implicit = True
773         if self.parsed_event.data.sequence_start.tag == NULL    \
774                 or (self.parsed_event.data.sequence_start.tag[0] == c'!'
775                         and self.parsed_event.data.sequence_start.tag[1] == c'\0'):
776             tag = self.resolve(SequenceNode, None, implicit)
777         else:
778             tag = PyUnicode_DecodeUTF8(self.parsed_event.data.sequence_start.tag,
779                     strlen(self.parsed_event.data.sequence_start.tag), 'strict')
780         flow_style = None
781         if self.parsed_event.data.sequence_start.style == YAML_FLOW_SEQUENCE_STYLE:
782             flow_style = True
783         elif self.parsed_event.data.sequence_start.style == YAML_BLOCK_SEQUENCE_STYLE:
784             flow_style = False
785         value = []
786         node = SequenceNode(tag, value, start_mark, None, flow_style)
787         if anchor is not None:
788             self.anchors[anchor] = node
789         yaml_event_delete(&self.parsed_event)
790         index = 0
791         self._parse_next_event()
792         while self.parsed_event.type != YAML_SEQUENCE_END_EVENT:
793             value.append(self._compose_node(node, index))
794             index = index+1
795             self._parse_next_event()
796         node.end_mark = Mark(self.stream_name,
797                 self.parsed_event.end_mark.index,
798                 self.parsed_event.end_mark.line,
799                 self.parsed_event.end_mark.column,
800                 None, None)
801         yaml_event_delete(&self.parsed_event)
802         return node
803
804     cdef _compose_mapping_node(self, object anchor):
805         start_mark = Mark(self.stream_name,
806                 self.parsed_event.start_mark.index,
807                 self.parsed_event.start_mark.line,
808                 self.parsed_event.start_mark.column,
809                 None, None)
810         implicit = False
811         if self.parsed_event.data.mapping_start.implicit == 1:
812             implicit = True
813         if self.parsed_event.data.mapping_start.tag == NULL    \
814                 or (self.parsed_event.data.mapping_start.tag[0] == c'!'
815                         and self.parsed_event.data.mapping_start.tag[1] == c'\0'):
816             tag = self.resolve(MappingNode, None, implicit)
817         else:
818             tag = PyUnicode_DecodeUTF8(self.parsed_event.data.mapping_start.tag,
819                     strlen(self.parsed_event.data.mapping_start.tag), 'strict')
820         flow_style = None
821         if self.parsed_event.data.mapping_start.style == YAML_FLOW_MAPPING_STYLE:
822             flow_style = True
823         elif self.parsed_event.data.mapping_start.style == YAML_BLOCK_MAPPING_STYLE:
824             flow_style = False
825         value = []
826         node = MappingNode(tag, value, start_mark, None, flow_style)
827         if anchor is not None:
828             self.anchors[anchor] = node
829         yaml_event_delete(&self.parsed_event)
830         self._parse_next_event()
831         while self.parsed_event.type != YAML_MAPPING_END_EVENT:
832             item_key = self._compose_node(node, None)
833             item_value = self._compose_node(node, item_key)
834             value.append((item_key, item_value))
835             self._parse_next_event()
836         node.end_mark = Mark(self.stream_name,
837                 self.parsed_event.end_mark.index,
838                 self.parsed_event.end_mark.line,
839                 self.parsed_event.end_mark.column,
840                 None, None)
841         yaml_event_delete(&self.parsed_event)
842         return node
843
844     cdef int _parse_next_event(self) except 0:
845         if self.parsed_event.type == YAML_NO_EVENT:
846             if yaml_parser_parse(&self.parser, &self.parsed_event) == 0:
847                 error = self._parser_error()
848                 raise error
849         return 1
850
851 cdef int input_handler(void *data, char *buffer, int size, int *read) except 0:
852     cdef CParser parser
853     parser = <CParser>data
854     value = parser.stream.read(size)
855     if PyString_CheckExact(value) == 0:
856         raise TypeError("a string value is expected")
857     if PyString_GET_SIZE(value) > size:
858         raise ValueError("a string value it too long")
859     memcpy(buffer, PyString_AS_STRING(value), PyString_GET_SIZE(value))
860     read[0] = PyString_GET_SIZE(value)
861     return 1
862
863 cdef class CEmitter:
864
865     cdef yaml_emitter_t emitter
866
867     cdef object stream
868
869     cdef yaml_encoding_t use_encoding
870     cdef int document_start_implicit
871     cdef int document_end_implicit
872     cdef object use_version
873     cdef object use_tags
874
875     cdef object serialized_nodes
876     cdef object anchors
877     cdef int last_alias_id
878     cdef int closed
879
880     def __init__(self, stream, canonical=None, indent=None, width=None,
881             allow_unicode=None, line_break=None, encoding=None,
882             explicit_start=None, explicit_end=None, version=None, tags=None):
883         if yaml_emitter_initialize(&self.emitter) == 0:
884             raise MemoryError
885         self.stream = stream
886         yaml_emitter_set_output(&self.emitter, output_handler, <void *>self)   
887         if canonical is not None:
888             yaml_emitter_set_canonical(&self.emitter, 1)
889         if indent is not None:
890             yaml_emitter_set_indent(&self.emitter, indent)
891         if width is not None:
892             yaml_emitter_set_width(&self.emitter, width)
893         if allow_unicode is not None:
894             yaml_emitter_set_unicode(&self.emitter, 1)
895         if line_break is not None:
896             if line_break == '\r':
897                 yaml_emitter_set_break(&self.emitter, YAML_CR_BREAK)
898             elif line_break == '\n':
899                 yaml_emitter_set_break(&self.emitter, YAML_LN_BREAK)
900             elif line_break == '\r\n':
901                 yaml_emitter_set_break(&self.emitter, YAML_CRLN_BREAK)
902         if encoding == 'utf-16-le':
903             self.use_encoding = YAML_UTF16LE_ENCODING
904         elif encoding == 'utf-16-be':
905             self.use_encoding = YAML_UTF16BE_ENCODING
906         else:
907             self.use_encoding = YAML_UTF8_ENCODING
908         self.document_start_implicit = 1
909         if explicit_start:
910             self.document_start_implicit = 0
911         self.document_end_implicit = 1
912         if explicit_end:
913             self.document_end_implicit = 0
914         self.use_version = version
915         self.use_tags = tags
916         self.serialized_nodes = {}
917         self.anchors = {}
918         self.last_alias_id = 0
919         self.closed = -1
920
921     def __dealloc__(self):
922         yaml_emitter_delete(&self.emitter)
923
924     cdef object _emitter_error(self):
925         if self.emitter.error == YAML_MEMORY_ERROR:
926             return MemoryError
927         elif self.emitter.error == YAML_EMITTER_ERROR:
928             return EmitterError(self.emitter.problem)
929         raise ValueError("no emitter error")
930
931     cdef int _object_to_event(self, object event_object, yaml_event_t *event) except 0:
932         cdef yaml_encoding_t encoding
933         cdef yaml_version_directive_t version_directive_value
934         cdef yaml_version_directive_t *version_directive
935         cdef yaml_tag_directive_t tag_directives_value[128]
936         cdef yaml_tag_directive_t *tag_directives_start
937         cdef yaml_tag_directive_t *tag_directives_end
938         cdef int implicit
939         cdef int plain_implicit
940         cdef int quoted_implicit
941         cdef char *anchor
942         cdef char *tag
943         cdef char *value
944         cdef int length
945         cdef yaml_scalar_style_t scalar_style
946         cdef yaml_sequence_style_t sequence_style
947         cdef yaml_mapping_style_t mapping_style
948         event_class = event_object.__class__
949         if event_class is StreamStartEvent:
950             encoding = YAML_UTF8_ENCODING
951             if event_object.encoding == 'utf-16-le':
952                 encoding = YAML_UTF16LE_ENCODING
953             elif event_object.encoding == 'utf-16-be':
954                 encoding = YAML_UTF16BE_ENCODING
955             yaml_stream_start_event_initialize(event, encoding)
956         elif event_class is StreamEndEvent:
957             yaml_stream_end_event_initialize(event)
958         elif event_class is DocumentStartEvent:
959             version_directive = NULL
960             if event_object.version:
961                 version_directive_value.major = event_object.version[0]
962                 version_directive_value.minor = event_object.version[1]
963                 version_directive = &version_directive_value
964             tag_directives_start = NULL
965             tag_directives_end = NULL
966             if event_object.tags:
967                 if len(event_object.tags) > 128:
968                     raise ValueError("too many tags")
969                 tag_directives_start = tag_directives_value
970                 tag_directives_end = tag_directives_value
971                 cache = []
972                 for handle in event_object.tags:
973                     prefix = event_object.tags[handle]
974                     if PyUnicode_CheckExact(handle):
975                         handle = PyUnicode_AsUTF8String(handle)
976                         cache.append(handle)
977                     if not PyString_CheckExact(handle):
978                         raise TypeError("tag handle must be a string")
979                     tag_directives_end.handle = PyString_AS_STRING(handle)
980                     if PyUnicode_CheckExact(prefix):
981                         prefix = PyUnicode_AsUTF8String(prefix)
982                         cache.append(prefix)
983                     if not PyString_CheckExact(prefix):
984                         raise TypeError("tag prefix must be a string")
985                     tag_directives_end.prefix = PyString_AS_STRING(prefix)
986                     tag_directives_end = tag_directives_end+1
987             implicit = 1
988             if event_object.explicit:
989                 implicit = 0
990             if yaml_document_start_event_initialize(event, version_directive,
991                     tag_directives_start, tag_directives_end, implicit) == 0:
992                 raise MemoryError
993         elif event_class is DocumentEndEvent:
994             implicit = 1
995             if event_object.explicit:
996                 implicit = 0
997             yaml_document_end_event_initialize(event, implicit)
998         elif event_class is AliasEvent:
999             anchor = NULL
1000             anchor_object = event_object.anchor
1001             if PyUnicode_CheckExact(anchor_object):
1002                 anchor_object = PyUnicode_AsUTF8String(anchor_object)
1003             if not PyString_CheckExact(anchor_object):
1004                 raise TypeError("anchor must be a string")
1005             anchor = PyString_AS_STRING(anchor_object)
1006             if yaml_alias_event_initialize(event, anchor) == 0:
1007                 raise MemoryError
1008         elif event_class is ScalarEvent:
1009             anchor = NULL
1010             anchor_object = event_object.anchor
1011             if anchor_object is not None:
1012                 if PyUnicode_CheckExact(anchor_object):
1013                     anchor_object = PyUnicode_AsUTF8String(anchor_object)
1014                 if not PyString_CheckExact(anchor_object):
1015                     raise TypeError("anchor must be a string")
1016                 anchor = PyString_AS_STRING(anchor_object)
1017             tag = NULL
1018             tag_object = event_object.tag
1019             if tag_object is not None:
1020                 if PyUnicode_CheckExact(tag_object):
1021                     tag_object = PyUnicode_AsUTF8String(tag_object)
1022                 if not PyString_CheckExact(tag_object):
1023                     raise TypeError("tag must be a string")
1024                 tag = PyString_AS_STRING(tag_object)
1025             value_object = event_object.value
1026             if PyUnicode_CheckExact(value_object):
1027                 value_object = PyUnicode_AsUTF8String(value_object)
1028             if not PyString_CheckExact(value_object):
1029                 raise TypeError("value must be a string")
1030             value = PyString_AS_STRING(value_object)
1031             length = PyString_GET_SIZE(value_object)
1032             plain_implicit = 0
1033             quoted_implicit = 0
1034             if event_object.implicit is not None:
1035                 plain_implicit = event_object.implicit[0]
1036                 quoted_implicit = event_object.implicit[1]
1037             style_object = event_object.style
1038             scalar_style = YAML_PLAIN_SCALAR_STYLE
1039             if style_object == "'":
1040                 scalar_style = YAML_SINGLE_QUOTED_SCALAR_STYLE
1041             elif style_object == "\"":
1042                 scalar_style = YAML_DOUBLE_QUOTED_SCALAR_STYLE
1043             elif style_object == "|":
1044                 scalar_style = YAML_LITERAL_SCALAR_STYLE
1045             elif style_object == ">":
1046                 scalar_style = YAML_FOLDED_SCALAR_STYLE
1047             if yaml_scalar_event_initialize(event, anchor, tag, value, length,
1048                     plain_implicit, quoted_implicit, scalar_style) == 0:
1049                 raise MemoryError
1050         elif event_class is SequenceStartEvent:
1051             anchor = NULL
1052             anchor_object = event_object.anchor
1053             if anchor_object is not None:
1054                 if PyUnicode_CheckExact(anchor_object):
1055                     anchor_object = PyUnicode_AsUTF8String(anchor_object)
1056                 if not PyString_CheckExact(anchor_object):
1057                     raise TypeError("anchor must be a string")
1058                 anchor = PyString_AS_STRING(anchor_object)
1059             tag = NULL
1060             tag_object = event_object.tag
1061             if tag_object is not None:
1062                 if PyUnicode_CheckExact(tag_object):
1063                     tag_object = PyUnicode_AsUTF8String(tag_object)
1064                 if not PyString_CheckExact(tag_object):
1065                     raise TypeError("tag must be a string")
1066                 tag = PyString_AS_STRING(tag_object)
1067             implicit = 0
1068             if event_object.implicit:
1069                 implicit = 1
1070             sequence_style = YAML_BLOCK_SEQUENCE_STYLE
1071             if event_object.flow_style:
1072                 sequence_style = YAML_FLOW_SEQUENCE_STYLE
1073             if yaml_sequence_start_event_initialize(event, anchor, tag,
1074                     implicit, sequence_style) == 0:
1075                 raise MemoryError
1076         elif event_class is MappingStartEvent:
1077             anchor = NULL
1078             anchor_object = event_object.anchor
1079             if anchor_object is not None:
1080                 if PyUnicode_CheckExact(anchor_object):
1081                     anchor_object = PyUnicode_AsUTF8String(anchor_object)
1082                 if not PyString_CheckExact(anchor_object):
1083                     raise TypeError("anchor must be a string")
1084                 anchor = PyString_AS_STRING(anchor_object)
1085             tag = NULL
1086             tag_object = event_object.tag
1087             if tag_object is not None:
1088                 if PyUnicode_CheckExact(tag_object):
1089                     tag_object = PyUnicode_AsUTF8String(tag_object)
1090                 if not PyString_CheckExact(tag_object):
1091                     raise TypeError("tag must be a string")
1092                 tag = PyString_AS_STRING(tag_object)
1093             implicit = 0
1094             if event_object.implicit:
1095                 implicit = 1
1096             mapping_style = YAML_BLOCK_MAPPING_STYLE
1097             if event_object.flow_style:
1098                 mapping_style = YAML_FLOW_MAPPING_STYLE
1099             if yaml_mapping_start_event_initialize(event, anchor, tag,
1100                     implicit, mapping_style) == 0:
1101                 raise MemoryError
1102         elif event_class is SequenceEndEvent:
1103             yaml_sequence_end_event_initialize(event)
1104         elif event_class is MappingEndEvent:
1105             yaml_mapping_end_event_initialize(event)
1106         else:
1107             raise TypeError("invalid event %s" % event_object)
1108         return 1
1109
1110     def emit(self, event_object):
1111         cdef yaml_event_t event
1112         self._object_to_event(event_object, &event)
1113         if yaml_emitter_emit(&self.emitter, &event) == 0:
1114             error = self._emitter_error()
1115             raise error
1116
1117     def open(self):
1118         cdef yaml_event_t event
1119         if self.closed == -1:
1120             yaml_stream_start_event_initialize(&event, self.use_encoding)
1121             if yaml_emitter_emit(&self.emitter, &event) == 0:
1122                 error = self._emitter_error()
1123                 raise error
1124             self.closed = 0
1125         elif self.closed == 1:
1126             raise SerializerError("serializer is closed")
1127         else:
1128             raise SerializerError("serializer is already opened")
1129
1130     def close(self):
1131         cdef yaml_event_t event
1132         if self.closed == -1:
1133             raise SerializerError("serializer is not opened")
1134         elif self.closed == 0:
1135             yaml_stream_end_event_initialize(&event)
1136             if yaml_emitter_emit(&self.emitter, &event) == 0:
1137                 error = self._emitter_error()
1138                 raise error
1139             self.closed = 1
1140
1141     def serialize(self, node):
1142         cdef yaml_event_t event
1143         cdef yaml_version_directive_t version_directive_value
1144         cdef yaml_version_directive_t *version_directive
1145         cdef yaml_tag_directive_t tag_directives_value[128]
1146         cdef yaml_tag_directive_t *tag_directives_start
1147         cdef yaml_tag_directive_t *tag_directives_end
1148         if self.closed == -1:
1149             raise SerializerError("serializer is not opened")
1150         elif self.closed == 1:
1151             raise SerializerError("serializer is closed")
1152         cache = []
1153         version_directive = NULL
1154         if self.use_version:
1155             version_directive_value.major = self.use_version[0]
1156             version_directive_value.minor = self.use_version[1]
1157             version_directive = &version_directive_value
1158         tag_directives_start = NULL
1159         tag_directives_end = NULL
1160         if self.use_tags:
1161             if len(self.use_tags) > 128:
1162                 raise ValueError("too many tags")
1163             tag_directives_start = tag_directives_value
1164             tag_directives_end = tag_directives_value
1165             for handle in self.use_tags:
1166                 prefix = self.use_tags[handle]
1167                 if PyUnicode_CheckExact(handle):
1168                     handle = PyUnicode_AsUTF8String(handle)
1169                     cache.append(handle)
1170                 if not PyString_CheckExact(handle):
1171                     raise TypeError("tag handle must be a string")
1172                 tag_directives_end.handle = PyString_AS_STRING(handle)
1173                 if PyUnicode_CheckExact(prefix):
1174                     prefix = PyUnicode_AsUTF8String(prefix)
1175                     cache.append(prefix)
1176                 if not PyString_CheckExact(prefix):
1177                     raise TypeError("tag prefix must be a string")
1178                 tag_directives_end.prefix = PyString_AS_STRING(prefix)
1179                 tag_directives_end = tag_directives_end+1
1180         if yaml_document_start_event_initialize(&event, version_directive,
1181                 tag_directives_start, tag_directives_end,
1182                 self.document_start_implicit) == 0:
1183             raise MemoryError
1184         if yaml_emitter_emit(&self.emitter, &event) == 0:
1185             error = self._emitter_error()
1186             raise error
1187         self._anchor_node(node)
1188         self._serialize_node(node, None, None)
1189         yaml_document_end_event_initialize(&event, self.document_end_implicit)
1190         if yaml_emitter_emit(&self.emitter, &event) == 0:
1191             error = self._emitter_error()
1192             raise error
1193         self.serialized_nodes = {}
1194         self.anchors = {}
1195         self.last_alias_id = 0
1196
1197     cdef int _anchor_node(self, object node) except 0:
1198         if node in self.anchors:
1199             if self.anchors[node] is None:
1200                 self.last_alias_id = self.last_alias_id+1
1201                 self.anchors[node] = "id%03d" % self.last_alias_id
1202         else:
1203             self.anchors[node] = None
1204             node_class = node.__class__
1205             if node_class is SequenceNode:
1206                 for item in node.value:
1207                     self._anchor_node(item)
1208             elif node_class is MappingNode:
1209                 for key, value in node.value:
1210                     self._anchor_node(key)
1211                     self._anchor_node(value)
1212         return 1
1213
1214     cdef int _serialize_node(self, object node, object parent, object index) except 0:
1215         cdef yaml_event_t event
1216         cdef int implicit
1217         cdef int plain_implicit
1218         cdef int quoted_implicit
1219         cdef char *anchor
1220         cdef char *tag
1221         cdef char *value
1222         cdef int length
1223         cdef int item_index
1224         cdef yaml_scalar_style_t scalar_style
1225         cdef yaml_sequence_style_t sequence_style
1226         cdef yaml_mapping_style_t mapping_style
1227         anchor_object = self.anchors[node]
1228         anchor = NULL
1229         if anchor_object is not None:
1230             anchor = PyString_AS_STRING(anchor_object)
1231         if node in self.serialized_nodes:
1232             if yaml_alias_event_initialize(&event, anchor) == 0:
1233                 raise MemoryError
1234             if yaml_emitter_emit(&self.emitter, &event) == 0:
1235                 error = self._emitter_error()
1236                 raise error
1237         else:
1238             node_class = node.__class__
1239             self.serialized_nodes[node] = True
1240             self.descend_resolver(parent, index)
1241             if node_class is ScalarNode:
1242                 plain_implicit = 0
1243                 quoted_implicit = 0
1244                 tag_object = node.tag
1245                 if self.resolve(ScalarNode, node.value, (True, False)) == tag_object:
1246                     plain_implicit = 1
1247                 if self.resolve(ScalarNode, node.value, (False, True)) == tag_object:
1248                     quoted_implicit = 1
1249                 tag = NULL
1250                 if tag_object is not None:
1251                     if PyUnicode_CheckExact(tag_object):
1252                         tag_object = PyUnicode_AsUTF8String(tag_object)
1253                     if not PyString_CheckExact(tag_object):
1254                         raise TypeError("tag must be a string")
1255                     tag = PyString_AS_STRING(tag_object)
1256                 value_object = node.value
1257                 if PyUnicode_CheckExact(value_object):
1258                     value_object = PyUnicode_AsUTF8String(value_object)
1259                 if not PyString_CheckExact(value_object):
1260                     raise TypeError("value must be a string")
1261                 value = PyString_AS_STRING(value_object)
1262                 length = PyString_GET_SIZE(value_object)
1263                 style_object = node.style
1264                 scalar_style = YAML_PLAIN_SCALAR_STYLE
1265                 if style_object == "'":
1266                     scalar_style = YAML_SINGLE_QUOTED_SCALAR_STYLE
1267                 elif style_object == "\"":
1268                     scalar_style = YAML_DOUBLE_QUOTED_SCALAR_STYLE
1269                 elif style_object == "|":
1270                     scalar_style = YAML_LITERAL_SCALAR_STYLE
1271                 elif style_object == ">":
1272                     scalar_style = YAML_FOLDED_SCALAR_STYLE
1273                 if yaml_scalar_event_initialize(&event, anchor, tag, value, length,
1274                         plain_implicit, quoted_implicit, scalar_style) == 0:
1275                     raise MemoryError
1276                 if yaml_emitter_emit(&self.emitter, &event) == 0:
1277                     error = self._emitter_error()
1278                     raise error
1279             elif node_class is SequenceNode:
1280                 implicit = 0
1281                 tag_object = node.tag
1282                 if self.resolve(SequenceNode, node.value, True) == tag_object:
1283                     implicit = 1
1284                 tag = NULL
1285                 if tag_object is not None:
1286                     if PyUnicode_CheckExact(tag_object):
1287                         tag_object = PyUnicode_AsUTF8String(tag_object)
1288                     if not PyString_CheckExact(tag_object):
1289                         raise TypeError("tag must be a string")
1290                     tag = PyString_AS_STRING(tag_object)
1291                 sequence_style = YAML_BLOCK_SEQUENCE_STYLE
1292                 if node.flow_style:
1293                     sequence_style = YAML_FLOW_SEQUENCE_STYLE
1294                 if yaml_sequence_start_event_initialize(&event, anchor, tag,
1295                         implicit, sequence_style) == 0:
1296                     raise MemoryError
1297                 if yaml_emitter_emit(&self.emitter, &event) == 0:
1298                     error = self._emitter_error()
1299                     raise error
1300                 item_index = 0
1301                 for item in node.value:
1302                     self._serialize_node(item, node, item_index)
1303                     item_index = item_index+1
1304                 yaml_sequence_end_event_initialize(&event)
1305                 if yaml_emitter_emit(&self.emitter, &event) == 0:
1306                     error = self._emitter_error()
1307                     raise error
1308             elif node_class is MappingNode:
1309                 implicit = 0
1310                 tag_object = node.tag
1311                 if self.resolve(MappingNode, node.value, True) == tag_object:
1312                     implicit = 1
1313                 tag = NULL
1314                 if tag_object is not None:
1315                     if PyUnicode_CheckExact(tag_object):
1316                         tag_object = PyUnicode_AsUTF8String(tag_object)
1317                     if not PyString_CheckExact(tag_object):
1318                         raise TypeError("tag must be a string")
1319                     tag = PyString_AS_STRING(tag_object)
1320                 mapping_style = YAML_BLOCK_MAPPING_STYLE
1321                 if node.flow_style:
1322                     mapping_style = YAML_FLOW_MAPPING_STYLE
1323                 if yaml_mapping_start_event_initialize(&event, anchor, tag,
1324                         implicit, mapping_style) == 0:
1325                     raise MemoryError
1326                 if yaml_emitter_emit(&self.emitter, &event) == 0:
1327                     error = self._emitter_error()
1328                     raise error
1329                 for item_key, item_value in node.value:
1330                     self._serialize_node(item_key, node, None)
1331                     self._serialize_node(item_value, node, item_key)
1332                 yaml_mapping_end_event_initialize(&event)
1333                 if yaml_emitter_emit(&self.emitter, &event) == 0:
1334                     error = self._emitter_error()
1335                     raise error
1336         return 1
1337
1338 cdef int output_handler(void *data, char *buffer, int size) except 0:
1339     cdef CEmitter emitter
1340     emitter = <CEmitter>data
1341     value = PyString_FromStringAndSize(buffer, size)
1342     emitter.stream.write(value)
1343     return 1
1344
Note: See TracBrowser for help on using the browser.