Skip to content

Commit 8fc2c48

Browse files
committed
API change: removed data_len, fixes #35
* removed bch.data_len * removed ecc and data_len from BCHObject * added test case for consecutive encode/decode * added test case for chaining encode * bumped major version
1 parent a5c296a commit 8fc2c48

File tree

5 files changed

+47
-45
lines changed

5 files changed

+47
-45
lines changed

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from setuptools import Extension, setup
66

77
NAME = 'bchlib'
8-
VERSION = '1.0.0'
8+
VERSION = '2.0.0'
99
DESCRIPTION = 'A python wrapper module for the Linux kernel BCH library.'
1010
URL = 'https://github.com/jkent/python-bchlib'
1111
EMAIL = 'jeff@jkent.net'

src/bchlib.c

Lines changed: 17 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <Python.h>
55
#include <structmember.h>
66

7+
#include <alloca.h>
78
#include <errno.h>
89
#include <stdbool.h>
910
#include <string.h>
@@ -18,8 +19,6 @@
1819
typedef struct {
1920
PyObject_HEAD
2021
struct bch_control *bch;
21-
uint8_t *ecc;
22-
unsigned int data_len;
2322
unsigned int *errloc;
2423
int nerr;
2524
} BCHObject;
@@ -32,11 +31,6 @@ BCH_dealloc(BCHObject *self)
3231
self->bch = NULL;
3332
}
3433

35-
if (self->ecc) {
36-
free(self->ecc);
37-
self->ecc = NULL;
38-
}
39-
4034
if (self->errloc) {
4135
free(self->errloc);
4236
self->errloc = NULL;
@@ -79,20 +73,10 @@ BCH_init(BCHObject *self, PyObject *args, PyObject *kwds)
7973
return -1;
8074
}
8175

82-
self->ecc = calloc(1, self->bch->ecc_bytes);
83-
if (!self->ecc) {
84-
bch_free(self->bch);
85-
self->bch = NULL;
86-
PyErr_SetString(PyExc_MemoryError, "unable to allocate ecc buffer");
87-
return -1;
88-
}
89-
9076
self->errloc = calloc(1, sizeof(unsigned int) * self->bch->t);
9177
if (!self->errloc) {
9278
bch_free(self->bch);
9379
self->bch = NULL;
94-
free(self->ecc);
95-
self->ecc = NULL;
9680
PyErr_SetString(PyExc_MemoryError, "unable to allocate errloc buffer");
9781
return -1;
9882
}
@@ -114,21 +98,20 @@ BCH_encode(BCHObject *self, PyObject *args, PyObject *kwds)
11498
return NULL;
11599
}
116100

117-
if (ecc.buf) {
118-
if (ecc.len != self->bch->ecc_bytes) {
119-
PyErr_Format(PyExc_ValueError, "ecc length must be %d bytes",
120-
self->bch->ecc_bytes);
121-
return NULL;
122-
}
123-
memcpy(self->ecc, ecc.buf, self->bch->ecc_bytes);
124-
} else {
125-
memset(self->ecc, 0, self->bch->ecc_bytes);
101+
if (!ecc.buf) {
102+
ecc.len = self->bch->ecc_bytes;
103+
ecc.buf = alloca(ecc.len);
104+
memset(ecc.buf, 0, ecc.len);
105+
} else if (ecc.len != self->bch->ecc_bytes) {
106+
PyErr_Format(PyExc_ValueError, "ecc length must be %d bytes",
107+
self->bch->ecc_bytes);
108+
return NULL;
126109
}
127110

128111
bch_encode(self->bch, (uint8_t *) data.buf, (unsigned int) data.len,
129-
self->ecc);
112+
ecc.buf);
130113

131-
return PyBytes_FromStringAndSize((const char *)self->ecc,
114+
return PyBytes_FromStringAndSize((const char *) ecc.buf,
132115
self->bch->ecc_bytes);
133116
}
134117

@@ -146,10 +129,6 @@ BCH_decode(BCHObject *self, PyObject *args, PyObject *kwds)
146129
return NULL;
147130
}
148131

149-
if (data.buf && self->data_len <= 0) {
150-
self->data_len = data.len;
151-
}
152-
153132
if (recv_ecc.buf && recv_ecc.len != self->bch->ecc_bytes) {
154133
PyErr_Format(PyExc_ValueError, "recv_ecc length should be %d bytes",
155134
self->bch->ecc_bytes);
@@ -194,7 +173,7 @@ BCH_decode(BCHObject *self, PyObject *args, PyObject *kwds)
194173
Py_DECREF(syn);
195174
}
196175

