repeated.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816
  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/repeated.h"
  28. #include "python/convert.h"
  29. #include "python/message.h"
  30. #include "python/protobuf.h"
  31. static PyObject* PyUpb_RepeatedCompositeContainer_Append(PyObject* _self,
  32. PyObject* value);
  33. static PyObject* PyUpb_RepeatedScalarContainer_Append(PyObject* _self,
  34. PyObject* value);
  35. // For an expression like:
  36. // foo[index]
  37. //
  38. // Converts `index` to an effective i/count/step, for a repeated field
  39. // field of size `size`.
  40. static bool IndexToRange(PyObject* index, Py_ssize_t size, Py_ssize_t* i,
  41. Py_ssize_t* count, Py_ssize_t* step) {
  42. assert(i && count && step);
  43. if (PySlice_Check(index)) {
  44. Py_ssize_t start, stop;
  45. if (PySlice_Unpack(index, &start, &stop, step) < 0) return false;
  46. *count = PySlice_AdjustIndices(size, &start, &stop, *step);
  47. *i = start;
  48. } else {
  49. *i = PyNumber_AsSsize_t(index, PyExc_IndexError);
  50. if (*i == -1 && PyErr_Occurred()) {
  51. PyErr_SetString(PyExc_TypeError, "list indices must be integers");
  52. return false;
  53. }
  54. if (*i < 0) *i += size;
  55. *step = 0;
  56. *count = 1;
  57. if (*i < 0 || size <= *i) {
  58. PyErr_Format(PyExc_IndexError, "list index out of range");
  59. return false;
  60. }
  61. }
  62. return true;
  63. }
  64. // Wrapper for a repeated field.
  65. typedef struct {
  66. PyObject_HEAD;
  67. PyObject* arena;
  68. // The field descriptor (PyObject*).
  69. // The low bit indicates whether the container is reified (see ptr below).
  70. // - low bit set: repeated field is a stub (no underlying data).
  71. // - low bit clear: repeated field is reified (points to upb_Array).
  72. uintptr_t field;
  73. union {
  74. PyObject* parent; // stub: owning pointer to parent message.
  75. upb_Array* arr; // reified: the data for this array.
  76. } ptr;
  77. } PyUpb_RepeatedContainer;
  78. static bool PyUpb_RepeatedContainer_IsStub(PyUpb_RepeatedContainer* self) {
  79. return self->field & 1;
  80. }
  81. static PyObject* PyUpb_RepeatedContainer_GetFieldDescriptor(
  82. PyUpb_RepeatedContainer* self) {
  83. return (PyObject*)(self->field & ~(uintptr_t)1);
  84. }
  85. static const upb_FieldDef* PyUpb_RepeatedContainer_GetField(
  86. PyUpb_RepeatedContainer* self) {
  87. return PyUpb_FieldDescriptor_GetDef(
  88. PyUpb_RepeatedContainer_GetFieldDescriptor(self));
  89. }
  90. // If the repeated field is reified, returns it. Otherwise, returns NULL.
  91. // If NULL is returned, the object is empty and has no underlying data.
  92. static upb_Array* PyUpb_RepeatedContainer_GetIfReified(
  93. PyUpb_RepeatedContainer* self) {
  94. return PyUpb_RepeatedContainer_IsStub(self) ? NULL : self->ptr.arr;
  95. }
  96. void PyUpb_RepeatedContainer_Reify(PyObject* _self, upb_Array* arr) {
  97. PyUpb_RepeatedContainer* self = (PyUpb_RepeatedContainer*)_self;
  98. assert(PyUpb_RepeatedContainer_IsStub(self));
  99. if (!arr) {
  100. const upb_FieldDef* f = PyUpb_RepeatedContainer_GetField(self);
  101. upb_Arena* arena = PyUpb_Arena_Get(self->arena);
  102. arr = upb_Array_New(arena, upb_FieldDef_CType(f));
  103. }
  104. PyUpb_ObjCache_Add(arr, &self->ob_base);
  105. Py_DECREF(self->ptr.parent);
  106. self->ptr.arr = arr; // Overwrites self->ptr.parent.
  107. self->field &= ~(uintptr_t)1;
  108. assert(!PyUpb_RepeatedContainer_IsStub(self));
  109. }
  110. upb_Array* PyUpb_RepeatedContainer_EnsureReified(PyObject* _self) {
  111. PyUpb_RepeatedContainer* self = (PyUpb_RepeatedContainer*)_self;
  112. upb_Array* arr = PyUpb_RepeatedContainer_GetIfReified(self);
  113. if (arr) return arr; // Already writable.
  114. const upb_FieldDef* f = PyUpb_RepeatedContainer_GetField(self);
  115. upb_Arena* arena = PyUpb_Arena_Get(self->arena);
  116. arr = upb_Array_New(arena, upb_FieldDef_CType(f));
  117. PyUpb_CMessage_SetConcreteSubobj(self->ptr.parent, f,
  118. (upb_MessageValue){.array_val = arr});
  119. PyUpb_RepeatedContainer_Reify((PyObject*)self, arr);
  120. return arr;
  121. }
  122. static void PyUpb_RepeatedContainer_Dealloc(PyObject* _self) {
  123. PyUpb_RepeatedContainer* self = (PyUpb_RepeatedContainer*)_self;
  124. Py_DECREF(self->arena);
  125. if (PyUpb_RepeatedContainer_IsStub(self)) {
  126. PyUpb_CMessage_CacheDelete(self->ptr.parent,
  127. PyUpb_RepeatedContainer_GetField(self));
  128. Py_DECREF(self->ptr.parent);
  129. } else {
  130. PyUpb_ObjCache_Delete(self->ptr.arr);
  131. }
  132. Py_DECREF(PyUpb_RepeatedContainer_GetFieldDescriptor(self));
  133. PyUpb_Dealloc(self);
  134. }
  135. static PyTypeObject* PyUpb_RepeatedContainer_GetClass(const upb_FieldDef* f) {
  136. assert(upb_FieldDef_IsRepeated(f) && !upb_FieldDef_IsMap(f));
  137. PyUpb_ModuleState* state = PyUpb_ModuleState_Get();
  138. return upb_FieldDef_IsSubMessage(f) ? state->repeated_composite_container_type
  139. : state->repeated_scalar_container_type;
  140. }
  141. static Py_ssize_t PyUpb_RepeatedContainer_Length(PyObject* self) {
  142. upb_Array* arr =
  143. PyUpb_RepeatedContainer_GetIfReified((PyUpb_RepeatedContainer*)self);
  144. return arr ? upb_Array_Size(arr) : 0;
  145. }
  146. PyObject* PyUpb_RepeatedContainer_NewStub(PyObject* parent,
  147. const upb_FieldDef* f,
  148. PyObject* arena) {
  149. // We only create stubs when the parent is reified, by convention. However
  150. // this is not an invariant: the parent could become reified at any time.
  151. assert(PyUpb_CMessage_GetIfReified(parent) == NULL);
  152. PyTypeObject* cls = PyUpb_RepeatedContainer_GetClass(f);
  153. PyUpb_RepeatedContainer* repeated = (void*)PyType_GenericAlloc(cls, 0);
  154. repeated->arena = arena;
  155. repeated->field = (uintptr_t)PyUpb_FieldDescriptor_Get(f) | 1;
  156. repeated->ptr.parent = parent;
  157. Py_INCREF(arena);
  158. Py_INCREF(parent);
  159. return &repeated->ob_base;
  160. }
  161. PyObject* PyUpb_RepeatedContainer_GetOrCreateWrapper(upb_Array* arr,
  162. const upb_FieldDef* f,
  163. PyObject* arena) {
  164. PyObject* ret = PyUpb_ObjCache_Get(arr);
  165. if (ret) return ret;
  166. PyTypeObject* cls = PyUpb_RepeatedContainer_GetClass(f);
  167. PyUpb_RepeatedContainer* repeated = (void*)PyType_GenericAlloc(cls, 0);
  168. repeated->arena = arena;
  169. repeated->field = (uintptr_t)PyUpb_FieldDescriptor_Get(f);
  170. repeated->ptr.arr = arr;
  171. ret = &repeated->ob_base;
  172. Py_INCREF(arena);
  173. PyUpb_ObjCache_Add(arr, ret);
  174. return ret;
  175. }
  176. static PyObject* PyUpb_RepeatedContainer_MergeFrom(PyObject* _self,
  177. PyObject* args);
  178. PyObject* PyUpb_RepeatedContainer_DeepCopy(PyObject* _self, PyObject* value) {
  179. PyUpb_RepeatedContainer* self = (PyUpb_RepeatedContainer*)_self;
  180. PyUpb_RepeatedContainer* clone =
  181. (void*)PyType_GenericAlloc(Py_TYPE(_self), 0);
  182. if (clone == NULL) return NULL;
  183. const upb_FieldDef* f = PyUpb_RepeatedContainer_GetField(self);
  184. clone->arena = PyUpb_Arena_New();
  185. clone->field = (uintptr_t)PyUpb_FieldDescriptor_Get(f);
  186. clone->ptr.arr =
  187. upb_Array_New(PyUpb_Arena_Get(clone->arena), upb_FieldDef_CType(f));
  188. PyUpb_ObjCache_Add(clone->ptr.arr, (PyObject*)clone);
  189. PyObject* result = PyUpb_RepeatedContainer_MergeFrom((PyObject*)clone, _self);
  190. if (!result) {
  191. Py_DECREF(clone);
  192. return NULL;
  193. }
  194. Py_DECREF(result);
  195. return (PyObject*)clone;
  196. }
  197. PyObject* PyUpb_RepeatedContainer_Extend(PyObject* _self, PyObject* value) {
  198. PyUpb_RepeatedContainer* self = (PyUpb_RepeatedContainer*)_self;
  199. upb_Array* arr = PyUpb_RepeatedContainer_EnsureReified(_self);
  200. size_t start_size = upb_Array_Size(arr);
  201. PyObject* it = PyObject_GetIter(value);
  202. if (!it) {
  203. PyErr_SetString(PyExc_TypeError, "Value must be iterable");
  204. return NULL;
  205. }
  206. const upb_FieldDef* f = PyUpb_RepeatedContainer_GetField(self);
  207. bool submsg = upb_FieldDef_IsSubMessage(f);
  208. PyObject* e;
  209. while ((e = PyIter_Next(it))) {
  210. PyObject* ret;
  211. if (submsg) {
  212. ret = PyUpb_RepeatedCompositeContainer_Append(_self, e);
  213. } else {
  214. ret = PyUpb_RepeatedScalarContainer_Append(_self, e);
  215. }
  216. Py_XDECREF(ret);
  217. Py_DECREF(e);
  218. }
  219. Py_DECREF(it);
  220. if (PyErr_Occurred()) {
  221. upb_Array_Resize(arr, start_size, NULL);
  222. return NULL;
  223. }
  224. Py_RETURN_NONE;
  225. }
  226. static PyObject* PyUpb_RepeatedContainer_Item(PyObject* _self,
  227. Py_ssize_t index) {
  228. PyUpb_RepeatedContainer* self = (PyUpb_RepeatedContainer*)_self;
  229. upb_Array* arr = PyUpb_RepeatedContainer_GetIfReified(self);
  230. Py_ssize_t size = arr ? upb_Array_Size(arr) : 0;
  231. if (index < 0 || index >= size) {
  232. PyErr_Format(PyExc_IndexError, "list index (%zd) out of range", index);
  233. return NULL;
  234. }
  235. const upb_FieldDef* f = PyUpb_RepeatedContainer_GetField(self);
  236. return PyUpb_UpbToPy(upb_Array_Get(arr, index), f, self->arena);
  237. }
  238. PyObject* PyUpb_RepeatedContainer_ToList(PyObject* _self) {
  239. PyUpb_RepeatedContainer* self = (PyUpb_RepeatedContainer*)_self;
  240. upb_Array* arr = PyUpb_RepeatedContainer_GetIfReified(self);
  241. if (!arr) return PyList_New(0);
  242. const upb_FieldDef* f = PyUpb_RepeatedContainer_GetField(self);
  243. size_t n = upb_Array_Size(arr);
  244. PyObject* list = PyList_New(n);
  245. for (size_t i = 0; i < n; i++) {
  246. PyObject* val = PyUpb_UpbToPy(upb_Array_Get(arr, i), f, self->arena);
  247. if (!val) {
  248. Py_DECREF(list);
  249. return NULL;
  250. }
  251. PyList_SetItem(list, i, val);
  252. }
  253. return list;
  254. }
  255. static PyObject* PyUpb_RepeatedContainer_Repr(PyObject* _self) {
  256. PyObject* list = PyUpb_RepeatedContainer_ToList(_self);
  257. if (!list) return NULL;
  258. assert(!PyErr_Occurred());
  259. PyObject* repr = PyObject_Repr(list);
  260. Py_DECREF(list);
  261. return repr;
  262. }
  263. static PyObject* PyUpb_RepeatedContainer_RichCompare(PyObject* _self,
  264. PyObject* _other,
  265. int opid) {
  266. if (opid != Py_EQ && opid != Py_NE) {
  267. Py_INCREF(Py_NotImplemented);
  268. return Py_NotImplemented;
  269. }
  270. PyObject* list1 = PyUpb_RepeatedContainer_ToList(_self);
  271. PyObject* list2 = _other;
  272. PyObject* del = NULL;
  273. if (PyObject_TypeCheck(_other, _self->ob_type)) {
  274. del = list2 = PyUpb_RepeatedContainer_ToList(_other);
  275. }
  276. PyObject* ret = PyObject_RichCompare(list1, list2, opid);
  277. Py_DECREF(list1);
  278. Py_XDECREF(del);
  279. return ret;
  280. }
  281. static PyObject* PyUpb_RepeatedContainer_Subscript(PyObject* _self,
  282. PyObject* key) {
  283. PyUpb_RepeatedContainer* self = (PyUpb_RepeatedContainer*)_self;
  284. upb_Array* arr = PyUpb_RepeatedContainer_GetIfReified(self);
  285. Py_ssize_t size = arr ? upb_Array_Size(arr) : 0;
  286. Py_ssize_t idx, count, step;
  287. if (!IndexToRange(key, size, &idx, &count, &step)) return NULL;
  288. const upb_FieldDef* f = PyUpb_RepeatedContainer_GetField(self);
  289. if (step == 0) {
  290. return PyUpb_UpbToPy(upb_Array_Get(arr, idx), f, self->arena);
  291. } else {
  292. PyObject* list = PyList_New(count);
  293. for (Py_ssize_t i = 0; i < count; i++, idx += step) {
  294. upb_MessageValue msgval = upb_Array_Get(self->ptr.arr, idx);
  295. PyObject* item = PyUpb_UpbToPy(msgval, f, self->arena);
  296. if (!item) {
  297. Py_DECREF(list);
  298. return NULL;
  299. }
  300. PyList_SetItem(list, i, item);
  301. }
  302. return list;
  303. }
  304. }
  305. static int PyUpb_RepeatedContainer_SetSubscript(
  306. PyUpb_RepeatedContainer* self, upb_Array* arr, const upb_FieldDef* f,
  307. Py_ssize_t idx, Py_ssize_t count, Py_ssize_t step, PyObject* value) {
  308. upb_Arena* arena = PyUpb_Arena_Get(self->arena);
  309. if (upb_FieldDef_IsSubMessage(f)) {
  310. PyErr_SetString(PyExc_TypeError, "does not support assignment");
  311. return -1;
  312. }
  313. if (step == 0) {
  314. // Set single value.
  315. upb_MessageValue msgval;
  316. if (!PyUpb_PyToUpb(value, f, &msgval, arena)) return -1;
  317. upb_Array_Set(arr, idx, msgval);
  318. return 0;
  319. }
  320. // Set range.
  321. PyObject* seq =
  322. PySequence_Fast(value, "must assign iterable to extended slice");
  323. PyObject* item = NULL;
  324. int ret = -1;
  325. if (!seq) goto err;
  326. Py_ssize_t seq_size = PySequence_Size(seq);
  327. if (seq_size != count) {
  328. if (step == 1) {
  329. // We must shift the tail elements (either right or left).
  330. size_t tail = upb_Array_Size(arr) - (idx + count);
  331. upb_Array_Resize(arr, idx + seq_size + tail, arena);
  332. upb_Array_Move(arr, idx + seq_size, idx + count, tail);
  333. count = seq_size;
  334. } else {
  335. PyErr_Format(PyExc_ValueError,
  336. "attempt to assign sequence of %zd to extended slice "
  337. "of size %zd",
  338. seq_size, count);
  339. goto err;
  340. }
  341. }
  342. for (Py_ssize_t i = 0; i < count; i++, idx += step) {
  343. upb_MessageValue msgval;
  344. item = PySequence_GetItem(seq, i);
  345. if (!item) goto err;
  346. // XXX: if this fails we can leave the list partially mutated.
  347. if (!PyUpb_PyToUpb(item, f, &msgval, arena)) goto err;
  348. Py_DECREF(item);
  349. item = NULL;
  350. upb_Array_Set(arr, idx, msgval);
  351. }
  352. ret = 0;
  353. err:
  354. Py_XDECREF(seq);
  355. Py_XDECREF(item);
  356. return ret;
  357. }
  358. static int PyUpb_RepeatedContainer_DeleteSubscript(upb_Array* arr,
  359. Py_ssize_t idx,
  360. Py_ssize_t count,
  361. Py_ssize_t step) {
  362. // Normalize direction: deletion is order-independent.
  363. Py_ssize_t start = idx;
  364. if (step < 0) {
  365. Py_ssize_t end = start + step * (count - 1);
  366. start = end;
  367. step = -step;
  368. }
  369. size_t dst = start;
  370. size_t src;
  371. if (step > 1) {
  372. // Move elements between steps:
  373. //
  374. // src
  375. // |
  376. // |------X---X---X---X------------------------------|
  377. // |
  378. // dst <-------- tail -------------->
  379. src = start + 1;
  380. for (Py_ssize_t i = 1; i < count; i++, dst += step - 1, src += step) {
  381. upb_Array_Move(arr, dst, src, step);
  382. }
  383. } else {
  384. src = start + count;
  385. }
  386. // Move tail.
  387. size_t tail = upb_Array_Size(arr) - src;
  388. size_t new_size = dst + tail;
  389. assert(new_size == upb_Array_Size(arr) - count);
  390. upb_Array_Move(arr, dst, src, tail);
  391. upb_Array_Resize(arr, new_size, NULL);
  392. return 0;
  393. }
  394. static int PyUpb_RepeatedContainer_AssignSubscript(PyObject* _self,
  395. PyObject* key,
  396. PyObject* value) {
  397. PyUpb_RepeatedContainer* self = (PyUpb_RepeatedContainer*)_self;
  398. const upb_FieldDef* f = PyUpb_RepeatedContainer_GetField(self);
  399. upb_Array* arr = PyUpb_RepeatedContainer_GetIfReified(self);
  400. Py_ssize_t size = arr ? upb_Array_Size(arr) : 0;
  401. Py_ssize_t idx, count, step;
  402. if (!IndexToRange(key, size, &idx, &count, &step)) return -1;
  403. if (value) {
  404. return PyUpb_RepeatedContainer_SetSubscript(self, arr, f, idx, count, step,
  405. value);
  406. } else {
  407. return PyUpb_RepeatedContainer_DeleteSubscript(arr, idx, count, step);
  408. }
  409. }
  410. static PyObject* PyUpb_RepeatedContainer_Pop(PyObject* _self, PyObject* args) {
  411. PyUpb_RepeatedContainer* self = (PyUpb_RepeatedContainer*)_self;
  412. Py_ssize_t index = -1;
  413. if (!PyArg_ParseTuple(args, "|n", &index)) return NULL;
  414. upb_Array* arr = PyUpb_RepeatedContainer_EnsureReified(_self);
  415. size_t size = upb_Array_Size(arr);
  416. if (index < 0) index += size;
  417. if (index >= size) index = size - 1;
  418. PyObject* ret = PyUpb_RepeatedContainer_Item(_self, index);
  419. if (!ret) return NULL;
  420. upb_Array_Delete(self->ptr.arr, index, 1);
  421. return ret;
  422. }
  423. static PyObject* PyUpb_RepeatedContainer_Remove(PyObject* _self,
  424. PyObject* value) {
  425. upb_Array* arr = PyUpb_RepeatedContainer_EnsureReified(_self);
  426. Py_ssize_t match_index = -1;
  427. Py_ssize_t n = PyUpb_RepeatedContainer_Length(_self);
  428. for (Py_ssize_t i = 0; i < n; ++i) {
  429. PyObject* elem = PyUpb_RepeatedContainer_Item(_self, i);
  430. if (!elem) return NULL;
  431. int eq = PyObject_RichCompareBool(elem, value, Py_EQ);
  432. Py_DECREF(elem);
  433. if (eq) {
  434. match_index = i;
  435. break;
  436. }
  437. }
  438. if (match_index == -1) {
  439. PyErr_SetString(PyExc_ValueError, "remove(x): x not in container");
  440. return NULL;
  441. }
  442. if (PyUpb_RepeatedContainer_DeleteSubscript(arr, match_index, 1, 1) < 0) {
  443. return NULL;
  444. }
  445. Py_RETURN_NONE;
  446. }
  447. // A helper function used only for Sort().
  448. static bool PyUpb_RepeatedContainer_Assign(PyObject* _self, PyObject* list) {
  449. PyUpb_RepeatedContainer* self = (PyUpb_RepeatedContainer*)_self;
  450. const upb_FieldDef* f = PyUpb_RepeatedContainer_GetField(self);
  451. upb_Array* arr = PyUpb_RepeatedContainer_EnsureReified(_self);
  452. Py_ssize_t size = PyList_Size(list);
  453. bool submsg = upb_FieldDef_IsSubMessage(f);
  454. upb_Arena* arena = PyUpb_Arena_Get(self->arena);
  455. for (Py_ssize_t i = 0; i < size; ++i) {
  456. PyObject* obj = PyList_GetItem(list, i);
  457. upb_MessageValue msgval;
  458. if (submsg) {
  459. msgval.msg_val = PyUpb_CMessage_GetIfReified(obj);
  460. assert(msgval.msg_val);
  461. } else {
  462. if (!PyUpb_PyToUpb(obj, f, &msgval, arena)) return false;
  463. }
  464. upb_Array_Set(arr, i, msgval);
  465. }
  466. return true;
  467. }
  468. static PyObject* PyUpb_RepeatedContainer_Sort(PyObject* pself, PyObject* args,
  469. PyObject* kwds) {
  470. // Support the old sort_function argument for backwards
  471. // compatibility.
  472. if (kwds != NULL) {
  473. PyObject* sort_func = PyDict_GetItemString(kwds, "sort_function");
  474. if (sort_func != NULL) {
  475. // Must set before deleting as sort_func is a borrowed reference
  476. // and kwds might be the only thing keeping it alive.
  477. if (PyDict_SetItemString(kwds, "cmp", sort_func) == -1) return NULL;
  478. if (PyDict_DelItemString(kwds, "sort_function") == -1) return NULL;
  479. }
  480. }
  481. PyObject* ret = NULL;
  482. PyObject* full_slice = NULL;
  483. PyObject* list = NULL;
  484. PyObject* m = NULL;
  485. PyObject* res = NULL;
  486. if ((full_slice = PySlice_New(NULL, NULL, NULL)) &&
  487. (list = PyUpb_RepeatedContainer_Subscript(pself, full_slice)) &&
  488. (m = PyObject_GetAttrString(list, "sort")) &&
  489. (res = PyObject_Call(m, args, kwds)) &&
  490. PyUpb_RepeatedContainer_Assign(pself, list)) {
  491. Py_INCREF(Py_None);
  492. ret = Py_None;
  493. }
  494. Py_XDECREF(full_slice);
  495. Py_XDECREF(list);
  496. Py_XDECREF(m);
  497. Py_XDECREF(res);
  498. return ret;
  499. }
  500. static PyObject* PyUpb_RepeatedContainer_Reverse(PyObject* _self) {
  501. upb_Array* arr = PyUpb_RepeatedContainer_EnsureReified(_self);
  502. size_t n = upb_Array_Size(arr);
  503. size_t half = n / 2; // Rounds down.
  504. for (size_t i = 0; i < half; i++) {
  505. size_t i2 = n - i - 1;
  506. upb_MessageValue val1 = upb_Array_Get(arr, i);
  507. upb_MessageValue val2 = upb_Array_Get(arr, i2);
  508. upb_Array_Set(arr, i, val2);
  509. upb_Array_Set(arr, i2, val1);
  510. }
  511. Py_RETURN_NONE;
  512. }
  513. static PyObject* PyUpb_RepeatedContainer_MergeFrom(PyObject* _self,
  514. PyObject* args) {
  515. return PyUpb_RepeatedContainer_Extend(_self, args);
  516. }
  517. // -----------------------------------------------------------------------------
  518. // RepeatedCompositeContainer
  519. // -----------------------------------------------------------------------------
  520. static PyObject* PyUpb_RepeatedCompositeContainer_AppendNew(PyObject* _self) {
  521. PyUpb_RepeatedContainer* self = (PyUpb_RepeatedContainer*)_self;
  522. upb_Array* arr = PyUpb_RepeatedContainer_EnsureReified(_self);
  523. if (!arr) return NULL;
  524. const upb_FieldDef* f = PyUpb_RepeatedContainer_GetField(self);
  525. upb_Arena* arena = PyUpb_Arena_Get(self->arena);
  526. const upb_MessageDef* m = upb_FieldDef_MessageSubDef(f);
  527. upb_Message* msg = upb_Message_New(m, arena);
  528. upb_MessageValue msgval = {.msg_val = msg};
  529. upb_Array_Append(arr, msgval, arena);
  530. return PyUpb_CMessage_Get(msg, m, self->arena);
  531. }
  532. PyObject* PyUpb_RepeatedCompositeContainer_Add(PyObject* _self, PyObject* args,
  533. PyObject* kwargs) {
  534. PyUpb_RepeatedContainer* self = (PyUpb_RepeatedContainer*)_self;
  535. PyObject* py_msg = PyUpb_RepeatedCompositeContainer_AppendNew(_self);
  536. if (!py_msg) return NULL;
  537. if (PyUpb_CMessage_InitAttributes(py_msg, args, kwargs) < 0) {
  538. Py_DECREF(py_msg);
  539. upb_Array_Delete(self->ptr.arr, upb_Array_Size(self->ptr.arr) - 1, 1);
  540. return NULL;
  541. }
  542. return py_msg;
  543. }
  544. static PyObject* PyUpb_RepeatedCompositeContainer_Append(PyObject* _self,
  545. PyObject* value) {
  546. if (!PyUpb_CMessage_Verify(value)) return NULL;
  547. PyObject* py_msg = PyUpb_RepeatedCompositeContainer_AppendNew(_self);
  548. if (!py_msg) return NULL;
  549. PyObject* none = PyUpb_CMessage_MergeFrom(py_msg, value);
  550. if (!none) {
  551. Py_DECREF(py_msg);
  552. return NULL;
  553. }
  554. Py_DECREF(none);
  555. return py_msg;
  556. }
  557. static PyObject* PyUpb_RepeatedContainer_Insert(PyObject* _self,
  558. PyObject* args) {
  559. PyUpb_RepeatedContainer* self = (PyUpb_RepeatedContainer*)_self;
  560. Py_ssize_t index;
  561. PyObject* value;
  562. if (!PyArg_ParseTuple(args, "nO", &index, &value)) return NULL;
  563. upb_Array* arr = PyUpb_RepeatedContainer_EnsureReified(_self);
  564. if (!arr) return NULL;
  565. // Normalize index.
  566. Py_ssize_t size = upb_Array_Size(arr);
  567. if (index < 0) index += size;
  568. if (index < 0) index = 0;
  569. if (index > size) index = size;
  570. const upb_FieldDef* f = PyUpb_RepeatedContainer_GetField(self);
  571. upb_MessageValue msgval;
  572. upb_Arena* arena = PyUpb_Arena_Get(self->arena);
  573. if (upb_FieldDef_IsSubMessage(f)) {
  574. // Create message.
  575. const upb_MessageDef* m = upb_FieldDef_MessageSubDef(f);
  576. upb_Message* msg = upb_Message_New(m, arena);
  577. PyObject* py_msg = PyUpb_CMessage_Get(msg, m, self->arena);
  578. PyObject* ret = PyUpb_CMessage_MergeFrom(py_msg, value);
  579. Py_DECREF(py_msg);
  580. if (!ret) return NULL;
  581. Py_DECREF(ret);
  582. msgval.msg_val = msg;
  583. } else {
  584. if (!PyUpb_PyToUpb(value, f, &msgval, arena)) return NULL;
  585. }
  586. upb_Array_Insert(arr, index, 1, arena);
  587. upb_Array_Set(arr, index, msgval);
  588. Py_RETURN_NONE;
  589. }
  590. static PyMethodDef PyUpb_RepeatedCompositeContainer_Methods[] = {
  591. // TODO(https://github.com/protocolbuffers/upb/issues/459)
  592. {"__deepcopy__", PyUpb_RepeatedContainer_DeepCopy, METH_VARARGS,
  593. "Makes a deep copy of the class."},
  594. {"add", (PyCFunction)PyUpb_RepeatedCompositeContainer_Add,
  595. METH_VARARGS | METH_KEYWORDS, "Adds an object to the repeated container."},
  596. {"append", PyUpb_RepeatedCompositeContainer_Append, METH_O,
  597. "Appends a message to the end of the repeated container."},
  598. {"insert", PyUpb_RepeatedContainer_Insert, METH_VARARGS,
  599. "Inserts a message before the specified index."},
  600. {"extend", PyUpb_RepeatedContainer_Extend, METH_O,
  601. "Adds objects to the repeated container."},
  602. {"pop", PyUpb_RepeatedContainer_Pop, METH_VARARGS,
  603. "Removes an object from the repeated container and returns it."},
  604. {"remove", PyUpb_RepeatedContainer_Remove, METH_O,
  605. "Removes an object from the repeated container."},
  606. {"sort", (PyCFunction)PyUpb_RepeatedContainer_Sort,
  607. METH_VARARGS | METH_KEYWORDS, "Sorts the repeated container."},
  608. {"reverse", (PyCFunction)PyUpb_RepeatedContainer_Reverse, METH_NOARGS,
  609. "Reverses elements order of the repeated container."},
  610. {"MergeFrom", PyUpb_RepeatedContainer_MergeFrom, METH_O,
  611. "Adds objects to the repeated container."},
  612. {NULL, NULL}};
  613. static PyType_Slot PyUpb_RepeatedCompositeContainer_Slots[] = {
  614. {Py_tp_dealloc, PyUpb_RepeatedContainer_Dealloc},
  615. {Py_tp_methods, PyUpb_RepeatedCompositeContainer_Methods},
  616. {Py_sq_length, PyUpb_RepeatedContainer_Length},
  617. {Py_sq_item, PyUpb_RepeatedContainer_Item},
  618. {Py_mp_length, PyUpb_RepeatedContainer_Length},
  619. {Py_tp_repr, PyUpb_RepeatedContainer_Repr},
  620. {Py_mp_subscript, PyUpb_RepeatedContainer_Subscript},
  621. {Py_mp_ass_subscript, PyUpb_RepeatedContainer_AssignSubscript},
  622. {Py_tp_new, PyUpb_Forbidden_New},
  623. {Py_tp_hash, PyObject_HashNotImplemented},
  624. {0, NULL}};
  625. static PyType_Spec PyUpb_RepeatedCompositeContainer_Spec = {
  626. PYUPB_MODULE_NAME ".RepeatedCompositeContainer",
  627. sizeof(PyUpb_RepeatedContainer),
  628. 0, // tp_itemsize
  629. Py_TPFLAGS_DEFAULT,
  630. PyUpb_RepeatedCompositeContainer_Slots,
  631. };
  632. // -----------------------------------------------------------------------------
  633. // RepeatedScalarContainer
  634. // -----------------------------------------------------------------------------
  635. static PyObject* PyUpb_RepeatedScalarContainer_Append(PyObject* _self,
  636. PyObject* value) {
  637. PyUpb_RepeatedContainer* self = (PyUpb_RepeatedContainer*)_self;
  638. upb_Array* arr = PyUpb_RepeatedContainer_EnsureReified(_self);
  639. upb_Arena* arena = PyUpb_Arena_Get(self->arena);
  640. const upb_FieldDef* f = PyUpb_RepeatedContainer_GetField(self);
  641. upb_MessageValue msgval;
  642. if (!PyUpb_PyToUpb(value, f, &msgval, arena)) {
  643. return NULL;
  644. }
  645. upb_Array_Append(arr, msgval, arena);
  646. Py_RETURN_NONE;
  647. }
  648. static int PyUpb_RepeatedScalarContainer_AssignItem(PyObject* _self,
  649. Py_ssize_t index,
  650. PyObject* item) {
  651. PyUpb_RepeatedContainer* self = (PyUpb_RepeatedContainer*)_self;
  652. upb_Array* arr = PyUpb_RepeatedContainer_GetIfReified(self);
  653. Py_ssize_t size = arr ? upb_Array_Size(arr) : 0;
  654. if (index < 0 || index >= size) {
  655. PyErr_Format(PyExc_IndexError, "list index (%zd) out of range", index);
  656. return -1;
  657. }
  658. const upb_FieldDef* f = PyUpb_RepeatedContainer_GetField(self);
  659. upb_MessageValue msgval;
  660. upb_Arena* arena = PyUpb_Arena_Get(self->arena);
  661. if (!PyUpb_PyToUpb(item, f, &msgval, arena)) {
  662. return -1;
  663. }
  664. upb_Array_Set(self->ptr.arr, index, msgval);
  665. return 0;
  666. }
  667. static PyMethodDef PyUpb_RepeatedScalarContainer_Methods[] = {
  668. // TODO(https://github.com/protocolbuffers/upb/issues/459)
  669. {"__deepcopy__", PyUpb_RepeatedContainer_DeepCopy, METH_VARARGS,
  670. "Makes a deep copy of the class."},
  671. // {"__reduce__", Reduce, METH_NOARGS,
  672. // "Outputs picklable representation of the repeated field."},
  673. {"append", PyUpb_RepeatedScalarContainer_Append, METH_O,
  674. "Appends an object to the repeated container."},
  675. {"extend", PyUpb_RepeatedContainer_Extend, METH_O,
  676. "Appends objects to the repeated container."},
  677. {"insert", PyUpb_RepeatedContainer_Insert, METH_VARARGS,
  678. "Inserts an object at the specified position in the container."},
  679. {"pop", PyUpb_RepeatedContainer_Pop, METH_VARARGS,
  680. "Removes an object from the repeated container and returns it."},
  681. {"remove", PyUpb_RepeatedContainer_Remove, METH_O,
  682. "Removes an object from the repeated container."},
  683. {"sort", (PyCFunction)PyUpb_RepeatedContainer_Sort,
  684. METH_VARARGS | METH_KEYWORDS, "Sorts the repeated container."},
  685. {"reverse", (PyCFunction)PyUpb_RepeatedContainer_Reverse, METH_NOARGS,
  686. "Reverses elements order of the repeated container."},
  687. {"MergeFrom", PyUpb_RepeatedContainer_MergeFrom, METH_O,
  688. "Merges a repeated container into the current container."},
  689. {NULL, NULL}};
  690. static PyType_Slot PyUpb_RepeatedScalarContainer_Slots[] = {
  691. {Py_tp_dealloc, PyUpb_RepeatedContainer_Dealloc},
  692. {Py_tp_methods, PyUpb_RepeatedScalarContainer_Methods},
  693. {Py_tp_new, PyUpb_Forbidden_New},
  694. {Py_tp_repr, PyUpb_RepeatedContainer_Repr},
  695. {Py_sq_length, PyUpb_RepeatedContainer_Length},
  696. {Py_sq_item, PyUpb_RepeatedContainer_Item},
  697. {Py_sq_ass_item, PyUpb_RepeatedScalarContainer_AssignItem},
  698. {Py_mp_length, PyUpb_RepeatedContainer_Length},
  699. {Py_mp_subscript, PyUpb_RepeatedContainer_Subscript},
  700. {Py_mp_ass_subscript, PyUpb_RepeatedContainer_AssignSubscript},
  701. {Py_tp_richcompare, PyUpb_RepeatedContainer_RichCompare},
  702. {Py_tp_hash, PyObject_HashNotImplemented},
  703. {0, NULL}};
  704. static PyType_Spec PyUpb_RepeatedScalarContainer_Spec = {
  705. PYUPB_MODULE_NAME ".RepeatedScalarContainer",
  706. sizeof(PyUpb_RepeatedContainer),
  707. 0, // tp_itemsize
  708. Py_TPFLAGS_DEFAULT,
  709. PyUpb_RepeatedScalarContainer_Slots,
  710. };
  711. // -----------------------------------------------------------------------------
  712. // Top Level
  713. // -----------------------------------------------------------------------------
  714. static bool PyUpb_Repeated_RegisterAsSequence(PyUpb_ModuleState* state) {
  715. PyObject* collections = NULL;
  716. PyObject* seq = NULL;
  717. PyObject* ret1 = NULL;
  718. PyObject* ret2 = NULL;
  719. PyTypeObject* type1 = state->repeated_scalar_container_type;
  720. PyTypeObject* type2 = state->repeated_composite_container_type;
  721. bool ok = (collections = PyImport_ImportModule("collections.abc")) &&
  722. (seq = PyObject_GetAttrString(collections, "MutableSequence")) &&
  723. (ret1 = PyObject_CallMethod(seq, "register", "O", type1)) &&
  724. (ret2 = PyObject_CallMethod(seq, "register", "O", type2));
  725. Py_XDECREF(collections);
  726. Py_XDECREF(seq);
  727. Py_XDECREF(ret1);
  728. Py_XDECREF(ret2);
  729. return ok;
  730. }
  731. bool PyUpb_Repeated_Init(PyObject* m) {
  732. PyUpb_ModuleState* state = PyUpb_ModuleState_GetFromModule(m);
  733. state->repeated_composite_container_type =
  734. PyUpb_AddClass(m, &PyUpb_RepeatedCompositeContainer_Spec);
  735. state->repeated_scalar_container_type =
  736. PyUpb_AddClass(m, &PyUpb_RepeatedScalarContainer_Spec);
  737. return state->repeated_composite_container_type &&
  738. state->repeated_scalar_container_type &&
  739. PyUpb_Repeated_RegisterAsSequence(state);
  740. }