• 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 #include <google/protobuf/pyext/unknown_fields.h>
32 
33 #include <Python.h>
34 #include <set>
35 #include <memory>
36 
37 #include <google/protobuf/message.h>
38 #include <google/protobuf/pyext/message.h>
39 #include <google/protobuf/pyext/scoped_pyobject_ptr.h>
40 #include <google/protobuf/unknown_field_set.h>
41 #include <google/protobuf/wire_format_lite.h>
42 
43 #if PY_MAJOR_VERSION >= 3
44   #define PyInt_FromLong PyLong_FromLong
45 #endif
46 
47 namespace google {
48 namespace protobuf {
49 namespace python {
50 
51 namespace unknown_fields {
52 
Len(PyObject * pself)53 static Py_ssize_t Len(PyObject* pself) {
54   PyUnknownFields* self =
55       reinterpret_cast<PyUnknownFields*>(pself);
56   if (self->fields == NULL) {
57     PyErr_Format(PyExc_ValueError,
58                  "UnknownFields does not exist. "
59                  "The parent message might be cleared.");
60     return -1;
61   }
62   return self->fields->field_count();
63 }
64 
Clear(PyUnknownFields * self)65 void Clear(PyUnknownFields* self) {
66   for (std::set<PyUnknownFields*>::iterator it =
67            self->sub_unknown_fields.begin();
68        it != self->sub_unknown_fields.end(); it++) {
69     Clear(*it);
70   }
71   self->fields = NULL;
72   self->sub_unknown_fields.clear();
73 }
74 
75 PyObject* NewPyUnknownFieldRef(PyUnknownFields* parent,
76                                Py_ssize_t index);
77 
Item(PyObject * pself,Py_ssize_t index)78 static PyObject* Item(PyObject* pself, Py_ssize_t index) {
79   PyUnknownFields* self =
80       reinterpret_cast<PyUnknownFields*>(pself);
81   if (self->fields == NULL) {
82     PyErr_Format(PyExc_ValueError,
83                  "UnknownFields does not exist. "
84                  "The parent message might be cleared.");
85     return NULL;
86   }
87   Py_ssize_t total_size = self->fields->field_count();
88   if (index < 0) {
89     index = total_size + index;
90   }
91   if (index < 0 || index >= total_size) {
92     PyErr_Format(PyExc_IndexError,
93                  "index (%zd) out of range",
94                  index);
95     return NULL;
96   }
97 
98   return unknown_fields::NewPyUnknownFieldRef(self, index);
99 }
100 
NewPyUnknownFields(CMessage * c_message)101 PyObject* NewPyUnknownFields(CMessage* c_message) {
102   PyUnknownFields* self = reinterpret_cast<PyUnknownFields*>(
103       PyType_GenericAlloc(&PyUnknownFields_Type, 0));
104   if (self == NULL) {
105     return NULL;
106   }
107   // Call "placement new" to initialize PyUnknownFields.
108   new (self) PyUnknownFields;
109 
110   Py_INCREF(c_message);
111   self->parent = reinterpret_cast<PyObject*>(c_message);
112   Message* message = c_message->message;
113   const Reflection* reflection = message->GetReflection();
114   self->fields = &reflection->GetUnknownFields(*message);
115 
116   return reinterpret_cast<PyObject*>(self);
117 }
118 
NewPyUnknownFieldRef(PyUnknownFields * parent,Py_ssize_t index)119 PyObject* NewPyUnknownFieldRef(PyUnknownFields* parent,
120                                Py_ssize_t index) {
121   PyUnknownFieldRef* self = reinterpret_cast<PyUnknownFieldRef*>(
122       PyType_GenericAlloc(&PyUnknownFieldRef_Type, 0));
123   if (self == NULL) {
124     return NULL;
125   }
126 
127   Py_INCREF(parent);
128   self->parent = parent;
129   self->index = index;
130 
131   return reinterpret_cast<PyObject*>(self);
132 }
133 
Dealloc(PyObject * pself)134 static void Dealloc(PyObject* pself) {
135   PyUnknownFields* self =
136       reinterpret_cast<PyUnknownFields*>(pself);
137   if (PyObject_TypeCheck(self->parent, &PyUnknownFields_Type)) {
138     reinterpret_cast<PyUnknownFields*>(
139         self->parent)->sub_unknown_fields.erase(self);
140   } else {
141     reinterpret_cast<CMessage*>(self->parent)->unknown_field_set = nullptr;
142   }
143   Py_CLEAR(self->parent);
144   self->~PyUnknownFields();
145 }
146 
147 static PySequenceMethods SqMethods = {
148   Len,        /* sq_length */
149   0,          /* sq_concat */
150   0,          /* sq_repeat */
151   Item,       /* sq_item */
152   0,          /* sq_slice */
153   0,          /* sq_ass_item */
154 };
155 
156 }  // namespace unknown_fields
157 
158 PyTypeObject PyUnknownFields_Type = {
159   PyVarObject_HEAD_INIT(&PyType_Type, 0)
160   FULL_MODULE_NAME ".PyUnknownFields",  // tp_name
161   sizeof(PyUnknownFields),             // tp_basicsize
162   0,                                   //  tp_itemsize
163   unknown_fields::Dealloc,             //  tp_dealloc
164   0,                                   //  tp_print
165   0,                                   //  tp_getattr
166   0,                                   //  tp_setattr
167   0,                                   //  tp_compare
168   0,                                   //  tp_repr
169   0,                                   //  tp_as_number
170   &unknown_fields::SqMethods,          //  tp_as_sequence
171   0,                                   //  tp_as_mapping
172   PyObject_HashNotImplemented,         //  tp_hash
173   0,                                   //  tp_call
174   0,                                   //  tp_str
175   0,                                   //  tp_getattro
176   0,                                   //  tp_setattro
177   0,                                   //  tp_as_buffer
178   Py_TPFLAGS_DEFAULT,                  //  tp_flags
179   "unknown field set",                 //  tp_doc
180   0,                                   //  tp_traverse
181   0,                                   //  tp_clear
182   0,                                   //  tp_richcompare
183   0,                                   //  tp_weaklistoffset
184   0,                                   //  tp_iter
185   0,                                   //  tp_iternext
186   0,                                   //  tp_methods
187   0,                                   //  tp_members
188   0,                                   //  tp_getset
189   0,                                   //  tp_base
190   0,                                   //  tp_dict
191   0,                                   //  tp_descr_get
192   0,                                   //  tp_descr_set
193   0,                                   //  tp_dictoffset
194   0,                                   //  tp_init
195 };
196 
197 namespace unknown_field {
PyUnknownFields_FromUnknownFieldSet(PyUnknownFields * parent,const UnknownFieldSet & fields)198 static PyObject* PyUnknownFields_FromUnknownFieldSet(
199     PyUnknownFields* parent, const UnknownFieldSet& fields) {
200   PyUnknownFields* self = reinterpret_cast<PyUnknownFields*>(
201       PyType_GenericAlloc(&PyUnknownFields_Type, 0));
202   if (self == NULL) {
203     return NULL;
204   }
205   // Call "placement new" to initialize PyUnknownFields.
206   new (self) PyUnknownFields;
207 
208   Py_INCREF(parent);
209   self->parent = reinterpret_cast<PyObject*>(parent);
210   self->fields = &fields;
211   parent->sub_unknown_fields.emplace(self);
212 
213   return reinterpret_cast<PyObject*>(self);
214 }
215 
GetUnknownField(PyUnknownFieldRef * self)216 const UnknownField* GetUnknownField(PyUnknownFieldRef* self) {
217   const UnknownFieldSet* fields = self->parent->fields;
218   if (fields == NULL) {
219     PyErr_Format(PyExc_ValueError,
220                  "UnknownField does not exist. "
221                  "The parent message might be cleared.");
222     return NULL;
223   }
224   ssize_t total_size = fields->field_count();
225   if (self->index >= total_size) {
226     PyErr_Format(PyExc_ValueError,
227                  "UnknownField does not exist. "
228                  "The parent message might be cleared.");
229     return NULL;
230   }
231   return &fields->field(self->index);
232 }
233 
GetFieldNumber(PyUnknownFieldRef * self,void * closure)234 static PyObject* GetFieldNumber(PyUnknownFieldRef* self, void *closure) {
235   const UnknownField* unknown_field = GetUnknownField(self);
236   if (unknown_field == NULL) {
237     return NULL;
238   }
239   return PyInt_FromLong(unknown_field->number());
240 }
241 
242 using internal::WireFormatLite;
GetWireType(PyUnknownFieldRef * self,void * closure)243 static PyObject* GetWireType(PyUnknownFieldRef* self, void *closure) {
244   const UnknownField* unknown_field = GetUnknownField(self);
245   if (unknown_field == NULL) {
246     return NULL;
247   }
248 
249   // Assign a default value to suppress may-unintialized warnings (errors
250   // when built in some places).
251   WireFormatLite::WireType wire_type = WireFormatLite::WIRETYPE_VARINT;
252   switch (unknown_field->type()) {
253     case UnknownField::TYPE_VARINT:
254       wire_type = WireFormatLite::WIRETYPE_VARINT;
255       break;
256     case UnknownField::TYPE_FIXED32:
257       wire_type = WireFormatLite::WIRETYPE_FIXED32;
258       break;
259     case UnknownField::TYPE_FIXED64:
260       wire_type = WireFormatLite::WIRETYPE_FIXED64;
261       break;
262     case UnknownField::TYPE_LENGTH_DELIMITED:
263       wire_type = WireFormatLite::WIRETYPE_LENGTH_DELIMITED;
264       break;
265     case UnknownField::TYPE_GROUP:
266       wire_type = WireFormatLite::WIRETYPE_START_GROUP;
267       break;
268   }
269   return PyInt_FromLong(wire_type);
270 }
271 
GetData(PyUnknownFieldRef * self,void * closure)272 static PyObject* GetData(PyUnknownFieldRef* self, void *closure) {
273   const UnknownField* field = GetUnknownField(self);
274   if (field == NULL) {
275     return NULL;
276   }
277   PyObject* data = NULL;
278   switch (field->type()) {
279     case UnknownField::TYPE_VARINT:
280       data = PyInt_FromLong(field->varint());
281       break;
282     case UnknownField::TYPE_FIXED32:
283       data = PyInt_FromLong(field->fixed32());
284       break;
285     case UnknownField::TYPE_FIXED64:
286       data = PyInt_FromLong(field->fixed64());
287       break;
288     case UnknownField::TYPE_LENGTH_DELIMITED:
289       data = PyBytes_FromStringAndSize(field->length_delimited().data(),
290                                        field->GetLengthDelimitedSize());
291       break;
292     case UnknownField::TYPE_GROUP:
293       data = PyUnknownFields_FromUnknownFieldSet(
294           self->parent, field->group());
295       break;
296   }
297   return data;
298 }
299 
Dealloc(PyObject * pself)300 static void Dealloc(PyObject* pself) {
301   PyUnknownFieldRef* self =
302       reinterpret_cast<PyUnknownFieldRef*>(pself);
303   Py_CLEAR(self->parent);
304 }
305 
306 static PyGetSetDef Getters[] = {
307   {"field_number", (getter)GetFieldNumber, NULL},
308   {"wire_type", (getter)GetWireType, NULL},
309   {"data", (getter)GetData, NULL},
310   {NULL}
311 };
312 
313 }  // namespace unknown_field
314 
315 PyTypeObject PyUnknownFieldRef_Type = {
316   PyVarObject_HEAD_INIT(&PyType_Type, 0)
317   FULL_MODULE_NAME ".PyUnknownFieldRef",  // tp_name
318   sizeof(PyUnknownFieldRef),           //  tp_basicsize
319   0,                                   //  tp_itemsize
320   unknown_field::Dealloc,              //  tp_dealloc
321   0,                                   //  tp_print
322   0,                                   //  tp_getattr
323   0,                                   //  tp_setattr
324   0,                                   //  tp_compare
325   0,                                   //  tp_repr
326   0,                                   //  tp_as_number
327   0,                                   //  tp_as_sequence
328   0,                                   //  tp_as_mapping
329   PyObject_HashNotImplemented,         //  tp_hash
330   0,                                   //  tp_call
331   0,                                   //  tp_str
332   0,                                   //  tp_getattro
333   0,                                   //  tp_setattro
334   0,                                   //  tp_as_buffer
335   Py_TPFLAGS_DEFAULT,                  //  tp_flags
336   "unknown field",                     //  tp_doc
337   0,                                   //  tp_traverse
338   0,                                   //  tp_clear
339   0,                                   //  tp_richcompare
340   0,                                   //  tp_weaklistoffset
341   0,                                   //  tp_iter
342   0,                                   //  tp_iternext
343   0,                                   //  tp_methods
344   0,                                   //  tp_members
345   unknown_field::Getters,              //  tp_getset
346   0,                                   //  tp_base
347   0,                                   //  tp_dict
348   0,                                   //  tp_descr_get
349   0,                                   //  tp_descr_set
350   0,                                   //  tp_dictoffset
351   0,                                   //  tp_init
352 };
353 
354 
355 }  // namespace python
356 }  // namespace protobuf
357 }  // namespace google
358