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