Changeset 4 for trunk/ext/_syckmodule.c
- Timestamp:
- 07/16/05 15:14:11 (8 years ago)
- File:
-
- 1 edited
-
trunk/ext/_syckmodule.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/ext/_syckmodule.c
r3 r4 3 3 #include <syck.h> 4 4 5 static PyMethodDef _syck_methods[] = { 5 /* Global objects. */ 6 7 static PyObject *_syck_Error; 8 9 static PyObject *_syck_ScalarKind; 10 static PyObject *_syck_SeqKind; 11 static PyObject *_syck_MapKind; 12 13 /* Node type. */ 14 15 typedef struct { 16 PyObject_HEAD 17 PyObject *kind; 18 PyObject *type_id; 19 PyObject *value; 20 } _syck_Node; 21 22 static void 23 _syck_Node_dealloc(_syck_Node *self) 24 { 25 Py_XDECREF(self->kind); 26 Py_XDECREF(self->type_id); 27 Py_XDECREF(self->value); 28 PyObject_Del(self); 29 } 30 31 static PyObject * 32 _syck_Node_getattr(_syck_Node *self, char *name) 33 { 34 PyObject *value; 35 36 if (strcmp(name, "kind") == 0) 37 value = self->kind; 38 else if (strcmp(name, "type_id") == 0) 39 value = self->type_id; 40 else if (strcmp(name, "value") == 0) 41 value = self->value; 42 else { 43 PyErr_SetString(PyExc_AttributeError, name); 44 return NULL; 45 } 46 47 Py_INCREF(value); 48 return value; 49 } 50 51 static char _syck_Node_doc[] = 52 "Node object\n" 53 "\n" 54 "Attributes of the Node object:\n\n" 55 "kind -- 'scalar', 'seq', or 'map'.\n" 56 "type_id -- the tag of the node.\n" 57 "value -- the value of the node, a string, list or dict object.\n"; 58 59 static PyTypeObject _syck_NodeType = { 60 PyObject_HEAD_INIT(NULL) 61 0, /* ob_size */ 62 "_syck.Node", /* tp_name */ 63 sizeof(_syck_Node), /* tp_basicsize */ 64 0, /* tp_itemsize */ 65 (destructor)_syck_Node_dealloc, /* tp_dealloc */ 66 0, /* tp_print */ 67 (getattrfunc)_syck_Node_getattr, /* tp_getattr */ 68 0, /* tp_setattr */ 69 0, /* tp_compare */ 70 0, /* tp_repr */ 71 0, /* tp_as_number */ 72 0, /* tp_as_sequence */ 73 0, /* tp_as_mapping */ 74 0, /* tp_hash */ 75 0, /* tp_call */ 76 0, /* tp_str */ 77 0, /* tp_getattro */ 78 0, /* tp_setattro */ 79 0, /* tp_as_buffer */ 80 Py_TPFLAGS_DEFAULT, /* tp_flags */ 81 _syck_Node_doc, /* tp_doc */ 82 }; 83 84 static PyObject * 85 _syck_NewNode(PyObject *self, PyObject *args) 86 { 87 if (!PyArg_ParseTuple(args, ":_syck.Node")) 88 return NULL; 89 90 PyErr_SetString(PyExc_TypeError, "Node object cannot be created explicitly. Use _syck.Parser.parse() instead."); 91 return NULL; 92 } 93 94 static char _syck_NewNode_doc[] = 95 "Node object cannot be created explicitly. Use _syck.Parser.parse() instead."; 96 97 static PyObject * 98 _syck_NewNode_FromValue(char *type_id, PyObject *value) /* Note: steals the reference to the value. */ 99 { 100 _syck_Node *self; 101 PyObject *kind; 102 103 self = PyObject_NEW(_syck_Node, &_syck_NodeType); 104 if (!self) { 105 Py_XDECREF(value); 106 return NULL; 107 } 108 109 self->value = value; 110 111 if (PyList_Check(value)) 112 kind = _syck_SeqKind; 113 else if (PyDict_Check(value)) 114 kind = _syck_MapKind; 115 else 116 kind = _syck_ScalarKind; 117 Py_INCREF(kind); 118 self->kind = kind; 119 120 if (type_id) { 121 self->type_id = PyString_FromString(type_id); 122 if (!self->type_id) { 123 Py_DECREF(self); 124 return NULL; 125 } 126 } 127 else { 128 Py_INCREF(Py_None); 129 self->type_id = Py_None; 130 } 131 132 return (PyObject *)self; 133 } 134 135 /* Parser type. */ 136 137 typedef struct { 138 PyObject_HEAD 139 PyObject *source; 140 PyObject *resolver; 141 PyObject *symbols; 142 int error_state; 143 int mark; 144 SyckParser *parser; 145 } _syck_Parser; 146 147 static PyObject * 148 _syck_Parser_parse(_syck_Parser *self, PyObject *args) 149 { 150 SYMID index; 151 PyObject *value; 152 153 if (!PyArg_ParseTuple(args, ":parse")) 154 return NULL; 155 156 if (!self->parser) { 157 PyErr_SetString(PyExc_TypeError, "Parser object is closed"); 158 return NULL; 159 } 160 161 self->symbols = PyList_New(0); 162 if (!self->symbols) { 163 return NULL; 164 } 165 166 index = syck_parse(self->parser); 167 if (!self->error_state && !self->parser->eof) { 168 value = PyList_GetItem(self->symbols, index-1); 169 } 170 171 Py_DECREF(self->symbols); 172 173 if (self->error_state) { 174 self->error_state = 0; 175 return NULL; 176 } 177 178 if (self->parser->eof) { 179 Py_INCREF(Py_None); 180 return Py_None; 181 } 182 183 return value; 184 } 185 186 static char _syck_Parser_parse_doc[] = 187 "Parses the next document in the YAML stream, return the root Node object or None on EOF."; 188 189 static PyObject * 190 _syck_Parser_parse_documents(_syck_Parser *self, PyObject *args) 191 { 192 SYMID index; 193 PyObject *value = NULL; 194 PyObject *result = NULL; 195 196 if (!PyArg_ParseTuple(args, ":parse_document")) 197 return NULL; 198 199 if (!self->parser) { 200 PyErr_SetString(PyExc_TypeError, "Parser object is closed"); 201 return NULL; 202 } 203 204 result = PyList_New(0); 205 if (!result) return NULL; 206 207 while (1) { 208 209 self->symbols = PyList_New(0); 210 if (!self->symbols) { 211 Py_DECREF(result); 212 return NULL; 213 }; 214 215 index = syck_parse(self->parser); 216 217 if (!self->error_state && !self->parser->eof) { 218 value = PyList_GetItem(self->symbols, index-1); 219 if (!value) { 220 Py_DECREF(self->symbols); 221 Py_DECREF(result); 222 return NULL; 223 } 224 if (PyList_Append(result, value) < 0) { 225 Py_DECREF(self->symbols); 226 Py_DECREF(value); 227 Py_DECREF(result); 228 return NULL; 229 } 230 Py_DECREF(value); 231 } 232 233 Py_DECREF(self->symbols); 234 235 if (self->error_state) { 236 self->error_state = 0; 237 Py_DECREF(result); 238 return NULL; 239 } 240 241 if (self->parser->eof) break; 242 } 243 244 return result; 245 } 246 247 static char _syck_Parser_parse_documents_doc[] = 248 "Parses the entire YAML stream and returns list of documents."; 249 250 static PyObject * 251 _syck_Parser_close(_syck_Parser *self, PyObject *args) 252 { 253 if (!PyArg_ParseTuple(args, ":close")) 254 return NULL; 255 256 Py_XDECREF(self->source); 257 self->source = NULL; 258 259 if (self->parser) { 260 syck_free_parser(self->parser); 261 } 262 self->parser = NULL; 263 264 Py_INCREF(Py_None); 265 return Py_None; 266 } 267 268 static char _syck_Parser_close_doc[] = 269 "Closes the parser and frees memory"; 270 271 static PyMethodDef _syck_Parser_methods[] = { 272 {"parse", (PyCFunction)_syck_Parser_parse, METH_VARARGS, _syck_Parser_parse_doc}, 273 {"parse_documents", (PyCFunction)_syck_Parser_parse_documents, METH_VARARGS, _syck_Parser_parse_documents_doc}, 274 {"close", (PyCFunction)_syck_Parser_close, METH_VARARGS, _syck_Parser_close_doc}, 6 275 {NULL} /* Sentinel */ 7 276 }; 8 277 278 static void 279 _syck_Parser_dealloc(_syck_Parser *self) 280 { 281 Py_XDECREF(self->source); 282 if (self->parser) { 283 syck_free_parser(self->parser); 284 } 285 PyObject_Del(self); 286 } 287 288 static PyObject * 289 _syck_Parser_getattr(_syck_Parser *self, char *name) 290 { 291 return Py_FindMethod(_syck_Parser_methods, (PyObject *)self, name); 292 } 293 294 static char _syck_Parser_doc[] = 295 "_syck.Parser(yaml_string_or_file, implicit_typing=True, taguri_expansion=True) -> Parser object\n" 296 "\n" 297 "Methods of the Parser object:\n\n" 298 "parse() -- Parses the next document in the YAML stream, return the root Node object or None on EOF.\n" 299 "parse_documents() -- Parses the entire YAML stream and returns list of documents.\n" 300 "close() -- Closes the parser and frees memory.\n"; 301 302 static PyTypeObject _syck_ParserType = { 303 PyObject_HEAD_INIT(NULL) 304 0, /* ob_size */ 305 "_syck.Parser", /* tp_name */ 306 sizeof(_syck_Parser), /* tp_basicsize */ 307 0, /* tp_itemsize */ 308 (destructor)_syck_Parser_dealloc, /* tp_dealloc */ 309 0, /* tp_print */ 310 (getattrfunc)_syck_Parser_getattr, /* tp_getattr */ 311 0, /* tp_setattr */ 312 0, /* tp_compare */ 313 0, /* tp_repr */ 314 0, /* tp_as_number */ 315 0, /* tp_as_sequence */ 316 0, /* tp_as_mapping */ 317 0, /* tp_hash */ 318 0, /* tp_call */ 319 0, /* tp_str */ 320 0, /* tp_getattro */ 321 0, /* tp_setattro */ 322 0, /* tp_as_buffer */ 323 Py_TPFLAGS_DEFAULT, /* tp_flags */ 324 _syck_Parser_doc, /* tp_doc */ 325 }; 326 327 static long 328 _syck_Parser_io_file_read(char *buf, SyckIoFile *file, long max_size, long skip) 329 { 330 _syck_Parser *runtime = (_syck_Parser *)file->ptr; 331 332 PyObject *value; 333 334 char *str; 335 int length; 336 337 buf[skip] = '\0'; 338 339 if (runtime->error_state) { 340 return skip; 341 } 342 343 max_size -= skip; 344 345 value = PyObject_CallMethod(runtime->source, "read", "(i)", max_size); 346 if (!value) { 347 runtime->error_state = 1; 348 return skip; 349 } 350 351 if (!PyString_Check(value)) { 352 Py_DECREF(value); 353 PyErr_SetString(PyExc_TypeError, "file-like object should return a string"); 354 runtime->error_state = 1; 355 356 return skip; 357 } 358 359 str = PyString_AS_STRING(value); 360 length = PyString_GET_SIZE(value); 361 if (!length) { 362 Py_DECREF(value); 363 return skip; 364 } 365 366 if (length > max_size) { 367 Py_DECREF(value); 368 PyErr_SetString(PyExc_ValueError, "read returns an overly long string"); 369 runtime->error_state = 1; 370 return skip; 371 } 372 373 memcpy(buf+skip, str, length); 374 length += skip; 375 buf[length] = '\0'; 376 377 Py_DECREF(value); 378 379 return length; 380 } 381 382 static SYMID 383 _syck_Parser_node_handler(SyckParser *parser, SyckNode *node) 384 { 385 _syck_Parser *runtime = (_syck_Parser *)parser->bonus; 386 387 SYMID index; 388 PyObject *object = NULL; 389 390 PyObject *key, *value, *item; 391 int k; 392 393 if (runtime->error_state) 394 return 0; 395 396 switch (node->kind) { 397 398 case syck_str_kind: 399 object = PyString_FromStringAndSize(node->data.str->ptr, 400 node->data.str->len); 401 if (!object) goto error; 402 break; 403 404 case syck_seq_kind: 405 object = PyList_New(node->data.list->idx); 406 if (!object) goto error; 407 for (k = 0; k < node->data.list->idx; k++) { 408 index = syck_seq_read(node, k); 409 item = PyList_GetItem(runtime->symbols, index-1); 410 if (!item) goto error; 411 Py_INCREF(item); 412 PyList_SET_ITEM(object, k, item); 413 } 414 break; 415 416 case syck_map_kind: 417 object = PyDict_New(); 418 if (!object) goto error; 419 for (k = 0; k < node->data.pairs->idx; k++) 420 { 421 index = syck_map_read(node, map_key, k); 422 key = PyList_GetItem(runtime->symbols, index-1); 423 if (!key) goto error; 424 index = syck_map_read(node, map_value, k); 425 value = PyList_GetItem(runtime->symbols, index-1); 426 if (!value) goto error; 427 if (PyDict_SetItem(object, key, value) < 0) 428 goto error; 429 } 430 break; 431 } 432 433 object = _syck_NewNode_FromValue(node->type_id, object); 434 if (!object) goto error; 435 436 if (PyList_Append(runtime->symbols, object) < 0) 437 goto error; 438 439 index = PyList_Size(runtime->symbols); 440 return index; 441 442 error: 443 Py_XDECREF(object); 444 runtime->error_state = 1; 445 return 0; 446 } 447 448 static void 449 _syck_Parser_error_handler(SyckParser *parser, char *str) 450 { 451 _syck_Parser *runtime = (_syck_Parser *)parser->bonus; 452 PyObject *value; 453 454 if (runtime->error_state) return; 455 456 runtime->error_state = 1; 457 458 value = Py_BuildValue("(sii)", str, parser->linect, parser->cursor-parser->lineptr); 459 if (value) { 460 PyErr_SetObject(_syck_Error, value); 461 } 462 } 463 464 static PyObject * 465 _syck_NewParser(PyObject *self, PyObject *args, PyObject *kwds) 466 { 467 _syck_Parser *parser; 468 PyObject *source; 469 int implicit_typing = 1; 470 int taguri_expansion = 1; 471 472 static char *kwdlist[] = {"source", "implicit_typing", "taguri_expansion", NULL}; 473 474 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|ii", kwdlist, 475 &source, &implicit_typing, &taguri_expansion)) 476 return NULL; 477 478 parser = PyObject_NEW(_syck_Parser, &_syck_ParserType); 479 if (!parser) 480 return NULL; 481 482 Py_INCREF(source); 483 parser->source = source; 484 parser->error_state = 0; 485 486 parser->parser = syck_new_parser(); 487 parser->parser->bonus = parser; 488 489 if (PyString_Check(source)) { 490 syck_parser_str_auto(parser->parser, PyString_AS_STRING(source), NULL); 491 } 492 else { 493 syck_parser_file(parser->parser, (FILE *)parser, _syck_Parser_io_file_read); 494 } 495 syck_parser_implicit_typing(parser->parser, implicit_typing); 496 syck_parser_taguri_expansion(parser->parser, taguri_expansion); 497 498 syck_parser_handler(parser->parser, _syck_Parser_node_handler); 499 syck_parser_error_handler(parser->parser, _syck_Parser_error_handler); 500 /* 501 syck_parser_bad_anchor_handler(parser, _syck_Parser_bad_anchor_handler); 502 */ 503 504 return (PyObject *)parser; 505 } 506 507 static char _syck_NewParser_doc[] = 508 "Creates a new Parser object."; 509 510 /* The module definitions. */ 511 512 static PyMethodDef _syck_methods[] = { 513 {"Node", (PyCFunction)_syck_NewNode, METH_VARARGS, _syck_NewNode_doc}, 514 {"Parser", (PyCFunction)_syck_NewParser, METH_VARARGS|METH_KEYWORDS, _syck_NewParser_doc}, 515 {NULL} /* Sentinel */ 516 }; 517 9 518 static char _syck_doc[] = 10 519 "This module provides low-level access to the Syck parser and emitter.\n" 11 "Do not use this module directly, use the module 'syck' instead.\n";520 "Do not use this module directly, use the package 'syck' instead.\n"; 12 521 13 522 PyMODINIT_FUNC 14 523 init_syck(void) 15 524 { 16 Py_InitModule3("_syck", _syck_methods, _syck_doc); 17 } 18 525 PyObject *m; 526 527 _syck_NodeType.ob_type = &PyType_Type; 528 _syck_ParserType.ob_type = &PyType_Type; 529 530 _syck_Error = PyErr_NewException("_syck.error", NULL, NULL); 531 if (!_syck_Error) 532 return; 533 534 _syck_ScalarKind = PyString_FromString("scalar"); 535 if (!_syck_ScalarKind) 536 return; 537 _syck_SeqKind = PyString_FromString("seq"); 538 if (!_syck_SeqKind) 539 return; 540 _syck_MapKind = PyString_FromString("map"); 541 if (!_syck_MapKind) 542 return; 543 544 m = Py_InitModule3("_syck", _syck_methods, _syck_doc); 545 546 Py_INCREF(_syck_Error); 547 if (!PyModule_AddObject(m, "error", _syck_Error) < 0) 548 return; 549 550 Py_INCREF(&_syck_NodeType); 551 if (PyModule_AddObject(m, "NodeType", (PyObject *)&_syck_NodeType) < 0) 552 return; 553 554 Py_INCREF(&_syck_ParserType); 555 if (PyModule_AddObject(m, "ParserType", (PyObject *)&_syck_ParserType) < 0) 556 return; 557 } 558
Note: See TracChangeset
for help on using the changeset viewer.
