rsys

Basic data structures and low-level features
git clone git://git.meso-star.fr/rsys.git
Log | Files | Refs | README | LICENSE

commit 108d9664ded8fa42df1110484ba50e33936dd797
parent 0d038728bebcd732be36f0b7c973535ea2a2afa7
Author: vaplv <vaplv@free.fr>
Date:   Thu, 15 Nov 2018 15:11:28 +0100

Merge branch 'release_0.7'

Diffstat:
MREADME.md | 17++++++++++++++---
Mcmake/CMakeLists.txt | 36++++++++++++++++++++++++++++++++----
Msrc/algorithm.h | 2+-
Msrc/cstr.h | 21+++++++++++++++++++++
Msrc/hash_table.h | 3++-
Msrc/mem_allocator.c | 40+++++++++++++++++++++++++---------------
Msrc/mem_lifo_allocator.c | 25+++++++++++++++----------
Msrc/real33.h | 2+-
Msrc/rsys.h | 8++++++++
Msrc/test_algorithm.c | 70+++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Dsrc/test_big_buffer.c | 369-------------------------------------------------------------------------------
Msrc/test_cstr.c | 13+++++++++++++
Msrc/test_mutex.c | 3++-
13 files changed, 191 insertions(+), 418 deletions(-)

diff --git a/README.md b/README.md @@ -17,6 +17,18 @@ project can be now edited, built, tested and installed as any CMake project. ## Release notes +### Version 0.7 + +- Add the `res_to_cstr` function that returns a string describing the submitted + result code. +- Add the `SIMD_AVX` macro that is defined if the AVX instruction set is + available on the host machine. +- Fix the aligned allocation of the LIFO allocator: the returned address was + not necessarily aligned on the expected value. +- Fix the `search_lower_bound` algorithm. +- Fix a compilation error when RSys was linked against a version of the GNU C + Library less than 2.17. + ### Version 0.6.1 - Fix the detection of a 64-bits architecture on the CL compiler. @@ -56,7 +68,6 @@ project can be now edited, built, tested and installed as any CMake project. ## License RSys is Copyright (C) 2013-2018 Vincent Forest (vaplv@free.fr). It is a free -software released under the [OSI](https://opensource.org)-approved LGPL v3+ -license. You are welcome to redistribute it under certain conditions; refer to -the COPYING files for details. +software released under LGPL v3+ license. You are welcome to redistribute it +under certain conditions; refer to the COPYING files for details. diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -34,8 +34,8 @@ include(rcmake) # Configure and define targets ################################################################################ set(VERSION_MAJOR 0) -set(VERSION_MINOR 6) -set(VERSION_PATCH 1) +set(VERSION_MINOR 7) +set(VERSION_PATCH 0) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) set(RSYS_FILES_SRC @@ -133,7 +133,7 @@ add_library(rsys SHARED ${RSYS_FILES_SRC_THREAD} ${RSYS_FILES_INC} ${RSYS_FILES_INC_API}) -set_target_properties(rsys +set_target_properties(rsys PROPERTIES DEFINE_SYMBOL RSYS_SHARED_BUILD DEFINE_SYMBOL RSYS_SHARED_BUILD VERSION ${VERSION} @@ -145,6 +145,33 @@ if(CMAKE_COMPILER_IS_GNUCC) if(NOT MINGW) target_link_libraries(rsys dl) endif() + + # On GLIBC version before 2.17 one has to link with the "rt" library to use + # the clock_gettime function. + find_library(_GLIBC NAMES glib-2.0) + get_filename_component(_GLIB_LIBRARY_DIR ${_GLIBC} PATH) + find_path(_GLIBCONFIG_INCLUDE_DIR NAMES glibconfig.h + HINTS ${_GLIB_LIBRARY_DIR} PATH_SUFFIXES glib-2.0/include) + + if(_GLIBCONFIG_INCLUDE_DIR) + file(STRINGS "${_GLIBCONFIG_INCLUDE_DIR}/glibconfig.h" + _GLIB_MAJOR_LINE REGEX "^#define[ \t]+GLIB_MAJOR_VERSION[ \t]+[0-9]+$") + file(STRINGS "${_GLIBCONFIG_INCLUDE_DIR}/glibconfig.h" + _GLIB_MINOR_LINE REGEX "^#define[ \t]+GLIB_MINOR_VERSION[ \t]+[0-9]+$") + file(STRINGS "${_GLIBCONFIG_INCLUDE_DIR}/glibconfig.h" + _GLIB_PATCH_LINE REGEX "^#define[ \t]+GLIB_MICRO_VERSION[ \t]+[0-9]+$") + string(REGEX REPLACE "^#define[ \t]+GLIB_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" + _GLIB_MAJOR "${_GLIB_MAJOR_LINE}") + string(REGEX REPLACE "^#define[ \t]+GLIB_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" + _GLIB_MINOR "${_GLIB_MINOR_LINE}") + string(REGEX REPLACE "^#define[ \t]+GLIB_MICRO_VERSION[ \t]+([0-9]+)$" "\\1" + _GLIB_PATCH "${_GLIB_PATCH_LINE}") + set(_GLIB_VERSION "${_GLIB_MAJOR}.${_GLIB_MINOR}.${_GLIB_PATCH}") + if("${_GLIBC_VERSION}" VERSION_LESS "2.17") + target_link_libraries(rsys rt) + endif() + endif() + endif() rcmake_setup_devel(rsys RSys ${VERSION} rsys/rsys_version.h) @@ -208,7 +235,8 @@ if(NOT NO_TEST) set_target_properties(test_cstr PROPERTIES COMPILE_FLAGS "-std=c99") # Remove a false positive warning - if(CMAKE_C_COMPILER_VERSION VERSION_EQUAL 5.4) + if(CMAKE_C_COMPILER_VERSION VERSION_EQUAL 5.4 + OR CMAKE_C_COMPILER_VERSION VERSION_EQUAL 7.3) set_target_properties(test_binary_heap PROPERTIES COMPILE_FLAGS "-Wno-aggressive-loop-optimizations") endif() diff --git a/src/algorithm.h b/src/algorithm.h @@ -37,7 +37,7 @@ search_lower_bound { #define AT(Base, Id) (void*)((const char*)(Base) + (Id)*size) size_t lo = 0, hi = nmemb - 1; - while(compar(AT(base, lo), AT(base, hi)) < 0) { + while(lo < hi) { size_t mid = (lo + hi) / 2; if(compar(key, AT(base, mid)) > 0) { lo = mid + 1; diff --git a/src/cstr.h b/src/cstr.h @@ -131,6 +131,25 @@ cstr_to_uint(const char* str, unsigned* dst) return RES_OK; } +static INLINE const char* +res_to_cstr(const res_T res) +{ + const char* cstr = NULL; + switch(res) { + case RES_OK: cstr = "Success"; break; + case RES_BAD_ARG: cstr = "Invalid argument"; break; + case RES_MEM_ERR: cstr = "Could not allocate memory"; break; + case RES_IO_ERR: cstr = "Input/Ouput error"; break; + case RES_UNKNOWN_ERR: cstr = "Unknown error"; break; + case RES_BAD_OP: cstr = "Invalid operation"; break; + case RES_EOF: cstr = "Reached end of file"; break; + default: FATAL("Ureachable code.\n"); break; + } + return cstr; +} + +BEGIN_DECLS + /* Convert a string "A:B:C:D:E:F" in a list of { A, B, C, D, E, F }. ':' can be * any user defined character */ RSYS_API res_T @@ -157,5 +176,7 @@ cstr_to_list_uint size_t* length, const size_t max_length); +END_DECLS + #endif /* CSTR_H */ diff --git a/src/hash_table.h b/src/hash_table.h @@ -351,11 +351,12 @@ HTABLE_FUNC__(reserve)(struct HTABLE__* htbl, const size_t size_submitted) if(size <= HTABLE_DATA_FUNC__(size_get)(&htbl->table)) goto exit; + darray_char_init(htbl->allocator, &tbl_slot_is_used); + HTABLE_DATA_FUNC__(init)(htbl->allocator, &tbl); if(RES_OK != (res = HTABLE_DATA_FUNC__(resize)(&tbl, size))) goto error; - darray_char_init(htbl->allocator, &tbl_slot_is_used); if(RES_OK != (res = darray_char_resize(&tbl_slot_is_used, size))) goto error; memset(darray_char_data_get(&tbl_slot_is_used), 0, size*sizeof(char)); diff --git a/src/mem_allocator.c b/src/mem_allocator.c @@ -50,21 +50,25 @@ mem_alloc(const size_t size) if(size) { #if defined(OS_UNIX) || defined (OS_MACH) mem = malloc(size); + if(mem) { + ATOMIC_ADD(&g_alloc_counter.allocated_size, mem_size(mem)); + ATOMIC_INCR(&g_alloc_counter.nb_allocs); + } #elif defined(OS_WINDOWS) const size_t DEFAULT_ALIGNMENT = 16; mem = _aligned_offset_malloc (size + MEM_HEADER_SIZE, DEFAULT_ALIGNMENT, MEM_HEADER_SIZE); - ((size_t*)mem)[0] = DEFAULT_ALIGNMENT; - ((size_t*)mem)[1] = size + MEM_HEADER_SIZE; - mem = ((char*)mem) + MEM_HEADER_SIZE; + if(mem) { + ((size_t*)mem)[0] = DEFAULT_ALIGNMENT; + ((size_t*)mem)[1] = size + MEM_HEADER_SIZE; + mem = ((char*)mem) + MEM_HEADER_SIZE; + ATOMIC_ADD(&g_alloc_counter.allocated_size, mem_size(mem)); + ATOMIC_INCR(&g_alloc_counter.nb_allocs); + } #else #error "Unsupported OS" #endif } - if(mem) { - ATOMIC_ADD(&g_alloc_counter.allocated_size, mem_size(mem)); - ATOMIC_INCR(&g_alloc_counter.nb_allocs); - } return mem; } @@ -101,8 +105,10 @@ mem_realloc(void* mem, const size_t size) mem = ((char*)mem) - MEM_HEADER_SIZE; new_mem = _aligned_offset_realloc (mem, size + MEM_HEADER_SIZE, ((size_t*)mem)[0], MEM_HEADER_SIZE); - ((size_t*)new_mem)[1] = size + MEM_HEADER_SIZE; - new_mem = ((char*)new_mem) + MEM_HEADER_SIZE; + if(new_mem) { + ((size_t*)new_mem)[1] = size + MEM_HEADER_SIZE; + new_mem = ((char*)new_mem) + MEM_HEADER_SIZE; + } #elif defined(OS_UNIX) || defined(OS_MACH) new_mem = realloc( mem, size ); #else @@ -124,9 +130,13 @@ mem_alloc_aligned(const size_t size, const size_t alignment) #if defined(OS_WINDOWS) mem = _aligned_offset_malloc (size + MEM_HEADER_SIZE, alignment, MEM_HEADER_SIZE); - ((size_t*)mem)[0] = alignment; - ((size_t*)mem)[1] = size + MEM_HEADER_SIZE; - mem = ((char*)mem) + MEM_HEADER_SIZE; + if(mem) { + ((size_t*)mem)[0] = alignment; + ((size_t*)mem)[1] = size + MEM_HEADER_SIZE; + mem = ((char*)mem) + MEM_HEADER_SIZE; + ATOMIC_ADD(&g_alloc_counter.allocated_size, mem_size(mem)); + ATOMIC_INCR(&g_alloc_counter.nb_allocs); + } #elif defined(OS_UNIX) || defined(OS_MACH) const int result = posix_memalign (&mem, (alignment < sizeof(void*)) ? sizeof(void*) : alignment, size); @@ -134,13 +144,13 @@ mem_alloc_aligned(const size_t size, const size_t alignment) /* The following assert may not occur due to previous conditions */ ASSERT(result != EINVAL); ASSERT((result != ENOMEM) || (mem == NULL)); -#else - #error "Unsupported OS" -#endif if(mem) { ATOMIC_ADD(&g_alloc_counter.allocated_size, mem_size(mem)); ATOMIC_INCR(&g_alloc_counter.nb_allocs); } +#else + #error "Unsupported OS" +#endif } return mem; } diff --git a/src/mem_lifo_allocator.c b/src/mem_lifo_allocator.c @@ -75,18 +75,21 @@ lifo_alloc_aligned align_adjusted = align < LIFO_DEFAULT_ALIGNMENT ? LIFO_DEFAULT_ALIGNMENT : align; - header_size = ALIGN_SIZE(sizeof(int64_t), align_adjusted); - footer_size = sizeof(int64_t); - data_size = ALIGN_SIZE(size, sizeof(int64_t)); - entry_size = header_size + data_size + footer_size; - - ASSERT(data_size < (size_t)(((int64_t)1<<48)-1)); - ASSERT(header_size < (1<<16)-1); - header = (int64_t)data_size | ((int64_t)header_size<<48); - footer = (int64_t)data_size | ((int64_t)1<<48); - mutex_lock(lifo->mutex); { /* Critical section */ + intptr_t data_addr = (intptr_t)(lifo->top + sizeof(int64_t)); + data_addr = ALIGN_SIZE(data_addr, (intptr_t)align_adjusted); + + header_size = (size_t)(data_addr - (intptr_t)lifo->top); + footer_size = sizeof(int64_t); + data_size = ALIGN_SIZE(size, sizeof(int64_t)); + entry_size = header_size + data_size + footer_size; + + ASSERT(data_size < (size_t)(((int64_t)1<<48)-1)); + ASSERT(header_size < (1<<16)-1); + header = (int64_t)data_size | ((int64_t)header_size<<48); + footer = (int64_t)data_size | ((int64_t)1<<48); + if(lifo->remain < entry_size) { mem = NULL; } else { @@ -98,6 +101,8 @@ lifo_alloc_aligned *(int64_t*)(mem + data_size) = footer; } } + CHK(IS_ALIGNED(mem, align)); + mutex_unlock(lifo->mutex); return mem; } diff --git a/src/real33.h b/src/real33.h @@ -170,7 +170,7 @@ static INLINE REAL_TYPE__* REALXY_FUNC__(basis)(REAL_TYPE__ dst[9], const REAL_TYPE__ N[3]) { REAL_TYPE__ a[3], b[3], x[3], y[3], normal[3], len; - ASSERT(N); + ASSERT(N && REALX_FUNC__(is_normalized(N))); REALX_FUNC__(set)(normal, N); a[0] = 1.f, a[1] = 0.f, a[2] = 0.f; b[0] = 0.f, b[1] = 1.f, b[2] = 0.f; diff --git a/src/rsys.h b/src/rsys.h @@ -282,10 +282,14 @@ static INLINE DEPRECATED void macro_NCHECK(void) { (void)0; } #ifdef __SSE4_2__ #define SIMD_SSE4_2 #endif + #ifdef __AVX__ + #define SIMD_AVX + #endif #elif defined(COMPILER_CL) #ifdef ARCH_64BITS #define SIMD_SSE #define SIMD_SSE2 + #else /* 32-bits */ #if _M_IX86_FP >= 1 #define SIMD_SSE @@ -294,6 +298,10 @@ static INLINE DEPRECATED void macro_NCHECK(void) { (void)0; } #define SIMD_SSE2 #endif #endif + + #ifdef __AVX__ + #define SIMD_AVX + #endif #endif /******************************************************************************* diff --git a/src/test_algorithm.c b/src/test_algorithm.c @@ -15,6 +15,11 @@ #include "algorithm.h" +struct data { + char dummy[16]; + double dbl; +}; + static int cmp_int(const void* a, const void* b) { @@ -32,6 +37,14 @@ cmp_dbl(const void* a, const void* b) ? -1 : (*(const double*)a > *(const double*)b ? 1 : 0); } +static int +cmp_key_data(const void* key, const void* data) +{ + const double h = *((const double*)key); + const struct data* d = (const struct data*)data; + return h < d->dbl ? -1 : (h > d->dbl ? 1 : 0); +} + int main(int argc, char** argv) { @@ -41,42 +54,73 @@ main(int argc, char** argv) -1.123, 2.3, 2.3, 2.3, 4, 5.0, 5.2, 6, 9.1, 19.123 }; const size_t ndbls = sizeof(array_dbl)/sizeof(double); + const struct data data[] = { + {{0},-1.123}, + {{0},2.3}, + {{0},2.3}, + {{0},2.3}, + {{0},4.0}, + {{0},5.0}, + {{0},5.2}, + {{0},6.0}, + {{0},9.1}, + {{0},19.123} + }; + const size_t ndata = sizeof(data)/sizeof(struct data); + int* pi; int i; double* pd; + struct data* pdata; double d; (void)argc, (void)argv; - i = 3, pi = search_lower_bound(&i, array_int, nints, sizeof(int), cmp_int); + #define SEARCH search_lower_bound + + i = 3, pi = SEARCH(&i, array_int, nints, sizeof(int), cmp_int); CHK(*pi == 4); CHK(pi[3] == 6); - i = 4, pi = search_lower_bound(&i, array_int, nints, sizeof(int), cmp_int); + i = 4, pi = SEARCH(&i, array_int, nints, sizeof(int), cmp_int); CHK(*pi == 4); CHK(pi[3] == 6); - i = 5, pi = search_lower_bound(&i, array_int, nints, sizeof(int), cmp_int); + i = 5, pi = SEARCH(&i, array_int, nints, sizeof(int), cmp_int); CHK(*pi == 6); - i = 13, pi = search_lower_bound(&i, array_int, nints, sizeof(int), cmp_int); + i = 13, pi = SEARCH(&i, array_int, nints, sizeof(int), cmp_int); CHK(*pi == 13); - i = -1, pi = search_lower_bound(&i, array_int, nints, sizeof(int), cmp_int); + i = -1, pi = SEARCH(&i, array_int, nints, sizeof(int), cmp_int); CHK(*pi == 0); - i = 19, pi = search_lower_bound(&i, array_int, nints, sizeof(int), cmp_int); + i = 19, pi = SEARCH(&i, array_int, nints, sizeof(int), cmp_int); CHK(pi == NULL); - d = 2.1, pd = search_lower_bound(&d, array_dbl, ndbls, sizeof(double), cmp_dbl); + d = 2.1, pd = SEARCH(&d, array_dbl, ndbls, sizeof(double), cmp_dbl); CHK(*pd == 2.3); - d = 2.3, pd = search_lower_bound(&d, array_dbl, ndbls, sizeof(double), cmp_dbl); + d = 2.3, pd = SEARCH(&d, array_dbl, ndbls, sizeof(double), cmp_dbl); CHK(*pd == 2.3); CHK(pd[3] == 4); - d = -1.0, pd = search_lower_bound(&d, array_dbl, ndbls, sizeof(double), cmp_dbl); + d = -1.0, pd = SEARCH(&d, array_dbl, ndbls, sizeof(double), cmp_dbl); CHK(*pd == 2.3); - d = 6.001, pd = search_lower_bound(&d, array_dbl, ndbls, sizeof(double), cmp_dbl); + d = 6.001, pd = SEARCH(&d, array_dbl, ndbls, sizeof(double), cmp_dbl); CHK(*pd == 9.1); - d = 19.0, pd = search_lower_bound(&d, array_dbl, ndbls, sizeof(double), cmp_dbl); + d = 19.0, pd = SEARCH(&d, array_dbl, ndbls, sizeof(double), cmp_dbl); CHK(*pd == 19.123); - d = 20.0, pd = search_lower_bound(&d, array_dbl, ndbls, sizeof(double), cmp_dbl); + d = 20.0, pd = SEARCH(&d, array_dbl, ndbls, sizeof(double), cmp_dbl); CHK(pd == NULL); - i = -1, pi = search_lower_bound(&i, array_int, 1, sizeof(int), cmp_int); + d = 2.1, pdata = SEARCH(&d, data, ndata, sizeof(struct data), cmp_key_data); + CHK(pdata->dbl == 2.3); + d = 2.3, pdata = SEARCH(&d, data, ndata, sizeof(struct data), cmp_key_data); + CHK(pdata->dbl == 2.3); + CHK(pdata[3].dbl == 4); + d = -1.0, pdata = SEARCH(&d, data, ndata, sizeof(struct data), cmp_key_data); + CHK(pdata->dbl == 2.3); + d = 6.001, pdata = SEARCH(&d, data, ndata, sizeof(struct data), cmp_key_data); + CHK(pdata->dbl == 9.1); + d = 19.0, pdata = SEARCH(&d, data, ndata, sizeof(struct data), cmp_key_data); + CHK(pdata->dbl == 19.123); + d = 20.0, pdata = SEARCH(&d, data, ndata, sizeof(struct data), cmp_key_data); + CHK(pdata == NULL); + + i = -1, pi = SEARCH(&i, array_int, 1, sizeof(int), cmp_int); CHK(*pi == 0); return 0; diff --git a/src/test_big_buffer.c b/src/test_big_buffer.c @@ -1,369 +0,0 @@ -/* Copyright (C) 2013-2018 Vincent Forest (vaplv@free.fr) - * - * The RSys library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The RSys library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the RSys library. If not, see <http://www.gnu.org/licenses/>. */ - -#include "big_buffer.h" -#include "test_utils.h" - -#include <stdlib.h> - -#define BIGBUF_NAME byte -#define BIGBUF_DATA char -#include "big_buffer.h" - -#define BIGBUF_NAME integer -#define BIGBUF_DATA int -#define BIGBUF_ALIGNMENT 64 -#include "big_buffer.h" - -#define BIGBUF_NAME real -#define BIGBUF_DATA double -#include "big_buffer.h" - -static INLINE double -rand_canonic(void) -{ - return (double)rand()/(double)(RAND_MAX-1); -} - -static void -test_byte(struct mem_allocator* allocator) -{ - struct bigbuf_byte bytes; - size_t i; - char byte; - - CHECK(bigbuf_byte_init(allocator, 4, NULL, BIGBUF_LOAD_STREAM, &bytes), RES_BAD_ARG); - CHECK(bigbuf_byte_init(allocator, 0, NULL, 0, &bytes), RES_BAD_ARG); - CHECK(bigbuf_byte_init(allocator, 4, NULL, 0, &bytes), RES_OK); - CHECK(bigbuf_byte_size_get(&bytes), 0); - - FOR_EACH(i, 0, 32) { - byte = (char)i; - CHECK(bigbuf_byte_push_back(&bytes, &byte), RES_OK); - } - - CHECK(bigbuf_byte_size_get(&bytes), 32); - - FOR_EACH(i, 0, bigbuf_byte_size_get(&bytes)) { - byte = *bigbuf_byte_at(&bytes, i); - CHECK((size_t)byte, i); - } - - FOR_EACH(i, 0, 16) { - size_t id = (size_t)(rand_canonic() * (double)bigbuf_byte_size_get(&bytes)); - byte = *bigbuf_byte_at(&bytes, id); - CHECK((size_t)byte, id); - } - - FOR_EACH(i, 0, 32) { - byte = (char)(i + 32); - CHECK(bigbuf_byte_push_back(&bytes, &byte), RES_OK); - } - - FOR_EACH(i, 0, bigbuf_byte_size_get(&bytes)) { - byte = *bigbuf_byte_at(&bytes, i); - CHECK((size_t)byte, i); - } - - CHECK(bigbuf_byte_size_get(&bytes), 64); - byte = *bigbuf_byte_at(&bytes, 61); - - CHECK(bigbuf_byte_resize(&bytes, 63), RES_OK); - CHECK(bigbuf_byte_size_get(&bytes), 63); - byte = *bigbuf_byte_at(&bytes, 62); - CHECK(byte, 62); - - byte = 63; - CHECK(bigbuf_byte_push_back(&bytes, &byte), RES_OK); - CHECK(bigbuf_byte_size_get(&bytes), 64); - FOR_EACH(i, 0, bigbuf_byte_size_get(&bytes)) { - byte = *bigbuf_byte_at(&bytes, i); - CHECK((size_t)byte, i); - } - - CHECK(bigbuf_byte_resize(&bytes, 32), RES_OK); - CHECK(bigbuf_byte_resize(&bytes, 32), RES_OK); - - byte = *bigbuf_byte_at(&bytes, 31); - CHECK(byte, 31); - FOR_EACH(i, 0, 32) { - byte = (char)(i + 32); - CHECK(bigbuf_byte_push_back(&bytes, &byte), RES_OK); - } - FOR_EACH(i, 0, bigbuf_byte_size_get(&bytes)) { - byte = *bigbuf_byte_at(&bytes, i); - CHECK((size_t)byte, i); - } - - CHECK(bigbuf_byte_resize(&bytes, 128), RES_OK); - CHECK(bigbuf_byte_size_get(&bytes), 128); - FOR_EACH(i, 0, bigbuf_byte_size_get(&bytes)) { - byte = *bigbuf_byte_at(&bytes, i); - if(i < 64) { - CHECK((size_t)byte, i); - } else { - CHECK(byte, 0); - } - } - - CHECK(bigbuf_byte_set(&bytes, 128, &byte), RES_BAD_ARG); - FOR_EACH(i, 0, 64) { - byte = (char)(i+64); - CHECK(bigbuf_byte_set(&bytes, (size_t)byte, &byte), RES_OK); - byte = *bigbuf_byte_at(&bytes, (size_t)byte - 1); - CHECK((size_t)byte, i+63); - } - FOR_EACH(i, 0, bigbuf_byte_size_get(&bytes)) { - byte = *bigbuf_byte_at(&bytes, i); - CHECK((size_t)byte, i); - } - - CHECK(bigbuf_byte_clear(&bytes), RES_OK); - CHECK(bigbuf_byte_size_get(&bytes), 0); - CHECK(bigbuf_byte_set(&bytes, 0, &byte), RES_BAD_ARG); - FOR_EACH(i, 0, 16) { - byte = (char)i; - CHECK(bigbuf_byte_push_back(&bytes, &byte), RES_OK); - } - CHECK(bigbuf_byte_size_get(&bytes), 16); - FOR_EACH(i, 0, bigbuf_byte_size_get(&bytes)) { - byte = *bigbuf_byte_at(&bytes, i); - CHECK((size_t)byte, i); - } - - bigbuf_byte_release(&bytes); -} - -static void -test_integer(struct mem_allocator* allocator) -{ - struct bigbuf_integer ints; - struct bigbuf_integer ints2; - FILE* stream; - size_t i; - int integer; - - NCHECK(stream = tmpfile(), NULL); - - CHECK(bigbuf_integer_init(NULL, 1, stream, 0, &ints), RES_OK); - - FOR_EACH(i, 0, 999) { - integer = (int)i; - CHECK(bigbuf_integer_push_back(&ints, &integer), RES_OK); - } - - FOR_EACH(i, 0, 666) { - size_t id = (size_t)(rand_canonic() * (double)bigbuf_integer_size_get(&ints)); - integer = *bigbuf_integer_at(&ints, id); - CHECK((size_t)integer, id); - } - - FOR_EACH(i, 0, 666) { - integer = (int)i + 999; - CHECK(bigbuf_integer_push_back(&ints, &integer), RES_OK); - } - - CHECK(bigbuf_integer_size_get(&ints), 1665); - FOR_EACH(i, 0, bigbuf_integer_size_get(&ints)) { - integer = *bigbuf_integer_at(&ints, i); - CHECK((size_t)integer, i); - } - - bigbuf_integer_release(&ints); - - rewind(stream); - CHECK(bigbuf_integer_init(allocator, 1, stream, BIGBUF_LOAD_STREAM, &ints), RES_OK); - CHECK(bigbuf_integer_size_get(&ints), 1665); - - FOR_EACH(i, 0, 666) { - size_t id = (size_t)(rand_canonic() * (double)bigbuf_integer_size_get(&ints)); - integer = *bigbuf_integer_at(&ints, id); - CHECK((size_t)integer, id); - } - - FOR_EACH(i, 0, 1024) { - integer = (int)i + 1665; - CHECK(bigbuf_integer_push_back(&ints, &integer), RES_OK); - } - CHECK(bigbuf_integer_size_get(&ints), 2689); - bigbuf_integer_release(&ints); - - rewind(stream); - CHECK(bigbuf_integer_init(NULL, 1, stream, BIGBUF_LOAD_STREAM, &ints2), RES_OK); - CHECK(bigbuf_integer_size_get(&ints2), bigbuf_integer_size_get(&ints)); - CHECK(bigbuf_integer_size_get(&ints2), 2689); - - FOR_EACH(i, 0, bigbuf_integer_size_get(&ints2)) { - integer = *bigbuf_integer_at(&ints2, i); - CHECK((size_t)integer, i); - } - - CHECK(bigbuf_integer_resize(&ints2, 999), RES_OK); - CHECK(bigbuf_integer_size_get(&ints2), 999); - FOR_EACH(i, 0, bigbuf_integer_size_get(&ints2)) { - integer = *bigbuf_integer_at(&ints2, i); - integer = -integer; - CHECK(bigbuf_integer_set(&ints2, i, &integer), RES_OK); - if(i) { - integer = *bigbuf_integer_at(&ints2, i-1); - CHECK(integer, 1 - (int)i); - } - } - - FOR_EACH(i, 0, bigbuf_integer_size_get(&ints2)) { - integer = *bigbuf_integer_at(&ints2, i); - CHECK(integer, -(int)i); - } - - CHECK(bigbuf_integer_clear(&ints2), RES_OK); - CHECK(bigbuf_integer_size_get(&ints2), 0); - CHECK(bigbuf_integer_set(&ints2, 0, &integer), RES_BAD_ARG); - FOR_EACH(i, 0, 64) { - integer = (int)i; - CHECK(bigbuf_integer_push_back(&ints2, &integer), RES_OK); - } - CHECK(bigbuf_integer_size_get(&ints2), 64); - FOR_EACH(i, 0, bigbuf_integer_size_get(&ints2)) { - integer = *bigbuf_integer_at(&ints2, i); - CHECK(integer, (int)i); - } - - bigbuf_integer_release(&ints2); - fclose(stream); -} - -static void -test_real(struct mem_allocator* allocator) -{ - struct bigbuf_real reals; - struct bigbuf_real reals2; - FILE* stream; - double real; - size_t ids[32]; - size_t i; - - NCHECK(stream = tmpfile(), NULL); - CHECK(bigbuf_real_init(allocator, 45, stream, BIGBUF_LOAD_STREAM, &reals), RES_IO_ERR); - CHECK(bigbuf_real_init(allocator, 45, stream, 0, &reals), RES_OK); - - FOR_EACH(i, 0, 4000) { - real = (double)i / 100.0; - CHECK(bigbuf_real_push_back(&reals, &real), RES_OK); - } - - CHECK(bigbuf_real_size_get(&reals), 4000); - - FOR_EACH(i, 0, 10) { - size_t id = (size_t)(rand_canonic() * (double)bigbuf_real_size_get(&reals)); - real = *bigbuf_real_at(&reals, id); - CHECK(real, (double)id/100.0); - } - - rewind(stream); - - FOR_EACH(i, 0, 2000) { - real = (double)(i+4000) / 100.0; - CHECK(bigbuf_real_push_back(&reals, &real), RES_OK); - } - - bigbuf_real_flush(&reals); - - rewind(stream); - bigbuf_real_init(allocator, 45, stream, BIGBUF_LOAD_STREAM, &reals2); - - CHECK(bigbuf_real_size_get(&reals), 6000); - CHECK(bigbuf_real_size_get(&reals2), 6000); - - FOR_EACH(i, 0, bigbuf_real_size_get(&reals)) { - real = *bigbuf_real_at(&reals, i); - CHECK(real, (double)i/100.0); - } - - FOR_EACH(i, 0, 300) { - size_t id = (size_t)(rand_canonic() * (double)bigbuf_real_size_get(&reals2)); - real = *bigbuf_real_at(&reals2, id); - CHECK(real, (double)id/100.0); - } - - real = *bigbuf_real_at(&reals2, 5990); - CHECK(real, 59.90); - CHECK(bigbuf_real_resize(&reals2, 5992), RES_OK); - real = *bigbuf_real_at(&reals2, 5990); - CHECK(real, 59.90); - CHECK(bigbuf_real_resize(&reals2, 5990), RES_OK); - real = *bigbuf_real_at(&reals2, 5989); - CHECK(real, 59.89); - CHECK(bigbuf_real_resize(&reals2, 5985), RES_OK); - real = *bigbuf_real_at(&reals2, 5984); - CHECK(real, 59.84); - - FOR_EACH(i, 0, sizeof(ids)/sizeof(size_t)) { - ids[i] = (size_t)(rand_canonic() * (double)bigbuf_real_size_get(&reals2)); - real = (double)ids[i]; - CHECK(bigbuf_real_set(&reals2, ids[i], &real), RES_OK); - } - - CHECK(bigbuf_real_size_get(&reals2), 5985); - FOR_EACH(i, 0, bigbuf_real_size_get(&reals2)) { - size_t j; - real = *bigbuf_real_at(&reals2, i); - - FOR_EACH(j, 0, sizeof(ids)/sizeof(size_t)) { - if(i == ids[j]) break; - } - - if(j == sizeof(ids)/sizeof(size_t)) { - CHECK(real, (double)i/100.0); - } else { - CHECK(real, (double)i); - } - } - - CHECK(bigbuf_real_clear(&reals2), RES_OK); - CHECK(bigbuf_real_size_get(&reals2), 0); - CHECK(bigbuf_real_set(&reals2, 0, &real), RES_BAD_ARG); - FOR_EACH(i, 0, 64) { - real = (double)i; - CHECK(bigbuf_real_push_back(&reals2, &real), RES_OK); - } - CHECK(bigbuf_real_size_get(&reals2), 64); - FOR_EACH(i, 0, bigbuf_real_size_get(&reals2)) { - real = *bigbuf_real_at(&reals2, i); - CHECK(real, (double)i); - } - - bigbuf_real_release(&reals); - bigbuf_real_release(&reals2); - fclose(stream); -} - -int -main(int argc, char** argv) -{ - struct mem_allocator allocator_proxy; - (void)argc, (void)argv; - - mem_init_proxy_allocator(&allocator_proxy, &mem_default_allocator); - - test_byte(&allocator_proxy); - test_integer(&allocator_proxy); - test_real(&allocator_proxy); - - check_memory_allocator(&allocator_proxy); - mem_shutdown_proxy_allocator(&allocator_proxy); - CHECK(mem_allocated_size(), 0); - return 0; -} - diff --git a/src/test_cstr.c b/src/test_cstr.c @@ -258,6 +258,18 @@ test_list_uint(void) CHK(ulist[3] == 3); } +static void +test_res_to_cstr(void) +{ + printf("%s\n", res_to_cstr(RES_OK)); + printf("%s\n", res_to_cstr(RES_BAD_ARG)); + printf("%s\n", res_to_cstr(RES_MEM_ERR)); + printf("%s\n", res_to_cstr(RES_IO_ERR)); + printf("%s\n", res_to_cstr(RES_UNKNOWN_ERR)); + printf("%s\n", res_to_cstr(RES_BAD_OP)); + printf("%s\n", res_to_cstr(RES_EOF)); +} + int main(int argc, char** argv) { @@ -271,5 +283,6 @@ main(int argc, char** argv) test_list_double(); test_list_float(); test_list_uint(); + test_res_to_cstr(); return 0; } diff --git a/src/test_mutex.c b/src/test_mutex.c @@ -201,7 +201,8 @@ test_mutex(void) string.str[0] = '\0'; string.i = 0; - CHK(string.mutex = mutex_create()); + string.mutex = mutex_create(); + CHK(string.mutex != NULL); time_current(&time_start);