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>
1819typedef 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
365344static 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"
0 commit comments