143 lines
3.4 KiB
C
143 lines
3.4 KiB
C
#define PY_SSIZE_T_CLEAN
|
|
#include <Python.h>
|
|
#include "tinytemplate.h"
|
|
|
|
typedef struct {
|
|
PyObject_HEAD
|
|
PyObject *src;
|
|
tinytemplate_instr_t *program;
|
|
} Template;
|
|
|
|
static void
|
|
TinyTemplate_dealloc(CustomObject *self)
|
|
{
|
|
Py_XDECREF(self->src);
|
|
Py_TYPE(self)->tp_free((PyObject *) self);
|
|
}
|
|
|
|
static PyObject *
|
|
TinyTemplate_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
Template *self;
|
|
self = (Template *) type->tp_alloc(type, 0);
|
|
if (self != NULL) {
|
|
self->src = PyUnicode_FromString("");
|
|
if (self->src == NULL) {
|
|
Py_DECREF(self);
|
|
return NULL;
|
|
}
|
|
}
|
|
return (PyObject *) self;
|
|
}
|
|
|
|
static int
|
|
TinyTemplate_init(Template *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"src", NULL};
|
|
PyObject *src = NULL;
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &src))
|
|
return -1;
|
|
|
|
if (src) {
|
|
PyObject *tmp = self->src;
|
|
Py_INCREF(src);
|
|
self->src = src;
|
|
Py_XDECREF(tmp);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *
|
|
TinyTemplate_eval(Template *self, PyObject *args)
|
|
{
|
|
PyObject *src = self->src;
|
|
|
|
if (src == NULL) {
|
|
PyErr_SetString(PyExc_AttributeError, "src");
|
|
return NULL;
|
|
}
|
|
if (!PyUnicode_Check(src))
|
|
return NULL; // Raise exception?
|
|
|
|
PyObject *bytes = PyUnicode_AsEncodedString(src, "UTF-8", "strict"); // Owned reference
|
|
if (bytes == NULL) {
|
|
..
|
|
return NULL;
|
|
}
|
|
|
|
char *cstr = PyBytes_AS_STRING(bytes);
|
|
|
|
..
|
|
|
|
}
|
|
|
|
static PyMemberDef TinyTemplate_members[] = {
|
|
{"src", T_OBJECT_EX, offsetof(Template, src), 0, "source string"},
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyMethodDef TinyTemplate_methods[] = {
|
|
{"eval", (PyCFunction) TinyTemplate_eval, METH_NOARGS, "Evaluate the template" },
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyTypeObject TemplateType = {
|
|
PyVarObject_HEAD_INIT(NULL, 0)
|
|
.tp_name = "tinytemplate.Template",
|
|
.tp_doc = PyDoc_STR("A template"),
|
|
.tp_basicsize = sizeof(Template),
|
|
.tp_itemsize = 0,
|
|
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
|
|
.tp_new = TinyTemplate_new,
|
|
.tp_init = (initproc) TinyTemplate_init,
|
|
.tp_dealloc = (destructor) TinyTemplate_dealloc,
|
|
.tp_members = TinyTemplate_members,
|
|
.tp_methods = TinyTemplate_methods,
|
|
};
|
|
|
|
static PyObject*
|
|
compile(PyObject *self, PyObject *args)
|
|
{
|
|
PyObject *src;
|
|
if (!PyArg_ParseTuple(args, "o", &src))
|
|
return NULL;
|
|
|
|
TinyTemplate_instr_t *prog = malloc();
|
|
|
|
return PyObject_Call((PyObject*) &TemplateType, src);
|
|
}
|
|
|
|
static PyMethodDef methods[] = {
|
|
{"compile", compile, METH_VARARGS, "Compile a template"},
|
|
{NULL, NULL, 0, NULL}, /* Sentinel */
|
|
};
|
|
|
|
static struct PyModuleDef module = {
|
|
PyModuleDef_HEAD_INIT,
|
|
"tinytemplate", /* name of module */
|
|
spam_doc, /* module documentation, may be NULL */
|
|
0, /* size of per-interpreter state of the module,
|
|
or -1 if the module keeps state in global variables. */
|
|
methods,
|
|
};
|
|
|
|
PyMODINIT_FUNC
|
|
PyInit_tinytemplate(void)
|
|
{
|
|
if (PyType_Ready(&TemplateType) < 0)
|
|
return NULL;
|
|
|
|
PyObject *m = PyModule_Create(&module);
|
|
if (m == NULL)
|
|
return NULL;
|
|
|
|
Py_INCREF(&TemplateType);
|
|
if (PyModule_AddObject(m, "Template", (PyObject *) &TemplateType) < 0) {
|
|
Py_DECREF(&TemplateType);
|
|
Py_DECREF(m);
|
|
return NULL;
|
|
}
|
|
|
|
return m;
|
|
} |