py_namespace.h 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. #ifndef _PY_NAMESPACE_OBJ_H
  2. #define _PY_NAMESPACE_OBJ_H
  3. #define PY_SSIZE_T_CLEAN
  4. #include <Python.h>
  5. #include <structmember.h>
  6. #include "namespace.h"
  7. typedef struct {
  8. PyObject_HEAD
  9. LSUP_NSMap *ob_struct;
  10. } NSMapObject;
  11. static int
  12. NSMap_init (NSMapObject *self, PyObject *args)
  13. {
  14. self->ob_struct = LSUP_nsmap_new();
  15. if (!self->ob_struct) {
  16. PyErr_SetString (PyExc_SystemError, "Could not create namespace.");
  17. return -1;
  18. }
  19. return 0;
  20. }
  21. static void
  22. NSMap_dealloc (NSMapObject *self)
  23. {
  24. LSUP_nsmap_free (self->ob_struct);
  25. Py_TYPE (self)->tp_free ((PyObject *) self);
  26. }
  27. static PyObject *
  28. NSMap_add (PyObject *self, PyObject *args)
  29. {
  30. const char *pfx, *ns;
  31. if (! PyArg_ParseTuple (args, "ss", &pfx, &ns)) return NULL;
  32. if (LSUP_nsmap_add (((NSMapObject *)self)->ob_struct, pfx, ns) < 0) {
  33. PyErr_SetString (PyExc_ValueError, "Error adding namespace.");
  34. return NULL;
  35. }
  36. Py_RETURN_NONE;
  37. }
  38. static PyObject *
  39. NSMap_remove (PyObject *self, PyObject *pfx_obj)
  40. {
  41. if (PyUnicode_READY (pfx_obj) < 0) return NULL;
  42. const char *pfx = PyUnicode_AsUTF8 (pfx_obj);
  43. if (LSUP_nsmap_remove (((NSMapObject *)self)->ob_struct, pfx) < 0) {
  44. PyErr_SetString (PyExc_ValueError, "Error removing namespace.");
  45. return NULL;
  46. }
  47. Py_RETURN_NONE;
  48. }
  49. static PyObject *
  50. NSMap_get (PyObject *self, PyObject *pfx_obj)
  51. {
  52. if (PyUnicode_READY (pfx_obj) < 0) return NULL;
  53. const char *pfx = PyUnicode_AsUTF8 (pfx_obj);
  54. const char *ns = LSUP_nsmap_get (((NSMapObject *)self)->ob_struct, pfx);
  55. if (!ns) Py_RETURN_NONE;
  56. PyObject *ns_obj = PyUnicode_FromString (ns);
  57. Py_INCREF (ns_obj);
  58. return (ns_obj);
  59. }
  60. static PyObject *
  61. NSMap_denormalize_uri (PyObject *self, PyObject *fq_uri_obj)
  62. {
  63. if (PyUnicode_READY (fq_uri_obj) < 0) return NULL;
  64. const char *fq_uri = PyUnicode_AsUTF8 (fq_uri_obj);
  65. char *pfx_uri;
  66. LSUP_rc rc = LSUP_nsmap_denormalize_uri (
  67. ((NSMapObject *)self)->ob_struct, fq_uri, &pfx_uri);
  68. if (rc < 0) {
  69. PyErr_SetString (PyExc_ValueError, "Error normalizing URI.");
  70. return NULL;
  71. } else if (rc == LSUP_NORESULT) Py_RETURN_NONE;
  72. PyObject *uri_obj = PyUnicode_FromString (pfx_uri);
  73. Py_INCREF (uri_obj);
  74. return (uri_obj);
  75. }
  76. static PyObject *
  77. NSMap_normalize_uri (PyObject *self, PyObject *pfx_uri_obj)
  78. {
  79. if (PyUnicode_READY (pfx_uri_obj) < 0) return NULL;
  80. const char *pfx_uri = PyUnicode_AsUTF8 (pfx_uri_obj);
  81. char *fq_uri;
  82. LSUP_rc rc = LSUP_nsmap_normalize_uri (
  83. ((NSMapObject *)self)->ob_struct, pfx_uri, &fq_uri);
  84. if (rc < 0) {
  85. PyErr_SetString (PyExc_ValueError, "Error denormalizing URI.");
  86. return NULL;
  87. }
  88. PyObject *uri_obj = PyUnicode_FromString (fq_uri);
  89. Py_INCREF (uri_obj);
  90. return (uri_obj);
  91. }
  92. static PyObject *
  93. NSMap_as_dict (PyObject *self)
  94. {
  95. const char ***data = LSUP_nsmap_dump (((NSMapObject *)self)->ob_struct);
  96. PyObject *data_obj = PyDict_New();
  97. // TODO PyDictProxy_New(PyObject *mapping)
  98. for (size_t i = 0; data[i] != NULL; i++) {
  99. PyObject *val_obj = PyUnicode_FromString(data[i][1]);
  100. if (PyDict_SetItemString (data_obj, data[i][0], val_obj) < 0)
  101. return NULL;
  102. }
  103. Py_INCREF (data_obj);
  104. return data_obj;
  105. }
  106. static PyMethodDef NSMap_methods[] = {
  107. {
  108. "add", (PyCFunction) NSMap_add, METH_VARARGS,
  109. "Add a namespace prefix."
  110. },
  111. {
  112. "remove", (PyCFunction) NSMap_remove, METH_O,
  113. "Remove a namespace prefix."
  114. },
  115. {
  116. "get", (PyCFunction) NSMap_get, METH_O,
  117. "Get the fully qualified namespace for a prefix."
  118. },
  119. {
  120. "normalize_uri", (PyCFunction) NSMap_normalize_uri, METH_O,
  121. "Normalize a URI (i.e. convert from prefixed to fully qualified)."
  122. },
  123. {
  124. "denormalize_uri", (PyCFunction) NSMap_denormalize_uri, METH_O,
  125. "Denormalize a URI (i.e. convert from fully qualified to prefixed)."
  126. },
  127. {
  128. "as_dict", (PyCFunction) NSMap_as_dict, METH_NOARGS,
  129. "Namespace map as a dictionary of prefixes and namespaces.",
  130. },
  131. {NULL},
  132. };
  133. PyTypeObject NSMapType = {
  134. PyVarObject_HEAD_INIT(NULL, 0)
  135. .tp_name = "namespace.NSMap",
  136. .tp_doc = "Namespace prefix map.",
  137. .tp_basicsize = sizeof(NSMapObject),
  138. .tp_itemsize = 0,
  139. .tp_flags = Py_TPFLAGS_DEFAULT,
  140. .tp_new = PyType_GenericNew,
  141. .tp_init = (initproc) NSMap_init,
  142. .tp_dealloc = (destructor) NSMap_dealloc,
  143. .tp_methods = NSMap_methods,
  144. };
  145. #endif /* _PY_NAMESPACE_OBJ */