Annotation of gpl/axl/py-axl/py_axl_node.c, revision 1.1

1.1     ! misho       1: /** 
        !             2:  *  PyAxl: Axl Library python bindings
        !             3:  *  Copyright (C) 2009 Advanced Software Production Line, S.L.
        !             4:  *
        !             5:  *  This program is free software; you can redistribute it and/or
        !             6:  *  modify it under the terms of the GNU Lesser General Public License
        !             7:  *  as published by the Free Software Foundation; either version 2.1
        !             8:  *  of the License, or (at your option) any later version.
        !             9:  *
        !            10:  *  This program is distributed in the hope that it will be useful,
        !            11:  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            12:  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
        !            13:  *  Lesser General Public License for more details.
        !            14:  *
        !            15:  *  You should have received a copy of the GNU Lesser General Public
        !            16:  *  License along with this program; if not, write to the Free
        !            17:  *  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
        !            18:  *  02111-1307 USA
        !            19:  *  
        !            20:  *  You may find a copy of the license under this software is released
        !            21:  *  at COPYING file. This is LGPL software: you are welcome to develop
        !            22:  *  proprietary applications using this library without any royalty or
        !            23:  *  fee but returning back any change, improvement or addition in the
        !            24:  *  form of source code, project image, documentation patches, etc.
        !            25:  *
        !            26:  *  For commercial support for XML enabled solutions contact us:
        !            27:  *          
        !            28:  *      Postal address:
        !            29:  *         Advanced Software Production Line, S.L.
        !            30:  *         C/ Antonio Suarez Nº 10, 
        !            31:  *         Edificio Alius A, Despacho 102
        !            32:  *         Alcalá de Henares 28802 (Madrid)
        !            33:  *         Spain
        !            34:  *
        !            35:  *      Email address:
        !            36:  *         info@aspl.es - http://www.aspl.es/axl
        !            37:  */
        !            38: #include <py_axl_node.h>
        !            39: 
        !            40: #define LOG_DOMAIN "py-axl-node"
        !            41: 
        !            42: struct _PyAxlNode {
        !            43:        /* header required to initialize python required bits for
        !            44:           every python object */
        !            45:        PyObject_HEAD
        !            46: 
        !            47:        /* pointer to the axl node */
        !            48:        axlNode   * node;
        !            49:        axl_bool    finish_on_gc;
        !            50: };
        !            51: 
        !            52: static int py_axl_node_init_type (PyAxlNode *self, PyObject *args, PyObject *kwds)
        !            53: {
        !            54:     return 0;
        !            55: }
        !            56: 
        !            57: /** 
        !            58:  * @brief Function used to allocate memory required by the object
        !            59:  * axl.Node
        !            60:  */
        !            61: static PyObject * py_axl_node_new (PyTypeObject *type, PyObject *args, PyObject *kwds)
        !            62: {
        !            63:        PyAxlNode  * self;
        !            64:        const char * name = NULL;
        !            65: 
        !            66:        /* create the object */
        !            67:        self = (PyAxlNode *)type->tp_alloc(type, 0);
        !            68: 
        !            69:        /* parse and get node name */
        !            70:        if (! PyArg_ParseTuple (args, "|s", &name))
        !            71:                return NULL;
        !            72:                
        !            73:        /* create the node if received a defined name */
        !            74:        if (name != NULL) {
        !            75:                self->node         = axl_node_create (name);
        !            76:                self->finish_on_gc = axl_true;
        !            77:        }
        !            78: 
        !            79:        return (PyObject *)self;
        !            80: }
        !            81: 
        !            82: /** 
        !            83:  * @brief Function used to finish and dealloc memory used by the
        !            84:  * object axl.Node
        !            85:  */
        !            86: static void py_axl_node_dealloc (PyAxlNode* self)
        !            87: {
        !            88: 
        !            89:        /* release node on if it is signaled to be released and it was
        !            90:         * not configured to be inside a document, which means the
        !            91:         * document will take care of this */
        !            92:        if (self->finish_on_gc && axl_node_get_doc (self->node) == NULL)
        !            93:                axl_node_free (self->node);
        !            94:        self->node = NULL;
        !            95: 
        !            96:        /* free the node it self */
        !            97:        self->ob_type->tp_free ((PyObject*)self);
        !            98: 
        !            99:        return;
        !           100: }
        !           101: 
        !           102: /** 
        !           103:  * @brief This function implements the generic attribute getting that
        !           104:  * allows to perform complex member resolution (not merely direct
        !           105:  * member access).
        !           106:  */
        !           107: PyObject * py_axl_node_get_attr (PyObject *o, PyObject *attr_name) {
        !           108:        const char      * attr = NULL;
        !           109:        PyObject        * result;
        !           110:        PyAxlNode       * self = (PyAxlNode *) o; 
        !           111:        PyObject        * tuple;
        !           112:        int               size = 0;
        !           113: 
        !           114:        /* now implement other attributes */
        !           115:        if (! PyArg_Parse (attr_name, "s", &attr))
        !           116:                return NULL;
        !           117: 
        !           118:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "received request to report node attr name %s (self: %p)",
        !           119:                   attr, o);
        !           120: 
        !           121:        if (axl_cmp (attr, "name")) {
        !           122:                /* name */
        !           123:                return Py_BuildValue ("s", axl_node_get_name (self->node));
        !           124:        } else if (axl_cmp (attr, "first_child")) {
        !           125:                /* first_child */
        !           126:                if (axl_node_get_first_child (self->node) == NULL) {
        !           127:                        Py_INCREF (Py_None);
        !           128:                        return Py_None;
        !           129:                } 
        !           130:                        
        !           131:                return Py_BuildValue ("O", py_axl_node_create (axl_node_get_first_child (self->node), axl_false));
        !           132:        } else if (axl_cmp (attr, "next")) {
        !           133:                /* next */
        !           134:                if (axl_node_get_next (self->node) == NULL) {
        !           135:                        Py_INCREF (Py_None);
        !           136:                        return Py_None;
        !           137:                } 
        !           138:                        
        !           139:                return Py_BuildValue ("O", py_axl_node_create (axl_node_get_next (self->node), axl_false));
        !           140:        } else if (axl_cmp (attr, "previous")) {
        !           141:                /* previous */
        !           142:                if (axl_node_get_previous (self->node) == NULL) {
        !           143:                        Py_INCREF (Py_None);
        !           144:                        return Py_None;
        !           145:                } 
        !           146:                        
        !           147:                return Py_BuildValue ("O", py_axl_node_create (axl_node_get_previous (self->node), axl_false));
        !           148:        } else if (axl_cmp (attr, "parent")) {
        !           149:                /* parent */
        !           150:                if (axl_node_get_parent (self->node) == NULL) {
        !           151:                        Py_INCREF (Py_None);
        !           152:                        return Py_None;
        !           153:                } 
        !           154:                        
        !           155:                return Py_BuildValue ("O", py_axl_node_create (axl_node_get_parent (self->node), axl_false));
        !           156: 
        !           157:        } else if (axl_cmp (attr, "content")) {
        !           158:                /* return a tuple with content and size */
        !           159:                tuple = PyTuple_New (2);
        !           160:                
        !           161:                PyTuple_SetItem (tuple, 0, Py_BuildValue ("z", axl_node_get_content (self->node, &size)));
        !           162:                PyTuple_SetItem (tuple, 1, Py_BuildValue ("i", size));
        !           163:                        
        !           164:                return tuple;
        !           165:        } else if (axl_cmp (attr, "doc")) {
        !           166:                
        !           167:                /* check if the node has a document configured */
        !           168:                if (axl_node_get_doc (self->node) == NULL) {
        !           169:                        /* return none */
        !           170:                        Py_INCREF (Py_None);
        !           171:                        return Py_None;
        !           172:                } /* end if */
        !           173: 
        !           174:                /* ok, return document holding the node */
        !           175:                return py_axl_doc_create (axl_node_get_doc (self->node), axl_false);
        !           176:        }
        !           177: 
        !           178:        /* first implement generic attr already defined */
        !           179:        result = PyObject_GenericGetAttr (o, attr_name);
        !           180:        if (result)
        !           181:                return result;
        !           182:        
        !           183:        return NULL;
        !           184: }
        !           185: 
        !           186: /** 
        !           187:  * @brief Implements attribute set operation.
        !           188:  */
        !           189: int py_axl_node_set_attr (PyObject *o, PyObject *attr_name, PyObject *v)
        !           190: {
        !           191:        const char      * attr = NULL;
        !           192: /*     PyAxlNode        * self = (PyAxlNode *) o; */
        !           193: /*     axl_bool          boolean_value = axl_false; */
        !           194: 
        !           195:        /* now implement other attributes */
        !           196:        if (! PyArg_Parse (attr_name, "s", &attr))
        !           197:                return -1;
        !           198: 
        !           199:        /* now implement generic setter */
        !           200:        return PyObject_GenericSetAttr (o, attr_name, v);
        !           201: }
        !           202: 
        !           203: static PyObject * py_axl_node_next_called (PyObject * _self, PyObject * args)
        !           204: {
        !           205:        PyAxlNode  * self      = (PyAxlNode *) _self;
        !           206:        const char * node_name = NULL;
        !           207:        axlNode    * node = NULL;
        !           208: 
        !           209:        /* parse and check result */
        !           210:        if (! PyArg_ParseTuple (args, "s", &node_name))
        !           211:                return NULL;
        !           212:        
        !           213:        /* get next called */
        !           214:        node = axl_node_get_next_called (self->node, node_name);
        !           215:        if (node == NULL) {
        !           216:                Py_INCREF (Py_None);
        !           217:                return Py_None;
        !           218:        } /* end if */
        !           219:        
        !           220:        /* create node result */
        !           221:        return py_axl_node_create (node, axl_false);
        !           222: }
        !           223: 
        !           224: static PyObject * py_axl_node_previous_called (PyObject * _self, PyObject * args)
        !           225: {
        !           226:        PyAxlNode  * self      = (PyAxlNode *) _self;
        !           227:        const char * node_name = NULL;
        !           228:        axlNode    * node = NULL;
        !           229: 
        !           230:        /* parse and check result */
        !           231:        if (! PyArg_ParseTuple (args, "s", &node_name))
        !           232:                return NULL;
        !           233:        
        !           234:        /* get previous called */
        !           235:        node = axl_node_get_previous_called (self->node, node_name);
        !           236:        if (node == NULL) {
        !           237:                Py_INCREF (Py_None);
        !           238:                return Py_None;
        !           239:        } /* end if */
        !           240:        
        !           241:        /* create node result */
        !           242:        return py_axl_node_create (node, axl_false);
        !           243: }
        !           244: 
        !           245: static PyObject * py_axl_node_child_called (PyObject * _self, PyObject * args)
        !           246: {
        !           247:        PyAxlNode  * self      = (PyAxlNode *) _self;
        !           248:        const char * node_name = NULL;
        !           249:        axlNode    * node = NULL;
        !           250: 
        !           251:        /* parse and check result */
        !           252:        if (! PyArg_ParseTuple (args, "s", &node_name))
        !           253:                return NULL;
        !           254:        
        !           255:        /* get previous called */
        !           256:        node = axl_node_get_child_called (self->node, node_name);
        !           257:        if (node == NULL) {
        !           258:                Py_INCREF (Py_None);
        !           259:                return Py_None;
        !           260:        } /* end if */
        !           261:        
        !           262:        /* create node result */
        !           263:        return py_axl_node_create (node, axl_false);
        !           264: }
        !           265: 
        !           266: static PyObject * py_axl_node_find_called (PyObject * _self, PyObject * args)
        !           267: {
        !           268:        PyAxlNode  * self      = (PyAxlNode *) _self;
        !           269:        const char * node_name = NULL;
        !           270:        axlNode    * node = NULL;
        !           271: 
        !           272:        /* parse and check result */
        !           273:        if (! PyArg_ParseTuple (args, "s", &node_name))
        !           274:                return NULL;
        !           275:        
        !           276:        /* get previous called */
        !           277:        node = axl_node_find_called (self->node, node_name);
        !           278:        if (node == NULL) {
        !           279:                Py_INCREF (Py_None);
        !           280:                return Py_None;
        !           281:        } /* end if */
        !           282:        
        !           283:        /* create node result */
        !           284:        return py_axl_node_create (node, axl_false);
        !           285: }
        !           286: 
        !           287: static PyObject * py_axl_node_nth_child (PyObject * _self, PyObject * args)
        !           288: {
        !           289:        PyAxlNode  * self      = (PyAxlNode *) _self;
        !           290:        int          position  = -1;
        !           291:        axlNode    * node = NULL;
        !           292: 
        !           293:        /* parse and check result */
        !           294:        if (! PyArg_ParseTuple (args, "i", &position))
        !           295:                return NULL;
        !           296:        
        !           297:        /* get previous called */
        !           298:        node = axl_node_get_child_nth (self->node, position);
        !           299:        if (node == NULL) {
        !           300:                Py_INCREF (Py_None);
        !           301:                return Py_None;
        !           302:        } /* end if */
        !           303:        
        !           304:        /* create node result */
        !           305:        return py_axl_node_create (node, axl_false);
        !           306: }
        !           307: 
        !           308: static PyObject * py_axl_node_has_attr (PyObject * _self, PyObject * args)
        !           309: {
        !           310:        PyAxlNode  * self      = (PyAxlNode *) _self;
        !           311:        char       * attr_name  = NULL;
        !           312:        char       * attr_value = NULL;
        !           313: 
        !           314:        /* parse and check result */
        !           315:        if (! PyArg_ParseTuple (args, "s|s", &attr_name, &attr_value))
        !           316:                return NULL;
        !           317: 
        !           318:        if (attr_value == NULL)
        !           319:                return Py_BuildValue ("i", HAS_ATTR (self->node, attr_name));
        !           320:        return Py_BuildValue ("i", HAS_ATTR_VALUE (self->node, attr_name, attr_value));
        !           321: }
        !           322: 
        !           323: static PyObject * py_axl_node_attr_value (PyObject * _self, PyObject * args)
        !           324: {
        !           325:        PyAxlNode  * self      = (PyAxlNode *) _self;
        !           326:        char       * attr_name  = NULL;
        !           327:        char       * attr_value = NULL;
        !           328: 
        !           329:        /* parse and check result */
        !           330:        if (! PyArg_ParseTuple (args, "s|s", &attr_name, &attr_value))
        !           331:                return NULL;
        !           332: 
        !           333:        /* check set operation */
        !           334:        if (PyTuple_Size (args) == 2) {
        !           335:                /* remove previous attribute if exists */
        !           336:                axl_node_remove_attribute (self->node, attr_name);
        !           337: 
        !           338:                /* found set operation */
        !           339:                axl_node_set_attribute (self->node, attr_name, attr_value);
        !           340:                Py_INCREF (Py_None);
        !           341:                return Py_None;
        !           342:        } /* end if */
        !           343:        
        !           344:        return Py_BuildValue ("z", ATTR_VALUE (self->node, attr_name));
        !           345: }
        !           346: 
        !           347: static PyObject * py_axl_node_set_child (PyObject * _self, PyObject * args)
        !           348: {
        !           349:        PyAxlNode  * self      = (PyAxlNode *) _self;
        !           350:        PyObject   * child     = Py_None;
        !           351: 
        !           352:        /* parse and check result */
        !           353:        if (! PyArg_ParseTuple (args, "O", &child))
        !           354:                return NULL;
        !           355: 
        !           356:        /* check object received */
        !           357:        if (! py_axl_node_check (child)) {
        !           358:                /* set exception */
        !           359:                PyErr_SetString (PyExc_TypeError, "Expected to receive an axl.Node object but received something different");
        !           360:                return NULL;
        !           361:        }
        !           362: 
        !           363:        /* set the node as child */
        !           364:        axl_node_set_child (self->node, py_axl_node_get (child));
        !           365:        
        !           366:        /* return ok */
        !           367:        Py_INCREF (Py_None);
        !           368:        return Py_None;
        !           369: }
        !           370: 
        !           371: static PyObject * py_axl_node_attr_cursor_new (PyObject * _self, PyObject * args)
        !           372: {
        !           373:        PyAxlNode  * self      = (PyAxlNode *) _self;
        !           374:        
        !           375:        /* create node cursor attr */
        !           376:        return py_axl_attr_cursor_create (axl_node_attr_cursor_new (self->node), axl_true);
        !           377: }
        !           378: 
        !           379: 
        !           380: static PyMethodDef py_axl_node_methods[] = { 
        !           381:        /* next_called */
        !           382:        {"next_called", (PyCFunction) py_axl_node_next_called, METH_VARARGS,
        !           383:         "Gest the xml node found at the same level, but with the name provided."},
        !           384:        /* previous_called */
        !           385:        {"previous_called", (PyCFunction) py_axl_node_previous_called, METH_VARARGS,
        !           386:         "Gest the xml node found at the same level, but with the name provided."},
        !           387:        /* child_called */
        !           388:        {"child_called", (PyCFunction) py_axl_node_child_called, METH_VARARGS,
        !           389:         "Gets the xml child node called as provided. The child is looked up only on direct childs."},
        !           390:        /* find_called */
        !           391:        {"find_called", (PyCFunction) py_axl_node_find_called, METH_VARARGS,
        !           392:         "Gets the xml child node called as provided. The child is looked up in all childs found starting the parent node."},
        !           393:        /* nth_child */
        !           394:        {"nth_child", (PyCFunction) py_axl_node_nth_child, METH_VARARGS,
        !           395:         "Allows to get a reference to the child node located at the same level at the nth position"},
        !           396:        /* has_attr */
        !           397:        {"has_attr", (PyCFunction) py_axl_node_has_attr, METH_VARARGS,
        !           398:         "Allows to check if the provided node has the given attribute."},
        !           399:        /* attr */
        !           400:        {"attr", (PyCFunction) py_axl_node_attr_value, METH_VARARGS,
        !           401:         "Allows to get/set the given attribute on the provided node."},
        !           402:        /* set_child */
        !           403:        {"set_child", (PyCFunction) py_axl_node_set_child, METH_VARARGS,
        !           404:         "Allows to configure the provided node as the instance's child."},
        !           405:        /* attr_cursor_new */
        !           406:        {"attr_cursor_new", (PyCFunction) py_axl_node_attr_cursor_new, METH_NOARGS,
        !           407:         "Allows to create a new attribute cursor object used to iterate over all attributes of a node."},
        !           408:        {NULL}  
        !           409: }; 
        !           410: 
        !           411: static PyTypeObject PyAxlNodeType = {
        !           412:     PyObject_HEAD_INIT(NULL)
        !           413:     0,                         /* ob_size*/
        !           414:     "axl.Node",                 /* tp_name*/
        !           415:     sizeof(PyAxlNode),       /* tp_basicsize*/
        !           416:     0,                         /* tp_itemsize*/
        !           417:     (destructor)py_axl_node_dealloc, /* tp_dealloc*/
        !           418:     0,                         /* tp_print*/
        !           419:     0,                         /* tp_getattr*/
        !           420:     0,                         /* tp_setattr*/
        !           421:     0,                         /* tp_compare*/
        !           422:     0,                         /* tp_repr*/
        !           423:     0,                         /* tp_as_number*/
        !           424:     0,                         /* tp_as_sequence*/
        !           425:     0,                         /* tp_as_mapping*/
        !           426:     0,                         /* tp_hash */
        !           427:     0,                         /* tp_call*/
        !           428:     0,                         /* tp_str*/
        !           429:     py_axl_node_get_attr,    /* tp_getattro*/
        !           430:     py_axl_node_set_attr,    /* tp_setattro*/
        !           431:     0,                         /* tp_as_buffer*/
        !           432:     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,  /* tp_flags*/
        !           433:     "Node object; wrapper of axlNode API type",           /* tp_doc */
        !           434:     0,                        /* tp_traverse */
        !           435:     0,                        /* tp_clear */
        !           436:     0,                        /* tp_richcompare */
        !           437:     0,                        /* tp_weaklistoffset */
        !           438:     0,                        /* tp_iter */
        !           439:     0,                        /* tp_iternext */
        !           440:     py_axl_node_methods,     /* tp_methods */
        !           441:     0, /* py_axl_node_members, */     /* tp_members */
        !           442:     0,                         /* tp_getset */
        !           443:     0,                         /* tp_base */
        !           444:     0,                         /* tp_dict */
        !           445:     0,                         /* tp_descr_get */
        !           446:     0,                         /* tp_descr_set */
        !           447:     0,                         /* tp_dictoffset */
        !           448:     (initproc)py_axl_node_init_type,      /* tp_init */
        !           449:     0,                         /* tp_alloc */
        !           450:     py_axl_node_new,         /* tp_new */
        !           451: 
        !           452: };
        !           453: 
        !           454: 
        !           455: /** 
        !           456:  * @brief Allows to check if the PyObject received represents a
        !           457:  * PyAxlNode reference.
        !           458:  */
        !           459: axl_bool             py_axl_node_check    (PyObject          * obj)
        !           460: {
        !           461:        /* check null references */
        !           462:        if (obj == NULL)
        !           463:                return axl_false;
        !           464: 
        !           465:        /* return check result */
        !           466:        return PyObject_TypeCheck (obj, &PyAxlNodeType);
        !           467: }
        !           468: 
        !           469: /** 
        !           470:  * @brief Allows to create a new PyAxlNode instance using the copy
        !           471:  * provided. 
        !           472:  *
        !           473:  * @param node The xml node that will represents the python instance.
        !           474:  *
        !           475:  * @param finish_on_gc Signal to finish or not the internal copy once
        !           476:  * the variable gets garbage collected.
        !           477:  */
        !           478: PyObject   * py_axl_node_create   (axlNode  * node, 
        !           479:                                   axl_bool   finish_on_gc)
        !           480: {
        !           481:        /* return a new instance */
        !           482:        PyAxlNode * obj = (PyAxlNode *) PyObject_CallObject ((PyObject *) &PyAxlNodeType, NULL); 
        !           483: 
        !           484:        /* check ref created */
        !           485:        if (obj == NULL) {
        !           486:                __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "Failed to create PyAxlNode object, returning NULL");
        !           487:                return NULL;
        !           488:        } /* end if */
        !           489: 
        !           490:        /* set node if defined */
        !           491:        if (node)
        !           492:                obj->node = node;
        !           493:        obj->finish_on_gc = finish_on_gc;
        !           494: 
        !           495:        return __PY_OBJECT (obj);
        !           496: }
        !           497: 
        !           498: /** 
        !           499:  * @internal Allows to get the internal reference used by the provided
        !           500:  * PyAxlNode.
        !           501:  */
        !           502: axlNode    * py_axl_node_get      (PyObject * obj)
        !           503: {
        !           504:        /* check object received */
        !           505:        if (! py_axl_node_check (obj))
        !           506:                return NULL;
        !           507: 
        !           508:        /* return the node */
        !           509:        return ((PyAxlNode *)obj)->node;
        !           510: }
        !           511: 
        !           512: void        init_axl_node      (PyObject * module)
        !           513: {
        !           514:        /* register type */
        !           515:        if (PyType_Ready(&PyAxlNodeType) < 0)
        !           516:                return;
        !           517:        
        !           518:        Py_INCREF (&PyAxlNodeType);
        !           519:        PyModule_AddObject(module, "Node", (PyObject *)&PyAxlNodeType);
        !           520: 
        !           521: }
        !           522: 
        !           523: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>