Sat, 02 Nov 2024 13:38:51 +0100
move szmul to common.h
relates to #470
CHANGELOG | file | annotate | diff | comparison | revisions | |
msvc/ucxtest/ucxtest.vcxproj | file | annotate | diff | comparison | revisions | |
msvc/ucxtest/ucxtest.vcxproj.filters | file | annotate | diff | comparison | revisions | |
src/Makefile | file | annotate | diff | comparison | revisions | |
src/allocator.c | file | annotate | diff | comparison | revisions | |
src/buffer.c | file | annotate | diff | comparison | revisions | |
src/cx/common.h | file | annotate | diff | comparison | revisions | |
src/cx/utils.h | file | annotate | diff | comparison | revisions | |
src/mempool.c | file | annotate | diff | comparison | revisions | |
tests/Makefile | file | annotate | diff | comparison | revisions | |
tests/test_szmul.c | file | annotate | diff | comparison | revisions | |
tests/test_utils.c | file | annotate | diff | comparison | revisions | |
tests/ucxtest.c | file | annotate | diff | comparison | revisions |
--- a/CHANGELOG Fri Nov 01 18:33:16 2024 +0100 +++ b/CHANGELOG Sat Nov 02 13:38:51 2024 +0100 @@ -12,6 +12,7 @@ * adds runtime constants to read out the actual SBO sizes * adds improved version of UCX 2 Test framework (now a self-contained header) * adds cx_nmemb() utility function to common.h + * move cx_szmul() to common.h * the cx_compare_func symbol is now declared by compare.h * fixes wrong link from UCX 2 documentation to UCX 3 documentation * fixes critical bug that produced wrong results when comparing lists of different type but same size
--- a/msvc/ucxtest/ucxtest.vcxproj Fri Nov 01 18:33:16 2024 +0100 +++ b/msvc/ucxtest/ucxtest.vcxproj Sat Nov 02 13:38:51 2024 +0100 @@ -31,6 +31,7 @@ <ClCompile Include="..\..\tests\test_printf.c" /> <ClCompile Include="..\..\tests\test_properties.c" /> <ClCompile Include="..\..\tests\test_string.c" /> + <ClCompile Include="..\..\tests\test_szmul.c" /> <ClCompile Include="..\..\tests\test_tree.c" /> <ClCompile Include="..\..\tests\test_utils.c" /> <ClCompile Include="..\..\tests\ucxtest.c" />
--- a/msvc/ucxtest/ucxtest.vcxproj.filters Fri Nov 01 18:33:16 2024 +0100 +++ b/msvc/ucxtest/ucxtest.vcxproj.filters Sat Nov 02 13:38:51 2024 +0100 @@ -47,6 +47,9 @@ <ClCompile Include="..\..\tests\test_string.c"> <Filter>Source</Filter> </ClCompile> + <ClCompile Include="..\..\tests\test_szmul.c"> + <Filter>Source</Filter> + </ClCompile> <ClCompile Include="..\..\tests\test_tree.c"> <Filter>Source</Filter> </ClCompile>
--- a/src/Makefile Fri Nov 01 18:33:16 2024 +0100 +++ b/src/Makefile Sat Nov 02 13:38:51 2024 +0100 @@ -66,8 +66,7 @@ FORCE: -$(build_dir)/allocator$(OBJ_EXT): allocator.c cx/allocator.h cx/common.h \ - cx/utils.h +$(build_dir)/allocator$(OBJ_EXT): allocator.c cx/allocator.h cx/common.h @echo "Compiling $<" $(CC) -o $@ $(CFLAGS) -c $< @@ -78,7 +77,7 @@ $(CC) -o $@ $(CFLAGS) -c $< $(build_dir)/buffer$(OBJ_EXT): buffer.c cx/buffer.h cx/common.h \ - cx/allocator.h cx/utils.h + cx/allocator.h @echo "Compiling $<" $(CC) -o $@ $(CFLAGS) -c $< @@ -123,7 +122,7 @@ $(CC) -o $@ $(CFLAGS) -c $< $(build_dir)/mempool$(OBJ_EXT): mempool.c cx/mempool.h cx/common.h \ - cx/allocator.h cx/utils.h + cx/allocator.h @echo "Compiling $<" $(CC) -o $@ $(CFLAGS) -c $<
--- a/src/allocator.c Fri Nov 01 18:33:16 2024 +0100 +++ b/src/allocator.c Sat Nov 02 13:38:51 2024 +0100 @@ -27,7 +27,6 @@ */ #include "cx/allocator.h" -#include "cx/utils.h" #include <errno.h>
--- a/src/buffer.c Fri Nov 01 18:33:16 2024 +0100 +++ b/src/buffer.c Sat Nov 02 13:38:51 2024 +0100 @@ -27,7 +27,6 @@ */ #include "cx/buffer.h" -#include "cx/utils.h" #include <stdio.h> #include <string.h>
--- a/src/cx/common.h Fri Nov 01 18:33:16 2024 +0100 +++ b/src/cx/common.h Sat Nov 02 13:38:51 2024 +0100 @@ -126,6 +126,54 @@ */ #define cx_nmemb(arr) (sizeof(arr)/sizeof((arr)[0])) +// cx_szmul() definition +#if (__GNUC__ >= 5 || defined(__clang__)) && !defined(CX_NO_SZMUL_BUILTIN) +#define CX_SZMUL_BUILTIN + +/** + * Alias for \c __builtin_mul_overflow. + * + * Performs a multiplication of size_t values and checks for overflow. + * + * @param a first operand + * @param b second operand + * @param result a pointer to a size_t, where the result should + * be stored + * @return zero, if no overflow occurred and the result is correct, non-zero + * otherwise + */ +#define cx_szmul(a, b, result) __builtin_mul_overflow(a, b, result) + +#else // no GNUC or clang bultin + +/** + * Performs a multiplication of size_t values and checks for overflow. + * + * @param a first operand + * @param b second operand + * @param result a pointer to a size_t, where the result should + * be stored + * @return zero, if no overflow occurred and the result is correct, non-zero + * otherwise + */ +#define cx_szmul(a, b, result) cx_szmul_impl(a, b, result) + +/** + * Performs a multiplication of size_t values and checks for overflow. + * + * This is a custom implementation in case there is no compiler builtin + * available. + * + * @param a first operand + * @param b second operand + * @param result a pointer to a size_t where the result should be stored + * @return zero, if no overflow occurred and the result is correct, non-zero + * otherwise + */ +int cx_szmul_impl(size_t a, size_t b, size_t *result); + +#endif // cx_szmul + // Compiler specific stuff #ifndef __GNUC__
--- a/src/cx/utils.h Fri Nov 01 18:33:16 2024 +0100 +++ b/src/cx/utils.h Sat Nov 02 13:38:51 2024 +0100 @@ -45,56 +45,6 @@ extern "C" { #endif -// cx_szmul() definition - -#if (__GNUC__ >= 5 || defined(__clang__)) && !defined(CX_NO_SZMUL_BUILTIN) -#define CX_SZMUL_BUILTIN - -/** - * Alias for \c __builtin_mul_overflow. - * - * Performs a multiplication of size_t values and checks for overflow. - * - * @param a first operand - * @param b second operand - * @param result a pointer to a size_t, where the result should - * be stored - * @return zero, if no overflow occurred and the result is correct, non-zero - * otherwise - */ -#define cx_szmul(a, b, result) __builtin_mul_overflow(a, b, result) - -#else // no GNUC or clang bultin - -/** - * Performs a multiplication of size_t values and checks for overflow. - * - * @param a first operand - * @param b second operand - * @param result a pointer to a size_t, where the result should - * be stored - * @return zero, if no overflow occurred and the result is correct, non-zero - * otherwise - */ -#define cx_szmul(a, b, result) cx_szmul_impl(a, b, result) - -/** - * Performs a multiplication of size_t values and checks for overflow. - * - * This is a custom implementation in case there is no compiler builtin - * available. - * - * @param a first operand - * @param b second operand - * @param result a pointer to a size_t where the result should be stored - * @return zero, if no overflow occurred and the result is correct, non-zero - * otherwise - */ -int cx_szmul_impl(size_t a, size_t b, size_t *result); - -#endif // cx_szmul - - /** * Reads data from a stream and writes it to another stream. *
--- a/src/mempool.c Fri Nov 01 18:33:16 2024 +0100 +++ b/src/mempool.c Sat Nov 02 13:38:51 2024 +0100 @@ -27,7 +27,7 @@ */ #include "cx/mempool.h" -#include "cx/utils.h" + #include <string.h> struct cx_mempool_memory_s {
--- a/tests/Makefile Fri Nov 01 18:33:16 2024 +0100 +++ b/tests/Makefile Sat Nov 02 13:38:51 2024 +0100 @@ -27,10 +27,16 @@ TEST_DIR=$(build_dir)/tests -SRC = util_allocator.c test_utils.c test_hash_key.c test_allocator.c \ - test_compare.c test_string.c test_buffer.c test_iterator.c \ - test_list.c test_tree.c test_hash_map.c test_properties.c \ - test_printf.c test_mempool.c test_json.c ucxtest.c +SRC = util_allocator.c \ + test_szmul.c test_allocator.c test_utils.c \ + test_compare.c \ + test_string.c test_buffer.c \ + test_hash_key.c test_hash_map.c \ + test_iterator.c test_list.c test_tree.c \ + test_properties.c test_json.c \ + test_printf.c \ + test_mempool.c \ + ucxtest.c OBJ_EXT=.o OBJ=$(SRC:%.c=$(TEST_DIR)/%$(OBJ_EXT)) @@ -126,6 +132,11 @@ @echo "Compiling $<" $(CC) -o $@ $(CFLAGS) -c $< +$(TEST_DIR)/test_szmul$(OBJ_EXT): test_szmul.c ../src/cx/test.h \ + ../src/cx/common.h ../src/szmul.c + @echo "Compiling $<" + $(CC) -o $@ $(CFLAGS) -c $< + $(TEST_DIR)/test_tree$(OBJ_EXT): test_tree.c ../src/cx/tree.h \ ../src/cx/common.h ../src/cx/collection.h ../src/cx/allocator.h \ ../src/cx/iterator.h ../src/cx/compare.h ../src/cx/test.h \ @@ -135,7 +146,7 @@ $(TEST_DIR)/test_utils$(OBJ_EXT): test_utils.c ../src/cx/test.h \ ../src/cx/common.h ../src/cx/utils.h ../src/cx/buffer.h \ - ../src/cx/allocator.h ../src/szmul.c + ../src/cx/allocator.h @echo "Compiling $<" $(CC) -o $@ $(CFLAGS) -c $<
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test_szmul.c Sat Nov 02 13:38:51 2024 +0100 @@ -0,0 +1,162 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2023 Mike Becker, Olaf Wintermann All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "cx/test.h" + +CX_TEST(test_szmul) { + size_t r; + int e; + + CX_TEST_DO { + e = cx_szmul(5, 7, &r); + CX_TEST_ASSERT(e == 0); + CX_TEST_ASSERT(r == 35); + + size_t s = SIZE_MAX & ~3; + + e = cx_szmul(s / 4, 2, &r); + CX_TEST_ASSERT(e == 0); + CX_TEST_ASSERT(r == s / 2); + + e = cx_szmul(2, s / 4, &r); + CX_TEST_ASSERT(e == 0); + CX_TEST_ASSERT(r == s / 2); + + e = cx_szmul(s / 4, 4, &r); + CX_TEST_ASSERT(e == 0); + CX_TEST_ASSERT(r == s); + + e = cx_szmul(4, s / 4, &r); + CX_TEST_ASSERT(e == 0); + CX_TEST_ASSERT(r == s); + + e = cx_szmul(s / 4, 5, &r); + CX_TEST_ASSERT(e != 0); + + e = cx_szmul(5, s / 4, &r); + CX_TEST_ASSERT(e != 0); + + e = cx_szmul(SIZE_MAX - 4, 0, &r); + CX_TEST_ASSERT(e == 0); + CX_TEST_ASSERT(r == 0); + + e = cx_szmul(0, SIZE_MAX - 1, &r); + CX_TEST_ASSERT(e == 0); + CX_TEST_ASSERT(r == 0); + + e = cx_szmul(SIZE_MAX, 0, &r); + CX_TEST_ASSERT(e == 0); + CX_TEST_ASSERT(r == 0); + + e = cx_szmul(0, SIZE_MAX, &r); + CX_TEST_ASSERT(e == 0); + CX_TEST_ASSERT(r == 0); + + e = cx_szmul(0, 0, &r); + CX_TEST_ASSERT(e == 0); + CX_TEST_ASSERT(r == 0); + } +} + +#ifdef CX_SZMUL_BUILTIN + +// also test the custom implementation +#undef CX_SZMUL_BUILTIN + +#include "../src/szmul.c" + +#define CX_SZMUL_BUILTIN + +CX_TEST(test_szmul_impl) { + size_t r; + int e; + + CX_TEST_DO { + e = cx_szmul_impl(5, 7, &r); + CX_TEST_ASSERT(e == 0); + CX_TEST_ASSERT(r == 35); + + size_t s = SIZE_MAX & ~3; + + e = cx_szmul_impl(s / 4, 2, &r); + CX_TEST_ASSERT(e == 0); + CX_TEST_ASSERT(r == s / 2); + + e = cx_szmul_impl(2, s / 4, &r); + CX_TEST_ASSERT(e == 0); + CX_TEST_ASSERT(r == s / 2); + + e = cx_szmul_impl(s / 4, 4, &r); + CX_TEST_ASSERT(e == 0); + CX_TEST_ASSERT(r == s); + + e = cx_szmul_impl(4, s / 4, &r); + CX_TEST_ASSERT(e == 0); + CX_TEST_ASSERT(r == s); + + e = cx_szmul_impl(s / 4, 5, &r); + CX_TEST_ASSERT(e != 0); + + e = cx_szmul_impl(5, s / 4, &r); + CX_TEST_ASSERT(e != 0); + + e = cx_szmul_impl(SIZE_MAX - 4, 0, &r); + CX_TEST_ASSERT(e == 0); + CX_TEST_ASSERT(r == 0); + + e = cx_szmul_impl(0, SIZE_MAX - 1, &r); + CX_TEST_ASSERT(e == 0); + CX_TEST_ASSERT(r == 0); + + e = cx_szmul_impl(SIZE_MAX, 0, &r); + CX_TEST_ASSERT(e == 0); + CX_TEST_ASSERT(r == 0); + + e = cx_szmul_impl(0, SIZE_MAX, &r); + CX_TEST_ASSERT(e == 0); + CX_TEST_ASSERT(r == 0); + + e = cx_szmul_impl(0, 0, &r); + CX_TEST_ASSERT(e == 0); + CX_TEST_ASSERT(r == 0); + } +} + +#endif // CX_SZMUL_BUILTIN + + +CxTestSuite *cx_test_suite_szmul(void) { + CxTestSuite *suite = cx_test_suite_new("szmul"); + + cx_test_register(suite, test_szmul); +#ifdef CX_SZMUL_BUILTIN + cx_test_register(suite, test_szmul_impl); +#endif + + return suite; +}
--- a/tests/test_utils.c Fri Nov 01 18:33:16 2024 +0100 +++ b/tests/test_utils.c Sat Nov 02 13:38:51 2024 +0100 @@ -95,137 +95,11 @@ cxBufferDestroy(&target); } -CX_TEST(test_szmul) { - size_t r; - int e; - - CX_TEST_DO { - e = cx_szmul(5, 7, &r); - CX_TEST_ASSERT(e == 0); - CX_TEST_ASSERT(r == 35); - - size_t s = SIZE_MAX & ~3; - - e = cx_szmul(s / 4, 2, &r); - CX_TEST_ASSERT(e == 0); - CX_TEST_ASSERT(r == s / 2); - - e = cx_szmul(2, s / 4, &r); - CX_TEST_ASSERT(e == 0); - CX_TEST_ASSERT(r == s / 2); - - e = cx_szmul(s / 4, 4, &r); - CX_TEST_ASSERT(e == 0); - CX_TEST_ASSERT(r == s); - - e = cx_szmul(4, s / 4, &r); - CX_TEST_ASSERT(e == 0); - CX_TEST_ASSERT(r == s); - - e = cx_szmul(s / 4, 5, &r); - CX_TEST_ASSERT(e != 0); - - e = cx_szmul(5, s / 4, &r); - CX_TEST_ASSERT(e != 0); - - e = cx_szmul(SIZE_MAX - 4, 0, &r); - CX_TEST_ASSERT(e == 0); - CX_TEST_ASSERT(r == 0); - - e = cx_szmul(0, SIZE_MAX - 1, &r); - CX_TEST_ASSERT(e == 0); - CX_TEST_ASSERT(r == 0); - - e = cx_szmul(SIZE_MAX, 0, &r); - CX_TEST_ASSERT(e == 0); - CX_TEST_ASSERT(r == 0); - - e = cx_szmul(0, SIZE_MAX, &r); - CX_TEST_ASSERT(e == 0); - CX_TEST_ASSERT(r == 0); - - e = cx_szmul(0, 0, &r); - CX_TEST_ASSERT(e == 0); - CX_TEST_ASSERT(r == 0); - } -} - -#ifdef CX_SZMUL_BUILTIN - -// also test the custom implementation -#undef CX_SZMUL_BUILTIN - -#include "../src/szmul.c" - -#define CX_SZMUL_BUILTIN - -CX_TEST(test_szmul_impl) { - size_t r; - int e; - - CX_TEST_DO { - e = cx_szmul_impl(5, 7, &r); - CX_TEST_ASSERT(e == 0); - CX_TEST_ASSERT(r == 35); - - size_t s = SIZE_MAX & ~3; - - e = cx_szmul_impl(s / 4, 2, &r); - CX_TEST_ASSERT(e == 0); - CX_TEST_ASSERT(r == s / 2); - - e = cx_szmul_impl(2, s / 4, &r); - CX_TEST_ASSERT(e == 0); - CX_TEST_ASSERT(r == s / 2); - - e = cx_szmul_impl(s / 4, 4, &r); - CX_TEST_ASSERT(e == 0); - CX_TEST_ASSERT(r == s); - - e = cx_szmul_impl(4, s / 4, &r); - CX_TEST_ASSERT(e == 0); - CX_TEST_ASSERT(r == s); - - e = cx_szmul_impl(s / 4, 5, &r); - CX_TEST_ASSERT(e != 0); - - e = cx_szmul_impl(5, s / 4, &r); - CX_TEST_ASSERT(e != 0); - - e = cx_szmul_impl(SIZE_MAX - 4, 0, &r); - CX_TEST_ASSERT(e == 0); - CX_TEST_ASSERT(r == 0); - - e = cx_szmul_impl(0, SIZE_MAX - 1, &r); - CX_TEST_ASSERT(e == 0); - CX_TEST_ASSERT(r == 0); - - e = cx_szmul_impl(SIZE_MAX, 0, &r); - CX_TEST_ASSERT(e == 0); - CX_TEST_ASSERT(r == 0); - - e = cx_szmul_impl(0, SIZE_MAX, &r); - CX_TEST_ASSERT(e == 0); - CX_TEST_ASSERT(r == 0); - - e = cx_szmul_impl(0, 0, &r); - CX_TEST_ASSERT(e == 0); - CX_TEST_ASSERT(r == 0); - } -} - -#endif // CX_SZMUL_BUILTIN - - CxTestSuite *cx_test_suite_utils(void) { CxTestSuite *suite = cx_test_suite_new("utils"); cx_test_register(suite, test_stream_bncopy); cx_test_register(suite, test_stream_ncopy); - cx_test_register(suite, test_szmul); -#ifdef CX_SZMUL_BUILTIN - cx_test_register(suite, test_szmul_impl); -#endif return suite; }
--- a/tests/ucxtest.c Fri Nov 01 18:33:16 2024 +0100 +++ b/tests/ucxtest.c Sat Nov 02 13:38:51 2024 +0100 @@ -30,25 +30,26 @@ #include "cx/test.h" CxTestSuite *cx_test_suite_testing_allocator(void); +CxTestSuite *cx_test_suite_szmul(void); +CxTestSuite *cx_test_suite_allocator(void); CxTestSuite *cx_test_suite_utils(void); CxTestSuite *cx_test_suite_compare(void); -CxTestSuite *cx_test_suite_hash_key(void); -CxTestSuite *cx_test_suite_allocator(void); CxTestSuite *cx_test_suite_string(void); CxTestSuite *cx_test_suite_buffer(void); -CxTestSuite *cx_test_suite_printf(void); +CxTestSuite *cx_test_suite_hash_key(void); +CxTestSuite *cx_test_suite_hash_map(void); CxTestSuite *cx_test_suite_iterator(void); CxTestSuite *cx_test_suite_empty_list(void); CxTestSuite *cx_test_suite_array_list(void); +CxTestSuite *cx_test_suite_array_list_defaulted_funcs(void); CxTestSuite *cx_test_suite_linked_list(void); -CxTestSuite *cx_test_suite_array_list_defaulted_funcs(void); CxTestSuite *cx_test_suite_linked_list_defaulted_funcs(void); CxTestSuite *cx_test_suite_tree_low_level(void); CxTestSuite *cx_test_suite_tree_high_level(void); -CxTestSuite *cx_test_suite_mempool(void); -CxTestSuite *cx_test_suite_hash_map(void); CxTestSuite *cx_test_suite_properties(void); CxTestSuite *cx_test_suite_json(void); +CxTestSuite *cx_test_suite_printf(void); +CxTestSuite *cx_test_suite_mempool(void); #define run_tests(suite) cx_test_run_stdout(suite); success += (suite)->success; failure += (suite)->failure #define execute_test_suites(...) unsigned success = 0, failure = 0; CxTestSuite* test_suites[] = {__VA_ARGS__}; \ @@ -60,25 +61,26 @@ execute_test_suites( cx_test_suite_testing_allocator(), + cx_test_suite_szmul(), + cx_test_suite_allocator(), cx_test_suite_utils(), cx_test_suite_compare(), - cx_test_suite_hash_key(), - cx_test_suite_allocator(), cx_test_suite_string(), cx_test_suite_buffer(), - cx_test_suite_printf(), + cx_test_suite_hash_key(), + cx_test_suite_hash_map(), cx_test_suite_iterator(), cx_test_suite_empty_list(), cx_test_suite_array_list(), + cx_test_suite_array_list_defaulted_funcs(), cx_test_suite_linked_list(), - cx_test_suite_array_list_defaulted_funcs(), cx_test_suite_linked_list_defaulted_funcs(), cx_test_suite_tree_low_level(), cx_test_suite_tree_high_level(), + cx_test_suite_properties(), cx_test_suite_mempool(), - cx_test_suite_hash_map(), - cx_test_suite_properties(), - cx_test_suite_json() + cx_test_suite_json(), + cx_test_suite_printf() ); printf("=== OVERALL RESULT ===\n"); printf(" Total: %u\n Success: %u\n Failure: %u\n",