LCOV - code coverage report
Current view: top level - dns/python - name_python.cc (source / functions) Hit Total Coverage
Test: report.info Lines: 191 197 97.0 %
Date: 2012-05-15 Functions: 25 25 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 131 193 67.9 %

           Branch data     Line data    Source code
       1                 :            : // Copyright (C) 2010  Internet Systems Consortium, Inc. ("ISC")
       2                 :            : //
       3                 :            : // Permission to use, copy, modify, and/or distribute this software for any
       4                 :            : // purpose with or without fee is hereby granted, provided that the above
       5                 :            : // copyright notice and this permission notice appear in all copies.
       6                 :            : //
       7                 :            : // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
       8                 :            : // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
       9                 :            : // AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
      10                 :            : // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
      11                 :            : // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
      12                 :            : // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
      13                 :            : // PERFORMANCE OF THIS SOFTWARE.
      14                 :            : 
      15                 :            : #include <Python.h>
      16                 :            : 
      17                 :            : #include <util/buffer.h>
      18                 :            : #include <util/python/pycppwrapper_util.h>
      19                 :            : 
      20                 :            : #include <dns/exceptions.h>
      21                 :            : #include <dns/messagerenderer.h>
      22                 :            : #include <dns/name.h>
      23                 :            : 
      24                 :            : #include "pydnspp_common.h"
      25                 :            : #include "messagerenderer_python.h"
      26                 :            : #include "name_python.h"
      27                 :            : 
      28                 :            : #include <iostream>
      29                 :            : 
      30                 :            : using namespace isc::dns;
      31                 :            : using namespace isc::dns::python;
      32                 :            : using namespace isc::util;
      33                 :            : using namespace isc::util::python;
      34                 :            : 
      35                 :            : namespace {
      36                 :            : // The s_* Class simply covers one instantiation of the object.
      37                 :            : class s_NameComparisonResult : public PyObject {
      38                 :            : public:
      39                 :            :     s_NameComparisonResult() : cppobj(NULL) {}
      40                 :            :     NameComparisonResult* cppobj;
      41                 :            : };
      42                 :            : 
      43                 :            : class s_Name : public PyObject {
      44                 :            : public:
      45                 :            :     s_Name() : cppobj(NULL), position(0) {}
      46                 :            :     Name* cppobj;
      47                 :            :     size_t position;
      48                 :            : };
      49                 :            : 
      50                 :            : int NameComparisonResult_init(s_NameComparisonResult*, PyObject*);
      51                 :            : void NameComparisonResult_destroy(s_NameComparisonResult* self);
      52                 :            : PyObject* NameComparisonResult_getOrder(s_NameComparisonResult* self);
      53                 :            : PyObject* NameComparisonResult_getCommonLabels(s_NameComparisonResult* self);
      54                 :            : PyObject* NameComparisonResult_getRelation(s_NameComparisonResult* self);
      55                 :            : 
      56                 :            : PyMethodDef NameComparisonResult_methods[] = {
      57                 :            :     { "get_order", reinterpret_cast<PyCFunction>(NameComparisonResult_getOrder), METH_NOARGS,
      58                 :            :       "Returns the order" },
      59                 :            :     { "get_common_labels", reinterpret_cast<PyCFunction>(NameComparisonResult_getCommonLabels), METH_NOARGS,
      60                 :            :       "Returns the number of common labels" },
      61                 :            :     { "get_relation", reinterpret_cast<PyCFunction>(NameComparisonResult_getRelation), METH_NOARGS,
      62                 :            :       "Returns the relation" },
      63                 :            :     { NULL, NULL, 0, NULL }
      64                 :            : };
      65                 :            : 
      66                 :            : int
      67                 :          1 : NameComparisonResult_init(s_NameComparisonResult*, PyObject*) {
      68                 :            :     PyErr_SetString(PyExc_NotImplementedError,
      69                 :          1 :                     "NameComparisonResult can't be built directly");
      70                 :          1 :     return (-1);
      71                 :            : }
      72                 :            : 
      73                 :            : void
      74                 :         36 : NameComparisonResult_destroy(s_NameComparisonResult* self) {
      75                 :         36 :     delete self->cppobj;
      76                 :         36 :     self->cppobj = NULL;
      77                 :         36 :     Py_TYPE(self)->tp_free(self);
      78                 :         36 : }
      79                 :            : 
      80                 :            : PyObject*
      81                 :          7 : NameComparisonResult_getOrder(s_NameComparisonResult* self) {
      82                 :          7 :     return (Py_BuildValue("i", self->cppobj->getOrder()));
      83                 :            : }
      84                 :            : 
      85                 :            : PyObject*
      86                 :          2 : NameComparisonResult_getCommonLabels(s_NameComparisonResult* self) {
      87                 :          2 :     return (Py_BuildValue("I", self->cppobj->getCommonLabels()));
      88                 :            : }
      89                 :            : 
      90                 :            : PyObject*
      91                 :          5 : NameComparisonResult_getRelation(s_NameComparisonResult* self) {
      92                 :          5 :     return (Py_BuildValue("I", self->cppobj->getRelation()));
      93                 :            : }
      94                 :            : 
      95                 :            : // Shortcut type which would be convenient for adding class variables safely.
      96                 :            : typedef CPPPyObjectContainer<s_Name, Name> NameContainer;
      97                 :            : 
      98                 :            : int Name_init(s_Name* self, PyObject* args);
      99                 :            : void Name_destroy(s_Name* self);
     100                 :            : 
     101                 :            : PyObject* Name_toWire(s_Name* self, PyObject* args);
     102                 :            : PyObject* Name_toText(s_Name* self, PyObject* args);
     103                 :            : PyObject* Name_str(PyObject* self);
     104                 :            : PyObject* Name_getLabelCount(s_Name* self);
     105                 :            : PyObject* Name_at(s_Name* self, PyObject* args);
     106                 :            : PyObject* Name_getLength(s_Name* self);
     107                 :            : 
     108                 :            : PyObject* Name_compare(s_Name* self, PyObject* args);
     109                 :            : PyObject* Name_equals(s_Name* self, PyObject* args);
     110                 :            : 
     111                 :            : PyObject* Name_richcmp(s_Name* self, s_Name* other, int op);
     112                 :            : PyObject* Name_split(s_Name* self, PyObject* args);
     113                 :            : PyObject* Name_reverse(s_Name* self);
     114                 :            : PyObject* Name_concatenate(s_Name* self, PyObject* args);
     115                 :            : PyObject* Name_downcase(s_Name* self);
     116                 :            : PyObject* Name_isWildCard(s_Name* self);
     117                 :            : 
     118                 :            : PyMethodDef Name_methods[] = {
     119                 :            :     { "at", reinterpret_cast<PyCFunction>(Name_at), METH_VARARGS,
     120                 :            :       "Returns the integer value of the name data at the specified position" },
     121                 :            :     { "get_length", reinterpret_cast<PyCFunction>(Name_getLength), METH_NOARGS,
     122                 :            :       "Returns the length" },
     123                 :            :     { "get_labelcount", reinterpret_cast<PyCFunction>(Name_getLabelCount), METH_NOARGS,
     124                 :            :       "Returns the number of labels" },
     125                 :            :     { "to_text", reinterpret_cast<PyCFunction>(Name_toText), METH_VARARGS,
     126                 :            :       "Returns the string representation. The optional argument must be either"
     127                 :            :       "True of False. If True, the final dot will be omitted." },
     128                 :            :     { "to_wire", reinterpret_cast<PyCFunction>(Name_toWire), METH_VARARGS,
     129                 :            :       "Converts the Name object to wire format.\n"
     130                 :            :       "The argument can be either a MessageRenderer or an object that "
     131                 :            :       "implements the sequence interface. If the object is mutable "
     132                 :            :       "(for instance a bytearray()), the wire data is added in-place.\n"
     133                 :            :       "If it is not (for instance a bytes() object), a new object is "
     134                 :            :       "returned" },
     135                 :            :     { "compare", reinterpret_cast<PyCFunction>(Name_compare), METH_VARARGS,
     136                 :            :       "Returns a NameComparisonResult object. The argument must be another Name object" },
     137                 :            :     { "equals", reinterpret_cast<PyCFunction>(Name_equals), METH_VARARGS,
     138                 :            :       "Returns true if the given Name object is equal to this one" },
     139                 :            :     { "split", reinterpret_cast<PyCFunction>(Name_split), METH_VARARGS,
     140                 :            :       "Splits the name, takes two arguments, the first is an integer "
     141                 :            :       "specifying the first label to place in the result. The second "
     142                 :            :       "is an integer specifying the number of labels to put in the "
     143                 :            :       "result. Returns a new Name object" },
     144                 :            :     { "reverse", reinterpret_cast<PyCFunction>(Name_reverse), METH_NOARGS,
     145                 :            :       "Returns a new Name object that is the reverse of this one" },
     146                 :            :     { "concatenate", reinterpret_cast<PyCFunction>(Name_concatenate), METH_VARARGS,
     147                 :            :       "Concatenates the given Name object to this one and returns the "
     148                 :            :       "result as a new Name object" },
     149                 :            :     { "downcase", reinterpret_cast<PyCFunction>(Name_downcase), METH_NOARGS,
     150                 :            :       "Downcases this name object (in-place). Returns a new reference to the Name." },
     151                 :            :     { "is_wildcard", reinterpret_cast<PyCFunction>(Name_isWildCard), METH_NOARGS,
     152                 :            :       "Returns True if the Name object represents a wildcard name." },
     153                 :            :     { NULL, NULL, 0, NULL }
     154                 :            : };
     155                 :            : 
     156                 :            : int
     157                 :       1684 : Name_init(s_Name* self, PyObject* args) {
     158                 :            :     const char* s;
     159                 :       1684 :     PyObject* downcase = Py_False;
     160                 :            : 
     161                 :            :     // Depending on the arguments in *args, we decide which of the
     162                 :            :     // constructors is meant. If the first argument is of type string,
     163                 :            :     // we use the string-based constructor. If it is a bytes object,
     164                 :            :     // we use the wire-based one.
     165         [ +  + ]:       1684 :     if (PyArg_ParseTuple(args, "s|O!", &s, &PyBool_Type, &downcase)) {
     166                 :            :         try {
     167         [ +  - ]:       3356 :             const std::string n(s);
     168                 :            : 
     169 [ +  - ][ +  + ]:       1678 :             self->cppobj = new Name(n, downcase == Py_True);
     170                 :       1666 :             self->position = 0;
     171                 :         10 :         } catch (const EmptyLabel&) {
     172         [ -  + ]:          5 :             PyErr_SetString(po_EmptyLabel, "EmptyLabel");
     173                 :            :             return (-1);
     174                 :          2 :         } catch (const TooLongLabel&) {
     175         [ -  + ]:          1 :             PyErr_SetString(po_TooLongLabel, "TooLongLabel");
     176                 :            :             return (-1);
     177                 :          2 :         } catch (const BadLabelType&) {
     178         [ -  + ]:          1 :             PyErr_SetString(po_BadLabelType, "BadLabelType");
     179                 :            :             return (-1);
     180                 :          2 :         } catch (const BadEscape&) {
     181         [ -  + ]:          1 :             PyErr_SetString(po_BadEscape, "BadEscape");
     182                 :            :             return (-1);
     183                 :          2 :         } catch (const TooLongName&) {
     184         [ -  + ]:          1 :             PyErr_SetString(po_TooLongName, "TooLongName");
     185                 :            :             return (-1);
     186                 :          6 :         } catch (const IncompleteName&) {
     187         [ -  + ]:          3 :             PyErr_SetString(po_IncompleteName, "IncompleteName");
     188                 :            :             return (-1);
     189                 :            : #ifdef CATCHMEMERR
     190                 :            :         } catch (const std::bad_alloc&) {
     191                 :            :             PyErr_NoMemory();
     192                 :            :             return (-1);
     193                 :            : #endif
     194   [ +  +  +  +  :         12 :         } catch (...) {
                +  +  - ]
     195         [ #  # ]:          0 :             PyErr_SetString(po_IscException, "Unexpected?!");
     196                 :            :             return (-1);
     197                 :            :         }
     198                 :       1666 :         return (0);
     199                 :            :     }
     200                 :          6 :     PyErr_Clear();
     201                 :            : 
     202                 :            :     PyObject* bytes_obj;
     203                 :            :     const char* bytes;
     204                 :            :     Py_ssize_t len;
     205                 :          6 :     long position = 0;
     206                 :            : 
     207                 :            :     // It was not a string (see comment above), so try bytes, and
     208                 :            :     // create with buffer object
     209   [ +  -  +  + ]:         12 :     if (PyArg_ParseTuple(args, "O|lO!", &bytes_obj, &position,
                 [ +  + ]
     210                 :          6 :                          &PyBool_Type, &downcase) &&
     211                 :          6 :                          PyObject_AsCharBuffer(bytes_obj, &bytes, &len) != -1) {
     212                 :            :         try {
     213         [ +  + ]:          5 :             if (position < 0) {
     214                 :            :                 // Throw IndexError here since name index should be unsigned
     215                 :            :                 PyErr_SetString(PyExc_IndexError,
     216         [ +  - ]:          1 :                                 "Name index shouldn't be negative");
     217                 :            :                 return (-1);
     218                 :            :             }
     219                 :          4 :             InputBuffer buffer(bytes, len);
     220                 :            : 
     221                 :          4 :             buffer.setPosition(position);
     222 [ +  - ][ +  + ]:          3 :             self->cppobj = new Name(buffer, downcase == Py_True);
     223                 :          2 :             self->position = buffer.getPosition();
     224                 :          2 :         } catch (const InvalidBufferPosition&) {
     225                 :            :             PyErr_SetString(po_InvalidBufferPosition,
     226         [ -  + ]:          1 :                             "InvalidBufferPosition");
     227                 :            :             return (-1);
     228                 :          2 :         } catch (const DNSMessageFORMERR&) {
     229         [ -  + ]:          1 :             PyErr_SetString(po_DNSMessageFORMERR, "DNSMessageFORMERR");
     230                 :            :             return (-1);
     231      [ +  +  - ]:          2 :         } catch (...) {
     232         [ #  # ]:          0 :             PyErr_SetString(po_IscException, "Unexpected?!");
     233                 :            :             return (-1);
     234                 :            :         }
     235                 :          2 :         return (0);
     236                 :            :     }
     237                 :            : 
     238                 :          1 :     PyErr_Clear();
     239                 :            :     PyErr_SetString(PyExc_TypeError,
     240                 :          1 :                     "No valid types in Name constructor (should be string or sequence and offset");
     241                 :       1684 :     return (-1);
     242                 :            : }
     243                 :            : 
     244                 :            : void
     245                 :       2909 : Name_destroy(s_Name* self) {
     246         [ +  + ]:       5797 :     delete self->cppobj;
     247                 :       2909 :     self->cppobj = NULL;
     248                 :       2909 :     Py_TYPE(self)->tp_free(self);
     249                 :       2909 : }
     250                 :            : 
     251                 :            : PyObject*
     252                 :          6 : Name_at(s_Name* self, PyObject* args) {
     253                 :            :     int pos;
     254         [ +  + ]:          6 :     if (!PyArg_ParseTuple(args, "i", &pos)) {
     255                 :            :         return (NULL);
     256                 :            :     }
     257         [ +  + ]:          5 :     if (pos < 0) {
     258                 :            :         // Throw IndexError here since name index should be unsigned
     259                 :            :         PyErr_SetString(PyExc_IndexError,
     260                 :          1 :                         "name index shouldn't be negative");
     261                 :          1 :         return (NULL);
     262                 :            :     }
     263                 :            : 
     264                 :            :     try {
     265 [ +  + ][ +  - ]:          8 :         return (Py_BuildValue("I", self->cppobj->at(pos)));
     266         [ -  + ]:          4 :     } catch (const isc::OutOfRange&) {
     267                 :            :         PyErr_SetString(PyExc_IndexError,
     268         [ -  + ]:          2 :                         "name index out of range");
     269                 :            :         return (NULL);
     270                 :            :     }
     271                 :            : }
     272                 :            : 
     273                 :            : PyObject*
     274                 :         19 : Name_getLength(s_Name* self) {
     275                 :         19 :     return (Py_BuildValue("i", self->cppobj->getLength()));
     276                 :            : }
     277                 :            : 
     278                 :            : PyObject*
     279                 :          3 : Name_getLabelCount(s_Name* self) {
     280                 :          3 :     return (Py_BuildValue("i", self->cppobj->getLabelCount()));
     281                 :            : }
     282                 :            : 
     283                 :            : PyObject*
     284                 :        494 : Name_toText(s_Name* self, PyObject* args) {
     285                 :        494 :     PyObject* omit_final_dot_obj = NULL;
     286         [ +  + ]:        494 :     if (PyArg_ParseTuple(args, "|O", &omit_final_dot_obj)) {
     287                 :        493 :         bool omit_final_dot = false;
     288         [ +  + ]:        493 :         if (omit_final_dot_obj != NULL) {
     289 [ +  + ][ +  + ]:        164 :             if (PyBool_Check(omit_final_dot_obj) != 0) {
     290                 :        161 :                 omit_final_dot = (omit_final_dot_obj == Py_True);
     291                 :            :             } else {
     292                 :            :                 PyErr_SetString(PyExc_TypeError,
     293                 :          3 :                     "Optional argument 1 of to_text() should be True of False");
     294                 :          3 :                 return (NULL);
     295                 :            :             }
     296                 :            :         }
     297                 :            :         return (Py_BuildValue("s",
     298         [ +  - ]:        494 :                               self->cppobj->toText(omit_final_dot).c_str()));
     299                 :            :     } else {
     300                 :            :         return (NULL);
     301                 :            :     }
     302                 :            : }
     303                 :            : 
     304                 :            : PyObject*
     305                 :         10 : Name_str(PyObject* self) {
     306                 :            :     // Simply call the to_text method we already defined
     307                 :            :     // str() is not defined in the c++ version, only to_text
     308                 :            :     // and we already have a wrapper for that one.
     309                 :            :     return (PyObject_CallMethod(self,
     310                 :            :                                const_cast<char*>("to_text"),
     311                 :         10 :                                 const_cast<char*>("")));
     312                 :            : }
     313                 :            : 
     314                 :            : PyObject*
     315                 :          6 : Name_toWire(s_Name* self, PyObject* args) {
     316                 :            :     PyObject* bytes;
     317                 :            :     PyObject* mr;
     318                 :            : 
     319 [ +  - ][ +  + ]:          6 :     if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) {
                 [ +  + ]
     320                 :          4 :         PyObject* bytes_o = bytes;
     321                 :            : 
     322                 :          4 :         OutputBuffer buffer(Name::MAX_WIRE);
     323         [ +  - ]:          4 :         self->cppobj->toWire(buffer);
     324         [ +  - ]:          4 :         PyObject* name_bytes = PyBytes_FromStringAndSize(static_cast<const char*>(buffer.getData()), buffer.getLength());
     325         [ +  - ]:          4 :         PyObject* result = PySequence_InPlaceConcat(bytes_o, name_bytes);
     326                 :            :         // We need to release the object we temporarily created here
     327                 :            :         // to prevent memory leak
     328 [ +  + ][ +  - ]:          4 :         Py_DECREF(name_bytes);
     329                 :            :         return (result);
     330         [ +  + ]:          2 :     } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, &mr)) {
     331                 :          1 :         self->cppobj->toWire(PyMessageRenderer_ToMessageRenderer(mr));
     332                 :            :         // If we return NULL it is seen as an error, so use this for
     333                 :            :         // None returns
     334                 :          1 :         Py_RETURN_NONE;
     335                 :            :     }
     336                 :          1 :     PyErr_Clear();
     337                 :            :     PyErr_SetString(PyExc_TypeError,
     338                 :          1 :                     "toWire argument must be a sequence object or a MessageRenderer");
     339                 :          6 :     return (NULL);
     340                 :            : }
     341                 :            : 
     342                 :            : PyObject*
     343                 :         35 : Name_compare(s_Name* self, PyObject* args) {
     344                 :            :     s_Name* other;
     345                 :            : 
     346         [ +  - ]:         35 :     if (!PyArg_ParseTuple(args, "O!", &name_type, &other))
     347                 :            :         return (NULL);
     348                 :            : 
     349                 :         35 :     s_NameComparisonResult* ret = PyObject_New(s_NameComparisonResult, &name_comparison_result_type);
     350         [ +  - ]:         35 :     if (ret != NULL) {
     351                 :            :         ret->cppobj = new NameComparisonResult(
     352         [ +  - ]:         35 :             self->cppobj->compare(*other->cppobj));
     353                 :            :     }
     354                 :            :     return (ret);
     355                 :            : }
     356                 :            : 
     357                 :            : PyObject*
     358                 :          3 : Name_equals(s_Name* self, PyObject* args) {
     359                 :            :     s_Name* other;
     360                 :            : 
     361         [ +  - ]:          3 :     if (!PyArg_ParseTuple(args, "O!", &name_type, &other))
     362                 :            :         return (NULL);
     363                 :            : 
     364         [ +  + ]:          3 :     if (self->cppobj->equals(*other->cppobj))
     365                 :          1 :         Py_RETURN_TRUE;
     366                 :            :     else
     367                 :          3 :         Py_RETURN_FALSE;
     368                 :            : }
     369                 :            : 
     370                 :            : PyObject*
     371                 :         17 : Name_split(s_Name* self, PyObject* args) {
     372                 :            :     int first, n;
     373                 :         17 :     s_Name* ret = NULL;
     374                 :            : 
     375         [ +  + ]:         17 :     if (PyArg_ParseTuple(args, "ii", &first, &n)) {
     376 [ +  + ][ +  + ]:          9 :         if (first < 0 || n < 0) {
     377                 :            :             // Throw IndexError here since name index should be unsigned
     378                 :            :             PyErr_SetString(PyExc_IndexError,
     379                 :          3 :                             "name index shouldn't be negative");
     380                 :          3 :             return (NULL);
     381                 :            :         }
     382                 :          6 :         ret = PyObject_New(s_Name, &name_type);
     383         [ +  - ]:          6 :         if (ret != NULL) {
     384                 :          6 :             ret->cppobj = NULL;
     385                 :            :             try {
     386 [ +  - ][ +  + ]:          6 :                 ret->cppobj = new Name(self->cppobj->split(first, n));
     387         [ -  + ]:          6 :             } catch(const isc::OutOfRange& oor) {
     388         [ -  + ]:          3 :                 PyErr_SetString(PyExc_IndexError, oor.what());
     389                 :          3 :                 ret->cppobj = NULL;
     390                 :            :             }
     391         [ +  + ]:          6 :             if (ret->cppobj == NULL) {
     392         [ +  - ]:          3 :                 Py_DECREF(ret);
     393                 :            :                 return (NULL);
     394                 :            :             }
     395                 :            :         }
     396         [ +  + ]:          8 :     } else if (PyArg_ParseTuple(args, "i", &n)) {
     397                 :          5 :         PyErr_Clear();
     398         [ +  + ]:          5 :         if (n < 0) {
     399                 :            :             // Throw IndexError here since name index should be unsigned
     400                 :            :             PyErr_SetString(PyExc_IndexError,
     401                 :          1 :                             "name index shouldn't be negative");
     402                 :          1 :             return (NULL);
     403                 :            :         }
     404                 :          4 :         ret = PyObject_New(s_Name, &name_type);
     405         [ +  - ]:          4 :         if (ret != NULL) {
     406                 :          4 :             ret->cppobj = NULL;
     407                 :            :             try {
     408 [ +  - ][ +  + ]:          4 :                 ret->cppobj = new Name(self->cppobj->split(n));
     409         [ -  + ]:          4 :             } catch(const isc::OutOfRange& oor) {
     410         [ -  + ]:          2 :                 PyErr_SetString(PyExc_IndexError, oor.what());
     411                 :          2 :                 ret->cppobj = NULL;
     412                 :            :             }
     413         [ +  + ]:          4 :             if (ret->cppobj == NULL) {
     414         [ +  - ]:          2 :                 Py_DECREF(ret);
     415                 :            :                 return (NULL);
     416                 :            :             }
     417                 :            :         }
     418                 :            :     }
     419                 :            : 
     420                 :          8 :     PyErr_Clear();
     421                 :            :     PyErr_SetString(PyExc_TypeError,
     422                 :          8 :                     "No valid type in split argument");
     423                 :         17 :     return (ret);
     424                 :            : }
     425                 :            : 
     426                 :            : //
     427                 :            : // richcmp defines the ==, !=, >, <, >= and <= operators in python
     428                 :            : // It is translated to a function that gets 3 arguments, an object,
     429                 :            : // an object to compare to, and an operator.
     430                 :            : //
     431                 :            : PyObject*
     432                 :       1104 : Name_richcmp(s_Name* self, s_Name* other, int op) {
     433                 :            :     bool c;
     434                 :            : 
     435                 :            :     // Check for null and if the types match. If different type,
     436                 :            :     // simply return False
     437 [ +  - ][ +  + ]:       1104 :     if (!other || (self->ob_type != other->ob_type)) {
     438                 :          1 :         Py_RETURN_FALSE;
     439                 :            :     }
     440                 :            : 
     441   [ +  +  +  +  :       1103 :     switch (op) {
                +  +  - ]
     442                 :            :     case Py_LT:
     443                 :          2 :         c = *self->cppobj < *other->cppobj;
     444                 :          2 :         break;
     445                 :            :     case Py_LE:
     446                 :          3 :         c = *self->cppobj <= *other->cppobj;
     447                 :          3 :         break;
     448                 :            :     case Py_EQ:
     449                 :        904 :         c = *self->cppobj == *other->cppobj;
     450                 :        904 :         break;
     451                 :            :     case Py_NE:
     452                 :        378 :         c = *self->cppobj != *other->cppobj;
     453                 :        189 :         break;
     454                 :            :     case Py_GT:
     455                 :          2 :         c = *self->cppobj > *other->cppobj;
     456                 :          2 :         break;
     457                 :            :     case Py_GE:
     458                 :          3 :         c = *self->cppobj >= *other->cppobj;
     459                 :          3 :         break;
     460                 :            :     default:
     461                 :            :         PyErr_SetString(PyExc_IndexError,
     462                 :          0 :                         "Unhandled rich comparison operator");
     463                 :          0 :         return (NULL);
     464                 :            :     }
     465         [ +  + ]:       1103 :     if (c) {
     466                 :        717 :         Py_RETURN_TRUE;
     467                 :            :     } else {
     468                 :       1104 :         Py_RETURN_FALSE;
     469                 :            :     }
     470                 :            : }
     471                 :            : 
     472                 :            : PyObject*
     473                 :          2 : Name_reverse(s_Name* self) {
     474                 :          2 :     s_Name* ret = PyObject_New(s_Name, &name_type);
     475                 :            : 
     476         [ +  - ]:          2 :     if (ret != NULL) {
     477         [ +  - ]:          2 :         ret->cppobj = new Name(self->cppobj->reverse());
     478         [ -  + ]:          2 :         if (ret->cppobj == NULL) {
     479         [ #  # ]:          2 :             Py_DECREF(ret);
     480                 :            :             return (NULL);
     481                 :            :         }
     482                 :            :     }
     483                 :            :     return (ret);
     484                 :            : }
     485                 :            : 
     486                 :            : PyObject*
     487                 :          4 : Name_concatenate(s_Name* self, PyObject* args) {
     488                 :            :     s_Name* other;
     489                 :            : 
     490         [ +  + ]:          4 :     if (!PyArg_ParseTuple(args, "O!", &name_type, &other))
     491                 :            :         return (NULL);
     492                 :            : 
     493                 :          3 :     s_Name* ret = PyObject_New(s_Name, &name_type);
     494         [ +  - ]:          3 :     if (ret != NULL) {
     495                 :            :         try {
     496 [ +  - ][ +  + ]:          5 :             ret->cppobj = new Name(self->cppobj->concatenate(*other->cppobj));
     497         [ -  + ]:          2 :         } catch (const TooLongName& tln) {
     498         [ -  + ]:          1 :             PyErr_SetString(po_TooLongName, tln.what());
     499                 :            :             return (NULL);
     500                 :            :         }
     501                 :            :     }
     502                 :            :     return (ret);
     503                 :            : }
     504                 :            : 
     505                 :            : PyObject*
     506                 :          1 : Name_downcase(s_Name* self) {
     507                 :          1 :     self->cppobj->downcase();
     508                 :          1 :     Py_INCREF(self);
     509                 :          1 :     return (self);
     510                 :            : }
     511                 :            : 
     512                 :            : PyObject*
     513                 :          2 : Name_isWildCard(s_Name* self) {
     514         [ +  + ]:          2 :     if (self->cppobj->isWildcard()) {
     515                 :          1 :         Py_RETURN_TRUE;
     516                 :            :     } else {
     517                 :          2 :         Py_RETURN_FALSE;
     518                 :            :     }
     519                 :            : }
     520                 :            : 
     521                 :            : } // end of unnamed namespace
     522                 :            : 
     523                 :            : namespace isc {
     524                 :            : namespace dns {
     525                 :            : namespace python {
     526                 :            : 
     527                 :            : //
     528                 :            : // Definition of the custom exceptions
     529                 :            : // Initialization and addition of these go in the module init at the
     530                 :            : // end
     531                 :            : //
     532                 :            : PyObject* po_EmptyLabel;
     533                 :            : PyObject* po_TooLongName;
     534                 :            : PyObject* po_TooLongLabel;
     535                 :            : PyObject* po_BadLabelType;
     536                 :            : PyObject* po_BadEscape;
     537                 :            : PyObject* po_IncompleteName;
     538                 :            : PyObject* po_InvalidBufferPosition;
     539                 :            : PyObject* po_DNSMessageFORMERR;
     540                 :            : 
     541                 :            : //
     542                 :            : // Definition of enums
     543                 :            : // Initialization and addition of these go in the module init at the
     544                 :            : // end
     545                 :            : //
     546                 :            : PyObject* po_NameRelation;
     547                 :            : 
     548                 :            : PyTypeObject name_comparison_result_type = {
     549                 :            :     PyVarObject_HEAD_INIT(NULL, 0)
     550                 :            :     "pydnspp.NameComparisonResult",
     551                 :            :     sizeof(s_NameComparisonResult),           // tp_basicsize
     552                 :            :     0,                                        // tp_itemsize
     553                 :            :     (destructor)NameComparisonResult_destroy, // tp_dealloc
     554                 :            :     NULL,                                     // tp_print
     555                 :            :     NULL,                                     // tp_getattr
     556                 :            :     NULL,                                     // tp_setattr
     557                 :            :     NULL,                                     // tp_reserved
     558                 :            :     NULL,                                     // tp_repr
     559                 :            :     NULL,                                     // tp_as_number
     560                 :            :     NULL,                                     // tp_as_sequence
     561                 :            :     NULL,                                     // tp_as_mapping
     562                 :            :     NULL,                                     // tp_hash
     563                 :            :     NULL,                                     // tp_call
     564                 :            :     NULL,                                     // tp_str
     565                 :            :     NULL,                                     // tp_getattro
     566                 :            :     NULL,                                     // tp_setattro
     567                 :            :     NULL,                                     // tp_as_buffer
     568                 :            :     Py_TPFLAGS_DEFAULT,                       // tp_flags
     569                 :            :     "This is a supplemental class used only as a return value of Name.compare(). "
     570                 :            :     "It encapsulate a tuple of the comparison: ordering, number of common labels, "
     571                 :            :     "and relationship as follows:\n"
     572                 :            :     "- ordering: relative ordering under the DNSSEC order relation\n"
     573                 :            :     "- labels: the number of common significant labels of the two names being"
     574                 :            :     "  compared\n"
     575                 :            :     "- relationship: see NameComparisonResult.NameRelation\n",
     576                 :            :     NULL,                                     // tp_traverse
     577                 :            :     NULL,                                     // tp_clear
     578                 :            :     NULL,                                     // tp_richcompare
     579                 :            :     0,                                        // tp_weaklistoffset
     580                 :            :     NULL,                                     // tp_iter
     581                 :            :     NULL,                                     // tp_iternext
     582                 :            :     NameComparisonResult_methods,             // tp_methods
     583                 :            :     NULL,                                     // tp_members
     584                 :            :     NULL,                                     // tp_getset
     585                 :            :     NULL,                                     // tp_base
     586                 :            :     NULL,                                     // tp_dict
     587                 :            :     NULL,                                     // tp_descr_get
     588                 :            :     NULL,                                     // tp_descr_set
     589                 :            :     0,                                        // tp_dictoffset
     590                 :            :     (initproc)NameComparisonResult_init,      // tp_init
     591                 :            :     NULL,                                     // tp_alloc
     592                 :            :     PyType_GenericNew,                        // tp_new
     593                 :            :     NULL,                                     // tp_free
     594                 :            :     NULL,                                     // tp_is_gc
     595                 :            :     NULL,                                     // tp_bases
     596                 :            :     NULL,                                     // tp_mro
     597                 :            :     NULL,                                     // tp_cache
     598                 :            :     NULL,                                     // tp_subclasses
     599                 :            :     NULL,                                     // tp_weaklist
     600                 :            :     NULL,                                     // tp_del
     601                 :            :     0                                         // tp_version_tag
     602                 :            : };
     603                 :            : 
     604                 :            : PyTypeObject name_type = {
     605                 :            :     PyVarObject_HEAD_INIT(NULL, 0)
     606                 :            :     "pydnspp.Name",
     607                 :            :     sizeof(s_Name),                     // tp_basicsize
     608                 :            :     0,                                  // tp_itemsize
     609                 :            :     (destructor)Name_destroy,           // tp_dealloc
     610                 :            :     NULL,                               // tp_print
     611                 :            :     NULL,                               // tp_getattr
     612                 :            :     NULL,                               // tp_setattr
     613                 :            :     NULL,                               // tp_reserved
     614                 :            :     NULL,                               // tp_repr
     615                 :            :     NULL,                               // tp_as_number
     616                 :            :     NULL,                               // tp_as_sequence
     617                 :            :     NULL,                               // tp_as_mapping
     618                 :            :     NULL,                               // tp_hash
     619                 :            :     NULL,                               // tp_call
     620                 :            :     Name_str,                           // tp_str
     621                 :            :     NULL,                               // tp_getattro
     622                 :            :     NULL,                               // tp_setattro
     623                 :            :     NULL,                               // tp_as_buffer
     624                 :            :     Py_TPFLAGS_DEFAULT,                 // tp_flags
     625                 :            :     "The Name class encapsulates DNS names.\n"
     626                 :            :     "It provides interfaces to construct a name from string or wire-format data, "
     627                 :            :     "transform a name into a string or wire-format data, compare two names, get "
     628                 :            :     "access to various properties of a name, etc.",
     629                 :            :     NULL,                               // tp_traverse
     630                 :            :     NULL,                               // tp_clear
     631                 :            :     (richcmpfunc)Name_richcmp,          // tp_richcompare
     632                 :            :     0,                                  // tp_weaklistoffset
     633                 :            :     NULL,                               // tp_iter
     634                 :            :     NULL,                               // tp_iternext
     635                 :            :     Name_methods,                       // tp_methods
     636                 :            :     NULL,                               // tp_members
     637                 :            :     NULL,                               // tp_getset
     638                 :            :     NULL,                               // tp_base
     639                 :            :     NULL,                               // tp_dict
     640                 :            :     NULL,                               // tp_descr_get
     641                 :            :     NULL,                               // tp_descr_set
     642                 :            :     0,                                  // tp_dictoffset
     643                 :            :     (initproc)Name_init,                // tp_init
     644                 :            :     NULL,                               // tp_alloc
     645                 :            :     PyType_GenericNew,                  // tp_new
     646                 :            :     NULL,                               // tp_free
     647                 :            :     NULL,                               // tp_is_gc
     648                 :            :     NULL,                               // tp_bases
     649                 :            :     NULL,                               // tp_mro
     650                 :            :     NULL,                               // tp_cache
     651                 :            :     NULL,                               // tp_subclasses
     652                 :            :     NULL,                               // tp_weaklist
     653                 :            :     // Note: not sure if the following are correct.  Added them just to
     654                 :            :     // make the compiler happy.
     655                 :            :     NULL,                               // tp_del
     656                 :            :     0                                   // tp_version_tag
     657                 :            : };
     658                 :            : 
     659                 :            : PyObject*
     660                 :       1414 : createNameObject(const Name& source) {
     661                 :       1414 :     NameContainer container(PyObject_New(s_Name, &name_type));
     662 [ +  - ][ +  - ]:       2828 :     container.set(new Name(source));
     663                 :       1414 :     return (container.release());
     664                 :            : }
     665                 :            : 
     666                 :            : bool
     667                 :          9 : PyName_Check(PyObject* obj) {
     668         [ -  + ]:          9 :     if (obj == NULL) {
     669         [ #  # ]:          0 :         isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck");
     670                 :            :     }
     671 [ +  + ][ +  - ]:          9 :     return (PyObject_TypeCheck(obj, &name_type));
     672                 :            : }
     673                 :            : 
     674                 :            : const Name&
     675                 :       2161 : PyName_ToName(const PyObject* name_obj) {
     676         [ -  + ]:       2161 :     if (name_obj == NULL) {
     677         [ #  # ]:          0 :         isc_throw(PyCPPWrapperException,
     678                 :            :                   "obj argument NULL in Name PyObject conversion");
     679                 :            :     }
     680                 :       2161 :     const s_Name* name = static_cast<const s_Name*>(name_obj);
     681                 :       2161 :     return (*name->cppobj);
     682                 :            : }
     683                 :            : 
     684                 :            : 
     685                 :            : } // namespace python
     686                 :            : } // namespace dns
     687                 :        123 : } // namespace isc

Generated by: LCOV version 1.9