Home | History | Annotate | Download | only in pyext
      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 (at) google.com (Anuraag Agrawal)
     32 // Author: tibell (at) 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