diff --git a/src/gmio_core/internal/string_utils.h b/src/gmio_core/internal/string_utils.h index 980f447..5ef25c2 100644 --- a/src/gmio_core/internal/string_utils.h +++ b/src/gmio_core/internal/string_utils.h @@ -18,6 +18,8 @@ #include "../global.h" +#include + #ifdef GMIO_STRINGUTILS_CTYPE_H # include #endif @@ -25,13 +27,14 @@ /*! Returns non-zero if \p c is a space (for C-locale), zero otherwise */ GMIO_INLINE int gmio_clocale_isspace(char c) { -#if defined(GMIO_STRINGUTILS_DIRECT_TESTS) /* 0x20 : space (SPC) * 0x09 : horizontal tab (TAB) * 0x0a : newline (LF) * 0x0b : vertical tab (VT) * 0x0c : feed (FF) * 0x0d : carriage return (CR) */ +#if defined(GMIO_STRINGUTILS_DIRECT_TESTS) + /* TODO: eliminate branch */ return c == 0x20 || ((uint8_t)(c - 0x09) < 5); #elif defined(GMIO_STRINGUTILS_C_ARRAYS) static const unsigned char space_chars[] = { @@ -58,11 +61,35 @@ GMIO_INLINE int gmio_clocale_isspace(char c) #endif } +GMIO_INLINE int gmio_clocale_isdigit(char c) +{ + static const unsigned char digit_chars[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + return digit_chars[c]; +} + /*! Returns non-zero if \p c is an uppercase letter (for C-locale), zero * otherwise */ GMIO_INLINE int gmio_clocale_isupper(char c) { #if defined(GMIO_STRINGUTILS_DIRECT_TESTS) + /* TODO: eliminate branch */ return 65 <= c && c <= 90; #elif defined(GMIO_STRINGUTILS_C_ARRAYS) static const unsigned char upper_chars[] = { @@ -94,6 +121,7 @@ GMIO_INLINE int gmio_clocale_isupper(char c) GMIO_INLINE int gmio_clocale_islower(char c) { #if defined(GMIO_STRINGUTILS_DIRECT_TESTS) + /* TODO: eliminate branch */ return 97 <= c && c <= 122; #elif defined(GMIO_STRINGUTILS_C_ARRAYS) static const unsigned char lower_chars[] = { @@ -123,13 +151,33 @@ GMIO_INLINE int gmio_clocale_islower(char c) /*! Returns the lowercase letter converted to uppercase */ GMIO_INLINE char gmio_clocale_toupper(char c) { - return gmio_clocale_islower(c) ? c - 32 : c; + static const uint8_t table_toupper[128] = { + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,0x09,0x0A, 0 , 0 ,0x0D, 0 , 0 , + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , + ' ', '!', '"', '#', '$', '%', '&','\'', '(', ')', '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', + '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[','\\', ']', '^', '_', + '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '|', '}', '~', 0, + }; + return table_toupper[c]; } /*! Returns the uppercase letter converted to lowercase */ GMIO_INLINE char gmio_clocale_tolower(char c) { - return gmio_clocale_isupper(c) ? c + 32 : c; + static const uint8_t table_tolower[128] = { + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,0x09,0x0A, 0 , 0 ,0x0D, 0 , 0 , + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , + ' ', '!', '"', '#', '$', '%', '&','\'', '(', ')', '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', + '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '[','\\', ']', '^', '_', + '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', 0, + }; + return table_tolower[c]; } /*! Returns true if \p c1 compare equals to \p c2 @@ -138,6 +186,7 @@ GMIO_INLINE char gmio_clocale_tolower(char c) */ GMIO_INLINE gmio_bool_t gmio_clocale_char_iequals(char c1, char c2) { + /* TODO: eliminate branch */ return c1 == c2 || (gmio_clocale_toupper(c1) == gmio_clocale_toupper(c2)); } @@ -148,7 +197,7 @@ GMIO_INLINE gmio_bool_t gmio_clocale_char_iequals(char c1, char c2) GMIO_INLINE int gmio_stricmp(const char* str1, const char* str2) { while (*str1 != 0 && *str2 != 0) { - if (gmio_clocale_char_iequals(*str1, *str2) == GMIO_FALSE) + if (!gmio_clocale_char_iequals(*str1, *str2)) return 1; ++str1; ++str2;