aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile6
-rw-r--r--aligned_strndup.c81
-rw-r--r--aligned_wcsndup.c6
-rw-r--r--enaligned_realloc.c82
-rw-r--r--enaligned_reallocarray.c82
-rw-r--r--enaligned_strdup.c14
-rw-r--r--enaligned_strndup.c6
-rw-r--r--enaligned_wcsdup.c55
-rw-r--r--enaligned_wcsndup.c111
-rw-r--r--enaligned_wmemdup.c41
-rw-r--r--enreallocarray.c109
-rw-r--r--enwcsdup.c41
-rw-r--r--enwcsndup.c109
-rw-r--r--enwmemdup.c49
-rw-r--r--libsimple.c290
-rw-r--r--libsimple/aligned_strdup.h4
-rw-r--r--libsimple/aligned_strndup.h2
-rw-r--r--libsimple/aligned_wcsdup.h8
-rw-r--r--libsimple/aligned_wcsndup.h4
-rw-r--r--libsimple/aligned_wmemdup.h6
-rw-r--r--libsimple/realloc.h4
-rw-r--r--libsimple/wcsndup.h6
-rw-r--r--libsimple/wmemdup.h4
-rw-r--r--test.c4
-rw-r--r--test.h39
-rw-r--r--wcsndup.c82
-rw-r--r--wmemdup.c23
27 files changed, 1184 insertions, 84 deletions
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;
}