Skip to content

Commit 864d1a6

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 09622c4 commit 864d1a6

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
@@ -1107,60 +1107,34 @@ static CborError iterate_string_chunks(const CborValue *value, char *buffer, siz
11071107
{
11081108
cbor_assert(cbor_value_is_byte_string(value) || cbor_value_is_text_string(value));
11091109

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

1146-
err = extract_length(value->parser, &ptr, &chunkLen);
1147-
if (err)
1148-
return err;
1115+
if (!next)
1116+
next = &tmp;
1117+
*next = *value;
1118+
*result = true;
11491119

1150-
if (unlikely(add_check_overflow(total, chunkLen, &newTotal)))
1151-
return CborErrorDataTooLarge;
1120+
while (1) {
1121+
size_t newTotal;
1122+
size_t chunkLen;
1123+
err = get_string_chunk(next, &ptr, &chunkLen);
1124+
if (err)
1125+
return err;
1126+
if (!ptr)
1127+
break;
11521128

1153-
if (chunkLen > (size_t)(value->parser->end - ptr))
1154-
return CborErrorUnexpectedEOF;
1129+
if (unlikely(add_check_overflow(total, chunkLen, &newTotal)))
1130+
return CborErrorDataTooLarge;
11551131

1156-
if (*result && *buflen >= newTotal)
1157-
*result = !!func(buffer + total, ptr, chunkLen);
1158-
else
1159-
*result = false;
1132+
if (*result && *buflen >= newTotal)
1133+
*result = !!func(buffer + total, (const uint8_t *)ptr, chunkLen);
1134+
else
1135+
*result = false;
11601136

1161-
ptr += chunkLen;
1162-
total = newTotal;
1163-
}
1137+
total = newTotal;
11641138
}
11651139

11661140
/* is there enough room for the ending NUL byte? */
@@ -1169,12 +1143,6 @@ static CborError iterate_string_chunks(const CborValue *value, char *buffer, siz
11691143
*result = !!func(buffer + total, nul, 1);
11701144
}
11711145
*buflen = total;
1172-
1173-
if (next) {
1174-
*next = *value;
1175-
next->ptr = ptr;
1176-
return preparse_next_value(next);
1177-
}
11781146
return CborNoError;
11791147
}
11801148

0 commit comments

Comments
 (0)