33 #include <google/protobuf/pyext/map_container.h>
38 #include <google/protobuf/stubs/logging.h>
39 #include <google/protobuf/stubs/common.h>
40 #include <google/protobuf/map.h>
41 #include <google/protobuf/map_field.h>
42 #include <google/protobuf/message.h>
43 #include <google/protobuf/pyext/message.h>
44 #include <google/protobuf/pyext/message_factory.h>
45 #include <google/protobuf/pyext/repeated_composite_container.h>
46 #include <google/protobuf/pyext/scoped_pyobject_ptr.h>
47 #include <google/protobuf/stubs/map_util.h>
55 class MapReflectionFriend {
58 static PyObject*
Contains(PyObject* _self, PyObject*
key);
59 static Py_ssize_t
Length(PyObject* _self);
61 static PyObject*
IterNext(PyObject* _self);
62 static PyObject*
MergeFrom(PyObject* _self, PyObject*
arg);
76 std::unique_ptr<::google::protobuf::MapIterator>
iter;
109 Py_ssize_t value_len;
114 if (PyBytes_AsStringAndSize(py_string, &
value, &value_len) < 0) {
115 Py_DECREF(py_string);
118 stl_string->assign(
value, value_len);
119 Py_DECREF(py_string);
127 switch (field_descriptor->
cpp_type()) {
163 PyExc_SystemError,
"Type %d cannot be a map key",
173 switch (field_descriptor->
cpp_type()) {
175 return PyLong_FromLong(
key.GetInt32Value());
177 return PyLong_FromLongLong(
key.GetInt64Value());
179 return PyLong_FromSize_t(
key.GetUInt32Value());
181 return PyLong_FromUnsignedLongLong(
key.GetUInt64Value());
183 return PyBool_FromLong(
key.GetBoolValue());
188 PyExc_SystemError,
"Couldn't convert type %d to value",
199 switch (field_descriptor->
cpp_type()) {
201 return PyLong_FromLong(
value.GetInt32Value());
203 return PyLong_FromLongLong(
value.GetInt64Value());
205 return PyLong_FromSize_t(
value.GetUInt32Value());
207 return PyLong_FromUnsignedLongLong(
value.GetUInt64Value());
209 return PyFloat_FromDouble(
value.GetFloatValue());
211 return PyFloat_FromDouble(
value.GetDoubleValue());
213 return PyBool_FromLong(
value.GetBoolValue());
217 return PyLong_FromLong(
value.GetEnumValue());
220 PyExc_SystemError,
"Couldn't convert type %d to value",
229 bool allow_unknown_enum_values,
233 switch (field_descriptor->
cpp_type()) {
279 if (allow_unknown_enum_values) {
286 if (enum_value != NULL) {
290 PyErr_Format(PyExc_ValueError,
"Unknown enum value: %d",
value);
298 PyExc_SystemError,
"Setting value to a field of unknown type %d",
311 MapContainer*
self =
GetMap(_self);
314 self->parent_field_descriptor);
317 PyObject*
Clear(PyObject* _self) {
318 MapContainer*
self =
GetMap(_self);
320 const Reflection* reflection =
message->GetReflection();
322 reflection->ClearField(
message,
self->parent_field_descriptor);
328 MapContainer*
self =
GetMap(_self);
331 self->parent_field_descriptor->message_type());
332 Py_XINCREF(message_class);
333 return reinterpret_cast<PyObject*
>(message_class);
337 MapContainer*
self =
GetMap(_self);
340 PyErr_SetString(PyExc_AttributeError,
"Not a map field");
345 const Message* other_message = other_map->parent->message;
346 const Reflection* reflection =
message->GetReflection();
347 const Reflection* other_reflection = other_message->GetReflection();
348 internal::MapFieldBase*
field = reflection->MutableMapData(
350 const internal::MapFieldBase* other_field = other_reflection->GetMapData(
351 *other_message, other_map->parent_field_descriptor);
352 field->MergeFrom(*other_field);
358 MapContainer*
self =
GetMap(_self);
361 const Reflection* reflection =
message->GetReflection();
368 if (reflection->ContainsMapKey(*
message,
self->parent_field_descriptor,
386 PyErr_Format(PyExc_RuntimeError,
387 "Could not allocate new container.");
394 self->parent = parent;
395 self->parent_field_descriptor = parent_field_descriptor;
403 MapContainer*
self =
GetMap(_self);
406 const Reflection* reflection =
message->GetReflection();
414 if (reflection->InsertOrLookupMapValue(
message,
self->parent_field_descriptor,
424 MapContainer*
self =
GetMap(_self);
427 const Reflection* reflection =
message->GetReflection();
439 reflection->InsertOrLookupMapValue(
message,
self->parent_field_descriptor,
449 if (reflection->DeleteMapValue(
message,
self->parent_field_descriptor,
453 PyErr_Format(PyExc_KeyError,
"Key not present in map");
461 static const char* kwlist[] = {
"key",
"default",
nullptr};
463 PyObject* default_value = NULL;
464 if (!PyArg_ParseTupleAndKeywords(
args, kwargs,
"O|O",
465 const_cast<char**
>(kwlist), &
key,
471 if (is_present.
get() == NULL) {
475 if (PyObject_IsTrue(is_present.
get())) {
478 if (default_value != NULL) {
479 Py_INCREF(default_value);
480 return default_value;
495 MapContainer*
self =
GetMap(_self);
497 const Reflection* reflection =
message->GetReflection();
500 it != reflection->MapEnd(
message,
self->parent_field_descriptor);
510 if (PyDict_SetItem(dict.get(),
key.get(),
value.get()) < 0) {
514 return PyObject_Repr(dict.get());
519 self->RemoveFromParentCache();
521 type->tp_free(_self);
522 if (
type->tp_flags & Py_TPFLAGS_HEAPTYPE) {
530 "Tests whether a key is a member of the map."},
531 {
"clear", (PyCFunction)
Clear, METH_NOARGS,
532 "Removes all elements from the map."},
533 {
"get", (PyCFunction)
ScalarMapGet, METH_VARARGS | METH_KEYWORDS,
534 "Gets the value for the given key if present, or otherwise a default"},
536 "Return the class used to build Entries of (key, value) pairs."},
538 "Merges a map into the current map."},
573 ->BuildSubMessageFromPointer(
self->parent_field_descriptor,
message,
580 CMessageClass* message_class) {
587 PyErr_SetString(PyExc_RuntimeError,
"Could not allocate new container.");
594 self->parent = parent;
595 self->parent_field_descriptor = parent_field_descriptor;
598 Py_INCREF(message_class);
599 self->message_class = message_class;
607 PyErr_Format(PyExc_ValueError,
608 "Direct assignment of submessage not allowed");
616 const Reflection* reflection =
message->GetReflection();
627 if (reflection->ContainsMapKey(*
message,
self->parent_field_descriptor,
631 reflection->InsertOrLookupMapValue(
message,
self->parent_field_descriptor,
637 self->parent->MaybeReleaseSubMessage(sub_message)) {
639 released->message =
msg->New();
640 msg->GetReflection()->Swap(
msg, released->message);
644 reflection->DeleteMapValue(
message,
self->parent_field_descriptor,
648 PyErr_Format(PyExc_KeyError,
"Key not present in map");
658 const Reflection* reflection =
message->GetReflection();
666 if (reflection->InsertOrLookupMapValue(
message,
self->parent_field_descriptor,
684 const Reflection* reflection =
message->GetReflection();
687 it != reflection->MapEnd(
message,
self->parent_field_descriptor);
697 if (PyDict_SetItem(dict.get(),
key.get(),
value.get()) < 0) {
701 return PyObject_Repr(dict.get());
705 static const char* kwlist[] = {
"key",
"default",
nullptr};
707 PyObject* default_value = NULL;
708 if (!PyArg_ParseTupleAndKeywords(
args, kwargs,
"O|O",
709 const_cast<char**
>(kwlist), &
key,
715 if (is_present.get() == NULL) {
719 if (PyObject_IsTrue(is_present.get())) {
722 if (default_value != NULL) {
723 Py_INCREF(default_value);
724 return default_value;
733 self->RemoveFromParentCache();
734 Py_DECREF(
self->message_class);
736 type->tp_free(_self);
737 if (
type->tp_flags & Py_TPFLAGS_HEAPTYPE) {
745 "Tests whether the map contains this element."},
746 {
"clear", (PyCFunction)
Clear, METH_NOARGS,
747 "Removes all elements from the map."},
748 {
"get", (PyCFunction)
MessageMapGet, METH_VARARGS | METH_KEYWORDS,
749 "Gets the value for the given key if present, or otherwise a default"},
751 "Alias for getitem, useful to make explicit that the map is mutated."},
753 "Return the class used to build Entries of (key, value) pairs."},
755 "Merges a map into the current map."},
787 MapContainer*
self =
GetMap(_self);
791 return PyErr_Format(PyExc_KeyError,
"Could not allocate iterator");
797 iter->container =
self;
798 iter->version =
self->version;
799 Py_INCREF(
self->parent);
800 iter->parent =
self->parent;
804 const Reflection* reflection =
message->GetReflection();
806 iter->iter.reset(new ::google::protobuf::MapIterator(
807 reflection->MapBegin(
message,
self->parent_field_descriptor)));
810 return obj.release();
814 MapIterator*
self =
GetIter(_self);
818 if (
self->version !=
self->container->version) {
819 return PyErr_Format(PyExc_RuntimeError,
820 "Map modified during iteration.");
822 if (
self->parent !=
self->container->parent) {
823 return PyErr_Format(PyExc_RuntimeError,
824 "Map cleared during iteration.");
827 if (
self->iter.get() == NULL) {
832 const Reflection* reflection =
message->GetReflection();
835 reflection->MapEnd(
message,
self->container->parent_field_descriptor)) {
849 Py_CLEAR(
self->container);
850 Py_CLEAR(
self->parent);
851 Py_TYPE(_self)->tp_free(_self);
901 PyObject_GetAttrString(abc.get(),
"MutableMapping"));
902 if (mutable_mapping == NULL) {
906 Py_INCREF(mutable_mapping.get());