Skip to content

Commit

Permalink
ConsAtom (C)
Browse files Browse the repository at this point in the history
  • Loading branch information
MatrixEditor committed Sep 7, 2024
1 parent fc8f68b commit fac0cd3
Show file tree
Hide file tree
Showing 11 changed files with 160 additions and 8 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 35,7 @@ python_add_library(
src/atomimpl/charatomobj.c
src/atomimpl/padatomobj.c
src/atomimpl/stringatomobj.c
src/atomimpl/constatomobj.c

WITH_SOABI
)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 28,7 @@ options will be added in the future. Documentation is [here >](https://matrixedi
* it helps you to create cleaner and more compact code.
* You can even extend Caterpillar and write your parsing logic in C or C !!

## What does it look like?
## Give me some code!

```python
from caterpillar.py import *
Expand Down
98 changes: 98 additions & 0 deletions src/atomimpl/constatomobj.c
Original file line number Diff line number Diff line change
@@ -0,0 1,98 @@
/* constatom C implementation */
#include "caterpillar/caterpillar.h"

#include <structmember.h>

static PyObject*
cp_constatom__type__(CpConstAtomObject* self)
{
return CpTypeOf(self->m_atom);
}

static PyObject*
cp_constatom__size__(CpConstAtomObject* self, CpLayerObject* layer)
{
return _Cp_SizeOf(self->m_atom, layer);
}

static PyObject*
cp_constatom_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
{
CpConstAtomObject* self = (CpConstAtomObject*)type->tp_alloc(type, 0);
if (self != NULL) {
CpFieldCAtom_CATOM(self).ob_pack = (packfunc)CpConstAtom_Pack;
CpFieldCAtom_CATOM(self).ob_unpack = (unpackfunc)CpConstAtom_Unpack;
CpFieldCAtom_CATOM(self).ob_pack_many = NULL;
CpFieldCAtom_CATOM(self).ob_unpack_many = NULL;
CpFieldCAtom_CATOM(self).ob_size = (sizefunc)cp_constatom__size__;
CpFieldCAtom_CATOM(self).ob_type = (typefunc)cp_constatom__type__;
CpFieldCAtom_CATOM(self).ob_bits = NULL;

self->m_atom = NULL;
self->m_value = NULL;
}
return (PyObject*)self;
}

static void
cp_constatom_dealloc(CpConstAtomObject* self)
{
Py_XDECREF(self->m_atom);
Py_XDECREF(self->m_value);
Py_TYPE(self)->tp_free((PyObject*)self);
}

static int
cp_constatom_init(CpConstAtomObject* self, PyObject* args, PyObject* kwds)
{
static char* kwlist[] = { "atom", "value", NULL };
PyObject* atom = NULL;
PyObject* value = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &atom, &value)) {
return -1;
}
_Cp_SetObj(self->m_atom, atom);
_Cp_SetObj(self->m_value, value);
return 0;
}

/* Public API */

/*CpAPI*/
int
CpConstAtom_Pack(CpConstAtomObject* self, PyObject* value, CpLayerObject* layer)
{
return _Cp_Pack(self->m_value, self->m_atom, layer);
}

/*CpAPI*/
PyObject*
CpConstAtom_Unpack(CpConstAtomObject* self, CpLayerObject* layer)
{
PyObject* res = _Cp_Unpack(self->m_atom, layer);
if (!res) {
return NULL;
}

if (PyObject_RichCompareBool(res, self->m_value, Py_NE)) {
PyErr_Format(PyExc_ValueError,
"Value is not equal to constant (parsed=%R, constant=%R)",
res,
self->m_value);
Py_DECREF(res);
return NULL;
}
// REVISIT: Should we free the 'res' object here?
return res;
}

/* type setup */

PyTypeObject CpConstAtom_Type = {
PyVarObject_HEAD_INIT(NULL, 0) _Cp_NameStr(CpConstAtom_NAME),
.tp_basicsize = sizeof(CpConstAtomObject),
.tp_dealloc = (destructor)cp_constatom_dealloc,
.tp_init = (initproc)cp_constatom_init,
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_new = (newfunc)cp_constatom_new,
};
5 changes: 3 additions & 2 deletions src/atomimpl/intatomobj.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 50,7 @@ cp_intatom_init(CpIntAtomObject* self, PyObject* args, PyObject* kwds)
{
static char* kwlist[] = { "nbits", "signed", "little_endian", NULL };
int _signed = true, little_endian = true;
size_t bits = 0;
unsigned int bits = 0;
if (!PyArg_ParseTupleAndKeywords(
args, kwds, "I|pp", kwlist, &bits, &_signed, &little_endian)) {
return -1;
Expand Down Expand Up @@ -101,7 101,7 @@ CpIntAtom_Pack(CpIntAtomObject* self, PyObject* op, CpLayerObject* layer)
}

int res = _PyLong_AsByteArray((PyLongObject*)op,
(unsigned char*)PyBytes_AS_STRING(op),
(unsigned char*)PyBytes_AS_STRING(bytes),
self->_m_byte_count,
little_endian,
self->_m_signed);
Expand Down Expand Up @@ -168,4 168,5 @@ PyTypeObject CpIntAtom_Type = {
.tp_doc = NULL,
.tp_members = CpIntAtom_Members,
.tp_new = (newfunc)cp_intatom_new,
.tp_init = (initproc)cp_intatom_init,
};
35 changes: 35 additions & 0 deletions src/caterpillar/include/caterpillar/atoms/const.h
Original file line number Diff line number Diff line change
@@ -0,0 1,35 @@
/**
* Copyright (C) MatrixEditor 2024
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef CONSTATOMOBJ_H
#define CONSTATOMOBJ_H

#include "caterpillar/caterpillarapi.h"
#include "caterpillar/field.h"

struct _constatomobj
{
CpFieldCAtom_HEAD

PyObject *m_value;
PyObject *m_atom;
};

#define CpConstAtom_NAME "const_t"
#define CpConstAtom_CheckExact(op) Py_IS_TYPE((op), &CpConstAtom_Type)
#define CpConstAtom_Check(op) PyObject_TypeCheck((op), &CpConstAtom_Type)

#endif
1 change: 1 addition & 0 deletions src/caterpillar/include/caterpillar/caterpillar.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 19,6 @@
#include "caterpillar/atoms/float.h"
#include "caterpillar/atoms/primitive.h"
#include "caterpillar/atoms/string.h"
#include "caterpillar/atoms/const.h"

#endif
8 changes: 8 additions & 0 deletions src/caterpillar/include/caterpillar/caterpillarapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 72,8 @@ struct _paddingatomobj;
typedef struct _paddingatomobj CpPaddingAtomObject;
struct _stringatomobj;
typedef struct _stringatomobj CpStringAtomObject;
struct _constatomobj;
typedef struct _constatomobj CpConstAtomObject;

#ifdef _CPMODULE

Expand Down Expand Up @@ -107,6 109,7 @@ extern PyTypeObject CpBoolAtom_Type;
extern PyTypeObject CpCharAtom_Type;
extern PyTypeObject CpPaddingAtom_Type;
extern PyTypeObject CpStringAtom_Type;
extern PyTypeObject CpConstAtom_Type;
int CpEndian_IsLittleEndian(CpEndianObject* endian, _modulestate* mod);
CpContextObject* CpContext_New(void);
CpUnaryExprObject* CpUnaryExpr_New(int op, PyObject* value);
Expand Down Expand Up @@ -176,6 179,8 @@ PyObject* CpPaddingAtom_Unpack(CpPaddingAtomObject* self, CpLayerObject* layer);
PyObject* CpPaddingAtom_UnpackMany(CpPaddingAtomObject* self, CpLayerObject* layer);
int CpStringAtom_Pack(CpStringAtomObject* self,PyObject* value,CpLayerObject* layer);
PyObject* CpStringAtom_Unpack(CpStringAtomObject* self, CpLayerObject* layer);
int CpConstAtom_Pack(CpConstAtomObject* self, PyObject* value, CpLayerObject* layer);
PyObject* CpConstAtom_Unpack(CpConstAtomObject* self, CpLayerObject* layer);

#else

Expand Down Expand Up @@ -212,6 217,7 @@ caterpillar_api.py
#define CpCharAtom_Type (*(PyTypeObject *)Cp_API[24])
#define CpPaddingAtom_Type (*(PyTypeObject *)Cp_API[25])
#define CpStringAtom_Type (*(PyTypeObject *)Cp_API[26])
#define CpConstAtom_Type (*(PyTypeObject *)Cp_API[27])
#define CpEndian_IsLittleEndian (*((int (*)(CpEndianObject* endian, _modulestate* mod)))Cp_API[50])
#define CpContext_New (*((CpContextObject* (*)(void)))Cp_API[53])
#define CpUnaryExpr_New (*((CpUnaryExprObject* (*)(int op, PyObject* value)))Cp_API[54])
Expand Down Expand Up @@ -281,6 287,8 @@ caterpillar_api.py
#define CpPaddingAtom_UnpackMany (*((PyObject* (*)(CpPaddingAtomObject* self, CpLayerObject* layer)))Cp_API[131])
#define CpStringAtom_Pack (*((int (*)(CpStringAtomObject* self,PyObject* value,CpLayerObject* layer)))Cp_API[132])
#define CpStringAtom_Unpack (*((PyObject* (*)(CpStringAtomObject* self, CpLayerObject* layer)))Cp_API[133])
#define CpConstAtom_Pack (*((int (*)(CpConstAtomObject* self, PyObject* value, CpLayerObject* layer)))Cp_API[134])
#define CpConstAtom_Unpack (*((PyObject* (*)(CpConstAtomObject* self, CpLayerObject* layer)))Cp_API[135])

/**
* @brief Public C API for extension modules as reference table
Expand Down
6 changes: 4 additions & 2 deletions src/caterpillarapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 30,7 @@ void *Cp_API[] = {
(void *) &CpCharAtom_Type,
(void *) &CpPaddingAtom_Type,
(void *) &CpStringAtom_Type,
NULL,
(void *) &CpConstAtom_Type,
NULL,
NULL,
NULL,
Expand Down Expand Up @@ -136,6 136,8 @@ void *Cp_API[] = {
(void *) &CpPaddingAtom_Unpack,
(void *) &CpPaddingAtom_UnpackMany,
(void *) &CpStringAtom_Pack,
(void *) &CpStringAtom_Unpack
(void *) &CpStringAtom_Unpack,
(void *) &CpConstAtom_Pack,
(void *) &CpConstAtom_Unpack
};

5 changes: 5 additions & 0 deletions src/code_gen/caterpillar_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 41,7 @@
"_charatomobj": "CpCharAtomObject",
"_paddingatomobj": "CpPaddingAtomObject",
"_stringatomobj": "CpStringAtomObject",
"_constatomobj": "CpConstAtomObject",
}

cp_type_api = {
Expand Down Expand Up @@ -71,6 72,7 @@
"CpCharAtom_Type": (24,),
"CpPaddingAtom_Type": (25,),
"CpStringAtom_Type": (26,),
"CpConstAtom_Type": (27,),
}

cp_func_api = {
Expand Down Expand Up @@ -148,6 150,8 @@
"CpPaddingAtom_UnpackMany": 131,
"CpStringAtom_Pack": 132,
"CpStringAtom_Unpack": 133,
"CpConstAtom_Pack": 134,
"CpConstAtom_Unpack": 135,
}

API_SRC = [
Expand All @@ -168,6 172,7 @@
"atomimpl/intatomobj.c",
"atomimpl/padatomobj.c",
"atomimpl/stringatomobj.c",
"atomimpl/constatomobj.c",
]


Expand Down
4 changes: 4 additions & 0 deletions src/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 404,9 @@ PyInit__C(void)
CpStringAtom_Type.tp_base = &CpFieldCAtom_Type;
CpModule_SetupType(&CpStringAtom_Type);

CpConstAtom_Type.tp_base = &CpFieldCAtom_Type;
CpModule_SetupType(&CpConstAtom_Type);

// module setup
m = PyModule_Create(&CpModule);
if (!m) {
Expand Down Expand Up @@ -437,6 440,7 @@ PyInit__C(void)
CpModule_AddObject(CpCharAtom_NAME, &CpCharAtom_Type);
CpModule_AddObject(CpPaddingAtom_NAME, &CpPaddingAtom_Type);
CpModule_AddObject(CpStringAtom_NAME, &CpStringAtom_Type);
CpModule_AddObject(CpConstAtom_NAME, &CpConstAtom_Type);

/* setup custom intatoms */
#define CpModule_DefAtom(name, ...) \
Expand Down
3 changes: 0 additions & 3 deletions src/parsing_pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -439,9 439,6 @@ _Cp_Pack(PyObject* op, PyObject* atom, CpLayerObject* layer)
success = CpPack_Struct(op, (CpStructObject*)atom, layer);
} else if (CpCAtom_Check(atom)) {
return CpPack_CAtom(op, (CpCAtomObject*)atom, layer);
// else CASE(&CpCAtom_Type, atom) {
// success = cp_pack_catom
// }
} else {
success = CpPack_Common(op, atom, layer);
}
Expand Down

0 comments on commit fac0cd3

Please sign in to comment.