• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 
8 #include "google/protobuf/pyext/unknown_field_set.h"
9 
10 #define PY_SSIZE_T_CLEAN
11 #include <Python.h>
12 
13 #include <memory>
14 #include <set>
15 
16 #include "google/protobuf/message.h"
17 #include "google/protobuf/unknown_field_set.h"
18 #include "google/protobuf/pyext/message.h"
19 #include "google/protobuf/pyext/scoped_pyobject_ptr.h"
20 #include "google/protobuf/wire_format_lite.h"
21 
22 namespace google {
23 namespace protobuf {
24 namespace python {
25 
26 namespace unknown_field_set {
27 
Len(PyObject * pself)28 static Py_ssize_t Len(PyObject* pself) {
29   PyUnknownFieldSet* self = reinterpret_cast<PyUnknownFieldSet*>(pself);
30   if (self->fields == nullptr) {
31     PyErr_Format(PyExc_ValueError, "UnknownFieldSet does not exist. ");
32     return -1;
33   }
34   return self->fields->field_count();
35 }
36 
37 PyObject* NewPyUnknownField(PyUnknownFieldSet* parent, Py_ssize_t index);
38 
Item(PyObject * pself,Py_ssize_t index)39 static PyObject* Item(PyObject* pself, Py_ssize_t index) {
40   PyUnknownFieldSet* self = reinterpret_cast<PyUnknownFieldSet*>(pself);
41   if (self->fields == nullptr) {
42     PyErr_Format(PyExc_ValueError, "UnknownFieldSet does not exist. ");
43     return nullptr;
44   }
45   Py_ssize_t total_size = self->fields->field_count();
46   if (index < 0) {
47     index = total_size + index;
48   }
49   if (index < 0 || index >= total_size) {
50     PyErr_Format(PyExc_IndexError, "index (%zd) out of range", index);
51     return nullptr;
52   }
53   return unknown_field_set::NewPyUnknownField(self, index);
54 }
55 
New(PyTypeObject * type,PyObject * args,PyObject * kwargs)56 PyObject* New(PyTypeObject* type, PyObject* args, PyObject* kwargs) {
57   if (args == nullptr || PyTuple_Size(args) != 1) {
58     PyErr_SetString(PyExc_TypeError,
59                     "Must provide a message to create UnknownFieldSet");
60     return nullptr;
61   }
62 
63   PyObject* c_message;
64   if (!PyArg_ParseTuple(args, "O", &c_message)) {
65     PyErr_SetString(PyExc_TypeError,
66                     "Must provide a message to create UnknownFieldSet");
67     return nullptr;
68   }
69 
70   if (!PyObject_TypeCheck(c_message, CMessage_Type)) {
71     PyErr_Format(PyExc_TypeError,
72                  "Parameter to UnknownFieldSet() must be a message "
73                  "got %s.",
74                  Py_TYPE(c_message)->tp_name);
75     return nullptr;
76   }
77 
78   PyUnknownFieldSet* self = reinterpret_cast<PyUnknownFieldSet*>(
79       PyType_GenericAlloc(&PyUnknownFieldSet_Type, 0));
80   if (self == nullptr) {
81     return nullptr;
82   }
83 
84   // Top UnknownFieldSet should set parent nullptr.
85   self->parent = nullptr;
86 
87   // Copy c_message's UnknownFieldSet.
88   Message* message = reinterpret_cast<CMessage*>(c_message)->message;
89   const Reflection* reflection = message->GetReflection();
90   self->fields = new google::protobuf::UnknownFieldSet;
91   self->fields->MergeFrom(reflection->GetUnknownFields(*message));
92   return reinterpret_cast<PyObject*>(self);
93 }
94 
NewPyUnknownField(PyUnknownFieldSet * parent,Py_ssize_t index)95 PyObject* NewPyUnknownField(PyUnknownFieldSet* parent, Py_ssize_t index) {
96   PyUnknownField* self = reinterpret_cast<PyUnknownField*>(
97       PyType_GenericAlloc(&PyUnknownField_Type, 0));
98   if (self == nullptr) {
99     return nullptr;
100   }
101 
102   Py_INCREF(parent);
103   self->parent = parent;
104   self->index = index;
105 
106   return reinterpret_cast<PyObject*>(self);
107 }
108 
Dealloc(PyObject * pself)109 static void Dealloc(PyObject* pself) {
110   PyUnknownFieldSet* self = reinterpret_cast<PyUnknownFieldSet*>(pself);
111   if (self->parent == nullptr) {
112     delete self->fields;
113   } else {
114     Py_CLEAR(self->parent);
115   }
116   auto* py_type = Py_TYPE(pself);
117   self->~PyUnknownFieldSet();
118   py_type->tp_free(pself);
119 }
120 
121 static PySequenceMethods SqMethods = {
122     Len,     /* sq_length */
123     nullptr, /* sq_concat */
124     nullptr, /* sq_repeat */
125     Item,    /* sq_item */
126     nullptr, /* sq_slice */
127     nullptr, /* sq_ass_item */
128 };
129 
130 }  // namespace unknown_field_set
131 
132 PyTypeObject PyUnknownFieldSet_Type = {
133     PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME
134     ".PyUnknownFieldSet",        // tp_name
135     sizeof(PyUnknownFieldSet),   // tp_basicsize
136     0,                           //  tp_itemsize
137     unknown_field_set::Dealloc,  //  tp_dealloc
138 #if PY_VERSION_HEX < 0x03080000
139     nullptr,  // tp_print
140 #else
141     0,  // tp_vectorcall_offset
142 #endif
143     nullptr,                        //  tp_getattr
144     nullptr,                        //  tp_setattr
145     nullptr,                        //  tp_compare
146     nullptr,                        //  tp_repr
147     nullptr,                        //  tp_as_number
148     &unknown_field_set::SqMethods,  //  tp_as_sequence
149     nullptr,                        //  tp_as_mapping
150     PyObject_HashNotImplemented,    //  tp_hash
151     nullptr,                        //  tp_call
152     nullptr,                        //  tp_str
153     nullptr,                        //  tp_getattro
154     nullptr,                        //  tp_setattro
155     nullptr,                        //  tp_as_buffer
156     Py_TPFLAGS_DEFAULT,             //  tp_flags
157     "unknown field set",            //  tp_doc
158     nullptr,                        //  tp_traverse
159     nullptr,                        //  tp_clear
160     nullptr,                        //  tp_richcompare
161     0,                              //  tp_weaklistoffset
162     nullptr,                        //  tp_iter
163     nullptr,                        //  tp_iternext
164     nullptr,                        //  tp_methods
165     nullptr,                        //  tp_members
166     nullptr,                        //  tp_getset
167     nullptr,                        //  tp_base
168     nullptr,                        //  tp_dict
169     nullptr,                        //  tp_descr_get
170     nullptr,                        //  tp_descr_set
171     0,                              //  tp_dictoffset
172     nullptr,                        //  tp_init
173     nullptr,                        //  tp_alloc
174     unknown_field_set::New,         //  tp_new
175 };
176 
177 namespace unknown_field {
PyUnknownFieldSet_FromUnknownFieldSet(PyUnknownFieldSet * parent,const UnknownFieldSet & fields)178 static PyObject* PyUnknownFieldSet_FromUnknownFieldSet(
179     PyUnknownFieldSet* parent, const UnknownFieldSet& fields) {
180   PyUnknownFieldSet* self = reinterpret_cast<PyUnknownFieldSet*>(
181       PyType_GenericAlloc(&PyUnknownFieldSet_Type, 0));
182   if (self == nullptr) {
183     return nullptr;
184   }
185 
186   Py_INCREF(parent);
187   self->parent = parent;
188   self->fields = const_cast<UnknownFieldSet*>(&fields);
189 
190   return reinterpret_cast<PyObject*>(self);
191 }
192 
GetUnknownField(PyUnknownField * self)193 const UnknownField* GetUnknownField(PyUnknownField* self) {
194   const UnknownFieldSet* fields = self->parent->fields;
195   if (fields == nullptr) {
196     PyErr_Format(PyExc_ValueError, "UnknownField does not exist. ");
197     return nullptr;
198   }
199   Py_ssize_t total_size = fields->field_count();
200   if (self->index >= total_size) {
201     PyErr_Format(PyExc_ValueError, "UnknownField does not exist. ");
202     return nullptr;
203   }
204   return &fields->field(self->index);
205 }
206 
GetFieldNumber(PyUnknownField * self,void * closure)207 static PyObject* GetFieldNumber(PyUnknownField* self, void* closure) {
208   const UnknownField* unknown_field = GetUnknownField(self);
209   if (unknown_field == nullptr) {
210     return nullptr;
211   }
212   return PyLong_FromLong(unknown_field->number());
213 }
214 
215 using internal::WireFormatLite;
GetWireType(PyUnknownField * self,void * closure)216 static PyObject* GetWireType(PyUnknownField* self, void* closure) {
217   const UnknownField* unknown_field = GetUnknownField(self);
218   if (unknown_field == nullptr) {
219     return nullptr;
220   }
221 
222   // Assign a default value to suppress may-uninitialized warnings (errors
223   // when built in some places).
224   WireFormatLite::WireType wire_type = WireFormatLite::WIRETYPE_VARINT;
225   switch (unknown_field->type()) {
226     case UnknownField::TYPE_VARINT:
227       wire_type = WireFormatLite::WIRETYPE_VARINT;
228       break;
229     case UnknownField::TYPE_FIXED32:
230       wire_type = WireFormatLite::WIRETYPE_FIXED32;
231       break;
232     case UnknownField::TYPE_FIXED64:
233       wire_type = WireFormatLite::WIRETYPE_FIXED64;
234       break;
235     case UnknownField::TYPE_LENGTH_DELIMITED:
236       wire_type = WireFormatLite::WIRETYPE_LENGTH_DELIMITED;
237       break;
238     case UnknownField::TYPE_GROUP:
239       wire_type = WireFormatLite::WIRETYPE_START_GROUP;
240       break;
241   }
242   return PyLong_FromLong(wire_type);
243 }
244 
GetData(PyUnknownField * self,void * closure)245 static PyObject* GetData(PyUnknownField* self, void* closure) {
246   const UnknownField* field = GetUnknownField(self);
247   if (field == nullptr) {
248     return nullptr;
249   }
250   PyObject* data = nullptr;
251   switch (field->type()) {
252     case UnknownField::TYPE_VARINT:
253       data = PyLong_FromUnsignedLongLong(field->varint());
254       break;
255     case UnknownField::TYPE_FIXED32:
256       data = PyLong_FromUnsignedLong(field->fixed32());
257       break;
258     case UnknownField::TYPE_FIXED64:
259       data = PyLong_FromUnsignedLongLong(field->fixed64());
260       break;
261     case UnknownField::TYPE_LENGTH_DELIMITED:
262       data = PyBytes_FromStringAndSize(field->length_delimited().data(),
263                                        field->GetLengthDelimitedSize());
264       break;
265     case UnknownField::TYPE_GROUP:
266       data =
267           PyUnknownFieldSet_FromUnknownFieldSet(self->parent, field->group());
268       break;
269   }
270   return data;
271 }
272 
Dealloc(PyObject * pself)273 static void Dealloc(PyObject* pself) {
274   PyUnknownField* self = reinterpret_cast<PyUnknownField*>(pself);
275   Py_CLEAR(self->parent);
276 }
277 
278 static PyGetSetDef Getters[] = {
279     {"field_number", (getter)GetFieldNumber, nullptr},
280     {"wire_type", (getter)GetWireType, nullptr},
281     {"data", (getter)GetData, nullptr},
282     {nullptr},
283 };
284 
285 }  // namespace unknown_field
286 
287 PyTypeObject PyUnknownField_Type = {
288     PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME
289     ".PyUnknownField",       // tp_name
290     sizeof(PyUnknownField),  //  tp_basicsize
291     0,                       //  tp_itemsize
292     unknown_field::Dealloc,  //  tp_dealloc
293 #if PY_VERSION_HEX < 0x03080000
294     nullptr,  // tp_print
295 #else
296     0,  // tp_vectorcall_offset
297 #endif
298     nullptr,                      //  tp_getattr
299     nullptr,                      //  tp_setattr
300     nullptr,                      //  tp_compare
301     nullptr,                      //  tp_repr
302     nullptr,                      //  tp_as_number
303     nullptr,                      //  tp_as_sequence
304     nullptr,                      //  tp_as_mapping
305     PyObject_HashNotImplemented,  //  tp_hash
306     nullptr,                      //  tp_call
307     nullptr,                      //  tp_str
308     nullptr,                      //  tp_getattro
309     nullptr,                      //  tp_setattro
310     nullptr,                      //  tp_as_buffer
311     Py_TPFLAGS_DEFAULT,           //  tp_flags
312     "unknown field",              //  tp_doc
313     nullptr,                      //  tp_traverse
314     nullptr,                      //  tp_clear
315     nullptr,                      //  tp_richcompare
316     0,                            //  tp_weaklistoffset
317     nullptr,                      //  tp_iter
318     nullptr,                      //  tp_iternext
319     nullptr,                      //  tp_methods
320     nullptr,                      //  tp_members
321     unknown_field::Getters,       //  tp_getset
322     nullptr,                      //  tp_base
323     nullptr,                      //  tp_dict
324     nullptr,                      //  tp_descr_get
325     nullptr,                      //  tp_descr_set
326     0,                            //  tp_dictoffset
327     nullptr,                      //  tp_init
328 };
329 
330 }  // namespace python
331 }  // namespace protobuf
332 }  // namespace google
333