From d8ccc87fed8a4c588e4ad9279e62925f416d36b3 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Sun, 25 Nov 2018 23:05:59 +0100 Subject: Some fixes and add wide-character string duplication functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- wmemdup.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 wmemdup.c (limited to 'wmemdup.c') diff --git a/wmemdup.c b/wmemdup.c new file mode 100644 index 0000000..239ae7d --- /dev/null +++ b/wmemdup.c @@ -0,0 +1,31 @@ +/* See LICENSE file for copyright and license details. */ +#include "libsimple.h" +#ifndef TEST + + +wchar_t * +libsimple_wmemdup(const wchar_t *s, size_t n) /* TODO test */ +{ + wchar_t *ret; + size_t size; + if (LIBSIMPLE_UMUL_OVERFLOW_NONZERO(n + !n, sizeof(wchar_t), &size, SIZE_MAX)) { + errno = ENOMEM; + return NULL; + } + ret = aligned_alloc(_Alignof(wchar_t), size); + if (!ret) + return NULL; + return wmemcpy(ret, s, n); +} + + +#else +#include "test.h" + +int +main(void) +{ + return 0; +} + +#endif -- cgit v1.2.3-70-g09d2 From d1122de6bb461e0448897869b4406300c12f259f Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Sat, 15 Dec 2018 14:56:23 +0100 Subject: More tests and fix attributes on wcsndup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- Makefile | 6 + aligned_strndup.c | 81 ++++++++++++- aligned_wcsndup.c | 6 +- enaligned_realloc.c | 82 ++++++++++++- enaligned_reallocarray.c | 82 ++++++++++++- enaligned_strdup.c | 14 +++ enaligned_strndup.c | 6 +- enaligned_wcsdup.c | 55 ++++++++- enaligned_wcsndup.c | 111 ++++++++++++++++- enaligned_wmemdup.c | 41 ++++++- enreallocarray.c | 109 ++++++++++++++++- enwcsdup.c | 41 ++++++- enwcsndup.c | 109 ++++++++++++++++- enwmemdup.c | 49 +++++++- libsimple.c | 290 +++++++++++++++++++++++++++++++++++++------- libsimple/aligned_strdup.h | 4 +- libsimple/aligned_strndup.h | 2 +- libsimple/aligned_wcsdup.h | 8 +- libsimple/aligned_wcsndup.h | 4 +- libsimple/aligned_wmemdup.h | 6 +- libsimple/realloc.h | 4 +- libsimple/wcsndup.h | 6 +- libsimple/wmemdup.h | 4 +- test.c | 4 + test.h | 39 ++++++ wcsndup.c | 82 ++++++++++++- wmemdup.c | 23 +++- 27 files changed, 1184 insertions(+), 84 deletions(-) (limited to 'wmemdup.c') diff --git a/Makefile b/Makefile index 1a8e05e..50152f4 100644 --- a/Makefile +++ b/Makefile @@ -64,6 +64,9 @@ OBJ =\ enaligned_reallocarray.o\ enaligned_strdup.o\ enaligned_strndup.o\ + enaligned_wcsdup.o\ + enaligned_wcsndup.o\ + enaligned_wmemdup.o\ encalloc.o\ enmalloc.o\ enmemdup.o\ @@ -79,6 +82,9 @@ OBJ =\ envposix_memalignzn.o\ envputenvf.o\ envreallocn.o\ + enwcsdup.o\ + enwcsndup.o\ + enwmemdup.o\ memcasechr.o\ memcasechr_inv.o\ memcasecmp.o\ diff --git a/aligned_strndup.c b/aligned_strndup.c index a714387..f41fa8c 100644 --- a/aligned_strndup.c +++ b/aligned_strndup.c @@ -4,7 +4,7 @@ char * -libsimple_aligned_strndup(const char *s, size_t alignment, size_t n) /* TODO test */ +libsimple_aligned_strndup(const char *s, size_t alignment, size_t n) { char *ret; n = strnlen(s, n); @@ -23,6 +23,85 @@ libsimple_aligned_strndup(const char *s, size_t alignment, size_t n) /* TODO tes int main(void) { + struct allocinfo *info; + void *s; + + assert((s = libsimple_aligned_strndup("hello", 2, SIZE_MAX))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 6); + assert(info->alignment == 2); + assert(!info->zeroed); + } + assert(!memcmp(s, "hello", 6)); + free(s); + + assert((s = libsimple_aligned_strndup("hello", 2, 100))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 6); + assert(info->alignment == 2); + assert(!info->zeroed); + } + assert(!memcmp(s, "hello", 6)); + free(s); + + assert((s = libsimple_aligned_strndup("hello", 4, 6))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 8); + assert(info->alignment == 4); + assert(!info->zeroed); + } + assert(!memcmp(s, "hello", 6)); + free(s); + + assert((s = libsimple_aligned_strndup("hello", 8, 6))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 8); + assert(info->alignment == 8); + assert(!info->zeroed); + } + assert(!memcmp(s, "hello", 6)); + free(s); + + assert((s = libsimple_aligned_strndup("hello", 16, 6))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 16); + assert(info->alignment == 16); + assert(!info->zeroed); + } + assert(!memcmp(s, "hello", 6)); + free(s); + + assert((s = libsimple_aligned_strndup("hello", 2, 5))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 6); + assert(info->alignment == 2); + assert(!info->zeroed); + } + assert(!memcmp(s, "hello", 6)); + free(s); + + assert((s = libsimple_aligned_strndup("hello", 2, 4))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 6); + assert(info->alignment == 2); + assert(!info->zeroed); + } + assert(!memcmp(s, "hell", 5)); + free(s); + + if (have_custom_malloc()) { + alloc_fail_in = 1; + assert(!libsimple_aligned_strndup("hello", 2, 10) && errno == ENOMEM); + assert(!alloc_fail_in); + } + return 0; } diff --git a/aligned_wcsndup.c b/aligned_wcsndup.c index 1839316..90ce7f7 100644 --- a/aligned_wcsndup.c +++ b/aligned_wcsndup.c @@ -8,10 +8,8 @@ libsimple_aligned_wcsndup(const wchar_t *s, size_t alignment, size_t n) { size_t size; wchar_t *ret; - if (LIBSIMPLE_UMUL_OVERFLOW_NONZERO(n + 1, sizeof(wchar_t), &size, SIZE_MAX)) { - errno = ENOMEM; - return NULL; - } + n = wcsnlen(s, n); + size = (n + 1) * sizeof(wchar_t); size = size + (alignment - size % alignment) % alignment; ret = aligned_alloc(alignment, size); if (!ret) diff --git a/enaligned_realloc.c b/enaligned_realloc.c index 9ae1612..6d5ac4e 100644 --- a/enaligned_realloc.c +++ b/enaligned_realloc.c @@ -4,7 +4,7 @@ void * -libsimple_enaligned_realloc(int status, void *ptr, size_t alignment, size_t n) /* TODO test (ealigned_realloc) */ +libsimple_enaligned_realloc(int status, void *ptr, size_t alignment, size_t n) { void *ret = aligned_realloc(ptr, alignment, n); if (!ret) @@ -19,6 +19,86 @@ libsimple_enaligned_realloc(int status, void *ptr, size_t alignment, size_t n) / int main(void) { +#ifdef LIBSIMPLE_HAVE_ALIGNED_REALLOC + + struct allocinfo *info; + void *ptr, *old; + DEFINE_CACHELINE; + + assert((ptr = libsimple_enaligned_realloc(1, NULL, 16, 5))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 5 || info->size == info->alignment); + assert(!info->zeroed); + ASSERT_ALIGNMENT(info, 16); + info->refcount += 1; + } + stpcpy(ptr, "test"); + assert((ptr = libsimple_enaligned_realloc(1, old = ptr, 32, 10))); + assert(!strcmp(ptr, "test")); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 10 || info->size == info->alignment); + assert(!info->zeroed); + ASSERT_ALIGNMENT(info, 32); + assert(ptr != old); + free(old); + } + free(ptr); + + assert((ptr = libsimple_ealigned_realloc(NULL, 8, 5))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 5 || info->size == info->alignment); + assert(!info->zeroed); + ASSERT_ALIGNMENT(info, 8); + info->refcount += 1; + } + stpcpy(ptr, "test"); + assert((ptr = libsimple_ealigned_realloc(old = ptr, 64, 10))); + assert(!strcmp(ptr, "test")); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 10 || info->size == info->alignment); + assert(!info->zeroed); + ASSERT_ALIGNMENT(info, 64); + assert(ptr != old); + free(old); + } + free(ptr); + + if (have_custom_malloc()) { + alloc_fail_in = 1; + assert_exit_ptr(libsimple_enaligned_realloc(2, NULL, 8, 1)); + assert(exit_status == 2); + assert_stderr("%s: aligned_realloc: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + + libsimple_default_failure_exit = 104; + alloc_fail_in = 1; + assert_exit_ptr(libsimple_ealigned_realloc(NULL, 16, 1)); + assert(exit_status == 104); + assert_stderr("%s: aligned_realloc: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + libsimple_default_failure_exit = 1; + } + +#else + + assert_exit_ptr(libsimple_enaligned_realloc(2, NULL, 8, 1)); + assert(exit_status == 2); + assert_stderr("%s: aligned_realloc: %s\n", argv0, strerror(ENOSYS)); + + libsimple_default_failure_exit = 104; + alloc_fail_in = 1; + assert_exit_ptr(libsimple_ealigned_realloc(NULL, 16, 1)); + assert(exit_status == 104); + assert_stderr("%s: aligned_realloc: %s\n", argv0, strerror(ENOSYS)); + assert(!alloc_fail_in); + libsimple_default_failure_exit = 1; + +#endif + return 0; } diff --git a/enaligned_reallocarray.c b/enaligned_reallocarray.c index 35050ec..5a71207 100644 --- a/enaligned_reallocarray.c +++ b/enaligned_reallocarray.c @@ -4,7 +4,7 @@ void * -libsimple_enaligned_reallocarray(int status, void *ptr, size_t alignment, size_t n, size_t m) /* TODO test (ealigned_reallocarray) */ +libsimple_enaligned_reallocarray(int status, void *ptr, size_t alignment, size_t n, size_t m) { void *ret = aligned_reallocarray(ptr, alignment, n, m); if (!ret) @@ -19,6 +19,86 @@ libsimple_enaligned_reallocarray(int status, void *ptr, size_t alignment, size_t int main(void) { +#ifdef LIBSIMPLE_HAVE_ALIGNED_REALLOC + + struct allocinfo *info; + void *ptr, *old; + DEFINE_CACHELINE; + + assert((ptr = libsimple_enaligned_reallocarray(1, NULL, 16, 5, 2))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 10 || info->size == info->alignment); + assert(!info->zeroed); + ASSERT_ALIGNMENT(info, 16); + info->refcount += 1; + } + stpcpy(ptr, "test"); + assert((ptr = libsimple_enaligned_reallocarray(1, old = ptr, 32, 10, 3))); + assert(!strcmp(ptr, "test")); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 30 || info->size == info->alignment); + assert(!info->zeroed); + ASSERT_ALIGNMENT(info, 32); + assert(ptr != old); + free(old); + } + free(ptr); + + assert((ptr = libsimple_ealigned_reallocarray(NULL, 8, 5, 3))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 15 || info->size == 16); + assert(!info->zeroed); + ASSERT_ALIGNMENT(info, 8); + info->refcount += 1; + } + stpcpy(ptr, "test"); + assert((ptr = libsimple_ealigned_reallocarray(old = ptr, 64, 10, 4))); + assert(!strcmp(ptr, "test")); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 40 || info->size == info->alignment); + assert(!info->zeroed); + ASSERT_ALIGNMENT(info, 64); + assert(ptr != old); + free(old); + } + free(ptr); + + if (have_custom_malloc()) { + alloc_fail_in = 1; + assert_exit_ptr(libsimple_enaligned_reallocarray(2, NULL, 8, 1, 2)); + assert(exit_status == 2); + assert_stderr("%s: aligned_reallocarray: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + + libsimple_default_failure_exit = 104; + alloc_fail_in = 1; + assert_exit_ptr(libsimple_ealigned_reallocarray(NULL, 16, 1, 2)); + assert(exit_status == 104); + assert_stderr("%s: aligned_reallocarray: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + libsimple_default_failure_exit = 1; + } + +#else + + assert_exit_ptr(libsimple_enaligned_reallocarray(2, NULL, 8, 1, 2)); + assert(exit_status == 2); + assert_stderr("%s: aligned_reallocarray: %s\n", argv0, strerror(ENOSYS)); + + libsimple_default_failure_exit = 104; + alloc_fail_in = 1; + assert_exit_ptr(libsimple_ealigned_reallocarray(NULL, 16, 1, 2)); + assert(exit_status == 104); + assert_stderr("%s: aligned_reallocarray: %s\n", argv0, strerror(ENOSYS)); + assert(!alloc_fail_in); + libsimple_default_failure_exit = 1; + +#endif + return 0; } diff --git a/enaligned_strdup.c b/enaligned_strdup.c index 6390ab0..533ff56 100644 --- a/enaligned_strdup.c +++ b/enaligned_strdup.c @@ -42,6 +42,16 @@ main(void) assert(!memcmp(s, "test", 5)); free(s); + assert((s = libsimple_aligned_strdup("test", 4))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 8); + assert(info->alignment == 4); + assert(!info->zeroed); + } + assert(!memcmp(s, "test", 5)); + free(s); + if (have_custom_malloc()) { alloc_fail_in = 1; assert_exit_ptr(libsimple_enaligned_strdup(44, "hello", 2)); @@ -56,6 +66,10 @@ main(void) assert_stderr("%s: aligned_strdup: %s\n", argv0, strerror(ENOMEM)); assert(!alloc_fail_in); libsimple_default_failure_exit = 1; + + alloc_fail_in = 1; + assert(!libsimple_aligned_strdup("test", 16) && errno == ENOMEM); + assert(!alloc_fail_in); } return 0; diff --git a/enaligned_strndup.c b/enaligned_strndup.c index 7778cb2..6812d1c 100644 --- a/enaligned_strndup.c +++ b/enaligned_strndup.c @@ -8,7 +8,7 @@ libsimple_enaligned_strndup(int status, const char *s, size_t alignment, size_t { void *ret = aligned_strndup(s, alignment, n); if (!ret) - enprintf(status, "aligned_strdup:"); + enprintf(status, "aligned_strndup:"); return ret; } @@ -116,14 +116,14 @@ main(void) alloc_fail_in = 1; assert_exit_ptr(libsimple_enaligned_strndup(44, "hello", 2, 10)); assert(exit_status == 44); - assert_stderr("%s: aligned_strdup: %s\n", argv0, strerror(ENOMEM)); + assert_stderr("%s: aligned_strndup: %s\n", argv0, strerror(ENOMEM)); assert(!alloc_fail_in); libsimple_default_failure_exit = 55; alloc_fail_in = 1; assert_exit_ptr(libsimple_ealigned_strndup("test", 8, 10)); assert(exit_status == 55); - assert_stderr("%s: aligned_strdup: %s\n", argv0, strerror(ENOMEM)); + assert_stderr("%s: aligned_strndup: %s\n", argv0, strerror(ENOMEM)); assert(!alloc_fail_in); libsimple_default_failure_exit = 1; } diff --git a/enaligned_wcsdup.c b/enaligned_wcsdup.c index 17d0a4c..10d9669 100644 --- a/enaligned_wcsdup.c +++ b/enaligned_wcsdup.c @@ -4,7 +4,7 @@ wchar_t * -libsimple_enaligned_wcsdup(int status, const wchar_t *s, size_t alignment) /* TOOD test */ +libsimple_enaligned_wcsdup(int status, const wchar_t *s, size_t alignment) { void *ret = aligned_wcsdup(s, alignment); if (!ret) @@ -19,6 +19,59 @@ libsimple_enaligned_wcsdup(int status, const wchar_t *s, size_t alignment) /* TO int main(void) { + struct allocinfo *info; + void *s; + + assert((s = libsimple_enaligned_wcsdup(1, L"hello", 2))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 6 * sizeof(wchar_t)); + assert(info->alignment == 2); + assert(!info->zeroed); + } + assert(!wmemcmp(s, L"hello", 6)); + free(s); + + assert((s = libsimple_ealigned_wcsdup(L"test", 8))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 5 * sizeof(wchar_t) + (8 - 5 * sizeof(wchar_t) % 8) % 8); + assert(info->alignment == 8); + assert(!info->zeroed); + } + assert(!wmemcmp(s, L"test", 5)); + free(s); + + assert((s = libsimple_aligned_wcsdup(L"test", 4))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 5 * sizeof(wchar_t) + (4 - 5 * sizeof(wchar_t) % 4) % 4); + assert(info->alignment == 4); + assert(!info->zeroed); + } + assert(!wmemcmp(s, L"test", 5)); + free(s); + + if (have_custom_malloc()) { + alloc_fail_in = 1; + assert_exit_ptr(libsimple_enaligned_wcsdup(44, L"hello", 2)); + assert(exit_status == 44); + assert_stderr("%s: aligned_wcsdup: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + + libsimple_default_failure_exit = 55; + alloc_fail_in = 1; + assert_exit_ptr(libsimple_ealigned_wcsdup(L"test", 8)); + assert(exit_status == 55); + assert_stderr("%s: aligned_wcsdup: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + libsimple_default_failure_exit = 1; + + alloc_fail_in = 1; + assert(!libsimple_aligned_wcsdup(L"test", 16) && errno == ENOMEM); + assert(!alloc_fail_in); + } + return 0; } diff --git a/enaligned_wcsndup.c b/enaligned_wcsndup.c index 9b1aae8..32cce57 100644 --- a/enaligned_wcsndup.c +++ b/enaligned_wcsndup.c @@ -4,7 +4,7 @@ wchar_t * -libsimple_enaligned_wcsndup(int status, const wchar_t *s, size_t alignment, size_t n) /* TOOD test */ +libsimple_enaligned_wcsndup(int status, const wchar_t *s, size_t alignment, size_t n) { void *ret = aligned_wcsndup(s, alignment, n); if (!ret) @@ -19,6 +19,115 @@ libsimple_enaligned_wcsndup(int status, const wchar_t *s, size_t alignment, size int main(void) { + struct allocinfo *info; + void *s; + + assert((s = libsimple_enaligned_wcsndup(1, L"hello", 2, SIZE_MAX))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 6 * sizeof(wchar_t)); + assert(info->alignment == 2); + assert(!info->zeroed); + } + assert(!wmemcmp(s, L"hello", 6)); + free(s); + + assert((s = libsimple_ealigned_wcsndup(L"test", 8, SIZE_MAX))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 5 * sizeof(wchar_t) + (8 - 5 * sizeof(wchar_t) % 8) % 8); + assert(info->alignment == 8); + assert(!info->zeroed); + } + assert(!wmemcmp(s, L"test", 5)); + free(s); + + assert((s = libsimple_enaligned_wcsndup(1, L"hello", 2, 100))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 6 * sizeof(wchar_t)); + assert(info->alignment == 2); + assert(!info->zeroed); + } + assert(!wmemcmp(s, L"hello", 6)); + free(s); + + assert((s = libsimple_ealigned_wcsndup(L"test", 8, 100))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 5 * sizeof(wchar_t) + (8 - 5 * sizeof(wchar_t) % 8) % 8); + assert(info->alignment == 8); + assert(!info->zeroed); + } + assert(!wmemcmp(s, L"test", 5)); + free(s); + + assert((s = libsimple_enaligned_wcsndup(1, L"hello", 2, 6))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 6 * sizeof(wchar_t)); + assert(info->alignment == 2); + assert(!info->zeroed); + } + assert(!wmemcmp(s, L"hello", 6)); + free(s); + + assert((s = libsimple_ealigned_wcsndup(L"test", 8, 5))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 5 * sizeof(wchar_t) + (8 - 5 * sizeof(wchar_t) % 8) % 8); + assert(info->alignment == 8); + assert(!info->zeroed); + } + assert(!wmemcmp(s, L"test", 5)); + free(s); + + assert((s = libsimple_enaligned_wcsndup(1, L"hello", 2, 5))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 6 * sizeof(wchar_t)); + assert(info->alignment == 2); + assert(!info->zeroed); + } + assert(!wmemcmp(s, L"hello", 6)); + free(s); + + assert((s = libsimple_ealigned_wcsndup(L"test", 8, 4))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 5 * sizeof(wchar_t) + (8 - 5 * sizeof(wchar_t) % 8) % 8); + assert(info->alignment == 8); + assert(!info->zeroed); + } + assert(!wmemcmp(s, L"test", 5)); + free(s); + + assert((s = libsimple_enaligned_wcsndup(1, L"hello", 2, 4))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 5 * sizeof(wchar_t)); + assert(info->alignment == 2); + assert(!info->zeroed); + } + assert(!wmemcmp(s, L"hell", 5)); + free(s); + + if (have_custom_malloc()) { + alloc_fail_in = 1; + assert_exit_ptr(libsimple_enaligned_wcsndup(44, L"hello", 2, 10)); + assert(exit_status == 44); + assert_stderr("%s: aligned_wcsndup: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + + libsimple_default_failure_exit = 55; + alloc_fail_in = 1; + assert_exit_ptr(libsimple_ealigned_wcsndup(L"test", 8, 10)); + assert(exit_status == 55); + assert_stderr("%s: aligned_wcsndup: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + libsimple_default_failure_exit = 1; + } + return 0; } diff --git a/enaligned_wmemdup.c b/enaligned_wmemdup.c index e55e863..ad36238 100644 --- a/enaligned_wmemdup.c +++ b/enaligned_wmemdup.c @@ -4,7 +4,7 @@ wchar_t * -libsimple_enaligned_wmemdup(int status, const wchar_t *s, size_t alignment, size_t n) /* TOOD test */ +libsimple_enaligned_wmemdup(int status, const wchar_t *s, size_t alignment, size_t n) { void *ret = aligned_wmemdup(s, alignment, n); if (!ret) @@ -19,6 +19,45 @@ libsimple_enaligned_wmemdup(int status, const wchar_t *s, size_t alignment, size int main(void) { + struct allocinfo *info; + void *s; + + assert((s = libsimple_enaligned_wmemdup(1, L"hello", 2, 5))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 5 * sizeof(wchar_t)); + assert(info->alignment == 2); + assert(!info->zeroed); + } + assert(!wmemcmp(s, L"hello", 5)); + free(s); + + assert((s = libsimple_ealigned_wmemdup(L"test", 8, 5))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 5 * sizeof(wchar_t) + (8 - 5 * sizeof(wchar_t) % 8) % 8); + assert(info->alignment == 8); + assert(!info->zeroed); + } + assert(!wmemcmp(s, L"test", 5)); + free(s); + + if (have_custom_malloc()) { + alloc_fail_in = 1; + assert_exit_ptr(libsimple_enaligned_wmemdup(44, L"hello", 2, 2)); + assert(exit_status == 44); + assert_stderr("%s: aligned_wmemdup: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + + libsimple_default_failure_exit = 55; + alloc_fail_in = 1; + assert_exit_ptr(libsimple_ealigned_wmemdup(L"test", 8, 2)); + assert(exit_status == 55); + assert_stderr("%s: aligned_wmemdup: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + libsimple_default_failure_exit = 1; + } + return 0; } diff --git a/enreallocarray.c b/enreallocarray.c index c988994..c208626 100644 --- a/enreallocarray.c +++ b/enreallocarray.c @@ -4,7 +4,7 @@ void * -libsimple_enreallocarray(int status, void *ptr, size_t n, size_t m) /* TODO test */ +libsimple_enreallocarray(int status, void *ptr, size_t n, size_t m) { void *ret = reallocarray(ptr, n, m); if (!ret) @@ -19,6 +19,113 @@ libsimple_enreallocarray(int status, void *ptr, size_t n, size_t m) /* TODO test int main(void) { + struct allocinfo *info; + void *ptr, *old; + + assert((ptr = libsimple_enreallocarray(1, NULL, 5, 3))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 15); + assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + info->refcount += 1; + } + stpcpy(ptr, "test"); + assert((ptr = libsimple_enreallocarray(1, old = ptr, 10, 2))); + assert(!strcmp(ptr, "test")); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 20); + assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + assert(ptr != old); + free(old); + } + free(ptr); + + assert((ptr = libsimple_ereallocarray(NULL, 1, 5))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 5); + assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + info->refcount += 1; + } + stpcpy(ptr, "test"); + assert((ptr = libsimple_ereallocarray(old = ptr, 10, 10))); + assert(!strcmp(ptr, "test")); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 100); + assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + assert(ptr != old); + free(old); + } + free(ptr); + + assert((ptr = libsimple_reallocarray(NULL, 1, 5))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 5); + assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + info->refcount += 1; + } + stpcpy(ptr, "test"); + assert((ptr = libsimple_reallocarray(old = ptr, 10, 10))); + assert(!strcmp(ptr, "test")); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 100); + assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + assert(ptr != old); + free(old); + } + free(ptr); + + if (have_custom_malloc()) { + alloc_fail_in = 1; + assert_exit_ptr(libsimple_enreallocarray(2, NULL, 1, 1)); + assert(exit_status == 2); + assert_stderr("%s: reallocarray: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + + libsimple_default_failure_exit = 104; + alloc_fail_in = 1; + assert_exit_ptr(libsimple_ereallocarray(NULL, 1, 1)); + assert(exit_status == 104); + assert_stderr("%s: reallocarray: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + libsimple_default_failure_exit = 1; + + alloc_fail_in = 1; + assert(!libsimple_reallocarray(NULL, 1, 1) && errno == ENOMEM); + assert(!alloc_fail_in); + } + +#if defined(__GNUC__) && !defined(__clang) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Walloc-size-larger-than=" +#endif + + assert_exit_ptr(libsimple_enreallocarray(3, NULL, SIZE_MAX, SIZE_MAX)); + assert(exit_status == 3); + assert_stderr("%s: reallocarray: %s\n", argv0, strerror(ENOMEM)); + + libsimple_default_failure_exit = 4; + assert_exit_ptr(libsimple_ereallocarray(NULL, SIZE_MAX, SIZE_MAX)); + assert(exit_status == 4); + assert_stderr("%s: reallocarray: %s\n", argv0, strerror(ENOMEM)); + libsimple_default_failure_exit = 1; + + assert(!libsimple_reallocarray(NULL, SIZE_MAX, SIZE_MAX) && errno == ENOMEM); + +#if defined(__GNUC__) && !defined(__clang) +# pragma GCC diagnostic pop +#endif + return 0; } diff --git a/enwcsdup.c b/enwcsdup.c index d9edbb0..1fa27c0 100644 --- a/enwcsdup.c +++ b/enwcsdup.c @@ -4,7 +4,7 @@ wchar_t * -libsimple_enwcsdup(int status, const wchar_t *s) /* TODO test */ +libsimple_enwcsdup(int status, const wchar_t *s) { size_t n = wcslen(s) + 1, size; wchar_t *ret; @@ -26,6 +26,45 @@ libsimple_enwcsdup(int status, const wchar_t *s) /* TODO test */ int main(void) { + struct allocinfo *info; + wchar_t *s; + + assert((s = libsimple_enwcsdup(1, L"hello"))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 6 * sizeof(wchar_t)); + assert(info->alignment == _Alignof(wchar_t)); + assert(!info->zeroed); + } + assert(!wcscmp(s, L"hello")); + free(s); + + assert((s = libsimple_ewcsdup(L"test"))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 5 * sizeof(wchar_t)); + assert(info->alignment == _Alignof(wchar_t)); + assert(!info->zeroed); + } + assert(!wcscmp(s, L"test")); + free(s); + + if (have_custom_malloc()) { + alloc_fail_in = 1; + assert_exit_ptr(libsimple_enwcsdup(18, L"hello")); + assert(exit_status == 18); + assert_stderr("%s: wcsdup: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + + libsimple_default_failure_exit = 5; + alloc_fail_in = 1; + assert_exit_ptr(libsimple_ewcsdup(L"test")); + assert(exit_status == 5); + assert_stderr("%s: wcsdup: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + libsimple_default_failure_exit = 1; + } + return 0; } diff --git a/enwcsndup.c b/enwcsndup.c index f08da34..105542c 100644 --- a/enwcsndup.c +++ b/enwcsndup.c @@ -4,7 +4,7 @@ wchar_t * -libsimple_enwcsndup(int status, const wchar_t *s, size_t n) /* TODO test */ +libsimple_enwcsndup(int status, const wchar_t *s, size_t n) { wchar_t *ret = libsimple_wcsndup(s, n); if (!ret) @@ -19,6 +19,113 @@ libsimple_enwcsndup(int status, const wchar_t *s, size_t n) /* TODO test */ int main(void) { + struct allocinfo *info; + wchar_t *s; + + assert((s = libsimple_enwcsndup(1, L"hello", 10))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 6 * sizeof(wchar_t)); + assert(info->alignment == _Alignof(wchar_t)); + assert(!info->zeroed); + } + assert(!wcscmp(s, L"hello")); + free(s); + + assert((s = libsimple_ewcsndup(L"test", 10))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 5 * sizeof(wchar_t)); + assert(info->alignment == _Alignof(wchar_t)); + assert(!info->zeroed); + } + assert(!wcscmp(s, L"test")); + free(s); + + assert((s = libsimple_enwcsndup(1, L"hello", 2))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 3 * sizeof(wchar_t)); + assert(info->alignment == _Alignof(wchar_t)); + assert(!info->zeroed); + } + assert(!wcscmp(s, L"he")); + free(s); + + assert((s = libsimple_ewcsndup(L"test", 3))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 4 * sizeof(wchar_t)); + assert(info->alignment == _Alignof(wchar_t)); + assert(!info->zeroed); + } + assert(!wcscmp(s, L"tes")); + free(s); + + assert((s = libsimple_enwcsndup(1, L"hello", 0))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 1 * sizeof(wchar_t)); + assert(info->alignment == _Alignof(wchar_t)); + assert(!info->zeroed); + } + assert(!wcscmp(s, L"")); + free(s); + + assert((s = libsimple_ewcsndup(L"test", 0))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 1 * sizeof(wchar_t)); + assert(info->alignment == _Alignof(wchar_t)); + assert(!info->zeroed); + } + assert(!wcscmp(s, L"")); + free(s); + + if (have_custom_malloc()) { + alloc_fail_in = 1; + assert_exit_ptr(libsimple_enwcsndup(24, L"hello", 10)); + assert(exit_status == 24); + assert_stderr("%s: wcsndup: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + + libsimple_default_failure_exit = 25; + alloc_fail_in = 1; + assert_exit_ptr(libsimple_ewcsndup(L"test", 10)); + assert(exit_status == 25); + assert_stderr("%s: wcsndup: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + libsimple_default_failure_exit = 1; + + alloc_fail_in = 1; + assert_exit_ptr(libsimple_enwcsndup(26, L"hello", 1)); + assert(exit_status == 26); + assert_stderr("%s: wcsndup: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + + libsimple_default_failure_exit = 27; + alloc_fail_in = 1; + assert_exit_ptr(libsimple_ewcsndup(L"test", 2)); + assert(exit_status == 27); + assert_stderr("%s: wcsndup: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + libsimple_default_failure_exit = 1; + + alloc_fail_in = 1; + assert_exit_ptr(libsimple_enwcsndup(28, L"hello", 0)); + assert(exit_status == 28); + assert_stderr("%s: wcsndup: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + + libsimple_default_failure_exit = 29; + alloc_fail_in = 1; + assert_exit_ptr(libsimple_ewcsndup(L"test", 0)); + assert(exit_status == 29); + assert_stderr("%s: wcsndup: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + libsimple_default_failure_exit = 1; + } + return 0; } diff --git a/enwmemdup.c b/enwmemdup.c index fb8c8dc..243c99e 100644 --- a/enwmemdup.c +++ b/enwmemdup.c @@ -4,7 +4,7 @@ wchar_t * -libsimple_enwmemdup(int status, const wchar_t *s, size_t n) /* TODO test */ +libsimple_enwmemdup(int status, const wchar_t *s, size_t n) { wchar_t *ret = libsimple_wmemdup(s, n); if (!ret) @@ -19,6 +19,53 @@ libsimple_enwmemdup(int status, const wchar_t *s, size_t n) /* TODO test */ int main(void) { + struct allocinfo *info; + wchar_t *s; + + assert((s = libsimple_enwmemdup(1, L"hello", 5))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 5 * sizeof(wchar_t)); + assert(!info->zeroed); + } + assert(!wmemcmp(s, L"hello", 5)); + free(s); + + assert((s = libsimple_ewmemdup(L"test", 5))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 5 * sizeof(wchar_t)); + assert(!info->zeroed); + } + assert(!wmemcmp(s, L"test", 5)); + free(s); + + if (have_custom_malloc()) { + alloc_fail_in = 1; + assert_exit_ptr(libsimple_enwmemdup(44, L"hello", 2)); + assert(exit_status == 44); + assert_stderr("%s: wmemdup: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + + libsimple_default_failure_exit = 55; + alloc_fail_in = 1; + assert_exit_ptr(libsimple_ewmemdup(L"test", 2)); + assert(exit_status == 55); + assert_stderr("%s: wmemdup: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + libsimple_default_failure_exit = 1; + + assert_exit_ptr(libsimple_enwmemdup(41, NULL, SSIZE_MAX)); + assert(exit_status == 41); + assert_stderr("%s: wmemdup: %s\n", argv0, strerror(ENOMEM)); + + libsimple_default_failure_exit = 51; + assert_exit_ptr(libsimple_ewmemdup(NULL, SSIZE_MAX)); + assert(exit_status == 51); + assert_stderr("%s: wmemdup: %s\n", argv0, strerror(ENOMEM)); + libsimple_default_failure_exit = 1; + } + return 0; } diff --git a/libsimple.c b/libsimple.c index 4ef6ec2..a2ae4bc 100644 --- a/libsimple.c +++ b/libsimple.c @@ -6,27 +6,6 @@ #else #include "test.h" -static size_t -gcd(size_t u, size_t v) -{ - size_t t; - int shift = 0; - /* Not needed because u>0, v>0: if (!(u | v)) return u + v; */ - while (!((u | v) & 1)) u >>= 1, v >>= 1, shift++; - while (!(u & 1)) u >>= 1; - do { - while (!(v & 1)) v >>= 1; - if (u > v) t = u, u = v, v = t; - } while (v -= u); - return u << shift; -} - -static size_t -lcm(size_t u, size_t v) -{ - return u / gcd(u, v) * v; -} - static int test_timespec(double d, time_t sec, long int nsec, double rd, const char *s, const char *ss) { @@ -113,18 +92,13 @@ main(void) struct timespec ts, ts1, ts2; struct timeval tv1, tv2; const char *cs; + const wchar_t *cws; char buf[1024], *s; + wchar_t *ws; int intarray[10]; size_t i, j, n; - size_t pagesize, cacheline; - - pagesize = (size_t)sysconf(_SC_PAGESIZE); - -#ifdef _SC_LEVEL1_DCACHE_LINESIZE - cacheline = (size_t)sysconf(_SC_LEVEL1_DCACHE_LINESIZE); -#else - cacheline = 64; -#endif + DEFINE_PAGESIZE; + DEFINE_CACHELINE; assert(libsimple_default_failure_exit == 1); @@ -734,6 +708,7 @@ main(void) s = libsimple_memdupa(cs, n); assert(s); assert(s != cs); + assert(!((uintptr_t)s % _Alignof(max_align_t))); assert(!memcmp(s, cs, n)); } #else @@ -743,14 +718,253 @@ main(void) #ifdef libsimple_aligned_memdupa cs = "xyz"; for (n = 1; n < 4; n++) { - s = libsimple_aligned_memdupa(cs, 4 + i, n); + for (i = 1; i < 5; i++) { + s = libsimple_aligned_memdupa(cs, i, n); + assert(s); + assert(s != cs); + assert(!((uintptr_t)s % i)); + assert(!memcmp(s, cs, n)); + } + } +#else + fprintf(stderr, "warning: libsimple_aligned_memdupa missing\n"); +#endif + +#ifdef libsimple_aligned_strdupa + for (i = 1; i < 5; i++) { + cs = ""; + s = libsimple_aligned_strdupa(cs, i); assert(s); assert(s != cs); - assert(!((uintptr_t)s % (4 + i))); - assert(!memcmp(s, cs, n)); + assert(!((uintptr_t)s % i)); + assert(!strcmp(s, cs)); + + cs = "xyz"; + s = libsimple_aligned_strdupa(cs, i); + assert(s); + assert(s != cs); + assert(!((uintptr_t)s % i)); + assert(!strcmp(s, cs)); } #else - fprintf(stderr, "warning: libsimple_aligned_memdupa missing\n"); + fprintf(stderr, "warning: libsimple_aligned_strdupa missing\n"); +#endif + +#ifdef libsimple_aligned_strndupa + for (i = 1; i < 5; i++) { + cs = ""; + s = libsimple_aligned_strndupa(cs, i, 5); + assert(s); + assert(s != cs); + assert(!((uintptr_t)s % i)); + assert(!strcmp(s, "")); + + cs = "xyz"; + + s = libsimple_aligned_strndupa(cs, i, 5); + assert(s); + assert(s != cs); + assert(!((uintptr_t)s % i)); + assert(!strcmp(s, "xyz")); + + s = libsimple_aligned_strndupa(cs, i, 4); + assert(s); + assert(s != cs); + assert(!((uintptr_t)s % i)); + assert(!strcmp(s, "xyz")); + + s = libsimple_aligned_strndupa(cs, i, 3); + assert(s); + assert(s != cs); + assert(!((uintptr_t)s % i)); + assert(!strcmp(s, "xyz")); + + s = libsimple_aligned_strndupa(cs, i, 2); + assert(s); + assert(s != cs); + assert(!((uintptr_t)s % i)); + assert(!strcmp(s, "xy")); + + s = libsimple_aligned_strndupa(cs, i, 1); + assert(s); + assert(s != cs); + assert(!((uintptr_t)s % i)); + assert(!strcmp(s, "x")); + + s = libsimple_aligned_strndupa(cs, i, 0); + assert(s); + assert(s != cs); + assert(!((uintptr_t)s % i)); + assert(!strcmp(s, "")); + } +#else + fprintf(stderr, "warning: libsimple_aligned_strndupa missing\n"); +#endif + +#ifdef libsimple_wcsdupa + cws = L""; + ws = libsimple_wcsdupa(cws); + assert(ws); + assert(ws != cws); + assert(!((uintptr_t)ws % _Alignof(wchar_t))); + assert(!wcscmp(ws, cws)); + + cws = L"xyz"; + ws = libsimple_wcsdupa(cws); + assert(ws); + assert(ws != cws); + assert(!((uintptr_t)ws % _Alignof(wchar_t))); + assert(!wcscmp(ws, cws)); +#else + fprintf(stderr, "warning: libsimple_wcsdupa missing\n"); +#endif + +#ifdef libsimple_wcsndupa + cws = L""; + ws = libsimple_wcsndupa(cws, 5); + assert(ws); + assert(ws != cws); + assert(!((uintptr_t)ws % _Alignof(wchar_t))); + assert(!wcscmp(ws, L"")); + + cws = L"xyz"; + + ws = libsimple_wcsndupa(cws, 5); + assert(ws); + assert(ws != cws); + assert(!((uintptr_t)ws % _Alignof(wchar_t))); + assert(!wcscmp(ws, L"xyz")); + + ws = libsimple_wcsndupa(cws, 4); + assert(ws); + assert(ws != cws); + assert(!((uintptr_t)ws % _Alignof(wchar_t))); + assert(!wcscmp(ws, L"xyz")); + + ws = libsimple_wcsndupa(cws, 3); + assert(ws); + assert(ws != cws); + assert(!((uintptr_t)ws % _Alignof(wchar_t))); + assert(!wcscmp(ws, L"xyz")); + + ws = libsimple_wcsndupa(cws, 2); + assert(ws); + assert(ws != cws); + assert(!((uintptr_t)ws % _Alignof(wchar_t))); + assert(!wcscmp(ws, L"xy")); + + ws = libsimple_wcsndupa(cws, 1); + assert(ws); + assert(ws != cws); + assert(!((uintptr_t)ws % _Alignof(wchar_t))); + assert(!wcscmp(ws, L"x")); + + ws = libsimple_wcsndupa(cws, 0); + assert(ws); + assert(ws != cws); + assert(!((uintptr_t)ws % _Alignof(wchar_t))); + assert(!wcscmp(ws, L"")); +#else + fprintf(stderr, "warning: libsimple_wcsndupa missing\n"); +#endif + +#ifdef libsimple_wmemdupa + cws = L"xyz"; + for (n = 1; n < 4; n++) { + ws = libsimple_wmemdupa(cws, n); + assert(ws); + assert(ws != cws); + assert(!((uintptr_t)ws % _Alignof(wchar_t))); + assert(!wmemcmp(ws, cws, n)); + } +#else + fprintf(stderr, "warning: libsimple_wmemdupa missing\n"); +#endif + +#ifdef libsimple_aligned_wmemdupa + cws = L"xyz"; + for (n = 1; n < 4; n++) { + for (i = 1; i < 5; i++) { + ws = libsimple_aligned_wmemdupa(cws, i, n); + assert(ws); + assert(ws != cws); + assert(!((uintptr_t)ws % i)); + assert(!wmemcmp(ws, cws, n)); + } + } +#else + fprintf(stderr, "warning: libsimple_aligned_wmemdupa missing\n"); +#endif + +#ifdef libsimple_aligned_wcsdupa + for (i = 1; i < 5; i++) { + cws = L""; + ws = libsimple_aligned_wcsdupa(cws, i); + assert(ws); + assert(ws != cws); + assert(!((uintptr_t)ws % i)); + assert(!wcscmp(ws, cws)); + + cws = L"xyz"; + ws = libsimple_aligned_wcsdupa(cws, i); + assert(ws); + assert(ws != cws); + assert(!((uintptr_t)ws % i)); + assert(!wcscmp(ws, cws)); + } +#else + fprintf(stderr, "warning: libsimple_aligned_wcsdupa missing\n"); +#endif + +#ifdef libsimple_aligned_wcsndupa + for (i = 1; i < 5; i++) { + cws = L""; + ws = libsimple_aligned_wcsndupa(cws, i, 5); + assert(ws); + assert(ws != cws); + assert(!((uintptr_t)ws % i)); + assert(!wcscmp(ws, L"")); + + cws = L"xyz"; + + ws = libsimple_aligned_wcsndupa(cws, i, 5); + assert(ws); + assert(ws != cws); + assert(!((uintptr_t)ws % i)); + assert(!wcscmp(ws, L"xyz")); + + ws = libsimple_aligned_wcsndupa(cws, i, 4); + assert(ws); + assert(ws != cws); + assert(!((uintptr_t)ws % i)); + assert(!wcscmp(ws, L"xyz")); + + ws = libsimple_aligned_wcsndupa(cws, i, 3); + assert(ws); + assert(ws != cws); + assert(!((uintptr_t)ws % i)); + assert(!wcscmp(ws, L"xyz")); + + ws = libsimple_aligned_wcsndupa(cws, i, 2); + assert(ws); + assert(ws != cws); + assert(!((uintptr_t)ws % i)); + assert(!wcscmp(ws, L"xy")); + + ws = libsimple_aligned_wcsndupa(cws, i, 1); + assert(ws); + assert(ws != cws); + assert(!((uintptr_t)ws % i)); + assert(!wcscmp(ws, L"x")); + + ws = libsimple_aligned_wcsndupa(cws, i, 0); + assert(ws); + assert(ws != cws); + assert(!((uintptr_t)ws % i)); + assert(!wcscmp(ws, L"")); + } +#else + fprintf(stderr, "warning: libsimple_aligned_wcsndupa missing\n"); #endif unsetenv("X"); @@ -1049,14 +1263,6 @@ main(void) tv2.tv_sec = 1, tv2.tv_usec = 0L; assert(libsimple_cmptimeval(&tv1, &tv2) == -1); -#define ASSERT_ALIGNMENT(INFO, ALIGN)\ - do {\ - assert((INFO)->alignment <= lcm(cacheline, ALIGN));\ - assert(!((INFO)->alignment % (ALIGN)));\ - if ((cacheline - (ALIGN) % cacheline) % cacheline + (INFO)->size % (ALIGN) > cacheline)\ - assert(!((INFO)->alignment % cacheline));\ - } while (0) - assert((ptr = libsimple_mallocz(0, 11))); if (have_custom_malloc()) { assert((info = get_allocinfo(ptr))); diff --git a/libsimple/aligned_strdup.h b/libsimple/aligned_strdup.h index 267c03e..07b7edf 100644 --- a/libsimple/aligned_strdup.h +++ b/libsimple/aligned_strdup.h @@ -9,7 +9,7 @@ * @return :char * Duplicate of `s` with automatic storage */ #if defined(__GNUC__) || defined(__clang__) -# define libsimple_aligned_strdupa(s, alignment) /* TODO test */\ +# define libsimple_aligned_strdupa(s, alignment)\ ({\ const char *__s = (s);\ size_t __n = strlen(__s) + 1;\ @@ -37,7 +37,7 @@ * @return Duplicate of `s`, `NULL` on failure */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __nonnull__, __warn_unused_result__))) -static inline char *libsimple_aligned_strdup(const char * __s, size_t __alignment) /* TODO test */ +static inline char *libsimple_aligned_strdup(const char * __s, size_t __alignment) { return libsimple_aligned_memdup(__s, __alignment, strlen(__s) + 1); } #ifndef aligned_strdup # define aligned_strdup libsimple_aligned_strdup diff --git a/libsimple/aligned_strndup.h b/libsimple/aligned_strndup.h index 51d50c8..16a3aac 100644 --- a/libsimple/aligned_strndup.h +++ b/libsimple/aligned_strndup.h @@ -10,7 +10,7 @@ * @return :char * Duplicate of `s` with automatic storage */ #if defined(__GNUC__) || defined(__clang__) -# define libsimple_aligned_strndupa(s, alignment, n) /* TODO test */\ +# define libsimple_aligned_strndupa(s, alignment, n)\ ({\ const char *__s = (s);\ size_t __n = strnlen(__s, n);\ diff --git a/libsimple/aligned_wcsdup.h b/libsimple/aligned_wcsdup.h index 8832c58..527d210 100644 --- a/libsimple/aligned_wcsdup.h +++ b/libsimple/aligned_wcsdup.h @@ -9,13 +9,13 @@ * @return :wchar_t * Duplicate of `s` with automatic storage */ #if defined(__GNUC__) || defined(__clang__) -# define libsimple_aligned_wcsdupa(s, alignment) /* TODO test */\ +# define libsimple_aligned_wcsdupa(s, alignment)\ ({\ const wchar_t *__s = (s);\ size_t __n = wcslen(__s) + 1;\ size_t __a = (alignment);\ uintptr_t __misalignment;\ - char *__r;\ + wchar_t *__r;\ __a += !__a;\ __r = alloca(__n * sizeof(wchar_t) + (__a - 1));\ __misalignment = (uintptr_t)__r % (uintptr_t)__a;\ @@ -37,7 +37,7 @@ * @return Duplicate of `s`, `NULL` on failure */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __nonnull__, __warn_unused_result__))) -static inline wchar_t *libsimple_aligned_wcsdup(const wchar_t * __s, size_t __alignment) /* TODO test */ +static inline wchar_t *libsimple_aligned_wcsdup(const wchar_t * __s, size_t __alignment) { return libsimple_aligned_wmemdup(__s, __alignment, wcslen(__s) + 1); } #ifndef aligned_wcsdup # define aligned_wcsdup libsimple_aligned_wcsdup @@ -67,7 +67,7 @@ wchar_t *libsimple_enaligned_wcsdup(int, const wchar_t *, size_t); * @return Duplicate of `s` */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __nonnull__, __warn_unused_result__, __returns_nonnull__))) -static inline wchar_t *libsimple_ealigned_wcsdup(const wchar_t *__s, size_t __alignment) /* TODO test */ +static inline wchar_t *libsimple_ealigned_wcsdup(const wchar_t *__s, size_t __alignment) { return libsimple_enaligned_wcsdup(libsimple_default_failure_exit, __s, __alignment); } #ifndef ealigned_wcsdup # define ealigned_wcsdup libsimple_ealigned_wcsdup diff --git a/libsimple/aligned_wcsndup.h b/libsimple/aligned_wcsndup.h index 5f3f1e4..015d1dc 100644 --- a/libsimple/aligned_wcsndup.h +++ b/libsimple/aligned_wcsndup.h @@ -10,7 +10,7 @@ * @return :wchar_t * Duplicate of `s` with automatic storage */ #if defined(__GNUC__) || defined(__clang__) -# define libsimple_aligned_wcsndupa(s, alignment, n) /* TODO test */\ +# define libsimple_aligned_wcsndupa(s, alignment, n)\ ({\ const wchar_t *__s = (s);\ size_t __n = wcsnlen(__s, n);\ @@ -72,7 +72,7 @@ wchar_t *libsimple_enaligned_wcsndup(int, const wchar_t *, size_t, size_t); * @return Duplicate of `s` */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __nonnull__, __warn_unused_result__, __returns_nonnull__))) -static inline wchar_t *libsimple_ealigned_wcsndup(const wchar_t *__s, size_t __alignment, size_t __n) /* TODO test */ +static inline wchar_t *libsimple_ealigned_wcsndup(const wchar_t *__s, size_t __alignment, size_t __n) { return libsimple_enaligned_wcsndup(libsimple_default_failure_exit, __s, __alignment, __n); } #ifndef ealigned_wcsndup # define ealigned_wcsndup libsimple_ealigned_wcsndup diff --git a/libsimple/aligned_wmemdup.h b/libsimple/aligned_wmemdup.h index bac1d0a..63a9d40 100644 --- a/libsimple/aligned_wmemdup.h +++ b/libsimple/aligned_wmemdup.h @@ -10,14 +10,14 @@ * @return :wchar_t * Duplicate of `s` with automatic storage */ #if defined(__GNUC__) || defined(__clang__) -# define libsimple_aligned_wmemdupa(s, alignment, n) /* TODO test */\ +# define libsimple_aligned_wmemdupa(s, alignment, n)\ ({\ const wchar_t *__s = (s);\ size_t __n = (n);\ size_t __a = (alignment);\ size_t __size;\ uintptr_t __misalignment;\ - char *__r;\ + wchar_t *__r;\ __a += !__a;\ __size = __n * sizeof(wchar_t) + (__a - 1);\ __r = alloca(__size + !__size);\ @@ -72,7 +72,7 @@ wchar_t *libsimple_enaligned_wmemdup(int, const wchar_t *, size_t, size_t); * @return Duplicate of `s` */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __alloc_size__(3), __warn_unused_result__, __returns_nonnull__))) -static inline wchar_t *libsimple_ealigned_wmemdup(const wchar_t *__s, size_t __alignment, size_t __n) /* TODO test */ +static inline wchar_t *libsimple_ealigned_wmemdup(const wchar_t *__s, size_t __alignment, size_t __n) { return libsimple_enaligned_wmemdup(libsimple_default_failure_exit, __s, __alignment, __n); } #ifndef ealigned_wmemdup # define ealigned_wmemdup libsimple_ealigned_wmemdup diff --git a/libsimple/realloc.h b/libsimple/realloc.h index f976556..b02c08a 100644 --- a/libsimple/realloc.h +++ b/libsimple/realloc.h @@ -347,7 +347,7 @@ libsimple_reallocf(void *__ptr, size_t __n) /* TODO test */ */ _LIBSIMPLE_GCC_ONLY(__attribute__((__alloc_size__(2, 3), __warn_unused_result__))) static inline void * -libsimple_reallocarray(void *__ptr, size_t __n, size_t __m) /* TODO test */ +libsimple_reallocarray(void *__ptr, size_t __n, size_t __m) { if (LIBSIMPLE_UMUL_OVERFLOW(__n, __m, &__n, SIZE_MAX)) { errno = ENOMEM; @@ -420,7 +420,7 @@ void *libsimple_enreallocarray(int, void *, size_t, size_t); * `alignof(max_align_t)` */ _LIBSIMPLE_GCC_ONLY(__attribute__((__alloc_size__(2, 3), __warn_unused_result__, __returns_nonnull__))) -static inline void *libsimple_ereallocarray(void *__ptr, size_t __n, size_t __m) /* TODO test */ +static inline void *libsimple_ereallocarray(void *__ptr, size_t __n, size_t __m) { return libsimple_enreallocarray(libsimple_default_failure_exit, __ptr, __n, __m); } #ifndef ereallocarray # define ereallocarray libsimple_ereallocarray diff --git a/libsimple/wcsndup.h b/libsimple/wcsndup.h index 664294d..31e9118 100644 --- a/libsimple/wcsndup.h +++ b/libsimple/wcsndup.h @@ -9,7 +9,7 @@ * @return :wchar_t * Duplicate of `s` with automatic storage */ #if defined(__GNUC__) || defined(__clang__) -# define libsimple_wcsndupa(s, n) /* TODO test */\ +# define libsimple_wcsndupa(s, n)\ ({\ const wchar_t *__s = (s);\ size_t __n = wcsnlen(__s, n);\ @@ -33,7 +33,7 @@ * @return Duplicate of `s` */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, _libsimple_assume_aligned_as(wchar_t), __nonnull__, - __warn_unused_result__, __returns_nonnull__))) + __warn_unused_result__))) wchar_t *libsimple_wcsndup(const wchar_t *, size_t); #ifndef wcsndup # define wcsndup libsimple_wcsndup @@ -65,7 +65,7 @@ wchar_t *libsimple_enwcsndup(int, const wchar_t *, size_t); */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, _libsimple_assume_aligned_as(wchar_t), __nonnull__, __warn_unused_result__, __returns_nonnull__))) -static inline wchar_t *libsimple_ewcsndup(const wchar_t *__s, size_t __n) /* TODO test */ +static inline wchar_t *libsimple_ewcsndup(const wchar_t *__s, size_t __n) { return libsimple_enwcsndup(libsimple_default_failure_exit, __s, __n); } #ifndef ewcsndup # define ewcsndup libsimple_ewcsndup diff --git a/libsimple/wmemdup.h b/libsimple/wmemdup.h index 85bfea4..2c1f899 100644 --- a/libsimple/wmemdup.h +++ b/libsimple/wmemdup.h @@ -9,7 +9,7 @@ * @return :wchar_t * Duplicate of `s` with automatic storage */ #if defined(__GNUC__) || defined(__clang__) -# define libsimple_wmemdupa(s, n) /* TODO test */\ +# define libsimple_wmemdupa(s, n)\ ({\ const wchar_t *__s = (s);\ size_t __n = (n);\ @@ -61,7 +61,7 @@ wchar_t *libsimple_enwmemdup(int, const wchar_t *, size_t); */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, _libsimple_assume_aligned_as(wchar_t), __alloc_size__(2), __warn_unused_result__, __returns_nonnull__))) -static inline wchar_t *libsimple_ewmemdup(const wchar_t *__s, size_t __n) /* TODO test */ +static inline wchar_t *libsimple_ewmemdup(const wchar_t *__s, size_t __n) { return libsimple_enwmemdup(libsimple_default_failure_exit, __s, __n); } #ifndef ewmemdup # define ewmemdup libsimple_ewmemdup diff --git a/test.c b/test.c index 01100e8..5297987 100644 --- a/test.c +++ b/test.c @@ -229,11 +229,13 @@ strndup(const char *s, size_t n) } +#if 0 void * memdup(const void *s, size_t size) { return libsimple_memdup(s, size); } +#endif wchar_t * @@ -250,6 +252,7 @@ wcsdup(const wchar_t *s) } +#if 0 wchar_t * wcsndup(const wchar_t *s, size_t n) { @@ -262,6 +265,7 @@ wmemdup(const wchar_t *s, size_t n) { return libsimple_wmemdup(s, n); } +#endif void diff --git a/test.h b/test.h index fe229ef..d8ac2d4 100644 --- a/test.h +++ b/test.h @@ -95,3 +95,42 @@ test_fprintf(FILE *restrict stream, const char *restrict format, ...) return test_vfprintf(stream, format, ap); va_end(ap); } + + + +static size_t +gcd(size_t u, size_t v) +{ + size_t t; + int shift = 0; + /* Not needed because u>0, v>0: if (!(u | v)) return u + v; */ + while (!((u | v) & 1)) u >>= 1, v >>= 1, shift++; + while (!(u & 1)) u >>= 1; + do { + while (!(v & 1)) v >>= 1; + if (u > v) t = u, u = v, v = t; + } while (v -= u); + return u << shift; +} + +static inline size_t +lcm(size_t u, size_t v) +{ + return u / gcd(u, v) * v; +} + +#define ASSERT_ALIGNMENT(INFO, ALIGN)\ + do {\ + assert((INFO)->alignment <= lcm(cacheline, ALIGN));\ + assert(!((INFO)->alignment % (ALIGN)));\ + if ((cacheline - (ALIGN) % cacheline) % cacheline + (INFO)->size % (ALIGN) > cacheline)\ + assert(!((INFO)->alignment % cacheline));\ + } while (0) + +#define DEFINE_PAGESIZE size_t pagesize = (size_t)sysconf(_SC_PAGESIZE) + +#ifdef _SC_LEVEL1_DCACHE_LINESIZ +#define DEFINE_CACHELINE size_t cacheline = (size_t)sysconf(_SC_LEVEL1_DCACHE_LINESIZE) +#else +#define DEFINE_CACHELINE size_t cacheline = 64 +#endif diff --git a/wcsndup.c b/wcsndup.c index 5b8f7cc..5621084 100644 --- a/wcsndup.c +++ b/wcsndup.c @@ -4,15 +4,12 @@ wchar_t * -libsimple_wcsndup(const wchar_t *s, size_t n) /* TODO test */ +libsimple_wcsndup(const wchar_t *s, size_t n) { size_t size; wchar_t *ret; n = wcsnlen(s, n); - if (LIBSIMPLE_UMUL_OVERFLOW_NONZERO(n + 1, sizeof(wchar_t), &size, SIZE_MAX)) { - errno = ENOMEM; - return NULL; - } + size = (n + 1) * sizeof(wchar_t); ret = aligned_alloc(_Alignof(wchar_t), size); if (!ret) return NULL; @@ -28,6 +25,81 @@ libsimple_wcsndup(const wchar_t *s, size_t n) /* TODO test */ int main(void) { + struct allocinfo *info; + const wchar_t *s = L"test"; + wchar_t *p; + + p = libsimple_wcsndup(s, SIZE_MAX); + assert(p); + assert(p != s); + assert(!((uintptr_t)s % _Alignof(wchar_t))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(p))); + assert(info->size == 5 * sizeof(wchar_t)); + assert(info->alignment == _Alignof(wchar_t)); + } + assert(!wmemcmp(p, s, 5)); + wmemset(p, 0, 5); + assert(!wmemcmp(s, L"test", 5)); + free(p); + + p = libsimple_wcsndup(s, 10); + assert(p); + assert(p != s); + assert(!((uintptr_t)s % _Alignof(wchar_t))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(p))); + assert(info->size == 5 * sizeof(wchar_t)); + assert(info->alignment == _Alignof(wchar_t)); + } + assert(!wmemcmp(p, s, 5)); + wmemset(p, 0, 5); + assert(!wmemcmp(s, L"test", 5)); + free(p); + + p = libsimple_wcsndup(s, 5); + assert(p); + assert(p != s); + assert(!((uintptr_t)s % _Alignof(wchar_t))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(p))); + assert(info->size == 5 * sizeof(wchar_t)); + assert(info->alignment == _Alignof(wchar_t)); + } + assert(!wmemcmp(p, s, 5)); + wmemset(p, 0, 5); + assert(!wmemcmp(s, L"test", 5)); + free(p); + + p = libsimple_wcsndup(s, 4); + assert(p); + assert(p != s); + assert(!((uintptr_t)s % _Alignof(wchar_t))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(p))); + assert(info->size == 5 * sizeof(wchar_t)); + assert(info->alignment == _Alignof(wchar_t)); + } + assert(!wmemcmp(p, s, 5)); + wmemset(p, 0, 5); + assert(!wmemcmp(s, L"test", 5)); + free(p); + + p = libsimple_wcsndup(s, 2); + assert(p); + assert(p != s); + assert(!((uintptr_t)s % _Alignof(wchar_t))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(p))); + assert(info->size == 3 * sizeof(wchar_t)); + assert(info->alignment == _Alignof(wchar_t)); + } + assert(!wmemcmp(p, s, 2)); + assert(!p[2]); + wmemset(p, 0, 3); + assert(!wmemcmp(s, L"test", 5)); + free(p); + return 0; } diff --git a/wmemdup.c b/wmemdup.c index 239ae7d..2e9cc1c 100644 --- a/wmemdup.c +++ b/wmemdup.c @@ -4,7 +4,7 @@ wchar_t * -libsimple_wmemdup(const wchar_t *s, size_t n) /* TODO test */ +libsimple_wmemdup(const wchar_t *s, size_t n) { wchar_t *ret; size_t size; @@ -25,6 +25,27 @@ libsimple_wmemdup(const wchar_t *s, size_t n) /* TODO test */ int main(void) { + struct allocinfo *info; + const wchar_t *s = L"test"; + wchar_t *p; + + p = libsimple_wmemdup(s, 5); + assert(p); + assert(p != s); + assert(!((uintptr_t)s % _Alignof(wchar_t))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(p))); + assert(info->size == 5 * sizeof(wchar_t)); + assert(info->alignment == _Alignof(wchar_t)); + } + assert(!wmemcmp(p, s, 5)); + wmemset(p, 0, 5); + assert(!wmemcmp(s, L"test", 5)); + free(p); + + errno = 0; + assert(!libsimple_wmemdup(NULL, SSIZE_MAX) && errno == ENOMEM); + return 0; } -- cgit v1.2.3-70-g09d2