map_container.cc 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155
  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. #if PY_MAJOR_VERSION >= 3
  43. #define PyInt_FromLong PyLong_FromLong
  44. #define PyInt_FromSize_t PyLong_FromSize_t
  45. #endif
  46. namespace google {
  47. namespace protobuf {
  48. namespace python {
  49. // Functions that need access to map reflection functionality.
  50. // They need to be contained in this class because it is friended.
  51. class MapReflectionFriend {
  52. public:
  53. // Methods that are in common between the map types.
  54. static PyObject* Contains(PyObject* _self, PyObject* key);
  55. static Py_ssize_t Length(PyObject* _self);
  56. static PyObject* GetIterator(PyObject *_self);
  57. static PyObject* IterNext(PyObject* _self);
  58. static PyObject* MergeFrom(PyObject* _self, PyObject* arg);
  59. // Methods that differ between the map types.
  60. static PyObject* ScalarMapGetItem(PyObject* _self, PyObject* key);
  61. static PyObject* MessageMapGetItem(PyObject* _self, PyObject* key);
  62. static int ScalarMapSetItem(PyObject* _self, PyObject* key, PyObject* v);
  63. static int MessageMapSetItem(PyObject* _self, PyObject* key, PyObject* v);
  64. static PyObject* ScalarMapToStr(PyObject* _self);
  65. static PyObject* MessageMapToStr(PyObject* _self);
  66. };
  67. struct MapIterator {
  68. PyObject_HEAD;
  69. std::unique_ptr<::google::protobuf::MapIterator> iter;
  70. // A pointer back to the container, so we can notice changes to the version.
  71. // We own a ref on this.
  72. MapContainer* container;
  73. // We need to keep a ref on the Message* too, because
  74. // MapIterator::~MapIterator() accesses it. Normally this would be ok because
  75. // the ref on container (above) would guarantee outlive semantics. However in
  76. // the case of ClearField(), InitializeAndCopyToParentContainer() resets the
  77. // message pointer (and the owner) to a different message, a copy of the
  78. // original. But our iterator still points to the original, which could now
  79. // 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::OwnerRef owner;
  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. // True if the container is empty. We signal this separately to avoid calling
  92. // any of the iteration methods, which are non-const.
  93. bool empty;
  94. };
  95. Message* MapContainer::GetMutableMessage() {
  96. cmessage::AssureWritable(parent);
  97. return const_cast<Message*>(message);
  98. }
  99. // Consumes a reference on the Python string object.
  100. static bool PyStringToSTL(PyObject* py_string, string* stl_string) {
  101. char *value;
  102. Py_ssize_t value_len;
  103. if (!py_string) {
  104. return false;
  105. }
  106. if (PyBytes_AsStringAndSize(py_string, &value, &value_len) < 0) {
  107. Py_DECREF(py_string);
  108. return false;
  109. } else {
  110. stl_string->assign(value, value_len);
  111. Py_DECREF(py_string);
  112. return true;
  113. }
  114. }
  115. static bool PythonToMapKey(PyObject* obj,
  116. const FieldDescriptor* field_descriptor,
  117. MapKey* key) {
  118. switch (field_descriptor->cpp_type()) {
  119. case FieldDescriptor::CPPTYPE_INT32: {
  120. GOOGLE_CHECK_GET_INT32(obj, value, false);
  121. key->SetInt32Value(value);
  122. break;
  123. }
  124. case FieldDescriptor::CPPTYPE_INT64: {
  125. GOOGLE_CHECK_GET_INT64(obj, value, false);
  126. key->SetInt64Value(value);
  127. break;
  128. }
  129. case FieldDescriptor::CPPTYPE_UINT32: {
  130. GOOGLE_CHECK_GET_UINT32(obj, value, false);
  131. key->SetUInt32Value(value);
  132. break;
  133. }
  134. case FieldDescriptor::CPPTYPE_UINT64: {
  135. GOOGLE_CHECK_GET_UINT64(obj, value, false);
  136. key->SetUInt64Value(value);
  137. break;
  138. }
  139. case FieldDescriptor::CPPTYPE_BOOL: {
  140. GOOGLE_CHECK_GET_BOOL(obj, value, false);
  141. key->SetBoolValue(value);
  142. break;
  143. }
  144. case FieldDescriptor::CPPTYPE_STRING: {
  145. string str;
  146. if (!PyStringToSTL(CheckString(obj, field_descriptor), &str)) {
  147. return false;
  148. }
  149. key->SetStringValue(str);
  150. break;
  151. }
  152. default:
  153. PyErr_Format(
  154. PyExc_SystemError, "Type %d cannot be a map key",
  155. field_descriptor->cpp_type());
  156. return false;
  157. }
  158. return true;
  159. }
  160. static PyObject* MapKeyToPython(const FieldDescriptor* field_descriptor,
  161. const MapKey& key) {
  162. switch (field_descriptor->cpp_type()) {
  163. case FieldDescriptor::CPPTYPE_INT32:
  164. return PyInt_FromLong(key.GetInt32Value());
  165. case FieldDescriptor::CPPTYPE_INT64:
  166. return PyLong_FromLongLong(key.GetInt64Value());
  167. case FieldDescriptor::CPPTYPE_UINT32:
  168. return PyInt_FromSize_t(key.GetUInt32Value());
  169. case FieldDescriptor::CPPTYPE_UINT64:
  170. return PyLong_FromUnsignedLongLong(key.GetUInt64Value());
  171. case FieldDescriptor::CPPTYPE_BOOL:
  172. return PyBool_FromLong(key.GetBoolValue());
  173. case FieldDescriptor::CPPTYPE_STRING:
  174. return ToStringObject(field_descriptor, key.GetStringValue());
  175. default:
  176. PyErr_Format(
  177. PyExc_SystemError, "Couldn't convert type %d to value",
  178. field_descriptor->cpp_type());
  179. return NULL;
  180. }
  181. }
  182. // This is only used for ScalarMap, so we don't need to handle the
  183. // CPPTYPE_MESSAGE case.
  184. PyObject* MapValueRefToPython(const FieldDescriptor* field_descriptor,
  185. const MapValueRef& value) {
  186. switch (field_descriptor->cpp_type()) {
  187. case FieldDescriptor::CPPTYPE_INT32:
  188. return PyInt_FromLong(value.GetInt32Value());
  189. case FieldDescriptor::CPPTYPE_INT64:
  190. return PyLong_FromLongLong(value.GetInt64Value());
  191. case FieldDescriptor::CPPTYPE_UINT32:
  192. return PyInt_FromSize_t(value.GetUInt32Value());
  193. case FieldDescriptor::CPPTYPE_UINT64:
  194. return PyLong_FromUnsignedLongLong(value.GetUInt64Value());
  195. case FieldDescriptor::CPPTYPE_FLOAT:
  196. return PyFloat_FromDouble(value.GetFloatValue());
  197. case FieldDescriptor::CPPTYPE_DOUBLE:
  198. return PyFloat_FromDouble(value.GetDoubleValue());
  199. case FieldDescriptor::CPPTYPE_BOOL:
  200. return PyBool_FromLong(value.GetBoolValue());
  201. case FieldDescriptor::CPPTYPE_STRING:
  202. return ToStringObject(field_descriptor, value.GetStringValue());
  203. case FieldDescriptor::CPPTYPE_ENUM:
  204. return PyInt_FromLong(value.GetEnumValue());
  205. default:
  206. PyErr_Format(
  207. PyExc_SystemError, "Couldn't convert type %d to value",
  208. field_descriptor->cpp_type());
  209. return NULL;
  210. }
  211. }
  212. // This is only used for ScalarMap, so we don't need to handle the
  213. // CPPTYPE_MESSAGE case.
  214. static bool PythonToMapValueRef(PyObject* obj,
  215. const FieldDescriptor* field_descriptor,
  216. bool allow_unknown_enum_values,
  217. MapValueRef* value_ref) {
  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. 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->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. MapContainer* other_map = GetMap(arg);
  316. Message* message = self->GetMutableMessage();
  317. const Message* other_message = other_map->message;
  318. const Reflection* reflection = message->GetReflection();
  319. const Reflection* other_reflection = other_message->GetReflection();
  320. internal::MapFieldBase* field = reflection->MutableMapData(
  321. message, self->parent_field_descriptor);
  322. const internal::MapFieldBase* other_field =
  323. other_reflection->GetMapData(*other_message,
  324. self->parent_field_descriptor);
  325. field->MergeFrom(*other_field);
  326. self->version++;
  327. Py_RETURN_NONE;
  328. }
  329. PyObject* MapReflectionFriend::Contains(PyObject* _self, PyObject* key) {
  330. MapContainer* self = GetMap(_self);
  331. const Message* message = self->message;
  332. const Reflection* reflection = message->GetReflection();
  333. MapKey map_key;
  334. if (!PythonToMapKey(key, self->key_field_descriptor, &map_key)) {
  335. return NULL;
  336. }
  337. if (reflection->ContainsMapKey(*message, self->parent_field_descriptor,
  338. map_key)) {
  339. Py_RETURN_TRUE;
  340. } else {
  341. Py_RETURN_FALSE;
  342. }
  343. }
  344. // Initializes the underlying Message object of "to" so it becomes a new parent
  345. // map container, and copies all the values from "from" to it. A child map
  346. // container can be released by passing it as both from and to (e.g. making it
  347. // the recipient of the new parent message and copying the values from itself).
  348. // In fact, this is the only supported use at the moment.
  349. static int InitializeAndCopyToParentContainer(MapContainer* from,
  350. MapContainer* to) {
  351. // For now we require from == to, re-evaluate if we want to support deep copy
  352. // as in repeated_scalar_container.cc.
  353. GOOGLE_DCHECK(from == to);
  354. Message* new_message = from->message->New();
  355. if (MapReflectionFriend::Length(reinterpret_cast<PyObject*>(from)) > 0) {
  356. // A somewhat roundabout way of copying just one field from old_message to
  357. // new_message. This is the best we can do with what Reflection gives us.
  358. Message* mutable_old = from->GetMutableMessage();
  359. std::vector<const FieldDescriptor*> fields;
  360. fields.push_back(from->parent_field_descriptor);
  361. // Move the map field into the new message.
  362. mutable_old->GetReflection()->SwapFields(mutable_old, new_message, fields);
  363. // If/when we support from != to, this will be required also to copy the
  364. // map field back into the existing message:
  365. // mutable_old->MergeFrom(*new_message);
  366. }
  367. // If from == to this could delete old_message.
  368. to->owner.reset(new_message);
  369. to->parent = NULL;
  370. to->parent_field_descriptor = from->parent_field_descriptor;
  371. to->message = new_message;
  372. // Invalidate iterators, since they point to the old copy of the field.
  373. to->version++;
  374. return 0;
  375. }
  376. int MapContainer::Release() {
  377. return InitializeAndCopyToParentContainer(this, this);
  378. }
  379. // ScalarMap ///////////////////////////////////////////////////////////////////
  380. PyObject *NewScalarMapContainer(
  381. CMessage* parent, const google::protobuf::FieldDescriptor* parent_field_descriptor) {
  382. if (!CheckFieldBelongsToMessage(parent_field_descriptor, parent->message)) {
  383. return NULL;
  384. }
  385. ScopedPyObjectPtr obj(PyType_GenericAlloc(ScalarMapContainer_Type, 0));
  386. if (obj.get() == NULL) {
  387. return PyErr_Format(PyExc_RuntimeError,
  388. "Could not allocate new container.");
  389. }
  390. MapContainer* self = GetMap(obj.get());
  391. self->message = parent->message;
  392. self->parent = parent;
  393. self->parent_field_descriptor = parent_field_descriptor;
  394. self->owner = parent->owner;
  395. self->version = 0;
  396. self->key_field_descriptor =
  397. parent_field_descriptor->message_type()->FindFieldByName("key");
  398. self->value_field_descriptor =
  399. parent_field_descriptor->message_type()->FindFieldByName("value");
  400. if (self->key_field_descriptor == NULL ||
  401. self->value_field_descriptor == NULL) {
  402. return PyErr_Format(PyExc_KeyError,
  403. "Map entry descriptor did not have key/value fields");
  404. }
  405. return obj.release();
  406. }
  407. PyObject* MapReflectionFriend::ScalarMapGetItem(PyObject* _self,
  408. PyObject* key) {
  409. MapContainer* self = GetMap(_self);
  410. Message* message = self->GetMutableMessage();
  411. const Reflection* reflection = message->GetReflection();
  412. MapKey map_key;
  413. MapValueRef value;
  414. if (!PythonToMapKey(key, self->key_field_descriptor, &map_key)) {
  415. return NULL;
  416. }
  417. if (reflection->InsertOrLookupMapValue(message, self->parent_field_descriptor,
  418. map_key, &value)) {
  419. self->version++;
  420. }
  421. return MapValueRefToPython(self->value_field_descriptor, value);
  422. }
  423. int MapReflectionFriend::ScalarMapSetItem(PyObject* _self, PyObject* key,
  424. PyObject* v) {
  425. MapContainer* self = GetMap(_self);
  426. Message* message = self->GetMutableMessage();
  427. const Reflection* reflection = message->GetReflection();
  428. MapKey map_key;
  429. MapValueRef value;
  430. if (!PythonToMapKey(key, self->key_field_descriptor, &map_key)) {
  431. return -1;
  432. }
  433. self->version++;
  434. if (v) {
  435. // Set item to v.
  436. reflection->InsertOrLookupMapValue(message, self->parent_field_descriptor,
  437. map_key, &value);
  438. return PythonToMapValueRef(v, self->value_field_descriptor,
  439. reflection->SupportsUnknownEnumValues(), &value)
  440. ? 0
  441. : -1;
  442. } else {
  443. // Delete key from map.
  444. if (reflection->DeleteMapValue(message, self->parent_field_descriptor,
  445. map_key)) {
  446. return 0;
  447. } else {
  448. PyErr_Format(PyExc_KeyError, "Key not present in map");
  449. return -1;
  450. }
  451. }
  452. }
  453. static PyObject* ScalarMapGet(PyObject* self, PyObject* args) {
  454. PyObject* key;
  455. PyObject* default_value = NULL;
  456. if (PyArg_ParseTuple(args, "O|O", &key, &default_value) < 0) {
  457. return NULL;
  458. }
  459. ScopedPyObjectPtr is_present(MapReflectionFriend::Contains(self, key));
  460. if (is_present.get() == NULL) {
  461. return NULL;
  462. }
  463. if (PyObject_IsTrue(is_present.get())) {
  464. return MapReflectionFriend::ScalarMapGetItem(self, key);
  465. } else {
  466. if (default_value != NULL) {
  467. Py_INCREF(default_value);
  468. return default_value;
  469. } else {
  470. Py_RETURN_NONE;
  471. }
  472. }
  473. }
  474. PyObject* MapReflectionFriend::ScalarMapToStr(PyObject* _self) {
  475. ScopedPyObjectPtr dict(PyDict_New());
  476. if (dict == NULL) {
  477. return NULL;
  478. }
  479. ScopedPyObjectPtr key;
  480. ScopedPyObjectPtr value;
  481. MapContainer* self = GetMap(_self);
  482. Message* message = self->GetMutableMessage();
  483. const Reflection* reflection = message->GetReflection();
  484. for (google::protobuf::MapIterator it = reflection->MapBegin(
  485. message, self->parent_field_descriptor);
  486. it != reflection->MapEnd(message, self->parent_field_descriptor);
  487. ++it) {
  488. key.reset(MapKeyToPython(self->key_field_descriptor,
  489. it.GetKey()));
  490. if (key == NULL) {
  491. return NULL;
  492. }
  493. value.reset(MapValueRefToPython(self->value_field_descriptor,
  494. it.GetValueRef()));
  495. if (value == NULL) {
  496. return NULL;
  497. }
  498. if (PyDict_SetItem(dict.get(), key.get(), value.get()) < 0) {
  499. return NULL;
  500. }
  501. }
  502. return PyObject_Repr(dict.get());
  503. }
  504. static void ScalarMapDealloc(PyObject* _self) {
  505. MapContainer* self = GetMap(_self);
  506. self->owner.reset();
  507. PyTypeObject *type = Py_TYPE(_self);
  508. type->tp_free(_self);
  509. if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) {
  510. // With Python3, the Map class is not static, and must be managed.
  511. Py_DECREF(type);
  512. }
  513. }
  514. static PyMethodDef ScalarMapMethods[] = {
  515. { "__contains__", MapReflectionFriend::Contains, METH_O,
  516. "Tests whether a key is a member of the map." },
  517. { "clear", (PyCFunction)Clear, METH_NOARGS,
  518. "Removes all elements from the map." },
  519. { "get", ScalarMapGet, METH_VARARGS,
  520. "Gets the value for the given key if present, or otherwise a default" },
  521. { "GetEntryClass", (PyCFunction)GetEntryClass, METH_NOARGS,
  522. "Return the class used to build Entries of (key, value) pairs." },
  523. { "MergeFrom", (PyCFunction)MapReflectionFriend::MergeFrom, METH_O,
  524. "Merges a map into the current map." },
  525. /*
  526. { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS,
  527. "Makes a deep copy of the class." },
  528. { "__reduce__", (PyCFunction)Reduce, METH_NOARGS,
  529. "Outputs picklable representation of the repeated field." },
  530. */
  531. {NULL, NULL},
  532. };
  533. PyTypeObject *ScalarMapContainer_Type;
  534. #if PY_MAJOR_VERSION >= 3
  535. static PyType_Slot ScalarMapContainer_Type_slots[] = {
  536. {Py_tp_dealloc, (void *)ScalarMapDealloc},
  537. {Py_mp_length, (void *)MapReflectionFriend::Length},
  538. {Py_mp_subscript, (void *)MapReflectionFriend::ScalarMapGetItem},
  539. {Py_mp_ass_subscript, (void *)MapReflectionFriend::ScalarMapSetItem},
  540. {Py_tp_methods, (void *)ScalarMapMethods},
  541. {Py_tp_iter, (void *)MapReflectionFriend::GetIterator},
  542. {Py_tp_repr, (void *)MapReflectionFriend::ScalarMapToStr},
  543. {0, 0},
  544. };
  545. PyType_Spec ScalarMapContainer_Type_spec = {
  546. FULL_MODULE_NAME ".ScalarMapContainer",
  547. sizeof(MapContainer),
  548. 0,
  549. Py_TPFLAGS_DEFAULT,
  550. ScalarMapContainer_Type_slots
  551. };
  552. #else
  553. static PyMappingMethods ScalarMapMappingMethods = {
  554. MapReflectionFriend::Length, // mp_length
  555. MapReflectionFriend::ScalarMapGetItem, // mp_subscript
  556. MapReflectionFriend::ScalarMapSetItem, // mp_ass_subscript
  557. };
  558. PyTypeObject _ScalarMapContainer_Type = {
  559. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  560. FULL_MODULE_NAME ".ScalarMapContainer", // tp_name
  561. sizeof(MapContainer), // tp_basicsize
  562. 0, // tp_itemsize
  563. ScalarMapDealloc, // tp_dealloc
  564. 0, // tp_print
  565. 0, // tp_getattr
  566. 0, // tp_setattr
  567. 0, // tp_compare
  568. MapReflectionFriend::ScalarMapToStr, // tp_repr
  569. 0, // tp_as_number
  570. 0, // tp_as_sequence
  571. &ScalarMapMappingMethods, // tp_as_mapping
  572. 0, // tp_hash
  573. 0, // tp_call
  574. 0, // tp_str
  575. 0, // tp_getattro
  576. 0, // tp_setattro
  577. 0, // tp_as_buffer
  578. Py_TPFLAGS_DEFAULT, // tp_flags
  579. "A scalar map container", // tp_doc
  580. 0, // tp_traverse
  581. 0, // tp_clear
  582. 0, // tp_richcompare
  583. 0, // tp_weaklistoffset
  584. MapReflectionFriend::GetIterator, // tp_iter
  585. 0, // tp_iternext
  586. ScalarMapMethods, // tp_methods
  587. 0, // tp_members
  588. 0, // tp_getset
  589. 0, // tp_base
  590. 0, // tp_dict
  591. 0, // tp_descr_get
  592. 0, // tp_descr_set
  593. 0, // tp_dictoffset
  594. 0, // tp_init
  595. };
  596. #endif
  597. // MessageMap //////////////////////////////////////////////////////////////////
  598. static MessageMapContainer* GetMessageMap(PyObject* obj) {
  599. return reinterpret_cast<MessageMapContainer*>(obj);
  600. }
  601. static PyObject* GetCMessage(MessageMapContainer* self, Message* message,
  602. bool insert_message_dict) {
  603. // Get or create the CMessage object corresponding to this message.
  604. ScopedPyObjectPtr key(PyLong_FromVoidPtr(message));
  605. PyObject* ret = PyDict_GetItem(self->message_dict, key.get());
  606. if (ret == NULL) {
  607. CMessage* cmsg = cmessage::NewEmptyMessage(self->message_class);
  608. ret = reinterpret_cast<PyObject*>(cmsg);
  609. if (cmsg == NULL) {
  610. return NULL;
  611. }
  612. cmsg->owner = self->owner;
  613. cmsg->message = message;
  614. cmsg->parent = self->parent;
  615. if (insert_message_dict) {
  616. if (PyDict_SetItem(self->message_dict, key.get(), ret) < 0) {
  617. Py_DECREF(ret);
  618. return NULL;
  619. }
  620. }
  621. } else {
  622. Py_INCREF(ret);
  623. }
  624. return ret;
  625. }
  626. PyObject* NewMessageMapContainer(
  627. CMessage* parent, const google::protobuf::FieldDescriptor* parent_field_descriptor,
  628. CMessageClass* message_class) {
  629. if (!CheckFieldBelongsToMessage(parent_field_descriptor, parent->message)) {
  630. return NULL;
  631. }
  632. PyObject* obj = PyType_GenericAlloc(MessageMapContainer_Type, 0);
  633. if (obj == NULL) {
  634. return PyErr_Format(PyExc_RuntimeError,
  635. "Could not allocate new container.");
  636. }
  637. MessageMapContainer* self = GetMessageMap(obj);
  638. self->message = parent->message;
  639. self->parent = parent;
  640. self->parent_field_descriptor = parent_field_descriptor;
  641. self->owner = parent->owner;
  642. self->version = 0;
  643. self->key_field_descriptor =
  644. parent_field_descriptor->message_type()->FindFieldByName("key");
  645. self->value_field_descriptor =
  646. parent_field_descriptor->message_type()->FindFieldByName("value");
  647. self->message_dict = PyDict_New();
  648. if (self->message_dict == NULL) {
  649. return PyErr_Format(PyExc_RuntimeError,
  650. "Could not allocate message dict.");
  651. }
  652. Py_INCREF(message_class);
  653. self->message_class = message_class;
  654. if (self->key_field_descriptor == NULL ||
  655. self->value_field_descriptor == NULL) {
  656. Py_DECREF(obj);
  657. return PyErr_Format(PyExc_KeyError,
  658. "Map entry descriptor did not have key/value fields");
  659. }
  660. return obj;
  661. }
  662. int MapReflectionFriend::MessageMapSetItem(PyObject* _self, PyObject* key,
  663. PyObject* v) {
  664. if (v) {
  665. PyErr_Format(PyExc_ValueError,
  666. "Direct assignment of submessage not allowed");
  667. return -1;
  668. }
  669. // Now we know that this is a delete, not a set.
  670. MessageMapContainer* self = GetMessageMap(_self);
  671. Message* message = self->GetMutableMessage();
  672. const Reflection* reflection = message->GetReflection();
  673. MapKey map_key;
  674. MapValueRef value;
  675. self->version++;
  676. if (!PythonToMapKey(key, self->key_field_descriptor, &map_key)) {
  677. return -1;
  678. }
  679. // Delete key from map.
  680. if (reflection->ContainsMapKey(*message, self->parent_field_descriptor,
  681. map_key)) {
  682. // Delete key from CMessage dict.
  683. MapValueRef value;
  684. reflection->InsertOrLookupMapValue(message, self->parent_field_descriptor,
  685. map_key, &value);
  686. ScopedPyObjectPtr key(PyLong_FromVoidPtr(value.MutableMessageValue()));
  687. PyObject* cmsg_value = PyDict_GetItem(self->message_dict, key.get());
  688. if (cmsg_value) {
  689. // Need to keep CMessage stay alive if it is still referenced after
  690. // deletion. Makes a new message and swaps values into CMessage
  691. // instead of just removing.
  692. CMessage* cmsg = reinterpret_cast<CMessage*>(cmsg_value);
  693. Message* msg = cmsg->message;
  694. cmsg->owner.reset(msg->New());
  695. cmsg->message = cmsg->owner.get();
  696. cmsg->parent = NULL;
  697. msg->GetReflection()->Swap(msg, cmsg->message);
  698. if (PyDict_DelItem(self->message_dict, key.get()) < 0) {
  699. return -1;
  700. }
  701. }
  702. // Delete key from map.
  703. reflection->DeleteMapValue(message, self->parent_field_descriptor,
  704. map_key);
  705. return 0;
  706. } else {
  707. PyErr_Format(PyExc_KeyError, "Key not present in map");
  708. return -1;
  709. }
  710. }
  711. PyObject* MapReflectionFriend::MessageMapGetItem(PyObject* _self,
  712. PyObject* key) {
  713. MessageMapContainer* self = GetMessageMap(_self);
  714. Message* message = self->GetMutableMessage();
  715. const Reflection* reflection = message->GetReflection();
  716. MapKey map_key;
  717. MapValueRef value;
  718. if (!PythonToMapKey(key, self->key_field_descriptor, &map_key)) {
  719. return NULL;
  720. }
  721. if (reflection->InsertOrLookupMapValue(message, self->parent_field_descriptor,
  722. map_key, &value)) {
  723. self->version++;
  724. }
  725. return GetCMessage(self, value.MutableMessageValue(), true);
  726. }
  727. PyObject* MapReflectionFriend::MessageMapToStr(PyObject* _self) {
  728. ScopedPyObjectPtr dict(PyDict_New());
  729. if (dict == NULL) {
  730. return NULL;
  731. }
  732. ScopedPyObjectPtr key;
  733. ScopedPyObjectPtr value;
  734. MessageMapContainer* self = GetMessageMap(_self);
  735. Message* message = self->GetMutableMessage();
  736. const Reflection* reflection = message->GetReflection();
  737. for (google::protobuf::MapIterator it = reflection->MapBegin(
  738. message, self->parent_field_descriptor);
  739. it != reflection->MapEnd(message, self->parent_field_descriptor);
  740. ++it) {
  741. key.reset(MapKeyToPython(self->key_field_descriptor,
  742. it.GetKey()));
  743. if (key == NULL) {
  744. return NULL;
  745. }
  746. // Do not insert the cmessage to self->message_dict because
  747. // the returned CMessage will not escape this function.
  748. value.reset(GetCMessage(
  749. self, it.MutableValueRef()->MutableMessageValue(), false));
  750. if (value == NULL) {
  751. return NULL;
  752. }
  753. if (PyDict_SetItem(dict.get(), key.get(), value.get()) < 0) {
  754. return NULL;
  755. }
  756. }
  757. return PyObject_Repr(dict.get());
  758. }
  759. PyObject* MessageMapGet(PyObject* self, PyObject* args) {
  760. PyObject* key;
  761. PyObject* default_value = NULL;
  762. if (PyArg_ParseTuple(args, "O|O", &key, &default_value) < 0) {
  763. return NULL;
  764. }
  765. ScopedPyObjectPtr is_present(MapReflectionFriend::Contains(self, key));
  766. if (is_present.get() == NULL) {
  767. return NULL;
  768. }
  769. if (PyObject_IsTrue(is_present.get())) {
  770. return MapReflectionFriend::MessageMapGetItem(self, key);
  771. } else {
  772. if (default_value != NULL) {
  773. Py_INCREF(default_value);
  774. return default_value;
  775. } else {
  776. Py_RETURN_NONE;
  777. }
  778. }
  779. }
  780. static void MessageMapDealloc(PyObject* _self) {
  781. MessageMapContainer* self = GetMessageMap(_self);
  782. self->owner.reset();
  783. Py_DECREF(self->message_dict);
  784. Py_DECREF(self->message_class);
  785. PyTypeObject *type = Py_TYPE(_self);
  786. type->tp_free(_self);
  787. if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) {
  788. // With Python3, the Map class is not static, and must be managed.
  789. Py_DECREF(type);
  790. }
  791. }
  792. static PyMethodDef MessageMapMethods[] = {
  793. { "__contains__", (PyCFunction)MapReflectionFriend::Contains, METH_O,
  794. "Tests whether the map contains this element."},
  795. { "clear", (PyCFunction)Clear, METH_NOARGS,
  796. "Removes all elements from the map."},
  797. { "get", MessageMapGet, METH_VARARGS,
  798. "Gets the value for the given key if present, or otherwise a default" },
  799. { "get_or_create", MapReflectionFriend::MessageMapGetItem, METH_O,
  800. "Alias for getitem, useful to make explicit that the map is mutated." },
  801. { "GetEntryClass", (PyCFunction)GetEntryClass, METH_NOARGS,
  802. "Return the class used to build Entries of (key, value) pairs." },
  803. { "MergeFrom", (PyCFunction)MapReflectionFriend::MergeFrom, METH_O,
  804. "Merges a map into the current map." },
  805. /*
  806. { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS,
  807. "Makes a deep copy of the class." },
  808. { "__reduce__", (PyCFunction)Reduce, METH_NOARGS,
  809. "Outputs picklable representation of the repeated field." },
  810. */
  811. {NULL, NULL},
  812. };
  813. PyTypeObject *MessageMapContainer_Type;
  814. #if PY_MAJOR_VERSION >= 3
  815. static PyType_Slot MessageMapContainer_Type_slots[] = {
  816. {Py_tp_dealloc, (void *)MessageMapDealloc},
  817. {Py_mp_length, (void *)MapReflectionFriend::Length},
  818. {Py_mp_subscript, (void *)MapReflectionFriend::MessageMapGetItem},
  819. {Py_mp_ass_subscript, (void *)MapReflectionFriend::MessageMapSetItem},
  820. {Py_tp_methods, (void *)MessageMapMethods},
  821. {Py_tp_iter, (void *)MapReflectionFriend::GetIterator},
  822. {Py_tp_repr, (void *)MapReflectionFriend::MessageMapToStr},
  823. {0, 0}
  824. };
  825. PyType_Spec MessageMapContainer_Type_spec = {
  826. FULL_MODULE_NAME ".MessageMapContainer",
  827. sizeof(MessageMapContainer),
  828. 0,
  829. Py_TPFLAGS_DEFAULT,
  830. MessageMapContainer_Type_slots
  831. };
  832. #else
  833. static PyMappingMethods MessageMapMappingMethods = {
  834. MapReflectionFriend::Length, // mp_length
  835. MapReflectionFriend::MessageMapGetItem, // mp_subscript
  836. MapReflectionFriend::MessageMapSetItem, // mp_ass_subscript
  837. };
  838. PyTypeObject _MessageMapContainer_Type = {
  839. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  840. FULL_MODULE_NAME ".MessageMapContainer", // tp_name
  841. sizeof(MessageMapContainer), // tp_basicsize
  842. 0, // tp_itemsize
  843. MessageMapDealloc, // tp_dealloc
  844. 0, // tp_print
  845. 0, // tp_getattr
  846. 0, // tp_setattr
  847. 0, // tp_compare
  848. MapReflectionFriend::MessageMapToStr, // tp_repr
  849. 0, // tp_as_number
  850. 0, // tp_as_sequence
  851. &MessageMapMappingMethods, // tp_as_mapping
  852. 0, // tp_hash
  853. 0, // tp_call
  854. 0, // tp_str
  855. 0, // tp_getattro
  856. 0, // tp_setattro
  857. 0, // tp_as_buffer
  858. Py_TPFLAGS_DEFAULT, // tp_flags
  859. "A map container for message", // tp_doc
  860. 0, // tp_traverse
  861. 0, // tp_clear
  862. 0, // tp_richcompare
  863. 0, // tp_weaklistoffset
  864. MapReflectionFriend::GetIterator, // tp_iter
  865. 0, // tp_iternext
  866. MessageMapMethods, // tp_methods
  867. 0, // tp_members
  868. 0, // tp_getset
  869. 0, // tp_base
  870. 0, // tp_dict
  871. 0, // tp_descr_get
  872. 0, // tp_descr_set
  873. 0, // tp_dictoffset
  874. 0, // tp_init
  875. };
  876. #endif
  877. // MapIterator /////////////////////////////////////////////////////////////////
  878. static MapIterator* GetIter(PyObject* obj) {
  879. return reinterpret_cast<MapIterator*>(obj);
  880. }
  881. PyObject* MapReflectionFriend::GetIterator(PyObject *_self) {
  882. MapContainer* self = GetMap(_self);
  883. ScopedPyObjectPtr obj(PyType_GenericAlloc(&MapIterator_Type, 0));
  884. if (obj == NULL) {
  885. return PyErr_Format(PyExc_KeyError, "Could not allocate iterator");
  886. }
  887. MapIterator* iter = GetIter(obj.get());
  888. Py_INCREF(self);
  889. iter->container = self;
  890. iter->version = self->version;
  891. iter->owner = self->owner;
  892. if (MapReflectionFriend::Length(_self) > 0) {
  893. Message* message = self->GetMutableMessage();
  894. const Reflection* reflection = message->GetReflection();
  895. iter->iter.reset(new ::google::protobuf::MapIterator(
  896. reflection->MapBegin(message, self->parent_field_descriptor)));
  897. }
  898. return obj.release();
  899. }
  900. PyObject* MapReflectionFriend::IterNext(PyObject* _self) {
  901. MapIterator* self = GetIter(_self);
  902. // This won't catch mutations to the map performed by MergeFrom(); no easy way
  903. // to address that.
  904. if (self->version != self->container->version) {
  905. return PyErr_Format(PyExc_RuntimeError,
  906. "Map modified during iteration.");
  907. }
  908. if (self->iter.get() == NULL) {
  909. return NULL;
  910. }
  911. Message* message = self->container->GetMutableMessage();
  912. const Reflection* reflection = message->GetReflection();
  913. if (*self->iter ==
  914. reflection->MapEnd(message, self->container->parent_field_descriptor)) {
  915. return NULL;
  916. }
  917. PyObject* ret = MapKeyToPython(self->container->key_field_descriptor,
  918. self->iter->GetKey());
  919. ++(*self->iter);
  920. return ret;
  921. }
  922. static void DeallocMapIterator(PyObject* _self) {
  923. MapIterator* self = GetIter(_self);
  924. self->iter.reset();
  925. self->owner.reset();
  926. Py_XDECREF(self->container);
  927. Py_TYPE(_self)->tp_free(_self);
  928. }
  929. PyTypeObject MapIterator_Type = {
  930. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  931. FULL_MODULE_NAME ".MapIterator", // tp_name
  932. sizeof(MapIterator), // tp_basicsize
  933. 0, // tp_itemsize
  934. DeallocMapIterator, // tp_dealloc
  935. 0, // tp_print
  936. 0, // tp_getattr
  937. 0, // tp_setattr
  938. 0, // tp_compare
  939. 0, // tp_repr
  940. 0, // tp_as_number
  941. 0, // tp_as_sequence
  942. 0, // tp_as_mapping
  943. 0, // tp_hash
  944. 0, // tp_call
  945. 0, // tp_str
  946. 0, // tp_getattro
  947. 0, // tp_setattro
  948. 0, // tp_as_buffer
  949. Py_TPFLAGS_DEFAULT, // tp_flags
  950. "A scalar map iterator", // tp_doc
  951. 0, // tp_traverse
  952. 0, // tp_clear
  953. 0, // tp_richcompare
  954. 0, // tp_weaklistoffset
  955. PyObject_SelfIter, // tp_iter
  956. MapReflectionFriend::IterNext, // tp_iternext
  957. 0, // tp_methods
  958. 0, // tp_members
  959. 0, // tp_getset
  960. 0, // tp_base
  961. 0, // tp_dict
  962. 0, // tp_descr_get
  963. 0, // tp_descr_set
  964. 0, // tp_dictoffset
  965. 0, // tp_init
  966. };
  967. bool InitMapContainers() {
  968. // ScalarMapContainer_Type derives from our MutableMapping type.
  969. ScopedPyObjectPtr containers(PyImport_ImportModule(
  970. "google.protobuf.internal.containers"));
  971. if (containers == NULL) {
  972. return false;
  973. }
  974. ScopedPyObjectPtr mutable_mapping(
  975. PyObject_GetAttrString(containers.get(), "MutableMapping"));
  976. if (mutable_mapping == NULL) {
  977. return false;
  978. }
  979. Py_INCREF(mutable_mapping.get());
  980. #if PY_MAJOR_VERSION >= 3
  981. ScopedPyObjectPtr bases(PyTuple_Pack(1, mutable_mapping.get()));
  982. if (bases == NULL) {
  983. return false;
  984. }
  985. ScalarMapContainer_Type = reinterpret_cast<PyTypeObject*>(
  986. PyType_FromSpecWithBases(&ScalarMapContainer_Type_spec, bases.get()));
  987. #else
  988. _ScalarMapContainer_Type.tp_base =
  989. reinterpret_cast<PyTypeObject*>(mutable_mapping.get());
  990. if (PyType_Ready(&_ScalarMapContainer_Type) < 0) {
  991. return false;
  992. }
  993. ScalarMapContainer_Type = &_ScalarMapContainer_Type;
  994. #endif
  995. if (PyType_Ready(&MapIterator_Type) < 0) {
  996. return false;
  997. }
  998. #if PY_MAJOR_VERSION >= 3
  999. MessageMapContainer_Type = reinterpret_cast<PyTypeObject*>(
  1000. PyType_FromSpecWithBases(&MessageMapContainer_Type_spec, bases.get()));
  1001. #else
  1002. Py_INCREF(mutable_mapping.get());
  1003. _MessageMapContainer_Type.tp_base =
  1004. reinterpret_cast<PyTypeObject*>(mutable_mapping.get());
  1005. if (PyType_Ready(&_MessageMapContainer_Type) < 0) {
  1006. return false;
  1007. }
  1008. MessageMapContainer_Type = &_MessageMapContainer_Type;
  1009. #endif
  1010. return true;
  1011. }
  1012. } // namespace python
  1013. } // namespace protobuf
  1014. } // namespace google