1
// Protocol Buffers - Google's data interchange format
2
// Copyright 2008 Google Inc. All rights reserved.
3
// http://code.google.com/p/protobuf/
5
// Redistribution and use in source and binary forms, with or without
6
// modification, are permitted provided that the following conditions are
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
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.
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.
31
// Author: petar@google.com (Petar Petrov)
35
#include <google/protobuf/pyext/python_descriptor.h>
36
#include <google/protobuf/descriptor.pb.h>
38
#define C(str) const_cast<char*>(str)
44
static void CFieldDescriptorDealloc(CFieldDescriptor* self);
46
static google::protobuf::DescriptorPool* g_descriptor_pool = NULL;
48
static PyObject* CFieldDescriptor_GetFullName(
49
CFieldDescriptor* self, void *closure) {
50
Py_XINCREF(self->full_name);
51
return self->full_name;
54
static PyObject* CFieldDescriptor_GetName(
55
CFieldDescriptor *self, void *closure) {
56
Py_XINCREF(self->name);
60
static PyObject* CFieldDescriptor_GetCppType(
61
CFieldDescriptor *self, void *closure) {
62
Py_XINCREF(self->cpp_type);
63
return self->cpp_type;
66
static PyObject* CFieldDescriptor_GetLabel(
67
CFieldDescriptor *self, void *closure) {
68
Py_XINCREF(self->label);
72
static PyObject* CFieldDescriptor_GetID(
73
CFieldDescriptor *self, void *closure) {
79
static PyGetSetDef CFieldDescriptorGetters[] = {
81
(getter)CFieldDescriptor_GetFullName, NULL, "Full name", NULL},
83
(getter)CFieldDescriptor_GetName, NULL, "last name", NULL},
85
(getter)CFieldDescriptor_GetCppType, NULL, "C++ Type", NULL},
87
(getter)CFieldDescriptor_GetLabel, NULL, "Label", NULL},
89
(getter)CFieldDescriptor_GetID, NULL, "ID", NULL},
93
PyTypeObject CFieldDescriptor_Type = {
94
PyObject_HEAD_INIT(&PyType_Type)
96
C("google3.net.google.protobuf.python.internal."
97
"_net_proto2___python."
98
"CFieldDescriptor"), // tp_name
99
sizeof(CFieldDescriptor), // tp_basicsize
101
(destructor)CFieldDescriptorDealloc, // tp_dealloc
116
Py_TPFLAGS_DEFAULT, // tp_flags
117
C("A Field Descriptor"), // tp_doc
121
0, // tp_weaklistoffset
126
CFieldDescriptorGetters, // tp_getset
133
PyType_GenericAlloc, // tp_alloc
134
PyType_GenericNew, // tp_new
135
PyObject_Del, // tp_free
138
static void CFieldDescriptorDealloc(CFieldDescriptor* self) {
139
Py_DECREF(self->full_name);
140
Py_DECREF(self->name);
141
Py_DECREF(self->cpp_type);
142
Py_DECREF(self->label);
144
self->ob_type->tp_free(reinterpret_cast<PyObject*>(self));
150
const google::protobuf::DescriptorPool* pool;
153
static void CDescriptorPoolDealloc(CDescriptorPool* self);
155
static PyObject* CDescriptorPool_NewCDescriptor(
156
const google::protobuf::FieldDescriptor* field_descriptor) {
157
CFieldDescriptor* cfield_descriptor = PyObject_New(
158
CFieldDescriptor, &CFieldDescriptor_Type);
159
if (cfield_descriptor == NULL) {
162
cfield_descriptor->descriptor = field_descriptor;
164
cfield_descriptor->full_name = PyString_FromString(
165
field_descriptor->full_name().c_str());
166
cfield_descriptor->name = PyString_FromString(
167
field_descriptor->name().c_str());
168
cfield_descriptor->cpp_type = PyLong_FromLong(field_descriptor->cpp_type());
169
cfield_descriptor->label = PyLong_FromLong(field_descriptor->label());
170
cfield_descriptor->id = PyLong_FromVoidPtr(cfield_descriptor);
171
return reinterpret_cast<PyObject*>(cfield_descriptor);
174
static PyObject* CDescriptorPool_FindFieldByName(
175
CDescriptorPool* self, PyObject* arg) {
176
const char* full_field_name = PyString_AsString(arg);
177
if (full_field_name == NULL) {
181
const google::protobuf::FieldDescriptor* field_descriptor = NULL;
183
field_descriptor = self->pool->FindFieldByName(full_field_name);
184
if (field_descriptor == NULL) {
185
PyErr_Format(PyExc_TypeError, "Couldn't find field %.200s",
190
return CDescriptorPool_NewCDescriptor(field_descriptor);
193
static PyObject* CDescriptorPool_FindExtensionByName(
194
CDescriptorPool* self, PyObject* arg) {
195
const char* full_field_name = PyString_AsString(arg);
196
if (full_field_name == NULL) {
200
const google::protobuf::FieldDescriptor* field_descriptor =
201
self->pool->FindExtensionByName(full_field_name);
202
if (field_descriptor == NULL) {
203
PyErr_Format(PyExc_TypeError, "Couldn't find field %.200s",
208
return CDescriptorPool_NewCDescriptor(field_descriptor);
211
static PyMethodDef CDescriptorPoolMethods[] = {
212
{ C("FindFieldByName"),
213
(PyCFunction)CDescriptorPool_FindFieldByName,
215
C("Searches for a field descriptor by full name.") },
216
{ C("FindExtensionByName"),
217
(PyCFunction)CDescriptorPool_FindExtensionByName,
219
C("Searches for extension descriptor by full name.") },
223
PyTypeObject CDescriptorPool_Type = {
224
PyObject_HEAD_INIT(&PyType_Type)
226
C("google3.net.google.protobuf.python.internal."
227
"_net_proto2___python."
228
"CFieldDescriptor"), // tp_name
229
sizeof(CDescriptorPool), // tp_basicsize
231
(destructor)CDescriptorPoolDealloc, // tp_dealloc
246
Py_TPFLAGS_DEFAULT, // tp_flags
247
C("A Descriptor Pool"), // tp_doc
251
0, // tp_weaklistoffset
254
CDescriptorPoolMethods, // tp_methods
263
PyType_GenericAlloc, // tp_alloc
264
PyType_GenericNew, // tp_new
265
PyObject_Del, // tp_free
268
static void CDescriptorPoolDealloc(CDescriptorPool* self) {
269
self->ob_type->tp_free(reinterpret_cast<PyObject*>(self));
272
google::protobuf::DescriptorPool* GetDescriptorPool() {
273
if (g_descriptor_pool == NULL) {
274
g_descriptor_pool = new google::protobuf::DescriptorPool(
275
google::protobuf::DescriptorPool::generated_pool());
277
return g_descriptor_pool;
280
PyObject* Python_NewCDescriptorPool(PyObject* ignored, PyObject* args) {
281
CDescriptorPool* cdescriptor_pool = PyObject_New(
282
CDescriptorPool, &CDescriptorPool_Type);
283
if (cdescriptor_pool == NULL) {
286
cdescriptor_pool->pool = GetDescriptorPool();
287
return reinterpret_cast<PyObject*>(cdescriptor_pool);
290
PyObject* Python_BuildFile(PyObject* ignored, PyObject* arg) {
292
Py_ssize_t message_len;
294
if (PyString_AsStringAndSize(arg, &message_type, &message_len) < 0) {
298
google::protobuf::FileDescriptorProto file_proto;
299
if (!file_proto.ParseFromArray(message_type, message_len)) {
300
PyErr_SetString(PyExc_TypeError, "Couldn't parse file content!");
304
// If this file is already in the generated pool, don't add it again.
305
if (google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
306
file_proto.name()) != NULL) {
310
const google::protobuf::FileDescriptor* descriptor = GetDescriptorPool()->BuildFile(
312
if (descriptor == NULL) {
313
PyErr_SetString(PyExc_TypeError,
314
"Couldn't build proto file into descriptor pool!");
321
bool InitDescriptor() {
322
CFieldDescriptor_Type.tp_new = PyType_GenericNew;
323
if (PyType_Ready(&CFieldDescriptor_Type) < 0)
326
CDescriptorPool_Type.tp_new = PyType_GenericNew;
327
if (PyType_Ready(&CDescriptorPool_Type) < 0)
332
} // namespace python
333
} // namespace protobuf
334
} // namespace google