diff options
| -rw-r--r-- | include/BH/String.h | 251 | ||||
| -rw-r--r-- | src/String/Int.c | 24 | ||||
| -rw-r--r-- | test/src/TestInt.c | 201 |
3 files changed, 462 insertions, 14 deletions
diff --git a/include/BH/String.h b/include/BH/String.h index 70cb922..0ce62c4 100644 --- a/include/BH/String.h +++ b/include/BH/String.h @@ -5,85 +5,332 @@ #include "Common.h" +/** + * Frees dynamically allocated \a string. + * + * \param string String pointer + */ void BH_StringFree(char *string); +/** + * Creates a copy of the input \a string. + * + * \param string String pointer + * + * \return On success, returns new string pointer. + * \return On failure, returns NULL pointer. + */ char *BH_StringCopy(const char *string); +/** + * Formats a double \a value into a string using the provided \a format and + * \a precision. + * + * Formats supported: + * - Scientific or fixed format ('g' or 'G') + * - Scientific format ('e' or 'E') + * - Fixed format ('f' or 'F') + * + * If precision is negative, string will contain shortest representation of the + * double that can round-trip (i.e. converted back without information loss). + * + * This function follows IEEE 754 round to even to break ties during rounding. + * + * \param value Value + * \param format Format + * \param precision Precision + * + * \return On success, returns new string pointer. + * \return On failure, returns NULL pointer. + */ char *BH_StringFromDouble(double value, char format, int precision); +/** + * Reads \a string containing double value in fixed or scientific format, + * optionally reports \a size amount of characters consumed and returns + * the result value. + * + * \param string String + * \param size Optional size + * + * \return On success, returns parsed double value. + * \return On failure, returns zero. + */ double BH_StringToDouble(const char *string, size_t *size); +/** + * Formats signed 8bit \a value into string with the specified \a base. + * + * \param value Value + * \param base Base + * + * \return On success, returns new string pointer. + * \return On failure, returns NULL pointer. + */ char *BH_StringFromInt8s(int8_t value, int base); +/** + * Formats signed 16bit \a value into string with the specified \a base. + * + * \param value Value + * \param base Base + * + * \return On success, returns new string pointer. + * \return On failure, returns NULL pointer. + */ +char *BH_StringFromInt16s(int16_t value, + int base); + + +/** + * Formats signed 32bit \a value into string with the specified \a base. + * + * \param value Value + * \param base Base + * + * \return On success, returns new string pointer. + * \return On failure, returns NULL pointer. + */ char *BH_StringFromInt32s(int32_t value, int base); +/** + * Formats signed 64bit \a value into string with the specified \a base. + * + * \param value Value + * \param base Base + * + * \return On success, returns new string pointer. + * \return On failure, returns NULL pointer. + */ char *BH_StringFromInt64s(int64_t value, int base); -char *BH_StringFromInt16s(int16_t value, - int base); +/** + * Formats unsigned 8bit \a value into string with the specified \a base. + * + * \param value Value + * \param base Base + * + * \return On success, returns new string pointer. + * \return On failure, returns NULL pointer. + */ char *BH_StringFromInt8u(uint8_t value, int base); +/** + * Formats unsigned 16bit \a value into string with the specified \a base. + * + * \param value Value + * \param base Base + * + * \return On success, returns new string pointer. + * \return On failure, returns NULL pointer. + */ char *BH_StringFromInt16u(uint16_t value, int base); +/** + * Formats unsigned 32bit \a value into string with the specified \a base. + * + * \param value Value + * \param base Base + * + * \return On success, returns new string pointer. + * \return On failure, returns NULL pointer. + */ char *BH_StringFromInt32u(uint32_t value, int base); +/** + * Formats unsigned 64bit \a value into string with the specified \a base. + * + * \param value Value + * \param base Base + * + * \return On success, returns new string pointer. + * \return On failure, returns NULL pointer. + */ char *BH_StringFromInt64u(uint64_t value, int base); +/** + * Reads \a string containing value in specified \a base, optionally reports + * \a size amount of characters consumed and returns the result value. + * + * If base is 0, function will automaticly detect input base by the prefix: + * - Base 8 if prefix is 0 + * - Base 16 if prefix is 0x + * - Base 10 in other cases + * + * \param string String + * \param size Optional size + * \param base Base + * + * \return On success, returns parsed value. + * \return On failure, returns zero. + */ int8_t BH_StringToInt8s(const char *string, size_t *size, int base); +/** + * Reads \a string containing value in specified \a base, optionally reports + * \a size amount of characters consumed and returns the result value. + * + * If base is 0, function will automaticly detect input base by the prefix: + * - Base 8 if prefix is 0 + * - Base 16 if prefix is 0x + * - Base 10 in other cases + * + * \param string String + * \param size Optional size + * \param base Base + * + * \return On success, returns parsed value. + * \return On failure, returns zero. + */ int16_t BH_StringToInt16s(const char *string, size_t *size, int base); +/** + * Reads \a string containing value in specified \a base, optionally reports + * \a size amount of characters consumed and returns the result value. + * + * If base is 0, function will automaticly detect input base by the prefix: + * - Base 8 if prefix is 0 + * - Base 16 if prefix is 0x + * - Base 10 in other cases + * + * \param string String + * \param size Optional size + * \param base Base + * + * \return On success, returns parsed value. + * \return On failure, returns zero. + */ int32_t BH_StringToInt32s(const char *string, size_t *size, int base); +/** + * Reads \a string containing value in specified \a base, optionally reports + * \a size amount of characters consumed and returns the result value. + * + * If base is 0, function will automaticly detect input base by the prefix: + * - Base 8 if prefix is 0 + * - Base 16 if prefix is 0x + * - Base 10 in other cases + * + * \param string String + * \param size Optional size + * \param base Base + * + * \return On success, returns parsed value. + * \return On failure, returns zero. + */ int64_t BH_StringToInt64s(const char *string, size_t *size, int base); +/** + * Reads \a string containing value in specified \a base, optionally reports + * \a size amount of characters consumed and returns the result value. + * + * If base is 0, function will automaticly detect input base by the prefix: + * - Base 8 if prefix is 0 + * - Base 16 if prefix is 0x + * - Base 10 in other cases + * + * \param string String + * \param size Optional size + * \param base Base + * + * \return On success, returns parsed value. + * \return On failure, returns zero. + */ uint8_t BH_StringToInt8u(const char *string, size_t *size, int base); +/** + * Reads \a string containing value in specified \a base, optionally reports + * \a size amount of characters consumed and returns the result value. + * + * If base is 0, function will automaticly detect input base by the prefix: + * - Base 8 if prefix is 0 + * - Base 16 if prefix is 0x + * - Base 10 in other cases + * + * \param string String + * \param size Optional size + * \param base Base + * + * \return On success, returns parsed value. + * \return On failure, returns zero. + */ uint16_t BH_StringToInt16u(const char *string, size_t *size, int base); +/** + * Reads \a string containing value in specified \a base, optionally reports + * \a size amount of characters consumed and returns the result value. + * + * If base is 0, function will automaticly detect input base by the prefix: + * - Base 8 if prefix is 0 + * - Base 16 if prefix is 0x + * - Base 10 in other cases + * + * \param string String + * \param size Optional size + * \param base Base + * + * \return On success, returns parsed value. + * \return On failure, returns zero. + */ uint32_t BH_StringToInt32u(const char *string, size_t *size, int base); +/** + * Reads \a string containing value in specified \a base, optionally reports + * \a size amount of characters consumed and returns the result value. + * + * If base is 0, function will automaticly detect input base by the prefix: + * - Base 8 if prefix is 0 + * - Base 16 if prefix is 0x + * - Base 10 in other cases + * + * \param string String + * \param size Optional size + * \param base Base + * + * \return On success, returns parsed value. + * \return On failure, returns zero. + */ uint64_t BH_StringToInt64u(const char *string, size_t *size, int base); diff --git a/src/String/Int.c b/src/String/Int.c index a9edf90..d4f468f 100644 --- a/src/String/Int.c +++ b/src/String/Int.c @@ -47,36 +47,36 @@ static void guessBase(const char **string, size_t *size, int *base) { - if (*base != 0) + if (*base != 0 && *base != 2 && *base != 8 && *base != 16) return; - *base = 10; if (**string != '0') + { + if (*base == 0) + *base = 10; return; + } (*string)++; if (size) (*size)++; - switch (**string) + if ((**string == 'x' || **string == 'X') && (*base == 0 || *base == 16)) { - case 'x': case 'X': *base = 16; (*string)++; if (size) (*size)++; - break; - - case 'b': case 'B': + } + else if ((**string == 'b' || **string == 'B') && (*base == 0 || *base == 2)) + { *base = 2; (*string)++; if (size) (*size)++; - break; - - default: - *base = 8; } + else if ((*base == 0 || *base == 8)) + *base = 8; } @@ -158,7 +158,7 @@ char *BH_StringFromInt64u(uint64_t value, #undef TEMPLATE_IMPL #define TEMPLATE_IMPL(type) \ - type result = 0; int sign, flag = 0; char sym; *size = 0; \ + type result = 0; int sign, flag = 0; char sym; if (size) *size = 0; \ if (base != 0 && (base < 2 || base > 36)) { return 0; } \ skipSpace(&string, size); handleSign(&string, size, &sign); \ guessBase(&string, size, &base); while(*string) { sym = *(string++); \ diff --git a/test/src/TestInt.c b/test/src/TestInt.c new file mode 100644 index 0000000..8040b2f --- /dev/null +++ b/test/src/TestInt.c @@ -0,0 +1,201 @@ +#include <BH/String.h> +#include <BH/Unit.h> + + +BH_UNIT_TEST(Int8) +{ + char *str; + size_t size; + + BH_VERIFY(str = BH_StringFromInt8s(-13, 16)); + BH_VERIFY(BH_StringToInt8s(str, &size, 16) == -13); + BH_VERIFY(size == 2); + BH_StringFree(str); + + BH_VERIFY(str = BH_StringFromInt8s(-13, 10)); + BH_VERIFY(BH_StringToInt8s(str, &size, 10) == -13); + BH_VERIFY(size == 3); + BH_StringFree(str); + + BH_VERIFY(str = BH_StringFromInt8s(-13, 8)); + BH_VERIFY(BH_StringToInt8s(str, &size, 8) == -13); + BH_VERIFY(size == 3); + BH_StringFree(str); + + BH_VERIFY(str = BH_StringFromInt8s(-13, 2)); + BH_VERIFY(BH_StringToInt8s(str, &size, 2) == -13); + BH_VERIFY(size == 5); + BH_StringFree(str); + + BH_VERIFY(str = BH_StringFromInt8u(200, 16)); + BH_VERIFY(BH_StringToInt8u(str, &size, 16) == 200); + BH_VERIFY(size == 2); + BH_StringFree(str); + + BH_VERIFY(str = BH_StringFromInt8u(200, 10)); + BH_VERIFY(BH_StringToInt8u(str, &size, 10) == 200); + BH_VERIFY(size == 3); + BH_StringFree(str); + + BH_VERIFY(str = BH_StringFromInt8u(200, 8)); + BH_VERIFY(BH_StringToInt8u(str, &size, 8) == 200); + BH_VERIFY(size == 3); + BH_StringFree(str); + + BH_VERIFY(str = BH_StringFromInt8u(200, 2)); + BH_VERIFY(BH_StringToInt8u(str, &size, 2) == 200); + BH_VERIFY(size == 8); + BH_StringFree(str); + + return 0; +} + + +BH_UNIT_TEST(Int16) +{ + char *str; + size_t size; + + BH_VERIFY(str = BH_StringFromInt16s(-1234, 16)); + BH_VERIFY(BH_StringToInt16s(str, &size, 16) == -1234); + BH_VERIFY(size == 4); + BH_StringFree(str); + + BH_VERIFY(str = BH_StringFromInt16s(-1234, 10)); + BH_VERIFY(BH_StringToInt16s(str, &size, 10) == -1234); + BH_VERIFY(size == 5); + BH_StringFree(str); + + BH_VERIFY(str = BH_StringFromInt16s(-1234, 8)); + BH_VERIFY(BH_StringToInt16s(str, &size, 8) == -1234); + BH_VERIFY(size == 5); + BH_StringFree(str); + + BH_VERIFY(str = BH_StringFromInt16s(-1234, 2)); + BH_VERIFY(BH_StringToInt16s(str, &size, 2) == -1234); + BH_VERIFY(size == 12); + BH_StringFree(str); + + BH_VERIFY(str = BH_StringFromInt16u(43210, 16)); + BH_VERIFY(BH_StringToInt16u(str, &size, 16) == 43210); + BH_VERIFY(size == 4); + BH_StringFree(str); + + BH_VERIFY(str = BH_StringFromInt16u(43210, 10)); + BH_VERIFY(BH_StringToInt16u(str, &size, 10) == 43210); + BH_VERIFY(size == 5); + BH_StringFree(str); + + BH_VERIFY(str = BH_StringFromInt16u(43210, 8)); + BH_VERIFY(BH_StringToInt16u(str, &size, 8) == 43210); + BH_VERIFY(size == 6); + BH_StringFree(str); + + BH_VERIFY(str = BH_StringFromInt16u(43210, 2)); + BH_VERIFY(BH_StringToInt16u(str, &size, 2) == 43210); + BH_VERIFY(size == 16); + BH_StringFree(str); + + return 0; +} + + +BH_UNIT_TEST(Int32) +{ + char *str; + size_t size; + + BH_VERIFY(str = BH_StringFromInt32s(-1234567890l, 16)); + BH_VERIFY(BH_StringToInt32s(str, &size, 16) == -1234567890l); + BH_VERIFY(size == 9); + BH_StringFree(str); + + BH_VERIFY(str = BH_StringFromInt32s(-1234567890l, 10)); + BH_VERIFY(BH_StringToInt32s(str, &size, 10) == -1234567890l); + BH_VERIFY(size == 11); + BH_StringFree(str); + + BH_VERIFY(str = BH_StringFromInt32s(-1234567890l, 8)); + BH_VERIFY(BH_StringToInt32s(str, &size, 8) == -1234567890l); + BH_VERIFY(size == 12); + BH_StringFree(str); + + BH_VERIFY(str = BH_StringFromInt32s(-1234567890l, 2)); + BH_VERIFY(BH_StringToInt32s(str, &size, 2) == -1234567890l); + BH_VERIFY(size == 32); + BH_StringFree(str); + + BH_VERIFY(str = BH_StringFromInt32u(3456789012ul, 16)); + BH_VERIFY(BH_StringToInt32u(str, &size, 16) == 3456789012ul); + BH_VERIFY(size == 8); + BH_StringFree(str); + + BH_VERIFY(str = BH_StringFromInt32u(3456789012ul, 10)); + BH_VERIFY(BH_StringToInt32u(str, &size, 10) == 3456789012ul); + BH_VERIFY(size == 10); + BH_StringFree(str); + + BH_VERIFY(str = BH_StringFromInt32u(3456789012ul, 8)); + BH_VERIFY(BH_StringToInt32u(str, &size, 8) == 3456789012ul); + BH_VERIFY(size == 11); + BH_StringFree(str); + + BH_VERIFY(str = BH_StringFromInt32u(3456789012ul, 2)); + BH_VERIFY(BH_StringToInt32u(str, &size, 2) == 3456789012ul); + BH_VERIFY(size == 32); + BH_StringFree(str); + + return 0; +} + + +BH_UNIT_TEST(Parsing) +{ + size_t size; + + BH_VERIFY(BH_StringToInt32s(" 0x1234", &size, 16) == 0x1234); + BH_VERIFY(size == 9); + + BH_VERIFY(BH_StringToInt32s(" 12345", &size, 10) == 12345); + BH_VERIFY(size == 8); + + BH_VERIFY(BH_StringToInt32s(" 0123", &size, 8) == 0123); + BH_VERIFY(size == 7); + + BH_VERIFY(BH_StringToInt32s(" 0b1111Hello", &size, 2) == 15); + BH_VERIFY(size == 9); + + BH_VERIFY(BH_StringToInt32s(" 0x1234", &size, 0) == 0x1234); + BH_VERIFY(size == 9); + + BH_VERIFY(BH_StringToInt32s(" 0123", &size, 0) == 0123); + BH_VERIFY(size == 7); + + BH_VERIFY(BH_StringToInt32s(" 123", &size, 0) == 123); + BH_VERIFY(size == 6); + + BH_VERIFY(BH_StringToInt32s(" 0b1111", &size, 0) == 15); + BH_VERIFY(size == 9); + + BH_VERIFY(BH_StringToInt32s(" 12345Hello", &size, 10) == 12345); + BH_VERIFY(size == 8); + + BH_VERIFY(BH_StringToInt32s(" Hello", &size, 10) == 0); + BH_VERIFY(size == 0); + + return 0; +} + + +int main(int argc, char **argv) +{ + BH_UNUSED(argc); + BH_UNUSED(argv); + + BH_UNIT_ADD(Int8); + BH_UNIT_ADD(Int16); + BH_UNIT_ADD(Int32); + BH_UNIT_ADD(Parsing); + + return BH_UnitRun(); +} |
