You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

238 lines
6.6 KiB

4 years ago
  1. #include "Python.h"
  2. #include "structmember.h"
  3. PyDoc_STRVAR(istr__doc__, "istr class implementation");
  4. /* We link this module statically for convenience. If compiled as a shared
  5. library instead, some compilers don't allow addresses of Python objects
  6. defined in other libraries to be used in static initializers here. The
  7. DEFERRED_ADDRESS macro is used to tag the slots where such addresses
  8. appear; the module init function must fill in the tagged slots at runtime.
  9. The argument is for documentation -- the macro ignores it.
  10. */
  11. #define DEFERRED_ADDRESS(ADDR) 0
  12. typedef struct {
  13. PyUnicodeObject str;
  14. PyObject * canonical;
  15. } istrobject;
  16. typedef struct {
  17. PyObject *title;
  18. PyObject *emptystr;
  19. PyObject *emptydict;
  20. } ModData;
  21. static struct PyModuleDef _istrmodule;
  22. static PyTypeObject istr_type;
  23. static ModData *
  24. modstate(PyObject *mod)
  25. {
  26. return (ModData*)PyModule_GetState(mod);
  27. }
  28. static ModData *
  29. global_state(void)
  30. {
  31. return modstate(PyState_FindModule(&_istrmodule));
  32. }
  33. static PyObject *
  34. istr_title(istrobject *self, PyObject *args)
  35. {
  36. if (!PyArg_ParseTuple(args, ":title"))
  37. return NULL;
  38. Py_INCREF(self);
  39. return (PyObject*)self;
  40. }
  41. static PyObject *
  42. istr_str(istrobject *self)
  43. {
  44. Py_INCREF(self->canonical);
  45. return self->canonical;
  46. }
  47. static PyMethodDef istr_methods[] = {
  48. {"title", (PyCFunction)istr_title, METH_VARARGS,
  49. PyDoc_STR("title()")},
  50. {NULL, NULL},
  51. };
  52. void istr_dealloc(istrobject *self)
  53. {
  54. Py_XDECREF(self->canonical);
  55. PyUnicode_Type.tp_dealloc((PyObject*)self);
  56. }
  57. static PyObject *
  58. istr_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
  59. {
  60. PyObject *x = NULL;
  61. static char *kwlist[] = {"object", "encoding", "errors", 0};
  62. char *encoding = NULL;
  63. char *errors = NULL;
  64. PyObject *s = NULL;
  65. PyObject *tmp = NULL;
  66. PyObject * new_args = NULL;
  67. PyObject * ret = NULL;
  68. ModData * state = global_state();
  69. if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oss:str",
  70. kwlist, &x, &encoding, &errors))
  71. return NULL;
  72. if (x == NULL) {
  73. s = state->emptystr;
  74. Py_INCREF(s);
  75. }
  76. else if (PyObject_IsInstance(x, (PyObject*)&istr_type)) {
  77. Py_INCREF(x);
  78. return x;
  79. }
  80. else {
  81. if (encoding == NULL && errors == NULL) {
  82. tmp = PyObject_Str(x);
  83. } else {
  84. tmp = PyUnicode_FromEncodedObject(x, encoding, errors);
  85. }
  86. if (!tmp) {
  87. goto finish;
  88. }
  89. s = PyObject_CallMethodObjArgs(tmp, state->title, NULL);
  90. }
  91. if (!s)
  92. goto finish;
  93. new_args = PyTuple_Pack(1, s);
  94. if (!new_args) {
  95. goto finish;
  96. }
  97. ret = PyUnicode_Type.tp_new(type, new_args, state->emptydict);
  98. if (!ret) {
  99. goto finish;
  100. }
  101. ((istrobject*)ret)->canonical = s;
  102. s = NULL; /* the reference is stollen by .canonical */
  103. finish:
  104. Py_XDECREF(tmp);
  105. Py_XDECREF(s);
  106. Py_XDECREF(new_args);
  107. return ret;
  108. }
  109. static PyTypeObject istr_type = {
  110. PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0)
  111. "multidict._istr.istr",
  112. sizeof(istrobject),
  113. 0,
  114. (destructor)istr_dealloc, /* tp_dealloc */
  115. 0, /* tp_print */
  116. 0, /* tp_getattr */
  117. 0, /* tp_setattr */
  118. 0, /* tp_reserved */
  119. 0, /* tp_repr */
  120. 0, /* tp_as_number */
  121. 0, /* tp_as_sequence */
  122. 0, /* tp_as_mapping */
  123. 0, /* tp_hash */
  124. 0, /* tp_call */
  125. (reprfunc)istr_str, /* tp_str */
  126. 0, /* tp_getattro */
  127. 0, /* tp_setattro */
  128. 0, /* tp_as_buffer */
  129. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_UNICODE_SUBCLASS,
  130. /* tp_flags */
  131. 0, /* tp_doc */
  132. 0, /* tp_traverse */
  133. 0, /* tp_clear */
  134. 0, /* tp_richcompare */
  135. 0, /* tp_weaklistoffset */
  136. 0, /* tp_iter */
  137. 0, /* tp_iternext */
  138. istr_methods, /* tp_methods */
  139. 0, /* tp_members */
  140. 0, /* tp_getset */
  141. DEFERRED_ADDRESS(&PyUnicode_Type), /* tp_base */
  142. 0, /* tp_dict */
  143. 0, /* tp_descr_get */
  144. 0, /* tp_descr_set */
  145. 0, /* tp_dictoffset */
  146. 0, /* tp_init */
  147. 0, /* tp_alloc */
  148. (newfunc)istr_new, /* tp_new */
  149. };
  150. static int mod_clear(PyObject *m)
  151. {
  152. Py_CLEAR(modstate(m)->title);
  153. Py_CLEAR(modstate(m)->emptystr);
  154. Py_CLEAR(modstate(m)->emptydict);
  155. return 0;
  156. }
  157. static struct PyModuleDef _istrmodule = {
  158. PyModuleDef_HEAD_INIT,
  159. "multidict._istr",
  160. istr__doc__,
  161. sizeof(ModData),
  162. NULL, /* m_methods */
  163. NULL, /* m_reload */
  164. NULL, /* m_traverse */
  165. mod_clear, /* m_clear */
  166. NULL /* m_free */
  167. };
  168. PyObject* PyInit__istr(void)
  169. {
  170. PyObject * tmp;
  171. PyObject *mod;
  172. mod = PyState_FindModule(&_istrmodule);
  173. if (mod) {
  174. Py_INCREF(mod);
  175. return mod;
  176. }
  177. istr_type.tp_base = &PyUnicode_Type;
  178. if (PyType_Ready(&istr_type) < 0) {
  179. return NULL;
  180. }
  181. mod = PyModule_Create(&_istrmodule);
  182. if (!mod) {
  183. return NULL;
  184. }
  185. tmp = PyUnicode_FromString("title");
  186. if (!tmp) {
  187. goto err;
  188. }
  189. modstate(mod)->title = tmp;
  190. tmp = PyUnicode_New(0, 0);
  191. if (!tmp) {
  192. goto err;
  193. }
  194. modstate(mod)->emptystr = tmp;
  195. tmp = PyUnicode_FromString("title");
  196. if(!tmp) {
  197. goto err;
  198. }
  199. modstate(mod)->title = tmp;
  200. Py_INCREF(&istr_type);
  201. if (PyModule_AddObject(mod, "istr", (PyObject *)&istr_type) < 0)
  202. goto err;
  203. return mod;
  204. err:
  205. Py_DECREF(mod);
  206. return NULL;
  207. }