aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/BH/String.h251
-rw-r--r--src/String/Int.c24
-rw-r--r--test/src/TestInt.c201
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();
+}