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 31 // Author: anuraag@google.com (Anuraag Agrawal) 32 // Author: tibell@google.com (Johan Tibell) 33 34 #ifndef GOOGLE_PROTOBUF_PYTHON_CPP_MESSAGE_H__ 35 #define GOOGLE_PROTOBUF_PYTHON_CPP_MESSAGE_H__ 36 37 #include <Python.h> 38 39 #include <memory> 40 #include <string> 41 #include <unordered_map> 42 43 #include <google/protobuf/stubs/common.h> 44 45 namespace google { 46 namespace protobuf { 47 48 class Message; 49 class Reflection; 50 class FieldDescriptor; 51 class Descriptor; 52 class DescriptorPool; 53 class MessageFactory; 54 55 namespace python { 56 57 struct ExtensionDict; 58 struct PyMessageFactory; 59 struct CMessageClass; 60 61 // Most of the complexity of the Message class comes from the "Release" 62 // behavior: 63 // 64 // When a field is cleared, it is only detached from its message. Existing 65 // references to submessages, to repeated container etc. won't see any change, 66 // as if the data was effectively managed by these containers. 67 // 68 // ExtensionDicts and UnknownFields containers do NOT follow this rule. They 69 // don't store any data, and always refer to their parent message. 70 71 struct ContainerBase { 72 PyObject_HEAD; 73 74 // Strong reference to a parent message object. For a CMessage there are three 75 // cases: 76 // - For a top-level message, this pointer is NULL. 77 // - For a sub-message, this points to the parent message. 78 // - For a message managed externally, this is a owned reference to Py_None. 79 // 80 // For all other types: repeated containers, maps, it always point to a 81 // valid parent CMessage. 82 struct CMessage* parent; 83 84 // If this object belongs to a parent message, describes which field it comes 85 // from. 86 // The pointer is owned by the DescriptorPool (which is kept alive 87 // through the message's Python class) 88 const FieldDescriptor* parent_field_descriptor; 89 AsPyObjectContainerBase90 PyObject* AsPyObject() { return reinterpret_cast<PyObject*>(this); } 91 92 // The Three methods below are only used by Repeated containers, and Maps. 93 94 // This implementation works for all containers which have a parent. 95 PyObject* DeepCopy(); 96 // Delete this container object from its parent. Does not work for messages. 97 void RemoveFromParentCache(); 98 }; 99 100 typedef struct CMessage : public ContainerBase { 101 // Pointer to the C++ Message object for this CMessage. 102 // - If this object has no parent, we own this pointer. 103 // - If this object has a parent message, the parent owns this pointer. 104 Message* message; 105 106 // Indicates this submessage is pointing to a default instance of a message. 107 // Submessages are always first created as read only messages and are then 108 // made writable, at which point this field is set to false. 109 bool read_only; 110 111 // A mapping indexed by field, containing weak references to contained objects 112 // which need to implement the "Release" mechanism: 113 // direct submessages, RepeatedCompositeContainer, RepeatedScalarContainer 114 // and MapContainer. 115 typedef std::unordered_map<const FieldDescriptor*, ContainerBase*> 116 CompositeFieldsMap; 117 CompositeFieldsMap* composite_fields; 118 119 // A mapping containing weak references to indirect child messages, accessed 120 // through containers: repeated messages, and values of message maps. 121 // This avoid the creation of similar maps in each of those containers. 122 typedef std::unordered_map<const Message*, CMessage*> SubMessagesMap; 123 SubMessagesMap* child_submessages; 124 125 // A reference to PyUnknownFields. 126 PyObject* unknown_field_set; 127 128 // Implements the "weakref" protocol for this object. 129 PyObject* weakreflist; 130 131 // Return a *borrowed* reference to the message class. GetMessageClassCMessage132 CMessageClass* GetMessageClass() { 133 return reinterpret_cast<CMessageClass*>(Py_TYPE(this)); 134 } 135 136 // For container containing messages, return a Python object for the given 137 // pointer to a message. 138 CMessage* BuildSubMessageFromPointer(const FieldDescriptor* field_descriptor, 139 Message* sub_message, 140 CMessageClass* message_class); 141 CMessage* MaybeReleaseSubMessage(Message* sub_message); 142 } CMessage; 143 144 // The (meta) type of all Messages classes. 145 // It allows us to cache some C++ pointers in the class object itself, they are 146 // faster to extract than from the type's dictionary. 147 148 struct CMessageClass { 149 // This is how CPython subclasses C structures: the base structure must be 150 // the first member of the object. 151 PyHeapTypeObject super; 152 153 // C++ descriptor of this message. 154 const Descriptor* message_descriptor; 155 156 // Owned reference, used to keep the pointer above alive. 157 // This reference must stay alive until all message pointers are destructed. 158 PyObject* py_message_descriptor; 159 160 // The Python MessageFactory used to create the class. It is needed to resolve 161 // fields descriptors, including extensions fields; its C++ MessageFactory is 162 // used to instantiate submessages. 163 // This reference must stay alive until all message pointers are destructed. 164 PyMessageFactory* py_message_factory; 165 AsPyObjectCMessageClass166 PyObject* AsPyObject() { 167 return reinterpret_cast<PyObject*>(this); 168 } 169 }; 170 171 extern PyTypeObject* CMessageClass_Type; 172 extern PyTypeObject* CMessage_Type; 173 174 namespace cmessage { 175 176 // Internal function to create a new empty Message Python object, but with empty 177 // pointers to the C++ objects. 178 // The caller must fill self->message, self->owner and eventually self->parent. 179 CMessage* NewEmptyMessage(CMessageClass* type); 180 181 // Retrieves the C++ descriptor of a Python Extension descriptor. 182 // On error, return NULL with an exception set. 183 const FieldDescriptor* GetExtensionDescriptor(PyObject* extension); 184 185 // Initializes a new CMessage instance for a submessage. Only called once per 186 // submessage as the result is cached in composite_fields. 187 // 188 // Corresponds to reflection api method GetMessage. 189 CMessage* InternalGetSubMessage( 190 CMessage* self, const FieldDescriptor* field_descriptor); 191 192 // Deletes a range of items in a repeated field (following a 193 // removal in a RepeatedCompositeContainer). 194 // 195 // Corresponds to reflection api method RemoveLast. 196 int DeleteRepeatedField(CMessage* self, 197 const FieldDescriptor* field_descriptor, 198 PyObject* slice); 199 200 // Sets the specified scalar value to the message. 201 int InternalSetScalar(CMessage* self, 202 const FieldDescriptor* field_descriptor, 203 PyObject* value); 204 205 // Sets the specified scalar value to the message. Requires it is not a Oneof. 206 int InternalSetNonOneofScalar(Message* message, 207 const FieldDescriptor* field_descriptor, 208 PyObject* arg); 209 210 // Retrieves the specified scalar value from the message. 211 // 212 // Returns a new python reference. 213 PyObject* InternalGetScalar(const Message* message, 214 const FieldDescriptor* field_descriptor); 215 216 bool SetCompositeField(CMessage* self, const FieldDescriptor* field, 217 ContainerBase* value); 218 219 bool SetSubmessage(CMessage* self, CMessage* submessage); 220 221 // Clears the message, removing all contained data. Extension dictionary and 222 // submessages are released first if there are remaining external references. 223 // 224 // Corresponds to message api method Clear. 225 PyObject* Clear(CMessage* self); 226 227 // Clears the data described by the given descriptor. Used to clear extensions 228 // (which don't have names). Extension release is handled by ExtensionDict 229 // class, not this function. 230 // TODO(anuraag): Try to make this discrepancy in release semantics with 231 // ClearField less confusing. 232 // 233 // Corresponds to reflection api method ClearField. 234 PyObject* ClearFieldByDescriptor( 235 CMessage* self, const FieldDescriptor* descriptor); 236 237 // Clears the data for the given field name. The message is released if there 238 // are any external references. 239 // 240 // Corresponds to reflection api method ClearField. 241 PyObject* ClearField(CMessage* self, PyObject* arg); 242 243 // Checks if the message has the field described by the descriptor. Used for 244 // extensions (which have no name). 245 // 246 // Corresponds to reflection api method HasField 247 PyObject* HasFieldByDescriptor( 248 CMessage* self, const FieldDescriptor* field_descriptor); 249 250 // Checks if the message has the named field. 251 // 252 // Corresponds to reflection api method HasField. 253 PyObject* HasField(CMessage* self, PyObject* arg); 254 255 // Initializes values of fields on a newly constructed message. 256 // Note that positional arguments are disallowed: 'args' must be NULL or the 257 // empty tuple. 258 int InitAttributes(CMessage* self, PyObject* args, PyObject* kwargs); 259 260 PyObject* MergeFrom(CMessage* self, PyObject* arg); 261 262 // This method does not do anything beyond checking that no other extension 263 // has been registered with the same field number on this class. 264 PyObject* RegisterExtension(PyObject* cls, PyObject* extension_handle); 265 266 // Get a field from a message. 267 PyObject* GetFieldValue(CMessage* self, 268 const FieldDescriptor* field_descriptor); 269 // Sets the value of a scalar field in a message. 270 // On error, return -1 with an extension set. 271 int SetFieldValue(CMessage* self, const FieldDescriptor* field_descriptor, 272 PyObject* value); 273 274 PyObject* FindInitializationErrors(CMessage* self); 275 276 int AssureWritable(CMessage* self); 277 278 // Returns the message factory for the given message. 279 // This is equivalent to message.MESSAGE_FACTORY 280 // 281 // The returned factory is suitable for finding fields and building submessages, 282 // even in the case of extensions. 283 // Returns a *borrowed* reference, and never fails because we pass a CMessage. 284 PyMessageFactory* GetFactoryForMessage(CMessage* message); 285 286 PyObject* SetAllowOversizeProtos(PyObject* m, PyObject* arg); 287 288 } // namespace cmessage 289 290 291 /* Is 64bit */ 292 #define IS_64BIT (SIZEOF_LONG == 8) 293 294 #define FIELD_IS_REPEATED(field_descriptor) \ 295 ((field_descriptor)->label() == FieldDescriptor::LABEL_REPEATED) 296 297 #define GOOGLE_CHECK_GET_INT32(arg, value, err) \ 298 int32 value; \ 299 if (!CheckAndGetInteger(arg, &value)) { \ 300 return err; \ 301 } 302 303 #define GOOGLE_CHECK_GET_INT64(arg, value, err) \ 304 int64 value; \ 305 if (!CheckAndGetInteger(arg, &value)) { \ 306 return err; \ 307 } 308 309 #define GOOGLE_CHECK_GET_UINT32(arg, value, err) \ 310 uint32 value; \ 311 if (!CheckAndGetInteger(arg, &value)) { \ 312 return err; \ 313 } 314 315 #define GOOGLE_CHECK_GET_UINT64(arg, value, err) \ 316 uint64 value; \ 317 if (!CheckAndGetInteger(arg, &value)) { \ 318 return err; \ 319 } 320 321 #define GOOGLE_CHECK_GET_FLOAT(arg, value, err) \ 322 float value; \ 323 if (!CheckAndGetFloat(arg, &value)) { \ 324 return err; \ 325 } \ 326 327 #define GOOGLE_CHECK_GET_DOUBLE(arg, value, err) \ 328 double value; \ 329 if (!CheckAndGetDouble(arg, &value)) { \ 330 return err; \ 331 } 332 333 #define GOOGLE_CHECK_GET_BOOL(arg, value, err) \ 334 bool value; \ 335 if (!CheckAndGetBool(arg, &value)) { \ 336 return err; \ 337 } 338 339 340 #define FULL_MODULE_NAME "google.protobuf.pyext._message" 341 342 void FormatTypeError(PyObject* arg, char* expected_types); 343 template<class T> 344 bool CheckAndGetInteger(PyObject* arg, T* value); 345 bool CheckAndGetDouble(PyObject* arg, double* value); 346 bool CheckAndGetFloat(PyObject* arg, float* value); 347 bool CheckAndGetBool(PyObject* arg, bool* value); 348 PyObject* CheckString(PyObject* arg, const FieldDescriptor* descriptor); 349 bool CheckAndSetString( 350 PyObject* arg, Message* message, 351 const FieldDescriptor* descriptor, 352 const Reflection* reflection, 353 bool append, 354 int index); 355 PyObject* ToStringObject(const FieldDescriptor* descriptor, 356 const string& value); 357 358 // Check if the passed field descriptor belongs to the given message. 359 // If not, return false and set a Python exception (a KeyError) 360 bool CheckFieldBelongsToMessage(const FieldDescriptor* field_descriptor, 361 const Message* message); 362 363 extern PyObject* PickleError_class; 364 365 const Message* PyMessage_GetMessagePointer(PyObject* msg); 366 Message* PyMessage_GetMutableMessagePointer(PyObject* msg); 367 PyObject* PyMessage_NewMessageOwnedExternally(Message* message, 368 PyObject* message_factory); 369 370 bool InitProto2MessageModule(PyObject *m); 371 372 // These are referenced by repeated_scalar_container, and must 373 // be explicitly instantiated. 374 extern template bool CheckAndGetInteger<int32>(PyObject*, int32*); 375 extern template bool CheckAndGetInteger<int64>(PyObject*, int64*); 376 extern template bool CheckAndGetInteger<uint32>(PyObject*, uint32*); 377 extern template bool CheckAndGetInteger<uint64>(PyObject*, uint64*); 378 379 } // namespace python 380 } // namespace protobuf 381 } // namespace google 382 383 #endif // GOOGLE_PROTOBUF_PYTHON_CPP_MESSAGE_H__ 384