197-
self->nerr = bch_decode(self->bch, data.buf, self->data_len, recv_ecc.buf,
176+
self->nerr = bch_decode(self->bch, data.buf, data.len, recv_ecc.buf,
198177
calc_ecc.buf, syn ? self->bch->syn : NULL, self->errloc);
199178

200179
if (self->nerr < 0) {
@@ -219,7 +198,7 @@ BCH_correct(BCHObject *self, PyObject *args, PyObject *kwds)
219198
PyObject *result = NULL;
220199

221200
static char *kwlist[] = {"data", "ecc", NULL};
222-
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|y*y*", kwlist, &data,
201+
if (!PyArg_ParseTupleAndKeywords(args, kwds, "y*|y*", kwlist, &data,
223202
&ecc)) {
224203
goto cleanup;
225204
}
@@ -240,20 +219,20 @@ BCH_correct(BCHObject *self, PyObject *args, PyObject *kwds)
240219

241220
for (int i = 0; i < self->nerr; i++) {
242221
unsigned int bitnum = self->errloc[i];
243-
if (bitnum >= (self->data_len + self->bch->ecc_bytes) * 8) {
222+
if (bitnum >= (data.len + self->bch->ecc_bytes) * 8) {
244223
PyErr_SetString(PyExc_IndexError, "uncorrectable error");
245224
return NULL;
246225
}
247226
unsigned int byte = bitnum / 8;
248227
unsigned char bit = 1 << (bitnum & 7);
249228

250-
if (byte < self->data_len) {
229+
if (byte < data.len) {
251230
if (data.buf && !data.readonly) {
252231
((uint8_t *) data.buf)[byte] ^= bit;
253232
}
254233
} else {
255234
if (ecc.buf && !ecc.readonly) {
256-
((uint8_t *) ecc.buf)[byte - self->data_len] ^= bit;
235+
((uint8_t *) ecc.buf)[byte - data.len] ^= bit;
257236
}
258237
}
259238
}
@@ -363,9 +342,6 @@ BCH_getattr(BCHObject *self, PyObject *name)
363342
}
364343

365344
static PyMemberDef BCH_members[] = {
366-
{"data_len", T_UINT, offsetof(BCHObject, data_len), 0,
367-
"Read/write; decode data length in bytes. Set this value before\n"
368-
"decoding."},
369345
{"ecc_bits", -1, 0, READONLY|RESTRICTED,
370346
"Readonly; number of ecc bits."},
371347
{"ecc_bytes", -1, 0, READONLY|RESTRICTED,
@@ -401,9 +377,7 @@ static PyMethodDef BCH_methods[] = {
401377
" 'data' and 'recv_ecc'\n"
402378
" 'recv_ecc' and 'calc_ecc'\n"
403379
" 'calc_ecc' (as recv_ecc XOR calc_ecc)\n"
404-
" 'syn' (a sequence of 2*t values)\n\n"
405-
406-
"'data_len' SHOULD be set before calling this function."},
380+
" 'syn' (a sequence of 2*t values)"},
407381
{"correct", (PyCFunction) BCH_correct, METH_VARARGS | METH_KEYWORDS, "\b\b\b\b"
408382
"correct(data=None, ecc=None) → None\n"
409383
"Corrects 'data' and 'ecc' if provided. Buffers must not be\n"

tests/test_chaining.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/usr/bin/env python
2+
3+
import bchlib
4+
import unittest
5+
6+
class BCHTestCase(unittest.TestCase):
7+
def test(self):
8+
bch = bchlib.BCH(16, m=13)
9+
ecc = bch.encode(b'First')
10+
ecc = bch.encode(b'Second', ecc=ecc)
11+
assert(bch.decode(b'FirstSecond', ecc) == 0)
12+
13+
if __name__ == '__main__':
14+
unittest.main()

tests/test_consecutive.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#!/usr/bin/env python
2+
3+
import bchlib
4+
import unittest
5+
6+
class BCHTestCase(unittest.TestCase):
7+
def test(self):
8+
bch = bchlib.BCH(16, m=13)
9+
ecc1 = bch.encode(b'First')
10+
ecc2 = bch.encode(b'Second')
11+
assert(bch.decode(b'First', ecc1) == 0)
12+
assert(bch.decode(b'Second', ecc2) == 0)
13+
14+
if __name__ == '__main__':
15+
unittest.main()

tests/test_exercise.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ def bitflip(packet):
5151
data, ecc = packet[:-bch.ecc_bytes], packet[-bch.ecc_bytes:]
5252

5353
# decode
54-
bch.data_len = max_data_len
5554
nerr = bch.decode(data, ecc)
5655

5756
print('nerr:', nerr)

0 commit comments

Comments
 (0)