• 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   Py_TYPE(pself)->tp_free(pself);
146 }
147 
148 static PySequenceMethods SqMethods = {
149   Len,        /* sq_length */
150   0,          /* sq_concat */
151   0,          /* sq_repeat */
152   Item,       /* sq_item */
153   0,          /* sq_slice */
154   0,          /* sq_ass_item */
155 };
156 
157 }  // namespace unknown_fields
158 
159 PyTypeObject PyUnknownFields_Type = {
160   PyVarObject_HEAD_INIT(&PyType_Type, 0)
161   FULL_MODULE_NAME ".PyUnknownFields",  // tp_name
162   sizeof(PyUnknownFields),             // tp_basicsize
163   0,                                   //  tp_itemsize
164   unknown_fields::Dealloc,             //  tp_dealloc
165   0,                                   //  tp_print
166   0,                                   //  tp_getattr
167   0,                                   //  tp_setattr
168   0,                                   //  tp_compare
169   0,                                   //  tp_repr
170   0,                                   //  tp_as_number
171   &unknown_fields::SqMethods,          //  tp_as_sequence
172   0,                                   //  tp_as_mapping
173   PyObject_HashNotImplemented,         //  tp_hash
174   0,                                   //  tp_call
175   0,                                   //  tp_str
176   0,                                   //  tp_getattro
177   0,                                   //  tp_setattro
178   0,                                   //  tp_as_buffer
179   Py_TPFLAGS_DEFAULT,                  //  tp_flags
180   "unknown field set",                 //  tp_doc
181   0,                                   //  tp_traverse
182   0,                                   //  tp_clear
183   0,                                   //  tp_richcompare
184   0,                                   //  tp_weaklistoffset
185   0,                                   //  tp_iter
186   0,                                   //  tp_iternext
187   0,                                   //  tp_methods
188   0,                                   //  tp_members
189   0,                                   //  tp_getset
190   0,                                   //  tp_base
191   0,                                   //  tp_dict
192   0,                                   //  tp_descr_get
193   0,                                   //  tp_descr_set
194   0,                                   //  tp_dictoffset
195   0,                                   //  tp_init
196 };
197 
198 namespace unknown_field {
PyUnknownFields_FromUnknownFieldSet(PyUnknownFields * parent,const UnknownFieldSet & fields)199 static PyObject* PyUnknownFields_FromUnknownFieldSet(
200     PyUnknownFields* parent, const UnknownFieldSet& fields) {
201   PyUnknownFields* self = reinterpret_cast<PyUnknownFields*>(
202       PyType_GenericAlloc(&PyUnknownFields_Type, 0));
203   if (self == NULL) {
204     return NULL;
205   }
206   // Call "placement new" to initialize PyUnknownFields.
207   new (self) PyUnknownFields;
208 
209   Py_INCREF(parent);
210   self->parent = reinterpret_cast<PyObject*>(parent);
211   self->fields = &fields;
212   parent->sub_unknown_fields.emplace(self);
213 
214   return reinterpret_cast<PyObject*>(self);
215 }
216 
GetUnknownField(PyUnknownFieldRef * self)217 const UnknownField* GetUnknownField(PyUnknownFieldRef* self) {
218   const UnknownFieldSet* fields = self->parent->fields;
219   if (fields == NULL) {
220     PyErr_Format(PyExc_ValueError,
221                  "UnknownField does not exist. "
222                  "The parent message might be cleared.");
223     return NULL;
224   }
225   ssize_t total_size = fields->field_count();
226   if (self->index >= total_size) {
227     PyErr_Format(PyExc_ValueError,
228                  "UnknownField does not exist. "
229                  "The parent message might be cleared.");
230     return NULL;
231   }
232   return &fields->field(self->index);
233 }
234 
GetFieldNumber(PyUnknownFieldRef * self,void * closure)235 static PyObject* GetFieldNumber(PyUnknownFieldRef* self, void *closure) {
236   const UnknownField* unknown_field = GetUnknownField(self);
237   if (unknown_field == NULL) {
238     return NULL;
239   }
240   return PyInt_FromLong(unknown_field->number());
241 }
242 
243 using internal::WireFormatLite;
GetWireType(PyUnknownFieldRef * self,void * closure)244 static PyObject* GetWireType(PyUnknownFieldRef* self, void *closure) {
245   const UnknownField* unknown_field = GetUnknownField(self);
246   if (unknown_field == NULL) {
247     return NULL;
248   }
249 
250   // Assign a default value to suppress may-uninitialized warnings (errors
251   // when built in some places).
252   WireFormatLite::WireType wire_type = WireFormatLite::WIRETYPE_VARINT;
253   switch (unknown_field->type()) {
254     case UnknownField::TYPE_VARINT:
255       wire_type = WireFormatLite::WIRETYPE_VARINT;
256       break;
257     case UnknownField::TYPE_FIXED32:
258       wire_type = WireFormatLite::WIRETYPE_FIXED32;
259       break;
260     case UnknownField::TYPE_FIXED64:
261       wire_type = WireFormatLite::WIRETYPE_FIXED64;
262       break;
263     case UnknownField::TYPE_LENGTH_DELIMITED:
264       wire_type = WireFormatLite::WIRETYPE_LENGTH_DELIMITED;
265       break;
266     case UnknownField::TYPE_GROUP:
267       wire_type = WireFormatLite::WIRETYPE_START_GROUP;
268       break;
269   }
270   return PyInt_FromLong(wire_type);
271 }
272 
GetData(PyUnknownFieldRef * self,void * closure)273 static PyObject* GetData(PyUnknownFieldRef* self, void *closure) {
274   const UnknownField* field = GetUnknownField(self);
275   if (field == NULL) {
276     return NULL;
277   }
278   PyObject* data = NULL;
279   switch (field->type()) {
280     case UnknownField::TYPE_VARINT:
281       data = PyInt_FromLong(field->varint());
282       break;
283     case UnknownField::TYPE_FIXED32:
284       data = PyInt_FromLong(field->fixed32());
285       break;
286     case UnknownField::TYPE_FIXED64:
287       data = PyInt_FromLong(field->fixed64());
288       break;
289     case UnknownField::TYPE_LENGTH_DELIMITED:
290       data = PyBytes_FromStringAndSize(field->length_delimited().data(),
291                                        field->GetLengthDelimitedSize());
292       break;
293     case UnknownField::TYPE_GROUP:
294       data = PyUnknownFields_FromUnknownFieldSet(
295           self->parent, field->group());
296       break;
297   }
298   return data;
299 }
300 
Dealloc(PyObject * pself)301 static void Dealloc(PyObject* pself) {
302   PyUnknownFieldRef* self =
303       reinterpret_cast<PyUnknownFieldRef*>(pself);
304   Py_CLEAR(self->parent);
305 }
306 
307 static PyGetSetDef Getters[] = {
308   {"field_number", (getter)GetFieldNumber, NULL},
309   {"wire_type", (getter)GetWireType, NULL},
310   {"data", (getter)GetData, NULL},
311   {NULL}
312 };
313 
314 }  // namespace unknown_field
315 
316 PyTypeObject PyUnknownFieldRef_Type = {
317   PyVarObject_HEAD_INIT(&PyType_Type, 0)
318   FULL_MODULE_NAME ".PyUnknownFieldRef",  // tp_name
319   sizeof(PyUnknownFieldRef),           //  tp_basicsize
320   0,                                   //  tp_itemsize
321   unknown_field::Dealloc,              //  tp_dealloc
322   0,                                   //  tp_print
323   0,                                   //  tp_getattr
324   0,                                   //  tp_setattr
325   0,                                   //  tp_compare
326   0,                                   //  tp_repr
327   0,                                   //  tp_as_number
328   0,                                   //  tp_as_sequence
329   0,                                   //  tp_as_mapping
330   PyObject_HashNotImplemented,         //  tp_hash
331   0,                                   //  tp_call
332   0,                                   //  tp_str
333   0,                                   //  tp_getattro
334   0,                                   //  tp_setattro
335   0,                                   //  tp_as_buffer
336   Py_TPFLAGS_DEFAULT,                  //  tp_flags
337   "unknown field",                     //  tp_doc
338   0,                                   //  tp_traverse
339   0,                                   //  tp_clear
340   0,                                   //  tp_richcompare
341   0,                                   //  tp_weaklistoffset
342   0,                                   //  tp_iter
343   0,                                   //  tp_iternext
344   0,                                   //  tp_methods
345   0,                                   //  tp_members
346   unknown_field::Getters,              //  tp_getset
347   0,                                   //  tp_base
348   0,                                   //  tp_dict
349   0,                                   //  tp_descr_get
350   0,                                   //  tp_descr_set
351   0,                                   //  tp_dictoffset
352   0,                                   //  tp_init
353 };
354 
355 
356 }  // namespace python
357 }  // namespace protobuf
358 }  // namespace google
359