• 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.
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