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