Skip to content

Commit 42c7948

Browse files
committed
decode: support multiple data segments.
Previously, the payload was assumed to consist of one large data segment. Now, multiple segments of different types may be concatenated together. The data type reported is the highest data type encountered while decoding.
1 parent bc253ec commit 42c7948

File tree

2 files changed

+94
-69
lines changed

2 files changed

+94
-69
lines changed

lib/decode.c

Lines changed: 90 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,7 @@ static quirc_decode_error_t correct_format(uint16_t *f_ret)
394394
struct datastream {
395395
uint8_t raw[QUIRC_MAX_PAYLOAD];
396396
int data_bits;
397+
int ptr;
397398

398399
uint8_t data[QUIRC_MAX_PAYLOAD];
399400
};
@@ -609,36 +610,41 @@ static quirc_decode_error_t codestream_ecc(struct quirc_data *data,
609610
return QUIRC_SUCCESS;
610611
}
611612

612-
static int get_bits(const uint8_t *data, int pos, int len)
613+
static inline int bits_remaining(const struct datastream *ds)
614+
{
615+
return ds->data_bits - ds->ptr;
616+
}
617+
618+
static int take_bits(struct datastream *ds, int len)
613619
{
614620
int ret = 0;
615621

616-
while (len--) {
617-
uint8_t b = data[pos >> 3];
618-
int bitpos = pos & 7;
622+
while (len && (ds->ptr < ds->data_bits)) {
623+
uint8_t b = ds->data[ds->ptr >> 3];
624+
int bitpos = ds->ptr & 7;
619625

620626
ret <<= 1;
621627
if ((b << bitpos) & 0x80)
622628
ret |= 1;
623629

624-
pos++;
630+
ds->ptr++;
631+
len--;
625632
}
626633

627634
return ret;
628635
}
629636

630637
static int numeric_tuple(struct quirc_data *data,
631-
const struct datastream *ds,
632-
int *ptr, int bits, int digits)
638+
struct datastream *ds,
639+
int bits, int digits)
633640
{
634641
int tuple;
635642
int i;
636643

637-
if (*ptr + bits > ds->data_bits)
644+
if (bits_remaining(ds) < bits)
638645
return -1;
639646

640-
tuple = get_bits(ds->data, *ptr, bits);
641-
*ptr += bits;
647+
tuple = take_bits(ds, bits);
642648

643649
for (i = digits - 1; i >= 0; i--) {
644650
data->payload[data->payload_len + i] = tuple % 10 + '0';
@@ -654,48 +660,48 @@ static quirc_decode_error_t decode_numeric(struct quirc_data *data,
654660
{
655661
int bits = 14;
656662
int count;
657-
int ptr;
658663

659664
if (data->version < 10)
660665
bits = 10;
661666
else if (data->version < 27)
662667
bits = 12;
663668

664-
count = get_bits(ds->data, 4, bits);
665-
if (count + 1 > QUIRC_MAX_PAYLOAD)
669+
count = take_bits(ds, bits);
670+
if (data->payload_len + count + 1 > QUIRC_MAX_PAYLOAD)
666671
return QUIRC_ERROR_DATA_OVERFLOW;
667672

668-
data->payload_len = 0;
669-
ptr = bits + 4;
670-
671-
while (data->payload_len + 2 < count)
672-
if (numeric_tuple(data, ds, &ptr, 10, 3) < 0)
673+
while (count >= 3) {
674+
if (numeric_tuple(data, ds, 10, 3) < 0)
673675
return QUIRC_ERROR_DATA_UNDERFLOW;
676+
count -= 3;
677+
}
674678

675-
if ((data->payload_len + 1 < count) &&
676-
(numeric_tuple(data, ds, &ptr, 7, 2) < 0))
677-
return QUIRC_ERROR_DATA_UNDERFLOW;
679+
if (count >= 2) {
680+
if (numeric_tuple(data, ds, 7, 2) < 0)
681+
return QUIRC_ERROR_DATA_UNDERFLOW;
682+
count -= 2;
683+
}
678684

679-
if ((data->payload_len < count) &&
680-
(numeric_tuple(data, ds, &ptr, 4, 1) < 0))
681-
return QUIRC_ERROR_DATA_UNDERFLOW;
685+
if (count) {
686+
if (numeric_tuple(data, ds, 4, 1) < 0)
687+
return QUIRC_ERROR_DATA_UNDERFLOW;
688+
count--;
689+
}
682690

683-
data->payload[count] = 0;
684691
return QUIRC_SUCCESS;
685692
}
686693

687694
static int alpha_tuple(struct quirc_data *data,
688-
const struct datastream *ds,
689-
int *ptr, int bits, int digits)
695+
struct datastream *ds,
696+
int bits, int digits)
690697
{
691698
int tuple;
692699
int i;
693700

694-
if (*ptr + bits > ds->data_bits)
701+
if (bits_remaining(ds) < bits)
695702
return -1;
696703

697-
tuple = get_bits(ds->data, *ptr, bits);
698-
*ptr += bits;
704+
tuple = take_bits(ds, bits);
699705

700706
for (i = 0; i < digits; i++) {
701707
static const char *alpha_map =
@@ -715,29 +721,28 @@ static quirc_decode_error_t decode_alpha(struct quirc_data *data,
715721
{
716722
int bits = 13;
717723
int count;
718-
int ptr;
719724

720725
if (data->version < 7)
721726
bits = 9;
722727
else if (data->version < 11)
723728
bits = 10;
724729

725-
count = get_bits(ds->data, 4, bits);
726-
if (count + 1 > QUIRC_MAX_PAYLOAD)
730+
count = take_bits(ds, bits);
731+
if (data->payload_len + count + 1 > QUIRC_MAX_PAYLOAD)
727732
return QUIRC_ERROR_DATA_OVERFLOW;
728733

729-
data->payload_len = 0;
730-
ptr = bits + 4;
731-
732-
while (data->payload_len + 1 < count)
733-
if (alpha_tuple(data, ds, &ptr, 11, 2) < 0)
734+
while (count >= 2) {
735+
if (alpha_tuple(data, ds, 11, 2) < 0)
734736
return QUIRC_ERROR_DATA_UNDERFLOW;
737+
count -= 2;
738+
}
735739

736-
if ((data->payload_len < count) &&
737-
(alpha_tuple(data, ds, &ptr, 6, 1) < 0))
738-
return QUIRC_ERROR_DATA_UNDERFLOW;
740+
if (count) {
741+
if (alpha_tuple(data, ds, 6, 1) < 0)
742+
return QUIRC_ERROR_DATA_UNDERFLOW;
743+
count--;
744+
}
739745

740-
data->payload[count] = 0;
741746
return QUIRC_SUCCESS;
742747
}
743748

@@ -751,17 +756,14 @@ static quirc_decode_error_t decode_byte(struct quirc_data *data,
751756
if (data->version < 10)
752757
bits = 8;
753758

754-
count = get_bits(ds->data, 4, bits);
755-
if (count + 1 > QUIRC_MAX_PAYLOAD)
759+
count = take_bits(ds, bits);
760+
if (data->payload_len + count + 1 > QUIRC_MAX_PAYLOAD)
756761
return QUIRC_ERROR_DATA_OVERFLOW;
757-
if (count * 8 + bits + 4 > ds->data_bits)
762+
if (bits_remaining(ds) < count * 8)
758763
return QUIRC_ERROR_DATA_UNDERFLOW;
759764

760765
for (i = 0; i < count; i++)
761-
data->payload[i] = get_bits(ds->data, i * 8 + bits + 4, 8);
762-
763-
data->payload[count] = 0;
764-
data->payload_len = count;
766+
data->payload[data->payload_len++] = take_bits(ds, 8);
765767

766768
return QUIRC_SUCCESS;
767769
}
@@ -778,51 +780,70 @@ static quirc_decode_error_t decode_kanji(struct quirc_data *data,
778780
else if (data->version < 27)
779781
bits = 10;
780782

781-
count = get_bits(ds->data, 4, bits);
782-
if (count * 2 + 1 > QUIRC_MAX_PAYLOAD)
783+
count = take_bits(ds, bits);
784+
if (data->payload_len + count * 2 + 1 > QUIRC_MAX_PAYLOAD)
783785
return QUIRC_ERROR_DATA_OVERFLOW;
784-
if (count * 13 + bits + 4 > ds->data_bits)
786+
if (bits_remaining(ds) < count * 13)
785787
return QUIRC_ERROR_DATA_UNDERFLOW;
786788

787789
for (i = 0; i < count; i++) {
788-
int d = get_bits(ds->data, i * 13 + bits + 4, 13);
790+
int d = take_bits(ds, 13);
789791
uint16_t sjw;
790792

791793
if (d + 0x8140 >= 0x9ffc)
792794
sjw = d + 0x8140;
793795
else
794796
sjw = d + 0xc140;
795797

796-
data->payload[i * 2] = sjw >> 8;
797-
data->payload[i * 2 + 1] = sjw & 0xff;
798+
data->payload[data->payload_len++] = sjw >> 8;
799+
data->payload[data->payload_len++] = sjw & 0xff;
798800
}
799801

800-
data->payload[count * 2] = 0;
801-
data->payload_len = count * 2;
802-
803802
return QUIRC_SUCCESS;
804803
}
805804

806805
static quirc_decode_error_t decode_payload(struct quirc_data *data,
807806
struct datastream *ds)
808807
{
809-
data->data_type = get_bits(ds->data, 0, 4);
808+
while (bits_remaining(ds) >= 4) {
809+
quirc_decode_error_t err = QUIRC_SUCCESS;
810+
int type = take_bits(ds, 4);
811+
812+
switch (type) {
813+
case QUIRC_DATA_TYPE_NUMERIC:
814+
err = decode_numeric(data, ds);
815+
break;
810816

811-
switch (data->data_type) {
812-
case QUIRC_DATA_TYPE_NUMERIC:
813-
return decode_numeric(data, ds);
817+
case QUIRC_DATA_TYPE_ALPHA:
818+
err = decode_alpha(data, ds);
819+
break;
814820

815-
case QUIRC_DATA_TYPE_ALPHA:
816-
return decode_alpha(data, ds);
821+
case QUIRC_DATA_TYPE_BYTE:
822+
err = decode_byte(data, ds);
823+
break;
817824

818-
case QUIRC_DATA_TYPE_BYTE:
819-
return decode_byte(data, ds);
825+
case QUIRC_DATA_TYPE_KANJI:
826+
err = decode_kanji(data, ds);
827+
break;
820828

821-
case QUIRC_DATA_TYPE_KANJI:
822-
return decode_kanji(data, ds);
829+
default:
830+
goto done;
831+
}
832+
833+
if (err)
834+
return err;
835+
836+
if (type > data->data_type)
837+
data->data_type = type;
823838
}
839+
done:
840+
841+
/* Add nul terminator to all payloads */
842+
if (data->payload_len >= sizeof(data->payload))
843+
data->payload_len--;
844+
data->payload[data->payload_len] = 0;
824845

825-
return QUIRC_ERROR_UNKNOWN_DATA_TYPE;
846+
return QUIRC_SUCCESS;
826847
}
827848

828849
quirc_decode_error_t quirc_decode(const struct quirc_code *code,

lib/quirc.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ struct quirc_data {
116116
int version;
117117
int ecc_level;
118118
int mask;
119+
120+
/* This field is the highest-valued data type found in the QR
121+
* code.
122+
*/
119123
int data_type;
120124

121125
/* Data payload. For the Kanji datatype, payload is encoded as

0 commit comments

Comments
 (0)