1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7
8 // Author: anuraag@google.com (Anuraag Agrawal)
9 // Author: tibell@google.com (Johan Tibell)
10
11 #include "google/protobuf/pyext/repeated_scalar_container.h"
12
13 #include <cstdint>
14 #include <memory>
15 #include <string>
16
17 #include "google/protobuf/stubs/common.h"
18 #include "google/protobuf/descriptor.h"
19 #include "google/protobuf/dynamic_message.h"
20 #include "google/protobuf/message.h"
21 #include "google/protobuf/pyext/descriptor.h"
22 #include "google/protobuf/pyext/descriptor_pool.h"
23 #include "google/protobuf/pyext/message.h"
24 #include "google/protobuf/pyext/scoped_pyobject_ptr.h"
25
26 #define PyString_AsString(ob) \
27 (PyUnicode_Check(ob) ? PyUnicode_AsUTF8(ob) : PyBytes_AsString(ob))
28
29 namespace google {
30 namespace protobuf {
31 namespace python {
32
33 namespace repeated_scalar_container {
34
InternalAssignRepeatedField(RepeatedScalarContainer * self,PyObject * list)35 static int InternalAssignRepeatedField(RepeatedScalarContainer* self,
36 PyObject* list) {
37 cmessage::AssureWritable(self->parent);
38 Message* message = self->parent->message;
39 message->GetReflection()->ClearField(message, self->parent_field_descriptor);
40 for (Py_ssize_t i = 0; i < PyList_GET_SIZE(list); ++i) {
41 PyObject* value = PyList_GET_ITEM(list, i);
42 if (ScopedPyObjectPtr(Append(self, value)) == nullptr) {
43 return -1;
44 }
45 }
46 return 0;
47 }
48
Len(PyObject * pself)49 static Py_ssize_t Len(PyObject* pself) {
50 RepeatedScalarContainer* self =
51 reinterpret_cast<RepeatedScalarContainer*>(pself);
52 Message* message = self->parent->message;
53 return message->GetReflection()->FieldSize(*message,
54 self->parent_field_descriptor);
55 }
56
AssignItem(PyObject * pself,Py_ssize_t index,PyObject * arg)57 static int AssignItem(PyObject* pself, Py_ssize_t index, PyObject* arg) {
58 RepeatedScalarContainer* self =
59 reinterpret_cast<RepeatedScalarContainer*>(pself);
60
61 cmessage::AssureWritable(self->parent);
62 Message* message = self->parent->message;
63 const FieldDescriptor* field_descriptor = self->parent_field_descriptor;
64
65 const Reflection* reflection = message->GetReflection();
66 int field_size = reflection->FieldSize(*message, field_descriptor);
67 if (index < 0) {
68 index = field_size + index;
69 }
70 if (index < 0 || index >= field_size) {
71 PyErr_Format(PyExc_IndexError, "list assignment index (%d) out of range",
72 static_cast<int>(index));
73 return -1;
74 }
75
76 if (arg == nullptr) {
77 ScopedPyObjectPtr py_index(PyLong_FromLong(index));
78 return cmessage::DeleteRepeatedField(self->parent, field_descriptor,
79 py_index.get());
80 }
81
82 if (PySequence_Check(arg) && !(PyBytes_Check(arg) || PyUnicode_Check(arg))) {
83 PyErr_SetString(PyExc_TypeError, "Value must be scalar");
84 return -1;
85 }
86
87 switch (field_descriptor->cpp_type()) {
88 case FieldDescriptor::CPPTYPE_INT32: {
89 PROTOBUF_CHECK_GET_INT32(arg, value, -1);
90 reflection->SetRepeatedInt32(message, field_descriptor, index, value);
91 break;
92 }
93 case FieldDescriptor::CPPTYPE_INT64: {
94 PROTOBUF_CHECK_GET_INT64(arg, value, -1);
95 reflection->SetRepeatedInt64(message, field_descriptor, index, value);
96 break;
97 }
98 case FieldDescriptor::CPPTYPE_UINT32: {
99 PROTOBUF_CHECK_GET_UINT32(arg, value, -1);
100 reflection->SetRepeatedUInt32(message, field_descriptor, index, value);
101 break;
102 }
103 case FieldDescriptor::CPPTYPE_UINT64: {
104 PROTOBUF_CHECK_GET_UINT64(arg, value, -1);
105 reflection->SetRepeatedUInt64(message, field_descriptor, index, value);
106 break;
107 }
108 case FieldDescriptor::CPPTYPE_FLOAT: {
109 PROTOBUF_CHECK_GET_FLOAT(arg, value, -1);
110 reflection->SetRepeatedFloat(message, field_descriptor, index, value);
111 break;
112 }
113 case FieldDescriptor::CPPTYPE_DOUBLE: {
114 PROTOBUF_CHECK_GET_DOUBLE(arg, value, -1);
115 reflection->SetRepeatedDouble(message, field_descriptor, index, value);
116 break;
117 }
118 case FieldDescriptor::CPPTYPE_BOOL: {
119 PROTOBUF_CHECK_GET_BOOL(arg, value, -1);
120 reflection->SetRepeatedBool(message, field_descriptor, index, value);
121 break;
122 }
123 case FieldDescriptor::CPPTYPE_STRING: {
124 if (!CheckAndSetString(arg, message, field_descriptor, reflection, false,
125 index)) {
126 return -1;
127 }
128 break;
129 }
130 case FieldDescriptor::CPPTYPE_ENUM: {
131 PROTOBUF_CHECK_GET_INT32(arg, value, -1);
132 if (!field_descriptor->legacy_enum_field_treated_as_closed()) {
133 reflection->SetRepeatedEnumValue(message, field_descriptor, index,
134 value);
135 } else {
136 const EnumDescriptor* enum_descriptor = field_descriptor->enum_type();
137 const EnumValueDescriptor* enum_value =
138 enum_descriptor->FindValueByNumber(value);
139 if (enum_value != nullptr) {
140 reflection->SetRepeatedEnum(message, field_descriptor, index,
141 enum_value);
142 } else {
143 ScopedPyObjectPtr s(PyObject_Str(arg));
144 if (s != nullptr) {
145 PyErr_Format(PyExc_ValueError, "Unknown enum value: %s",
146 PyString_AsString(s.get()));
147 }
148 return -1;
149 }
150 }
151 break;
152 }
153 default:
154 PyErr_Format(PyExc_SystemError,
155 "Adding value to a field of unknown type %d",
156 field_descriptor->cpp_type());
157 return -1;
158 }
159 return 0;
160 }
161
Item(PyObject * pself,Py_ssize_t index)162 static PyObject* Item(PyObject* pself, Py_ssize_t index) {
163 RepeatedScalarContainer* self =
164 reinterpret_cast<RepeatedScalarContainer*>(pself);
165
166 Message* message = self->parent->message;
167 const FieldDescriptor* field_descriptor = self->parent_field_descriptor;
168 const Reflection* reflection = message->GetReflection();
169
170 int field_size = reflection->FieldSize(*message, field_descriptor);
171 if (index < 0) {
172 index = field_size + index;
173 }
174 if (index < 0 || index >= field_size) {
175 PyErr_Format(PyExc_IndexError, "list index (%zd) out of range", index);
176 return nullptr;
177 }
178
179 PyObject* result = nullptr;
180 switch (field_descriptor->cpp_type()) {
181 case FieldDescriptor::CPPTYPE_INT32: {
182 int32_t value =
183 reflection->GetRepeatedInt32(*message, field_descriptor, index);
184 result = PyLong_FromLong(value);
185 break;
186 }
187 case FieldDescriptor::CPPTYPE_INT64: {
188 int64_t value =
189 reflection->GetRepeatedInt64(*message, field_descriptor, index);
190 result = PyLong_FromLongLong(value);
191 break;
192 }
193 case FieldDescriptor::CPPTYPE_UINT32: {
194 uint32_t value =
195 reflection->GetRepeatedUInt32(*message, field_descriptor, index);
196 result = PyLong_FromLongLong(value);
197 break;
198 }
199 case FieldDescriptor::CPPTYPE_UINT64: {
200 uint64_t value =
201 reflection->GetRepeatedUInt64(*message, field_descriptor, index);
202 result = PyLong_FromUnsignedLongLong(value);
203 break;
204 }
205 case FieldDescriptor::CPPTYPE_FLOAT: {
206 float value =
207 reflection->GetRepeatedFloat(*message, field_descriptor, index);
208 result = PyFloat_FromDouble(value);
209 break;
210 }
211 case FieldDescriptor::CPPTYPE_DOUBLE: {
212 double value =
213 reflection->GetRepeatedDouble(*message, field_descriptor, index);
214 result = PyFloat_FromDouble(value);
215 break;
216 }
217 case FieldDescriptor::CPPTYPE_BOOL: {
218 bool value =
219 reflection->GetRepeatedBool(*message, field_descriptor, index);
220 result = PyBool_FromLong(value ? 1 : 0);
221 break;
222 }
223 case FieldDescriptor::CPPTYPE_ENUM: {
224 const EnumValueDescriptor* enum_value =
225 message->GetReflection()->GetRepeatedEnum(*message, field_descriptor,
226 index);
227 result = PyLong_FromLong(enum_value->number());
228 break;
229 }
230 case FieldDescriptor::CPPTYPE_STRING: {
231 std::string scratch;
232 const std::string& value = reflection->GetRepeatedStringReference(
233 *message, field_descriptor, index, &scratch);
234 result = ToStringObject(field_descriptor, value);
235 break;
236 }
237 default:
238 PyErr_Format(PyExc_SystemError,
239 "Getting value from a repeated field of unknown type %d",
240 field_descriptor->cpp_type());
241 }
242
243 return result;
244 }
245
Subscript(PyObject * pself,PyObject * slice)246 static PyObject* Subscript(PyObject* pself, PyObject* slice) {
247 Py_ssize_t from;
248 Py_ssize_t to;
249 Py_ssize_t step;
250 Py_ssize_t length;
251 Py_ssize_t slicelength;
252 bool return_list = false;
253 if (PyLong_Check(slice)) {
254 from = to = PyLong_AsLong(slice);
255 } else if (PyIndex_Check(slice)) {
256 from = to = PyNumber_AsSsize_t(slice, PyExc_ValueError);
257 if (from == -1 && PyErr_Occurred()) {
258 return nullptr;
259 }
260 } else if (PySlice_Check(slice)) {
261 length = Len(pself);
262 if (PySlice_GetIndicesEx(slice, length, &from, &to, &step, &slicelength) ==
263 -1) {
264 return nullptr;
265 }
266 return_list = true;
267 } else {
268 PyErr_SetString(PyExc_TypeError, "list indices must be integers");
269 return nullptr;
270 }
271
272 if (!return_list) {
273 return Item(pself, from);
274 }
275
276 PyObject* list = PyList_New(0);
277 if (list == nullptr) {
278 return nullptr;
279 }
280 if (from <= to) {
281 if (step < 0) {
282 return list;
283 }
284 for (Py_ssize_t index = from; index < to; index += step) {
285 if (index < 0 || index >= length) {
286 break;
287 }
288 ScopedPyObjectPtr s(Item(pself, index));
289 PyList_Append(list, s.get());
290 }
291 } else {
292 if (step > 0) {
293 return list;
294 }
295 for (Py_ssize_t index = from; index > to; index += step) {
296 if (index < 0 || index >= length) {
297 break;
298 }
299 ScopedPyObjectPtr s(Item(pself, index));
300 PyList_Append(list, s.get());
301 }
302 }
303 return list;
304 }
305
Append(RepeatedScalarContainer * self,PyObject * item)306 PyObject* Append(RepeatedScalarContainer* self, PyObject* item) {
307 cmessage::AssureWritable(self->parent);
308 Message* message = self->parent->message;
309 const FieldDescriptor* field_descriptor = self->parent_field_descriptor;
310
311 const Reflection* reflection = message->GetReflection();
312 switch (field_descriptor->cpp_type()) {
313 case FieldDescriptor::CPPTYPE_INT32: {
314 PROTOBUF_CHECK_GET_INT32(item, value, nullptr);
315 reflection->AddInt32(message, field_descriptor, value);
316 break;
317 }
318 case FieldDescriptor::CPPTYPE_INT64: {
319 PROTOBUF_CHECK_GET_INT64(item, value, nullptr);
320 reflection->AddInt64(message, field_descriptor, value);
321 break;
322 }
323 case FieldDescriptor::CPPTYPE_UINT32: {
324 PROTOBUF_CHECK_GET_UINT32(item, value, nullptr);
325 reflection->AddUInt32(message, field_descriptor, value);
326 break;
327 }
328 case FieldDescriptor::CPPTYPE_UINT64: {
329 PROTOBUF_CHECK_GET_UINT64(item, value, nullptr);
330 reflection->AddUInt64(message, field_descriptor, value);
331 break;
332 }
333 case FieldDescriptor::CPPTYPE_FLOAT: {
334 PROTOBUF_CHECK_GET_FLOAT(item, value, nullptr);
335 reflection->AddFloat(message, field_descriptor, value);
336 break;
337 }
338 case FieldDescriptor::CPPTYPE_DOUBLE: {
339 PROTOBUF_CHECK_GET_DOUBLE(item, value, nullptr);
340 reflection->AddDouble(message, field_descriptor, value);
341 break;
342 }
343 case FieldDescriptor::CPPTYPE_BOOL: {
344 PROTOBUF_CHECK_GET_BOOL(item, value, nullptr);
345 reflection->AddBool(message, field_descriptor, value);
346 break;
347 }
348 case FieldDescriptor::CPPTYPE_STRING: {
349 if (!CheckAndSetString(item, message, field_descriptor, reflection, true,
350 -1)) {
351 return nullptr;
352 }
353 break;
354 }
355 case FieldDescriptor::CPPTYPE_ENUM: {
356 PROTOBUF_CHECK_GET_INT32(item, value, nullptr);
357 if (!field_descriptor->legacy_enum_field_treated_as_closed()) {
358 reflection->AddEnumValue(message, field_descriptor, value);
359 } else {
360 const EnumDescriptor* enum_descriptor = field_descriptor->enum_type();
361 const EnumValueDescriptor* enum_value =
362 enum_descriptor->FindValueByNumber(value);
363 if (enum_value != nullptr) {
364 reflection->AddEnum(message, field_descriptor, enum_value);
365 } else {
366 ScopedPyObjectPtr s(PyObject_Str(item));
367 if (s != nullptr) {
368 PyErr_Format(PyExc_ValueError, "Unknown enum value: %s",
369 PyString_AsString(s.get()));
370 }
371 return nullptr;
372 }
373 }
374 break;
375 }
376 default:
377 PyErr_Format(PyExc_SystemError,
378 "Adding value to a field of unknown type %d",
379 field_descriptor->cpp_type());
380 return nullptr;
381 }
382
383 Py_RETURN_NONE;
384 }
385
AppendMethod(PyObject * self,PyObject * item)386 static PyObject* AppendMethod(PyObject* self, PyObject* item) {
387 return Append(reinterpret_cast<RepeatedScalarContainer*>(self), item);
388 }
389
AssSubscript(PyObject * pself,PyObject * slice,PyObject * value)390 static int AssSubscript(PyObject* pself, PyObject* slice, PyObject* value) {
391 RepeatedScalarContainer* self =
392 reinterpret_cast<RepeatedScalarContainer*>(pself);
393
394 Py_ssize_t from;
395 Py_ssize_t to;
396 Py_ssize_t step;
397 Py_ssize_t length;
398 Py_ssize_t slicelength;
399 bool create_list = false;
400
401 cmessage::AssureWritable(self->parent);
402 Message* message = self->parent->message;
403 const FieldDescriptor* field_descriptor = self->parent_field_descriptor;
404
405 if (PyLong_Check(slice)) {
406 from = to = PyLong_AsLong(slice);
407 } else if (PySlice_Check(slice)) {
408 const Reflection* reflection = message->GetReflection();
409 length = reflection->FieldSize(*message, field_descriptor);
410 if (PySlice_GetIndicesEx(slice, length, &from, &to, &step, &slicelength) ==
411 -1) {
412 return -1;
413 }
414 create_list = true;
415 } else {
416 PyErr_SetString(PyExc_TypeError, "list indices must be integers");
417 return -1;
418 }
419
420 if (value == nullptr) {
421 return cmessage::DeleteRepeatedField(self->parent, field_descriptor, slice);
422 }
423
424 if (!create_list) {
425 return AssignItem(pself, from, value);
426 }
427
428 ScopedPyObjectPtr full_slice(PySlice_New(nullptr, nullptr, nullptr));
429 if (full_slice == nullptr) {
430 return -1;
431 }
432 ScopedPyObjectPtr new_list(Subscript(pself, full_slice.get()));
433 if (new_list == nullptr) {
434 return -1;
435 }
436 if (PySequence_SetSlice(new_list.get(), from, to, value) < 0) {
437 return -1;
438 }
439
440 return InternalAssignRepeatedField(self, new_list.get());
441 }
442
Extend(RepeatedScalarContainer * self,PyObject * value)443 PyObject* Extend(RepeatedScalarContainer* self, PyObject* value) {
444 cmessage::AssureWritable(self->parent);
445
446 ScopedPyObjectPtr iter(PyObject_GetIter(value));
447 if (iter == nullptr) {
448 PyErr_SetString(PyExc_TypeError, "Value must be iterable");
449 return nullptr;
450 }
451 ScopedPyObjectPtr next;
452 while ((next.reset(PyIter_Next(iter.get()))) != nullptr) {
453 if (ScopedPyObjectPtr(Append(self, next.get())) == nullptr) {
454 return nullptr;
455 }
456 }
457 if (PyErr_Occurred()) {
458 return nullptr;
459 }
460 Py_RETURN_NONE;
461 }
462
Insert(PyObject * pself,PyObject * args)463 static PyObject* Insert(PyObject* pself, PyObject* args) {
464 RepeatedScalarContainer* self =
465 reinterpret_cast<RepeatedScalarContainer*>(pself);
466
467 Py_ssize_t index;
468 PyObject* value;
469 if (!PyArg_ParseTuple(args, "lO", &index, &value)) {
470 return nullptr;
471 }
472 ScopedPyObjectPtr full_slice(PySlice_New(nullptr, nullptr, nullptr));
473 ScopedPyObjectPtr new_list(Subscript(pself, full_slice.get()));
474 if (PyList_Insert(new_list.get(), index, value) < 0) {
475 return nullptr;
476 }
477 int ret = InternalAssignRepeatedField(self, new_list.get());
478 if (ret < 0) {
479 return nullptr;
480 }
481 Py_RETURN_NONE;
482 }
483
Remove(PyObject * pself,PyObject * value)484 static PyObject* Remove(PyObject* pself, PyObject* value) {
485 Py_ssize_t match_index = -1;
486 for (Py_ssize_t i = 0; i < Len(pself); ++i) {
487 ScopedPyObjectPtr elem(Item(pself, i));
488 if (PyObject_RichCompareBool(elem.get(), value, Py_EQ)) {
489 match_index = i;
490 break;
491 }
492 }
493 if (match_index == -1) {
494 PyErr_SetString(PyExc_ValueError, "remove(x): x not in container");
495 return nullptr;
496 }
497 if (AssignItem(pself, match_index, nullptr) < 0) {
498 return nullptr;
499 }
500 Py_RETURN_NONE;
501 }
502
ExtendMethod(PyObject * self,PyObject * value)503 static PyObject* ExtendMethod(PyObject* self, PyObject* value) {
504 return Extend(reinterpret_cast<RepeatedScalarContainer*>(self), value);
505 }
506
RichCompare(PyObject * pself,PyObject * other,int opid)507 static PyObject* RichCompare(PyObject* pself, PyObject* other, int opid) {
508 if (opid != Py_EQ && opid != Py_NE) {
509 Py_INCREF(Py_NotImplemented);
510 return Py_NotImplemented;
511 }
512
513 // Copy the contents of this repeated scalar container, and other if it is
514 // also a repeated scalar container, into Python lists so we can delegate
515 // to the list's compare method.
516
517 ScopedPyObjectPtr full_slice(PySlice_New(nullptr, nullptr, nullptr));
518 if (full_slice == nullptr) {
519 return nullptr;
520 }
521
522 ScopedPyObjectPtr other_list_deleter;
523 if (PyObject_TypeCheck(other, &RepeatedScalarContainer_Type)) {
524 other_list_deleter.reset(Subscript(other, full_slice.get()));
525 other = other_list_deleter.get();
526 }
527
528 ScopedPyObjectPtr list(Subscript(pself, full_slice.get()));
529 if (list == nullptr) {
530 return nullptr;
531 }
532 return PyObject_RichCompare(list.get(), other, opid);
533 }
534
Reduce(PyObject * unused_self,PyObject * unused_other)535 PyObject* Reduce(PyObject* unused_self, PyObject* unused_other) {
536 PyErr_Format(PickleError_class,
537 "can't pickle repeated message fields, convert to list first");
538 return nullptr;
539 }
540
Sort(PyObject * pself,PyObject * args,PyObject * kwds)541 static PyObject* Sort(PyObject* pself, PyObject* args, PyObject* kwds) {
542 // Support the old sort_function argument for backwards
543 // compatibility.
544 if (kwds != nullptr) {
545 PyObject* sort_func = PyDict_GetItemString(kwds, "sort_function");
546 if (sort_func != nullptr) {
547 // Must set before deleting as sort_func is a borrowed reference
548 // and kwds might be the only thing keeping it alive.
549 if (PyDict_SetItemString(kwds, "cmp", sort_func) == -1) return nullptr;
550 if (PyDict_DelItemString(kwds, "sort_function") == -1) return nullptr;
551 }
552 }
553
554 ScopedPyObjectPtr full_slice(PySlice_New(nullptr, nullptr, nullptr));
555 if (full_slice == nullptr) {
556 return nullptr;
557 }
558 ScopedPyObjectPtr list(Subscript(pself, full_slice.get()));
559 if (list == nullptr) {
560 return nullptr;
561 }
562 if (PyList_GET_SIZE(list.get()) == 0) {
563 Py_RETURN_NONE;
564 }
565 ScopedPyObjectPtr m(PyObject_GetAttrString(list.get(), "sort"));
566 if (m == nullptr) {
567 return nullptr;
568 }
569 ScopedPyObjectPtr res(PyObject_Call(m.get(), args, kwds));
570 if (res == nullptr) {
571 return nullptr;
572 }
573 int ret = InternalAssignRepeatedField(
574 reinterpret_cast<RepeatedScalarContainer*>(pself), list.get());
575 if (ret < 0) {
576 return nullptr;
577 }
578 Py_RETURN_NONE;
579 }
580
Reverse(PyObject * pself)581 static PyObject* Reverse(PyObject* pself) {
582 ScopedPyObjectPtr full_slice(PySlice_New(nullptr, nullptr, nullptr));
583 if (full_slice == nullptr) {
584 return nullptr;
585 }
586 ScopedPyObjectPtr list(Subscript(pself, full_slice.get()));
587 if (list == nullptr) {
588 return nullptr;
589 }
590 ScopedPyObjectPtr res(PyObject_CallMethod(list.get(), "reverse", nullptr));
591 if (res == nullptr) {
592 return nullptr;
593 }
594 int ret = InternalAssignRepeatedField(
595 reinterpret_cast<RepeatedScalarContainer*>(pself), list.get());
596 if (ret < 0) {
597 return nullptr;
598 }
599 Py_RETURN_NONE;
600 }
601
Pop(PyObject * pself,PyObject * args)602 static PyObject* Pop(PyObject* pself, PyObject* args) {
603 Py_ssize_t index = -1;
604 if (!PyArg_ParseTuple(args, "|n", &index)) {
605 return nullptr;
606 }
607 PyObject* item = Item(pself, index);
608 if (item == nullptr) {
609 PyErr_Format(PyExc_IndexError, "list index (%zd) out of range", index);
610 return nullptr;
611 }
612 if (AssignItem(pself, index, nullptr) < 0) {
613 return nullptr;
614 }
615 return item;
616 }
617
ToStr(PyObject * pself)618 static PyObject* ToStr(PyObject* pself) {
619 ScopedPyObjectPtr full_slice(PySlice_New(nullptr, nullptr, nullptr));
620 if (full_slice == nullptr) {
621 return nullptr;
622 }
623 ScopedPyObjectPtr list(Subscript(pself, full_slice.get()));
624 if (list == nullptr) {
625 return nullptr;
626 }
627 return PyObject_Repr(list.get());
628 }
629
MergeFrom(PyObject * pself,PyObject * arg)630 static PyObject* MergeFrom(PyObject* pself, PyObject* arg) {
631 return Extend(reinterpret_cast<RepeatedScalarContainer*>(pself), arg);
632 }
633
634 // The private constructor of RepeatedScalarContainer objects.
NewContainer(CMessage * parent,const FieldDescriptor * parent_field_descriptor)635 RepeatedScalarContainer* NewContainer(
636 CMessage* parent, const FieldDescriptor* parent_field_descriptor) {
637 if (!CheckFieldBelongsToMessage(parent_field_descriptor, parent->message)) {
638 return nullptr;
639 }
640
641 RepeatedScalarContainer* self = reinterpret_cast<RepeatedScalarContainer*>(
642 PyType_GenericAlloc(&RepeatedScalarContainer_Type, 0));
643 if (self == nullptr) {
644 return nullptr;
645 }
646
647 Py_INCREF(parent);
648 self->parent = parent;
649 self->parent_field_descriptor = parent_field_descriptor;
650
651 return self;
652 }
653
DeepCopy(PyObject * pself,PyObject * arg)654 PyObject* DeepCopy(PyObject* pself, PyObject* arg) {
655 return reinterpret_cast<RepeatedScalarContainer*>(pself)->DeepCopy();
656 }
657
Dealloc(PyObject * pself)658 static void Dealloc(PyObject* pself) {
659 reinterpret_cast<RepeatedScalarContainer*>(pself)->RemoveFromParentCache();
660 Py_TYPE(pself)->tp_free(pself);
661 }
662
663 static PySequenceMethods SqMethods = {
664 Len, /* sq_length */
665 nullptr, /* sq_concat */
666 nullptr, /* sq_repeat */
667 Item, /* sq_item */
668 nullptr, /* sq_slice */
669 AssignItem /* sq_ass_item */
670 };
671
672 static PyMappingMethods MpMethods = {
673 Len, /* mp_length */
674 Subscript, /* mp_subscript */
675 AssSubscript, /* mp_ass_subscript */
676 };
677
678 static PyMethodDef Methods[] = {
679 {"__deepcopy__", DeepCopy, METH_VARARGS, "Makes a deep copy of the class."},
680 {"__reduce__", Reduce, METH_NOARGS,
681 "Outputs picklable representation of the repeated field."},
682 {"append", AppendMethod, METH_O,
683 "Appends an object to the repeated container."},
684 {"extend", ExtendMethod, METH_O,
685 "Appends objects to the repeated container."},
686 {"insert", Insert, METH_VARARGS,
687 "Inserts an object at the specified position in the container."},
688 {"pop", Pop, METH_VARARGS,
689 "Removes an object from the repeated container and returns it."},
690 {"remove", Remove, METH_O,
691 "Removes an object from the repeated container."},
692 {"sort", reinterpret_cast<PyCFunction>(Sort), METH_VARARGS | METH_KEYWORDS,
693 "Sorts the repeated container."},
694 {"reverse", reinterpret_cast<PyCFunction>(Reverse), METH_NOARGS,
695 "Reverses elements order of the repeated container."},
696 {"MergeFrom", static_cast<PyCFunction>(MergeFrom), METH_O,
697 "Merges a repeated container into the current container."},
698 {nullptr, nullptr}};
699
700 } // namespace repeated_scalar_container
701
702 PyTypeObject RepeatedScalarContainer_Type = {
703 PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME
704 ".RepeatedScalarContainer", // tp_name
705 sizeof(RepeatedScalarContainer), // tp_basicsize
706 0, // tp_itemsize
707 repeated_scalar_container::Dealloc, // tp_dealloc
708 #if PY_VERSION_HEX >= 0x03080000
709 0, // tp_vectorcall_offset
710 #else
711 nullptr, // tp_print
712 #endif
713 nullptr, // tp_getattr
714 nullptr, // tp_setattr
715 nullptr, // tp_compare
716 repeated_scalar_container::ToStr, // tp_repr
717 nullptr, // tp_as_number
718 &repeated_scalar_container::SqMethods, // tp_as_sequence
719 &repeated_scalar_container::MpMethods, // tp_as_mapping
720 PyObject_HashNotImplemented, // tp_hash
721 nullptr, // tp_call
722 nullptr, // tp_str
723 nullptr, // tp_getattro
724 nullptr, // tp_setattro
725 nullptr, // tp_as_buffer
726 #if PY_VERSION_HEX >= 0x030A0000
727 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_SEQUENCE, // tp_flags
728 #else
729 Py_TPFLAGS_DEFAULT, // tp_flags
730 #endif
731 "A Repeated scalar container", // tp_doc
732 nullptr, // tp_traverse
733 nullptr, // tp_clear
734 repeated_scalar_container::RichCompare, // tp_richcompare
735 0, // tp_weaklistoffset
736 nullptr, // tp_iter
737 nullptr, // tp_iternext
738 repeated_scalar_container::Methods, // tp_methods
739 nullptr, // tp_members
740 nullptr, // tp_getset
741 nullptr, // tp_base
742 nullptr, // tp_dict
743 nullptr, // tp_descr_get
744 nullptr, // tp_descr_set
745 0, // tp_dictoffset
746 nullptr, // tp_init
747 };
748
749 } // namespace python
750 } // namespace protobuf
751 } // namespace google
752