Add support for allocating heap instead of stack memory

This can be enabled by defining `QUIRC_USE_HEAP`.
Define this before import, or add `-D QUIRC_USE_HEAP` flag while compiling.
This commit is contained in:
MU-Software 2022-01-10 02:14:14 +09:00
parent 516d91a94d
commit 18c27d6dd5
2 changed files with 134 additions and 43 deletions

View file

@ -179,15 +179,19 @@ static void berlekamp_massey(const uint8_t *s, int N,
const struct galois_field *gf, const struct galois_field *gf,
uint8_t *sigma) uint8_t *sigma)
{ {
uint8_t C[MAX_POLY]; #ifdef QUIRC_USE_HEAP
uint8_t B[MAX_POLY]; uint8_t *C = (uint8_t*)calloc(MAX_POLY, sizeof(uint8_t));
uint8_t *B = (uint8_t*)calloc(MAX_POLY, sizeof(uint8_t));
#else
uint8_t C[MAX_POLY] = {0};
uint8_t B[MAX_POLY] = {0};
#endif
int L = 0; int L = 0;
int m = 1; int m = 1;
uint8_t b = 1; uint8_t b = 1;
int n; int n;
memset(B, 0, sizeof(B));
memset(C, 0, sizeof(C));
B[0] = 1; B[0] = 1;
C[0] = 1; C[0] = 1;
@ -210,21 +214,35 @@ static void berlekamp_massey(const uint8_t *s, int N,
if (!d) { if (!d) {
m++; m++;
} else if (L * 2 <= n) { } else if (L * 2 <= n) {
uint8_t T[MAX_POLY]; #ifdef QUIRC_USE_HEAP
uint8_t *T = (uint8_t*)calloc(MAX_POLY, sizeof(uint8_t));
#else
uint8_t T[MAX_POLY] = {0};
#endif
memcpy(T, C, sizeof(T)); memcpy(T, C, sizeof(uint8_t) * MAX_POLY);
poly_add(C, B, mult, m, gf); poly_add(C, B, mult, m, gf);
memcpy(B, T, sizeof(B)); memcpy(B, T, sizeof(uint8_t) * MAX_POLY);
L = n + 1 - L; L = n + 1 - L;
b = d; b = d;
m = 1; m = 1;
#ifdef QUIRC_USE_HEAP
free(T);
#endif
} else { } else {
poly_add(C, B, mult, m, gf); poly_add(C, B, mult, m, gf);
m++; m++;
} }
} }
memcpy(sigma, C, MAX_POLY); memcpy(sigma, C, sizeof(uint8_t) * MAX_POLY);
#ifdef QUIRC_USE_HEAP
free(B);
free(C);
#endif
} }
/************************************************************************ /************************************************************************
@ -238,7 +256,7 @@ static int block_syndromes(const uint8_t *data, int bs, int npar, uint8_t *s)
int nonzero = 0; int nonzero = 0;
int i; int i;
memset(s, 0, MAX_POLY); memset(s, 0, sizeof(uint8_t) * MAX_POLY);
for (i = 0; i < npar; i++) { for (i = 0; i < npar; i++) {
int j; int j;
@ -266,7 +284,7 @@ static void eloc_poly(uint8_t *omega,
{ {
int i; int i;
memset(omega, 0, MAX_POLY); memset(omega, 0, sizeof(uint8_t) * MAX_POLY);
for (i = 0; i < npar; i++) { for (i = 0; i < npar; i++) {
const uint8_t a = sigma[i]; const uint8_t a = sigma[i];
@ -295,20 +313,36 @@ static quirc_decode_error_t correct_block(uint8_t *data,
const struct quirc_rs_params *ecc) const struct quirc_rs_params *ecc)
{ {
int npar = ecc->bs - ecc->dw; int npar = ecc->bs - ecc->dw;
uint8_t s[MAX_POLY];
uint8_t sigma[MAX_POLY];
uint8_t sigma_deriv[MAX_POLY];
uint8_t omega[MAX_POLY];
int i; int i;
#ifdef QUIRC_USE_HEAP
uint8_t *s = (uint8_t*)calloc(MAX_POLY, sizeof(uint8_t));
#else
uint8_t s[MAX_POLY] = {0};
#endif
/* Compute syndrome vector */ /* Compute syndrome vector */
if (!block_syndromes(data, ecc->bs, npar, s)) if (!block_syndromes(data, ecc->bs, npar, s)) {
#ifdef QUIRC_USE_HEAP
free(s);
#endif
return QUIRC_SUCCESS; return QUIRC_SUCCESS;
}
#ifdef QUIRC_USE_HEAP
uint8_t *sigma = (uint8_t*)calloc(MAX_POLY, sizeof(uint8_t));
uint8_t *sigma_deriv = (uint8_t*)calloc(MAX_POLY, sizeof(uint8_t));
uint8_t *omega = (uint8_t*)calloc(MAX_POLY, sizeof(uint8_t));
#else
uint8_t sigma[MAX_POLY] = {0};
uint8_t sigma_deriv[MAX_POLY] = {0};
uint8_t omega[MAX_POLY] = {0};
#endif
berlekamp_massey(s, npar, &gf256, sigma); berlekamp_massey(s, npar, &gf256, sigma);
/* Compute derivative of sigma */ /* Compute derivative of sigma */
memset(sigma_deriv, 0, MAX_POLY);
for (i = 0; i + 1 < MAX_POLY; i += 2) for (i = 0; i + 1 < MAX_POLY; i += 2)
sigma_deriv[i] = sigma[i + 1]; sigma_deriv[i] = sigma[i + 1];
@ -329,8 +363,23 @@ static quirc_decode_error_t correct_block(uint8_t *data,
} }
} }
if (block_syndromes(data, ecc->bs, npar, s)) #ifdef QUIRC_USE_HEAP
free(sigma);
free(sigma_deriv);
free(omega);
#endif
if (block_syndromes(data, ecc->bs, npar, s)){
#ifdef QUIRC_USE_HEAP
free(s);
#endif
return QUIRC_ERROR_DATA_ECC; return QUIRC_ERROR_DATA_ECC;
}
#ifdef QUIRC_USE_HEAP
free(s);
#endif
return QUIRC_SUCCESS; return QUIRC_SUCCESS;
} }
@ -350,7 +399,7 @@ static int format_syndromes(uint16_t u, uint8_t *s)
int i; int i;
int nonzero = 0; int nonzero = 0;
memset(s, 0, MAX_POLY); memset(s, 0, sizeof(uint8_t) * MAX_POLY);
for (i = 0; i < FORMAT_SYNDROMES; i++) { for (i = 0; i < FORMAT_SYNDROMES; i++) {
int j; int j;
@ -371,14 +420,28 @@ static quirc_decode_error_t correct_format(uint16_t *f_ret)
{ {
uint16_t u = *f_ret; uint16_t u = *f_ret;
int i; int i;
uint8_t s[MAX_POLY]; #ifdef QUIRC_USE_HEAP
uint8_t sigma[MAX_POLY]; uint8_t *s = (uint8_t*)calloc(MAX_POLY, sizeof(uint8_t));
#else
uint8_t s[MAX_POLY] = {0};
#endif
/* Evaluate U (received codeword) at each of alpha_1 .. alpha_6 /* Evaluate U (received codeword) at each of alpha_1 .. alpha_6
* to get S_1 .. S_6 (but we index them from 0). * to get S_1 .. S_6 (but we index them from 0).
*/ */
if (!format_syndromes(u, s)) if (!format_syndromes(u, s)) {
#ifdef QUIRC_USE_HEAP
free(s);
#endif
return QUIRC_SUCCESS; return QUIRC_SUCCESS;
}
#ifdef QUIRC_USE_HEAP
uint8_t *sigma = (uint8_t*)calloc(MAX_POLY, sizeof(uint8_t));
#else
uint8_t sigma[MAX_POLY] = {0};
#endif
berlekamp_massey(s, FORMAT_SYNDROMES, &gf16, sigma); berlekamp_massey(s, FORMAT_SYNDROMES, &gf16, sigma);
@ -387,6 +450,10 @@ static quirc_decode_error_t correct_format(uint16_t *f_ret)
if (!poly_eval(sigma, gf16_exp[15 - i], &gf16)) if (!poly_eval(sigma, gf16_exp[15 - i], &gf16))
u ^= (1 << i); u ^= (1 << i);
#ifdef QUIRC_USE_HEAP
free(sigma);
#endif
if (format_syndromes(u, s)) if (format_syndromes(u, s))
return QUIRC_ERROR_FORMAT_ECC; return QUIRC_ERROR_FORMAT_ECC;
@ -884,29 +951,34 @@ quirc_decode_error_t quirc_decode(const struct quirc_code *code,
struct quirc_data *data) struct quirc_data *data)
{ {
quirc_decode_error_t err; quirc_decode_error_t err;
struct datastream ds;
if (code->size > QUIRC_MAX_GRID_SIZE) #ifdef QUIRC_USE_HEAP
return QUIRC_ERROR_INVALID_GRID_SIZE; struct datastream *dsp = (struct datastream*)calloc(1, sizeof(struct datastream));
#else
struct datastream ds = {0};
struct datastream *dsp = &ds;
#endif
if ((code->size - 17) % 4) memset(data, 0, sizeof(struct quirc_data) * 1);
return QUIRC_ERROR_INVALID_GRID_SIZE;
memset(data, 0, sizeof(*data)); if (code->size > QUIRC_MAX_GRID_SIZE || (code->size - 17) % 4) {
memset(&ds, 0, sizeof(ds)); err = QUIRC_ERROR_INVALID_GRID_SIZE;
goto on_error;
}
data->version = (code->size - 17) / 4; data->version = (code->size - 17) / 4;
if (data->version < 1 || if (data->version < 1 || data->version > QUIRC_MAX_VERSION) {
data->version > QUIRC_MAX_VERSION) err = QUIRC_ERROR_INVALID_VERSION;
return QUIRC_ERROR_INVALID_VERSION; goto on_error;
}
/* Read format information -- try both locations */ /* Read format information -- try both locations */
err = read_format(code, data, 0); err = read_format(code, data, 0);
if (err) if (err)
err = read_format(code, data, 1); err = read_format(code, data, 1);
if (err) if (err)
return err; goto on_error;
/* /*
* Borrow data->payload to store the raw bits. * Borrow data->payload to store the raw bits.
@ -916,20 +988,31 @@ quirc_decode_error_t quirc_decode(const struct quirc_code *code,
* on the stack. * on the stack.
*/ */
ds.raw = data->payload; dsp->raw = data->payload;
read_data(code, data, &ds); read_data(code, data, dsp);
err = codestream_ecc(data, &ds); err = codestream_ecc(data, dsp);
if (err) if (err)
return err; goto on_error;
ds.raw = NULL; /* We've done with this buffer. */ dsp->raw = NULL; /* We've done with this buffer. */
err = decode_payload(data, &ds); err = decode_payload(data, dsp);
if (err) if (err)
return err; goto on_error;
#ifdef QUIRC_USE_HEAP
free(dsp);
#endif
return QUIRC_SUCCESS; return QUIRC_SUCCESS;
on_error:
#ifdef QUIRC_USE_HEAP
free(dsp);
#endif
return err;
} }
void quirc_flip(struct quirc_code *code) void quirc_flip(struct quirc_code *code)

View file

@ -289,8 +289,12 @@ static uint8_t otsu(const struct quirc *q)
unsigned int numPixels = q->w * q->h; unsigned int numPixels = q->w * q->h;
// Calculate histogram // Calculate histogram
unsigned int histogram[UINT8_MAX + 1]; #ifdef QUIRC_USE_HEAP
(void)memset(histogram, 0, sizeof(histogram)); unsigned int *histogram = (unsigned int*)calloc(UINT8_MAX + 1, sizeof(unsigned int));
#else
unsigned int histogram[UINT8_MAX + 1] = {0};
#endif
uint8_t* ptr = q->image; uint8_t* ptr = q->image;
unsigned int length = numPixels; unsigned int length = numPixels;
while (length--) { while (length--) {
@ -332,6 +336,10 @@ static uint8_t otsu(const struct quirc *q)
} }
} }
#ifdef QUIRC_USE_HEAP
free(histogram);
#endif
return threshold; return threshold;
} }