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 #ifndef _SHARED_PTR_H 41 #include <google/protobuf/stubs/shared_ptr.h> 42 #endif 43 #include <string> 44 45 46 namespace google { 47 namespace protobuf { 48 49 class Message; 50 class Reflection; 51 class FieldDescriptor; 52 53 using internal::shared_ptr; 54 55 namespace python { 56 57 struct CFieldDescriptor; 58 struct ExtensionDict; 59 60 typedef struct CMessage { 61 PyObject_HEAD; 62 63 // This is the top-level C++ Message object that owns the whole 64 // proto tree. Every Python CMessage holds a reference to it in 65 // order to keep it alive as long as there's a Python object that 66 // references any part of the tree. 67 shared_ptr<Message> owner; 68 69 // Weak reference to a parent CMessage object. This is NULL for any top-level 70 // message and is set for any child message (i.e. a child submessage or a 71 // part of a repeated composite field). 72 // 73 // Used to make sure all ancestors are also mutable when first modifying 74 // a child submessage (in other words, turning a default message instance 75 // into a mutable one). 76 // 77 // If a submessage is released (becomes a new top-level message), this field 78 // MUST be set to NULL. The parent may get deallocated and further attempts 79 // to use this pointer will result in a crash. 80 struct CMessage* parent; 81 82 // Weak reference to the parent's descriptor that describes this submessage. 83 // Used together with the parent's message when making a default message 84 // instance mutable. 85 // TODO(anuraag): With a bit of work on the Python/C++ layer, it should be 86 // possible to make this a direct pointer to a C++ FieldDescriptor, this would 87 // be easier if this implementation replaces upstream. 88 CFieldDescriptor* parent_field; 89 90 // Pointer to the C++ Message object for this CMessage. The 91 // CMessage does not own this pointer. 92 Message* message; 93 94 // Indicates this submessage is pointing to a default instance of a message. 95 // Submessages are always first created as read only messages and are then 96 // made writable, at which point this field is set to false. 97 bool read_only; 98 99 // A reference to a Python dictionary containing CMessage, 100 // RepeatedCompositeContainer, and RepeatedScalarContainer 101 // objects. Used as a cache to make sure we don't have to make a 102 // Python wrapper for the C++ Message objects on every access, or 103 // deal with the synchronization nightmare that could create. 104 PyObject* composite_fields; 105 106 // A reference to the dictionary containing the message's extensions. 107 // Similar to composite_fields, acting as a cache, but also contains the 108 // required extension dict logic. 109 ExtensionDict* extensions; 110 } CMessage; 111 112 extern PyTypeObject CMessage_Type; 113 114 namespace cmessage { 115 116 // Create a new empty message that can be populated by the parent. 117 PyObject* NewEmpty(PyObject* type); 118 119 // Release a submessage from its proto tree, making it a new top-level messgae. 120 // A new message will be created if this is a read-only default instance. 121 // 122 // Corresponds to reflection api method ReleaseMessage. 123 int ReleaseSubMessage(google::protobuf::Message* message, 124 const google::protobuf::FieldDescriptor* field_descriptor, 125 CMessage* child_cmessage); 126 127 // Initializes a new CMessage instance for a submessage. Only called once per 128 // submessage as the result is cached in composite_fields. 129 // 130 // Corresponds to reflection api method GetMessage. 131 PyObject* InternalGetSubMessage(CMessage* self, 132 CFieldDescriptor* cfield_descriptor); 133 134 // Deletes a range of C++ submessages in a repeated field (following a 135 // removal in a RepeatedCompositeContainer). 136 // 137 // Releases messages to the provided cmessage_list if it is not NULL rather 138 // than just removing them from the underlying proto. This cmessage_list must 139 // have a CMessage for each underlying submessage. The CMessages refered to 140 // by slice will be removed from cmessage_list by this function. 141 // 142 // Corresponds to reflection api method RemoveLast. 143 int InternalDeleteRepeatedField(google::protobuf::Message* message, 144 const google::protobuf::FieldDescriptor* field_descriptor, 145 PyObject* slice, PyObject* cmessage_list); 146 147 // Sets the specified scalar value to the message. 148 int InternalSetScalar(CMessage* self, 149 const google::protobuf::FieldDescriptor* field_descriptor, 150 PyObject* value); 151 152 // Retrieves the specified scalar value from the message. 153 // 154 // Returns a new python reference. 155 PyObject* InternalGetScalar(CMessage* self, 156 const google::protobuf::FieldDescriptor* field_descriptor); 157 158 // Clears the message, removing all contained data. Extension dictionary and 159 // submessages are released first if there are remaining external references. 160 // 161 // Corresponds to message api method Clear. 162 PyObject* Clear(CMessage* self); 163 164 // Clears the data described by the given descriptor. Used to clear extensions 165 // (which don't have names). Extension release is handled by ExtensionDict 166 // class, not this function. 167 // TODO(anuraag): Try to make this discrepancy in release semantics with 168 // ClearField less confusing. 169 // 170 // Corresponds to reflection api method ClearField. 171 PyObject* ClearFieldByDescriptor( 172 CMessage* self, 173 const google::protobuf::FieldDescriptor* descriptor); 174 175 // Clears the data for the given field name. The message is released if there 176 // are any external references. 177 // 178 // Corresponds to reflection api method ClearField. 179 PyObject* ClearField(CMessage* self, PyObject* arg); 180 181 // Checks if the message has the field described by the descriptor. Used for 182 // extensions (which have no name). 183 // 184 // Corresponds to reflection api method HasField 185 PyObject* HasFieldByDescriptor( 186 CMessage* self, const google::protobuf::FieldDescriptor* field_descriptor); 187 188 // Checks if the message has the named field. 189 // 190 // Corresponds to reflection api method HasField. 191 PyObject* HasField(CMessage* self, PyObject* arg); 192 193 // Initializes constants/enum values on a message. This is called by 194 // RepeatedCompositeContainer and ExtensionDict after calling the constructor. 195 // TODO(anuraag): Make it always called from within the constructor since it can 196 int InitAttributes(CMessage* self, PyObject* descriptor, PyObject* kwargs); 197 198 PyObject* MergeFrom(CMessage* self, PyObject* arg); 199 200 // Retrieves an attribute named 'name' from CMessage 'self'. Returns 201 // the attribute value on success, or NULL on failure. 202 // 203 // Returns a new reference. 204 PyObject* GetAttr(CMessage* self, PyObject* name); 205 206 // Set the value of the attribute named 'name', for CMessage 'self', 207 // to the value 'value'. Returns -1 on failure. 208 int SetAttr(CMessage* self, PyObject* name, PyObject* value); 209 210 PyObject* FindInitializationErrors(CMessage* self); 211 212 // Set the owner field of self and any children of self, recursively. 213 // Used when self is being released and thus has a new owner (the 214 // released Message.) 215 int SetOwner(CMessage* self, const shared_ptr<Message>& new_owner); 216 217 int AssureWritable(CMessage* self); 218 219 } // namespace cmessage 220 221 /* Is 64bit */ 222 #define IS_64BIT (SIZEOF_LONG == 8) 223 224 #define FIELD_BELONGS_TO_MESSAGE(field_descriptor, message) \ 225 ((message)->GetDescriptor() == (field_descriptor)->containing_type()) 226 227 #define FIELD_IS_REPEATED(field_descriptor) \ 228 ((field_descriptor)->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) 229 230 #define GOOGLE_CHECK_GET_INT32(arg, value, err) \ 231 int32 value; \ 232 if (!CheckAndGetInteger(arg, &value, kint32min_py, kint32max_py)) { \ 233 return err; \ 234 } 235 236 #define GOOGLE_CHECK_GET_INT64(arg, value, err) \ 237 int64 value; \ 238 if (!CheckAndGetInteger(arg, &value, kint64min_py, kint64max_py)) { \ 239 return err; \ 240 } 241 242 #define GOOGLE_CHECK_GET_UINT32(arg, value, err) \ 243 uint32 value; \ 244 if (!CheckAndGetInteger(arg, &value, kPythonZero, kuint32max_py)) { \ 245 return err; \ 246 } 247 248 #define GOOGLE_CHECK_GET_UINT64(arg, value, err) \ 249 uint64 value; \ 250 if (!CheckAndGetInteger(arg, &value, kPythonZero, kuint64max_py)) { \ 251 return err; \ 252 } 253 254 #define GOOGLE_CHECK_GET_FLOAT(arg, value, err) \ 255 float value; \ 256 if (!CheckAndGetFloat(arg, &value)) { \ 257 return err; \ 258 } \ 259 260 #define GOOGLE_CHECK_GET_DOUBLE(arg, value, err) \ 261 double value; \ 262 if (!CheckAndGetDouble(arg, &value)) { \ 263 return err; \ 264 } 265 266 #define GOOGLE_CHECK_GET_BOOL(arg, value, err) \ 267 bool value; \ 268 if (!CheckAndGetBool(arg, &value)) { \ 269 return err; \ 270 } 271 272 273 extern PyObject* kPythonZero; 274 extern PyObject* kint32min_py; 275 extern PyObject* kint32max_py; 276 extern PyObject* kuint32max_py; 277 extern PyObject* kint64min_py; 278 extern PyObject* kint64max_py; 279 extern PyObject* kuint64max_py; 280 281 #define C(str) const_cast<char*>(str) 282 283 void FormatTypeError(PyObject* arg, char* expected_types); 284 template<class T> 285 bool CheckAndGetInteger( 286 PyObject* arg, T* value, PyObject* min, PyObject* max); 287 bool CheckAndGetDouble(PyObject* arg, double* value); 288 bool CheckAndGetFloat(PyObject* arg, float* value); 289 bool CheckAndGetBool(PyObject* arg, bool* value); 290 bool CheckAndSetString( 291 PyObject* arg, google::protobuf::Message* message, 292 const google::protobuf::FieldDescriptor* descriptor, 293 const google::protobuf::Reflection* reflection, 294 bool append, 295 int index); 296 PyObject* ToStringObject( 297 const google::protobuf::FieldDescriptor* descriptor, string value); 298 299 extern PyObject* PickleError_class; 300 301 } // namespace python 302 } // namespace protobuf 303 304 } // namespace google 305 #endif // GOOGLE_PROTOBUF_PYTHON_CPP_MESSAGE_H__ 306