source: trunk/ext/_syckmodule.c @ 12

Revision 12, 30.0 KB checked in by xi, 9 years ago (diff)

Add _syck.Node and _syck.Scalar types.

Line 
1
2#include <Python.h>
3#include <syck.h>
4
5/* Python 2.2 compatibility. */
6
7#ifndef PyDoc_STR
8#define PyDoc_VAR(name)         static char name[]
9#define PyDoc_STR(str)          (str)
10#define PyDoc_STRVAR(name, str) PyDoc_VAR(name) = PyDoc_STR(str)
11#endif
12
13#ifndef PyMODINIT_FUNC
14#define PyMODINIT_FUNC  void
15#endif
16
17/* Global objects: _syck.error, 'scalar', 'seq', 'map',
18    '1quote', '2quote', 'fold', 'literal', 'plain', '+', '-'. */
19
20static PyObject *PySyck_Error;
21
22static PyObject *PySyck_ScalarKind;
23static PyObject *PySyck_SeqKind;
24static PyObject *PySyck_MapKind;
25
26static PyObject *PySyck_1QuoteStyle;
27static PyObject *PySyck_2QuoteStyle;
28static PyObject *PySyck_FoldStyle;
29static PyObject *PySyck_LiteralStyle;
30static PyObject *PySyck_PlainStyle;
31
32static PyObject *PySyck_StripChomp;
33static PyObject *PySyck_KeepChomp;
34
35/* The type _syck.Node. */
36
37PyDoc_STRVAR(PySyckNode_doc,
38    "The base Node type\n\n"
39    "_syck.Node is an abstract type. It is a base type for _syck.Scalar,\n"
40    "_syck.Seq, and _syck.Map. You cannot create an instance of _syck.Node\n"
41    "directly. You may use _syck.Node for type checking.\n");
42
43static PyTypeObject PySyckNode_Type = {
44    PyObject_HEAD_INIT(NULL)
45    0,                                          /* ob_size */
46    "_syck.Node",                               /* tp_name */
47    sizeof(PyObject),                           /* tp_basicsize */
48    0,                                          /* tp_itemsize */
49    0,                                          /* tp_dealloc */
50    0,                                          /* tp_print */
51    0,                                          /* tp_getattr */
52    0,                                          /* tp_setattr */
53    0,                                          /* tp_compare */
54    0,                                          /* tp_repr */
55    0,                                          /* tp_as_number */
56    0,                                          /* tp_as_sequence */
57    0,                                          /* tp_as_mapping */
58    0,                                          /* tp_hash */
59    0,                                          /* tp_call */
60    0,                                          /* tp_str */
61    0,                                          /* tp_getattro */
62    0,                                          /* tp_setattro */
63    0,                                          /* tp_as_buffer */
64    Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,     /* tp_flags */
65    PySyckNode_doc,                             /* tp_doc */
66};
67
68/* The type _syck.Scalar */
69
70PyDoc_STRVAR(PySyckScalar_doc,
71    "The Scalar node type\n\n"
72    "_syck.Scalar represents a scalar node in Syck parser and emitter\n"
73    "graph. A scalar node points to a single string value.\n\n"
74    "Attributes:\n\n"
75    "kind -- always 'scalar'; read-only\n"
76    "value -- the node value, a string\n"
77    "tag -- the node tag; a string or None\n"
78    "anchor -- the name of the node anchor or None; read-only\n"
79    "style -- the node style; None (means literal or plain),\n"
80    "         '1quote', '2quote', 'fold', 'literal', 'plain'\n"
81    "indent -- indentation, an integer; 0 means default\n"
82    "width -- the preferred width; 0 means default\n"
83    "chomp -- None (clip), '-' (strip), or '+' (keep)\n");
84
85typedef struct {
86    PyObject_HEAD
87    PyObject *value;
88    PyObject *tag;
89    PyObject *anchor;
90    enum scalar_style style;
91    int indent;
92    int width;
93    char chomp;
94} PySyckScalarObject;
95
96static int
97PySyckScalar_clear(PySyckScalarObject *self)
98{
99    Py_XDECREF(self->value);
100    self->value = NULL;
101    Py_XDECREF(self->tag);
102    self->tag = NULL;
103    Py_XDECREF(self->anchor);
104    self->anchor = NULL;
105
106    return 0;
107}
108
109static int
110PySyckScalar_traverse(PySyckScalarObject *self, visitproc visit, void *arg)
111{
112    if (self->value && visit(self->value, arg) < 0)
113        return -1;
114    if (self->tag && visit(self->tag, arg) < 0)
115        return -1;
116    if (self->anchor && visit(self->anchor, arg) < 0)
117        return -1;
118
119    return 0;
120}
121
122static void
123PySyckScalar_dealloc(PySyckScalarObject *self)
124{
125    PySyckScalar_clear(self);
126    self->ob_type->tp_free((PyObject *)self);
127}
128
129static PyObject *
130PySyckScalar_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
131{
132    PySyckScalarObject *self;
133
134    self = (PySyckScalarObject *)type->tp_alloc(type, 0);
135    if (!self) return NULL;
136
137    self->value = PyString_FromString("");
138    if (!self->value) {
139        Py_DECREF(self);
140        return NULL;
141    }
142
143    self->tag = NULL;
144    self->anchor = NULL;
145    self->style = scalar_none;
146    self->indent = 0;
147    self->width = 0;
148    self->chomp = 0;
149
150    return (PyObject *)self;
151}
152
153static PyObject *
154PySyckScalar_getkind(PySyckScalarObject *self, void *closure)
155{
156    Py_INCREF(PySyck_ScalarKind);
157    return PySyck_ScalarKind;
158}
159
160static PyObject *
161PySyckScalar_getvalue(PySyckScalarObject *self, void *closure)
162{
163    Py_INCREF(self->value);
164    return self->value;
165}
166
167static int
168PySyckScalar_setvalue(PySyckScalarObject *self, PyObject *value, void *closure)
169{
170    if (!value) {
171        PyErr_SetString(PyExc_TypeError, "cannot delete 'value'");
172        return -1;
173    }
174    if (!PyString_Check(value)) {
175        PyErr_SetString(PyExc_TypeError, "'value' must be a string");
176        return -1;
177    }
178
179    Py_DECREF(self->value);
180    Py_INCREF(value);
181    self->value = value;
182
183    return 0;
184}
185
186static PyObject *
187PySyckScalar_gettag(PySyckScalarObject *self, void *closure)
188{
189    PyObject *value = self->tag ? self->tag : Py_None;
190    Py_INCREF(value);
191    return value;
192}
193
194static int
195PySyckScalar_settag(PySyckScalarObject *self, PyObject *value, void *closure)
196{
197    if (!value) {
198        PyErr_SetString(PyExc_TypeError, "cannot delete 'tag'");
199        return -1;
200    }
201
202    if (value == Py_None) {
203        Py_XDECREF(self->tag);
204        self->tag = NULL;
205        return 0;
206    }
207
208    if (!PyString_Check(value)) {
209        PyErr_SetString(PyExc_TypeError, "'tag' must be a string");
210        return -1;
211    }
212
213    Py_XDECREF(self->tag);
214    Py_INCREF(value);
215    self->tag = value;
216
217    return 0;
218}
219
220static PyObject *
221PySyckScalar_getanchor(PySyckScalarObject *self, void *closure)
222{
223    PyObject *value = self->anchor ? self->anchor : Py_None;
224    Py_INCREF(value);
225    return value;
226}
227
228static int
229PySyckScalar_setanchor(PySyckScalarObject *self, PyObject *value, void *closure)
230{
231    if (!value) {
232        PyErr_SetString(PyExc_TypeError, "cannot delete 'anchor'");
233        return -1;
234    }
235
236    if (value == Py_None) {
237        Py_XDECREF(self->anchor);
238        self->anchor = NULL;
239        return 0;
240    }
241
242    if (!PyString_Check(value)) {
243        PyErr_SetString(PyExc_TypeError, "'anchor' must be a string");
244        return -1;
245    }
246
247    Py_XDECREF(self->anchor);
248    Py_INCREF(value);
249    self->anchor = value;
250
251    return 0;
252}
253
254static PyObject *
255PySyckScalar_getstyle(PySyckScalarObject *self, void *closure)
256{
257    PyObject *value;
258
259    switch (self->style) {
260        case scalar_1quote: value = PySyck_1QuoteStyle; break;
261        case scalar_2quote: value = PySyck_2QuoteStyle; break;
262        case scalar_fold: value = PySyck_FoldStyle; break;
263        case scalar_literal: value = PySyck_LiteralStyle; break;
264        case scalar_plain: value = PySyck_PlainStyle; break;
265        default: value = Py_None;
266    }
267
268    Py_INCREF(value);
269    return value;
270}
271
272static int
273PySyckScalar_setstyle(PySyckScalarObject *self, PyObject *value, void *closure)
274{
275    char *str;
276
277    if (!value) {
278        PyErr_SetString(PyExc_TypeError, "cannot delete 'style'");
279        return -1;
280    }
281
282    if (value == Py_None) {
283        self->style = scalar_none;
284        return 0;
285    }
286
287    if (!PyString_Check(value)) {
288        PyErr_SetString(PyExc_TypeError, "'style' must be a string or None");
289        return -1;
290    }
291
292    str = PyString_AsString(value);
293    if (!str) return -1;
294
295    if (strcmp(str, "1quote") == 0)
296        self->style = scalar_1quote;
297    else if (strcmp(str, "2quote") == 0)
298        self->style = scalar_2quote;
299    else if (strcmp(str, "fold") == 0)
300        self->style = scalar_fold;
301    else if (strcmp(str, "literal") == 0)
302        self->style = scalar_literal;
303    else if (strcmp(str, "plain") == 0)
304        self->style = scalar_plain;
305    else {
306        PyErr_SetString(PyExc_TypeError, "unknown 'style'");
307        return -1;
308    }
309
310    return 0;
311}
312
313static PyObject *
314PySyckScalar_getindent(PySyckScalarObject *self, void *closure)
315{
316    return PyInt_FromLong(self->indent);
317}
318
319static int
320PySyckScalar_setindent(PySyckScalarObject *self, PyObject *value, void *closure)
321{
322    if (!value) {
323        PyErr_SetString(PyExc_TypeError, "cannot delete 'indent'");
324        return -1;
325    }
326
327    if (!PyInt_Check(value)) {
328        PyErr_SetString(PyExc_TypeError, "'indent' must be an integer");
329        return -1;
330    }
331
332    self->indent = PyInt_AS_LONG(value);
333
334    return 0;
335}
336
337static PyObject *
338PySyckScalar_getwidth(PySyckScalarObject *self, void *closure)
339{
340    return PyInt_FromLong(self->width);
341}
342
343static int
344PySyckScalar_setwidth(PySyckScalarObject *self, PyObject *value, void *closure)
345{
346    if (!value) {
347        PyErr_SetString(PyExc_TypeError, "cannot delete 'width'");
348        return -1;
349    }
350
351    if (!PyInt_Check(value)) {
352        PyErr_SetString(PyExc_TypeError, "'width' must be an integer");
353        return -1;
354    }
355
356    self->width = PyInt_AS_LONG(value);
357
358    return 0;
359}
360
361static PyObject *
362PySyckScalar_getchomp(PySyckScalarObject *self, void *closure)
363{
364    PyObject *value;
365
366    switch (self->chomp) {
367        case NL_CHOMP: value = PySyck_StripChomp; break;
368        case NL_KEEP: value = PySyck_KeepChomp; break;
369        default: value = Py_None;
370    }
371
372    Py_INCREF(value);
373    return value;
374}
375
376static int
377PySyckScalar_setchomp(PySyckScalarObject *self, PyObject *value, void *closure)
378{
379    char *str;
380
381    if (!value) {
382        PyErr_SetString(PyExc_TypeError, "cannot delete 'chomp'");
383        return -1;
384    }
385
386    if (value == Py_None) {
387        self->chomp = 0;
388        return 0;
389    }
390
391    if (!PyString_Check(value)) {
392        PyErr_SetString(PyExc_TypeError, "'chomp' must be '+', '-', or None");
393        return -1;
394    }
395
396    str = PyString_AsString(value);
397    if (!str) return -1;
398
399    if (strcmp(str, "-") == 0)
400        self->chomp = NL_CHOMP;
401    else if (strcmp(str, "+") == 0)
402        self->chomp = NL_KEEP;
403    else {
404        PyErr_SetString(PyExc_TypeError, "'chomp' must be '+', '-', or None");
405        return -1;
406    }
407
408    return 0;
409}
410
411static int
412PySyckScalar_init(PySyckScalarObject *self, PyObject *args, PyObject *kwds)
413{
414    PyObject *value = NULL;
415    PyObject *tag = NULL;
416    PyObject *anchor = NULL;
417    PyObject *style = NULL;
418    PyObject *indent = NULL;
419    PyObject *width = NULL;
420    PyObject *chomp = NULL;
421
422    static char *kwdlist[] = {"value", "tag", "anchor",
423        "style", "indent", "width", "chomp", NULL};
424
425    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOOOO", kwdlist,
426                &value, &tag, &anchor, &style, &indent, &width, &chomp))
427        return -1;
428
429    if (value && PySyckScalar_setvalue(self, value, NULL) < 0)
430        return -1;
431
432    if (tag && PySyckScalar_settag(self, tag, NULL) < 0)
433        return -1;
434
435    if (anchor && PySyckScalar_setanchor(self, anchor, NULL) < 0)
436        return -1;
437
438    if (style && PySyckScalar_setstyle(self, style, NULL) < 0)
439        return -1;
440
441    if (indent && PySyckScalar_setindent(self, indent, NULL) < 0)
442        return -1;
443
444    if (width && PySyckScalar_setwidth(self, width, NULL) < 0)
445        return -1;
446
447    if (chomp && PySyckScalar_setchomp(self, chomp, NULL) < 0)
448        return -1;
449
450    return 0;
451}
452
453static PyGetSetDef PySyckScalar_getsetters[] = {
454    {"kind", (getter)PySyckScalar_getkind, NULL,
455        "the node kind", NULL},
456    {"value", (getter)PySyckScalar_getvalue, (setter)PySyckScalar_setvalue,
457        "the node value", NULL},
458    {"tag", (getter)PySyckScalar_gettag, (setter)PySyckScalar_settag,
459        "the node tag", NULL},
460    {"anchor", (getter)PySyckScalar_getanchor, (setter)PySyckScalar_setanchor,
461        "the node anchor", NULL},
462    {"style", (getter)PySyckScalar_getstyle, (setter)PySyckScalar_setstyle,
463        "the node style", NULL},
464    {"indent", (getter)PySyckScalar_getindent, (setter)PySyckScalar_setindent,
465        "the field indentation", NULL},
466    {"width", (getter)PySyckScalar_getwidth, (setter)PySyckScalar_setwidth,
467        "the field width", NULL},
468    {"chomp", (getter)PySyckScalar_getchomp, (setter)PySyckScalar_setchomp,
469        "the chomping method", NULL},
470    {NULL}  /* Sentinel */
471};
472
473static PyTypeObject PySyckScalar_Type = {
474    PyObject_HEAD_INIT(NULL)
475    0,                                          /* ob_size */
476    "_syck.Scalar",                             /* tp_name */
477    sizeof(PySyckScalarObject),                 /* tp_basicsize */
478    0,                                          /* tp_itemsize */
479    (destructor)PySyckScalar_dealloc,           /* tp_dealloc */
480    0,                                          /* tp_print */
481    0,                                          /* tp_getattr */
482    0,                                          /* tp_setattr */
483    0,                                          /* tp_compare */
484    0,                                          /* tp_repr */
485    0,                                          /* tp_as_number */
486    0,                                          /* tp_as_sequence */
487    0,                                          /* tp_as_mapping */
488    0,                                          /* tp_hash */
489    0,                                          /* tp_call */
490    0,                                          /* tp_str */
491    0,                                          /* tp_getattro */
492    0,                                          /* tp_setattro */
493    0,                                          /* tp_as_buffer */
494    Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC,  /* tp_flags */
495    PySyckScalar_doc,                           /* tp_doc */
496    (traverseproc)PySyckScalar_traverse,        /* tp_traverse */
497    (inquiry)PySyckScalar_clear,                /* tp_clear */
498    0,                                          /* tp_richcompare */
499    0,                                          /* tp_weaklistoffset */
500    0,                                          /* tp_iter */
501    0,                                          /* tp_iternext */
502    0,                                          /* tp_methods */
503    0,                                          /* tp_members */
504    PySyckScalar_getsetters,                    /* tp_getset */
505    &PySyckNode_Type,                           /* tp_base */
506    0,                                          /* tp_dict */
507    0,                                          /* tp_descr_get */
508    0,                                          /* tp_descr_set */
509    0,                                          /* tp_dictoffset */
510    (initproc)PySyckScalar_init,                /* tp_init */
511    0,                                          /* tp_alloc */
512    PySyckScalar_new,                           /* tp_new */
513};
514
515
516/*
517typedef struct {
518    PyObject_HEAD
519    PyObject *kind;
520    PyObject *type_id;
521    PyObject *value;
522} PySyckNodeObject;
523
524static void
525PySyckNode_dealloc(PySyckNodeObject *self)
526{
527    Py_XDECREF(self->kind);
528    Py_XDECREF(self->type_id);
529    Py_XDECREF(self->value);
530    PyObject_Del(self);
531}
532
533static PyObject *
534PySyckNode_getattr(PySyckNodeObject *self, char *name)
535{
536    PyObject *value;
537
538    if (strcmp(name, "kind") == 0)
539        value = self->kind;
540    else if (strcmp(name, "type_id") == 0)
541        value = self->type_id;
542    else if (strcmp(name, "value") == 0)
543        value = self->value;
544    else {
545        PyErr_SetString(PyExc_AttributeError, name);
546        return NULL;
547    }
548
549    Py_INCREF(value);
550    return value;
551}
552
553
554*/
555#if 0
556   
557static PyTypeObject PySyckNode_Type = {
558    PyObject_HEAD_INIT(NULL)
559    0,                                  /* ob_size */
560    "_syck.Node",                       /* tp_name */
561    sizeof(PySyckNodeObject),           /* tp_basicsize */
562    0,                                  /* tp_itemsize */
563    (destructor)PySyckNode_dealloc,     /* tp_dealloc */
564    0,                                  /* tp_print */
565    (getattrfunc)PySyckNode_getattr,    /* tp_getattr */
566    0,                                  /* tp_setattr */
567    0,                                  /* tp_compare */
568    0,                                  /* tp_repr */
569    0,                                  /* tp_as_number */
570    0,                                  /* tp_as_sequence */
571    0,                                  /* tp_as_mapping */
572    0,                                  /* tp_hash */
573    0,                                  /* tp_call */
574    0,                                  /* tp_str */
575    0,                                  /* tp_getattro */
576    0,                                  /* tp_setattro */
577    0,                                  /* tp_as_buffer */
578    Py_TPFLAGS_DEFAULT,                 /* tp_flags */
579    PySyckNode_doc,                     /* tp_doc */
580};
581
582static PyObject *
583PySyckNode_New(char *type_id, PyObject *value) /* Note: steals the reference to the value. */
584{
585    PySyckNodeObject *self;
586    PyObject *kind;
587
588    self = PyObject_NEW(PySyckNodeObject, &PySyckNode_Type);
589    if (!self) {
590        Py_XDECREF(value);
591        return NULL;
592    }
593
594    self->value = value;
595
596    if (PyList_Check(value))
597        kind = PySyck_SeqKind;
598    else if (PyDict_Check(value))
599        kind = PySyck_MapKind;
600    else
601        kind = PySyck_ScalarKind;
602    Py_INCREF(kind);
603    self->kind = kind;
604
605    if (type_id) {
606        self->type_id = PyString_FromString(type_id);
607        if (!self->type_id) {
608            Py_DECREF(self);
609            return NULL;
610        }
611    }
612    else {
613        Py_INCREF(Py_None);
614        self->type_id = Py_None;
615    }
616
617    return (PyObject *)self;
618}
619
620static PyObject *
621PySyck_Node(PyObject *self, PyObject *args)
622{
623    if (!PyArg_ParseTuple(args, ":_syck.Node"))
624        return NULL;
625
626    PyErr_SetString(PyExc_TypeError, "Node object cannot be created explicitly. Use _syck.Parser.parse() instead.");
627    return NULL;
628}
629
630static char PySyck_Node_doc[] =
631    "Node object cannot be created explicitly. Use _syck.Parser.parse() instead.";
632
633
634*/
635
636/* Parser type. */
637
638typedef struct {
639    PyObject_HEAD
640    PyObject *source;
641    PyObject *resolver;
642    PyObject *symbols;
643    SyckParser *syck;
644    int error;
645} PySyckParserObject;
646
647static void
648PySyckParser_free(PySyckParserObject *parser)
649{
650    Py_XDECREF(parser->source);
651    parser->source = NULL;
652    Py_XDECREF(parser->resolver);
653    parser->resolver = NULL;
654    Py_XDECREF(parser->symbols);
655    parser->symbols = NULL;
656    if (parser->syck) {
657        syck_free_parser(parser->syck);
658        parser->syck = NULL;
659    }
660}
661
662static PyObject *
663PySyckParser_parse(PySyckParserObject *parser, PyObject *args)
664{
665    SYMID index;
666    PyObject *value;
667
668    if (!PyArg_ParseTuple(args, ":parse"))
669        return NULL;
670
671    if (!parser->syck) {
672        Py_INCREF(Py_None);
673        return Py_None;
674    }
675
676    if (parser->symbols) {
677        PyErr_SetString(PyExc_RuntimeError, "do not call Parser.parse while it is running");
678        return NULL;
679    }
680
681    parser->symbols = PyList_New(0);
682    if (!parser->symbols) {
683        return NULL;
684    }
685
686    index = syck_parse(parser->syck);
687
688    if (parser->error) {
689        PySyckParser_free(parser);
690        return NULL;
691    }
692
693    if (parser->syck->eof) {
694        PySyckParser_free(parser);
695        Py_INCREF(Py_None);
696        return Py_None;
697    }
698
699    value = PyList_GetItem(parser->symbols, index);
700
701    Py_DECREF(parser->symbols);
702    parser->symbols = NULL;
703
704    return value;
705}
706
707static char PySyckParser_parse_doc[] =
708    "Parses the next document in the YAML stream, return the root Node object or None on EOF.";
709
710static PyObject *
711PySyckParser_eof(PySyckParserObject *parser, PyObject *args)
712{
713    PyObject *value;
714
715    if (!PyArg_ParseTuple(args, ":eof"))
716        return NULL;
717
718    value = parser->syck ? Py_False : Py_True;
719
720    Py_INCREF(value);
721    return value;
722}
723
724static char PySyckParser_eof_doc[] =
725    "Checks if the parser is stopped.";
726
727static PyMethodDef PySyckParser_methods[] = {
728    {"parse",  (PyCFunction)PySyckParser_parse, METH_VARARGS, PySyckParser_parse_doc},
729    {"eof",  (PyCFunction)PySyckParser_eof, METH_VARARGS, PySyckParser_eof_doc},
730    {NULL}  /* Sentinel */
731};
732
733static void
734PySyckParser_dealloc(PySyckParserObject *parser)
735{
736    PySyckParser_free(parser);
737    PyObject_Del(parser);
738}
739
740static PyObject *
741PySyckParser_getattr(PySyckParserObject *parser, char *name)
742{
743    return Py_FindMethod(PySyckParser_methods, (PyObject *)parser, name);
744}
745
746static char PySyckParser_doc[] =
747    "_syck.Parser(yaml_string_or_file, resolver=None, implicit_typing=True, taguri_expansion=True) -> Parser object\n"
748    "\n"
749    "Methods of the Parser object:\n\n"
750    "parse() -- Parses the next document in the YAML stream, return the root Node object or None on EOF.\n"
751    "eof() -- Checks if the parser is stopped.\n";
752
753static PyTypeObject PySyckParser_Type = {
754    PyObject_HEAD_INIT(NULL)
755    0,                                  /* ob_size */
756    "_syck.Parser",                     /* tp_name */
757    sizeof(PySyckParserObject),         /* tp_basicsize */
758    0,                                  /* tp_itemsize */
759    (destructor)PySyckParser_dealloc,   /* tp_dealloc */
760    0,                                  /* tp_print */
761    (getattrfunc)PySyckParser_getattr,  /* tp_getattr */
762    0,                                  /* tp_setattr */
763    0,                                  /* tp_compare */
764    0,                                  /* tp_repr */
765    0,                                  /* tp_as_number */
766    0,                                  /* tp_as_sequence */
767    0,                                  /* tp_as_mapping */
768    0,                                  /* tp_hash */
769    0,                                  /* tp_call */
770    0,                                  /* tp_str */
771    0,                                  /* tp_getattro */
772    0,                                  /* tp_setattro */
773    0,                                  /* tp_as_buffer */
774    Py_TPFLAGS_DEFAULT,                 /* tp_flags */
775    PySyckParser_doc,                   /* tp_doc */
776};
777
778static long
779PySyckParser_read_handler(char *buf, SyckIoFile *file, long max_size, long skip)
780{
781    PySyckParserObject *parser = (PySyckParserObject *)file->ptr;
782
783    PyObject *value;
784
785    char *str;
786    int length;
787
788    buf[skip] = '\0';
789
790    if (parser->error) {
791        return skip;
792    }
793   
794    max_size -= skip;
795
796    value = PyObject_CallMethod(parser->source, "read", "(i)", max_size);
797    if (!value) {
798        parser->error = 1;
799        return skip;
800    }
801
802    if (!PyString_Check(value)) {
803        Py_DECREF(value);
804        PyErr_SetString(PyExc_TypeError, "file-like object should return a string");
805        parser->error = 1;
806       
807        return skip;
808    }
809
810    str = PyString_AS_STRING(value);
811    length = PyString_GET_SIZE(value);
812    if (!length) {
813        Py_DECREF(value);
814        return skip;
815    }
816
817    if (length > max_size) {
818        Py_DECREF(value);
819        PyErr_SetString(PyExc_ValueError, "read returns an overly long string");
820        parser->error = 1;
821        return skip;
822    }
823
824    memcpy(buf+skip, str, length);
825    length += skip;
826    buf[length] = '\0';
827
828    Py_DECREF(value);
829
830    return length;
831}
832
833static SYMID
834PySyckParser_node_handler(SyckParser *syck, SyckNode *node)
835{
836    PySyckParserObject *parser = (PySyckParserObject *)syck->bonus;
837
838    SYMID index;
839    PyObject *object = NULL;
840
841    PyObject *key, *value, *item;
842    int k;
843
844    if (parser->error)
845        return -1;
846
847    switch (node->kind) {
848
849        case syck_str_kind:
850            object = PyString_FromStringAndSize(node->data.str->ptr,
851                    node->data.str->len);
852            if (!object) goto error;
853            break;
854
855        case syck_seq_kind:
856            object = PyList_New(node->data.list->idx);
857            if (!object) goto error;
858            for (k = 0; k < node->data.list->idx; k++) {
859                index = syck_seq_read(node, k);
860                item = PyList_GetItem(parser->symbols, index);
861                if (!item) goto error;
862                Py_INCREF(item);
863                PyList_SET_ITEM(object, k, item);
864            }
865            break;
866
867        case syck_map_kind:
868            object = PyDict_New();
869            if (!object) goto error;
870            for (k = 0; k < node->data.pairs->idx; k++)
871            {
872                index = syck_map_read(node, map_key, k);
873                key = PyList_GetItem(parser->symbols, index);
874                if (!key) goto error;
875                index = syck_map_read(node, map_value, k);
876                value = PyList_GetItem(parser->symbols, index);
877                if (!value) goto error;
878                if (PyDict_SetItem(object, key, value) < 0)
879                    goto error;
880            }
881            break;
882    }
883
884    object = PySyckNode_New(node->type_id, object);
885    if (!object) goto error;
886
887    if (parser->resolver) {
888        value = PyObject_CallFunction(parser->resolver, "(O)", object);
889        if (!value) goto error;
890        Py_DECREF(object);
891        object = value;
892    }
893
894    if (PyList_Append(parser->symbols, object) < 0)
895        goto error;
896
897    index = PyList_Size(parser->symbols)-1;
898    return index;
899
900error:
901    Py_XDECREF(object);
902    parser->error = 1;
903    return -1;
904}
905
906static void
907PySyckParser_error_handler(SyckParser *syck, char *str)
908{
909    PySyckParserObject *parser = (PySyckParserObject *)syck->bonus;
910    PyObject *value;
911
912    if (parser->error) return;
913
914    parser->error = 1;
915
916    value = Py_BuildValue("(sii)", str, syck->linect, syck->cursor-syck->lineptr);
917    if (value) {
918        PyErr_SetObject(PySyck_Error, value);
919    }
920}
921
922static PyObject *
923PySyck_Parser(PyObject *self, PyObject *args, PyObject *kwds)
924{
925    PySyckParserObject *parser;
926    PyObject *source;
927    PyObject *resolver = NULL;
928    int implicit_typing = 1;
929    int taguri_expansion = 1;
930
931    static char *kwdlist[] = {"source", "resolver", "implicit_typing", "taguri_expansion", NULL};
932
933    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|Oii", kwdlist,
934                &source, &resolver, &implicit_typing, &taguri_expansion))
935        return NULL;
936
937    parser = PyObject_NEW(PySyckParserObject, &PySyckParser_Type);
938    if (!parser)
939        return NULL;
940
941    parser->error = 0;
942    parser->symbols = NULL;
943
944    Py_INCREF(source);
945    parser->source = source;
946
947    if (resolver == Py_None)
948        resolver = NULL;
949    Py_XINCREF(resolver);
950    parser->resolver = resolver;
951
952    parser->syck = syck_new_parser();
953    parser->syck->bonus = parser;
954
955    if (PyString_Check(source)) {
956        syck_parser_str(parser->syck, PyString_AS_STRING(source), PyString_GET_SIZE(source), NULL);
957    }
958    else {
959        syck_parser_file(parser->syck, (FILE *)parser, PySyckParser_read_handler);
960    }
961    syck_parser_implicit_typing(parser->syck, implicit_typing);
962    syck_parser_taguri_expansion(parser->syck, taguri_expansion);
963
964    syck_parser_handler(parser->syck, PySyckParser_node_handler);
965    syck_parser_error_handler(parser->syck, PySyckParser_error_handler);
966    /*
967    syck_parser_bad_anchor_handler(parser, PySyckParser_bad_anchor_handler);
968    */
969
970    return (PyObject *)parser;
971}
972
973static char PySyck_Parser_doc[] =
974    "Creates a new Parser object.";
975
976/* The module definitions. */
977
978static PyMethodDef PySyck_methods[] = {
979    {"Node",  (PyCFunction)PySyck_Node, METH_VARARGS, PySyck_Node_doc},
980    {"Parser",  (PyCFunction)PySyck_Parser, METH_VARARGS|METH_KEYWORDS, PySyck_Parser_doc},
981    {NULL}  /* Sentinel */
982};
983
984static char PySyck_doc[] =
985    "This module provides low-level access to the Syck parser and emitter.\n"
986    "Do not use this module directly, use the package 'syck' instead.\n";
987
988/* PyMODINIT_FUNC - does not work with versions <2.3 */
989void
990init_syck(void)
991{
992    PyObject *m;
993
994    PySyckNode_Type.ob_type = &PyType_Type;
995    PySyckParser_Type.ob_type = &PyType_Type;
996
997    PySyck_Error = PyErr_NewException("_syck.error", NULL, NULL);
998    if (!PySyck_Error)
999        return;
1000
1001    PySyck_ScalarKind = PyString_FromString("scalar");
1002    if (!PySyck_ScalarKind)
1003        return;
1004    PySyck_SeqKind = PyString_FromString("seq");
1005    if (!PySyck_SeqKind)
1006        return;
1007    PySyck_MapKind = PyString_FromString("map");
1008    if (!PySyck_MapKind)
1009        return;
1010
1011    m = Py_InitModule3("_syck", PySyck_methods, PySyck_doc);
1012
1013    Py_INCREF(PySyck_Error);
1014    if (!PyModule_AddObject(m, "error", PySyck_Error) < 0)
1015        return;
1016
1017    Py_INCREF(&PySyckNode_Type);
1018    if (PyModule_AddObject(m, "NodeType", (PyObject *)&PySyckNode_Type) < 0)
1019        return;
1020
1021    Py_INCREF(&PySyckParser_Type);
1022    if (PyModule_AddObject(m, "ParserType", (PyObject *)&PySyckParser_Type) < 0)
1023        return;
1024}
1025
1026#endif
1027
1028/* The module _syck. */
1029
1030static PyMethodDef PySyck_methods[] = {
1031    {NULL}  /* Sentinel */
1032};
1033
1034PyDoc_STRVAR(PySyck_doc,
1035    "The low-level wrapper for the Syck YAML parser and emitter\n\n"
1036    "Types:\n\n"
1037    "Node -- the base Node type\n");
1038
1039PyMODINIT_FUNC
1040init_syck(void)
1041{
1042    PyObject *m;
1043
1044    if (PyType_Ready(&PySyckNode_Type) < 0)
1045        return;
1046    if (PyType_Ready(&PySyckScalar_Type) < 0)
1047        return;
1048   
1049    PySyck_Error = PyErr_NewException("_syck.error", NULL, NULL);
1050    if (!PySyck_Error) return;
1051
1052    PySyck_ScalarKind = PyString_FromString("scalar");
1053    if (!PySyck_ScalarKind) return;
1054    PySyck_SeqKind = PyString_FromString("seq");
1055    if (!PySyck_SeqKind) return;
1056    PySyck_MapKind = PyString_FromString("map");
1057    if (!PySyck_MapKind) return;
1058
1059    PySyck_1QuoteStyle = PyString_FromString("1quote");
1060    if (!PySyck_1QuoteStyle) return;
1061    PySyck_2QuoteStyle = PyString_FromString("2quote");
1062    if (!PySyck_2QuoteStyle) return;
1063    PySyck_FoldStyle = PyString_FromString("fold");
1064    if (!PySyck_FoldStyle) return;
1065    PySyck_LiteralStyle = PyString_FromString("literal");
1066    if (!PySyck_LiteralStyle) return;
1067    PySyck_PlainStyle = PyString_FromString("plain");
1068    if (!PySyck_PlainStyle) return;
1069
1070    PySyck_StripChomp = PyString_FromString("-");
1071    if (!PySyck_StripChomp) return;
1072    PySyck_KeepChomp = PyString_FromString("+");
1073    if (!PySyck_KeepChomp) return;
1074
1075    m = Py_InitModule3("_syck", PySyck_methods, PySyck_doc);
1076
1077    Py_INCREF(&PySyckNode_Type);
1078    if (PyModule_AddObject(m, "Node", (PyObject *)&PySyckNode_Type) < 0)
1079        return;
1080
1081    Py_INCREF(&PySyckScalar_Type);
1082    if (PyModule_AddObject(m, "Scalar", (PyObject *)&PySyckScalar_Type) < 0)
1083        return;
1084}
1085
1086
Note: See TracBrowser for help on using the repository browser.