source: pysyck/trunk/ext/_syckmodule.c @ 123

Revision 123, 67.6 KB checked in by xi, 9 years ago (diff)

Fix a leak in _syckmodule.c (thanks, jbj)

Change the production status to Stable.

RevLine 
[3]1
2#include <Python.h>
3#include <syck.h>
4
[14]5/****************************************************************************
6 * Python 2.2 compatibility.
7 ****************************************************************************/
[4]8
[12]9#ifndef PyDoc_STR
10#define PyDoc_VAR(name)         static char name[]
11#define PyDoc_STR(str)          (str)
12#define PyDoc_STRVAR(name, str) PyDoc_VAR(name) = PyDoc_STR(str)
13#endif
14
15#ifndef PyMODINIT_FUNC
16#define PyMODINIT_FUNC  void
17#endif
18
[14]19/****************************************************************************
20 * Global objects: _syck.error, 'scalar', 'seq', 'map',
21 * '1quote', '2quote', 'fold', 'literal', 'plain', '+', '-'.
22 ****************************************************************************/
[12]23
[5]24static PyObject *PySyck_Error;
[4]25
[5]26static PyObject *PySyck_ScalarKind;
27static PyObject *PySyck_SeqKind;
28static PyObject *PySyck_MapKind;
[4]29
[12]30static PyObject *PySyck_1QuoteStyle;
31static PyObject *PySyck_2QuoteStyle;
32static PyObject *PySyck_FoldStyle;
33static PyObject *PySyck_LiteralStyle;
34static PyObject *PySyck_PlainStyle;
[4]35
[12]36static PyObject *PySyck_StripChomp;
37static PyObject *PySyck_KeepChomp;
38
[14]39/****************************************************************************
40 * The type _syck.Node.
41 ****************************************************************************/
[12]42
43PyDoc_STRVAR(PySyckNode_doc,
[15]44    "_syck.Node() -> TypeError\n\n"
[25]45    "_syck.Node is an abstract type. It is the base type for _syck.Scalar,\n"
[12]46    "_syck.Seq, and _syck.Map. You cannot create an instance of _syck.Node\n"
[15]47    "directly. You may use _syck.Node for type checking or subclassing.\n");
[12]48
[4]49typedef struct {
50    PyObject_HEAD
[14]51    /* Common fields for all Node types: */
52    PyObject *value;    /* always an object */
53    PyObject *tag;      /* a string object or NULL */
54    PyObject *anchor;   /* a string object or NULL */
55} PySyckNodeObject;
[12]56
[14]57
[12]58static int
[14]59PySyckNode_clear(PySyckNodeObject *self)
[12]60{
[14]61    PyObject *tmp;
62
63    tmp = self->value;
[12]64    self->value = NULL;
[14]65    Py_XDECREF(tmp);
66
67    tmp = self->tag;
[12]68    self->tag = NULL;
[14]69    Py_XDECREF(tmp);
[12]70
[14]71    tmp = self->anchor;
72    self->value = NULL;
73    Py_XDECREF(tmp);
74
[12]75    return 0;
76}
77
78static int
[14]79PySyckNode_traverse(PySyckNodeObject *self, visitproc visit, void *arg)
[12]80{
[14]81    int ret;
[12]82
[14]83    if (self->value)
84        if ((ret = visit(self->value, arg)) != 0)
85            return ret;
86
87    if (self->tag)
88        if ((ret = visit(self->tag, arg)) != 0)
89            return ret;
90
91    if (self->anchor)
92        if ((ret = visit(self->anchor, arg)) != 0)
93            return ret;
94
[12]95    return 0;
96}
97
98static void
[14]99PySyckNode_dealloc(PySyckNodeObject *self)
[12]100{
[14]101    PySyckNode_clear(self);
[12]102    self->ob_type->tp_free((PyObject *)self);
103}
104
105static PyObject *
[14]106PySyckNode_getkind(PySyckNodeObject *self, PyObject **closure)
[12]107{
[14]108    Py_INCREF(*closure);
109    return *closure;
[12]110}
111
112static PyObject *
[14]113PySyckNode_getvalue(PySyckNodeObject *self, void *closure)
[12]114{
115    Py_INCREF(self->value);
116    return self->value;
117}
118
119static PyObject *
[14]120PySyckNode_gettag(PySyckNodeObject *self, void *closure)
[12]121{
122    PyObject *value = self->tag ? self->tag : Py_None;
123    Py_INCREF(value);
124    return value;
125}
126
127static int
[14]128PySyckNode_settag(PySyckNodeObject *self, PyObject *value, void *closure)
[12]129{
130    if (!value) {
131        PyErr_SetString(PyExc_TypeError, "cannot delete 'tag'");
132        return -1;
133    }
134
135    if (value == Py_None) {
136        Py_XDECREF(self->tag);
137        self->tag = NULL;
138        return 0;
139    }
140
141    if (!PyString_Check(value)) {
142        PyErr_SetString(PyExc_TypeError, "'tag' must be a string");
143        return -1;
144    }
145
146    Py_XDECREF(self->tag);
147    Py_INCREF(value);
148    self->tag = value;
149
150    return 0;
151}
152
153static PyObject *
[14]154PySyckNode_getanchor(PySyckNodeObject *self, void *closure)
[12]155{
156    PyObject *value = self->anchor ? self->anchor : Py_None;
157    Py_INCREF(value);
158    return value;
159}
160
161static int
[14]162PySyckNode_setanchor(PySyckNodeObject *self, PyObject *value, void *closure)
[12]163{
164    if (!value) {
165        PyErr_SetString(PyExc_TypeError, "cannot delete 'anchor'");
166        return -1;
167    }
168
169    if (value == Py_None) {
170        Py_XDECREF(self->anchor);
171        self->anchor = NULL;
172        return 0;
173    }
174
175    if (!PyString_Check(value)) {
176        PyErr_SetString(PyExc_TypeError, "'anchor' must be a string");
177        return -1;
178    }
179
180    Py_XDECREF(self->anchor);
181    Py_INCREF(value);
182    self->anchor = value;
183
184    return 0;
185}
186
[14]187static PyTypeObject PySyckNode_Type = {
188    PyObject_HEAD_INIT(NULL)
189    0,                                          /* ob_size */
190    "_syck.Node",                               /* tp_name */
191    sizeof(PySyckNodeObject),                   /* tp_basicsize */
192    0,                                          /* tp_itemsize */
193    (destructor)PySyckNode_dealloc,             /* tp_dealloc */
194    0,                                          /* tp_print */
195    0,                                          /* tp_getattr */
196    0,                                          /* tp_setattr */
197    0,                                          /* tp_compare */
198    0,                                          /* tp_repr */
199    0,                                          /* tp_as_number */
200    0,                                          /* tp_as_sequence */
201    0,                                          /* tp_as_mapping */
202    0,                                          /* tp_hash */
203    0,                                          /* tp_call */
204    0,                                          /* tp_str */
205    0,                                          /* tp_getattro */
206    0,                                          /* tp_setattro */
207    0,                                          /* tp_as_buffer */
208    Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC,  /* tp_flags */
209    PySyckNode_doc,                             /* tp_doc */
210    (traverseproc)PySyckNode_traverse,          /* tp_traverse */
211    (inquiry)PySyckNode_clear,                  /* tp_clear */
212};
213
214/****************************************************************************
215 * The type _syck.Scalar.
216 ****************************************************************************/
217
218PyDoc_STRVAR(PySyckScalar_doc,
219    "Scalar(value='', tag=None, style=None, indent=0, width=0, chomp=None)\n"
220    "      -> a Scalar node\n\n"
221    "_syck.Scalar represents a scalar node in Syck parser and emitter\n"
[25]222    "trees. A scalar node points to a single string value.\n");
[14]223
224typedef struct {
225    PyObject_HEAD
226    /* Common fields for all Node types: */
227    PyObject *value;    /* always a string object */
228    PyObject *tag;      /* a string object or NULL */
229    PyObject *anchor;   /* a string object or NULL */
230    /* Scalar-specific fields: */
231    enum scalar_style style;
232    int indent;
233    int width;
234    char chomp;
235} PySyckScalarObject;
236
[12]237static PyObject *
[14]238PySyckScalar_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
239{
240    PySyckScalarObject *self;
241
242    self = (PySyckScalarObject *)type->tp_alloc(type, 0);
243    if (!self) return NULL;
244
245    self->value = PyString_FromString("");
246    if (!self->value) {
247        Py_DECREF(self);
248        return NULL;
249    }
250
251    self->tag = NULL;
252    self->anchor = NULL;
253    self->style = scalar_none;
254    self->indent = 0;
255    self->width = 0;
256    self->chomp = 0;
257
258    return (PyObject *)self;
259}
260
261static int
262PySyckScalar_setvalue(PySyckScalarObject *self, PyObject *value, void *closure)
263{
264    if (!value) {
265        PyErr_SetString(PyExc_TypeError, "cannot delete 'value'");
266        return -1;
267    }
268    if (!PyString_Check(value)) {
269        PyErr_SetString(PyExc_TypeError, "'value' must be a string");
270        return -1;
271    }
272
273    Py_DECREF(self->value);
274    Py_INCREF(value);
275    self->value = value;
276
277    return 0;
278}
279
280static PyObject *
[12]281PySyckScalar_getstyle(PySyckScalarObject *self, void *closure)
282{
283    PyObject *value;
284
285    switch (self->style) {
286        case scalar_1quote: value = PySyck_1QuoteStyle; break;
287        case scalar_2quote: value = PySyck_2QuoteStyle; break;
288        case scalar_fold: value = PySyck_FoldStyle; break;
289        case scalar_literal: value = PySyck_LiteralStyle; break;
290        case scalar_plain: value = PySyck_PlainStyle; break;
291        default: value = Py_None;
292    }
293
294    Py_INCREF(value);
295    return value;
296}
297
298static int
299PySyckScalar_setstyle(PySyckScalarObject *self, PyObject *value, void *closure)
300{
301    char *str;
302
303    if (!value) {
304        PyErr_SetString(PyExc_TypeError, "cannot delete 'style'");
305        return -1;
306    }
307
308    if (value == Py_None) {
309        self->style = scalar_none;
310        return 0;
311    }
312
313    if (!PyString_Check(value)) {
314        PyErr_SetString(PyExc_TypeError, "'style' must be a string or None");
315        return -1;
316    }
317
318    str = PyString_AsString(value);
319    if (!str) return -1;
320
321    if (strcmp(str, "1quote") == 0)
322        self->style = scalar_1quote;
323    else if (strcmp(str, "2quote") == 0)
324        self->style = scalar_2quote;
325    else if (strcmp(str, "fold") == 0)
326        self->style = scalar_fold;
327    else if (strcmp(str, "literal") == 0)
328        self->style = scalar_literal;
329    else if (strcmp(str, "plain") == 0)
330        self->style = scalar_plain;
331    else {
[17]332        PyErr_SetString(PyExc_ValueError, "unknown 'style'");
[12]333        return -1;
334    }
335
336    return 0;
337}
338
339static PyObject *
340PySyckScalar_getindent(PySyckScalarObject *self, void *closure)
341{
342    return PyInt_FromLong(self->indent);
343}
344
345static int
346PySyckScalar_setindent(PySyckScalarObject *self, PyObject *value, void *closure)
347{
348    if (!value) {
349        PyErr_SetString(PyExc_TypeError, "cannot delete 'indent'");
350        return -1;
351    }
352
353    if (!PyInt_Check(value)) {
354        PyErr_SetString(PyExc_TypeError, "'indent' must be an integer");
355        return -1;
356    }
357
358    self->indent = PyInt_AS_LONG(value);
359
360    return 0;
361}
362
363static PyObject *
364PySyckScalar_getwidth(PySyckScalarObject *self, void *closure)
365{
366    return PyInt_FromLong(self->width);
367}
368
369static int
370PySyckScalar_setwidth(PySyckScalarObject *self, PyObject *value, void *closure)
371{
372    if (!value) {
373        PyErr_SetString(PyExc_TypeError, "cannot delete 'width'");
374        return -1;
375    }
376
377    if (!PyInt_Check(value)) {
378        PyErr_SetString(PyExc_TypeError, "'width' must be an integer");
379        return -1;
380    }
381
382    self->width = PyInt_AS_LONG(value);
383
384    return 0;
385}
386
387static PyObject *
388PySyckScalar_getchomp(PySyckScalarObject *self, void *closure)
389{
390    PyObject *value;
391
392    switch (self->chomp) {
393        case NL_CHOMP: value = PySyck_StripChomp; break;
394        case NL_KEEP: value = PySyck_KeepChomp; break;
395        default: value = Py_None;
396    }
397
398    Py_INCREF(value);
399    return value;
400}
401
402static int
403PySyckScalar_setchomp(PySyckScalarObject *self, PyObject *value, void *closure)
404{
405    char *str;
406
407    if (!value) {
408        PyErr_SetString(PyExc_TypeError, "cannot delete 'chomp'");
409        return -1;
410    }
411
412    if (value == Py_None) {
413        self->chomp = 0;
414        return 0;
415    }
416
417    if (!PyString_Check(value)) {
418        PyErr_SetString(PyExc_TypeError, "'chomp' must be '+', '-', or None");
419        return -1;
420    }
421
422    str = PyString_AsString(value);
423    if (!str) return -1;
424
425    if (strcmp(str, "-") == 0)
426        self->chomp = NL_CHOMP;
427    else if (strcmp(str, "+") == 0)
428        self->chomp = NL_KEEP;
429    else {
430        PyErr_SetString(PyExc_TypeError, "'chomp' must be '+', '-', or None");
431        return -1;
432    }
433
434    return 0;
435}
436
437static int
438PySyckScalar_init(PySyckScalarObject *self, PyObject *args, PyObject *kwds)
439{
440    PyObject *value = NULL;
441    PyObject *tag = NULL;
442    PyObject *anchor = NULL;
443    PyObject *style = NULL;
444    PyObject *indent = NULL;
445    PyObject *width = NULL;
446    PyObject *chomp = NULL;
447
448    static char *kwdlist[] = {"value", "tag", "anchor",
449        "style", "indent", "width", "chomp", NULL};
450
451    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOOOO", kwdlist,
452                &value, &tag, &anchor, &style, &indent, &width, &chomp))
453        return -1;
454
455    if (value && PySyckScalar_setvalue(self, value, NULL) < 0)
456        return -1;
457
[14]458    if (tag && PySyckNode_settag((PySyckNodeObject *)self, tag, NULL) < 0)
[12]459        return -1;
460
[14]461    if (anchor && PySyckNode_setanchor((PySyckNodeObject *)self, anchor, NULL) < 0)
[12]462        return -1;
463
464    if (style && PySyckScalar_setstyle(self, style, NULL) < 0)
465        return -1;
466
467    if (indent && PySyckScalar_setindent(self, indent, NULL) < 0)
468        return -1;
469
470    if (width && PySyckScalar_setwidth(self, width, NULL) < 0)
471        return -1;
472
473    if (chomp && PySyckScalar_setchomp(self, chomp, NULL) < 0)
474        return -1;
475
476    return 0;
477}
478
479static PyGetSetDef PySyckScalar_getsetters[] = {
[14]480    {"kind", (getter)PySyckNode_getkind, NULL,
[15]481        PyDoc_STR("the node kind, always 'scalar', read-only"),
482        &PySyck_ScalarKind},
[14]483    {"value", (getter)PySyckNode_getvalue, (setter)PySyckScalar_setvalue,
[15]484        PyDoc_STR("the node value, a string"), NULL},
[14]485    {"tag", (getter)PySyckNode_gettag, (setter)PySyckNode_settag,
[15]486        PyDoc_STR("the node tag, a string or None"), NULL},
[14]487    {"anchor", (getter)PySyckNode_getanchor, (setter)PySyckNode_setanchor,
[15]488        PyDoc_STR("the node anchor, a string or None"), NULL},
[12]489    {"style", (getter)PySyckScalar_getstyle, (setter)PySyckScalar_setstyle,
[15]490        PyDoc_STR("the node style, values: None (means literal or plain),\n"
491            "'1quote', '2quote', 'fold', 'literal', 'plain'"), NULL},
[12]492    {"indent", (getter)PySyckScalar_getindent, (setter)PySyckScalar_setindent,
[15]493        PyDoc_STR("the node indentation, an integer"), NULL},
[12]494    {"width", (getter)PySyckScalar_getwidth, (setter)PySyckScalar_setwidth,
[15]495        PyDoc_STR("the node width, an integer"), NULL},
[12]496    {"chomp", (getter)PySyckScalar_getchomp, (setter)PySyckScalar_setchomp,
[15]497        PyDoc_STR("the chomping method,\n"
498            "values: None (clip), '-' (strip), or '+' (keep)"), NULL},
[12]499    {NULL}  /* Sentinel */
500};
501
502static PyTypeObject PySyckScalar_Type = {
503    PyObject_HEAD_INIT(NULL)
504    0,                                          /* ob_size */
505    "_syck.Scalar",                             /* tp_name */
506    sizeof(PySyckScalarObject),                 /* tp_basicsize */
507    0,                                          /* tp_itemsize */
[14]508    0,                                          /* tp_dealloc */
[12]509    0,                                          /* tp_print */
510    0,                                          /* tp_getattr */
511    0,                                          /* tp_setattr */
512    0,                                          /* tp_compare */
513    0,                                          /* tp_repr */
514    0,                                          /* tp_as_number */
515    0,                                          /* tp_as_sequence */
516    0,                                          /* tp_as_mapping */
517    0,                                          /* tp_hash */
518    0,                                          /* tp_call */
519    0,                                          /* tp_str */
520    0,                                          /* tp_getattro */
521    0,                                          /* tp_setattro */
522    0,                                          /* tp_as_buffer */
[14]523    Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,     /* tp_flags */
[12]524    PySyckScalar_doc,                           /* tp_doc */
[14]525    0,                                          /* tp_traverse */
526    0,                                          /* tp_clear */
[12]527    0,                                          /* tp_richcompare */
528    0,                                          /* tp_weaklistoffset */
529    0,                                          /* tp_iter */
530    0,                                          /* tp_iternext */
531    0,                                          /* tp_methods */
532    0,                                          /* tp_members */
533    PySyckScalar_getsetters,                    /* tp_getset */
534    &PySyckNode_Type,                           /* tp_base */
535    0,                                          /* tp_dict */
536    0,                                          /* tp_descr_get */
537    0,                                          /* tp_descr_set */
538    0,                                          /* tp_dictoffset */
539    (initproc)PySyckScalar_init,                /* tp_init */
540    0,                                          /* tp_alloc */
541    PySyckScalar_new,                           /* tp_new */
542};
543
[14]544/****************************************************************************
545 * The type _syck.Seq.
546 ****************************************************************************/
[12]547
[14]548PyDoc_STRVAR(PySyckSeq_doc,
549    "Seq(value=[], tag=None, inline=False) -> a Seq node\n\n"
550    "_syck.Seq represents a sequence node in Syck parser and emitter\n"
[25]551    "trees. A sequence node points to an ordered set of subnodes.\n");
[14]552
553typedef struct {
554    PyObject_HEAD
555    /* Common fields for all Node types: */
556    PyObject *value;    /* always an object */
557    PyObject *tag;      /* a string object or NULL */
558    PyObject *anchor;   /* a string object or NULL */
559    /* Seq-specific fields: */
560    enum seq_style style;
561} PySyckSeqObject;
562
563static PyObject *
564PySyckSeq_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
565{
566    PySyckSeqObject *self;
567
568    self = (PySyckSeqObject *)type->tp_alloc(type, 0);
569    if (!self) return NULL;
570
571    self->value = PyList_New(0);
572    if (!self->value) {
573        Py_DECREF(self);
574        return NULL;
575    }
576
577    self->tag = NULL;
578    self->anchor = NULL;
579    self->style = seq_none;
580
581    return (PyObject *)self;
582}
583
584static int
585PySyckSeq_setvalue(PySyckSeqObject *self, PyObject *value, void *closure)
586{
587    if (!value) {
588        PyErr_SetString(PyExc_TypeError, "cannot delete 'value'");
589        return -1;
590    }
[17]591    if (!PyList_Check(value)) {
592        PyErr_SetString(PyExc_TypeError, "'value' must be a list");
[14]593        return -1;
594    }
595
596    Py_DECREF(self->value);
597    Py_INCREF(value);
598    self->value = value;
599
600    return 0;
601}
602
603static PyObject *
604PySyckSeq_getinline(PySyckSeqObject *self, void *closure)
605{
606    PyObject *value = (self->style == seq_inline) ? Py_True : Py_False;
607
608    Py_INCREF(value);
609    return value;
610}
611
612static int
613PySyckSeq_setinline(PySyckSeqObject *self, PyObject *value, void *closure)
614{
615    if (!value) {
616        PyErr_SetString(PyExc_TypeError, "cannot delete 'inline'");
617        return -1;
618    }
619
620    if (!PyInt_Check(value)) {
621        PyErr_SetString(PyExc_TypeError, "'inline' must be a Boolean object");
622        return -1;
623    }
624
625    self->style = PyInt_AS_LONG(value) ? seq_inline : seq_none;
626
627    return 0;
628}
629
630static int
631PySyckSeq_init(PySyckSeqObject *self, PyObject *args, PyObject *kwds)
632{
633    PyObject *value = NULL;
634    PyObject *tag = NULL;
635    PyObject *anchor = NULL;
636    PyObject *inline_ = NULL;
637
638    static char *kwdlist[] = {"value", "tag", "anchor", "inline", NULL};
639
640    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwdlist,
641                &value, &tag, &anchor, &inline_))
642        return -1;
643
644    if (value && PySyckSeq_setvalue(self, value, NULL) < 0)
645        return -1;
646
647    if (tag && PySyckNode_settag((PySyckNodeObject *)self, tag, NULL) < 0)
648        return -1;
649
650    if (anchor && PySyckNode_setanchor((PySyckNodeObject *)self, anchor, NULL) < 0)
651        return -1;
652
653    if (inline_ && PySyckSeq_setinline(self, inline_, NULL) < 0)
654        return -1;
655
656    return 0;
657}
658
659static PyGetSetDef PySyckSeq_getsetters[] = {
660    {"kind", (getter)PySyckNode_getkind, NULL,
[15]661        PyDoc_STR("the node kind, always 'seq', read-only"), &PySyck_SeqKind},
[14]662    {"value", (getter)PySyckNode_getvalue, (setter)PySyckSeq_setvalue,
[15]663        PyDoc_STR("the node value, a sequence"), NULL},
[14]664    {"tag", (getter)PySyckNode_gettag, (setter)PySyckNode_settag,
[15]665        PyDoc_STR("the node tag, a string or None"), NULL},
[14]666    {"anchor", (getter)PySyckNode_getanchor, (setter)PySyckNode_setanchor,
[15]667        PyDoc_STR("the node anchor, a string or None"), NULL},
[14]668    {"inline", (getter)PySyckSeq_getinline, (setter)PySyckSeq_setinline,
[15]669        PyDoc_STR("the block/flow flag"), NULL},
[14]670    {NULL}  /* Sentinel */
671};
672
673static PyTypeObject PySyckSeq_Type = {
674    PyObject_HEAD_INIT(NULL)
675    0,                                          /* ob_size */
676    "_syck.Seq",                                /* tp_name */
677    sizeof(PySyckSeqObject),                    /* tp_basicsize */
678    0,                                          /* tp_itemsize */
679    0,                                          /* tp_dealloc */
680    0,                                          /* tp_print */
681    0,                                          /* tp_getattr */
682    0,                                          /* tp_setattr */
683    0,                                          /* tp_compare */
684    0,                                          /* tp_repr */
685    0,                                          /* tp_as_number */
686    0,                                          /* tp_as_sequence */
687    0,                                          /* tp_as_mapping */
688    0,                                          /* tp_hash */
689    0,                                          /* tp_call */
690    0,                                          /* tp_str */
691    0,                                          /* tp_getattro */
692    0,                                          /* tp_setattro */
693    0,                                          /* tp_as_buffer */
694    Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC,  /* tp_flags */
695    PySyckSeq_doc,                              /* tp_doc */
696    (traverseproc)PySyckNode_traverse,          /* tp_traverse */
697    (inquiry)PySyckNode_clear,                  /* tp_clear */
698    0,                                          /* tp_richcompare */
699    0,                                          /* tp_weaklistoffset */
700    0,                                          /* tp_iter */
701    0,                                          /* tp_iternext */
702    0,                                          /* tp_methods */
703    0,                                          /* tp_members */
704    PySyckSeq_getsetters,                       /* tp_getset */
705    &PySyckNode_Type,                           /* tp_base */
706    0,                                          /* tp_dict */
707    0,                                          /* tp_descr_get */
708    0,                                          /* tp_descr_set */
709    0,                                          /* tp_dictoffset */
710    (initproc)PySyckSeq_init,                   /* tp_init */
711    0,                                          /* tp_alloc */
712    PySyckSeq_new,                              /* tp_new */
713};
714
715/****************************************************************************
716 * The type _syck.Map.
717 ****************************************************************************/
718
719PyDoc_STRVAR(PySyckMap_doc,
[25]720    "Map(value={}, tag=None, inline=False) -> a Map node\n\n"
[14]721    "_syck.Map represents a mapping node in Syck parser and emitter\n"
[25]722    "trees. A mapping node points to an unordered collections of pairs.\n");
[14]723
724typedef struct {
725    PyObject_HEAD
726    /* Common fields for all Node types: */
727    PyObject *value;    /* always an object */
728    PyObject *tag;      /* a string object or NULL */
729    PyObject *anchor;   /* a string object or NULL */
730    /* Map-specific fields: */
731    enum map_style style;
732} PySyckMapObject;
733
734static PyObject *
735PySyckMap_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
736{
737    PySyckMapObject *self;
738
739    self = (PySyckMapObject *)type->tp_alloc(type, 0);
740    if (!self) return NULL;
741
742    self->value = PyDict_New();
743    if (!self->value) {
744        Py_DECREF(self);
745        return NULL;
746    }
747
748    self->tag = NULL;
749    self->anchor = NULL;
750    self->style = seq_none;
751
752    return (PyObject *)self;
753}
754
755static int
756PySyckMap_setvalue(PySyckMapObject *self, PyObject *value, void *closure)
757{
758    if (!value) {
759        PyErr_SetString(PyExc_TypeError, "cannot delete 'value'");
760        return -1;
761    }
[17]762    if (!PyDict_Check(value) && !PyList_Check(value)) {
763        PyErr_SetString(PyExc_TypeError,
764                "'value' must be a list of pairs or a dictionary");
[14]765        return -1;
766    }
767
768    Py_DECREF(self->value);
769    Py_INCREF(value);
770    self->value = value;
771
772    return 0;
773}
774
775static PyObject *
776PySyckMap_getinline(PySyckMapObject *self, void *closure)
777{
778    PyObject *value = (self->style == map_inline) ? Py_True : Py_False;
779
780    Py_INCREF(value);
781    return value;
782}
783
784static int
785PySyckMap_setinline(PySyckMapObject *self, PyObject *value, void *closure)
786{
787    if (!value) {
788        PyErr_SetString(PyExc_TypeError, "cannot delete 'inline'");
789        return -1;
790    }
791
792    if (!PyInt_Check(value)) {
793        PyErr_SetString(PyExc_TypeError, "'inline' must be a Boolean object");
794        return -1;
795    }
796
797    self->style = PyInt_AS_LONG(value) ? map_inline : map_none;
798
799    return 0;
800}
801
802static int
803PySyckMap_init(PySyckMapObject *self, PyObject *args, PyObject *kwds)
804{
805    PyObject *value = NULL;
806    PyObject *tag = NULL;
807    PyObject *anchor = NULL;
808    PyObject *inline_ = NULL;
809
810    static char *kwdlist[] = {"value", "tag", "anchor", "inline", NULL};
811
812    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwdlist,
813                &value, &tag, &anchor, &inline_))
814        return -1;
815
816    if (value && PySyckMap_setvalue(self, value, NULL) < 0)
817        return -1;
818
819    if (tag && PySyckNode_settag((PySyckNodeObject *)self, tag, NULL) < 0)
820        return -1;
821
822    if (anchor && PySyckNode_setanchor((PySyckNodeObject *)self, anchor, NULL) < 0)
823        return -1;
824
825    if (inline_ && PySyckMap_setinline(self, inline_, NULL) < 0)
826        return -1;
827
828    return 0;
829}
830
831static PyGetSetDef PySyckMap_getsetters[] = {
832    {"kind", (getter)PySyckNode_getkind, NULL,
[15]833        PyDoc_STR("the node kind, always 'map', read-only"), &PySyck_MapKind},
[14]834    {"value", (getter)PySyckNode_getvalue, (setter)PySyckMap_setvalue,
[25]835        PyDoc_STR("the node value, a list of pairs or a dictionary"), NULL},
[14]836    {"tag", (getter)PySyckNode_gettag, (setter)PySyckNode_settag,
[15]837        PyDoc_STR("the node tag, a string or None"), NULL},
[14]838    {"anchor", (getter)PySyckNode_getanchor, (setter)PySyckNode_setanchor,
[15]839        PyDoc_STR("the node anchor, a string or None"), NULL},
[14]840    {"inline", (getter)PySyckMap_getinline, (setter)PySyckMap_setinline,
[15]841        PyDoc_STR("the block/flow flag"), NULL},
[14]842    {NULL}  /* Sentinel */
843};
844
845static PyTypeObject PySyckMap_Type = {
846    PyObject_HEAD_INIT(NULL)
847    0,                                          /* ob_size */
848    "_syck.Map",                                /* tp_name */
849    sizeof(PySyckMapObject),                    /* tp_basicsize */
850    0,                                          /* tp_itemsize */
851    0,                                          /* tp_dealloc */
852    0,                                          /* tp_print */
853    0,                                          /* tp_getattr */
854    0,                                          /* tp_setattr */
855    0,                                          /* tp_compare */
856    0,                                          /* tp_repr */
857    0,                                          /* tp_as_number */
858    0,                                          /* tp_as_sequence */
859    0,                                          /* tp_as_mapping */
860    0,                                          /* tp_hash */
861    0,                                          /* tp_call */
862    0,                                          /* tp_str */
863    0,                                          /* tp_getattro */
864    0,                                          /* tp_setattro */
865    0,                                          /* tp_as_buffer */
866    Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC,  /* tp_flags */
867    PySyckMap_doc,                              /* tp_doc */
868    (traverseproc)PySyckNode_traverse,          /* tp_traverse */
869    (inquiry)PySyckNode_clear,                  /* tp_clear */
870    0,                                          /* tp_richcompare */
871    0,                                          /* tp_weaklistoffset */
872    0,                                          /* tp_iter */
873    0,                                          /* tp_iternext */
874    0,                                          /* tp_methods */
875    0,                                          /* tp_members */
876    PySyckMap_getsetters,                       /* tp_getset */
877    &PySyckNode_Type,                           /* tp_base */
878    0,                                          /* tp_dict */
879    0,                                          /* tp_descr_get */
880    0,                                          /* tp_descr_set */
881    0,                                          /* tp_dictoffset */
882    (initproc)PySyckMap_init,                   /* tp_init */
883    0,                                          /* tp_alloc */
884    PySyckMap_new,                              /* tp_new */
885};
886
[15]887/****************************************************************************
888 * The type _syck.Parser.
889 ****************************************************************************/
[14]890
[15]891PyDoc_STRVAR(PySyckParser_doc,
892    "Parser(source, implicit_typing=True, taguri_expansion=True)\n"
893    "      -> a Parser object\n\n"
894    "_syck.Parser is a low-lever wrapper of the Syck parser. It parses\n"
[25]895    "a YAML stream and produces a tree of Nodes.\n");
[15]896
[12]897typedef struct {
898    PyObject_HEAD
[15]899    /* Attributes: */
900    PyObject *source;       /* a string or file-like object */
901    int implicit_typing;
902    int taguri_expansion;
903    /* Internal fields: */
904    PyObject *symbols;      /* symbol table, a list, NULL outside parse() */
905    SyckParser *parser;
906    int parsing;
907    int halt;
908} PySyckParserObject;
[4]909
[15]910static PyObject *
911PySyckParser_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
912{
913    PySyckParserObject *self;
914
915    self = (PySyckParserObject *)type->tp_alloc(type, 0);
916    if (!self) return NULL;
917
918    self->source = NULL;
919    self->implicit_typing = 0;
920    self->taguri_expansion = 0;
921    self->symbols = NULL;
922    self->parser = NULL;
923    self->parsing = 0;
924    self->halt = 1;
925
926    /*
927    self->symbols = PyList_New(0);
928    if (!self->symbols) {
929        Py_DECREF(self);
930        return NULL;
931    }
932    */
933
934    return (PyObject *)self;
935}
936
937static int
938PySyckParser_clear(PySyckParserObject *self)
939{
940    PyObject *tmp;
941
942    if (self->parser) {
943        syck_free_parser(self->parser);
944        self->parser = NULL;
945    }
946
947    tmp = self->source;
948    self->source = NULL;
949    Py_XDECREF(tmp);
950
951    tmp = self->symbols;
952    self->symbols = NULL;
953    Py_XDECREF(tmp);
954
955    return 0;
956}
957
958static int
959PySyckParser_traverse(PySyckParserObject *self, visitproc visit, void *arg)
960{
961    int ret;
962
963    if (self->source)
964        if ((ret = visit(self->source, arg)) != 0)
965            return ret;
966
967    if (self->symbols)
968        if ((ret = visit(self->symbols, arg)) != 0)
969            return ret;
970
971    return 0;
972}
973
[4]974static void
[15]975PySyckParser_dealloc(PySyckParserObject *self)
[4]976{
[15]977    PySyckParser_clear(self);
978    self->ob_type->tp_free((PyObject *)self);
[4]979}
980
981static PyObject *
[15]982PySyckParser_getsource(PySyckParserObject *self, void *closure)
[4]983{
[15]984    PyObject *value = self->source ? self->source : Py_None;
985
986    Py_INCREF(value);
987    return value;
988}
989
990static PyObject *
991PySyckParser_getimplicit_typing(PySyckParserObject *self, void *closure)
992{
993    PyObject *value = self->implicit_typing ? Py_True : Py_False;
994
995    Py_INCREF(value);
996    return value;
997}
998
999static PyObject *
1000PySyckParser_gettaguri_expansion(PySyckParserObject *self, void *closure)
1001{
1002    PyObject *value = self->taguri_expansion ? Py_True : Py_False;
1003
1004    Py_INCREF(value);
1005    return value;
1006}
1007
1008static PyObject *
1009PySyckParser_geteof(PySyckParserObject *self, void *closure)
1010{
1011    PyObject *value = self->halt ? Py_True : Py_False;
1012
1013    Py_INCREF(value);
1014    return value;
1015}
1016
1017static PyGetSetDef PySyckParser_getsetters[] = {
1018    {"source", (getter)PySyckParser_getsource, NULL,
[25]1019        PyDoc_STR("IO source, a string or a file-like object"), NULL},
[15]1020    {"implicit_typing", (getter)PySyckParser_getimplicit_typing, NULL,
1021        PyDoc_STR("implicit typing of builtin YAML types"), NULL},
1022    {"taguri_expansion", (getter)PySyckParser_gettaguri_expansion, NULL,
1023        PyDoc_STR("expansion of types in full taguri"), NULL},
1024    {"eof", (getter)PySyckParser_geteof, NULL,
1025        PyDoc_STR("EOF flag"), NULL},
1026    {NULL}  /* Sentinel */
1027};
1028
1029static SYMID
1030PySyckParser_node_handler(SyckParser *parser, SyckNode *node)
1031{
[34]1032    PyGILState_STATE gs;
1033
[15]1034    PySyckParserObject *self = (PySyckParserObject *)parser->bonus;
1035
1036    SYMID index;
1037    PySyckNodeObject *object = NULL;
1038
1039    PyObject *key, *value;
1040    int k;
1041
1042    if (self->halt)
1043        return -1;
1044
[34]1045    gs = PyGILState_Ensure();
1046
[15]1047    switch (node->kind) {
1048
1049        case syck_str_kind:
1050            object = (PySyckNodeObject *)
1051                PySyckScalar_new(&PySyckScalar_Type, NULL, NULL);
1052            if (!object) goto error;
1053            value = PyString_FromStringAndSize(node->data.str->ptr,
1054                    node->data.str->len);
1055            if (!value) goto error;
1056            Py_DECREF(object->value);
1057            object->value = value;
1058            break;
1059
1060        case syck_seq_kind:
1061            object = (PySyckNodeObject *)
1062                PySyckSeq_new(&PySyckSeq_Type, NULL, NULL);
1063            if (!object) goto error;
1064            for (k = 0; k < node->data.list->idx; k++) {
[20]1065                index = syck_seq_read(node, k)-1;
[15]1066                value = PyList_GetItem(self->symbols, index);
1067                if (!value) goto error;
1068                if (PyList_Append(object->value, value) < 0)
1069                    goto error;
1070            }
1071            break;
1072
1073        case syck_map_kind:
1074            object = (PySyckNodeObject *)
1075                PySyckMap_new(&PySyckMap_Type, NULL, NULL);
1076            if (!object) goto error;
1077            for (k = 0; k < node->data.pairs->idx; k++)
1078            {
[20]1079                index = syck_map_read(node, map_key, k)-1;
[15]1080                key = PyList_GetItem(self->symbols, index);
1081                if (!key) goto error;
[20]1082                index = syck_map_read(node, map_value, k)-1;
[15]1083                value = PyList_GetItem(self->symbols, index);
1084                if (!value) goto error;
1085                if (PyDict_SetItem(object->value, key, value) < 0)
1086                    goto error;
1087            }
1088            break;
1089    }
1090
1091    if (node->type_id) {
1092        object->tag = PyString_FromString(node->type_id);
1093        if (!object->tag) goto error;
1094    }
1095
1096    if (node->anchor) {
1097        object->anchor = PyString_FromString(node->anchor);
1098        if (!object->anchor) goto error;
1099    }
1100
1101    if (PyList_Append(self->symbols, (PyObject *)object) < 0)
1102        goto error;
1103
[123]1104    Py_DECREF(object);
1105
[20]1106    index = PyList_GET_SIZE(self->symbols);
[34]1107    PyGILState_Release(gs);
[15]1108    return index;
1109
1110error:
1111    Py_XDECREF(object);
[34]1112    PyGILState_Release(gs);
[15]1113    self->halt = 1;
1114    return -1;
1115}
1116
1117static void
1118PySyckParser_error_handler(SyckParser *parser, char *str)
1119{
[34]1120    PyGILState_STATE gs;
1121
[15]1122    PySyckParserObject *self = (PySyckParserObject *)parser->bonus;
[4]1123    PyObject *value;
1124
[15]1125    if (self->halt) return;
1126
[34]1127    gs = PyGILState_Ensure();
1128
[15]1129    self->halt = 1;
1130
1131    value = Py_BuildValue("(sii)", str,
1132            parser->linect, parser->cursor - parser->lineptr);
1133    if (value) {
1134        PyErr_SetObject(PySyck_Error, value);
1135    }
[34]1136
1137    PyGILState_Release(gs);
[15]1138}
1139
[17]1140SyckNode *
1141PySyckParser_bad_anchor_handler(SyckParser *parser, char *anchor)
1142{
[34]1143    PyGILState_STATE gs;
1144
[17]1145    PySyckParserObject *self = (PySyckParserObject *)parser->bonus;
1146
1147    if (!self->halt) {
[34]1148        gs = PyGILState_Ensure();
1149
[17]1150        self->halt = 1;
1151        PyErr_SetString(PyExc_TypeError, "recursive anchors are not implemented");
[34]1152
1153        PyGILState_Release(gs);
[17]1154    }
1155
1156    return syck_alloc_str();
1157}
1158
[15]1159static long
1160PySyckParser_read_handler(char *buf, SyckIoFile *file, long max_size, long skip)
1161{
[34]1162    PyGILState_STATE gs;
1163
[15]1164    PySyckParserObject *self = (PySyckParserObject *)file->ptr;
1165
1166    PyObject *value;
1167
1168    char *str;
1169    int length;
1170
1171    buf[skip] = '\0';
1172
1173    if (self->halt) {
1174        return skip;
1175    }
1176   
1177    max_size -= skip;
1178
[34]1179    gs = PyGILState_Ensure();
1180
[15]1181    value = PyObject_CallMethod(self->source, "read", "(i)", max_size);
1182    if (!value) {
1183        self->halt = 1;
[34]1184
1185        PyGILState_Release(gs);
1186
[15]1187        return skip;
1188    }
1189
1190    if (!PyString_CheckExact(value)) {
1191        Py_DECREF(value);
1192        PyErr_SetString(PyExc_TypeError, "file-like object should return a string");
1193        self->halt = 1;
1194       
[34]1195        PyGILState_Release(gs);
1196
[15]1197        return skip;
1198    }
1199
1200    str = PyString_AS_STRING(value);
1201    length = PyString_GET_SIZE(value);
1202    if (!length) {
1203        Py_DECREF(value);
[34]1204
1205        PyGILState_Release(gs);
1206
[15]1207        return skip;
1208    }
1209
1210    if (length > max_size) {
1211        Py_DECREF(value);
1212        PyErr_SetString(PyExc_ValueError, "read returns an overly long string");
1213        self->halt = 1;
[34]1214
1215        PyGILState_Release(gs);
1216
[15]1217        return skip;
1218    }
1219
1220    memcpy(buf+skip, str, length);
1221    length += skip;
1222    buf[length] = '\0';
1223
1224    Py_DECREF(value);
1225
[34]1226    PyGILState_Release(gs);
1227
[15]1228    return length;
1229}
1230
1231static int
1232PySyckParser_init(PySyckParserObject *self, PyObject *args, PyObject *kwds)
1233{
1234    PyObject *source = NULL;
1235    int implicit_typing = 1;
1236    int taguri_expansion = 1;
1237
1238    static char *kwdlist[] = {"source", "implicit_typing", "taguri_expansion",
1239        NULL};
1240
1241    PySyckParser_clear(self);
1242
1243    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|ii", kwdlist,
1244                &source, &implicit_typing, &taguri_expansion))
1245        return -1;
1246
1247    Py_INCREF(source);
1248    self->source = source;
1249
1250    self->implicit_typing = implicit_typing;
1251    self->taguri_expansion = taguri_expansion;
1252
1253    self->parser = syck_new_parser();
1254    self->parser->bonus = self;
1255
1256    if (PyString_CheckExact(self->source)) {
1257        syck_parser_str(self->parser,
1258                PyString_AS_STRING(self->source),
1259                PyString_GET_SIZE(self->source), NULL);
1260    }
1261    /*
1262    else if (PyUnicode_CheckExact(self->source)) {
1263        syck_parser_str(self->parser,
1264                PyUnicode_AS_DATA(self->source),
1265                PyString_GET_DATA_SIZE(self->source), NULL);
1266    }
1267    */
[4]1268    else {
[15]1269        syck_parser_file(self->parser, (FILE *)self, PySyckParser_read_handler);
1270    }
1271
1272    syck_parser_implicit_typing(self->parser, self->implicit_typing);
1273    syck_parser_taguri_expansion(self->parser, self->taguri_expansion);
1274
1275    syck_parser_handler(self->parser, PySyckParser_node_handler);
1276    syck_parser_error_handler(self->parser, PySyckParser_error_handler);
[17]1277    syck_parser_bad_anchor_handler(self->parser, PySyckParser_bad_anchor_handler);
[15]1278
1279    self->parsing = 0;
1280    self->halt = 0;
1281
1282    return 0;
1283}
1284
1285static PyObject *
1286PySyckParser_parse(PySyckParserObject *self)
1287{
1288    SYMID index;
1289    PyObject *value;
1290
1291    if (self->parsing) {
[25]1292        PyErr_SetString(PyExc_RuntimeError,
1293                "do not call Parser.parse while it is already running");
[4]1294        return NULL;
1295    }
1296
[15]1297    if (self->halt) {
1298        Py_INCREF(Py_None);
1299        return Py_None;
1300    }
1301
1302    self->symbols = PyList_New(0);
1303    if (!self->symbols) {
1304        return NULL;
1305    }
1306
1307    self->parsing = 1;
[34]1308    Py_BEGIN_ALLOW_THREADS
[20]1309    index = syck_parse(self->parser)-1;
[34]1310    Py_END_ALLOW_THREADS
[15]1311    self->parsing = 0;
1312
1313    if (self->halt || self->parser->eof) {
1314        Py_DECREF(self->symbols);
1315        self->symbols = NULL;
1316
1317        if (self->halt) return NULL;
1318
1319        self->halt = 1;
1320        Py_INCREF(Py_None);
1321        return Py_None;
1322    }
1323
1324    value = PyList_GetItem(self->symbols, index);
[123]1325    Py_XINCREF(value);
[15]1326
1327    Py_DECREF(self->symbols);
1328    self->symbols = NULL;
1329
[4]1330    return value;
1331}
1332
[15]1333PyDoc_STRVAR(PySyckParser_parse_doc,
1334    "parse() -> the root Node object\n\n"
[25]1335    "Parses the source and returns the root of the Node tree. Call it\n"
1336    "several times to retrieve all documents from the source. On EOF,\n"
1337    "returns None and sets the 'eof' attribute on.\n");
[4]1338
[15]1339static PyMethodDef PySyckParser_methods[] = {
1340    {"parse",  (PyCFunction)PySyckParser_parse,
1341        METH_NOARGS, PySyckParser_parse_doc},
1342    {NULL}  /* Sentinel */
1343};
1344
1345static PyTypeObject PySyckParser_Type = {
[4]1346    PyObject_HEAD_INIT(NULL)
[15]1347    0,                                          /* ob_size */
1348    "_syck.Parser",                             /* tp_name */
1349    sizeof(PySyckParserObject),                 /* tp_basicsize */
1350    0,                                          /* tp_itemsize */
1351    (destructor)PySyckParser_dealloc,           /* tp_dealloc */
1352    0,                                          /* tp_print */
1353    0,                                          /* tp_getattr */
1354    0,                                          /* tp_setattr */
1355    0,                                          /* tp_compare */
1356    0,                                          /* tp_repr */
1357    0,                                          /* tp_as_number */
1358    0,                                          /* tp_as_sequence */
1359    0,                                          /* tp_as_mapping */
1360    0,                                          /* tp_hash */
1361    0,                                          /* tp_call */
1362    0,                                          /* tp_str */
1363    0,                                          /* tp_getattro */
1364    0,                                          /* tp_setattro */
1365    0,                                          /* tp_as_buffer */
1366    Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC,  /* tp_flags */
1367    PySyckParser_doc,                           /* tp_doc */
1368    (traverseproc)PySyckParser_traverse,        /* tp_traverse */
1369    (inquiry)PySyckParser_clear,                /* tp_clear */
1370    0,                                          /* tp_richcompare */
1371    0,                                          /* tp_weaklistoffset */
1372    0,                                          /* tp_iter */
1373    0,                                          /* tp_iternext */
1374    PySyckParser_methods,                       /* tp_methods */
1375    0,                                          /* tp_members */
1376    PySyckParser_getsetters,                    /* tp_getset */
1377    0,                                          /* tp_base */
1378    0,                                          /* tp_dict */
1379    0,                                          /* tp_descr_get */
1380    0,                                          /* tp_descr_set */
1381    0,                                          /* tp_dictoffset */
1382    (initproc)PySyckParser_init,                /* tp_init */
1383    0,                                          /* tp_alloc */
1384    PySyckParser_new,                           /* tp_new */
[4]1385};
1386
[16]1387/****************************************************************************
[17]1388 * The type _syck.Emitter.
1389 ****************************************************************************/
1390
1391PyDoc_STRVAR(PySyckEmitter_doc,
[25]1392    "Emitter(output, headless=False, use_header=False, use_version=False,\n"
1393    "        explicit_typing=True, style=None, best_width=80, indent=2)\n"
1394    "                -> an Emitter object\n\n"
1395    "_syck.Emitter is a low-lever wrapper of the Syck emitter. It emits\n"
[17]1396    "a tree of Nodes into a YAML stream.\n");
1397
1398typedef struct {
1399    PyObject_HEAD
1400    /* Attributes: */
1401    PyObject *output;       /* a file-like object */
1402    int headless;
1403    int use_header;
1404    int use_version;
1405    int explicit_typing;
1406    enum scalar_style style;
1407    int best_width;
1408    int indent;
1409    /* Internal fields: */
1410    PyObject *symbols;      /* symbol table, a list, NULL outside emit() */
1411    PyObject *nodes;        /* node -> symbol, a dict, NULL outside emit() */
1412    SyckEmitter *emitter;
1413    int emitting;
1414    int halt;
1415} PySyckEmitterObject;
1416
1417static PyObject *
1418PySyckEmitter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1419{
1420    PySyckEmitterObject *self;
1421
1422    self = (PySyckEmitterObject *)type->tp_alloc(type, 0);
1423    if (!self) return NULL;
1424
1425    self->output = NULL;
1426    self->headless = 0;
1427    self->use_header = 0;
1428    self->use_version = 0;
1429    self->explicit_typing = 0;
1430    self->style = scalar_none;
1431    self->best_width = 0;
1432    self->indent = 0;
1433    self->symbols = NULL;
1434    self->nodes = NULL;
1435    self->emitter = NULL;
1436    self->emitting = 0;
1437    self->halt = 1;
1438
1439    return (PyObject *)self;
1440}
1441
1442static int
1443PySyckEmitter_clear(PySyckEmitterObject *self)
1444{
1445    PyObject *tmp;
1446
1447    if (self->emitter) {
1448        syck_free_emitter(self->emitter);
1449        self->emitter = NULL;
1450    }
1451
1452    tmp = self->output;
1453    self->output = NULL;
1454    Py_XDECREF(tmp);
1455
1456    tmp = self->symbols;
1457    self->symbols = NULL;
1458    Py_XDECREF(tmp);
1459
1460    tmp = self->nodes;
1461    self->nodes = NULL;
1462    Py_XDECREF(tmp);
1463
1464    return 0;
1465}
1466
1467static int
1468PySyckEmitter_traverse(PySyckEmitterObject *self, visitproc visit, void *arg)
1469{
1470    int ret;
1471
1472    if (self->output)
1473        if ((ret = visit(self->output, arg)) != 0)
1474            return ret;
1475
1476    if (self->symbols)
1477        if ((ret = visit(self->symbols, arg)) != 0)
1478            return ret;
1479
1480    if (self->nodes)
1481        if ((ret = visit(self->nodes, arg)) != 0)
1482            return ret;
1483
1484    return 0;
1485}
1486
1487static void
1488PySyckEmitter_dealloc(PySyckEmitterObject *self)
1489{
1490    PySyckEmitter_clear(self);
1491    self->ob_type->tp_free((PyObject *)self);
1492}
1493
1494static PyObject *
1495PySyckEmitter_getoutput(PySyckEmitterObject *self, void *closure)
1496{
1497    PyObject *value = self->output ? self->output : Py_None;
1498
1499    Py_INCREF(value);
1500    return value;
1501}
1502
1503static PyObject *
1504PySyckEmitter_getheadless(PySyckEmitterObject *self, void *closure)
1505{
1506    PyObject *value = self->headless ? Py_True : Py_False;
1507
1508    Py_INCREF(value);
1509    return value;
1510}
1511
1512static PyObject *
1513PySyckEmitter_getuse_header(PySyckEmitterObject *self, void *closure)
1514{
1515    PyObject *value = self->use_header ? Py_True : Py_False;
1516
1517    Py_INCREF(value);
1518    return value;
1519}
1520
1521static PyObject *
1522PySyckEmitter_getuse_version(PySyckEmitterObject *self, void *closure)
1523{
1524    PyObject *value = self->use_version ? Py_True : Py_False;
1525
1526    Py_INCREF(value);
1527    return value;
1528}
1529
1530static PyObject *
1531PySyckEmitter_getexplicit_typing(PySyckEmitterObject *self, void *closure)
1532{
1533    PyObject *value = self->explicit_typing ? Py_True : Py_False;
1534
1535    Py_INCREF(value);
1536    return value;
1537}
1538
1539static PyObject *
1540PySyckEmitter_getstyle(PySyckEmitterObject *self, void *closure)
1541{
1542    PyObject *value;
1543
1544    switch (self->style) {
1545        case scalar_1quote: value = PySyck_1QuoteStyle; break;
1546        case scalar_2quote: value = PySyck_2QuoteStyle; break;
1547        case scalar_fold: value = PySyck_FoldStyle; break;
1548        case scalar_literal: value = PySyck_LiteralStyle; break;
1549        case scalar_plain: value = PySyck_PlainStyle; break;
1550        default: value = Py_None;
1551    }
1552
1553    Py_INCREF(value);
1554    return value;
1555}
1556
1557static PyObject *
1558PySyckEmitter_getbest_width(PySyckEmitterObject *self, void *closure)
1559{
1560    return PyInt_FromLong(self->best_width);
1561}
1562
1563static PyObject *
1564PySyckEmitter_getindent(PySyckEmitterObject *self, void *closure)
1565{
1566    return PyInt_FromLong(self->indent);
1567}
1568
1569static PyGetSetDef PySyckEmitter_getsetters[] = {
1570    {"output", (getter)PySyckEmitter_getoutput, NULL,
1571        PyDoc_STR("output stream, a file-like object"), NULL},
1572    {"headless", (getter)PySyckEmitter_getheadless, NULL,
1573        PyDoc_STR("headerless document flag"), NULL},
1574    {"use_header", (getter)PySyckEmitter_getuse_header, NULL,
[25]1575        PyDoc_STR("force header flag"), NULL},
[17]1576    {"use_version", (getter)PySyckEmitter_getuse_version, NULL,
[25]1577        PyDoc_STR("force version flag"), NULL},
[17]1578    {"explicit_typing", (getter)PySyckEmitter_getexplicit_typing, NULL,
1579        PyDoc_STR("explicit typing for all collections"), NULL},
1580    {"style", (getter)PySyckEmitter_getstyle, NULL,
1581        PyDoc_STR("use literal or folded blocks on all text"), NULL},
1582    {"best_width", (getter)PySyckEmitter_getbest_width, NULL,
1583        PyDoc_STR("best width for folded scalars"), NULL},
1584    {"indent", (getter)PySyckEmitter_getindent, NULL,
1585        PyDoc_STR("default indentation"), NULL},
1586    {NULL}  /* Sentinel */
1587};
1588
1589static void
1590PySyckEmitter_node_handler(SyckEmitter *emitter, st_data_t id)
1591{
[34]1592    PyGILState_STATE gs;
1593
[17]1594    PySyckEmitterObject *self = (PySyckEmitterObject *)emitter->bonus;
1595
1596    PySyckNodeObject *node;
1597    char *tag = NULL;
1598    PyObject *index;
1599    PyObject *key, *value, *item, *pair;
1600    int j, k, l;
1601    char *str;
1602    int len;
1603    int dict_pos;
1604
1605    if (self->halt) return;
1606
[34]1607    gs = PyGILState_Ensure();
1608
[17]1609    node = (PySyckNodeObject *)PyList_GetItem(self->symbols, id);
1610    if (!node) {
1611        PyErr_SetString(PyExc_RuntimeError, "unknown data id");
1612        self->halt = 1;
[34]1613        PyGILState_Release(gs);
[17]1614        return;
1615    }
1616
1617    if (node->tag) {
1618        tag = PyString_AsString(node->tag);
1619        if (!tag) {
1620            self->halt = 1;
[34]1621            PyGILState_Release(gs);
[17]1622            return;
1623        }
1624    }
1625
1626    if (PyObject_TypeCheck((PyObject *)node, &PySyckSeq_Type)) {
1627
1628        syck_emit_seq(emitter, tag, ((PySyckSeqObject *)node)->style);
1629
1630        if (!PyList_Check(node->value)) {
1631            PyErr_SetString(PyExc_TypeError, "value of _syck.Seq must be a list");
1632            self->halt = 1;
[34]1633            PyGILState_Release(gs);
[17]1634            return;
1635        }
1636        l = PyList_GET_SIZE(node->value);
1637        for (k = 0; k < l; k ++) {
1638            item = PyList_GET_ITEM(node->value, k);
1639            if ((index = PyDict_GetItem(self->nodes, item))) {
1640                syck_emit_item(emitter, PyInt_AS_LONG(index));
[34]1641                if (self->halt) {
1642                    PyGILState_Release(gs);
1643                    return;
1644                }
[17]1645            }
1646            else {
1647                PyErr_SetString(PyExc_RuntimeError, "sequence item is not marked");
1648                self->halt = 1;
[34]1649                PyGILState_Release(gs);
[17]1650                return;
1651            }
1652        }
1653        syck_emit_end(emitter);
1654    }
1655
1656    else if (PyObject_TypeCheck((PyObject *)node, &PySyckMap_Type)) {
1657
1658        syck_emit_map(emitter, tag, ((PySyckMapObject *)node)->style);
1659       
1660        if (PyList_Check(node->value)) {
1661            l = PyList_GET_SIZE(node->value);
1662            for (k = 0; k < l; k ++) {
1663                pair = PyList_GET_ITEM(node->value, k);
1664                if (!PyTuple_Check(pair) || PyTuple_GET_SIZE(pair) != 2) {
1665                    PyErr_SetString(PyExc_TypeError,
1666                            "value of _syck.Map must be a list of pairs or a dictionary");
1667                    self->halt = 1;
[34]1668                    PyGILState_Release(gs);
[17]1669                    return;
1670                }
1671                for (j = 0; j < 2; j++) {
1672                    item = PyTuple_GET_ITEM(pair, j);
1673                    if ((index = PyDict_GetItem(self->nodes, item))) {
1674                        syck_emit_item(emitter, PyInt_AS_LONG(index));
[34]1675                        if (self->halt) {
1676                            PyGILState_Release(gs);
1677                            return;
1678                        }
[17]1679                    }
1680                    else {
1681                        PyErr_SetString(PyExc_RuntimeError, "mapping item is not marked");
1682                        self->halt = 1;
[34]1683                        PyGILState_Release(gs);
[17]1684                        return;
1685                    }
1686                }
1687            }
1688        }
1689        else if (PyDict_Check(node->value)) {
1690            dict_pos = 0;
1691            while (PyDict_Next(node->value, &dict_pos, &key, &value)) {
1692                for (j = 0; j < 2; j++) {
1693                    item = j ? value : key;
1694                    if ((index = PyDict_GetItem(self->nodes, item))) {
1695                        syck_emit_item(emitter, PyInt_AS_LONG(index));
[34]1696                        if (self->halt) {
1697                            PyGILState_Release(gs);
1698                            return;
1699                        }
[17]1700                    }
1701                    else {
1702                        PyErr_SetString(PyExc_RuntimeError, "mapping item is not marked");
1703                        self->halt = 1;
[34]1704                        PyGILState_Release(gs);
[17]1705                        return;
1706                    }
1707                }
1708            }
1709        }
1710        else {
1711            PyErr_SetString(PyExc_TypeError,
1712                    "value of _syck.Map must be a list of pairs or a dictionary");
1713            self->halt = 1;
[34]1714            PyGILState_Release(gs);
[17]1715            return;
1716        }
1717
1718        syck_emit_end(emitter);
1719    }
1720
1721    else if (PyObject_TypeCheck((PyObject *)node, &PySyckScalar_Type)) {
1722        if (PyString_AsStringAndSize(node->value, &str, &len) < 0) {
1723            self->halt = 1;
[34]1724            PyGILState_Release(gs);
[17]1725            return;
1726        }
1727        syck_emit_scalar(emitter, tag, ((PySyckScalarObject *)node)->style,
1728                ((PySyckScalarObject *)node)->indent,
1729                ((PySyckScalarObject *)node)->width,
1730                ((PySyckScalarObject *)node)->chomp, str, len);
1731    }
1732
1733    else {
1734        PyErr_SetString(PyExc_TypeError, "Node instance is required");
1735        self->halt = 1;
[34]1736        PyGILState_Release(gs);
[17]1737        return;
1738    }   
[34]1739    PyGILState_Release(gs);
[17]1740}
[34]1741
[17]1742static void
1743PySyckEmitter_write_handler(SyckEmitter *emitter, char *buf, long len)
1744{
[34]1745    PyGILState_STATE gs;
1746
[17]1747    PySyckEmitterObject *self = (PySyckEmitterObject *)emitter->bonus;
1748
[34]1749    gs = PyGILState_Ensure();
1750
[17]1751    if (!PyObject_CallMethod(self->output, "write", "(s#)", buf, len))
1752        self->halt = 1;
[34]1753
1754    PyGILState_Release(gs);
[17]1755}
1756
1757static int
1758PySyckEmitter_init(PySyckEmitterObject *self, PyObject *args, PyObject *kwds)
1759{
1760    PyObject *output = NULL;
1761    int headless = 0;
1762    int use_header = 0;
1763    int use_version = 0;
1764    int explicit_typing = 0;
1765    PyObject *style = NULL;
1766    int best_width = 80;
1767    int indent = 2;
1768
1769    char *str;
1770
1771    static char *kwdlist[] = {"output", "headless", "use_header",
1772        "use_version", "explicit_typing", "style",
1773        "best_width", "indent", NULL};
1774
1775    PySyckEmitter_clear(self);
1776
1777    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|iiiiOii", kwdlist,
1778                &output, &headless, &use_header, &use_version,
1779                &explicit_typing, &style, &best_width, &indent))
1780        return -1;
1781
1782    if (best_width <= 0) {
1783        PyErr_SetString(PyExc_ValueError, "'best_width' must be positive");
1784        return -1;
1785    }
1786    if (indent <= 0) {
1787        PyErr_SetString(PyExc_ValueError, "'indent' must be positive");
1788        return -1;
1789    }
1790
1791    if (!style || style == Py_None) {
1792        self->style = scalar_none;
1793    }
1794    else {
1795        if (!PyString_Check(style)) {
1796            PyErr_SetString(PyExc_TypeError, "'style' must be a string or None");
1797            return -1;
1798        }
1799
1800        str = PyString_AsString(style);
1801        if (!str) return -1;
1802
1803        if (strcmp(str, "1quote") == 0)
1804            self->style = scalar_1quote;
1805        else if (strcmp(str, "2quote") == 0)
1806            self->style = scalar_2quote;
1807        else if (strcmp(str, "fold") == 0)
1808            self->style = scalar_fold;
1809        else if (strcmp(str, "literal") == 0)
1810            self->style = scalar_literal;
1811        else if (strcmp(str, "plain") == 0)
1812            self->style = scalar_plain;
1813        else {
1814            PyErr_SetString(PyExc_ValueError, "unknown 'style'");
1815            return -1;
1816        }
1817    }
1818
1819    self->headless = headless;
1820    self->use_header = use_header;
1821    self->use_version = use_version;
1822    self->explicit_typing = explicit_typing;
1823    self->best_width = best_width;
1824    self->indent = indent;
1825
1826    Py_INCREF(output);
1827    self->output = output;
1828
1829    self->emitting = 0;
1830    self->halt = 0;
1831
1832    return 0;
1833}
1834
1835static int
1836PySyckEmitter_mark(PySyckEmitterObject *self, PyObject *root_node)
1837{
1838    int current, last;
1839    int j, k, l;
1840    PySyckNodeObject *node;
1841    PyObject *item, *key, *value, *pair;
1842    PyObject *index;
1843    int dict_pos;
1844
1845    last = 0;
1846    syck_emitter_mark_node(self->emitter, last);
1847    if (PyList_Append(self->symbols, root_node) < 0)
1848        return -1;
1849    index = PyInt_FromLong(last);
1850    if (!index) return -1;
1851    if (PyDict_SetItem(self->nodes, root_node, index) < 0) {
1852        Py_DECREF(index);
1853        return -1;
1854    }
1855    Py_DECREF(index);
1856
1857    for (current = 0; current < PyList_GET_SIZE(self->symbols); current++) {
1858
1859        node = (PySyckNodeObject *)PyList_GET_ITEM(self->symbols, current);
1860
1861        if (PyObject_TypeCheck((PyObject *)node, &PySyckSeq_Type)) {
1862            if (!PyList_Check(node->value)) {
1863                PyErr_SetString(PyExc_TypeError, "value of _syck.Seq must be a list");
1864                return -1;
1865            }
1866            l = PyList_GET_SIZE(node->value);
1867            for (k = 0; k < l; k ++) {
1868                item = PyList_GET_ITEM(node->value, k);
1869                if ((index = PyDict_GetItem(self->nodes, item))) {
1870                    syck_emitter_mark_node(self->emitter, PyInt_AS_LONG(index));
1871                }
1872                else {
1873                    syck_emitter_mark_node(self->emitter, ++last);
1874                    if (PyList_Append(self->symbols, item) < 0)
1875                        return -1;
1876                    index = PyInt_FromLong(last);
1877                    if (!index) return -1;
1878                    if (PyDict_SetItem(self->nodes, item, index) < 0) {
1879                        Py_DECREF(index);
1880                        return -1;
1881                    }
1882                    Py_DECREF(index);
1883                }
1884            }
1885        }
1886
1887        else if (PyObject_TypeCheck((PyObject *)node, &PySyckMap_Type)) {
1888           
1889            if (PyList_Check(node->value)) {
1890                l = PyList_GET_SIZE(node->value);
1891                for (k = 0; k < l; k ++) {
1892                    pair = PyList_GET_ITEM(node->value, k);
1893                    if (!PyTuple_Check(pair) || PyTuple_GET_SIZE(pair) != 2) {
1894                        PyErr_SetString(PyExc_TypeError,
1895                                "value of _syck.Map must be a list of pairs or a dictionary");
1896                        return -1;
1897                    }
1898                    for (j = 0; j < 2; j++) {
1899                        item = PyTuple_GET_ITEM(pair, j);
1900                        if ((index = PyDict_GetItem(self->nodes, item))) {
1901                            syck_emitter_mark_node(self->emitter, PyInt_AS_LONG(index));
1902                        }
1903                        else {
1904                            syck_emitter_mark_node(self->emitter, ++last);
1905                            if (PyList_Append(self->symbols, item) < 0)
1906                                return -1;
1907                            index = PyInt_FromLong(last);
1908                            if (!index) return -1;
1909                            if (PyDict_SetItem(self->nodes, item, index) < 0) {
1910                                Py_DECREF(index);
1911                                return -1;
1912                            }
1913                            Py_DECREF(index);
1914                        }
1915                    }
1916                }
1917               
1918            }
1919            else if (PyDict_Check(node->value)) {
1920                dict_pos = 0;
1921                while (PyDict_Next(node->value, &dict_pos, &key, &value)) {
1922                    for (j = 0; j < 2; j++) {
1923                        item = j ? value : key;
1924                        if ((index = PyDict_GetItem(self->nodes, item))) {
1925                            syck_emitter_mark_node(self->emitter, PyInt_AS_LONG(index));
1926                        }
1927                        else {
1928                            syck_emitter_mark_node(self->emitter, ++last);
1929                            if (PyList_Append(self->symbols, item) < 0)
1930                                return -1;
1931                            index = PyInt_FromLong(last);
1932                            if (!index) return -1;
1933                            if (PyDict_SetItem(self->nodes, item, index) < 0) {
1934                                Py_DECREF(index);
1935                                return -1;
1936                            }
1937                            Py_DECREF(index);
1938                        }
1939                    }
1940                }
1941            }
1942            else {
1943                PyErr_SetString(PyExc_TypeError,
1944                        "value of _syck.Map must be a list of pairs or a dictionary");
1945                return -1;
1946            }
1947        }
1948
1949        else if (!PyObject_TypeCheck((PyObject *)node, &PySyckScalar_Type)) {
1950            PyErr_SetString(PyExc_TypeError, "Node instance is required");
1951            return -1;
1952        }   
1953    }
1954    return 0;
1955}
1956
1957static PyObject *
1958PySyckEmitter_emit(PySyckEmitterObject *self, PyObject *args)
1959{
1960    PyObject *node;
1961
1962    if (self->emitting) {
1963        PyErr_SetString(PyExc_RuntimeError, "do not call Emitter.emit while it is already emitting");
1964        return NULL;
1965    }
1966
1967    if (self->halt) {
1968        Py_INCREF(Py_None);
1969        return Py_None;
1970    }
1971
1972    if (!PyArg_ParseTuple(args, "O", &node))
1973        return NULL;
1974
1975    self->emitting = 1;
1976
1977
1978    self->symbols = PyList_New(0);
1979    if (!self->symbols) {
1980        return NULL;
1981    }
1982    self->nodes = PyDict_New();
1983    if (!self->nodes) {
1984        Py_DECREF(self->symbols);
1985        self->symbols = NULL;
1986        return NULL;
1987    }
1988
1989    self->emitter = syck_new_emitter();
1990    self->emitter->bonus = self;
1991    self->emitter->headless = self->headless;
1992    self->emitter->use_header = self->use_header;
1993    self->emitter->use_version = self->use_version;
1994    self->emitter->explicit_typing = self->explicit_typing;
1995    self->emitter->style = self->style;
1996    self->emitter->best_width = self->best_width;
1997    self->emitter->indent = self->indent;
1998
1999    syck_emitter_handler(self->emitter, PySyckEmitter_node_handler);
2000    syck_output_handler(self->emitter, PySyckEmitter_write_handler);
2001
2002    if (PySyckEmitter_mark(self, node) < 0) {
2003        Py_DECREF(self->symbols);
2004        self->symbols = NULL;
2005        Py_DECREF(self->nodes);
2006        self->nodes = NULL;
2007        self->emitting = 0;
2008        self->halt = 1;
2009        syck_free_emitter(self->emitter);
2010        self->emitter = NULL;
2011        return NULL;
2012    }
2013
[34]2014    Py_BEGIN_ALLOW_THREADS
[17]2015    syck_emit(self->emitter, 0);
2016    syck_emitter_flush(self->emitter, 0);
[34]2017    Py_END_ALLOW_THREADS
[17]2018
2019    syck_free_emitter(self->emitter);
2020    self->emitter = NULL;
2021
2022    self->emitting = 0;
2023
2024    Py_DECREF(self->symbols);
2025    self->symbols = NULL;
2026    Py_DECREF(self->nodes);
2027    self->nodes = NULL;
2028
2029    if (self->halt) return NULL;
2030
2031    Py_INCREF(Py_None);
2032    return Py_None;
2033}
2034
2035PyDoc_STRVAR(PySyckEmitter_emit_doc,
2036    "emit(root_node) -> None\n\n"
[25]2037    "Emits the Node tree to the output.\n");
[17]2038
2039static PyMethodDef PySyckEmitter_methods[] = {
2040    {"emit",  (PyCFunction)PySyckEmitter_emit,
2041        METH_VARARGS, PySyckEmitter_emit_doc},
2042    {NULL}  /* Sentinel */
2043};
2044
2045static PyTypeObject PySyckEmitter_Type = {
2046    PyObject_HEAD_INIT(NULL)
2047    0,                                          /* ob_size */
2048    "_syck.Emitter",                            /* tp_name */
2049    sizeof(PySyckEmitterObject),                /* tp_basicsize */
2050    0,                                          /* tp_itemsize */
2051    (destructor)PySyckEmitter_dealloc,          /* tp_dealloc */
2052    0,                                          /* tp_print */
2053    0,                                          /* tp_getattr */
2054    0,                                          /* tp_setattr */
2055    0,                                          /* tp_compare */
2056    0,                                          /* tp_repr */
2057    0,                                          /* tp_as_number */
2058    0,                                          /* tp_as_sequence */
2059    0,                                          /* tp_as_mapping */
2060    0,                                          /* tp_hash */
2061    0,                                          /* tp_call */
2062    0,                                          /* tp_str */
2063    0,                                          /* tp_getattro */
2064    0,                                          /* tp_setattro */
2065    0,                                          /* tp_as_buffer */
2066    Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC,  /* tp_flags */
2067    PySyckEmitter_doc,                          /* tp_doc */
2068    (traverseproc)PySyckEmitter_traverse,       /* tp_traverse */
2069    (inquiry)PySyckEmitter_clear,               /* tp_clear */
2070    0,                                          /* tp_richcompare */
2071    0,                                          /* tp_weaklistoffset */
2072    0,                                          /* tp_iter */
2073    0,                                          /* tp_iternext */
2074    PySyckEmitter_methods,                      /* tp_methods */
2075    0,                                          /* tp_members */
2076    PySyckEmitter_getsetters,                   /* tp_getset */
2077    0,                                          /* tp_base */
2078    0,                                          /* tp_dict */
2079    0,                                          /* tp_descr_get */
2080    0,                                          /* tp_descr_set */
2081    0,                                          /* tp_dictoffset */
2082    (initproc)PySyckEmitter_init,               /* tp_init */
2083    0,                                          /* tp_alloc */
2084    PySyckEmitter_new,                          /* tp_new */
2085};
2086
2087/****************************************************************************
[16]2088 * The module _syck.
2089 ****************************************************************************/
[15]2090
[12]2091static PyMethodDef PySyck_methods[] = {
2092    {NULL}  /* Sentinel */
2093};
2094
2095PyDoc_STRVAR(PySyck_doc,
[25]2096    "_syck is a low-level wrapper for the Syck YAML parser and emitter.\n"
2097    "Do not use it directly, use the module 'syck' instead.\n");
[12]2098
[25]2099static int
2100add_slotnames(PyTypeObject *type)
2101{
2102    PyObject *slotnames;
2103    PyObject *name;
2104    PyGetSetDef *getsetter;
2105
2106    if (!type->tp_getset) return 0;
2107    if (!type->tp_dict) return 0;
2108
2109    slotnames = PyList_New(0);
2110    if (!slotnames) return -1;
2111
2112    for (getsetter = type->tp_getset; getsetter->name; getsetter++) {
2113        if (!getsetter->set) continue;
2114        name = PyString_FromString(getsetter->name);
2115        if (!name) {
2116           Py_DECREF(slotnames);
2117           return -1;
2118        }
2119        if (PyList_Append(slotnames, name) < 0) {
2120            Py_DECREF(name);
2121            Py_DECREF(slotnames);
2122            return -1;
2123        }
2124        Py_DECREF(name);
2125    }
2126
2127    if (PyDict_SetItemString(type->tp_dict, "__slotnames__", slotnames) < 0) {
2128        Py_DECREF(slotnames);
2129        return -1;
2130    }
2131
2132    Py_DECREF(slotnames);
2133    return 0;
2134}
2135
[12]2136PyMODINIT_FUNC
2137init_syck(void)
2138{
2139    PyObject *m;
2140
[49]2141    PyEval_InitThreads();   /* Fix segfault for Python 2.3 */
2142
[12]2143    if (PyType_Ready(&PySyckNode_Type) < 0)
2144        return;
2145    if (PyType_Ready(&PySyckScalar_Type) < 0)
2146        return;
[25]2147    if (add_slotnames(&PySyckScalar_Type) < 0)
2148        return;
[14]2149    if (PyType_Ready(&PySyckSeq_Type) < 0)
2150        return;
[25]2151    if (add_slotnames(&PySyckSeq_Type) < 0)
2152        return;
[14]2153    if (PyType_Ready(&PySyckMap_Type) < 0)
2154        return;
[25]2155    if (add_slotnames(&PySyckMap_Type) < 0)
2156        return;
[15]2157    if (PyType_Ready(&PySyckParser_Type) < 0)
2158        return;
[17]2159    if (PyType_Ready(&PySyckEmitter_Type) < 0)
2160        return;
[12]2161   
2162    PySyck_Error = PyErr_NewException("_syck.error", NULL, NULL);
2163    if (!PySyck_Error) return;
2164
2165    PySyck_ScalarKind = PyString_FromString("scalar");
2166    if (!PySyck_ScalarKind) return;
2167    PySyck_SeqKind = PyString_FromString("seq");
2168    if (!PySyck_SeqKind) return;
2169    PySyck_MapKind = PyString_FromString("map");
2170    if (!PySyck_MapKind) return;
2171
2172    PySyck_1QuoteStyle = PyString_FromString("1quote");
2173    if (!PySyck_1QuoteStyle) return;
2174    PySyck_2QuoteStyle = PyString_FromString("2quote");
2175    if (!PySyck_2QuoteStyle) return;
2176    PySyck_FoldStyle = PyString_FromString("fold");
2177    if (!PySyck_FoldStyle) return;
2178    PySyck_LiteralStyle = PyString_FromString("literal");
2179    if (!PySyck_LiteralStyle) return;
2180    PySyck_PlainStyle = PyString_FromString("plain");
2181    if (!PySyck_PlainStyle) return;
2182
2183    PySyck_StripChomp = PyString_FromString("-");
2184    if (!PySyck_StripChomp) return;
2185    PySyck_KeepChomp = PyString_FromString("+");
2186    if (!PySyck_KeepChomp) return;
2187
2188    m = Py_InitModule3("_syck", PySyck_methods, PySyck_doc);
2189
[15]2190    Py_INCREF(PySyck_Error);
2191    if (PyModule_AddObject(m, "error", (PyObject *)PySyck_Error) < 0)
2192        return;
[12]2193    Py_INCREF(&PySyckNode_Type);
2194    if (PyModule_AddObject(m, "Node", (PyObject *)&PySyckNode_Type) < 0)
2195        return;
2196    Py_INCREF(&PySyckScalar_Type);
2197    if (PyModule_AddObject(m, "Scalar", (PyObject *)&PySyckScalar_Type) < 0)
2198        return;
[14]2199    Py_INCREF(&PySyckSeq_Type);
2200    if (PyModule_AddObject(m, "Seq", (PyObject *)&PySyckSeq_Type) < 0)
2201        return;
2202    Py_INCREF(&PySyckMap_Type);
2203    if (PyModule_AddObject(m, "Map", (PyObject *)&PySyckMap_Type) < 0)
2204        return;
[15]2205    Py_INCREF(&PySyckParser_Type);
2206    if (PyModule_AddObject(m, "Parser", (PyObject *)&PySyckParser_Type) < 0)
2207        return;
[17]2208    Py_INCREF(&PySyckEmitter_Type);
2209    if (PyModule_AddObject(m, "Emitter", (PyObject *)&PySyckEmitter_Type) < 0)
2210        return;
[12]2211}
2212
Note: See TracBrowser for help on using the repository browser.