map_container.cc 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056
  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 Google Inc. All rights reserved.
  3. // https://developers.google.com/protocol-buffers/
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above
  12. // copyright notice, this list of conditions and the following disclaimer
  13. // in the documentation and/or other materials provided with the
  14. // distribution.
  15. // * Neither the name of Google Inc. nor the names of its
  16. // contributors may be used to endorse or promote products derived from
  17. // this software without specific prior written permission.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. // Author: haberman@google.com (Josh Haberman)
  31. #include <google/protobuf/pyext/map_container.h>
  32. #include <memory>
  33. #include <google/protobuf/stubs/logging.h>
  34. #include <google/protobuf/stubs/common.h>
  35. #include <google/protobuf/map_field.h>
  36. #include <google/protobuf/map.h>
  37. #include <google/protobuf/message.h>
  38. #include <google/protobuf/pyext/message_factory.h>
  39. #include <google/protobuf/pyext/message.h>
  40. #include <google/protobuf/pyext/repeated_composite_container.h>
  41. #include <google/protobuf/pyext/scoped_pyobject_ptr.h>
  42. #include <google/protobuf/stubs/map_util.h>
  43. #if PY_MAJOR_VERSION >= 3
  44. #define PyInt_FromLong PyLong_FromLong
  45. #define PyInt_FromSize_t PyLong_FromSize_t
  46. #endif
  47. namespace google {
  48. namespace protobuf {
  49. namespace python {
  50. // Functions that need access to map reflection functionality.
  51. // They need to be contained in this class because it is friended.
  52. class MapReflectionFriend {
  53. public:
  54. // Methods that are in common between the map types.
  55. static PyObject* Contains(PyObject* _self, PyObject* key);
  56. static Py_ssize_t Length(PyObject* _self);
  57. static PyObject* GetIterator(PyObject *_self);
  58. static PyObject* IterNext(PyObject* _self);
  59. static PyObject* MergeFrom(PyObject* _self, PyObject* arg);
  60. // Methods that differ between the map types.
  61. static PyObject* ScalarMapGetItem(PyObject* _self, PyObject* key);
  62. static PyObject* MessageMapGetItem(PyObject* _self, PyObject* key);
  63. static int ScalarMapSetItem(PyObject* _self, PyObject* key, PyObject* v);
  64. static int MessageMapSetItem(PyObject* _self, PyObject* key, PyObject* v);
  65. static PyObject* ScalarMapToStr(PyObject* _self);
  66. static PyObject* MessageMapToStr(PyObject* _self);
  67. };
  68. struct MapIterator {
  69. PyObject_HEAD;
  70. std::unique_ptr<::google::protobuf::MapIterator> iter;
  71. // A pointer back to the container, so we can notice changes to the version.
  72. // We own a ref on this.
  73. MapContainer* container;
  74. // We need to keep a ref on the parent Message too, because
  75. // MapIterator::~MapIterator() accesses it. Normally this would be ok because
  76. // the ref on container (above) would guarantee outlive semantics. However in
  77. // the case of ClearField(), the MapContainer points to a different message,
  78. // a copy of the original. But our iterator still points to the original,
  79. // which could now get deleted before us.
  80. //
  81. // To prevent this, we ensure that the Message will always stay alive as long
  82. // as this iterator does. This is solely for the benefit of the MapIterator
  83. // destructor -- we should never actually access the iterator in this state
  84. // except to delete it.
  85. CMessage* parent;
  86. // The version of the map when we took the iterator to it.
  87. //
  88. // We store this so that if the map is modified during iteration we can throw
  89. // an error.
  90. uint64 version;
  91. };
  92. Message* MapContainer::GetMutableMessage() {
  93. cmessage::AssureWritable(parent);
  94. return parent->message;
  95. }
  96. // Consumes a reference on the Python string object.
  97. static bool PyStringToSTL(PyObject* py_string, std::string* stl_string) {
  98. char *value;
  99. Py_ssize_t value_len;
  100. if (!py_string) {
  101. return false;
  102. }
  103. if (PyBytes_AsStringAndSize(py_string, &value, &value_len) < 0) {
  104. Py_DECREF(py_string);
  105. return false;
  106. } else {
  107. stl_string->assign(value, value_len);
  108. Py_DECREF(py_string);
  109. return true;
  110. }
  111. }
  112. static bool PythonToMapKey(MapContainer* self, PyObject* obj, MapKey* key) {
  113. const FieldDescriptor* field_descriptor =
  114. self->parent_field_descriptor->message_type()->map_key();
  115. switch (field_descriptor->cpp_type()) {
  116. case FieldDescriptor::CPPTYPE_INT32: {
  117. GOOGLE_CHECK_GET_INT32(obj, value, false);
  118. key->SetInt32Value(value);
  119. break;
  120. }
  121. case FieldDescriptor::CPPTYPE_INT64: {
  122. GOOGLE_CHECK_GET_INT64(obj, value, false);
  123. key->SetInt64Value(value);
  124. break;
  125. }
  126. case FieldDescriptor::CPPTYPE_UINT32: {
  127. GOOGLE_CHECK_GET_UINT32(obj, value, false);
  128. key->SetUInt32Value(value);
  129. break;
  130. }
  131. case FieldDescriptor::CPPTYPE_UINT64: {
  132. GOOGLE_CHECK_GET_UINT64(obj, value, false);
  133. key->SetUInt64Value(value);
  134. break;
  135. }
  136. case FieldDescriptor::CPPTYPE_BOOL: {
  137. GOOGLE_CHECK_GET_BOOL(obj, value, false);
  138. key->SetBoolValue(value);
  139. break;
  140. }
  141. case FieldDescriptor::CPPTYPE_STRING: {
  142. std::string str;
  143. if (!PyStringToSTL(CheckString(obj, field_descriptor), &str)) {
  144. return false;
  145. }
  146. key->SetStringValue(str);
  147. break;
  148. }
  149. default:
  150. PyErr_Format(
  151. PyExc_SystemError, "Type %d cannot be a map key",
  152. field_descriptor->cpp_type());
  153. return false;
  154. }
  155. return true;
  156. }
  157. static PyObject* MapKeyToPython(MapContainer* self, const MapKey& key) {
  158. const FieldDescriptor* field_descriptor =
  159. self->parent_field_descriptor->message_type()->map_key();
  160. switch (field_descriptor->cpp_type()) {
  161. case FieldDescriptor::CPPTYPE_INT32:
  162. return PyInt_FromLong(key.GetInt32Value());
  163. case FieldDescriptor::CPPTYPE_INT64:
  164. return PyLong_FromLongLong(key.GetInt64Value());
  165. case FieldDescriptor::CPPTYPE_UINT32:
  166. return PyInt_FromSize_t(key.GetUInt32Value());
  167. case FieldDescriptor::CPPTYPE_UINT64:
  168. return PyLong_FromUnsignedLongLong(key.GetUInt64Value());
  169. case FieldDescriptor::CPPTYPE_BOOL:
  170. return PyBool_FromLong(key.GetBoolValue());
  171. case FieldDescriptor::CPPTYPE_STRING:
  172. return ToStringObject(field_descriptor, key.GetStringValue());
  173. default:
  174. PyErr_Format(
  175. PyExc_SystemError, "Couldn't convert type %d to value",
  176. field_descriptor->cpp_type());
  177. return NULL;
  178. }
  179. }
  180. // This is only used for ScalarMap, so we don't need to handle the
  181. // CPPTYPE_MESSAGE case.
  182. PyObject* MapValueRefToPython(MapContainer* self, const MapValueRef& value) {
  183. const FieldDescriptor* field_descriptor =
  184. self->parent_field_descriptor->message_type()->map_value();
  185. switch (field_descriptor->cpp_type()) {
  186. case FieldDescriptor::CPPTYPE_INT32:
  187. return PyInt_FromLong(value.GetInt32Value());
  188. case FieldDescriptor::CPPTYPE_INT64:
  189. return PyLong_FromLongLong(value.GetInt64Value());
  190. case FieldDescriptor::CPPTYPE_UINT32:
  191. return PyInt_FromSize_t(value.GetUInt32Value());
  192. case FieldDescriptor::CPPTYPE_UINT64:
  193. return PyLong_FromUnsignedLongLong(value.GetUInt64Value());
  194. case FieldDescriptor::CPPTYPE_FLOAT:
  195. return PyFloat_FromDouble(value.GetFloatValue());
  196. case FieldDescriptor::CPPTYPE_DOUBLE:
  197. return PyFloat_FromDouble(value.GetDoubleValue());
  198. case FieldDescriptor::CPPTYPE_BOOL:
  199. return PyBool_FromLong(value.GetBoolValue());
  200. case FieldDescriptor::CPPTYPE_STRING:
  201. return ToStringObject(field_descriptor, value.GetStringValue());
  202. case FieldDescriptor::CPPTYPE_ENUM:
  203. return PyInt_FromLong(value.GetEnumValue());
  204. default:
  205. PyErr_Format(
  206. PyExc_SystemError, "Couldn't convert type %d to value",
  207. field_descriptor->cpp_type());
  208. return NULL;
  209. }
  210. }
  211. // This is only used for ScalarMap, so we don't need to handle the
  212. // CPPTYPE_MESSAGE case.
  213. static bool PythonToMapValueRef(MapContainer* self, PyObject* obj,
  214. bool allow_unknown_enum_values,
  215. MapValueRef* value_ref) {
  216. const FieldDescriptor* field_descriptor =
  217. self->parent_field_descriptor->message_type()->map_value();
  218. switch (field_descriptor->cpp_type()) {
  219. case FieldDescriptor::CPPTYPE_INT32: {
  220. GOOGLE_CHECK_GET_INT32(obj, value, false);
  221. value_ref->SetInt32Value(value);
  222. return true;
  223. }
  224. case FieldDescriptor::CPPTYPE_INT64: {
  225. GOOGLE_CHECK_GET_INT64(obj, value, false);
  226. value_ref->SetInt64Value(value);
  227. return true;
  228. }
  229. case FieldDescriptor::CPPTYPE_UINT32: {
  230. GOOGLE_CHECK_GET_UINT32(obj, value, false);
  231. value_ref->SetUInt32Value(value);
  232. return true;
  233. }
  234. case FieldDescriptor::CPPTYPE_UINT64: {
  235. GOOGLE_CHECK_GET_UINT64(obj, value, false);
  236. value_ref->SetUInt64Value(value);
  237. return true;
  238. }
  239. case FieldDescriptor::CPPTYPE_FLOAT: {
  240. GOOGLE_CHECK_GET_FLOAT(obj, value, false);
  241. value_ref->SetFloatValue(value);
  242. return true;
  243. }
  244. case FieldDescriptor::CPPTYPE_DOUBLE: {
  245. GOOGLE_CHECK_GET_DOUBLE(obj, value, false);
  246. value_ref->SetDoubleValue(value);
  247. return true;
  248. }
  249. case FieldDescriptor::CPPTYPE_BOOL: {
  250. GOOGLE_CHECK_GET_BOOL(obj, value, false);
  251. value_ref->SetBoolValue(value);
  252. return true;;
  253. }
  254. case FieldDescriptor::CPPTYPE_STRING: {
  255. std::string str;
  256. if (!PyStringToSTL(CheckString(obj, field_descriptor), &str)) {
  257. return false;
  258. }
  259. value_ref->SetStringValue(str);
  260. return true;
  261. }
  262. case FieldDescriptor::CPPTYPE_ENUM: {
  263. GOOGLE_CHECK_GET_INT32(obj, value, false);
  264. if (allow_unknown_enum_values) {
  265. value_ref->SetEnumValue(value);
  266. return true;
  267. } else {
  268. const EnumDescriptor* enum_descriptor = field_descriptor->enum_type();
  269. const EnumValueDescriptor* enum_value =
  270. enum_descriptor->FindValueByNumber(value);
  271. if (enum_value != NULL) {
  272. value_ref->SetEnumValue(value);
  273. return true;
  274. } else {
  275. PyErr_Format(PyExc_ValueError, "Unknown enum value: %d", value);
  276. return false;
  277. }
  278. }
  279. break;
  280. }
  281. default:
  282. PyErr_Format(
  283. PyExc_SystemError, "Setting value to a field of unknown type %d",
  284. field_descriptor->cpp_type());
  285. return false;
  286. }
  287. }
  288. // Map methods common to ScalarMap and MessageMap //////////////////////////////
  289. static MapContainer* GetMap(PyObject* obj) {
  290. return reinterpret_cast<MapContainer*>(obj);
  291. }
  292. Py_ssize_t MapReflectionFriend::Length(PyObject* _self) {
  293. MapContainer* self = GetMap(_self);
  294. const google::protobuf::Message* message = self->parent->message;
  295. return message->GetReflection()->MapSize(*message,
  296. self->parent_field_descriptor);
  297. }
  298. PyObject* Clear(PyObject* _self) {
  299. MapContainer* self = GetMap(_self);
  300. Message* message = self->GetMutableMessage();
  301. const Reflection* reflection = message->GetReflection();
  302. reflection->ClearField(message, self->parent_field_descriptor);
  303. Py_RETURN_NONE;
  304. }
  305. PyObject* GetEntryClass(PyObject* _self) {
  306. MapContainer* self = GetMap(_self);
  307. CMessageClass* message_class = message_factory::GetMessageClass(
  308. cmessage::GetFactoryForMessage(self->parent),
  309. self->parent_field_descriptor->message_type());
  310. Py_XINCREF(message_class);
  311. return reinterpret_cast<PyObject*>(message_class);
  312. }
  313. PyObject* MapReflectionFriend::MergeFrom(PyObject* _self, PyObject* arg) {
  314. MapContainer* self = GetMap(_self);
  315. if (!PyObject_TypeCheck(arg, ScalarMapContainer_Type) &&
  316. !PyObject_TypeCheck(arg, MessageMapContainer_Type)) {
  317. PyErr_SetString(PyExc_AttributeError, "Not a map field");
  318. return nullptr;
  319. }
  320. MapContainer* other_map = GetMap(arg);
  321. Message* message = self->GetMutableMessage();
  322. const Message* other_message = other_map->parent->message;
  323. const Reflection* reflection = message->GetReflection();
  324. const Reflection* other_reflection = other_message->GetReflection();
  325. internal::MapFieldBase* field = reflection->MutableMapData(
  326. message, self->parent_field_descriptor);
  327. const internal::MapFieldBase* other_field = other_reflection->GetMapData(
  328. *other_message, other_map->parent_field_descriptor);
  329. field->MergeFrom(*other_field);
  330. self->version++;
  331. Py_RETURN_NONE;
  332. }
  333. PyObject* MapReflectionFriend::Contains(PyObject* _self, PyObject* key) {
  334. MapContainer* self = GetMap(_self);
  335. const Message* message = self->parent->message;
  336. const Reflection* reflection = message->GetReflection();
  337. MapKey map_key;
  338. if (!PythonToMapKey(self, key, &map_key)) {
  339. return NULL;
  340. }
  341. if (reflection->ContainsMapKey(*message, self->parent_field_descriptor,
  342. map_key)) {
  343. Py_RETURN_TRUE;
  344. } else {
  345. Py_RETURN_FALSE;
  346. }
  347. }
  348. // ScalarMap ///////////////////////////////////////////////////////////////////
  349. MapContainer* NewScalarMapContainer(
  350. CMessage* parent, const google::protobuf::FieldDescriptor* parent_field_descriptor) {
  351. if (!CheckFieldBelongsToMessage(parent_field_descriptor, parent->message)) {
  352. return NULL;
  353. }
  354. PyObject* obj(PyType_GenericAlloc(ScalarMapContainer_Type, 0));
  355. if (obj == NULL) {
  356. PyErr_Format(PyExc_RuntimeError,
  357. "Could not allocate new container.");
  358. return NULL;
  359. }
  360. MapContainer* self = GetMap(obj);
  361. Py_INCREF(parent);
  362. self->parent = parent;
  363. self->parent_field_descriptor = parent_field_descriptor;
  364. self->version = 0;
  365. return self;
  366. }
  367. PyObject* MapReflectionFriend::ScalarMapGetItem(PyObject* _self,
  368. PyObject* key) {
  369. MapContainer* self = GetMap(_self);
  370. Message* message = self->GetMutableMessage();
  371. const Reflection* reflection = message->GetReflection();
  372. MapKey map_key;
  373. MapValueRef value;
  374. if (!PythonToMapKey(self, key, &map_key)) {
  375. return NULL;
  376. }
  377. if (reflection->InsertOrLookupMapValue(message, self->parent_field_descriptor,
  378. map_key, &value)) {
  379. self->version++;
  380. }
  381. return MapValueRefToPython(self, value);
  382. }
  383. int MapReflectionFriend::ScalarMapSetItem(PyObject* _self, PyObject* key,
  384. PyObject* v) {
  385. MapContainer* self = GetMap(_self);
  386. Message* message = self->GetMutableMessage();
  387. const Reflection* reflection = message->GetReflection();
  388. MapKey map_key;
  389. MapValueRef value;
  390. if (!PythonToMapKey(self, key, &map_key)) {
  391. return -1;
  392. }
  393. self->version++;
  394. if (v) {
  395. // Set item to v.
  396. reflection->InsertOrLookupMapValue(message, self->parent_field_descriptor,
  397. map_key, &value);
  398. if (!PythonToMapValueRef(self, v, reflection->SupportsUnknownEnumValues(),
  399. &value)) {
  400. return -1;
  401. }
  402. return 0;
  403. } else {
  404. // Delete key from map.
  405. if (reflection->DeleteMapValue(message, self->parent_field_descriptor,
  406. map_key)) {
  407. return 0;
  408. } else {
  409. PyErr_Format(PyExc_KeyError, "Key not present in map");
  410. return -1;
  411. }
  412. }
  413. }
  414. static PyObject* ScalarMapGet(PyObject* self, PyObject* args,
  415. PyObject* kwargs) {
  416. static char* kwlist[] = {"key", "default", nullptr};
  417. PyObject* key;
  418. PyObject* default_value = NULL;
  419. if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", kwlist, &key,
  420. &default_value)) {
  421. return NULL;
  422. }
  423. ScopedPyObjectPtr is_present(MapReflectionFriend::Contains(self, key));
  424. if (is_present.get() == NULL) {
  425. return NULL;
  426. }
  427. if (PyObject_IsTrue(is_present.get())) {
  428. return MapReflectionFriend::ScalarMapGetItem(self, key);
  429. } else {
  430. if (default_value != NULL) {
  431. Py_INCREF(default_value);
  432. return default_value;
  433. } else {
  434. Py_RETURN_NONE;
  435. }
  436. }
  437. }
  438. PyObject* MapReflectionFriend::ScalarMapToStr(PyObject* _self) {
  439. ScopedPyObjectPtr dict(PyDict_New());
  440. if (dict == NULL) {
  441. return NULL;
  442. }
  443. ScopedPyObjectPtr key;
  444. ScopedPyObjectPtr value;
  445. MapContainer* self = GetMap(_self);
  446. Message* message = self->GetMutableMessage();
  447. const Reflection* reflection = message->GetReflection();
  448. for (google::protobuf::MapIterator it = reflection->MapBegin(
  449. message, self->parent_field_descriptor);
  450. it != reflection->MapEnd(message, self->parent_field_descriptor);
  451. ++it) {
  452. key.reset(MapKeyToPython(self, it.GetKey()));
  453. if (key == NULL) {
  454. return NULL;
  455. }
  456. value.reset(MapValueRefToPython(self, it.GetValueRef()));
  457. if (value == NULL) {
  458. return NULL;
  459. }
  460. if (PyDict_SetItem(dict.get(), key.get(), value.get()) < 0) {
  461. return NULL;
  462. }
  463. }
  464. return PyObject_Repr(dict.get());
  465. }
  466. static void ScalarMapDealloc(PyObject* _self) {
  467. MapContainer* self = GetMap(_self);
  468. self->RemoveFromParentCache();
  469. PyTypeObject *type = Py_TYPE(_self);
  470. type->tp_free(_self);
  471. if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) {
  472. // With Python3, the Map class is not static, and must be managed.
  473. Py_DECREF(type);
  474. }
  475. }
  476. static PyMethodDef ScalarMapMethods[] = {
  477. {"__contains__", MapReflectionFriend::Contains, METH_O,
  478. "Tests whether a key is a member of the map."},
  479. {"clear", (PyCFunction)Clear, METH_NOARGS,
  480. "Removes all elements from the map."},
  481. {"get", (PyCFunction)ScalarMapGet, METH_VARARGS | METH_KEYWORDS,
  482. "Gets the value for the given key if present, or otherwise a default"},
  483. {"GetEntryClass", (PyCFunction)GetEntryClass, METH_NOARGS,
  484. "Return the class used to build Entries of (key, value) pairs."},
  485. {"MergeFrom", (PyCFunction)MapReflectionFriend::MergeFrom, METH_O,
  486. "Merges a map into the current map."},
  487. /*
  488. { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS,
  489. "Makes a deep copy of the class." },
  490. { "__reduce__", (PyCFunction)Reduce, METH_NOARGS,
  491. "Outputs picklable representation of the repeated field." },
  492. */
  493. {NULL, NULL},
  494. };
  495. PyTypeObject *ScalarMapContainer_Type;
  496. #if PY_MAJOR_VERSION >= 3
  497. static PyType_Slot ScalarMapContainer_Type_slots[] = {
  498. {Py_tp_dealloc, (void *)ScalarMapDealloc},
  499. {Py_mp_length, (void *)MapReflectionFriend::Length},
  500. {Py_mp_subscript, (void *)MapReflectionFriend::ScalarMapGetItem},
  501. {Py_mp_ass_subscript, (void *)MapReflectionFriend::ScalarMapSetItem},
  502. {Py_tp_methods, (void *)ScalarMapMethods},
  503. {Py_tp_iter, (void *)MapReflectionFriend::GetIterator},
  504. {Py_tp_repr, (void *)MapReflectionFriend::ScalarMapToStr},
  505. {0, 0},
  506. };
  507. PyType_Spec ScalarMapContainer_Type_spec = {
  508. FULL_MODULE_NAME ".ScalarMapContainer",
  509. sizeof(MapContainer),
  510. 0,
  511. Py_TPFLAGS_DEFAULT,
  512. ScalarMapContainer_Type_slots
  513. };
  514. #else
  515. static PyMappingMethods ScalarMapMappingMethods = {
  516. MapReflectionFriend::Length, // mp_length
  517. MapReflectionFriend::ScalarMapGetItem, // mp_subscript
  518. MapReflectionFriend::ScalarMapSetItem, // mp_ass_subscript
  519. };
  520. PyTypeObject _ScalarMapContainer_Type = {
  521. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  522. FULL_MODULE_NAME ".ScalarMapContainer", // tp_name
  523. sizeof(MapContainer), // tp_basicsize
  524. 0, // tp_itemsize
  525. ScalarMapDealloc, // tp_dealloc
  526. 0, // tp_print
  527. 0, // tp_getattr
  528. 0, // tp_setattr
  529. 0, // tp_compare
  530. MapReflectionFriend::ScalarMapToStr, // tp_repr
  531. 0, // tp_as_number
  532. 0, // tp_as_sequence
  533. &ScalarMapMappingMethods, // tp_as_mapping
  534. 0, // tp_hash
  535. 0, // tp_call
  536. 0, // tp_str
  537. 0, // tp_getattro
  538. 0, // tp_setattro
  539. 0, // tp_as_buffer
  540. Py_TPFLAGS_DEFAULT, // tp_flags
  541. "A scalar map container", // tp_doc
  542. 0, // tp_traverse
  543. 0, // tp_clear
  544. 0, // tp_richcompare
  545. 0, // tp_weaklistoffset
  546. MapReflectionFriend::GetIterator, // tp_iter
  547. 0, // tp_iternext
  548. ScalarMapMethods, // tp_methods
  549. 0, // tp_members
  550. 0, // tp_getset
  551. 0, // tp_base
  552. 0, // tp_dict
  553. 0, // tp_descr_get
  554. 0, // tp_descr_set
  555. 0, // tp_dictoffset
  556. 0, // tp_init
  557. };
  558. #endif
  559. // MessageMap //////////////////////////////////////////////////////////////////
  560. static MessageMapContainer* GetMessageMap(PyObject* obj) {
  561. return reinterpret_cast<MessageMapContainer*>(obj);
  562. }
  563. static PyObject* GetCMessage(MessageMapContainer* self, Message* message) {
  564. // Get or create the CMessage object corresponding to this message.
  565. return self->parent
  566. ->BuildSubMessageFromPointer(self->parent_field_descriptor, message,
  567. self->message_class)
  568. ->AsPyObject();
  569. }
  570. MessageMapContainer* NewMessageMapContainer(
  571. CMessage* parent, const google::protobuf::FieldDescriptor* parent_field_descriptor,
  572. CMessageClass* message_class) {
  573. if (!CheckFieldBelongsToMessage(parent_field_descriptor, parent->message)) {
  574. return NULL;
  575. }
  576. PyObject* obj = PyType_GenericAlloc(MessageMapContainer_Type, 0);
  577. if (obj == NULL) {
  578. PyErr_SetString(PyExc_RuntimeError, "Could not allocate new container.");
  579. return NULL;
  580. }
  581. MessageMapContainer* self = GetMessageMap(obj);
  582. Py_INCREF(parent);
  583. self->parent = parent;
  584. self->parent_field_descriptor = parent_field_descriptor;
  585. self->version = 0;
  586. Py_INCREF(message_class);
  587. self->message_class = message_class;
  588. return self;
  589. }
  590. int MapReflectionFriend::MessageMapSetItem(PyObject* _self, PyObject* key,
  591. PyObject* v) {
  592. if (v) {
  593. PyErr_Format(PyExc_ValueError,
  594. "Direct assignment of submessage not allowed");
  595. return -1;
  596. }
  597. // Now we know that this is a delete, not a set.
  598. MessageMapContainer* self = GetMessageMap(_self);
  599. Message* message = self->GetMutableMessage();
  600. const Reflection* reflection = message->GetReflection();
  601. MapKey map_key;
  602. MapValueRef value;
  603. self->version++;
  604. if (!PythonToMapKey(self, key, &map_key)) {
  605. return -1;
  606. }
  607. // Delete key from map.
  608. if (reflection->ContainsMapKey(*message, self->parent_field_descriptor,
  609. map_key)) {
  610. // Delete key from CMessage dict.
  611. MapValueRef value;
  612. reflection->InsertOrLookupMapValue(message, self->parent_field_descriptor,
  613. map_key, &value);
  614. Message* sub_message = value.MutableMessageValue();
  615. // If there is a living weak reference to an item, we "Release" it,
  616. // otherwise we just discard the C++ value.
  617. if (CMessage* released =
  618. self->parent->MaybeReleaseSubMessage(sub_message)) {
  619. Message* msg = released->message;
  620. released->message = msg->New();
  621. msg->GetReflection()->Swap(msg, released->message);
  622. }
  623. // Delete key from map.
  624. reflection->DeleteMapValue(message, self->parent_field_descriptor,
  625. map_key);
  626. return 0;
  627. } else {
  628. PyErr_Format(PyExc_KeyError, "Key not present in map");
  629. return -1;
  630. }
  631. }
  632. PyObject* MapReflectionFriend::MessageMapGetItem(PyObject* _self,
  633. PyObject* key) {
  634. MessageMapContainer* self = GetMessageMap(_self);
  635. Message* message = self->GetMutableMessage();
  636. const Reflection* reflection = message->GetReflection();
  637. MapKey map_key;
  638. MapValueRef value;
  639. if (!PythonToMapKey(self, key, &map_key)) {
  640. return NULL;
  641. }
  642. if (reflection->InsertOrLookupMapValue(message, self->parent_field_descriptor,
  643. map_key, &value)) {
  644. self->version++;
  645. }
  646. return GetCMessage(self, value.MutableMessageValue());
  647. }
  648. PyObject* MapReflectionFriend::MessageMapToStr(PyObject* _self) {
  649. ScopedPyObjectPtr dict(PyDict_New());
  650. if (dict == NULL) {
  651. return NULL;
  652. }
  653. ScopedPyObjectPtr key;
  654. ScopedPyObjectPtr value;
  655. MessageMapContainer* self = GetMessageMap(_self);
  656. Message* message = self->GetMutableMessage();
  657. const Reflection* reflection = message->GetReflection();
  658. for (google::protobuf::MapIterator it = reflection->MapBegin(
  659. message, self->parent_field_descriptor);
  660. it != reflection->MapEnd(message, self->parent_field_descriptor);
  661. ++it) {
  662. key.reset(MapKeyToPython(self, it.GetKey()));
  663. if (key == NULL) {
  664. return NULL;
  665. }
  666. value.reset(GetCMessage(self, it.MutableValueRef()->MutableMessageValue()));
  667. if (value == NULL) {
  668. return NULL;
  669. }
  670. if (PyDict_SetItem(dict.get(), key.get(), value.get()) < 0) {
  671. return NULL;
  672. }
  673. }
  674. return PyObject_Repr(dict.get());
  675. }
  676. PyObject* MessageMapGet(PyObject* self, PyObject* args, PyObject* kwargs) {
  677. static char* kwlist[] = {"key", "default", nullptr};
  678. PyObject* key;
  679. PyObject* default_value = NULL;
  680. if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", kwlist, &key,
  681. &default_value)) {
  682. return NULL;
  683. }
  684. ScopedPyObjectPtr is_present(MapReflectionFriend::Contains(self, key));
  685. if (is_present.get() == NULL) {
  686. return NULL;
  687. }
  688. if (PyObject_IsTrue(is_present.get())) {
  689. return MapReflectionFriend::MessageMapGetItem(self, key);
  690. } else {
  691. if (default_value != NULL) {
  692. Py_INCREF(default_value);
  693. return default_value;
  694. } else {
  695. Py_RETURN_NONE;
  696. }
  697. }
  698. }
  699. static void MessageMapDealloc(PyObject* _self) {
  700. MessageMapContainer* self = GetMessageMap(_self);
  701. self->RemoveFromParentCache();
  702. Py_DECREF(self->message_class);
  703. PyTypeObject *type = Py_TYPE(_self);
  704. type->tp_free(_self);
  705. if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) {
  706. // With Python3, the Map class is not static, and must be managed.
  707. Py_DECREF(type);
  708. }
  709. }
  710. static PyMethodDef MessageMapMethods[] = {
  711. {"__contains__", (PyCFunction)MapReflectionFriend::Contains, METH_O,
  712. "Tests whether the map contains this element."},
  713. {"clear", (PyCFunction)Clear, METH_NOARGS,
  714. "Removes all elements from the map."},
  715. {"get", (PyCFunction)MessageMapGet, METH_VARARGS | METH_KEYWORDS,
  716. "Gets the value for the given key if present, or otherwise a default"},
  717. {"get_or_create", MapReflectionFriend::MessageMapGetItem, METH_O,
  718. "Alias for getitem, useful to make explicit that the map is mutated."},
  719. {"GetEntryClass", (PyCFunction)GetEntryClass, METH_NOARGS,
  720. "Return the class used to build Entries of (key, value) pairs."},
  721. {"MergeFrom", (PyCFunction)MapReflectionFriend::MergeFrom, METH_O,
  722. "Merges a map into the current map."},
  723. /*
  724. { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS,
  725. "Makes a deep copy of the class." },
  726. { "__reduce__", (PyCFunction)Reduce, METH_NOARGS,
  727. "Outputs picklable representation of the repeated field." },
  728. */
  729. {NULL, NULL},
  730. };
  731. PyTypeObject *MessageMapContainer_Type;
  732. #if PY_MAJOR_VERSION >= 3
  733. static PyType_Slot MessageMapContainer_Type_slots[] = {
  734. {Py_tp_dealloc, (void *)MessageMapDealloc},
  735. {Py_mp_length, (void *)MapReflectionFriend::Length},
  736. {Py_mp_subscript, (void *)MapReflectionFriend::MessageMapGetItem},
  737. {Py_mp_ass_subscript, (void *)MapReflectionFriend::MessageMapSetItem},
  738. {Py_tp_methods, (void *)MessageMapMethods},
  739. {Py_tp_iter, (void *)MapReflectionFriend::GetIterator},
  740. {Py_tp_repr, (void *)MapReflectionFriend::MessageMapToStr},
  741. {0, 0}
  742. };
  743. PyType_Spec MessageMapContainer_Type_spec = {
  744. FULL_MODULE_NAME ".MessageMapContainer",
  745. sizeof(MessageMapContainer),
  746. 0,
  747. Py_TPFLAGS_DEFAULT,
  748. MessageMapContainer_Type_slots
  749. };
  750. #else
  751. static PyMappingMethods MessageMapMappingMethods = {
  752. MapReflectionFriend::Length, // mp_length
  753. MapReflectionFriend::MessageMapGetItem, // mp_subscript
  754. MapReflectionFriend::MessageMapSetItem, // mp_ass_subscript
  755. };
  756. PyTypeObject _MessageMapContainer_Type = {
  757. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  758. FULL_MODULE_NAME ".MessageMapContainer", // tp_name
  759. sizeof(MessageMapContainer), // tp_basicsize
  760. 0, // tp_itemsize
  761. MessageMapDealloc, // tp_dealloc
  762. 0, // tp_print
  763. 0, // tp_getattr
  764. 0, // tp_setattr
  765. 0, // tp_compare
  766. MapReflectionFriend::MessageMapToStr, // tp_repr
  767. 0, // tp_as_number
  768. 0, // tp_as_sequence
  769. &MessageMapMappingMethods, // tp_as_mapping
  770. 0, // tp_hash
  771. 0, // tp_call
  772. 0, // tp_str
  773. 0, // tp_getattro
  774. 0, // tp_setattro
  775. 0, // tp_as_buffer
  776. Py_TPFLAGS_DEFAULT, // tp_flags
  777. "A map container for message", // tp_doc
  778. 0, // tp_traverse
  779. 0, // tp_clear
  780. 0, // tp_richcompare
  781. 0, // tp_weaklistoffset
  782. MapReflectionFriend::GetIterator, // tp_iter
  783. 0, // tp_iternext
  784. MessageMapMethods, // tp_methods
  785. 0, // tp_members
  786. 0, // tp_getset
  787. 0, // tp_base
  788. 0, // tp_dict
  789. 0, // tp_descr_get
  790. 0, // tp_descr_set
  791. 0, // tp_dictoffset
  792. 0, // tp_init
  793. };
  794. #endif
  795. // MapIterator /////////////////////////////////////////////////////////////////
  796. static MapIterator* GetIter(PyObject* obj) {
  797. return reinterpret_cast<MapIterator*>(obj);
  798. }
  799. PyObject* MapReflectionFriend::GetIterator(PyObject *_self) {
  800. MapContainer* self = GetMap(_self);
  801. ScopedPyObjectPtr obj(PyType_GenericAlloc(&MapIterator_Type, 0));
  802. if (obj == NULL) {
  803. return PyErr_Format(PyExc_KeyError, "Could not allocate iterator");
  804. }
  805. MapIterator* iter = GetIter(obj.get());
  806. Py_INCREF(self);
  807. iter->container = self;
  808. iter->version = self->version;
  809. Py_INCREF(self->parent);
  810. iter->parent = self->parent;
  811. if (MapReflectionFriend::Length(_self) > 0) {
  812. Message* message = self->GetMutableMessage();
  813. const Reflection* reflection = message->GetReflection();
  814. iter->iter.reset(new ::google::protobuf::MapIterator(
  815. reflection->MapBegin(message, self->parent_field_descriptor)));
  816. }
  817. return obj.release();
  818. }
  819. PyObject* MapReflectionFriend::IterNext(PyObject* _self) {
  820. MapIterator* self = GetIter(_self);
  821. // This won't catch mutations to the map performed by MergeFrom(); no easy way
  822. // to address that.
  823. if (self->version != self->container->version) {
  824. return PyErr_Format(PyExc_RuntimeError,
  825. "Map modified during iteration.");
  826. }
  827. if (self->parent != self->container->parent) {
  828. return PyErr_Format(PyExc_RuntimeError,
  829. "Map cleared during iteration.");
  830. }
  831. if (self->iter.get() == NULL) {
  832. return NULL;
  833. }
  834. Message* message = self->container->GetMutableMessage();
  835. const Reflection* reflection = message->GetReflection();
  836. if (*self->iter ==
  837. reflection->MapEnd(message, self->container->parent_field_descriptor)) {
  838. return NULL;
  839. }
  840. PyObject* ret = MapKeyToPython(self->container, self->iter->GetKey());
  841. ++(*self->iter);
  842. return ret;
  843. }
  844. static void DeallocMapIterator(PyObject* _self) {
  845. MapIterator* self = GetIter(_self);
  846. self->iter.reset();
  847. Py_CLEAR(self->container);
  848. Py_CLEAR(self->parent);
  849. Py_TYPE(_self)->tp_free(_self);
  850. }
  851. PyTypeObject MapIterator_Type = {
  852. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  853. FULL_MODULE_NAME ".MapIterator", // tp_name
  854. sizeof(MapIterator), // tp_basicsize
  855. 0, // tp_itemsize
  856. DeallocMapIterator, // tp_dealloc
  857. 0, // tp_print
  858. 0, // tp_getattr
  859. 0, // tp_setattr
  860. 0, // tp_compare
  861. 0, // tp_repr
  862. 0, // tp_as_number
  863. 0, // tp_as_sequence
  864. 0, // tp_as_mapping
  865. 0, // tp_hash
  866. 0, // tp_call
  867. 0, // tp_str
  868. 0, // tp_getattro
  869. 0, // tp_setattro
  870. 0, // tp_as_buffer
  871. Py_TPFLAGS_DEFAULT, // tp_flags
  872. "A scalar map iterator", // tp_doc
  873. 0, // tp_traverse
  874. 0, // tp_clear
  875. 0, // tp_richcompare
  876. 0, // tp_weaklistoffset
  877. PyObject_SelfIter, // tp_iter
  878. MapReflectionFriend::IterNext, // tp_iternext
  879. 0, // tp_methods
  880. 0, // tp_members
  881. 0, // tp_getset
  882. 0, // tp_base
  883. 0, // tp_dict
  884. 0, // tp_descr_get
  885. 0, // tp_descr_set
  886. 0, // tp_dictoffset
  887. 0, // tp_init
  888. };
  889. bool InitMapContainers() {
  890. // ScalarMapContainer_Type derives from our MutableMapping type.
  891. ScopedPyObjectPtr containers(PyImport_ImportModule(
  892. "google.protobuf.internal.containers"));
  893. if (containers == NULL) {
  894. return false;
  895. }
  896. ScopedPyObjectPtr mutable_mapping(
  897. PyObject_GetAttrString(containers.get(), "MutableMapping"));
  898. if (mutable_mapping == NULL) {
  899. return false;
  900. }
  901. Py_INCREF(mutable_mapping.get());
  902. #if PY_MAJOR_VERSION >= 3
  903. ScopedPyObjectPtr bases(PyTuple_Pack(1, mutable_mapping.get()));
  904. if (bases == NULL) {
  905. return false;
  906. }
  907. ScalarMapContainer_Type = reinterpret_cast<PyTypeObject*>(
  908. PyType_FromSpecWithBases(&ScalarMapContainer_Type_spec, bases.get()));
  909. #else
  910. _ScalarMapContainer_Type.tp_base =
  911. reinterpret_cast<PyTypeObject*>(mutable_mapping.get());
  912. if (PyType_Ready(&_ScalarMapContainer_Type) < 0) {
  913. return false;
  914. }
  915. ScalarMapContainer_Type = &_ScalarMapContainer_Type;
  916. #endif
  917. if (PyType_Ready(&MapIterator_Type) < 0) {
  918. return false;
  919. }
  920. #if PY_MAJOR_VERSION >= 3
  921. MessageMapContainer_Type = reinterpret_cast<PyTypeObject*>(
  922. PyType_FromSpecWithBases(&MessageMapContainer_Type_spec, bases.get()));
  923. #else
  924. Py_INCREF(mutable_mapping.get());
  925. _MessageMapContainer_Type.tp_base =
  926. reinterpret_cast<PyTypeObject*>(mutable_mapping.get());
  927. if (PyType_Ready(&_MessageMapContainer_Type) < 0) {
  928. return false;
  929. }
  930. MessageMapContainer_Type = &_MessageMapContainer_Type;
  931. #endif
  932. return true;
  933. }
  934. } // namespace python
  935. } // namespace protobuf
  936. } // namespace google