Commit f95d147
Changed files (4)
util/limits.h
@@ -1,7 +1,7 @@
#ifndef NOTLIBC_HEADER_UTIL_LIMITS_INCLUDED
#define NOTLIBC_HEADER_UTIL_LIMITS_INCLUDED
-#include "platform/platform.h"
+#include "../platform/platform.h"
#define u8_MIN 0
#define u16_MIN 0
util/mathops.h
@@ -1,42 +1,77 @@
#ifndef NOTLIBC_HEADER_UTIL_MATHOPS_INCLUDED
#define NOTLIBC_HEADER_UTIL_MATHOPS_INCLUDED
-#include "../platform/platform.h"
#include "./safemath.h"
+static inline Status u64_round_up( u64 number, u64 multiple, u64 *out ) {
+ if( multiple == 0 ) return S_FAILURE | ERR_ARG_2 | ERR_INVALID_ARGUMENT;
+ u64 rem = number%multiple;
+ if( rem == 0 ) {
+ *out = number;
+ } else {
+ TRY( u64_add( number, multiple - rem, out ) );
+ }
+ return S_SUCCESS;
+}
-// TODO: Add overflow and underflow checks for both signed and unsigned, as well as for gcc-likes and generic ones with portable C checks.
-
+static inline Status u32_round_up( u32 number, u32 multiple, u32 *out ) {
+ if( multiple == 0 ) return S_FAILURE | ERR_ARG_2 | ERR_INVALID_ARGUMENT;
+ u32 rem = number%multiple;
+ if( rem == 0 ) {
+ *out = number;
+ } else {
+ TRY( u32_add( number, multiple - rem, out ) );
+ }
+ return S_SUCCESS;
+}
-#define GEN_ROUND_UP(T) \
- static inline Status T##_round_up( T number, T multiple, T *out ) { \
- if( multiple == 0 ) return S_FAILURE | ERR_ARG_2 | ERR_INVALID_ARGUMENT; \
- T rem = number%multiple; \
- \
- if( rem == 0 ) { \
- *out = number; \
- } else { \
- TRY( T##_add( number, multiple - rem, out ) ); \
- } \
- return S_SUCCESS; \
+static inline Status u16_round_up( u16 number, u16 multiple, u16 *out ) {
+ if( multiple == 0 ) return S_FAILURE | ERR_ARG_2 | ERR_INVALID_ARGUMENT;
+ u16 rem = number%multiple;
+ if( rem == 0 ) {
+ *out = number;
+ } else {
+ TRY( u16_add( number, multiple - rem, out ) );
}
+ return S_SUCCESS;
+}
-#define GEN_ROUND_DOWN(T) \
- static inline Status T##_round_down(T number, T multiple, T *out) { \
- if( multiple == 0 ) return S_FAILURE | ERR_ARG_2 | ERR_INVALID_ARGUMENT; \
- *out = number - (number%multiple); \
- return S_SUCCESS; \
+static inline Status u8_round_up( u8 number, u8 multiple, u8 *out ) {
+ if( multiple == 0 ) return S_FAILURE | ERR_ARG_2 | ERR_INVALID_ARGUMENT;
+ u8 rem = number%multiple;
+ if( rem == 0 ) {
+ *out = number;
+ } else {
+ TRY( u8_add( number, multiple - rem, out ) );
}
+ return S_SUCCESS;
+}
+
+
+static inline Status u64_round_down(u64 number, u64 multiple, u64 *out) {
+ if( multiple == 0 ) return S_FAILURE | ERR_ARG_2 | ERR_INVALID_ARGUMENT;
+ *out = number - (number%multiple);
+ return S_SUCCESS;
+}
+
+static inline Status u32_round_down(u32 number, u32 multiple, u32 *out) {
+ if( multiple == 0 ) return S_FAILURE | ERR_ARG_2 | ERR_INVALID_ARGUMENT;
+ *out = number - (number%multiple);
+ return S_SUCCESS;
+}
+
+static inline Status u16_round_down(u16 number, u16 multiple, u16 *out) {
+ if( multiple == 0 ) return S_FAILURE | ERR_ARG_2 | ERR_INVALID_ARGUMENT;
+ *out = number - (number%multiple);
+ return S_SUCCESS;
+}
+static inline Status u8_round_down(u8 number, u8 multiple, u8 *out) {
+ if( multiple == 0 ) return S_FAILURE | ERR_ARG_2 | ERR_INVALID_ARGUMENT;
+ *out = number - (number%multiple);
+ return S_SUCCESS;
+}
-GEN_ROUND_UP(u8)
-GEN_ROUND_UP(u16)
-GEN_ROUND_UP(u32)
-GEN_ROUND_UP(u64)
-GEN_ROUND_DOWN(u8)
-GEN_ROUND_DOWN(u16)
-GEN_ROUND_DOWN(u32)
-GEN_ROUND_DOWN(u64)
#endif
util/safemath_gcclike.h
@@ -3,41 +3,126 @@
#include "../platform/platform.h"
-#define GEN_ADD(T) \
- static inline Status T##_add( T n1, T n2, T*out ) { \
- if( __builtin_add_overflow(n1, n2, out) ) { \
- return S_FAILURE | ERR_OVERFLOW;\
- } \
- return S_SUCCESS; \
- } \
-
-#define GEN_SUB(T) \
- static inline Status T##_sub( T n1, T n2, T*out ) { \
- if( __builtin_sub_overflow(n1, n2, out) ) { \
- return S_FAILURE | ERR_OVERFLOW;\
- } \
- return S_SUCCESS; \
- } \
-
-
-GEN_ADD(u8)
-GEN_ADD(u16)
-GEN_ADD(u32)
-GEN_ADD(u64)
-
-GEN_ADD(s8)
-GEN_ADD(s16)
-GEN_ADD(s32)
-GEN_ADD(s64)
-
-GEN_SUB(u8)
-GEN_SUB(u16)
-GEN_SUB(u32)
-GEN_SUB(u64)
-
-GEN_SUB(s8)
-GEN_SUB(s16)
-GEN_SUB(s32)
-GEN_SUB(s64)
+/* Unsigned addition */
+
+static inline Status u64_add( u64 n1, u64 n2, u64 *out ) {
+ if( __builtin_add_overflow(n1, n2, out) ) {
+ return S_FAILURE | ERR_OVERFLOW;
+ }
+ return S_SUCCESS;
+}
+
+static inline Status u32_add( u32 n1, u32 n2, u32 *out ) {
+ if( __builtin_add_overflow(n1, n2, out) ) {
+ return S_FAILURE | ERR_OVERFLOW;
+ }
+ return S_SUCCESS;
+}
+
+static inline Status u16_add( u16 n1, u16 n2, u16 *out ) {
+ if( __builtin_add_overflow(n1, n2, out) ) {
+ return S_FAILURE | ERR_OVERFLOW;
+ }
+ return S_SUCCESS;
+}
+
+static inline Status u8_add( u8 n1, u8 n2, u8 *out ) {
+ if( __builtin_add_overflow(n1, n2, out) ) {
+ return S_FAILURE | ERR_OVERFLOW;
+ }
+ return S_SUCCESS;
+}
+
+
+/* Signed addition */
+
+static inline Status s64_add( s64 n1, s64 n2, s64 *out ) {
+ if( __builtin_add_overflow(n1, n2, out) ) {
+ return S_FAILURE | ERR_OVERFLOW;
+ }
+ return S_SUCCESS;
+}
+
+static inline Status s32_add( s32 n1, s32 n2, s32 *out ) {
+ if( __builtin_add_overflow(n1, n2, out) ) {
+ return S_FAILURE | ERR_OVERFLOW;
+ }
+ return S_SUCCESS;
+}
+
+static inline Status s16_add( s16 n1, s16 n2, s16 *out ) {
+ if( __builtin_add_overflow(n1, n2, out) ) {
+ return S_FAILURE | ERR_OVERFLOW;
+ }
+ return S_SUCCESS;
+}
+
+static inline Status s8_add( s8 n1, s8 n2, s8 *out ) {
+ if( __builtin_add_overflow(n1, n2, out) ) {
+ return S_FAILURE | ERR_OVERFLOW;
+ }
+ return S_SUCCESS;
+}
+
+
+/* Unsigned subtraction */
+
+static inline Status u64_sub( u64 n1, u64 n2, u64 *out ) {
+ if( __builtin_sub_overflow(n1, n2, out) ) {
+ return S_FAILURE | ERR_OVERFLOW;
+ }
+ return S_SUCCESS;
+}
+
+static inline Status u32_sub( u32 n1, u32 n2, u32 *out ) {
+ if( __builtin_sub_overflow(n1, n2, out) ) {
+ return S_FAILURE | ERR_OVERFLOW;
+ }
+ return S_SUCCESS;
+}
+
+static inline Status u16_sub( u16 n1, u16 n2, u16 *out ) {
+ if( __builtin_sub_overflow(n1, n2, out) ) {
+ return S_FAILURE | ERR_OVERFLOW;
+ }
+ return S_SUCCESS;
+}
+
+static inline Status u8_sub( u8 n1, u8 n2, u8 *out ) {
+ if( __builtin_sub_overflow(n1, n2, out) ) {
+ return S_FAILURE | ERR_OVERFLOW;
+ }
+ return S_SUCCESS;
+}
+
+/* Signed subtraction */
+
+static inline Status s64_sub( s64 n1, s64 n2, s64 *out ) {
+ if( __builtin_sub_overflow(n1, n2, out) ) {
+ return S_FAILURE | ERR_OVERFLOW;
+ }
+ return S_SUCCESS;
+}
+
+static inline Status s32_sub( s32 n1, s32 n2, s32 *out ) {
+ if( __builtin_sub_overflow(n1, n2, out) ) {
+ return S_FAILURE | ERR_OVERFLOW;
+ }
+ return S_SUCCESS;
+}
+
+static inline Status s16_sub( s16 n1, s16 n2, s16 *out ) {
+ if( __builtin_sub_overflow(n1, n2, out) ) {
+ return S_FAILURE | ERR_OVERFLOW;
+ }
+ return S_SUCCESS;
+}
+
+static inline Status s8_sub( s8 n1, s8 n2, s8 *out ) {
+ if( __builtin_sub_overflow(n1, n2, out) ) {
+ return S_FAILURE | ERR_OVERFLOW;
+ }
+ return S_SUCCESS;
+}
#endif
util/safemath_generic.h
@@ -4,65 +4,140 @@
#include "../platform/platform.h"
#include "util/limits.h"
-#define GEN_ADDU(T) \
- static inline Status T##_add( T n1, T n2, T*out ) { \
- if( n1 > (T##_MAX) - n2 ) { \
- return S_FAILURE | ERR_OVERFLOW; \
- } \
- *out = n1 + n2; \
- return S_SUCCESS; \
- }
-
-GEN_ADDU(u8)
-GEN_ADDU(u16)
-GEN_ADDU(u32)
-GEN_ADDU(u64)
-
-#define GEN_ADDS(T) \
- static inline Status T##_add( T n1, T n2, T*out ) { \
- if( (n1 >= 0 && n2 > T##_MAX - n1) \
- || (n1 < 0 && n2 < T##_MIN - n1) ) \
- { \
- return S_FAILURE | ERR_OVERFLOW; \
- } \
- *out = n1 + n2; \
- return S_SUCCESS; \
- }
-
-GEN_ADDS(s8)
-GEN_ADDS(s16)
-GEN_ADDS(s32)
-GEN_ADDS(s64)
-
-
-#define GEN_SUBU(T) \
- static inline Status T##_sub( T n1, T n2, T*out ) { \
- if( n2 > n1 ) { \
- return S_FAILURE | ERR_OVERFLOW; \
- } \
- *out = n1 - n2; \
- return S_SUCCESS; \
- }
-
-GEN_SUBU(u8)
-GEN_SUBU(u16)
-GEN_SUBU(u32)
-GEN_SUBU(u64)
-
-#define GEN_SUBS(T) \
- static inline Status T##_sub( T n1, T n2, T*out ) { \
- if( (n2 > 0 && n1 < T##_MIN + n2) \
- || (n2 < 0 && n1 > T##_MAX + n2) ) \
- { \
- return S_FAILURE | ERR_OVERFLOW; \
- } \
- *out = n1 - n2; \
- return S_SUCCESS; \
- }
-
-GEN_SUBS(s8)
-GEN_SUBS(s16)
-GEN_SUBS(s32)
-GEN_SUBS(s64)
+/* Unsigned addition */
+
+static inline Status u64_add( u64 n1, u64 n2, u64*out ) {
+ if( n1 > (u64_MAX) - n2 ) {
+ return S_FAILURE | ERR_OVERFLOW;
+ }
+ *out = n1 + n2;
+ return S_SUCCESS;
+}
+
+static inline Status u32_add( u32 n1, u32 n2, u32*out ) {
+ if( n1 > (u32_MAX) - n2 ) {
+ return S_FAILURE | ERR_OVERFLOW;
+ }
+ *out = n1 + n2;
+ return S_SUCCESS;
+}
+
+static inline Status u16_add( u16 n1, u16 n2, u16*out ) {
+ if( n1 > (u16_MAX) - n2 ) {
+ return S_FAILURE | ERR_OVERFLOW;
+ }
+ *out = n1 + n2;
+ return S_SUCCESS;
+}
+
+static inline Status u8_add( u8 n1, u8 n2, u8*out ) {
+ if( n1 > (u8_MAX) - n2 ) {
+ return S_FAILURE | ERR_OVERFLOW;
+ }
+ *out = n1 + n2;
+ return S_SUCCESS;
+}
+
+/* Signed addition */
+
+static inline Status s64_add( s64 n1, s64 n2, s64*out ) {
+ if( (n1 >= 0 && n2 > s64_MAX - n1) || (n1 < 0 && n2 < s64_MIN - n1) ) {
+ return S_FAILURE | ERR_OVERFLOW;
+ }
+ *out = n1 + n2;
+ return S_SUCCESS;
+}
+
+static inline Status s32_add( s32 n1, s32 n2, s32*out ) {
+ if( (n1 >= 0 && n2 > s32_MAX - n1) || (n1 < 0 && n2 < s32_MIN - n1) ) {
+ return S_FAILURE | ERR_OVERFLOW;
+ }
+ *out = n1 + n2;
+ return S_SUCCESS;
+}
+
+static inline Status s16_add( s16 n1, s16 n2, s16*out ) {
+ if( (n1 >= 0 && n2 > s16_MAX - n1) || (n1 < 0 && n2 < s16_MIN - n1) ) {
+ return S_FAILURE | ERR_OVERFLOW;
+ }
+ *out = n1 + n2;
+ return S_SUCCESS;
+}
+
+static inline Status s8_add( s8 n1, s8 n2, s8*out ) {
+ if( (n1 >= 0 && n2 > s8_MAX - n1) || (n1 < 0 && n2 < s8_MIN - n1) ) {
+ return S_FAILURE | ERR_OVERFLOW;
+ }
+ *out = n1 + n2;
+ return S_SUCCESS;
+}
+
+/* Unsigned subtraction */
+
+static inline Status u64_sub( u64 n1, u64 n2, u64*out ) {
+ if( n2 > n1 ) {
+ return S_FAILURE | ERR_OVERFLOW;
+ }
+ *out = n1 - n2;
+ return S_SUCCESS;
+}
+
+static inline Status u32_sub( u32 n1, u32 n2, u32*out ) {
+ if( n2 > n1 ) {
+ return S_FAILURE | ERR_OVERFLOW;
+ }
+ *out = n1 - n2;
+ return S_SUCCESS;
+}
+
+static inline Status u16_sub( u16 n1, u16 n2, u16*out ) {
+ if( n2 > n1 ) {
+ return S_FAILURE | ERR_OVERFLOW;
+ }
+ *out = n1 - n2;
+ return S_SUCCESS;
+}
+
+static inline Status u8_sub( u8 n1, u8 n2, u8*out ) {
+ if( n2 > n1 ) {
+ return S_FAILURE | ERR_OVERFLOW;
+ }
+ *out = n1 - n2;
+ return S_SUCCESS;
+}
+
+/* Signed Subtraction */
+
+static inline Status s64_sub( s64 n1, s64 n2, s64*out ) {
+ if( (n2 > 0 && n1 < s64_MIN + n2) || (n2 < 0 && n1 > s64_MAX + n2) ) {
+ return S_FAILURE | ERR_OVERFLOW;
+ }
+ *out = n1 - n2;
+ return S_SUCCESS;
+}
+
+static inline Status s32_sub( s32 n1, s32 n2, s32*out ) {
+ if( (n2 > 0 && n1 < s32_MIN + n2) || (n2 < 0 && n1 > s32_MAX + n2) ) {
+ return S_FAILURE | ERR_OVERFLOW;
+ }
+ *out = n1 - n2;
+ return S_SUCCESS;
+}
+
+static inline Status s16_sub( s16 n1, s16 n2, s16*out ) {
+ if( (n2 > 0 && n1 < s16_MIN + n2) || (n2 < 0 && n1 > s16_MAX + n2) ) {
+ return S_FAILURE | ERR_OVERFLOW;
+ }
+ *out = n1 - n2;
+ return S_SUCCESS;
+}
+
+static inline Status s8_sub( s8 n1, s8 n2, s8*out ) {
+ if( (n2 > 0 && n1 < s8_MIN + n2) || (n2 < 0 && n1 > s8_MAX + n2) ) {
+ return S_FAILURE | ERR_OVERFLOW;
+ }
+ *out = n1 - n2;
+ return S_SUCCESS;
+}
#endif