intc: Add number -> u128/256 constructor
This commit is contained in:
parent
beb24f96d5
commit
614c47bebc
96
intc.h
96
intc.h
@ -191,7 +191,7 @@ struct intc_u128_divmod_result
|
||||
struct intc_u128_string
|
||||
{
|
||||
// NOTE: Max value 340,282,366,920,938,463,463,374,607,431,768,211,455
|
||||
char data[256 + 1];
|
||||
char data[63 + 1];
|
||||
int size;
|
||||
};
|
||||
|
||||
@ -220,11 +220,16 @@ struct intc_u128_string
|
||||
INTC_BEGIN_EXTERN_C
|
||||
// NOTE: U128 Converters
|
||||
// -----------------------------------------------------------------------------
|
||||
// Reminder: If INTC_API_PREFIX is not defined, example API looks like: intc_u128_init_cstring(...)
|
||||
// Reminder: If INTC_API_PREFIX is not defined, example API looks like: intc_u128_init_hex_cstring(...)
|
||||
// Construct a 128 unsigned integer from a string. This function supports
|
||||
// hexadecimal strings with and without the 0x prefix i.e. "0xafc8a" or "afc8a"
|
||||
// or "0xAFC8A" or "xafc8a" .
|
||||
INTC_API bool INTC_API_PREFIX(128_init_cstring)(const char *string, int size, struct intc_u128 *dest);
|
||||
INTC_API bool INTC_API_PREFIX(128_init_hex_cstring)(const char *string, int size, struct intc_u128 *dest);
|
||||
|
||||
// Construct a 128 unsigned integer from a base 10 number string. The separator
|
||||
// character given will be permitted and skipped in the string if encountered,
|
||||
// e.g. ','. If no separator is permitted, pass 0 as the separator.
|
||||
INTC_API bool INTC_API_PREFIX(128_init_cstring)(char const *string, int size, struct intc_u128 *dest, char separator);
|
||||
|
||||
// Interpret the 128 bit integer as a lower bit-type by using the lo bits of the
|
||||
// integer and truncating where necessary.
|
||||
@ -435,17 +440,22 @@ struct intc_u256_string
|
||||
INTC_BEGIN_EXTERN_C
|
||||
// NOTE: U256 Converters
|
||||
// -----------------------------------------------------------------------------
|
||||
// Reminder: If INTC_API_PREFIX is not defined, example API looks like: intc_u256_init_cstring(...)
|
||||
// Reminder: If INTC_API_PREFIX is not defined, example API looks like: intc_u256_init_hex_cstring(...)
|
||||
// Construct a 128 unsigned integer from a string. This function supports
|
||||
// hexadecimal strings with and without the 0x prefix i.e. "0xafc8a" or "afc8a"
|
||||
// or "0xAFC8A" or "xafc8a".
|
||||
INTC_API bool INTC_API_PREFIX(256_init_cstring)(char const *string, int size, struct intc_u256 *dest);
|
||||
INTC_API bool INTC_API_PREFIX(256_init_hex_cstring)(char const *string, int size, struct intc_u256 *dest);
|
||||
|
||||
// TODO(dqn): We should support all the bases that the printing functions work
|
||||
// with so you can always do a round-trip store and load from disk.
|
||||
// Similar to above except the base of the number can be specified, base must be
|
||||
// between (2 < base < 17).
|
||||
INTC_API bool INTC_API_PREFIX(256_init_cstring_base)(char const *string, int size, int base, struct intc_u256 *dest);
|
||||
INTC_API bool INTC_API_PREFIX(256_init_hex_cstring_base)(char const *string, int size, int base, struct intc_u256 *dest);
|
||||
|
||||
// Construct a 256 unsigned integer from a base 10 number string. The separator
|
||||
// character given will be permitted and skipped in the string if encountered,
|
||||
// e.g. ','. If no separator is permitted, pass 0 as the separator.
|
||||
INTC_API bool INTC_API_PREFIX(256_init_cstring)(char const *string, int size, struct intc_u256 *dest, char separator);
|
||||
|
||||
// Interpret the 256 bit integer as a lower bit-type by using the lo bits of the
|
||||
// integer and truncating where necessary.
|
||||
@ -613,7 +623,7 @@ INTC_BEGIN_EXTERN_C
|
||||
// -----------------------------------------------------------------------------
|
||||
// NOTE: U128 Converters
|
||||
// -----------------------------------------------------------------------------
|
||||
INTC_API bool INTC_API_PREFIX(128_init_cstring)(char const *string, int size, struct intc_u128 *dest)
|
||||
INTC_API bool INTC_API_PREFIX(128_init_hex_cstring)(char const *string, int size, struct intc_u128 *dest)
|
||||
{
|
||||
if (string == 0 || size == 0 || !dest)
|
||||
return false;
|
||||
@ -651,6 +661,41 @@ INTC_API bool INTC_API_PREFIX(128_init_cstring)(char const *string, int size, st
|
||||
return true;
|
||||
}
|
||||
|
||||
INTC_API bool INTC_API_PREFIX(128_init_cstring)(char const *string, int size, struct intc_u128 *dest, char separator)
|
||||
{
|
||||
if (string == 0 || size == 0 || !dest)
|
||||
return false;
|
||||
|
||||
if (size < 0) {
|
||||
for (size = 0; string[size]; size++)
|
||||
;
|
||||
}
|
||||
|
||||
int const MAX_SIZE = sizeof("340282366920938463463374607431768211456") - 1; // 2^128
|
||||
*dest = INTC_U128_ZERO;
|
||||
for (int index = 0, digits_written = 0;
|
||||
index < size;
|
||||
index++)
|
||||
{
|
||||
if (digits_written >= MAX_SIZE)
|
||||
return true;
|
||||
|
||||
char digit = string[index];
|
||||
if (separator != 0 && digit == separator)
|
||||
continue;
|
||||
|
||||
intc_u64 value = (digit >= '0' && digit <= '9') ? (digit - '0') : 0xFF;
|
||||
if (value == 0xFF)
|
||||
return false;
|
||||
|
||||
*dest = intc_u128_mul_u64(*dest, 10);
|
||||
*dest = intc_u128_add_u64(*dest, value);
|
||||
digits_written++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
INTC_API bool INTC_API_PREFIX(128_as_bool)(struct intc_u128 in)
|
||||
{
|
||||
bool result = in.lo | in.hi;
|
||||
@ -1015,7 +1060,7 @@ INTC_API struct intc_u128_string INTC_API_PREFIX(128_str)(struct intc_u128 in, u
|
||||
div_result = INTC_API_PREFIX(128_divmod)(div_result.quot, INTC_U64_TO_U128(base));
|
||||
val.data[val.size++] = "0123456789abcdefghijklmnopqrstuvwxyz"[div_result.rem.lo];
|
||||
|
||||
if (separate_every_n_chars > 0 && INTC_API_PREFIX(128_as_bool)(div_result.quot)) {
|
||||
if (separate_ch && separate_every_n_chars > 0 && INTC_API_PREFIX(128_as_bool)(div_result.quot)) {
|
||||
insert_count++;
|
||||
if (insert_count % separate_every_n_chars == 0)
|
||||
val.data[val.size++] = separate_ch;
|
||||
@ -1266,7 +1311,7 @@ INTC_BEGIN_EXTERN_C
|
||||
// -----------------------------------------------------------------------------
|
||||
// NOTE: U256 Converters
|
||||
// -----------------------------------------------------------------------------
|
||||
INTC_API bool INTC_API_PREFIX(256_init_cstring)(char const *string, int size, struct intc_u256 *dest)
|
||||
INTC_API bool INTC_API_PREFIX(256_init_hex_cstring)(char const *string, int size, struct intc_u256 *dest)
|
||||
{
|
||||
if (string == 0 || size == 0 || !dest)
|
||||
return false;
|
||||
@ -1288,13 +1333,13 @@ INTC_API bool INTC_API_PREFIX(256_init_cstring)(char const *string, int size, st
|
||||
buffer[pad_length + string_index] = string[string_index];
|
||||
|
||||
int half_buffer_size = sizeof(buffer) / 2;
|
||||
bool result = INTC_API_PREFIX(128_init_cstring)(buffer, half_buffer_size, &dest->hi);
|
||||
result |= INTC_API_PREFIX(128_init_cstring)(buffer + half_buffer_size, half_buffer_size, &dest->lo);
|
||||
bool result = INTC_API_PREFIX(128_init_hex_cstring)(buffer, half_buffer_size, &dest->hi);
|
||||
result |= INTC_API_PREFIX(128_init_hex_cstring)(buffer + half_buffer_size, half_buffer_size, &dest->lo);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
INTC_API bool INTC_API_PREFIX(256_init_cstring_base)(char const *string, int size, int base, struct intc_u256 *dest)
|
||||
INTC_API bool INTC_API_PREFIX(256_init_hex_cstring_base)(char const *string, int size, int base, struct intc_u256 *dest)
|
||||
{
|
||||
if (string == 0 || size == 0 || !dest || base <= 0)
|
||||
return false;
|
||||
@ -1329,6 +1374,31 @@ INTC_API bool INTC_API_PREFIX(256_init_cstring_base)(char const *string, int siz
|
||||
return true;
|
||||
}
|
||||
|
||||
INTC_API bool INTC_API_PREFIX(256_init_cstring)(char const *string, int size, struct intc_u256 *dest, char separator)
|
||||
{
|
||||
if (string == 0 || size == 0 || !dest)
|
||||
return false;
|
||||
|
||||
if (size < 0) {
|
||||
for (size = 0; string[size]; size++)
|
||||
;
|
||||
}
|
||||
|
||||
char buffer[64];
|
||||
int pad_length = (int)sizeof(buffer) - size;
|
||||
for (int pad_index = 0; pad_index < pad_length; pad_index++)
|
||||
buffer[pad_index] = '0';
|
||||
|
||||
for (int string_index = 0; string_index < size; string_index++)
|
||||
buffer[pad_length + string_index] = string[string_index];
|
||||
|
||||
int half_buffer_size = sizeof(buffer) / 2;
|
||||
bool result = INTC_API_PREFIX(128_init_cstring)(buffer, half_buffer_size, &dest->hi, separator);
|
||||
result |= INTC_API_PREFIX(128_init_cstring)(buffer + half_buffer_size, half_buffer_size, &dest->lo, separator);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
INTC_API bool INTC_API_PREFIX(256_as_bool)(struct intc_u256 in)
|
||||
{
|
||||
bool result = (bool)((unsigned)INTC_API_PREFIX(128_as_bool)(in.lo) |
|
||||
@ -1743,7 +1813,7 @@ INTC_API struct intc_u256_string INTC_API_PREFIX(256_str)(struct intc_u256 in, u
|
||||
div_result = INTC_API_PREFIX(256_divmod)(div_result.quot, INTC_U64_TO_U256(base));
|
||||
val.data[val.size++] = "0123456789abcdefghijklmnopqrstuvwxyz"[INTC_API_PREFIX(128_as_u32)(div_result.rem.lo)];
|
||||
|
||||
if (separate_every_n_chars > 0 && INTC_API_PREFIX(256_as_bool)(div_result.quot)) {
|
||||
if (separate_ch && separate_every_n_chars > 0 && INTC_API_PREFIX(256_as_bool)(div_result.quot)) {
|
||||
insert_count++;
|
||||
if (insert_count % separate_every_n_chars == 0)
|
||||
val.data[val.size++] = separate_ch;
|
||||
|
29
intc_tests.c
29
intc_tests.c
@ -1199,30 +1199,37 @@ struct intc_test_state intc_u256_unit_tests(void)
|
||||
}
|
||||
|
||||
{
|
||||
INTC_TESTS_BEGIN("Constructor.string");
|
||||
INTC_TESTS_BEGIN("Constructor.dataing");
|
||||
struct intc_u256 val;
|
||||
INTC_TESTS_ASSERT(intc_u256_init_cstring("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", -1 /*size*/, &val));
|
||||
INTC_TESTS_ASSERT(intc_u256_init_hex_cstring("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", -1 /*size*/, &val));
|
||||
INTC_TESTS_ASSERT_MSG(intc_u256_eq(val, INTC_U256_MAX),
|
||||
"val: %s\n"
|
||||
"expect: %s\n",
|
||||
intc_u256_readable_hex_str(val).data,
|
||||
intc_u256_readable_hex_str(INTC_U256_MAX).data);
|
||||
|
||||
INTC_TESTS_ASSERT(intc_u256_init_cstring("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", -1 /*size*/, &val));
|
||||
INTC_TESTS_ASSERT(intc_u256_init_hex_cstring("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", -1 /*size*/, &val));
|
||||
INTC_TESTS_ASSERT_MSG(intc_u256_eq(val, INTC_U256_MAX),
|
||||
"val: %s\n"
|
||||
"expect: %s\n",
|
||||
intc_u256_readable_hex_str(val).data,
|
||||
intc_u256_readable_hex_str(INTC_U256_MAX).data);
|
||||
|
||||
<<<<<<< HEAD
|
||||
INTC_TESTS_ASSERT(intc_u256_init_cstring("0x0", -1 /*size*/, &val));
|
||||
INTC_TESTS_ASSERT_MSG(intc_u256_eq(val, INTC_U256_ZERO), "val: %s\n", intc_u256_readable_hex_str(val).data);
|
||||
|
||||
INTC_TESTS_ASSERT(intc_u256_init_cstring("0x0", -1 /*size*/, &val));
|
||||
=======
|
||||
INTC_TESTS_ASSERT(intc_u256_init_hex_cstring("0x0", -1 /*size*/, &val));
|
||||
INTC_TESTS_ASSERT_MSG(intc_u256_eq(val, INTC_U256_ZERO), "val: %s\n", intc_u256_readable_hex_str(val).data);
|
||||
|
||||
INTC_TESTS_ASSERT(intc_u256_init_hex_cstring("0x0", -1 /*size*/, &val));
|
||||
>>>>>>> f769dd0 (intc: Add number -> u128/256 constructor)
|
||||
INTC_TESTS_ASSERT_MSG(intc_u256_eq(val, INTC_U256_ZERO), "val: %s\n", intc_u256_readable_hex_str(val).data);
|
||||
|
||||
struct intc_u256 expect = INTC_U64_TO_U256(0x0123456789abcdefULL);
|
||||
INTC_TESTS_ASSERT(intc_u256_init_cstring("0x0123456789abcdef", -1 /*size*/, &val));
|
||||
INTC_TESTS_ASSERT(intc_u256_init_hex_cstring("0x0123456789abcdef", -1 /*size*/, &val));
|
||||
INTC_TESTS_ASSERT_MSG(intc_u256_eq(val, expect),
|
||||
"val: %s\n"
|
||||
"expect: %s\n",
|
||||
@ -1234,37 +1241,37 @@ struct intc_test_state intc_u256_unit_tests(void)
|
||||
{
|
||||
INTC_TESTS_BEGIN("Constructor.base_string");
|
||||
struct intc_u256 val;
|
||||
INTC_TESTS_ASSERT(intc_u256_init_cstring_base("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", -1 /*size*/, 16 /*base*/, &val));
|
||||
INTC_TESTS_ASSERT(intc_u256_init_hex_cstring_base("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", -1 /*size*/, 16 /*base*/, &val));
|
||||
INTC_TESTS_ASSERT_MSG(intc_u256_eq(val, INTC_U256_MAX),
|
||||
"val: %s\n"
|
||||
"expect: %s\n",
|
||||
intc_u256_readable_hex_str(val).data,
|
||||
intc_u256_readable_hex_str(INTC_U256_MAX).data);
|
||||
|
||||
INTC_TESTS_ASSERT(intc_u256_init_cstring_base("115792089237316195423570985008687907853269984665640564039457584007913129639935", -1 /*size*/, 10 /*base*/, &val));
|
||||
INTC_TESTS_ASSERT(intc_u256_init_hex_cstring_base("115792089237316195423570985008687907853269984665640564039457584007913129639935", -1 /*size*/, 10 /*base*/, &val));
|
||||
INTC_TESTS_ASSERT_MSG(intc_u256_eq(val, INTC_U256_MAX),
|
||||
"val: %s\n"
|
||||
"expect: %s\n",
|
||||
intc_u256_readable_hex_str(val).data,
|
||||
intc_u256_readable_hex_str(INTC_U256_MAX).data);
|
||||
|
||||
INTC_TESTS_ASSERT(intc_u256_init_cstring_base("1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", -1 /*size*/, 2 /*base*/, &val));
|
||||
INTC_TESTS_ASSERT(intc_u256_init_hex_cstring_base("1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", -1 /*size*/, 2 /*base*/, &val));
|
||||
INTC_TESTS_ASSERT_MSG(intc_u256_eq(val, INTC_U256_MAX),
|
||||
"val: %s\n"
|
||||
"expect: %s\n",
|
||||
intc_u256_readable_hex_str(val).data,
|
||||
intc_u256_readable_hex_str(INTC_U256_MAX).data);
|
||||
|
||||
INTC_TESTS_ASSERT(intc_u256_init_cstring_base("0", -1 /*size*/, 10 /*base*/, &val));
|
||||
INTC_TESTS_ASSERT(intc_u256_init_hex_cstring_base("0", -1 /*size*/, 10 /*base*/, &val));
|
||||
INTC_TESTS_ASSERT(intc_u256_eq(val, INTC_U256_ZERO));
|
||||
|
||||
INTC_TESTS_ASSERT(intc_u256_init_cstring_base("0x0123456789abcdef", -1 /*size*/, 16 /*base*/, &val));
|
||||
INTC_TESTS_ASSERT(intc_u256_init_hex_cstring_base("0x0123456789abcdef", -1 /*size*/, 16 /*base*/, &val));
|
||||
INTC_TESTS_ASSERT(intc_u256_eq(val, INTC_U64_TO_U256(0x0123456789abcdefULL)));
|
||||
|
||||
INTC_TESTS_ASSERT(intc_u256_init_cstring_base("755", -1 /*size*/, 8 /*base*/, &val));
|
||||
INTC_TESTS_ASSERT(intc_u256_init_hex_cstring_base("755", -1 /*size*/, 8 /*base*/, &val));
|
||||
INTC_TESTS_ASSERT(intc_u256_eq(val, INTC_U64_TO_U256(0x01ed)));
|
||||
|
||||
INTC_TESTS_ASSERT(intc_u256_init_cstring_base("31415926", -1 /*size*/, 10 /*base*/, &val));
|
||||
INTC_TESTS_ASSERT(intc_u256_init_hex_cstring_base("31415926", -1 /*size*/, 10 /*base*/, &val));
|
||||
INTC_TESTS_ASSERT(intc_u256_eq(val, INTC_U64_TO_U256(0x01df5e76ULL)));
|
||||
INTC_TESTS_END;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user