LCOV - code coverage report
Current view: top level - src/decode - decode_qr.c (source / functions) Coverage Total Hit
Test: lierre Coverage Report Lines: 87.7 % 334 293
Test Date: 2026-03-06 08:40:14 Functions: 100.0 % 20 20
Legend: Lines: hit not hit

            Line data    Source code
       1              : /*
       2              :  * liblierre - decode_qr.c
       3              :  *
       4              :  * This file is part of liblierre.
       5              :  *
       6              :  * Author: Go Kudo <zeriyoshi@gmail.com>
       7              :  * SPDX-License-Identifier: MIT AND ISC
       8              :  *
       9              :  * This file contains code derived from quirc (https://github.com/dlbeer/quirc).
      10              :  * Copyright (C) 2010-2012 Daniel Beer <dlbeer@gmail.com>
      11              :  * Licensed under the ISC License.
      12              :  */
      13              : 
      14              : #include <poporon.h>
      15              : 
      16              : #include "../internal/decoder.h"
      17              : 
      18              : #define FORMAT_BITS_COUNT      15
      19              : #define FORMAT_XOR_MASK        0x5412
      20              : #define FORMAT_DATA_SHIFT      10
      21              : #define FORMAT_ECC_LEVEL_SHIFT 3
      22              : #define FORMAT_MASK_BITS       7
      23              : 
      24              : #define FORMAT_BCH_SYMBOL_SIZE  4
      25              : #define FORMAT_BCH_GEN_POLY     0x13
      26              : #define FORMAT_BCH_CORRECTION_T 3
      27              : 
      28              : #define FINDER_PATTERN_SIZE        7
      29              : #define FINDER_EDGE_SIZE           8
      30              : #define FINDER_CENTER              9
      31              : #define TIMING_PATTERN_POSITION    6
      32              : #define VERSION_INFO_OFFSET        11
      33              : #define VERSION_INFO_SIZE          6
      34              : #define QR_VERSION1_SIZE           17
      35              : #define LIERRE_QR_VERSION_INFO_MIN 7
      36              : 
      37              : #define MODE_NUMERIC      1
      38              : #define MODE_ALPHANUMERIC 2
      39              : #define MODE_BYTE         4
      40              : #define MODE_ECI          7
      41              : #define MODE_KANJI        8
      42              : 
      43              : #define ALPHANUMERIC_CHARSET_SIZE 45
      44              : 
      45              : #define KANJI_ENCODE_DIVISOR 0xc0
      46              : #define KANJI_SJIS_BASE1     0x8140
      47              : #define KANJI_SJIS_BOUNDARY  0x9ffc
      48              : #define KANJI_SJIS_BASE2     0xc140
      49              : 
      50              : #define VERSION_THRESHOLD_SMALL  10
      51              : #define VERSION_THRESHOLD_MEDIUM 27
      52              : 
      53              : #define NUMERIC_BITS_SMALL  10
      54              : #define NUMERIC_BITS_MEDIUM 12
      55              : #define NUMERIC_BITS_LARGE  14
      56              : 
      57              : #define ALPHA_BITS_SMALL   9
      58              : #define ALPHA_BITS_MEDIUM  11
      59              : #define ALPHA_BITS_LARGE   13
      60              : #define BYTE_BITS_SMALL    8
      61              : #define BYTE_BITS_LARGE    16
      62              : #define KANJI_BITS_SMALL   8
      63              : #define KANJI_BITS_MEDIUM  10
      64              : #define KANJI_BITS_LARGE   12
      65              : #define KANJI_ENCODED_BITS 13
      66              : 
      67       984050 : static inline int32_t grid_bit(const qr_code_t *code, int32_t x, int32_t y)
      68              : {
      69              :     int32_t bit_position;
      70              : 
      71       984050 :     bit_position = y * code->size + x;
      72       984050 :     return (code->cell_bitmap[bit_position >> 3] >> (bit_position & 7)) & 1;
      73              : }
      74              : 
      75          138 : static inline lierre_error_t correct_format_bits(uint16_t *format_bits)
      76              : {
      77              :     poporon_config_t *config;
      78              :     poporon_t *pprn;
      79              :     uint8_t data[1], parity[2];
      80              :     size_t corrected;
      81              : 
      82          138 :     config = poporon_bch_config_create(FORMAT_BCH_SYMBOL_SIZE, FORMAT_BCH_GEN_POLY, FORMAT_BCH_CORRECTION_T);
      83          138 :     if (!config) {
      84            0 :         return LIERRE_ERROR_FORMAT_ECC;
      85              :     }
      86              : 
      87          138 :     pprn = poporon_create(config);
      88          138 :     if (!pprn) {
      89            0 :         poporon_config_destroy(config);
      90            0 :         return LIERRE_ERROR_FORMAT_ECC;
      91              :     }
      92              : 
      93          138 :     data[0] = (uint8_t)((*format_bits >> 10) & 0x1F);
      94          138 :     parity[0] = (uint8_t)((*format_bits >> 8) & 0x03);
      95          138 :     parity[1] = (uint8_t)(*format_bits & 0xFF);
      96              : 
      97          138 :     if (!poporon_decode(pprn, data, 1, parity, &corrected)) {
      98           15 :         poporon_destroy(pprn);
      99           15 :         poporon_config_destroy(config);
     100           15 :         return LIERRE_ERROR_FORMAT_ECC;
     101              :     }
     102              : 
     103          123 :     poporon_destroy(pprn);
     104          123 :     poporon_config_destroy(config);
     105              : 
     106          123 :     *format_bits = (uint16_t)((data[0] << 10) | (parity[0] << 8) | parity[1]);
     107              : 
     108          123 :     return LIERRE_ERROR_SUCCESS;
     109              : }
     110              : 
     111          138 : static inline lierre_error_t read_format(const qr_code_t *code, qr_data_t *data, int32_t use_secondary)
     112              : {
     113              :     static const int32_t primary_x_positions[FORMAT_BITS_COUNT] = {8, 8, 8, 8, 8, 8, 8, 8, 7, 5, 4, 3, 2, 1, 0},
     114              :                          primary_y_positions[FORMAT_BITS_COUNT] = {0, 1, 2, 3, 4, 5, 7, 8, 8, 8, 8, 8, 8, 8, 8};
     115              :     lierre_error_t err;
     116              :     uint16_t format_bits, format_data;
     117              :     int32_t i;
     118              : 
     119          138 :     format_bits = 0;
     120              : 
     121          138 :     if (use_secondary) {
     122           72 :         for (i = 0; i < FINDER_PATTERN_SIZE; i++) {
     123           63 :             format_bits = (uint16_t)((format_bits << 1) | grid_bit(code, FINDER_EDGE_SIZE, code->size - 1 - i));
     124              :         }
     125              : 
     126           81 :         for (i = 0; i < FINDER_EDGE_SIZE; i++) {
     127           72 :             format_bits =
     128           72 :                 (uint16_t)((format_bits << 1) | grid_bit(code, code->size - FINDER_EDGE_SIZE + i, FINDER_EDGE_SIZE));
     129              :         }
     130              :     } else {
     131         2064 :         for (i = FORMAT_BITS_COUNT - 1; i >= 0; i--) {
     132         1935 :             format_bits =
     133         1935 :                 (uint16_t)((format_bits << 1) | grid_bit(code, primary_x_positions[i], primary_y_positions[i]));
     134              :         }
     135              :     }
     136              : 
     137          138 :     format_bits ^= FORMAT_XOR_MASK;
     138              : 
     139          138 :     err = correct_format_bits(&format_bits);
     140          138 :     if (err) {
     141           15 :         return err;
     142              :     }
     143              : 
     144          123 :     format_data = (uint16_t)(format_bits >> FORMAT_DATA_SHIFT);
     145          123 :     data->ecc_level = format_data >> FORMAT_ECC_LEVEL_SHIFT;
     146          123 :     data->mask = format_data & FORMAT_MASK_BITS;
     147              : 
     148          123 :     return LIERRE_ERROR_SUCCESS;
     149              : }
     150              : 
     151       981640 : static inline int32_t mask_bit(int32_t mask_pattern, int32_t row, int32_t col)
     152              : {
     153       981640 :     switch (mask_pattern) {
     154       100916 :     case 0:
     155       100916 :         return !((row + col) % 2);
     156        49805 :     case 1:
     157        49805 :         return !(row % 2);
     158       214240 :     case 2:
     159       214240 :         return !(col % 3);
     160       279855 :     case 3:
     161       279855 :         return !((row + col) % 3);
     162       160433 :     case 4:
     163       160433 :         return !(((row / 2) + (col / 3)) % 2);
     164        42821 :     case 5:
     165        42821 :         return !((row * col) % 2 + (row * col) % 3);
     166        80100 :     case 6:
     167        80100 :         return !(((row * col) % 2 + (row * col) % 3) % 2);
     168        61921 :     case 7:
     169        61921 :         return !(((row * col) % 3 + (row + col) % 2) % 2);
     170              :     }
     171              : 
     172            0 :     return 0;
     173              : }
     174              : 
     175      1058467 : static inline int32_t is_reserved_cell(int32_t version, int32_t row, int32_t col)
     176              : {
     177              :     const version_info_t *version_info;
     178              :     int32_t size, alignment_row_idx, alignment_col_idx, alignment_idx, pos;
     179              : 
     180      1058467 :     version_info = &lierre_version_db[version];
     181      1058467 :     size = version * 4 + QR_VERSION1_SIZE;
     182      1058467 :     alignment_row_idx = -1;
     183      1058467 :     alignment_col_idx = -1;
     184              : 
     185      1058467 :     if (row < FINDER_CENTER && col < FINDER_CENTER) {
     186         8831 :         return 1;
     187              :     }
     188              : 
     189      1049636 :     if (row + FINDER_EDGE_SIZE >= size && col < FINDER_CENTER) {
     190         7857 :         return 1;
     191              :     }
     192              : 
     193      1041779 :     if (row < FINDER_CENTER && col + FINDER_EDGE_SIZE >= size) {
     194         8856 :         return 1;
     195              :     }
     196              : 
     197      1032923 :     if (row == TIMING_PATTERN_POSITION || col == TIMING_PATTERN_POSITION) {
     198         7804 :         return 1;
     199              :     }
     200              : 
     201      1025119 :     if (version >= LIERRE_QR_VERSION_INFO_MIN) {
     202       999295 :         if (row < TIMING_PATTERN_POSITION && col + VERSION_INFO_OFFSET >= size) {
     203         1386 :             return 1;
     204              :         }
     205              : 
     206       997909 :         if (row + VERSION_INFO_OFFSET >= size && col < TIMING_PATTERN_POSITION) {
     207         1383 :             return 1;
     208              :         }
     209              :     }
     210              : 
     211      6727415 :     for (alignment_idx = 0; alignment_idx < LIERRE_DECODER_MAX_ALIGNMENT && version_info->apat[alignment_idx];
     212      5705065 :          alignment_idx++) {
     213      5705065 :         pos = version_info->apat[alignment_idx];
     214              : 
     215      5705065 :         if ((pos - row) >= -2 && (pos - row) <= 2) {
     216       212914 :             alignment_row_idx = alignment_idx;
     217              :         }
     218              : 
     219      5705065 :         if ((pos - col) >= -2 && (pos - col) <= 2) {
     220       212940 :             alignment_col_idx = alignment_idx;
     221              :         }
     222              :     }
     223              : 
     224      1022350 :     if (alignment_row_idx >= 0 && alignment_col_idx >= 0) {
     225        42920 :         alignment_idx--;
     226              : 
     227        42920 :         if (alignment_row_idx > 0 && alignment_row_idx < alignment_idx) {
     228        29799 :             return 1;
     229              :         }
     230              : 
     231        13121 :         if (alignment_col_idx > 0 && alignment_col_idx < alignment_idx) {
     232        10035 :             return 1;
     233              :         }
     234              : 
     235         3086 :         if (alignment_col_idx == alignment_idx && alignment_row_idx == alignment_idx) {
     236         2575 :             return 1;
     237              :         }
     238              :     }
     239              : 
     240       979941 :     return 0;
     241              : }
     242              : 
     243       982413 : static inline void read_bit(const qr_code_t *code, qr_data_t *data, datastream_t *ds, int32_t row, int32_t col)
     244              : {
     245              :     int32_t bit_offset, byte_offset, value;
     246              : 
     247       982413 :     bit_offset = ds->data_bits & 7;
     248       982413 :     byte_offset = ds->data_bits >> 3;
     249       982413 :     value = grid_bit(code, col, row);
     250              : 
     251       982138 :     if (mask_bit(data->mask, row, col)) {
     252       419024 :         value ^= 1;
     253              :     }
     254              : 
     255       981628 :     if (value) {
     256       489722 :         ds->raw[byte_offset] |= (0x80 >> bit_offset);
     257              :     }
     258              : 
     259       981628 :     ds->data_bits++;
     260       981628 : }
     261              : 
     262          123 : static inline void read_data(const qr_code_t *code, qr_data_t *data, datastream_t *ds)
     263              : {
     264              :     int32_t row, col, direction;
     265              : 
     266          123 :     row = code->size - 1;
     267          123 :     col = code->size - 1;
     268          123 :     direction = -1;
     269              : 
     270       533085 :     while (col > 0) {
     271       532990 :         if (col == 6) {
     272          123 :             col--;
     273              :         }
     274              : 
     275       532990 :         if (!is_reserved_cell(data->version, row, col)) {
     276       490365 :             read_bit(code, data, ds, row, col);
     277              :         }
     278              : 
     279       532320 :         if (!is_reserved_cell(data->version, row, col - 1)) {
     280       498360 :             read_bit(code, data, ds, row, col - 1);
     281              :         }
     282              : 
     283       532962 :         row += direction;
     284       532962 :         if (row < 0 || row >= code->size) {
     285         4801 :             direction = -direction;
     286         4801 :             col -= 2;
     287         4801 :             row += direction;
     288              :         }
     289              :     }
     290           95 : }
     291              : 
     292         1565 : static inline lierre_error_t correct_block_with_poporon(uint8_t *block_data, const rs_params_t *ecc_params)
     293              : {
     294              :     poporon_t *rs_decoder;
     295              :     poporon_config_t *config;
     296              :     int32_t parity_bytes;
     297              :     size_t corrected;
     298              :     bool success;
     299              : 
     300         1565 :     parity_bytes = ecc_params->bs - ecc_params->dw;
     301              : 
     302         1565 :     config = poporon_rs_config_create(8, 0x11D, 0, 1, (uint8_t)parity_bytes, NULL, NULL);
     303         1565 :     if (!config) {
     304            0 :         return LIERRE_ERROR_DATA_ECC;
     305              :     }
     306              : 
     307         1565 :     rs_decoder = poporon_create(config);
     308         1565 :     if (!rs_decoder) {
     309            0 :         poporon_config_destroy(config);
     310            0 :         return LIERRE_ERROR_DATA_ECC;
     311              :     }
     312              : 
     313         1565 :     success = poporon_decode(rs_decoder, block_data, (size_t)ecc_params->dw, &block_data[ecc_params->dw], &corrected);
     314         1565 :     poporon_destroy(rs_decoder);
     315         1565 :     poporon_config_destroy(config);
     316              : 
     317         1565 :     if (!success) {
     318           19 :         return LIERRE_ERROR_DATA_ECC;
     319              :     }
     320              : 
     321         1546 :     return LIERRE_ERROR_SUCCESS;
     322              : }
     323              : 
     324          123 : static inline lierre_error_t codestream_ecc(qr_data_t *data, datastream_t *ds)
     325              : {
     326              :     const version_info_t *version_info;
     327              :     const rs_params_t *short_block_ecc, *current_ecc;
     328              :     rs_params_t long_block_ecc;
     329              :     lierre_error_t err;
     330              :     uint8_t *dst;
     331              :     int32_t long_block_count, total_blocks, ecc_offset, dst_offset, block_idx, byte_idx, parity_count;
     332              : 
     333          123 :     version_info = &lierre_version_db[data->version];
     334          123 :     short_block_ecc = &version_info->ecc[data->ecc_level];
     335          123 :     long_block_count =
     336          123 :         (version_info->data_bytes - short_block_ecc->bs * short_block_ecc->ns) / (short_block_ecc->bs + 1);
     337          123 :     total_blocks = long_block_count + short_block_ecc->ns;
     338          123 :     ecc_offset = short_block_ecc->dw * total_blocks + long_block_count;
     339          123 :     dst_offset = 0;
     340              : 
     341          123 :     lmemcpy(&long_block_ecc, short_block_ecc, sizeof(long_block_ecc));
     342          123 :     long_block_ecc.dw++;
     343          123 :     long_block_ecc.bs++;
     344              : 
     345         1669 :     for (block_idx = 0; block_idx < total_blocks; block_idx++) {
     346         1565 :         dst = ds->data + dst_offset;
     347         1565 :         current_ecc = (block_idx < short_block_ecc->ns) ? short_block_ecc : &long_block_ecc;
     348         1565 :         parity_count = current_ecc->bs - current_ecc->dw;
     349              : 
     350        72522 :         for (byte_idx = 0; byte_idx < current_ecc->dw; byte_idx++) {
     351        70957 :             dst[byte_idx] = ds->raw[byte_idx * total_blocks + block_idx];
     352              :         }
     353              : 
     354        43850 :         for (byte_idx = 0; byte_idx < parity_count; byte_idx++) {
     355        42285 :             dst[current_ecc->dw + byte_idx] = ds->raw[ecc_offset + byte_idx * total_blocks + block_idx];
     356              :         }
     357              : 
     358         1565 :         err = correct_block_with_poporon(dst, current_ecc);
     359         1565 :         if (err) {
     360           19 :             return err;
     361              :         }
     362              : 
     363         1546 :         dst_offset += current_ecc->dw;
     364              :     }
     365              : 
     366          104 :     ds->data_bits = dst_offset * 8;
     367              : 
     368          104 :     return LIERRE_ERROR_SUCCESS;
     369              : }
     370              : 
     371          345 : static inline int32_t bits_remaining(const datastream_t *ds)
     372              : {
     373          345 :     return ds->data_bits - ds->ptr;
     374              : }
     375              : 
     376        65676 : static inline int32_t take_bits(datastream_t *ds, int32_t count)
     377              : {
     378              :     int32_t result, bit_position;
     379              :     uint8_t byte_value;
     380              : 
     381        65676 :     result = 0;
     382              : 
     383       590856 :     while (count && (ds->ptr < ds->data_bits)) {
     384       525180 :         byte_value = ds->data[ds->ptr >> 3];
     385       525180 :         bit_position = ds->ptr & 7;
     386              : 
     387       525180 :         result <<= 1;
     388       525180 :         if ((byte_value << bit_position) & 0x80) {
     389       261536 :             result |= 1;
     390              :         }
     391              : 
     392       525180 :         ds->ptr++;
     393       525180 :         count--;
     394              :     }
     395              : 
     396        65676 :     return result;
     397              : }
     398              : 
     399           21 : static inline int32_t decode_numeric_tuple(qr_data_t *data, datastream_t *ds, int32_t bits, int32_t digits)
     400              : {
     401              :     int32_t value, i;
     402              : 
     403           21 :     if (bits_remaining(ds) < bits) {
     404            0 :         return -1;
     405              :     }
     406              : 
     407           21 :     value = take_bits(ds, bits);
     408              : 
     409           81 :     for (i = digits - 1; i >= 0; i--) {
     410           60 :         data->payload[data->payload_len + i] = (uint8_t)(value % 10 + '0');
     411           60 :         value /= 10;
     412              :     }
     413              : 
     414           21 :     data->payload_len += digits;
     415              : 
     416           21 :     return 0;
     417              : }
     418              : 
     419            2 : static inline lierre_error_t decode_numeric(qr_data_t *data, datastream_t *ds)
     420              : {
     421              :     int32_t count_bits, char_count;
     422              : 
     423            2 :     count_bits = NUMERIC_BITS_LARGE;
     424              : 
     425            2 :     if (data->version < VERSION_THRESHOLD_SMALL) {
     426            2 :         count_bits = NUMERIC_BITS_SMALL;
     427            0 :     } else if (data->version < VERSION_THRESHOLD_MEDIUM) {
     428            0 :         count_bits = NUMERIC_BITS_MEDIUM;
     429              :     }
     430              : 
     431            2 :     char_count = take_bits(ds, count_bits);
     432            2 :     if (data->payload_len + char_count + 1 > LIERRE_DECODER_MAX_PAYLOAD) {
     433            0 :         return LIERRE_ERROR_DATA_OVERFLOW;
     434              :     }
     435              : 
     436           21 :     while (char_count >= 3) {
     437           19 :         if (decode_numeric_tuple(data, ds, 10, 3) < 0) {
     438            0 :             return LIERRE_ERROR_DATA_UNDERFLOW;
     439              :         }
     440              : 
     441           19 :         char_count -= 3;
     442              :     }
     443              : 
     444            2 :     if (char_count >= 2) {
     445            1 :         if (decode_numeric_tuple(data, ds, 7, 2) < 0) {
     446            0 :             return LIERRE_ERROR_DATA_UNDERFLOW;
     447              :         }
     448              : 
     449            1 :         char_count -= 2;
     450              :     }
     451              : 
     452            2 :     if (char_count) {
     453            1 :         if (decode_numeric_tuple(data, ds, 4, 1) < 0) {
     454            0 :             return LIERRE_ERROR_DATA_UNDERFLOW;
     455              :         }
     456              :     }
     457              : 
     458            2 :     return LIERRE_ERROR_SUCCESS;
     459              : }
     460              : 
     461           14 : static inline int32_t decode_alpha_tuple(qr_data_t *data, datastream_t *ds, int32_t bits, int32_t digits)
     462              : {
     463              :     static const char *ALPHANUMERIC_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:";
     464              :     int32_t value, i;
     465              : 
     466           14 :     if (bits_remaining(ds) < bits) {
     467            0 :         return -1;
     468              :     }
     469              : 
     470           14 :     value = take_bits(ds, bits);
     471              : 
     472           40 :     for (i = 0; i < digits; i++) {
     473           26 :         data->payload[data->payload_len + digits - i - 1] =
     474           26 :             (uint8_t)ALPHANUMERIC_CHARSET[value % ALPHANUMERIC_CHARSET_SIZE];
     475           26 :         value /= ALPHANUMERIC_CHARSET_SIZE;
     476              :     }
     477              : 
     478           14 :     data->payload_len += digits;
     479              : 
     480           14 :     return 0;
     481              : }
     482              : 
     483            2 : static inline lierre_error_t decode_alpha(qr_data_t *data, datastream_t *ds)
     484              : {
     485              :     int32_t count_bits, char_count;
     486              : 
     487            2 :     count_bits = ALPHA_BITS_LARGE;
     488              : 
     489            2 :     if (data->version < VERSION_THRESHOLD_SMALL) {
     490            2 :         count_bits = ALPHA_BITS_SMALL;
     491            0 :     } else if (data->version < VERSION_THRESHOLD_MEDIUM) {
     492            0 :         count_bits = ALPHA_BITS_MEDIUM;
     493              :     }
     494              : 
     495            2 :     char_count = take_bits(ds, count_bits);
     496            2 :     if (data->payload_len + char_count + 1 > LIERRE_DECODER_MAX_PAYLOAD) {
     497            0 :         return LIERRE_ERROR_DATA_OVERFLOW;
     498              :     }
     499              : 
     500           14 :     while (char_count >= 2) {
     501           12 :         if (decode_alpha_tuple(data, ds, 11, 2) < 0) {
     502            0 :             return LIERRE_ERROR_DATA_UNDERFLOW;
     503              :         }
     504              : 
     505           12 :         char_count -= 2;
     506              :     }
     507              : 
     508            2 :     if (char_count) {
     509            2 :         if (decode_alpha_tuple(data, ds, 6, 1) < 0) {
     510            0 :             return LIERRE_ERROR_DATA_UNDERFLOW;
     511              :         }
     512              :     }
     513              : 
     514            2 :     return LIERRE_ERROR_SUCCESS;
     515              : }
     516              : 
     517           98 : static inline lierre_error_t decode_byte(qr_data_t *data, datastream_t *ds)
     518              : {
     519              :     int32_t count_bits, char_count, i;
     520              : 
     521           98 :     count_bits = BYTE_BITS_LARGE;
     522              : 
     523           98 :     if (data->version < VERSION_THRESHOLD_SMALL) {
     524           34 :         count_bits = BYTE_BITS_SMALL;
     525              :     }
     526              : 
     527           98 :     char_count = take_bits(ds, count_bits);
     528           98 :     if (data->payload_len + char_count + 1 > LIERRE_DECODER_MAX_PAYLOAD) {
     529            0 :         return LIERRE_ERROR_DATA_OVERFLOW;
     530              :     }
     531              : 
     532           98 :     if (bits_remaining(ds) < char_count * 8) {
     533            0 :         return LIERRE_ERROR_DATA_UNDERFLOW;
     534              :     }
     535              : 
     536        65420 :     for (i = 0; i < char_count; i++) {
     537        65322 :         data->payload[data->payload_len++] = (uint8_t)take_bits(ds, 8);
     538              :     }
     539              : 
     540           98 :     return LIERRE_ERROR_SUCCESS;
     541              : }
     542              : 
     543            2 : static inline lierre_error_t decode_kanji(qr_data_t *data, datastream_t *ds)
     544              : {
     545              :     uint16_t sjis_char;
     546              :     int32_t count_bits, char_count, i, encoded_value, high_byte, low_byte, intermediate;
     547              : 
     548            2 :     count_bits = KANJI_BITS_LARGE;
     549              : 
     550            2 :     if (data->version < VERSION_THRESHOLD_SMALL) {
     551            2 :         count_bits = KANJI_BITS_SMALL;
     552            0 :     } else if (data->version < VERSION_THRESHOLD_MEDIUM) {
     553            0 :         count_bits = KANJI_BITS_MEDIUM;
     554              :     }
     555              : 
     556            2 :     char_count = take_bits(ds, count_bits);
     557            2 :     if (data->payload_len + char_count * 2 + 1 > LIERRE_DECODER_MAX_PAYLOAD) {
     558            0 :         return LIERRE_ERROR_DATA_OVERFLOW;
     559              :     }
     560              : 
     561            2 :     if (bits_remaining(ds) < char_count * KANJI_ENCODED_BITS) {
     562            0 :         return LIERRE_ERROR_DATA_UNDERFLOW;
     563              :     }
     564              : 
     565            7 :     for (i = 0; i < char_count; i++) {
     566            5 :         encoded_value = take_bits(ds, KANJI_ENCODED_BITS);
     567            5 :         high_byte = encoded_value / KANJI_ENCODE_DIVISOR;
     568            5 :         low_byte = encoded_value % KANJI_ENCODE_DIVISOR;
     569            5 :         intermediate = (high_byte << 8) | low_byte;
     570              : 
     571            5 :         if (intermediate + KANJI_SJIS_BASE1 <= KANJI_SJIS_BOUNDARY) {
     572            5 :             sjis_char = (uint16_t)(intermediate + KANJI_SJIS_BASE1);
     573              :         } else {
     574            0 :             sjis_char = (uint16_t)(intermediate + KANJI_SJIS_BASE2);
     575              :         }
     576              : 
     577            5 :         data->payload[data->payload_len++] = (uint8_t)(sjis_char >> 8);
     578            5 :         data->payload[data->payload_len++] = (uint8_t)(sjis_char & 0xff);
     579              :     }
     580              : 
     581            2 :     return LIERRE_ERROR_SUCCESS;
     582              : }
     583              : 
     584            1 : static inline lierre_error_t decode_eci(qr_data_t *data, datastream_t *ds)
     585              : {
     586            1 :     if (bits_remaining(ds) < 8) {
     587            0 :         return LIERRE_ERROR_DATA_UNDERFLOW;
     588              :     }
     589              : 
     590            1 :     data->eci = (uint32_t)take_bits(ds, 8);
     591              : 
     592            1 :     if ((data->eci & 0xc0) == 0x80) {
     593            0 :         if (bits_remaining(ds) < 8) {
     594            0 :             return LIERRE_ERROR_DATA_UNDERFLOW;
     595              :         }
     596              : 
     597            0 :         data->eci = (data->eci << 8) | (uint32_t)take_bits(ds, 8);
     598            1 :     } else if ((data->eci & 0xe0) == 0xc0) {
     599            0 :         if (bits_remaining(ds) < 16) {
     600            0 :             return LIERRE_ERROR_DATA_UNDERFLOW;
     601              :         }
     602              : 
     603            0 :         data->eci = (data->eci << 16) | (uint32_t)take_bits(ds, 16);
     604              :     }
     605              : 
     606            1 :     return LIERRE_ERROR_SUCCESS;
     607              : }
     608              : 
     609          104 : static inline lierre_error_t decode_payload(qr_data_t *data, datastream_t *ds)
     610              : {
     611              :     lierre_error_t err;
     612              :     int32_t mode_indicator;
     613              : 
     614          209 :     while (bits_remaining(ds) >= 4) {
     615          209 :         err = LIERRE_ERROR_SUCCESS;
     616          209 :         mode_indicator = take_bits(ds, 4);
     617              : 
     618          209 :         switch (mode_indicator) {
     619            2 :         case MODE_NUMERIC:
     620            2 :             err = decode_numeric(data, ds);
     621            2 :             break;
     622            2 :         case MODE_ALPHANUMERIC:
     623            2 :             err = decode_alpha(data, ds);
     624            2 :             break;
     625           98 :         case MODE_BYTE:
     626           98 :             err = decode_byte(data, ds);
     627           98 :             break;
     628            2 :         case MODE_KANJI:
     629            2 :             err = decode_kanji(data, ds);
     630            2 :             break;
     631            1 :         case MODE_ECI:
     632            1 :             err = decode_eci(data, ds);
     633            1 :             break;
     634          104 :         default:
     635          104 :             goto done;
     636              :         }
     637              : 
     638          105 :         if (err) {
     639            0 :             return err;
     640              :         }
     641              : 
     642          105 :         if (!(mode_indicator & (mode_indicator - 1)) && (mode_indicator > data->data_type)) {
     643          104 :             data->data_type = mode_indicator;
     644              :         }
     645              :     }
     646              : 
     647            0 : done:
     648          104 :     if (data->payload_len >= LIERRE_DECODER_MAX_PAYLOAD) {
     649            0 :         data->payload_len = LIERRE_DECODER_MAX_PAYLOAD - 1;
     650              :     }
     651              : 
     652          104 :     data->payload[data->payload_len] = 0;
     653              : 
     654          104 :     return LIERRE_ERROR_SUCCESS;
     655              : }
     656              : 
     657          129 : lierre_error_t decode_qr(const qr_code_t *code, qr_data_t *data)
     658              : {
     659              :     lierre_error_t err;
     660          129 :     datastream_t ds = {0};
     661              : 
     662          129 :     if (code->size > LIERRE_DECODER_MAX_GRID_SIZE) {
     663            0 :         return LIERRE_ERROR_INVALID_GRID_SIZE;
     664              :     }
     665              : 
     666          129 :     if ((code->size - QR_VERSION1_SIZE) % 4) {
     667            0 :         return LIERRE_ERROR_INVALID_GRID_SIZE;
     668              :     }
     669              : 
     670          129 :     lmemset(data, 0, sizeof(*data));
     671              : 
     672          129 :     data->version = (code->size - QR_VERSION1_SIZE) / 4;
     673              : 
     674          129 :     if (data->version < 1 || data->version > LIERRE_DECODER_MAX_VERSION) {
     675            0 :         return LIERRE_ERROR_INVALID_VERSION;
     676              :     }
     677              : 
     678          129 :     err = read_format(code, data, 0);
     679          129 :     if (err) {
     680            9 :         err = read_format(code, data, 1);
     681              :     }
     682          129 :     if (err) {
     683            6 :         return err;
     684              :     }
     685              : 
     686          123 :     ds.raw = data->payload;
     687              : 
     688          123 :     read_data(code, data, &ds);
     689          123 :     err = codestream_ecc(data, &ds);
     690          123 :     if (err) {
     691           19 :         return err;
     692              :     }
     693              : 
     694          104 :     ds.raw = NULL;
     695              : 
     696          104 :     err = decode_payload(data, &ds);
     697          104 :     if (err) {
     698            0 :         return err;
     699              :     }
     700              : 
     701          104 :     return LIERRE_ERROR_SUCCESS;
     702              : }
        

Generated by: LCOV version 2.0-1