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