From 487bfdfc0603ab7bf5fad381f52b8932cbcd355e Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Mon, 8 Aug 2011 16:33:48 -0700 Subject: Begin port of Python extension to new APIs. --- lang_ext/python/upb.c | 190 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 lang_ext/python/upb.c (limited to 'lang_ext/python/upb.c') diff --git a/lang_ext/python/upb.c b/lang_ext/python/upb.c new file mode 100644 index 0000000..9a48401 --- /dev/null +++ b/lang_ext/python/upb.c @@ -0,0 +1,190 @@ +/* + * upb - a minimalist implementation of protocol buffers. + * + * Copyright (c) 2009 Google Inc. See LICENSE for details. + * Author: Josh Haberman + * + * Python extension exposing the core of upb: definitions, handlers, + * and a message type. + */ + +#include +#include "upb/def.h" + +static bool streql(const char *a, const char *b) { return strcmp(a, b) == 0; } + +PyObject *PyUpb_Error(const char *str) { + PyErr_SetString(PyExc_TypeError, str); + return NULL; +} + +int PyUpb_ErrorInt(const char *str) { + PyErr_SetString(PyExc_TypeError, str); + return -1; +} + +/* PyUpb_Def ******************************************************************/ + +// All the def types share the same C layout, even though they are different +// Python types. For the moment we don't bother trying to make them an actual +// inheritance hierarchy. + +typedef struct { + PyObject_HEAD; + upb_def *def; +} PyUpb_Def; + + +/* PyUpb_FieldDef *************************************************************/ + +typedef struct { + PyObject_HEAD; + upb_fielddef *field; +} PyUpb_FieldDef; + +static PyTypeObject PyUpb_FieldDefType; + +#define Check_FieldDef(obj, badret) \ + (void*)obj; do { \ + if(!PyObject_TypeCheck(obj, &PyUpb_FieldDefType)) { \ + PyErr_SetString(PyExc_TypeError, "must be a upb.FieldDef"); \ + return badret; \ + } \ + } while(0) + +static void PyUpb_FieldDef_dealloc(PyObject *obj) { + PyUpb_FieldDef *f = (void*)obj; + upb_fielddef_unref(f->field); + obj->ob_type->tp_free(obj); +} + +static PyObject* PyUpb_FieldDef_getattro(PyObject *obj, PyObject *attr_name) { + PyUpb_FieldDef *f = Check_FieldDef(obj, NULL); + const char *name = PyString_AsString(attr_name); + if (streql(name, "name")) { + return PyString_FromString(upb_fielddef_name(f->field)); + } else if (streql(name, "number")) { + return PyInt_FromLong(upb_fielddef_number(f->field)); + } else if (streql(name, "type")) { + return PyInt_FromLong(upb_fielddef_type(f->field)); + } else if (streql(name, "label")) { + return PyInt_FromLong(upb_fielddef_label(f->field)); + } else if (streql(name, "subdef")) { + // NYI; + return NULL; + } else if (streql(name, "msgdef")) { + // NYI; + return NULL; + } else { + return PyUpb_Error("Invalid fielddef member."); + } +} + +static int PyUpb_FieldDef_setattro(PyObject *o, PyObject *key, PyObject *val) { + PyUpb_FieldDef *f = Check_FieldDef(o, -1); + const char *field = PyString_AsString(key); + if (!upb_fielddef_ismutable(f->field)) + return PyUpb_ErrorInt("fielddef is not mutable."); + if (streql(field, "name")) { + const char *name = PyString_AsString(val); + if (!name || !upb_fielddef_setname(f->field, name)) + return PyUpb_ErrorInt("Invalid name"); + } else if (streql(field, "number")) { + // TODO: should check truncation. Non-security issue. + // Non-int will return -1, which is already invalid as a field number. + if (!upb_fielddef_setnumber(f->field, PyInt_AsLong(val))) + return PyUpb_ErrorInt("Invalid number"); + } else if (streql(field, "type")) { + // TODO: should check truncation. Non-security issue. + if (!upb_fielddef_settype(f->field, PyInt_AsLong(val))) + return PyUpb_ErrorInt("Invalid type"); + } else if (streql(field, "label")) { + // TODO: should check truncation. Non-security issue. + if (!upb_fielddef_setlabel(f->field, PyInt_AsLong(val))) + return PyUpb_ErrorInt("Invalid label"); + } else if (streql(field, "type_name")) { + const char *name = PyString_AsString(val); + if (!name || !upb_fielddef_settypename(f->field, name)) + return PyUpb_ErrorInt("Invalid type_name"); + } else if (streql(field, "default_value")) { + // NYI + return -1; + } else { + return PyUpb_ErrorInt("Invalid fielddef member."); + } + return 0; +} + +static int PyUpb_FieldDef_init(PyObject *self, PyObject *args, PyObject *kwds) { + if (!kwds) return 0; + PyObject *key, *value; + Py_ssize_t pos = 0; + while (PyDict_Next(kwds, &pos, &key, &value)) + PyUpb_FieldDef_setattro(self, key, value); + return 0; +} + +static PyObject *PyUpb_FieldDef_new(PyTypeObject *subtype, + PyObject *args, PyObject *kwds) { + PyUpb_FieldDef *f = (PyUpb_FieldDef*)subtype->tp_alloc(subtype, 0); + f->field = upb_fielddef_new(); + return (PyObject*)f; +} + +static PyTypeObject PyUpb_FieldDefType = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "upb.FieldDef", /* tp_name */ + sizeof(PyUpb_FieldDef), /* tp_basicsize */ + 0, /* tp_itemsize */ + &PyUpb_FieldDef_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* TODO */ /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + &PyUpb_FieldDef_getattro, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + &PyUpb_FieldDef_init, /* tp_init */ + 0, /* tp_alloc */ + &PyUpb_FieldDef_new, /* tp_new */ + 0, /* tp_free */ +}; + +static PyMethodDef methods[] = { + {NULL, NULL} +}; + +PyMODINIT_FUNC initupb(void) { + PyObject *mod = Py_InitModule("upb", methods); + if (PyType_Ready(&PyUpb_FieldDefType) < 0) return; + + // PyModule_AddObject steals a ref, but our object is statically allocated + // and must not be deleted. + Py_INCREF(&PyUpb_FieldDefType); + + PyModule_AddObject(mod, "FieldDef", (PyObject*)&PyUpb_FieldDefType); +} -- cgit v1.2.3