name_python.cc 24 KB

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