• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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