extension_dict.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /*
  2. * Copyright (c) 2009-2021, Google LLC
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of Google LLC nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  17. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19. * ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT,
  20. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. #include "python/extension_dict.h"
  28. #include "python/message.h"
  29. #include "python/protobuf.h"
  30. // -----------------------------------------------------------------------------
  31. // ExtensionDict
  32. // -----------------------------------------------------------------------------
  33. typedef struct {
  34. PyObject_HEAD;
  35. PyObject* msg; // Owning ref to our parent pessage.
  36. } PyUpb_ExtensionDict;
  37. PyObject* PyUpb_ExtensionDict_New(PyObject* msg) {
  38. PyUpb_ModuleState* state = PyUpb_ModuleState_Get();
  39. PyUpb_ExtensionDict* ext_dict =
  40. (void*)PyType_GenericAlloc(state->extension_dict_type, 0);
  41. ext_dict->msg = msg;
  42. Py_INCREF(ext_dict->msg);
  43. return &ext_dict->ob_base;
  44. }
  45. static PyObject* PyUpb_ExtensionDict_FindExtensionByName(PyObject* _self,
  46. PyObject* key) {
  47. PyUpb_ExtensionDict* self = (PyUpb_ExtensionDict*)_self;
  48. const char* name = PyUpb_GetStrData(key);
  49. const upb_MessageDef* m = PyUpb_CMessage_GetMsgdef(self->msg);
  50. const upb_FileDef* file = upb_MessageDef_File(m);
  51. const upb_DefPool* symtab = upb_FileDef_Pool(file);
  52. const upb_FieldDef* ext = upb_DefPool_FindExtensionByName(symtab, name);
  53. if (ext) {
  54. return PyUpb_FieldDescriptor_Get(ext);
  55. } else {
  56. Py_RETURN_NONE;
  57. }
  58. }
  59. static PyObject* PyUpb_ExtensionDict_FindExtensionByNumber(PyObject* _self,
  60. PyObject* arg) {
  61. PyUpb_ExtensionDict* self = (PyUpb_ExtensionDict*)_self;
  62. const upb_MessageDef* m = PyUpb_CMessage_GetMsgdef(self->msg);
  63. const upb_MiniTable* l = upb_MessageDef_MiniTable(m);
  64. const upb_FileDef* file = upb_MessageDef_File(m);
  65. const upb_DefPool* symtab = upb_FileDef_Pool(file);
  66. const upb_ExtensionRegistry* reg = upb_DefPool_ExtensionRegistry(symtab);
  67. int64_t number = PyLong_AsLong(arg);
  68. const upb_MiniTable_Extension* ext =
  69. (upb_MiniTable_Extension*)_upb_extreg_get(reg, l, number);
  70. if (ext) {
  71. const upb_FieldDef* f = _upb_DefPool_FindExtensionByMiniTable(symtab, ext);
  72. return PyUpb_FieldDescriptor_Get(f);
  73. } else {
  74. Py_RETURN_NONE;
  75. }
  76. }
  77. static void PyUpb_ExtensionDict_Dealloc(PyUpb_ExtensionDict* self) {
  78. PyUpb_CMessage_ClearExtensionDict(self->msg);
  79. Py_DECREF(self->msg);
  80. PyUpb_Dealloc(self);
  81. }
  82. static int PyUpb_ExtensionDict_Contains(PyObject* _self, PyObject* key) {
  83. PyUpb_ExtensionDict* self = (PyUpb_ExtensionDict*)_self;
  84. const upb_FieldDef* f = PyUpb_CMessage_GetExtensionDef(self->msg, key);
  85. if (!f) return -1;
  86. upb_Message* msg = PyUpb_CMessage_GetIfReified(self->msg);
  87. if (!msg) return 0;
  88. if (upb_FieldDef_IsRepeated(f)) {
  89. upb_MessageValue val = upb_Message_Get(msg, f);
  90. return upb_Array_Size(val.array_val) > 0;
  91. } else {
  92. return upb_Message_Has(msg, f);
  93. }
  94. }
  95. static Py_ssize_t PyUpb_ExtensionDict_Length(PyObject* _self) {
  96. PyUpb_ExtensionDict* self = (PyUpb_ExtensionDict*)_self;
  97. upb_Message* msg = PyUpb_CMessage_GetIfReified(self->msg);
  98. return msg ? upb_Message_ExtensionCount(msg) : 0;
  99. }
  100. static PyObject* PyUpb_ExtensionDict_Subscript(PyObject* _self, PyObject* key) {
  101. PyUpb_ExtensionDict* self = (PyUpb_ExtensionDict*)_self;
  102. const upb_FieldDef* f = PyUpb_CMessage_GetExtensionDef(self->msg, key);
  103. if (!f) return NULL;
  104. return PyUpb_CMessage_GetFieldValue(self->msg, f);
  105. }
  106. static int PyUpb_ExtensionDict_AssignSubscript(PyObject* _self, PyObject* key,
  107. PyObject* val) {
  108. PyUpb_ExtensionDict* self = (PyUpb_ExtensionDict*)_self;
  109. const upb_FieldDef* f = PyUpb_CMessage_GetExtensionDef(self->msg, key);
  110. if (!f) return -1;
  111. if (val) {
  112. return PyUpb_CMessage_SetFieldValue(self->msg, f, val, PyExc_TypeError);
  113. } else {
  114. PyUpb_CMessage_DoClearField(self->msg, f);
  115. return 0;
  116. }
  117. }
  118. static PyObject* PyUpb_ExtensionIterator_New(PyObject* _ext_dict);
  119. static PyMethodDef PyUpb_ExtensionDict_Methods[] = {
  120. {"_FindExtensionByName", PyUpb_ExtensionDict_FindExtensionByName, METH_O,
  121. "Finds an extension by name."},
  122. {"_FindExtensionByNumber", PyUpb_ExtensionDict_FindExtensionByNumber,
  123. METH_O, "Finds an extension by number."},
  124. {NULL, NULL},
  125. };
  126. static PyType_Slot PyUpb_ExtensionDict_Slots[] = {
  127. {Py_tp_dealloc, PyUpb_ExtensionDict_Dealloc},
  128. {Py_tp_methods, PyUpb_ExtensionDict_Methods},
  129. //{Py_tp_getset, PyUpb_ExtensionDict_Getters},
  130. //{Py_tp_hash, PyObject_HashNotImplemented},
  131. //{Py_tp_richcompare, PyUpb_ExtensionDict_RichCompare},
  132. {Py_tp_iter, PyUpb_ExtensionIterator_New},
  133. {Py_sq_contains, PyUpb_ExtensionDict_Contains},
  134. {Py_sq_length, PyUpb_ExtensionDict_Length},
  135. {Py_mp_length, PyUpb_ExtensionDict_Length},
  136. {Py_mp_subscript, PyUpb_ExtensionDict_Subscript},
  137. {Py_mp_ass_subscript, PyUpb_ExtensionDict_AssignSubscript},
  138. {0, NULL}};
  139. static PyType_Spec PyUpb_ExtensionDict_Spec = {
  140. PYUPB_MODULE_NAME ".ExtensionDict", // tp_name
  141. sizeof(PyUpb_ExtensionDict), // tp_basicsize
  142. 0, // tp_itemsize
  143. Py_TPFLAGS_DEFAULT, // tp_flags
  144. PyUpb_ExtensionDict_Slots,
  145. };
  146. // -----------------------------------------------------------------------------
  147. // ExtensionIterator
  148. // -----------------------------------------------------------------------------
  149. typedef struct {
  150. PyObject_HEAD;
  151. PyObject* msg;
  152. size_t iter;
  153. } PyUpb_ExtensionIterator;
  154. static PyObject* PyUpb_ExtensionIterator_New(PyObject* _ext_dict) {
  155. PyUpb_ExtensionDict* ext_dict = (PyUpb_ExtensionDict*)_ext_dict;
  156. PyUpb_ModuleState* state = PyUpb_ModuleState_Get();
  157. PyUpb_ExtensionIterator* iter =
  158. (void*)PyType_GenericAlloc(state->extension_iterator_type, 0);
  159. if (!iter) return NULL;
  160. iter->msg = ext_dict->msg;
  161. iter->iter = kUpb_Message_Begin;
  162. Py_INCREF(iter->msg);
  163. return &iter->ob_base;
  164. }
  165. static void PyUpb_ExtensionIterator_Dealloc(void* _self) {
  166. PyUpb_ExtensionIterator* self = (PyUpb_ExtensionIterator*)_self;
  167. Py_DECREF(self->msg);
  168. PyUpb_Dealloc(_self);
  169. }
  170. PyObject* PyUpb_ExtensionIterator_IterNext(PyObject* _self) {
  171. PyUpb_ExtensionIterator* self = (PyUpb_ExtensionIterator*)_self;
  172. upb_Message* msg = PyUpb_CMessage_GetIfReified(self->msg);
  173. if (!msg) return NULL;
  174. const upb_MessageDef* m = PyUpb_CMessage_GetMsgdef(self->msg);
  175. const upb_DefPool* symtab = upb_FileDef_Pool(upb_MessageDef_File(m));
  176. while (true) {
  177. const upb_FieldDef* f;
  178. upb_MessageValue val;
  179. if (!upb_Message_Next(msg, m, symtab, &f, &val, &self->iter)) return NULL;
  180. if (upb_FieldDef_IsExtension(f)) return PyUpb_FieldDescriptor_Get(f);
  181. }
  182. }
  183. static PyType_Slot PyUpb_ExtensionIterator_Slots[] = {
  184. {Py_tp_dealloc, PyUpb_ExtensionIterator_Dealloc},
  185. {Py_tp_iter, PyObject_SelfIter},
  186. {Py_tp_iternext, PyUpb_ExtensionIterator_IterNext},
  187. {0, NULL}};
  188. static PyType_Spec PyUpb_ExtensionIterator_Spec = {
  189. PYUPB_MODULE_NAME ".ExtensionIterator", // tp_name
  190. sizeof(PyUpb_ExtensionIterator), // tp_basicsize
  191. 0, // tp_itemsize
  192. Py_TPFLAGS_DEFAULT, // tp_flags
  193. PyUpb_ExtensionIterator_Slots,
  194. };
  195. // -----------------------------------------------------------------------------
  196. // Top Level
  197. // -----------------------------------------------------------------------------
  198. bool PyUpb_InitExtensionDict(PyObject* m) {
  199. PyUpb_ModuleState* s = PyUpb_ModuleState_GetFromModule(m);
  200. s->extension_dict_type = PyUpb_AddClass(m, &PyUpb_ExtensionDict_Spec);
  201. s->extension_iterator_type = PyUpb_AddClass(m, &PyUpb_ExtensionIterator_Spec);
  202. return s->extension_dict_type && s->extension_iterator_type;
  203. }