Skip to content

Commit 2dcf42f

Browse files
Parser: rewrite the iterate_string_chunks function with new chunk code
The new get_string_chunk function allows us to merge the chunked and non-chunked versions into one single code path. Not only will this share code with the chunk functions (if the user is using them), there is an actual reduction in code size after this change. Before, the function was 0x1d8 bytes in size on x86-64 (-march=skylake) and 0x17b bytes for x86 (-march=silvermont -miamcu). After, the combination of the the new iteration function and get_string_chunk is, respectively, 0x193 and 0x157 bytes, a reduction of 69 and 36 bytes. Signed-off-by: Thiago Macieira <[email protected]>
1 parent 51b5606 commit 2dcf42f

File tree

1 file changed

+22
-54
lines changed

1 file changed

+22
-54
lines changed

src/cborparser.c

Lines changed: 22 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1104,60 +1104,34 @@ static CborError iterate_string_chunks(const CborValue *value, char *buffer, siz
11041104
{
11051105
cbor_assert(cbor_value_is_byte_string(value) || cbor_value_is_text_string(value));
11061106

1107-
size_t total;
11081107
CborError err;
1109-
const uint8_t *ptr = value->ptr;
1110-
if (cbor_value_is_length_known(value)) {
1111-
/* easy case: fixed length */
1112-
err = extract_length(value->parser, &ptr, &total);
1113-
if (err)
1114-
return err;
1115-
if (total > (size_t)(value->parser->end - ptr))
1116-
return CborErrorUnexpectedEOF;
1117-
if (total <= *buflen)
1118-
*result = !!func(buffer, ptr, total);
1119-
else
1120-
*result = false;
1121-
ptr += total;
1122-
} else {
1123-
/* chunked */
1124-
++ptr;
1125-
total = 0;
1126-
*result = true;
1127-
while (true) {
1128-
size_t chunkLen;
1129-
size_t newTotal;
1130-
1131-
if (ptr == value->parser->end)
1132-
return CborErrorUnexpectedEOF;
1133-
1134-
if (*ptr == (uint8_t)BreakByte) {
1135-
++ptr;
1136-
break;
1137-
}
1138-
1139-
/* is this the right type? */
1140-
if ((*ptr & MajorTypeMask) != value->type)
1141-
return CborErrorIllegalType;
1108+
CborValue tmp;
1109+
size_t total = 0;
1110+
const void *ptr;
11421111

1143-
err = extract_length(value->parser, &ptr, &chunkLen);
1144-
if (err)
1145-
return err;
1112+
if (!next)
1113+
next = &tmp;
1114+
*next = *value;
1115+
*result = true;
11461116

1147-
if (unlikely(add_check_overflow(total, chunkLen, &newTotal)))
1148-
return CborErrorDataTooLarge;
1117+
while (1) {
1118+
size_t newTotal;
1119+
size_t chunkLen;
1120+
err = get_string_chunk(next, &ptr, &chunkLen);
1121+
if (err)
1122+
return err;
1123+
if (!ptr)
1124+
break;
11491125

1150-
if (chunkLen > (size_t)(value->parser->end - ptr))
1151-
return CborErrorUnexpectedEOF;
1126+
if (unlikely(add_check_overflow(total, chunkLen, &newTotal)))
1127+
return CborErrorDataTooLarge;
11521128

1153-
if (*result && *buflen >= newTotal)
1154-
*result = !!func(buffer + total, ptr, chunkLen);
1155-
else
1156-
*result = false;
1129+
if (*result && *buflen >= newTotal)
1130+
*result = !!func(buffer + total, (const uint8_t *)ptr, chunkLen);
1131+
else
1132+
*result = false;
11571133

1158-
ptr += chunkLen;
1159-
total = newTotal;
1160-
}
1134+
total = newTotal;
11611135
}
11621136

11631137
/* is there enough room for the ending NUL byte? */
@@ -1166,12 +1140,6 @@ static CborError iterate_string_chunks(const CborValue *value, char *buffer, siz
11661140
*result = !!func(buffer + total, nul, 1);
11671141
}
11681142
*buflen = total;
1169-
1170-
if (next) {
1171-
*next = *value;
1172-
next->ptr = ptr;
1173-
return preparse_next_value(next);
1174-
}
11751143
return CborNoError;
11761144
}
11771145

0 commit comments

Comments
 (0)