From 86894351ffb6cc7f9fd9a4d63ba0a6eecc64d29d Mon Sep 17 00:00:00 2001 From: David Robillard Date: Mon, 8 May 2023 21:29:52 -0400 Subject: Avoid use of strtoul() This function is overkill for the simple cases actually needed here, and pretty slow anyway. --- src/n3.c | 14 +++++++------- src/string_utils.h | 6 ++++++ src/uri.c | 5 +++-- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/n3.c b/src/n3.c index d332504d..d5866393 100644 --- a/src/n3.c +++ b/src/n3.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #if defined(__clang__) && __clang_major__ >= 10 @@ -71,17 +70,18 @@ read_UCHAR(SerdReader* const reader, const Ref dest, uint32_t* const char_code) skip_byte(reader, b); - uint8_t buf[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; - for (unsigned i = 0; i < length; ++i) { + // Read character code point in hex + uint8_t buf[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; + uint32_t code = 0U; + for (unsigned i = 0U; i < length; ++i) { if (!(buf[i] = read_HEX(reader))) { return SERD_ERR_BAD_SYNTAX; } - } - char* endptr = NULL; - const uint32_t code = (uint32_t)strtoul((const char*)buf, &endptr, 16); - assert(endptr == (char*)buf + length); + code = (code << (i ? 4U : 0U)) | hex_digit_value(buf[i]); + } + // Determine the encoded size from the code point unsigned size = 0; if (code < 0x00000080) { size = 1; diff --git a/src/string_utils.h b/src/string_utils.h index 9ae0abcb..7770e1eb 100644 --- a/src/string_utils.h +++ b/src/string_utils.h @@ -89,6 +89,12 @@ serd_substrlen(const uint8_t* str, size_t* n_bytes, SerdNodeFlags* flags); +static inline uint8_t +hex_digit_value(const uint8_t c) +{ + return (uint8_t)((c > '9') ? ((c & ~0x20) - 'A' + 10) : (c - '0')); +} + static inline char serd_to_upper(const char c) { diff --git a/src/uri.c b/src/uri.c index d78b8e8c..b45f7e16 100644 --- a/src/uri.c +++ b/src/uri.c @@ -72,8 +72,9 @@ serd_file_uri_parse(const uint8_t* const uri, uint8_t** const hostname) serd_chunk_sink("%", 1, &chunk); ++s; } else if (is_hexdig(*(s + 1)) && is_hexdig(*(s + 2))) { - const uint8_t code[3] = {*(s + 1), *(s + 2), 0}; - const uint8_t c = (uint8_t)strtoul((const char*)code, NULL, 16); + const uint8_t hi = hex_digit_value(s[1]); + const uint8_t lo = hex_digit_value(s[2]); + const char c = (char)((hi << 4U) | lo); serd_chunk_sink(&c, 1, &chunk); s += 2; } else { -- cgit v1.2.1