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