lib/, tests/: addsl(): Add addsl(), a variadic macro

Add a variadic macro addsl() that accepts an arbitrary number of
addends, instead of having specific versions like addsl2() or addsl3().

It is internally implemented by the addslN() function, which itself
calls addsl2().  addsl3() is now obsolete and thus removed.

Code should just call addsl().

Link: <https://github.com/shadow-maint/shadow/pull/882#discussion_r1437155212>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
This commit is contained in:
Alejandro Colomar
2024-01-16 16:58:18 +01:00
committed by Iker Pedrosa
parent 2e5fc4c90b
commit 2e56af1902
3 changed files with 58 additions and 33 deletions
+3 -1
View File
@@ -6,8 +6,10 @@
#include "adds.h"
#include <stddef.h>
extern inline long addsl2(long a, long b);
extern inline long addsl3(long a, long b, long c);
extern inline long addslN(size_t n, long addend[n]);
extern inline int cmpl(const void *p1, const void *p2);
+24 -10
View File
@@ -10,13 +10,22 @@
#include <errno.h>
#include <limits.h>
#include <stddef.h>
#include <stdlib.h>
#include "sizeof.h"
#define addsl(a, b, ...) \
({ \
long addend_[] = {a, b, __VA_ARGS__}; \
\
addslN(NITEMS(addend_), addend_); \
})
inline long addsl2(long a, long b);
inline long addsl3(long a, long b, long c);
inline long addslN(size_t n, long addend[n]);
inline int cmpl(const void *p1, const void *p2);
@@ -37,21 +46,26 @@ addsl2(long a, long b)
inline long
addsl3(long a, long b, long c)
addslN(size_t n, long addend[n])
{
int e;
long sum;
long n[3] = {a, b, c};
if (n == 0) {
errno = EDOM;
return 0;
}
e = errno;
qsort(n, NITEMS(n), sizeof(n[0]), cmpl);
while (n > 1) {
qsort(addend, n, sizeof(addend[0]), cmpl);
errno = 0;
sum = addsl(n[0], n[2]);
if (errno == EOVERFLOW)
return sum;
errno = 0;
addend[0] = addsl2(addend[0], addend[--n]);
if (errno == EOVERFLOW)
return addend[0];
}
errno = e;
return addsl(sum, n[1]);
return addend[0];
}
+31 -22
View File
@@ -19,6 +19,7 @@ static void test_addsl_2_overflow(void **state);
static void test_addsl_3_ok(void **state);
static void test_addsl_3_underflow(void **state);
static void test_addsl_3_overflow(void **state);
static void test_addsl_5_ok(void **state);
int
@@ -31,6 +32,7 @@ main(void)
cmocka_unit_test(test_addsl_3_ok),
cmocka_unit_test(test_addsl_3_underflow),
cmocka_unit_test(test_addsl_3_overflow),
cmocka_unit_test(test_addsl_5_ok),
};
return cmocka_run_group_tests(tests, NULL, NULL);
@@ -40,41 +42,41 @@ main(void)
static void
test_addsl_2_ok(void **state)
{
assert_true(addsl2(1, 3) == 1 + 3);
assert_true(addsl2(-4321, 7) == -4321 + 7);
assert_true(addsl2(1, 1) == 1 + 1);
assert_true(addsl2(-1, -2) == -1 - 2);
assert_true(addsl2(LONG_MAX, -1) == LONG_MAX - 1);
assert_true(addsl2(LONG_MIN, 1) == LONG_MIN + 1);
assert_true(addsl2(LONG_MIN, LONG_MAX) == LONG_MIN + LONG_MAX);
assert_true(addsl2(0, 0) == 0);
assert_true(addsl(1, 3) == 1 + 3);
assert_true(addsl(-4321, 7) == -4321 + 7);
assert_true(addsl(1, 1) == 1 + 1);
assert_true(addsl(-1, -2) == -1 - 2);
assert_true(addsl(LONG_MAX, -1) == LONG_MAX - 1);
assert_true(addsl(LONG_MIN, 1) == LONG_MIN + 1);
assert_true(addsl(LONG_MIN, LONG_MAX) == LONG_MIN + LONG_MAX);
assert_true(addsl(0, 0) == 0);
}
static void
test_addsl_2_underflow(void **state)
{
assert_true(addsl2(LONG_MIN, -1) == LONG_MIN);
assert_true(addsl2(LONG_MIN + 3, -7) == LONG_MIN);
assert_true(addsl2(LONG_MIN, LONG_MIN) == LONG_MIN);
assert_true(addsl(LONG_MIN, -1) == LONG_MIN);
assert_true(addsl(LONG_MIN + 3, -7) == LONG_MIN);
assert_true(addsl(LONG_MIN, LONG_MIN) == LONG_MIN);
}
static void
test_addsl_2_overflow(void **state)
{
assert_true(addsl2(LONG_MAX, 1) == LONG_MAX);
assert_true(addsl2(LONG_MAX - 3, 7) == LONG_MAX);
assert_true(addsl2(LONG_MAX, LONG_MAX) == LONG_MAX);
assert_true(addsl(LONG_MAX, 1) == LONG_MAX);
assert_true(addsl(LONG_MAX - 3, 7) == LONG_MAX);
assert_true(addsl(LONG_MAX, LONG_MAX) == LONG_MAX);
}
static void
test_addsl_3_ok(void **state)
{
assert_true(addsl3(1, 2, 3) == 1 + 2 + 3);
assert_true(addsl3(LONG_MIN, -3, 4) == LONG_MIN + 4 - 3);
assert_true(addsl3(LONG_MAX, LONG_MAX, LONG_MIN)
assert_true(addsl(1, 2, 3) == 1 + 2 + 3);
assert_true(addsl(LONG_MIN, -3, 4) == LONG_MIN + 4 - 3);
assert_true(addsl(LONG_MAX, LONG_MAX, LONG_MIN)
== LONG_MAX + LONG_MIN + LONG_MAX);
}
@@ -82,15 +84,22 @@ test_addsl_3_ok(void **state)
static void
test_addsl_3_underflow(void **state)
{
assert_true(addsl3(LONG_MIN, 2, -3) == LONG_MIN);
assert_true(addsl3(LONG_MIN, -1, 0) == LONG_MIN);
assert_true(addsl(LONG_MIN, 2, -3) == LONG_MIN);
assert_true(addsl(LONG_MIN, -1, 0) == LONG_MIN);
}
static void
test_addsl_3_overflow(void **state)
{
assert_true(addsl3(LONG_MAX, -1, 2) == LONG_MAX);
assert_true(addsl3(LONG_MAX, +1, 0) == LONG_MAX);
assert_true(addsl3(LONG_MAX, LONG_MAX, 0)== LONG_MAX);
assert_true(addsl(LONG_MAX, -1, 2) == LONG_MAX);
assert_true(addsl(LONG_MAX, +1, 0) == LONG_MAX);
assert_true(addsl(LONG_MAX, LONG_MAX, 0)== LONG_MAX);
}
static void
test_addsl_5_ok(void **state)
{
assert_true(addsl(LONG_MAX, LONG_MAX, LONG_MIN, LONG_MIN, 44) == 42);
}