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. 228 // Returns -1 on error. 229 // 230 // Corresponds to reflection api method ClearField. 231 int ClearFieldByDescriptor(CMessage* self, const FieldDescriptor* descriptor); 232 233 // Checks if the message has the field described by the descriptor. Used for 234 // extensions (which have no name). 235 // Returns 1 if true, 0 if false, and -1 on error. 236 // 237 // Corresponds to reflection api method HasField 238 int HasFieldByDescriptor(CMessage* self, 239 const FieldDescriptor* field_descriptor); 240 241 // Checks if the message has the named field. 242 // 243 // Corresponds to reflection api method HasField. 244 PyObject* HasField(CMessage* self, PyObject* arg); 245 246 // Initializes values of fields on a newly constructed message. 247 // Note that positional arguments are disallowed: 'args' must be NULL or the 248 // empty tuple. 249 int InitAttributes(CMessage* self, PyObject* args, PyObject* kwargs); 250 251 PyObject* MergeFrom(CMessage* self, PyObject* arg); 252 253 // This method does not do anything beyond checking that no other extension 254 // has been registered with the same field number on this class. 255 PyObject* RegisterExtension(PyObject* cls, PyObject* extension_handle); 256 257 // Get a field from a message. 258 PyObject* GetFieldValue(CMessage* self, 259 const FieldDescriptor* field_descriptor); 260 // Sets the value of a scalar field in a message. 261 // On error, return -1 with an extension set. 262 int SetFieldValue(CMessage* self, const FieldDescriptor* field_descriptor, 263 PyObject* value); 264 265 PyObject* FindInitializationErrors(CMessage* self); 266 267 int AssureWritable(CMessage* self); 268 269 // Returns the message factory for the given message. 270 // This is equivalent to message.MESSAGE_FACTORY 271 // 272 // The returned factory is suitable for finding fields and building submessages, 273 // even in the case of extensions. 274 // Returns a *borrowed* reference, and never fails because we pass a CMessage. 275 PyMessageFactory* GetFactoryForMessage(CMessage* message); 276 277 PyObject* SetAllowOversizeProtos(PyObject* m, PyObject* arg); 278 279 } // namespace cmessage 280 281 282 /* Is 64bit */ 283 #define IS_64BIT (SIZEOF_LONG == 8) 284 285 #define FIELD_IS_REPEATED(field_descriptor) \ 286 ((field_descriptor)->label() == FieldDescriptor::LABEL_REPEATED) 287 288 #define GOOGLE_CHECK_GET_INT32(arg, value, err) \ 289 int32 value; \ 290 if (!CheckAndGetInteger(arg, &value)) { \ 291 return err; \ 292 } 293 294 #define GOOGLE_CHECK_GET_INT64(arg, value, err) \ 295 int64 value; \ 296 if (!CheckAndGetInteger(arg, &value)) { \ 297 return err; \ 298 } 299 300 #define GOOGLE_CHECK_GET_UINT32(arg, value, err) \ 301 uint32 value; \ 302 if (!CheckAndGetInteger(arg, &value)) { \ 303 return err; \ 304 } 305 306 #define GOOGLE_CHECK_GET_UINT64(arg, value, err) \ 307 uint64 value; \ 308 if (!CheckAndGetInteger(arg, &value)) { \ 309 return err; \ 310 } 311 312 #define GOOGLE_CHECK_GET_FLOAT(arg, value, err) \ 313 float value; \ 314 if (!CheckAndGetFloat(arg, &value)) { \ 315 return err; \ 316 } \ 317 318 #define GOOGLE_CHECK_GET_DOUBLE(arg, value, err) \ 319 double value; \ 320 if (!CheckAndGetDouble(arg, &value)) { \ 321 return err; \ 322 } 323 324 #define GOOGLE_CHECK_GET_BOOL(arg, value, err) \ 325 bool value; \ 326 if (!CheckAndGetBool(arg, &value)) { \ 327 return err; \ 328 } 329 330 331 #define FULL_MODULE_NAME "google.protobuf.pyext._message" 332 333 void FormatTypeError(PyObject* arg, char* expected_types); 334 template<class T> 335 bool CheckAndGetInteger(PyObject* arg, T* value); 336 bool CheckAndGetDouble(PyObject* arg, double* value); 337 bool CheckAndGetFloat(PyObject* arg, float* value); 338 bool CheckAndGetBool(PyObject* arg, bool* value); 339 PyObject* CheckString(PyObject* arg, const FieldDescriptor* descriptor); 340 bool CheckAndSetString( 341 PyObject* arg, Message* message, 342 const FieldDescriptor* descriptor, 343 const Reflection* reflection, 344 bool append, 345 int index); 346 PyObject* ToStringObject(const FieldDescriptor* descriptor, 347 const std::string& value); 348 349 // Check if the passed field descriptor belongs to the given message. 350 // If not, return false and set a Python exception (a KeyError) 351 bool CheckFieldBelongsToMessage(const FieldDescriptor* field_descriptor, 352 const Message* message); 353 354 extern PyObject* PickleError_class; 355 356 const Message* PyMessage_GetMessagePointer(PyObject* msg); 357 Message* PyMessage_GetMutableMessagePointer(PyObject* msg); 358 PyObject* PyMessage_NewMessageOwnedExternally(Message* message, 359 PyObject* message_factory); 360 361 bool InitProto2MessageModule(PyObject *m); 362 363 // These are referenced by repeated_scalar_container, and must 364 // be explicitly instantiated. 365 extern template bool CheckAndGetInteger<int32>(PyObject*, int32*); 366 extern template bool CheckAndGetInteger<int64>(PyObject*, int64*); 367 extern template bool CheckAndGetInteger<uint32>(PyObject*, uint32*); 368 extern template bool CheckAndGetInteger<uint64>(PyObject*, uint64*); 369 370 } // namespace python 371 } // namespace protobuf 372 } // namespace google 373 374 #endif // GOOGLE_PROTOBUF_PYTHON_CPP_MESSAGE_H__ 375