diff options
-rw-r--r-- | src/decimal.c | 25 | ||||
-rw-r--r-- | src/decimal.h | 26 | ||||
-rw-r--r-- | src/node.c | 3 | ||||
-rw-r--r-- | tests/decimal_test.c | 55 | ||||
-rw-r--r-- | wscript | 4 |
5 files changed, 112 insertions, 1 deletions
diff --git a/src/decimal.c b/src/decimal.c new file mode 100644 index 00000000..7f78c8a7 --- /dev/null +++ b/src/decimal.c @@ -0,0 +1,25 @@ +/* + Copyright 2019 David Robillard <http://drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#include "decimal.h" + +#include "int_math.h" + +int +serd_count_digits(const uint64_t i) +{ + return i == 0 ? 1 : (int)serd_ilog10(i) + 1; +} diff --git a/src/decimal.h b/src/decimal.h new file mode 100644 index 00000000..11e6a9bf --- /dev/null +++ b/src/decimal.h @@ -0,0 +1,26 @@ +/* + Copyright 2019 David Robillard <http://drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#ifndef SERD_DECIMAL_H +#define SERD_DECIMAL_H + +#include <stdint.h> + +/// Return the number of decimal digits required to represent `n` +int +serd_count_digits(uint64_t i); + +#endif // SERD_DECIMAL_H @@ -16,6 +16,7 @@ #include "node.h" +#include "decimal.h" #include "namespaces.h" #include "static_nodes.h" #include "string_utils.h" @@ -640,7 +641,7 @@ serd_new_integer(int64_t i, const SerdNode* datatype) { const SerdNode* type = datatype ? datatype : &serd_xsd_integer.node; uint64_t abs_i = (uint64_t)((i < 0) ? -i : i); - const unsigned digits = serd_digits((double)abs_i); + const unsigned digits = (unsigned)serd_count_digits(abs_i); const size_t type_len = serd_node_total_size(type); const size_t total_len = digits + 2 + type_len; diff --git a/tests/decimal_test.c b/tests/decimal_test.c new file mode 100644 index 00000000..b0361e2c --- /dev/null +++ b/tests/decimal_test.c @@ -0,0 +1,55 @@ +/* + Copyright 2011-2019 David Robillard <http://drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#undef NDEBUG + +#include "../src/decimal.h" + +#include <assert.h> + +static void +test_count_digits(void) +{ + assert(1 == serd_count_digits(0)); + assert(1 == serd_count_digits(1)); + assert(1 == serd_count_digits(9)); + assert(2 == serd_count_digits(10)); + assert(2 == serd_count_digits(99ull)); + assert(3 == serd_count_digits(999ull)); + assert(4 == serd_count_digits(9999ull)); + assert(5 == serd_count_digits(99999ull)); + assert(6 == serd_count_digits(999999ull)); + assert(7 == serd_count_digits(9999999ull)); + assert(8 == serd_count_digits(99999999ull)); + assert(9 == serd_count_digits(999999999ull)); + assert(10 == serd_count_digits(9999999999ull)); + assert(11 == serd_count_digits(99999999999ull)); + assert(12 == serd_count_digits(999999999999ull)); + assert(13 == serd_count_digits(9999999999999ull)); + assert(14 == serd_count_digits(99999999999999ull)); + assert(15 == serd_count_digits(999999999999999ull)); + assert(16 == serd_count_digits(9999999999999999ull)); + assert(17 == serd_count_digits(99999999999999999ull)); + assert(18 == serd_count_digits(999999999999999999ull)); + assert(19 == serd_count_digits(9999999999999999999ull)); + assert(20 == serd_count_digits(18446744073709551615ull)); +} + +int +main(void) +{ + test_count_digits(); +} @@ -73,6 +73,7 @@ def configure(conf): 'msvc': [ '/wd4061', # enumerator in switch is not explicitly handled '/wd4200', # nonstandard: zero-sized array in struct/union + '/wd4464', # relative include path contains '..' '/wd4514', # unreferenced inline function has been removed '/wd4710', # function not inlined '/wd4711', # function selected for automatic inline expansion @@ -168,6 +169,7 @@ lib_source = ['src/base64.c', 'src/byte_sink.c', 'src/byte_source.c', 'src/cursor.c', + 'src/decimal.c', 'src/env.c', 'src/inserter.c', 'src/int_math.c', @@ -255,6 +257,7 @@ def build(bld): for prog in [('serdi_static', 'src/serdi.c'), ('base64_test', 'tests/base64_test.c'), ('cursor_test', 'tests/cursor_test.c'), + ('decimal_test', 'tests/decimal_test.c'), ('env_test', 'tests/env_test.c'), ('free_null_test', 'tests/free_null_test.c'), ('int_math_test', 'tests/int_math_test.c'), @@ -686,6 +689,7 @@ def test(tst): with tst.group('Unit') as check: check(['./base64_test']) check(['./cursor_test']) + check(['./decimal_test']) check(['./env_test']) check(['./free_null_test']) check(['./int_math_test']) |