source: pyyaml/trunk/ext/_yaml.pyx @ 196

Revision 196, 8.9 KB checked in by xi, 8 years ago (diff)

Trying to make libyaml bindings faster.

RevLine 
[195]1
2import yaml
3
4def get_version_string():
5    return yaml_get_version_string()
6
7def get_version():
8    cdef int major, minor, patch
9    yaml_get_version(&major, &minor, &patch)
10    return (major, minor, patch)
11
[196]12def test_scanner(data):
13    cdef yaml_parser_t *parser
14    cdef yaml_token_t *token
15    cdef int done
16    if PyString_CheckExact(data) == 0:
17        raise TypeError("string input required")
18    parser = yaml_parser_new()
19    if parser == NULL:
20        raise MemoryError
21    yaml_parser_set_input_string(parser, PyString_AS_STRING(data), PyString_GET_SIZE(data))
22    done = 0
23    while done == 0:
24        token = yaml_parser_get_token(parser)
25        if token == NULL:
26            raise MemoryError
27        if token.type == YAML_STREAM_END_TOKEN:
28            done = 1
29        yaml_token_delete(token)
30    yaml_parser_delete(parser)
31
[195]32cdef class Scanner:
33
34    cdef yaml_parser_t *parser
35    cdef int eof
36    cdef object stream
[196]37    cdef yaml_token_t *cached_token
38    cdef object cached_obj
[195]39
40    def __init__(self, stream):
41        if hasattr(stream, 'read'):
42            stream = stream.read()
43        if PyUnicode_CheckExact(stream) != 0:
44            stream = stream.encode('utf-8')
45        if PyString_CheckExact(stream) == 0:
46            raise TypeError("a string or stream input is required")
47        self.parser = yaml_parser_new()
48        if self.parser == NULL:
49            raise MemoryError
50        yaml_parser_set_input_string(self.parser, PyString_AS_STRING(stream), PyString_GET_SIZE(stream))
51        self.eof = 0
52        self.stream = stream
[196]53        self.cached_token = NULL
54        self.cached_obj = None
[195]55
56    def __dealloc__(self):
57        if self.parser != NULL:
58            yaml_parser_delete(self.parser)
59            self.parser = NULL
60
61    cdef object _convert(self, yaml_token_t *token):
62        if token == NULL:
63            if self.parser.error == YAML_MEMORY_ERROR:
64                raise MemoryError
65            elif self.parser.error == YAML_READER_ERROR:
66                raise yaml.reader.ReaderError("<input>",
67                        self.parser.problem_offset,
68                        self.parser.problem_value,
69                        '?', self.parser.problem)
70            elif self.parser.error == YAML_SCANNER_ERROR:
71                if self.parser.context != NULL:
72                    raise yaml.scanner.ScannerError(
73                            self.parser.context,
74                            yaml.Mark("<input>",
75                                self.parser.context_mark.index,
76                                self.parser.context_mark.line,
77                                self.parser.context_mark.column,
78                                None, None),
79                            self.parser.problem,
80                            yaml.Mark("<input>",
81                                self.parser.problem_mark.index,
82                                self.parser.problem_mark.line,
83                                self.parser.problem_mark.column,
84                                None, None))
85                else:
86                    raise yaml.scanner.ScannerError(None, None,
87                            self.parser.problem,
88                            yaml.Mark("<input>",
89                                self.parser.problem_mark.index,
90                                self.parser.problem_mark.line,
91                                self.parser.problem_mark.column,
92                                None, None))
93            else:
94                raise RuntimeError("neither error nor token produced")
95        start_mark = yaml.Mark("<input>",
96                token.start_mark.index,
97                token.start_mark.line,
98                token.start_mark.column,
99                None, None)
100        end_mark = yaml.Mark("<input>",
101                token.end_mark.index,
102                token.end_mark.line,
103                token.end_mark.column,
104                None, None)
105        if token.type == YAML_STREAM_START_TOKEN:
106            return yaml.StreamStartToken(start_mark, end_mark)
107        elif token.type == YAML_STREAM_END_TOKEN:
108            return yaml.StreamEndToken(start_mark, end_mark)
109        elif token.type == YAML_VERSION_DIRECTIVE_TOKEN:
110            return yaml.DirectiveToken('YAML',
111                    (token.data.version_directive.major,
112                        token.data.version_directive.minor),
113                    start_mark, end_mark)
114        elif token.type == YAML_TAG_DIRECTIVE_TOKEN:
115            return yaml.DirectiveToken('TAG',
116                    (token.data.tag_directive.handle,
117                        token.data.tag_directive.prefix),
118                    start_mark, end_mark)
119        elif token.type == YAML_DOCUMENT_START_TOKEN:
120            return yaml.DocumentStartToken(start_mark, end_mark)
121        elif token.type == YAML_DOCUMENT_END_TOKEN:
122            return yaml.DocumentEndToken(start_mark, end_mark)
123        elif token.type == YAML_BLOCK_SEQUENCE_START_TOKEN:
124            return yaml.BlockSequenceStartToken(start_mark, end_mark)
125        elif token.type == YAML_BLOCK_MAPPING_START_TOKEN:
126            return yaml.BlockMappingStartToken(start_mark, end_mark)
127        elif token.type == YAML_BLOCK_END_TOKEN:
128            return yaml.BlockEndToken(start_mark, end_mark)
129        elif token.type == YAML_FLOW_SEQUENCE_START_TOKEN:
130            return yaml.FlowSequenceStartToken(start_mark, end_mark)
131        elif token.type == YAML_FLOW_SEQUENCE_END_TOKEN:
132            return yaml.FlowSequenceEndToken(start_mark, end_mark)
133        elif token.type == YAML_FLOW_MAPPING_START_TOKEN:
134            return yaml.FlowMappingStartToken(start_mark, end_mark)
135        elif token.type == YAML_FLOW_MAPPING_END_TOKEN:
136            return yaml.FlowMappingEndToken(start_mark, end_mark)
137        elif token.type == YAML_BLOCK_ENTRY_TOKEN:
138            return yaml.BlockEntryToken(start_mark, end_mark)
139        elif token.type == YAML_FLOW_ENTRY_TOKEN:
140            return yaml.FlowEntryToken(start_mark, end_mark)
141        elif token.type == YAML_KEY_TOKEN:
142            return yaml.KeyToken(start_mark, end_mark)
143        elif token.type == YAML_VALUE_TOKEN:
144            return yaml.ValueToken(start_mark, end_mark)
145        elif token.type == YAML_ALIAS_TOKEN:
146            return yaml.AliasToken(token.data.anchor,
147                    start_mark, end_mark)
148        elif token.type == YAML_ANCHOR_TOKEN:
149            return yaml.AnchorToken(token.data.anchor,
150                    start_mark, end_mark)
151        elif token.type == YAML_TAG_TOKEN:
152            handle = token.data.tag.handle
153            if handle == '':
154                handle = None
155            return yaml.TagToken((handle, token.data.tag.suffix),
156                    start_mark, end_mark)
157        elif token.type == YAML_SCALAR_TOKEN:
158            value = PyString_FromStringAndSize(token.data.scalar.value, token.data.scalar.length)
159            return yaml.ScalarToken(unicode(value, 'utf-8'),
160                    bool(token.data.scalar.style == YAML_PLAIN_SCALAR_STYLE),
161                    start_mark, end_mark)
162        else:
163            raise RuntimeError("unknown token type")
164
165    def get_token(self):
166        cdef yaml_token_t *token
[196]167        if self.cached_token != NULL:
168            yaml_token_delete(yaml_parser_get_token(self.parser))
169            obj = self.cached_obj
170            self.cached_token = NULL
171            self.cached_obj = None
172            return obj
[195]173        if self.eof != 0:
174            return None
175        token = yaml_parser_get_token(self.parser)
176        obj = self._convert(token)
177        if token.type == YAML_STREAM_END_TOKEN:
178            self.eof = 1
179        yaml_token_delete(token)
180        return obj
181
182    def peek_token(self):
183        cdef yaml_token_t *token
[196]184        if self.cached_token != NULL:
185            return self.cached_obj
[195]186        if self.eof != 0:
187            return None
188        token = yaml_parser_peek_token(self.parser)
[196]189        obj = self._convert(token)
190        if token.type == YAML_STREAM_END_TOKEN:
191            self.eof = 1
192        self.cached_token = token
193        self.cached_obj = obj
194        return obj
[195]195
196    def check_token(self, *choices):
197        cdef yaml_token_t *token
[196]198        if self.cached_token != NULL:
199            obj = self.cached_obj
200        elif self.eof != 0:
[195]201            return False
[196]202        else:
203            token = yaml_parser_peek_token(self.parser)
204            obj = self._convert(token)
205            if token.type == YAML_STREAM_END_TOKEN:
206                self.eof = 1
207            self.cached_token = token
208            self.cached_obj = obj
[195]209        if not choices:
210            return True
211        for choice in choices:
212            if isinstance(obj, choice):
213                return True
214        return False
215
216class Loader(Scanner,
217        yaml.parser.Parser,
218        yaml.composer.Composer,
219        yaml.constructor.Constructor,
220        yaml.resolver.Resolver):
221
222    def __init__(self, stream):
223        Scanner.__init__(self, stream)
224        yaml.parser.Parser.__init__(self)
225        yaml.composer.Composer.__init__(self)
226        yaml.constructor.Constructor.__init__(self)
227        yaml.resolver.Resolver.__init__(self)
228
229yaml.ExtLoader = Loader
230
Note: See TracBrowser for help on using the repository browser.