Commit d7f8eae
Changed files (12)
testing/tests/002_safemath.c
@@ -5,250 +5,244 @@
void PRESERVE_WITH_LTO entry(void) {
- union {
- u64 u64;
- u32 u32;
- u16 u16;
- u8 u8;
- s64 s64;
- s32 s32;
- s16 s16;
- s8 s8;
- } res;
-
assert( (-1^1) == -2 ); /* All safemath code assumes 2's complement. Assert it here, too. */
+ Status s = S_SUCCESS;
+
/* Validate correct basic addition and subtraction behaviour */
- assert( S_OK( u64_add( 3, 2, &res.u64 ))); assert( res.u64 == 5 );
- assert( S_OK( u32_add( 3, 2, &res.u32 ))); assert( res.u32 == 5 );
- assert( S_OK( u16_add( 3, 2, &res.u16 ))); assert( res.u16 == 5 );
- assert( S_OK( u8_add( 3, 2, &res.u8 ))); assert( res.u8 == 5 );
-
- assert( S_OK( u64_sub( 3, 2, &res.u64 ))); assert( res.u64 == 1 );
- assert( S_OK( u32_sub( 3, 2, &res.u32 ))); assert( res.u32 == 1 );
- assert( S_OK( u16_sub( 3, 2, &res.u16 ))); assert( res.u16 == 1 );
- assert( S_OK( u8_sub( 3, 2, &res.u8 ))); assert( res.u8 == 1 );
-
- assert( S_OK( s64_add( 3, 2, &res.s64 ))); assert( res.s64 == 5 );
- assert( S_OK( s32_add( 3, 2, &res.s32 ))); assert( res.s32 == 5 );
- assert( S_OK( s16_add( 3, 2, &res.s16 ))); assert( res.s16 == 5 );
- assert( S_OK( s8_add( 3, 2, &res.s8 ))); assert( res.s8 == 5 );
-
- assert( S_OK( s64_sub( 3, 2, &res.s64 ))); assert( res.s64 == 1 );
- assert( S_OK( s32_sub( 3, 2, &res.s32 ))); assert( res.s32 == 1 );
- assert( S_OK( s16_sub( 3, 2, &res.s16 ))); assert( res.s16 == 1 );
- assert( S_OK( s8_sub( 3, 2, &res.s8 ))); assert( res.s8 == 1 );
+ assert( u64_add( &s, 3, 2 ) == 5 ); assert(S_OK(s));
+ assert( u32_add( &s, 3, 2 ) == 5 ); assert(S_OK(s));
+ assert( u16_add( &s, 3, 2 ) == 5 ); assert(S_OK(s));
+ assert( u8_add( &s, 3, 2 ) == 5 ); assert(S_OK(s));
+
+ assert( u64_sub( &s, 3, 2 ) == 1 ); assert(S_OK(s));
+ assert( u32_sub( &s, 3, 2 ) == 1 ); assert(S_OK(s));
+ assert( u16_sub( &s, 3, 2 ) == 1 ); assert(S_OK(s));
+ assert( u8_sub( &s, 3, 2 ) == 1 ); assert(S_OK(s));
+
+ assert( s64_add( &s, 3, 2 ) == 5 ); assert(S_OK(s));
+ assert( s32_add( &s, 3, 2 ) == 5 ); assert(S_OK(s));
+ assert( s16_add( &s, 3, 2 ) == 5 ); assert(S_OK(s));
+ assert( s8_add( &s, 3, 2 ) == 5 ); assert(S_OK(s));
+
+ assert( s64_sub( &s, 3, 2 ) == 1 ); assert(S_OK(s));
+ assert( s32_sub( &s, 3, 2 ) == 1 ); assert(S_OK(s));
+ assert( s16_sub( &s, 3, 2 ) == 1 ); assert(S_OK(s));
+ assert( s8_sub( &s, 3, 2 ) == 1 ); assert(S_OK(s));
/* Catch potential off-by-one implementation errors */
/* Unsigned */
- assert( S_OK( u64_add( u64_MAX - 1, 1, &res.u64 ))); assert( res.u64 == u64_MAX );
- assert( S_OK( u32_add( u32_MAX - 1, 1, &res.u32 ))); assert( res.u32 == u32_MAX );
- assert( S_OK( u16_add( u16_MAX - 1, 1, &res.u16 ))); assert( res.u16 == u16_MAX );
- assert( S_OK( u8_add( u8_MAX - 1, 1, &res.u8 ))); assert( res.u8 == u8_MAX );
+ assert( u64_add( &s, u64_MAX - 1, 1 ) == u64_MAX ); assert(S_OK(s));
+ assert( u32_add( &s, u32_MAX - 1, 1 ) == u32_MAX ); assert(S_OK(s));
+ assert( u16_add( &s, u16_MAX - 1, 1 ) == u16_MAX ); assert(S_OK(s));
+ assert( u8_add( &s, u8_MAX - 1, 1 ) == u8_MAX ); assert(S_OK(s));
- assert( S_OK( u64_sub( u64_MIN + 1, 1, &res.u64 ))); assert( res.u64 == u64_MIN );
- assert( S_OK( u32_sub( u32_MIN + 1, 1, &res.u32 ))); assert( res.u32 == u32_MIN );
- assert( S_OK( u16_sub( u16_MIN + 1, 1, &res.u16 ))); assert( res.u16 == u16_MIN );
- assert( S_OK( u8_sub( u8_MIN + 1, 1, &res.u8 ))); assert( res.u8 == u8_MIN );
+ assert( u64_sub( &s, u64_MIN + 1, 1 ) == u64_MIN ); assert(S_OK(s));
+ assert( u32_sub( &s, u32_MIN + 1, 1 ) == u32_MIN ); assert(S_OK(s));
+ assert( u16_sub( &s, u16_MIN + 1, 1 ) == u16_MIN ); assert(S_OK(s));
+ assert( u8_sub( &s, u8_MIN + 1, 1 ) == u8_MIN ); assert(S_OK(s));
/* Signed */
- assert( S_OK( s64_add( s64_MAX - 1, 1, &res.s64 ))); assert( res.s64 == s64_MAX );
- assert( S_OK( s32_add( s32_MAX - 1, 1, &res.s32 ))); assert( res.s32 == s32_MAX );
- assert( S_OK( s16_add( s16_MAX - 1, 1, &res.s16 ))); assert( res.s16 == s16_MAX );
- assert( S_OK( s8_add( s8_MAX - 1, 1, &res.s8 ))); assert( res.s8 == s8_MAX );
-
- assert( S_OK( s64_sub( s64_MAX - 1, -1, &res.s64 ))); assert( res.s64 == s64_MAX );
- assert( S_OK( s32_sub( s32_MAX - 1, -1, &res.s32 ))); assert( res.s32 == s32_MAX );
- assert( S_OK( s16_sub( s16_MAX - 1, -1, &res.s16 ))); assert( res.s16 == s16_MAX );
- assert( S_OK( s8_sub( s8_MAX - 1, -1, &res.s8 ))); assert( res.s8 == s8_MAX );
-
- assert( S_OK( s64_sub( s64_MIN + 1, 1, &res.s64 ))); assert( res.s64 == s64_MIN );
- assert( S_OK( s32_sub( s32_MIN + 1, 1, &res.s32 ))); assert( res.s32 == s32_MIN );
- assert( S_OK( s16_sub( s16_MIN + 1, 1, &res.s16 ))); assert( res.s16 == s16_MIN );
- assert( S_OK( s8_sub( s8_MIN + 1, 1, &res.s8 ))); assert( res.s8 == s8_MIN );
-
- assert( S_OK( s64_add( s64_MIN + 1, -1, &res.s64 ))); assert( res.s64 == s64_MIN );
- assert( S_OK( s32_add( s32_MIN + 1, -1, &res.s32 ))); assert( res.s32 == s32_MIN );
- assert( S_OK( s16_add( s16_MIN + 1, -1, &res.s16 ))); assert( res.s16 == s16_MIN );
- assert( S_OK( s8_add( s8_MIN + 1, -1, &res.s8 ))); assert( res.s8 == s8_MIN );
+ assert( s64_add( &s, s64_MAX - 1, 1 ) == s64_MAX ); assert(S_OK(s));
+ assert( s32_add( &s, s32_MAX - 1, 1 ) == s32_MAX ); assert(S_OK(s));
+ assert( s16_add( &s, s16_MAX - 1, 1 ) == s16_MAX ); assert(S_OK(s));
+ assert( s8_add( &s, s8_MAX - 1, 1 ) == s8_MAX ); assert(S_OK(s));
+
+ assert( s64_sub( &s, s64_MAX - 1, -1 ) == s64_MAX ); assert(S_OK(s));
+ assert( s32_sub( &s, s32_MAX - 1, -1 ) == s32_MAX ); assert(S_OK(s));
+ assert( s16_sub( &s, s16_MAX - 1, -1 ) == s16_MAX ); assert(S_OK(s));
+ assert( s8_sub( &s, s8_MAX - 1, -1 ) == s8_MAX ); assert(S_OK(s));
+
+ assert( s64_sub( &s, s64_MIN + 1, 1 ) == s64_MIN ); assert(S_OK(s));
+ assert( s32_sub( &s, s32_MIN + 1, 1 ) == s32_MIN ); assert(S_OK(s));
+ assert( s16_sub( &s, s16_MIN + 1, 1 ) == s16_MIN ); assert(S_OK(s));
+ assert( s8_sub( &s, s8_MIN + 1, 1 ) == s8_MIN ); assert(S_OK(s));
+
+ assert( s64_add( &s, s64_MIN + 1, -1 ) == s64_MIN ); assert(S_OK(s));
+ assert( s32_add( &s, s32_MIN + 1, -1 ) == s32_MIN ); assert(S_OK(s));
+ assert( s16_add( &s, s16_MIN + 1, -1 ) == s16_MIN ); assert(S_OK(s));
+ assert( s8_add( &s, s8_MIN + 1, -1 ) == s8_MIN ); assert(S_OK(s));
/* Overflow */
/* Unsigned */
- assert( S_FAILED( u64_add( u64_MAX, N, &res.u64 )));
- assert( S_FAILED( u32_add( u32_MAX, N, &res.u32 )));
- assert( S_FAILED( u16_add( u16_MAX, N, &res.u16 )));
- assert( S_FAILED( u8_add( u8_MAX, N, &res.u8 )));
+ s = S_SUCCESS; (void)u64_add( &s, u64_MAX, N ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)u32_add( &s, u32_MAX, N ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)u16_add( &s, u16_MAX, N ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void) u8_add( &s, u8_MAX, N ); assert( S_NOK(s) );
- assert( S_FAILED( u64_add( u64_MAX, 1, &res.u64 )));
- assert( S_FAILED( u32_add( u32_MAX, 1, &res.u32 )));
- assert( S_FAILED( u16_add( u16_MAX, 1, &res.u16 )));
- assert( S_FAILED( u8_add( u8_MAX, 1, &res.u8 )));
+ s = S_SUCCESS; (void)u64_add( &s, u64_MAX, 1 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)u32_add( &s, u32_MAX, 1 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)u16_add( &s, u16_MAX, 1 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void) u8_add( &s, u8_MAX, 1 ); assert( S_NOK(s) );
/* Signed */
- assert( S_FAILED( s64_add( s64_MAX, N, &res.s64 )));
- assert( S_FAILED( s32_add( s32_MAX, N, &res.s32 )));
- assert( S_FAILED( s16_add( s16_MAX, N, &res.s16 )));
- assert( S_FAILED( s8_add( s8_MAX, N, &res.s8 )));
- assert( S_FAILED( s64_sub( s64_MAX, -N, &res.s64 )));
- assert( S_FAILED( s32_sub( s32_MAX, -N, &res.s32 )));
- assert( S_FAILED( s16_sub( s16_MAX, -N, &res.s16 )));
- assert( S_FAILED( s8_sub( s8_MAX, -N, &res.s8 )));
-
- assert( S_FAILED( s64_add( s64_MAX, 1, &res.s64 )));
- assert( S_FAILED( s32_add( s32_MAX, 1, &res.s32 )));
- assert( S_FAILED( s16_add( s16_MAX, 1, &res.s16 )));
- assert( S_FAILED( s8_add( s8_MAX, 1, &res.s8 )));
- assert( S_FAILED( s64_sub( s64_MAX, -1, &res.s64 )));
- assert( S_FAILED( s32_sub( s32_MAX, -1, &res.s32 )));
- assert( S_FAILED( s16_sub( s16_MAX, -1, &res.s16 )));
- assert( S_FAILED( s8_sub( s8_MAX, -1, &res.s8 )));
+ s = S_SUCCESS; (void)s64_add( &s, s64_MAX, N ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)s32_add( &s, s32_MAX, N ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)s16_add( &s, s16_MAX, N ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void) s8_add( &s, s8_MAX, N ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)s64_sub( &s, s64_MAX, -N ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)s32_sub( &s, s32_MAX, -N ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)s16_sub( &s, s16_MAX, -N ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void) s8_sub( &s, s8_MAX, -N ); assert( S_NOK(s) );
+
+ s = S_SUCCESS; (void)s64_add( &s, s64_MAX, 1 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)s32_add( &s, s32_MAX, 1 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)s16_add( &s, s16_MAX, 1 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void) s8_add( &s, s8_MAX, 1 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)s64_sub( &s, s64_MAX, -1 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)s32_sub( &s, s32_MAX, -1 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)s16_sub( &s, s16_MAX, -1 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void) s8_sub( &s, s8_MAX, -1 ); assert( S_NOK(s) );
/* Underflow */
/* Unsigned */
- assert( S_FAILED( u64_sub( u64_MIN, N, &res.u64 )));
- assert( S_FAILED( u32_sub( u32_MIN, N, &res.u32 )));
- assert( S_FAILED( u16_sub( u16_MIN, N, &res.u16 )));
- assert( S_FAILED( u8_sub( u8_MIN, N, &res.u8 )));
+ s = S_SUCCESS; (void)u64_sub( &s, u64_MIN, N ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)u32_sub( &s, u32_MIN, N ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)u16_sub( &s, u16_MIN, N ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void) u8_sub( &s, u8_MIN, N ); assert( S_NOK(s) );
- assert( S_FAILED( u64_sub( u64_MIN, 1, &res.u64 )));
- assert( S_FAILED( u32_sub( u32_MIN, 1, &res.u32 )));
- assert( S_FAILED( u16_sub( u16_MIN, 1, &res.u16 )));
- assert( S_FAILED( u8_sub( u8_MIN, 1, &res.u8 )));
+ s = S_SUCCESS; (void)u64_sub( &s, u64_MIN, 1 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)u32_sub( &s, u32_MIN, 1 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)u16_sub( &s, u16_MIN, 1 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void) u8_sub( &s, u8_MIN, 1 ); assert( S_NOK(s) );
/* Signed */
- assert( S_FAILED( s64_sub( s64_MIN, N, &res.s64 )));
- assert( S_FAILED( s32_sub( s32_MIN, N, &res.s32 )));
- assert( S_FAILED( s16_sub( s16_MIN, N, &res.s16 )));
- assert( S_FAILED( s8_sub( s8_MIN, N, &res.s8 )));
- assert( S_FAILED( s64_sub( s64_MIN, 1, &res.s64 )));
- assert( S_FAILED( s32_sub( s32_MIN, 1, &res.s32 )));
- assert( S_FAILED( s16_sub( s16_MIN, 1, &res.s16 )));
- assert( S_FAILED( s8_sub( s8_MIN, 1, &res.s8 )));
-
- assert( S_FAILED( s64_add( s64_MIN, -N, &res.s64 )));
- assert( S_FAILED( s32_add( s32_MIN, -N, &res.s32 )));
- assert( S_FAILED( s16_add( s16_MIN, -N, &res.s16 )));
- assert( S_FAILED( s8_add( s8_MIN, -N, &res.s8 )));
- assert( S_FAILED( s64_add( s64_MIN, -1, &res.s64 )));
- assert( S_FAILED( s32_add( s32_MIN, -1, &res.s32 )));
- assert( S_FAILED( s16_add( s16_MIN, -1, &res.s16 )));
- assert( S_FAILED( s8_add( s8_MIN, -1, &res.s8 )));
+ s = S_SUCCESS; (void)s64_sub( &s, s64_MIN, N ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)s32_sub( &s, s32_MIN, N ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)s16_sub( &s, s16_MIN, N ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void) s8_sub( &s, s8_MIN, N ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)s64_sub( &s, s64_MIN, 1 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)s32_sub( &s, s32_MIN, 1 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)s16_sub( &s, s16_MIN, 1 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void) s8_sub( &s, s8_MIN, 1 ); assert( S_NOK(s) );
+
+ s = S_SUCCESS; (void)s64_add( &s, s64_MIN, -N ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)s32_add( &s, s32_MIN, -N ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)s16_add( &s, s16_MIN, -N ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void) s8_add( &s, s8_MIN, -N ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)s64_add( &s, s64_MIN, -1 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)s32_add( &s, s32_MIN, -1 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)s16_add( &s, s16_MIN, -1 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void) s8_add( &s, s8_MIN, -1 ); assert( S_NOK(s) );
+ s = S_SUCCESS;
/* Basic multiplication */
- assert( S_OK( u64_mul( 3, 2, &res.u64 ))); assert( res.u64 == 6 );
- assert( S_OK( u32_mul( 3, 2, &res.u32 ))); assert( res.u32 == 6 );
- assert( S_OK( u16_mul( 3, 2, &res.u16 ))); assert( res.u16 == 6 );
- assert( S_OK( u8_mul( 3, 2, &res.u8 ))); assert( res.u8 == 6 );
+ assert( u64_mul( &s, 3, 2 ) == 6 ); assert(S_OK(s));
+ assert( u32_mul( &s, 3, 2 ) == 6 ); assert(S_OK(s));
+ assert( u16_mul( &s, 3, 2 ) == 6 ); assert(S_OK(s));
+ assert( u8_mul( &s, 3, 2 ) == 6 ); assert(S_OK(s));
- assert( S_OK( s64_mul( 3, 2, &res.s64 ))); assert( res.s64 == 6 );
- assert( S_OK( s32_mul( 3, 2, &res.s32 ))); assert( res.s32 == 6 );
- assert( S_OK( s16_mul( 3, 2, &res.s16 ))); assert( res.s16 == 6 );
- assert( S_OK( s8_mul( 3, 2, &res.s8 ))); assert( res.s8 == 6 );
+ assert( s64_mul( &s, 3, 2 ) == 6 ); assert(S_OK(s));
+ assert( s32_mul( &s, 3, 2 ) == 6 ); assert(S_OK(s));
+ assert( s16_mul( &s, 3, 2 ) == 6 ); assert(S_OK(s));
+ assert( s8_mul( &s, 3, 2 ) == 6 ); assert(S_OK(s));
- assert( S_OK( s64_mul( -3, 2, &res.s64 ))); assert( res.s64 == -6 );
- assert( S_OK( s32_mul( -3, 2, &res.s32 ))); assert( res.s32 == -6 );
- assert( S_OK( s16_mul( -3, 2, &res.s16 ))); assert( res.s16 == -6 );
- assert( S_OK( s8_mul( -3, 2, &res.s8 ))); assert( res.s8 == -6 );
+ assert( s64_mul( &s, -3, 2 ) == -6 ); assert(S_OK(s));
+ assert( s32_mul( &s, -3, 2 ) == -6 ); assert(S_OK(s));
+ assert( s16_mul( &s, -3, 2 ) == -6 ); assert(S_OK(s));
+ assert( s8_mul( &s, -3, 2 ) == -6 ); assert(S_OK(s));
/* Zero */
- assert( S_OK( u64_mul( u64_MAX, 0, &res.u64 ))); assert( res.u64 == 0 );
- assert( S_OK( u32_mul( u32_MAX, 0, &res.u32 ))); assert( res.u32 == 0 );
- assert( S_OK( u16_mul( u16_MAX, 0, &res.u16 ))); assert( res.u16 == 0 );
- assert( S_OK( u8_mul( u8_MAX, 0, &res.u8 ))); assert( res.u8 == 0 );
-
- assert( S_OK( s64_mul( s64_MAX, 0, &res.s64 ))); assert( res.s64 == 0 );
- assert( S_OK( s32_mul( s32_MAX, 0, &res.s32 ))); assert( res.s32 == 0 );
- assert( S_OK( s16_mul( s16_MAX, 0, &res.s16 ))); assert( res.s16 == 0 );
- assert( S_OK( s8_mul( s8_MAX, 0, &res.s8 ))); assert( res.s8 == 0 );
-
- assert( S_OK( u64_mul( 0, u64_MAX, &res.u64 ))); assert( res.u64 == 0 );
- assert( S_OK( u32_mul( 0, u32_MAX, &res.u32 ))); assert( res.u32 == 0 );
- assert( S_OK( u16_mul( 0, u16_MAX, &res.u16 ))); assert( res.u16 == 0 );
- assert( S_OK( u8_mul( 0, u8_MAX, &res.u8 ))); assert( res.u8 == 0 );
-
- assert( S_OK( s64_mul( 0, s64_MIN, &res.s64 ))); assert( res.s64 == 0 );
- assert( S_OK( s32_mul( 0, s32_MIN, &res.s32 ))); assert( res.s32 == 0 );
- assert( S_OK( s16_mul( 0, s16_MIN, &res.s16 ))); assert( res.s16 == 0 );
- assert( S_OK( s8_mul( 0, s8_MIN, &res.s8 ))); assert( res.s8 == 0 );
+ assert( u64_mul( &s, u64_MAX, 0 ) == 0 ); assert(S_OK(s));
+ assert( u32_mul( &s, u32_MAX, 0 ) == 0 ); assert(S_OK(s));
+ assert( u16_mul( &s, u16_MAX, 0 ) == 0 ); assert(S_OK(s));
+ assert( u8_mul( &s, u8_MAX, 0 ) == 0 ); assert(S_OK(s));
+
+ assert( s64_mul( &s, s64_MAX, 0 ) == 0 ); assert(S_OK(s));
+ assert( s32_mul( &s, s32_MAX, 0 ) == 0 ); assert(S_OK(s));
+ assert( s16_mul( &s, s16_MAX, 0 ) == 0 ); assert(S_OK(s));
+ assert( s8_mul( &s, s8_MAX, 0 ) == 0 ); assert(S_OK(s));
+
+ assert( u64_mul( &s, 0, u64_MAX ) == 0 ); assert(S_OK(s));
+ assert( u32_mul( &s, 0, u32_MAX ) == 0 ); assert(S_OK(s));
+ assert( u16_mul( &s, 0, u16_MAX ) == 0 ); assert(S_OK(s));
+ assert( u8_mul( &s, 0, u8_MAX ) == 0 ); assert(S_OK(s));
+
+ assert( s64_mul( &s, 0, s64_MIN ) == 0 ); assert(S_OK(s));
+ assert( s32_mul( &s, 0, s32_MIN ) == 0 ); assert(S_OK(s));
+ assert( s16_mul( &s, 0, s16_MIN ) == 0 ); assert(S_OK(s));
+ assert( s8_mul( &s, 0, s8_MIN ) == 0 ); assert(S_OK(s));
/* Overflow */
- assert( S_FAILED( u64_mul( u64_MAX, 2, &res.u64 )));
- assert( S_FAILED( u32_mul( u32_MAX, 2, &res.u32 )));
- assert( S_FAILED( u16_mul( u16_MAX, 2, &res.u16 )));
- assert( S_FAILED( u8_mul( u8_MAX, 2, &res.u8 )));
-
- assert( S_FAILED( s64_mul( s64_MIN, 2, &res.s64 )));
- assert( S_FAILED( s32_mul( s32_MIN, 2, &res.s32 )));
- assert( S_FAILED( s16_mul( s16_MIN, 2, &res.s16 )));
- assert( S_FAILED( s8_mul( s8_MIN, 2, &res.s8 )));
-
- assert( S_FAILED( s64_mul( s64_MAX, 2, &res.s64 )));
- assert( S_FAILED( s32_mul( s32_MAX, 2, &res.s32 )));
- assert( S_FAILED( s16_mul( s16_MAX, 2, &res.s16 )));
- assert( S_FAILED( s8_mul( s8_MAX, 2, &res.s8 )));
-
- assert( S_FAILED( s64_mul( s64_MIN, -1, &res.s64 )));
- assert( S_FAILED( s32_mul( s32_MIN, -1, &res.s32 )));
- assert( S_FAILED( s16_mul( s16_MIN, -1, &res.s16 )));
- assert( S_FAILED( s8_mul( s8_MIN, -1, &res.s8 )));
-
- assert( S_FAILED( s64_mul( s64_MIN/2, -2, &res.s64 )));
- assert( S_FAILED( s32_mul( s32_MIN/2, -2, &res.s32 )));
- assert( S_FAILED( s16_mul( s16_MIN/2, -2, &res.s16 )));
- assert( S_FAILED( s8_mul( s8_MIN/2, -2, &res.s8 )));
+ s = S_SUCCESS; (void)u64_mul( &s, u64_MAX, 2 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)u32_mul( &s, u32_MAX, 2 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)u16_mul( &s, u16_MAX, 2 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void) u8_mul( &s, u8_MAX, 2 ); assert( S_NOK(s) );
+
+ s = S_SUCCESS; (void)s64_mul( &s, s64_MIN, 2 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)s32_mul( &s, s32_MIN, 2 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)s16_mul( &s, s16_MIN, 2 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void) s8_mul( &s, s8_MIN, 2 ); assert( S_NOK(s) );
+
+ s = S_SUCCESS; (void)s64_mul( &s, s64_MAX, 2 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)s32_mul( &s, s32_MAX, 2 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)s16_mul( &s, s16_MAX, 2 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void) s8_mul( &s, s8_MAX, 2 ); assert( S_NOK(s) );
+
+ s = S_SUCCESS; (void)s64_mul( &s, s64_MIN, -1 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)s32_mul( &s, s32_MIN, -1 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)s16_mul( &s, s16_MIN, -1 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void) s8_mul( &s, s8_MIN, -1 ); assert( S_NOK(s) );
+
+ s = S_SUCCESS; (void)s64_mul( &s, s64_MIN/2, -2 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)s32_mul( &s, s32_MIN/2, -2 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)s16_mul( &s, s16_MIN/2, -2 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void) s8_mul( &s, s8_MIN/2, -2 ); assert( S_NOK(s) );
+ s = S_SUCCESS;
/* Signed-specific */
- assert( S_OK( s64_mul( s64_MAX, -1, &res.s64 )));
- assert( S_OK( s32_mul( s32_MAX, -1, &res.s32 )));
- assert( S_OK( s16_mul( s16_MAX, -1, &res.s16 )));
- assert( S_OK( s8_mul( s8_MAX, -1, &res.s8 )));
-
- assert( S_OK( s64_mul( s64_MIN + 1, -1, &res.s64 ))); assert( res.s64 == s64_MAX );
- assert( S_OK( s32_mul( s32_MIN + 1, -1, &res.s32 ))); assert( res.s32 == s32_MAX );
- assert( S_OK( s16_mul( s16_MIN + 1, -1, &res.s16 ))); assert( res.s16 == s16_MAX );
- assert( S_OK( s8_mul( s8_MIN + 1, -1, &res.s8 ))); assert( res.s8 == s8_MAX );
-
- assert( S_OK( s64_mul( s64_MIN / -2, -2, &res.s64 ))); assert( res.s64 == s64_MIN );
- assert( S_OK( s32_mul( s32_MIN / -2, -2, &res.s32 ))); assert( res.s32 == s32_MIN );
- assert( S_OK( s16_mul( s16_MIN / -2, -2, &res.s16 ))); assert( res.s16 == s16_MIN );
- assert( S_OK( s8_mul( s8_MIN / -2, -2, &res.s8 ))); assert( res.s8 == s8_MIN );
-
- assert( S_OK( s64_mul( s64_MIN / 2 + 1, -2, &res.s64 ))); assert( res.s64 == s64_MAX - 1 );
- assert( S_OK( s32_mul( s32_MIN / 2 + 1, -2, &res.s32 ))); assert( res.s32 == s32_MAX - 1 );
- assert( S_OK( s16_mul( s16_MIN / 2 + 1, -2, &res.s16 ))); assert( res.s16 == s16_MAX - 1 );
- assert( S_OK( s8_mul( s8_MIN / 2 + 1, -2, &res.s8 ))); assert( res.s8 == s8_MAX - 1 );
+ s64_mul( &s, s64_MAX, -1 );
+ s32_mul( &s, s32_MAX, -1 );
+ s16_mul( &s, s16_MAX, -1 );
+ s8_mul( &s, s8_MAX, -1);
+
+ assert( s64_mul( &s, s64_MIN + 1, -1 ) == s64_MAX ); assert(S_OK(s));
+ assert( s32_mul( &s, s32_MIN + 1, -1 ) == s32_MAX ); assert(S_OK(s));
+ assert( s16_mul( &s, s16_MIN + 1, -1 ) == s16_MAX ); assert(S_OK(s));
+ assert( s8_mul( &s, s8_MIN + 1, -1 ) == s8_MAX ); assert(S_OK(s));
+
+ assert( s64_mul( &s, s64_MIN / -2, -2 ) == s64_MIN ); assert(S_OK(s));
+ assert( s32_mul( &s, s32_MIN / -2, -2 ) == s32_MIN ); assert(S_OK(s));
+ assert( s16_mul( &s, s16_MIN / -2, -2 ) == s16_MIN ); assert(S_OK(s));
+ assert( s8_mul( &s, s8_MIN / -2, -2 ) == s8_MIN ); assert(S_OK(s));
+
+ assert( s64_mul( &s, s64_MIN / 2 + 1, -2 ) == s64_MAX - 1 ); assert(S_OK(s));
+ assert( s32_mul( &s, s32_MIN / 2 + 1, -2 ) == s32_MAX - 1 ); assert(S_OK(s));
+ assert( s16_mul( &s, s16_MIN / 2 + 1, -2 ) == s16_MAX - 1 ); assert(S_OK(s));
+ assert( s8_mul( &s, s8_MIN / 2 + 1, -2 ) == s8_MAX - 1 ); assert(S_OK(s));
/* Catch potential off-by-one errors */
- assert( S_OK( u64_mul( u64_MAX/2, 2, &res.u64 ))); assert( res.u64 == u64_MAX - 1 );
- assert( S_OK( u32_mul( u32_MAX/2, 2, &res.u32 ))); assert( res.u32 == u32_MAX - 1 );
- assert( S_OK( u16_mul( u16_MAX/2, 2, &res.u16 ))); assert( res.u16 == u16_MAX - 1 );
- assert( S_OK( u8_mul( u8_MAX/2, 2, &res.u8 ))); assert( res.u8 == u8_MAX - 1 );
-
- assert( S_FAILED( u64_mul( u64_MAX / 2 + 1, 2, &res.u64 )));
- assert( S_FAILED( u32_mul( u32_MAX / 2 + 1, 2, &res.u32 )));
- assert( S_FAILED( u16_mul( u16_MAX / 2 + 1, 2, &res.u16 )));
- assert( S_FAILED( u8_mul( u8_MAX / 2 + 1, 2, &res.u8 )));
-
- assert( S_OK( s64_mul( s64_MAX/2, 2, &res.s64 ))); assert( res.s64 == s64_MAX - 1 );
- assert( S_OK( s32_mul( s32_MAX/2, 2, &res.s32 ))); assert( res.s32 == s32_MAX - 1 );
- assert( S_OK( s16_mul( s16_MAX/2, 2, &res.s16 ))); assert( res.s16 == s16_MAX - 1 );
- assert( S_OK( s8_mul( s8_MAX/2, 2, &res.s8 ))); assert( res.s8 == s8_MAX - 1 );
-
- assert( S_OK( s64_mul( s64_MIN/2, 2, &res.s64 ))); assert( res.s64 == s64_MIN );
- assert( S_OK( s32_mul( s32_MIN/2, 2, &res.s32 ))); assert( res.s32 == s32_MIN );
- assert( S_OK( s16_mul( s16_MIN/2, 2, &res.s16 ))); assert( res.s16 == s16_MIN );
- assert( S_OK( s8_mul( s8_MIN/2, 2, &res.s8 ))); assert( res.s8 == s8_MIN );
-
- assert( S_FAILED( s64_mul( s64_MAX/2 + 1, 2, &res.s64 )));
- assert( S_FAILED( s32_mul( s32_MAX/2 + 1, 2, &res.s32 )));
- assert( S_FAILED( s16_mul( s16_MAX/2 + 1, 2, &res.s16 )));
- assert( S_FAILED( s8_mul( s8_MAX/2 + 1, 2, &res.s8 )));
-
- assert( S_FAILED( s64_mul( s64_MIN/2 - 1, 2, &res.s64 )));
- assert( S_FAILED( s32_mul( s32_MIN/2 - 1, 2, &res.s32 )));
- assert( S_FAILED( s16_mul( s16_MIN/2 - 1, 2, &res.s16 )));
- assert( S_FAILED( s8_mul( s8_MIN/2 - 1, 2, &res.s8 )));
+ assert( u64_mul( &s, u64_MAX/2, 2 ) == u64_MAX - 1 ); assert(S_OK(s));
+ assert( u32_mul( &s, u32_MAX/2, 2 ) == u32_MAX - 1 ); assert(S_OK(s));
+ assert( u16_mul( &s, u16_MAX/2, 2 ) == u16_MAX - 1 ); assert(S_OK(s));
+ assert( u8_mul( &s, u8_MAX/2, 2 ) == u8_MAX - 1 ); assert(S_OK(s));
+
+ s = S_SUCCESS; (void)u64_mul( &s, u64_MAX / 2 + 1, 2 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)u32_mul( &s, u32_MAX / 2 + 1, 2 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)u16_mul( &s, u16_MAX / 2 + 1, 2 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void) u8_mul( &s, u8_MAX / 2 + 1, 2 ); assert( S_NOK(s) );
+ s = S_SUCCESS;
+
+ assert( s64_mul( &s, s64_MAX/2, 2 ) == s64_MAX - 1 ); assert(S_OK(s));
+ assert( s32_mul( &s, s32_MAX/2, 2 ) == s32_MAX - 1 ); assert(S_OK(s));
+ assert( s16_mul( &s, s16_MAX/2, 2 ) == s16_MAX - 1 ); assert(S_OK(s));
+ assert( s8_mul( &s, s8_MAX/2, 2 ) == s8_MAX - 1 ); assert(S_OK(s));
+
+ assert( s64_mul( &s, s64_MIN/2, 2 ) == s64_MIN ); assert(S_OK(s));
+ assert( s32_mul( &s, s32_MIN/2, 2 ) == s32_MIN ); assert(S_OK(s));
+ assert( s16_mul( &s, s16_MIN/2, 2 ) == s16_MIN ); assert(S_OK(s));
+ assert( s8_mul( &s, s8_MIN/2, 2 ) == s8_MIN ); assert(S_OK(s));
+
+ s = S_SUCCESS; (void)s64_mul( &s, s64_MAX/2 + 1, 2 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)s32_mul( &s, s32_MAX/2 + 1, 2 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)s16_mul( &s, s16_MAX/2 + 1, 2 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void) s8_mul( &s, s8_MAX/2 + 1, 2 ); assert( S_NOK(s) );
+
+ s = S_SUCCESS; (void)s64_mul( &s, s64_MIN/2 - 1, 2 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)s32_mul( &s, s32_MIN/2 - 1, 2 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void)s16_mul( &s, s16_MIN/2 - 1, 2 ); assert( S_NOK(s) );
+ s = S_SUCCESS; (void) s8_mul( &s, s8_MIN/2 - 1, 2 ); assert( S_NOK(s) );
terminate(0);
}
testing/tests/003_round.c
@@ -4,24 +4,24 @@
#define N 13
void PRESERVE_WITH_LTO entry(void) {
- u64 result = N - 1;
+ Status s = S_SUCCESS;
/* Basic functionality test */
- assert( S_OK( u64_round_up( N+1, N, &result ))); assert( result == 2*N);
- assert( S_OK( u32_round_up( N+1, N, (u32*)&result ))); assert( result == 2*N);
- assert( S_OK( u16_round_up( N+1, N, (u16*)&result ))); assert( result == 2*N);
- assert( S_OK( u8_round_up( N+1, N, (u8 *)&result ))); assert( result == 2*N);
+ assert( u64_round_up( &s, N+1, N ) == 2*N ); assert(S_OK(s));
+ assert( u32_round_up( &s, N+1, N ) == 2*N ); assert(S_OK(s));
+ assert( u16_round_up( &s, N+1, N ) == 2*N ); assert(S_OK(s));
+ assert( u8_round_up( &s, N+1, N ) == 2*N ); assert(S_OK(s));
- assert( S_OK( u64_round_down( 2*N-1, N, &result ))); assert( result == N);
- assert( S_OK( u32_round_down( 2*N-1, N, (u32*)&result ))); assert( result == N);
- assert( S_OK( u16_round_down( 2*N-1, N, (u16*)&result ))); assert( result == N);
- assert( S_OK( u8_round_down( 2*N-1, N, (u8 *)&result ))); assert( result == N);
+ assert( u64_round_down( &s, 2*N-1, N ) == N ); assert(S_OK(s));
+ assert( u32_round_down( &s, 2*N-1, N ) == N ); assert(S_OK(s));
+ assert( u16_round_down( &s, 2*N-1, N ) == N ); assert(S_OK(s));
+ assert( u8_round_down( &s, 2*N-1, N ) == N ); assert(S_OK(s));
/* Overflow */
- assert( S_FAILED( u64_round_up( u64_MAX, N, &result )));
- assert( S_FAILED( u32_round_up( u32_MAX, N, (u32*)&result )));
- assert( S_FAILED( u16_round_up( u16_MAX, N, (u16*)&result )));
- assert( S_FAILED( u8_round_up( u8_MAX, N, (u8 *)&result )));
+ u64_round_up( &s, u64_MAX, N ); assert( S_NOK(s) );
+ u32_round_up( &s, u32_MAX, N ); assert( S_NOK(s) );
+ u16_round_up( &s, u16_MAX, N ); assert( S_NOK(s) );
+ u8_round_up( &s, u8_MAX, N ); assert( S_NOK(s) );
/* Rounding down to 0 is valid, so no underflow test */
testing/tests/012_mem_basic.c
@@ -6,30 +6,24 @@
void PRESERVE_WITH_LTO entry(void) {
Page *mem = 0;
- assert(S_OK(
- mem_claim( PAGECOUNT, &mem )
- ));
-
+ Status s = S_SUCCESS;
+ mem = mem_claim( &s, PAGECOUNT );
+ assert( S_OK(s) );
assert( mem != 0 );
- assert(S_OK(
- mem_occupy( mem, PAGECOUNT )
- ));
+ mem_occupy( &s, mem, PAGECOUNT );
+ assert( S_OK(s) );
mem_set( mem, PAGECOUNT*sizeof(Page), 0xde );
-
for( usize i = 0; i < PAGECOUNT*sizeof(Page); ++i ) {
assert( *(u8*)mem == 0xde );
}
- assert(S_OK(
- mem_vacate( mem, PAGECOUNT )
- ));
-
- assert(S_OK(
- mem_relinquish( mem, PAGECOUNT )
- ));
+ mem_vacate( &s, mem, PAGECOUNT );
+ assert( S_OK(s) );
+ mem_relinquish( &s, mem, PAGECOUNT );
+ assert( S_OK(s) );
terminate(0);
}
testing/tests/013_arena_basic.c
@@ -4,23 +4,17 @@
Arena a = {0};
void PRESERVE_WITH_LTO entry(void) {
- assert( S_OK(
- Arena_create( &a, KiB(5) )
- ));
+ Status s = S_SUCCESS;
+ Arena a = Arena_create( &s, KiB(5) );
+ assert( S_OK( s ));
for( u64 i = 0; i < KiB(5)/sizeof(u32); ++i ) {
- u32 *out = 0;
- assert( S_OK(
- Arena_take( &a, sizeof(u32), (u8**)&out )
- ));
+ u32 *out = Arena_take( &s, &a, sizeof(u32) );
+ assert( S_OK( s ));
*out = 0xdeadbeef;
}
-
- assert( S_OK(
- Arena_destroy( &a )
- ));
-
+ Arena_destroy( &s, &a );
terminate(0);
}
testing/tests/014_heap.c
@@ -3,14 +3,16 @@
void PRESERVE_WITH_LTO entry(void) {
- Heap h = {0};
+ Status s = S_SUCCESS;
- assert(S_OK( Heap_create( &h, KiB(8) ) ));
+ Heap h = Heap_create( &s, KiB(8) );
+ assert(S_OK( s ));
- void *ptr1 = 0;
- void *ptr2 = 0;
- assert(S_OK( Heap_alloc( &h, 32, &ptr1 ) ));
- assert(S_OK( Heap_alloc( &h, 32, &ptr2 ) ));
+ void *ptr1 = Heap_alloc( &s, &h, 32 );
+ assert(S_OK( s ));
+
+ void *ptr2 = Heap_alloc( &s, &h, 32 );
+ assert(S_OK( s ));
void *original_ptr1 = ptr1;
@@ -19,21 +21,29 @@ void PRESERVE_WITH_LTO entry(void) {
((u8*)ptr2)[i] = 'i';
}
- assert(S_OK( Heap_free( &h, &ptr1 ) ));
+ Heap_free( &s, &h, ptr1 );
+ assert(S_OK( s ));
#if BUILD_TYPE == BUILD_RELEASE
- assert(S_NOK( Heap_alloc( &h, 0, &ptr1 ) ));
+ Heap_alloc( &s, &h, 0 );
+ assert(S_NOK( s ));
+ s = S_SUCCESS;
#endif
void *ptr3 = 0;
- assert(S_OK( Heap_alloc( &h, 32, &ptr3 ) ));
+ ptr3 = Heap_alloc( &s, &h, 32 );
+ assert(S_OK( s ));
assert( ptr3 == original_ptr1 );
- assert(S_OK( Heap_free( &h, &ptr3 ) ));
- assert(S_OK( Heap_free( &h, &ptr2 ) ));
+ Heap_free( &s, &h, ptr3 );
+ assert(S_OK( s ));
+
+ Heap_free( &s, &h, ptr2 );
+ assert(S_OK( s ));
- assert(S_OK( Heap_destroy( &h ) ));
+ Heap_destroy( &s, &h);
+ assert(S_OK( s ));
terminate(0);
}
testing/tests/015_array_basic.c
@@ -2,32 +2,34 @@
#include "notlibc.c"
void PRESERVE_WITH_LTO entry(void) {
- Heap h = {0};
+ Status s = S_SUCCESS;
- assert(S_OK( Heap_create( &h, KiB(8) ) ));
+ Heap h = Heap_create( &s, KiB(8) );
+ assert(S_OK( s ));
- usizes *a = 0;
- assert(S_OK( usizes_create( &h, 16, &a ) ));
+ usizes *a = usizes_create( &s, &h, 16 );
+ assert(S_OK( s ));
for( usize i = 0; i < 8; ++i ) {
- assert(S_OK( usizes_push( &a, &i, &h ) ));
+ a = usizes_push( &s, a, &i, &h );
+ assert(S_OK( s ));
}
/* Resize allocation to minimum needed size aka 16 elements + metadata */
- assert(S_OK( usizes_deflate( &a, &h ) ));
-
- /* Not much to assert here, since the heap may allocate more than asked for */
+ a = usizes_deflate( &s, a, &h );
+ assert(S_OK( s ));
assert( a->len == 8 );
- /* Truncate by cutting 16 elements off the end - this preserves allocation size, only changes logical length */
- usizes_truncate( a, 8 );
+
+ /* Truncate by cutting 8 elements off the end - this preserves allocation size, only changes logical length */
+ usizes_truncate( &s, a, 8 );
+ assert(S_OK( s ));
assert( a->len == 0 );
- /* extend - make sure 24 more elemets will fit (0 + 24 = 24) */
- assert(S_OK( usizes_extend( &a, 24, &h ) ));
- assert( a->len == 24 );
- for( usize i = 0; i < a->len; ++i ) {
+ for( usize i = 0; i < 24; ++i ) {
+ a = usizes_push( &s, a, &i, &h );
+ assert(S_OK( s ));
a->data[i] = i;
}
@@ -36,17 +38,21 @@ void PRESERVE_WITH_LTO entry(void) {
}
usize el = 12;
- usizes_push( &a, &el, &h );
+ usizes_push( &s, a, &el, &h );
+ assert(S_OK( s ));
assert( a->len == 25 );
el = 0;
- usizes_pop( a, &el );
+ usizes_pop( &s, a, &el );
+ assert(S_OK( s ));
assert( el == 12 );
- assert(S_OK( usizes_destroy( &a, &h ) ));
+ usizes_destroy( &s, &a, &h );
+ assert(S_OK( s ));
- assert(S_OK( Heap_destroy( &h ) ));
+ Heap_destroy( &s, &h );
+ assert(S_OK( s ));
terminate(0);
}
testing/tests/016_strings_and_slices.c
@@ -7,87 +7,117 @@ void PRESERVE_WITH_LTO entry(void) {
STRING( hack2, "hack" );
STRING( una, "una" );
- Arena a = {0};
- Heap h = {0};
- assert(S_OK( Arena_create( &a, KiB(4) ) ));
- assert(S_OK( Heap_create( &h, KiB(4) ) ));
+ Status s = S_SUCCESS;
- StrSlc hack_slc = {0};
- assert(S_OK( StrSlc_from_Str( &hack_slc, (const Str*)&hack, 0, hack.len ) ));
- assert( StrSlc_equals( hack_slc, hack_slc ) == 1);
- assert( StrSlc_equals_by_ref( &hack_slc, &hack_slc ) == 1);
+ Arena a = Arena_create( &s, KiB(4) );
+ assert(S_OK( s ));
- assert(S_OK( StrSlc_equals_Str( hack_slc, (const Str*)&hack ) ));
- assert(S_OK( StrSlc_equals_Str_by_ref( &hack_slc, (const Str*)&hack ) ));
+ Heap h = Heap_create( &s, KiB(4) );
+ assert(S_OK( s ));
+
+ StrSlc hack_slc = StrSlc_from_Str( &s, (const Str*)&hack, 0, hack.len );
+ assert(S_OK( s ));
+
+ assert( StrSlc_equals( hack_slc, hack_slc ) == 1 );
+ assert( StrSlc_equals_by_ref( &hack_slc, &hack_slc ) == 1 );
+
+ StrSlc_equals_Str( hack_slc, (const Str*)&hack );
+ assert(S_OK( s ));
+
+ StrSlc_equals_Str_by_ref( &hack_slc, (const Str*)&hack );
+ assert(S_OK( s ));
+
+ StrSlc hack2_slc = StrSlc_from_Str( &s, (const Str*)&hack2, 0, hack.len );
+ assert(S_OK( s ));
- StrSlc hack2_slc = {0};
- assert(S_OK( StrSlc_from_Str( &hack2_slc, (const Str*)&hack2, 0, hack.len ) ));
assert( StrSlc_equals( hack_slc, hack2_slc ) == 1);
assert( StrSlc_equals_by_ref( &hack_slc, &hack2_slc ) == 1);
- StrSlc na_slc = {0};
- assert(S_OK( StrSlc_from_Str( &na_slc, (const Str*)&una, 1, una.len - 1 ) ));
+ StrSlc na_slc = StrSlc_from_Str( &s, (const Str*)&una, 1, una.len - 1 );
+ assert(S_OK( s ));
- StrAsm sa = {0};
- assert( S_OK( StrAsm_create( &sa, KiB(4) ) ));
+ StrAsm sa = StrAsm_create( &s, KiB(4) );
+ assert(S_OK( s ));
-
- assert( S_OK( StrAsm_cat_Str( &sa, (const Str*)&hack ) ));
- assert( S_OK( StrAsm_cat_char( &sa, 'u' ) ));
- assert( S_OK( StrAsm_cat_StrSlc( &sa, na_slc ) ) );
- assert( S_OK( StrAsm_cat_StrSlc_by_ref( &sa, &na_slc ) ) );
+ StrAsm_cat_Str( &s, &sa, (const Str*)&hack );
+ assert(S_OK( s ));
+ StrAsm_cat_char( &s, &sa, 'u' );
+ assert(S_OK( s ));
+ StrAsm_cat_StrSlc( &s, &sa, na_slc );
+ assert(S_OK( s ));
+ StrAsm_cat_StrSlc_by_ref( &s, &sa, &na_slc );
+ assert(S_OK( s ));
Str *s_a = 0;
Str *s_h = 0;
- assert( S_OK( StrAsm_store_into_arena( &sa, &a, &s_a ) ) );
- assert( S_OK( StrAsm_store_onto_heap( &sa, &h, &s_h ) ) );
+ StrAsm_store_into_arena( &s, &sa, &a, &s_a );
+ assert(S_OK( s ));
+ StrAsm_store_onto_heap( &s, &sa, &h, &s_h );
+ assert(S_OK( s ));
assert( Str_equals( s_a, s_h ) == 1 );
assert( Str_equals( s_a, (const Str*)&hackunana ) == 1);
assert( Str_equals( s_h, (const Str*)&hackunana ) == 1);
- Heap_free( &h, (void**)&s_h );
+ Heap_free( &s, &h, s_h );
- assert( S_OK( StrAsm_reset( &sa ) ) );
+ StrAsm_reset( &s, &sa );
+ assert(S_OK( s ));
StrSlc slc = {0};
STRING( numbers_hex, "0xfe" "0xffff" "0xffffffff" "0xffffffffffffffff" );
- assert( S_OK( StrAsm_fmtx_u8( &sa, 0xfe ) ) );
- assert( S_OK( StrAsm_fmtx_u16( &sa, 0xffff ) ) );
- assert( S_OK( StrAsm_fmtx_u32( &sa, 0xffffffff) ) );
- assert( S_OK( StrAsm_fmtx_u64( &sa, 0xffffffffffffffff ) ) );
+ StrAsm_fmtx_u8( &s, &sa, 0xfe );
+ assert(S_OK( s ));
+ StrAsm_fmtx_u16( &s, &sa, 0xffff );
+ assert(S_OK( s ));
+ StrAsm_fmtx_u32( &s, &sa, 0xffffffff);
+ assert(S_OK( s ));
+ StrAsm_fmtx_u64( &s, &sa, 0xffffffffffffffff );
+ assert(S_OK( s ));
slc = StrAsm_as_StrSlc( &sa );
assert( StrSlc_equals_Str( slc, (const Str*)&numbers_hex ) == 1 );
- assert( S_OK( StrAsm_reset( &sa ) ) );
+ StrAsm_reset( &s, &sa );
+ assert(S_OK( s ));
STRING( numbers_dec, "255" "65535" "4294967295" "18446744073709551615" );
- assert( S_OK( StrAsm_fmtd_u8( &sa, 255 ) ) );
- assert( S_OK( StrAsm_fmtd_u16( &sa, 65535 ) ) );
- assert( S_OK( StrAsm_fmtd_u32( &sa, 4294967295) ) );
- assert( S_OK( StrAsm_fmtd_u64( &sa, 18446744073709551615u ) ) );
+ StrAsm_fmtd_u8( &s, &sa, 255 );
+ assert(S_OK( s ));
+ StrAsm_fmtd_u16( &s, &sa, 65535 );
+ assert(S_OK( s ));
+ StrAsm_fmtd_u32( &s, &sa, 4294967295);
+ assert(S_OK( s ));
+ StrAsm_fmtd_u64( &s, &sa, 18446744073709551615u );
+ assert(S_OK( s ));
slc = StrAsm_as_StrSlc( &sa );
assert( StrSlc_equals_Str( slc, (const Str*)&numbers_dec ) == 1 );
- assert( S_OK( StrAsm_reset( &sa ) ) );
+ StrAsm_reset( &s, &sa );
+ assert(S_OK( s ));
STRING( numbers_dec_s, "-128" "-32768" "-2147483648" "-9223372036854775808" );
- assert( S_OK( StrAsm_fmtd_s8( &sa, -128 ) ) );
- assert( S_OK( StrAsm_fmtd_s16( &sa, -32768 ) ) );
- assert( S_OK( StrAsm_fmtd_s32( &sa, -2147483648 ) ) );
- assert( S_OK( StrAsm_fmtd_s64( &sa, -9223372036854775807LL - 1 ) ) );
+ StrAsm_fmtd_s8( &s, &sa, -128 );
+ assert(S_OK( s ));
+ StrAsm_fmtd_s16( &s, &sa, -32768 );
+ assert(S_OK( s ));
+ StrAsm_fmtd_s32( &s, &sa, -2147483648 );
+ assert(S_OK( s ));
+ StrAsm_fmtd_s64( &s, &sa, -9223372036854775807LL - 1 );
+ assert(S_OK( s ));
slc = StrAsm_as_StrSlc( &sa );
assert( StrSlc_equals_Str( slc, (const Str*)&numbers_dec_s ) == 1 );
- assert( S_OK( StrAsm_destroy( &sa ) ));
- assert( S_OK( Arena_destroy( &a ) ));
- assert( S_OK( Heap_destroy( &h ) ));
-
+ StrAsm_destroy( &s, &sa );
+ assert(S_OK( s ));
+ Arena_destroy( &s, &a );
+ assert(S_OK( s ));
+ Heap_destroy( &s, &h );
+ assert(S_OK( s ));
terminate(0);
}
testing/tests/020_file_basic.c
@@ -60,29 +60,41 @@ void test_existing_open_missing_create(void) {
FILE_LINK_FAIL |
FILE_ACCESS_READ | FILE_ACCESS_WRITE;
+ Status s = S_SUCCESS;
+
/* Create */
- Status s = File_open( (Str*)&filename, flags, &f); assert( S_SUCCESSFUL(s) );
+ f = File_open( &s, (Str*)&filename, flags );
+ assert( S_SUCCESSFUL(s) );
- s = File_write( &f, msg.len, &written_amount, (const u8*)&msg.data ); assert( S_SUCCESSFUL(s) );
+ written_amount = File_write( &s, &f, msg.len, (const u8*)&msg.data );
+ assert( S_SUCCESSFUL(s) );
assert( written_amount == msg.len );
+ File_seek( &s, &f, 0 );
+ assert( S_SUCCESSFUL(s) );
- s = File_seek( &f, 0 ); assert( S_SUCCESSFUL(s) );
- s = File_read( &f, msg.len, &read_amount, (u8*)&buffer ); assert( S_SUCCESSFUL(s) );
+ read_amount = File_read( &s, &f, msg.len, (u8*)&buffer );
+ assert( S_SUCCESSFUL(s) );
for( usize i = 0; i < msg.len; ++i ) {
assert( buffer[i] == msg.data[i] );
}
- s = File_close( &f ); assert( S_SUCCESSFUL(s) );
+ File_close( &s, &f );
+ assert( S_SUCCESSFUL(s) );
/* Open */
- s = File_open( (Str*)&filename, flags, &f); assert( S_SUCCESSFUL(s) );
+ f = File_open( &s, (Str*)&filename, flags );
+ assert( S_SUCCESSFUL(s) );
+
+ read_amount = File_read( &s, &f, msg.len, (u8*)&buffer );
+ assert( S_SUCCESSFUL(s) );
- s = File_read( &f, msg.len, &read_amount, (u8*)&buffer ); assert( S_SUCCESSFUL(s) );
+ File_close( &s, &f );
+ assert( S_SUCCESSFUL(s) );
- s = File_close( &f ); assert( S_SUCCESSFUL(s) );
- s = File_delete( (Str*)&filename ); assert( S_SUCCESSFUL(s) );
+ File_delete( &s, (Str*)&filename );
+ assert( S_SUCCESSFUL(s) );
}
@@ -92,21 +104,32 @@ void test_existing_truncate_missing_create(void) {
FILE_MISSING_CREATE |
FILE_LINK_FAIL |
FILE_ACCESS_READ | FILE_ACCESS_WRITE;
+
+ Status s = S_SUCCESS;
/* Create */
- Status s = File_open( (Str*)&filename, flags, &f); assert( S_SUCCESSFUL(s) );
- s = File_write( &f, msg.len, &written_amount, (const u8*)&msg.data ); assert( S_SUCCESSFUL(s) );
+ f = File_open( &s, (Str*)&filename, flags ); assert( S_SUCCESSFUL(s) );
+
+ written_amount = File_write( &s, &f, msg.len, (const u8*)&msg.data );
+ assert( S_SUCCESSFUL(s) );
assert( written_amount == msg.len );
- s = File_close( &f ); assert( S_SUCCESSFUL(s) );
+
+ File_close( &s, &f );
+ assert( S_SUCCESSFUL(s) );
/* Open (truncate) */
- s = File_open( (Str*)&filename, flags, &f); assert( S_SUCCESSFUL(s) );
+ f = File_open( &s, (Str*)&filename, flags );
+ assert( S_SUCCESSFUL(s) );
- s = File_read( &f, msg.len, &read_amount, (u8*)&buffer ); assert( S_SUCCESSFUL(s) );
+ read_amount = File_read( &s, &f, msg.len, (u8*)&buffer );
+ assert( S_SUCCESSFUL(s) );
assert( read_amount == 0 );
- s = File_close( &f ); assert( S_SUCCESSFUL(s) );
- s = File_delete( (Str*)&filename ); assert( S_SUCCESSFUL(s) );
+ File_close( &s, &f );
+ assert( S_SUCCESSFUL(s) );
+
+ File_delete( &s, (Str*)&filename );
+ assert( S_SUCCESSFUL(s) );
}
void test_existing_fail_missing_create(void) {
@@ -116,16 +139,23 @@ void test_existing_fail_missing_create(void) {
FILE_LINK_FAIL |
FILE_ACCESS_READ | FILE_ACCESS_WRITE;
+ Status s = S_SUCCESS;
/* Create */
- Status s = File_open( (Str*)&filename, flags, &f); assert( S_SUCCESSFUL(s) );
- s = File_write( &f, msg.len, &written_amount, (const u8*)&msg.data ); assert( S_SUCCESSFUL(s) );
+ f = File_open( &s, (Str*)&filename, flags );
+ assert( S_SUCCESSFUL(s) );
+
+ written_amount = File_write( &s, &f, msg.len, (const u8*)&msg.data ); assert( S_SUCCESSFUL(s) );
assert( written_amount == msg.len );
- s = File_close( &f ); assert( S_SUCCESSFUL(s) );
+
+ File_close( &s, &f );
+ assert( S_SUCCESSFUL(s) );
/* Open (fail) */
- s = File_open( (Str*)&filename, flags, &f); assert( S_FAILED(s) );
+ f = File_open( &s, (Str*)&filename, flags );
+ assert( S_FAILED(s) ); s = S_SUCCESS;
- s = File_delete( (Str*)&filename ); assert( S_SUCCESSFUL(s) );
+ File_delete( &s, (Str*)&filename );
+ assert( S_SUCCESSFUL(s) );
}
void test_existing_open_missing_fail(void) {
@@ -134,26 +164,33 @@ void test_existing_open_missing_fail(void) {
FILE_MISSING_FAIL |
FILE_LINK_FAIL |
FILE_ACCESS_READ | FILE_ACCESS_WRITE;
-
+
+ Status s = S_SUCCESS;
+
/* Create */
- Status s = File_open( (Str*)&filename, flags, &f); assert( S_FAILED(s) );
+ f = File_open( &s, (Str*)&filename, flags);
+ assert( S_FAILED(s) ); s = S_SUCCESS;
/* actually create for open */
- s = File_open( (Str*)&filename,
+ f = File_open( &s, (Str*)&filename,
FILE_EXISTING_FAIL |
FILE_MISSING_CREATE |
FILE_LINK_FAIL |
- FILE_ACCESS_READ | FILE_ACCESS_WRITE,
- &f
- ); assert( S_SUCCESSFUL(s) );
+ FILE_ACCESS_READ | FILE_ACCESS_WRITE
+ );
+ assert( S_SUCCESSFUL(s) );
- s = File_close( &f ); assert( S_SUCCESSFUL(s) );
+ File_close( &s, &f );
+ assert( S_SUCCESSFUL(s) );
/* Open */
- s = File_open( (Str*)&filename, flags, &f); assert( S_SUCCESSFUL(s) );
+ File_open( &s, (Str*)&filename, flags);
+ assert( S_SUCCESSFUL(s) );
- s = File_close( &f ); assert( S_SUCCESSFUL(s) );
- s = File_delete( (Str*)&filename ); assert( S_SUCCESSFUL(s) );
+ File_close( &s, &f );
+ assert( S_SUCCESSFUL(s) );
+ File_delete( &s, (Str*)&filename );
+ assert( S_SUCCESSFUL(s) );
}
void test_existing_truncate_missing_fail(void) {
@@ -163,45 +200,67 @@ void test_existing_truncate_missing_fail(void) {
FILE_LINK_FAIL |
FILE_ACCESS_READ | FILE_ACCESS_WRITE;
+
+ Status s = S_SUCCESS;
+
/* Create */
- Status s = File_open( (Str*)&filename, flags, &f); assert( S_FAILED(s) );
+ f = File_open( &s, (Str*)&filename, flags);
+ assert( S_FAILED(s) ); s = S_SUCCESS;
/* actually create for open */
- s = File_open( (Str*)&filename,
+ f = File_open( &s, (Str*)&filename,
FILE_EXISTING_FAIL |
FILE_MISSING_CREATE |
FILE_LINK_FAIL |
- FILE_ACCESS_READ | FILE_ACCESS_WRITE,
- &f
- ); assert( S_SUCCESSFUL(s) );
- s = File_write( &f, msg.len, &written_amount, (const u8*)&msg.data ); assert( S_SUCCESSFUL(s) );
+ FILE_ACCESS_READ | FILE_ACCESS_WRITE
+ );
+ assert( S_SUCCESSFUL(s) );
+
+ written_amount = File_write( &s, &f, msg.len, (const u8*)&msg.data );
+ assert( S_SUCCESSFUL(s) );
assert( written_amount == msg.len );
- s = File_close( &f ); assert( S_SUCCESSFUL(s) );
+
+ File_close( &s, &f );
+ assert( S_SUCCESSFUL(s) );
/* Open (truncate) */
- s = File_open( (Str*)&filename, flags, &f); assert( S_SUCCESSFUL(s) );
+ f = File_open( &s, (Str*)&filename, flags );
+ assert( S_SUCCESSFUL(s) );
- s = File_read( &f, msg.len, &read_amount, (u8*)&buffer ); assert( S_SUCCESSFUL(s) );
+ read_amount = File_read( &s, &f, msg.len, (u8*)&buffer );
+ assert( S_SUCCESSFUL(s) );
assert( read_amount == 0 );
- s = File_close( &f ); assert( S_SUCCESSFUL(s) );
- s = File_delete( (Str*)&filename ); assert( S_SUCCESSFUL(s) );
+ File_close( &s, &f ); assert( S_SUCCESSFUL(s) );
+ File_delete( &s, (Str*)&filename ); assert( S_SUCCESSFUL(s) );
}
void test_file_access(void) {
usize flags = FILE_EXISTING_OPEN | FILE_MISSING_CREATE | FILE_LINK_FAIL;
- Status s = File_open( (Str*)&filename, flags | FILE_ACCESS_READ, &f); assert( S_SUCCESSFUL(s) );
- s = File_write( &f, msg.len, &written_amount, (const u8*)&msg.data ); assert( S_FAILED(s) );
- s = File_close( &f ); assert( S_SUCCESSFUL(s) );
+ Status s = S_SUCCESS;
+ f = File_open( &s, (Str*)&filename, flags | FILE_ACCESS_READ );
+ assert( S_SUCCESSFUL(s) );
+
+ written_amount = File_write( &s, &f, msg.len, (const u8*)&msg.data );
+ assert( S_FAILED(s) ); s = S_SUCCESS;
+
+ File_close( &s, &f );
+ assert( S_SUCCESSFUL(s) );
- s = File_open( (Str*)&filename, flags | FILE_ACCESS_WRITE, &f); assert( S_SUCCESSFUL(s) );
- s = File_read( &f, msg.len, &read_amount, (u8*)&buffer ); assert( S_FAILED(s) );
- s = File_close( &f ); assert( S_SUCCESSFUL(s) );
+ f = File_open( &s, (Str*)&filename, flags | FILE_ACCESS_WRITE );
+ assert( S_SUCCESSFUL(s) );
+
+ File_read( &s, &f, msg.len, (u8*)&buffer );
+ assert( S_FAILED(s) ); s = S_SUCCESS;
- s = File_open( (Str*)&filename, flags | FILE_ACCESS_APPEND, &f); assert( S_SUCCESSFUL(s) );
- s = File_read( &f, msg.len, &read_amount, (u8*)&buffer ); assert( S_FAILED(s) );
- s = File_close( &f ); assert( S_SUCCESSFUL(s) );
+ File_close( &s, &f );
+ assert( S_SUCCESSFUL(s) );
+
+ f = File_open( &s, (Str*)&filename, flags | FILE_ACCESS_APPEND ); assert( S_SUCCESSFUL(s) );
+ File_read( &s, &f, msg.len, (u8*)&buffer );
+ assert( S_FAILED(s) ); s = S_SUCCESS;
+ File_close( &s, &f ); assert( S_SUCCESSFUL(s) );
}
void test_existing_fail_missing_fail(void) {
@@ -211,19 +270,33 @@ void test_existing_fail_missing_fail(void) {
FILE_LINK_FAIL |
FILE_ACCESS_READ | FILE_ACCESS_WRITE;
- Status s = File_open( (Str*)&filename, flags, &f); assert( S_FAILED(s) );
+ Status s = S_SUCCESS;
+
+ f = File_open( &s, (Str*)&filename, flags);
+ assert( S_FAILED(s) ); s = S_SUCCESS;
}
void test_invalid_combinations(void) {
usize flags = FILE_EXISTING_OPEN | FILE_MISSING_CREATE | FILE_LINK_FAIL | FILE_ACCESS_READ;
- Status s = File_open( (Str*)&filename, flags | FILE_ACCESS_APPEND | FILE_ACCESS_WRITE, &f); assert( S_FAILED(s) );
- s = File_open( (Str*)&filename, flags | FILE_EXISTING_FAIL, &f); assert( S_FAILED(s) );
- s = File_open( (Str*)&filename, flags | FILE_EXISTING_TRUNCATE, &f); assert( S_FAILED(s) );
- s = File_open( (Str*)&filename, flags | FILE_EXISTING_TRUNCATE | FILE_EXISTING_FAIL, &f); assert( S_FAILED(s) );
+ Status s = S_SUCCESS;
+ f = File_open( &s, (Str*)&filename, flags | FILE_ACCESS_APPEND | FILE_ACCESS_WRITE );
+ assert( S_FAILED(s) ); s = S_SUCCESS;
+
+ f = File_open( &s, (Str*)&filename, flags | FILE_EXISTING_FAIL );
+ assert( S_FAILED(s) ); s = S_SUCCESS;
+
+ f = File_open( &s, (Str*)&filename, flags | FILE_EXISTING_TRUNCATE );
+ assert( S_FAILED(s) ); s = S_SUCCESS;
+
+ f = File_open( &s, (Str*)&filename, flags | FILE_EXISTING_TRUNCATE | FILE_EXISTING_FAIL );
+ assert( S_FAILED(s) ); s = S_SUCCESS;
+
+ f = File_open( &s, (Str*)&filename, flags | FILE_MISSING_FAIL );
+ assert( S_FAILED(s) ); s = S_SUCCESS;
- s = File_open( (Str*)&filename, flags | FILE_MISSING_FAIL, &f); assert( S_FAILED(s) );
- s = File_open( (Str*)&filename, flags | FILE_LINK_FOLLOW, &f); assert( S_FAILED(s) );
+ f = File_open( &s, (Str*)&filename, flags | FILE_LINK_FOLLOW );
+ assert( S_FAILED(s) ); s = S_SUCCESS;
}
testing/tests/021_fileview.c
@@ -6,12 +6,12 @@ void PRESERVE_WITH_LTO entry(void) {
FileView fv = {0};
STRING( filename, "test.txt" );
- Status s;
+ Status s = S_SUCCESS;
- s = FileView_from_path( (Str*)&filename, MiB(1), FILEVIEW_OWN_FILE, &fv );
+ fv = FileView_from_path( &s, (Str*)&filename, MiB(1), FILEVIEW_OWN_FILE );
assert( S_SUCCESSFUL(s) );
- s = FileView_extend_file( &fv, 5 );
+ FileView_extend_file( &s, &fv, 5 );
assert( S_SUCCESSFUL(s) );
fv.start->data[0] = 'h';
@@ -20,12 +20,12 @@ void PRESERVE_WITH_LTO entry(void) {
fv.start->data[3] = 'l';
fv.start->data[4] = 'o';
- s = FileView_destroy( &fv );
+ FileView_destroy( &s, &fv );
assert( S_SUCCESSFUL(s) );
mem_set( &fv, sizeof(fv), 0 );
- s = FileView_from_path( (Str*)&filename, MiB(1), FILEVIEW_OWN_FILE, &fv );
+ fv = FileView_from_path( &s, (Str*)&filename, MiB(1), FILEVIEW_OWN_FILE );
assert( S_SUCCESSFUL(s) );
assert( fv.start->data[0] == 'h');
@@ -34,7 +34,7 @@ void PRESERVE_WITH_LTO entry(void) {
assert( fv.start->data[3] == 'l');
assert( fv.start->data[4] == 'o');
- s = FileView_destroy( &fv );
+ FileView_destroy( &s, &fv );
assert( S_SUCCESSFUL(s) );
terminate(0);
testing/test.sh
@@ -3,7 +3,7 @@
rm -rf ./build/tests/*
mkdir -p ./build/tests
-CFLAGS=(-nostdlib -ffreestanding -I. -DNOTLIBC_IMPLEMENT -DNOTLIBC_SILENCE -fno-builtin -g -Wall -Wextra -Wpedantic -Werror -fno-strict-aliasing)
+CFLAGS=(-nostdlib -ffreestanding -static -fno-stack-protector -I. -DNOTLIBC_IMPLEMENT -DNOTLIBC_SILENCE -fno-builtin -g -Wall -Wextra -Wpedantic -Werror -fno-strict-aliasing)
pids=()
ensure () {
notlibc.c
@@ -32,70 +32,129 @@ void *memcpy( void *dest, const void *src, unsigned long n ) {
/*================================ Arena =====================================*/
- Status Arena_create( Arena *out, usize size ) {
- TRY( u64_round_up( size, 0x1000, &size ) );
- TRY( mem_claim( size/0x1000, &out->start ) );
- out->claimed = size;
- out->occupied = 0;
- out->taken = 0;
+Arena Arena_create( Status *s, usize size ) {
+ Arena ret = {0};
+ END_IF_NOK( *s );
- return S_SUCCESS;
- }
+ size = u64_round_up( s, size, sizeof(Page));
+ ret.start = mem_claim( s, size/sizeof(Page) );
- Status Arena_destroy( Arena *a ) {
- TRY( mem_relinquish( a->start, a->claimed/sizeof(Page) ) );
+ END_IF_NOK( *s );
+ ret.claimed = size;
+
+end:
+ return ret;
+}
+void Arena_destroy( Status *s, Arena *a ) {
+ Status substatus = S_SUCCESS;
+
+ /* Object should be destroyed */
+ if( a && a->start && a->claimed ) {
+ mem_relinquish( &substatus, a->start, a->claimed/sizeof(Page) );
mem_set( a, sizeof(*a), 0 );
- return S_SUCCESS;
}
- Status Arena_align( Arena *a, usize alignment ) {
- u64 take_amount = 0;
- TRY( u64_round_up( a->taken, alignment, &take_amount ) );
- take_amount -= a->taken;
-
- if( take_amount != 0 ) {
- u8* discard;
- TRY( Arena_take( a, take_amount, &discard ) );
- }
-
- return S_SUCCESS;
+ if( S_OK(*s) && S_NOK( substatus ) ) {
+ *s = substatus;
}
+}
- Status Arena_take( Arena *a, usize amount, u8 **out ) {
- assert( out != 0 );
- assert( amount != 0 );
+void Arena_align( Status *s, Arena *a, usize alignment ) {
+ END_IF_NOK( *s );
- if( a->claimed - a->taken < amount ) { /* no overflow risk this way */
- return S_FAILURE | ERR_OUT_OF_BOUND;
- }
+ u64 take_amount = u64_round_up( s, a->taken, alignment ) - a->taken;
+
+ if( take_amount ) {
+ (void)Arena_take( s, a, take_amount );
+ }
+
+end:
+ return;
+}
+
+void* Arena_take( Status *s, Arena *a, usize amount ) {
+ void *ret = 0;
+ END_IF_NOK( *s );
- u64 new_taken = a->taken + amount;
+ if( amount == 0 ) {
+ ERRORING_FAIL( S_FAILURE | ERR_INVALID_ARGUMENT | ERRSRC_ARG_3 );
+ return 0;
+ }
- if( new_taken > a->occupied ) {
- u64 occupy_amount = 0;
+ if( a->claimed - a->taken < amount ) { /* no overflow risk this way */
+ ERRORING_FAIL( S_FAILURE | ERR_OUT_OF_BOUND );
+ return 0;
+ }
- TRY( u64_round_up( new_taken - a->occupied , sizeof(Page), &occupy_amount ) );
- TRY( mem_occupy( a->start + a->occupied/sizeof(Page), occupy_amount/0x1000 ) );
-
- a->occupied += occupy_amount;
- }
+ u64 new_taken = a->taken + amount;
- *out = ((u8*)a->start + a->taken);
- a->taken = new_taken;
+ if( new_taken > a->occupied ) {
+ u64 occupy_amount = u64_round_up( s, new_taken - a->occupied, sizeof(Page) );
+ mem_occupy( s, a->start + a->occupied/sizeof(Page), occupy_amount/0x1000 );
- return S_SUCCESS;
+ END_IF_NOK( *s );
+ a->occupied += occupy_amount;
}
- Status Arena_give( Arena *a, usize amount ) {
- if( amount > a->taken ) return S_FAILURE | ERR_OUT_OF_BOUND;
- a->taken -= amount;
- return S_SUCCESS;
+ ret = ((u8*)a->start + a->taken);
+ a->taken = new_taken;
+end:
+ return ret;
+}
+
+void Arena_give( Status *s, Arena *a, usize amount ) {
+ END_IF_NOK( *s );
+
+ if( amount > a->taken ) {
+ DEBUG(breakpoint());
+ *s = S_FAILURE | ERR_OUT_OF_BOUND;
+ return;
}
+ a->taken -= amount;
+end:
+ return;
+}
+
+
/*================================ Heap ======================================*/
+
+Heap Heap_create( Status *s, usize size ) {
+ Heap ret = {0};
+ END_IF_NOK( *s );
+
+ if( size == 0 ) {
+ ERRORING_FAIL( S_FAILURE | ERR_INVALID_ARGUMENT | ERRSRC_ARG_2 );
+ /* notice no separate return, cause ret is alread 0 */
+ } else {
+ ret.arena = Arena_create( s, size );
+ }
+
+end:
+ return ret;
+}
+
+void Heap_destroy( Status *s, Heap *h ) {
+ if( h == 0 ) {
+ return;
+ }
+
+ Status local_status = S_SUCCESS;
+ Arena_destroy( &local_status, &h->arena );
+
+ END_IF_NOK( *s );
+ mem_set( h, sizeof(*h), 0 );
+
+end:
+ if( S_OK(*s) && S_NOK( local_status ) ) {
+ *s = local_status;
+ }
+ return;
+}
+
#if BUILD_TYPE == BUILD_DEBUG
static inline Status _Heap_find_block( Heap *h, HeapEntry *e, HeapEntry **out_prev ) {
u8 ptr_correct = 0;
@@ -163,36 +222,28 @@ void *memcpy( void *dest, const void *src, unsigned long n ) {
return e->size;
}
- Status Heap_create( Heap *out, usize size ) {
- assert( out != 0 );
- assert( size != 0 );
- TRY( Arena_create( &out->arena, size ) );
- out->freelist = (HeapEntry){0};
- out->blocklist = (HeapEntry){0};
- return S_SUCCESS;
- }
+ void* Heap_alloc( Status *s, Heap *h, usize amount ) {
+ if( h == 0 ) {
+ ERRORING_FAIL( S_FAILURE | ERR_INVALID_ARGUMENT | ERRSRC_ARG_2 );
+ return 0;
+ }
- Status Heap_destroy( Heap *h ) {
- assert( h != 0 );
- TRY( Arena_destroy( &h->arena ) );
- mem_set( h, sizeof(*h), 0 );
- return S_SUCCESS;
- }
+ if( amount == 0 ) {
+ ERRORING_FAIL( S_FAILURE | ERR_INVALID_ARGUMENT | ERRSRC_ARG_3 );
+ return 0;
+ }
- Status Heap_alloc( Heap *h, usize amount, void **out ) {
- assert( h != 0 );
- assert( amount > 0 ); /* If your code can try to allocate 0 amount of memory you should consider rewriting it (or getting some help) */
+ void *ret = 0;
- TRY( usize_round_up( amount, sizeof(usize), &amount ) );
+ amount = usize_round_up( s, amount, sizeof(usize) );
usize total_amount = amount + sizeof(HeapEntry) + sizeof(usize); /* usize for end guard */
HeapEntry *new = 0;
HeapEntry *prev = &h->freelist;
- usize max_size = 0;
- TRY( usize_mul(total_amount, 4, &max_size) );
+ usize max_size = usize_mul(s, total_amount, 4 );
+ END_IF_NOK( *s );
-
for( HeapEntry *i = h->freelist.next; i != 0; i = i->next ) {
u8* data = (u8*)(&i->header_end_guard + 1);
@@ -212,7 +263,8 @@ void *memcpy( void *dest, const void *src, unsigned long n ) {
}
if( !new ) {
- TRY( Arena_take( &h->arena, total_amount, (u8**)&new ) );
+ new = Arena_take( s, &h->arena, total_amount );
+ END_IF_NOK( *s );
new->allowed_size = amount;
}
@@ -229,32 +281,38 @@ void *memcpy( void *dest, const void *src, unsigned long n ) {
new->header_end_guard = HEAP_HEADER_GUARD_NUMBER;
_Heap_link_block( h, new );
- *out = data;
-
- return S_SUCCESS;
+ ret = data;
+ end:
+ return ret;
}
- Status Heap_free( Heap *h, void **ptr ) {
- assert( h != 0 );
- assert( ptr != 0 );
+ void Heap_free( Status *s, Heap *h, void *ptr ) {
- HeapEntry *e = (HeapEntry*)( (u8*)*ptr - sizeof(HeapEntry) );
+ if( ptr == 0 ) {
+ return;
+ } else {
- HeapEntry *prev = 0;
+ if( h == 0 ) {
+ if( S_OK( *s ) ) *s = S_FAILURE | ERR_INVALID_ARGUMENT | ERRSRC_ARG_2;
+ DEBUG(breakpoint());
+ return;
+ }
- assert(S_OK( _Heap_find_block( h, e, &prev ) ));
- assert(S_OK( _Heap_check_entry( e ) ));
+ HeapEntry *e = (HeapEntry*)( (u8*)ptr - sizeof(HeapEntry) );
- _Heap_unlink_entry( prev, e );
- _Heap_link_free_entry( h, e );
+ HeapEntry *prev = 0;
- u8* data = (u8*)(&e->header_end_guard + 1);
- mem_set( data, e->allowed_size, MAGIC_FREED_MEM );
- *(usize*)(data + e->allowed_size) = HEAP_OVERRUN_GUARD_NUMBER;
+ assert(S_OK( _Heap_find_block( h, e, &prev ) ));
+ assert(S_OK( _Heap_check_entry( e ) ));
- *ptr = 0;
+ _Heap_unlink_entry( prev, e );
+ _Heap_link_free_entry( h, e );
- return S_SUCCESS;
+ u8* data = (u8*)(&e->header_end_guard + 1);
+ mem_set( data, e->allowed_size, MAGIC_FREED_MEM );
+ *(usize*)(data + e->allowed_size) = HEAP_OVERRUN_GUARD_NUMBER;
+
+ }
}
#elif BUILD_TYPE == BUILD_RELEASE
@@ -264,98 +322,100 @@ void *memcpy( void *dest, const void *src, unsigned long n ) {
return *((usize*)ptr - 1);
}
- Status Heap_create( Heap *out, usize size ) {
- TRY( Arena_create( &out->arena, size ) );
- out->freelist = (HeapEntry){0};
- out->freelist_data = 0;
- return S_SUCCESS;
- }
-
- Status Heap_destroy( Heap *h ) {
- TRY( Arena_destroy( &h->arena ) );
- h->freelist = (HeapEntry){0};
- h->freelist_data = 0;
- return S_SUCCESS;
- }
+ void* Heap_alloc( Status *s, Heap *h, usize amount ) {
- Status Heap_alloc( Heap *h, usize amount, void **out ) {
- if( amount == 0 ) return S_FAILURE | ERR_INVALID_ARGUMENT | ERRSRC_ARG_2;
+ if( amount == 0 ) {
+ ERRORING_FAIL( S_FAILURE | ERR_INVALID_ARGUMENT | ERRSRC_ARG_2 );
+ return 0;
+ }
usize required_amount = usize_max(amount, sizeof(void*)); /* A pointer must fit into data, otherwise it can not be linked into the freelist when freed. */
- TRY( usize_add( required_amount, sizeof(HeapEntry), &required_amount ) );
- TRY( usize_round_up( required_amount, sizeof(usize), &required_amount ) ); /* word-align */
+ required_amount = usize_add( s, required_amount, sizeof(HeapEntry) );
+ required_amount = usize_round_up( s, required_amount, sizeof(usize) ); /* word-align */
+
+ void *ret = 0;
HeapEntry *new = 0;
-
- /* Check freelist */
HeapEntry *prev = &h->freelist;
+ usize max_size = usize_mul( s, required_amount, 4 );
- usize max_size = 0;
- TRY( usize_mul(required_amount, 4, &max_size) );
+ END_IF_NOK( *s )
for( HeapEntry *i = h->freelist_data; i != 0; i = *(HeapEntry**)(&i->size + 1) ) {
- if( i->size >= required_amount && i->size <= max_size ) {
- new = i;
- *(HeapEntry**)(&prev->size + 1) = *(HeapEntry**)(&new->size + 1); /* unlink entry */
- break;
- }
- prev = i;
+ usize cur_entry_size = i->size+sizeof(HeapEntry);
+ if( cur_entry_size + sizeof(HeapEntry) >= required_amount && cur_entry_size + sizeof(HeapEntry) <= max_size ) {
+ new = i;
+ *(HeapEntry**)(&prev->size + 1) = *(HeapEntry**)(&new->size + 1); /* unlink entry */
+ break;
+ }
+ prev = i;
}
/* New allocation */
if( !new ) {
- TRY( Arena_take( &h->arena, required_amount, (u8**)&new ) );
- new->size = required_amount;
- }
- /* otherwise we leave original size */
+ new = Arena_take( s, &h->arena, required_amount);
- *out = (u8*)(&new->size + 1);
+ END_IF_NOK( *s )
- return S_SUCCESS;
+ new->size = required_amount - sizeof(HeapEntry);
+ } /* otherwise we leave original size */
+ ret = (u8*)(&new->size + 1);
+ end:
+ return ret;
}
- Status Heap_free( Heap *h, void **ptr ) {
- if( h == 0 ) return S_FAILURE | ERR_INVALID_ARGUMENT | ERRSRC_ARG_1;
- if( ptr == 0 ) return S_FAILURE | ERR_INVALID_ARGUMENT | ERRSRC_ARG_2;
-
- HeapEntry *e = (HeapEntry*)( (u8*)*ptr - sizeof(HeapEntry) );
-
- /* Link into freelist */
- *((HeapEntry**)(&e->size + 1)) = h->freelist_data;
- h->freelist_data = e;
+ void Heap_free( Status *s, Heap *h, void *ptr ) {
+ if( ptr == 0 ) {
+ return;
+ } else {
+ if( h == 0 ) {
+ if( S_OK( *s ) ) *s = S_FAILURE | ERR_INVALID_ARGUMENT | ERRSRC_ARG_2;
+ return;
+ }
- *ptr = 0;
+ HeapEntry *e = (HeapEntry*)( (u8*)ptr - sizeof(HeapEntry) );
- return S_SUCCESS;
+ /* Link into freelist */
+ *((HeapEntry**)(&e->size + 1)) = h->freelist_data;
+ h->freelist_data = e;
+ }
}
#endif
/*=============================== Arrays =====================================*/
-Status AnyArr_create( usize count, AnyArr **out, Heap *h, usize elem_size ) {
+AnyArr* AnyArr_create( Status *s, usize count, Heap *h, usize elem_size ) {
+ AnyArr *ret = 0;
+ END_IF_NOK( *s );
+
usize alloc_count = count;
DEBUG( alloc_count++ ); /* additional poisoned element in debug */
usize alloc_size = sizeof(AnyArr) + alloc_count*elem_size;
- TRY( Heap_alloc( h, alloc_size, (void**)out ) );
- (*out)->len = 0;
+ ret = Heap_alloc( s, h, alloc_size );
+
+ END_IF_NOK( *s );
+
+ ret->len = 0;
DEBUG(
- (*out)->heap = h;
- _AnyArr_update_checksum( *out )
+ ret->heap = h;
+ _AnyArr_update_checksum( ret )
);
- return S_SUCCESS;
+
+end:
+ return ret;
}
-Status AnyArr_destroy( AnyArr** arr, Heap *h ) {
+void AnyArr_destroy( Status *s, AnyArr** arr, Heap *h ) {
+
DEBUG(
assert( h == (*arr)->heap );
_AnyArr_validate( *arr );
)
- TRY( Heap_free( h, (void**)arr ) );
- return S_SUCCESS;
+ Heap_free( s, h, *arr );
}
#if BUILD_TYPE == BUILD_DEBUG
@@ -372,66 +432,46 @@ Status AnyArr_destroy( AnyArr** arr, Heap *h ) {
#endif
-Status AnyArr_inflate( AnyArr **arr, usize additional_count, Heap *h, usize elem_size ) {
+AnyArr* AnyArr_inflate( Status *s, AnyArr *arr, usize additional_count, Heap *h, usize elem_size ) {
+ AnyArr *ret = arr;
+
+ END_IF_NOK( *s );
+
DEBUG(
- assert( h == (*arr)->heap );
- _AnyArr_validate( *arr );
+ assert( h == arr->heap );
+ _AnyArr_validate( arr );
)
if( additional_count == 0 ) {
- return S_COMPLETION;
+ *s = S_COMPLETION;
+ return arr;
}
- usize newsize = ((*arr)->len + additional_count)*elem_size + sizeof(AnyArr);
+ usize newsize = (arr->len + additional_count)*elem_size + sizeof(AnyArr);
DEBUG( newsize += elem_size; )
- AnyArr *newarr = 0;
- TRY( Heap_alloc( h, newsize, (void**)&newarr ) );
-
- usize total_size = (*arr)->len*elem_size + sizeof(AnyArr);
- DEBUG( total_size += elem_size; )
-
- mem_copy( (*arr), newarr, total_size );
- newarr->len = (*arr)->len;
+ ret = Heap_alloc( s, h, newsize );
- DEBUG( _AnyArr_update_checksum( *arr ) );
-
- TRY( Heap_free( h, (void**)arr ) );
- *arr = newarr;
- return S_SUCCESS;
-}
+ END_IF_NOK( *s );
-Status AnyArr_extend( AnyArr **arr, usize additional_len, Heap *h, usize elem_size ) {
- DEBUG(
- assert( (*arr)->heap == h );
- _AnyArr_validate( *arr );
- usize old_len = (*arr)->len;
- )
+ usize total_size = arr->len*elem_size + sizeof(AnyArr);
+ DEBUG( total_size += elem_size; )
- usize asize = Heap_get_asize( h, *arr );
- usize maxcount = asize - sizeof(AnyArr);
- DEBUG( maxcount--);
- maxcount /= elem_size;
- usize newlen = (*arr)->len + additional_len;
+ mem_copy( arr, ret, total_size );
- if( newlen >= maxcount ) {
- TRY( AnyArr_inflate( arr, additional_len, h, elem_size ) );
- }
+ DEBUG( _AnyArr_update_checksum( ret ) );
- (*arr)->len += additional_len;
+ /* Don't want to free the original if we couldn't grow it, hence it's
+ * jumped over if the heap alloc fails - otherwise we risk double-free. */
+ Heap_free( s, h, arr );
- DEBUG(
-
- u8 *data = (u8*)((*arr) + 1);
- u8 *uninint = data + newlen*elem_size;
- mem_set( uninint, (newlen - old_len)*elem_size, MAGIC_UNINITIALIZED_MEM );
- _AnyArr_update_checksum( *arr );
- )
-
- return S_SUCCESS;
+end:
+ return ret;
}
-Status AnyArr_truncate( AnyArr *arr, usize cutlen, usize elem_size ) {
+void AnyArr_truncate( Status *s, AnyArr *arr, usize cutlen, usize elem_size ) {
+ END_IF_NOK( *s );
+
DEBUG(
_AnyArr_validate( arr );
usize old_len = arr->len;
@@ -441,8 +481,8 @@ Status AnyArr_truncate( AnyArr *arr, usize cutlen, usize elem_size ) {
)
if( cutlen > arr->len ) {
- DEBUG( assert(0) );
- return S_FAILURE | ERR_INVALID_ARGUMENT | ERRSRC_ARG_2;
+ ERRORING_FAIL( S_FAILURE | ERR_INVALID_ARGUMENT | ERRSRC_ARG_2 );
+ return;
}
arr->len -= cutlen;
@@ -455,103 +495,82 @@ Status AnyArr_truncate( AnyArr *arr, usize cutlen, usize elem_size ) {
_AnyArr_update_checksum( arr );
)
-
- return S_SUCCESS;
+end:
+ return;
}
-Status AnyArr_deflate( AnyArr **arr, Heap *h, usize elem_size ) { /* reallocate to just fit the currently contained elements - we assume it's on the same heap */
- DEBUG(
- assert( h == (*arr)->heap );
- _AnyArr_validate( (*arr) );
- )
-
- usize total_size = (*arr)->len*elem_size + sizeof(AnyArr);
- DEBUG( total_size += elem_size; )
+AnyArr* AnyArr_deflate( Status *s, AnyArr *arr, Heap *h, usize elem_size ) {
+ AnyArr *ret = arr;
+ END_IF_NOK( *s );
- AnyArr *out = 0;
- TRY( Heap_alloc( h, total_size, (void**)&out ) );
- mem_copy( *arr, out, total_size );
- TRY( Heap_free( h, (void**)arr ) );
-
- *arr = out;
-
- DEBUG( _AnyArr_update_checksum( *arr ) );
-
- return S_SUCCESS;
-}
-
-Status AnyArr_copy( const AnyArr *arr, AnyArr **out, Heap *source_heap, Heap *target_heap, usize maxcount, usize len, usize elem_size ) {
DEBUG(
- assert( source_heap == arr->heap );
+ assert( h == arr->heap );
_AnyArr_validate( arr );
)
- usize alloc_size = (maxcount)? maxcount*elem_size + sizeof(AnyArr) : Heap_get_asize( source_heap, arr );
- DEBUG( alloc_size += elem_size );
-
- TRY( Heap_alloc( target_heap, alloc_size, (void**)out ) );
- (*out)->len = len;
+ usize total_size = arr->len*elem_size + sizeof(AnyArr);
+ DEBUG( total_size += elem_size; )
- DEBUG( _AnyArr_update_checksum( *out ); )
+ ret = voidp_by_status( s, Heap_alloc( s, h, total_size ), arr ); /* standard C guarantees that function arguments are evaluated before the function call, so s's state should propagate correctly */
+ END_IF_NOK( *s );
- mem_copy( arr + 1, *out + 1, len*elem_size );
+ mem_copy( arr, ret, total_size );
+ Heap_free( s, h, arr );
- DEBUG(
- u8* data = (u8*)(arr + 1);
- usize data_size = len*elem_size;
- u8* poison_start = data + data_size;
- usize poison_amount = alloc_size - data_size - sizeof(AnyArr);
- DEBUG( poison_amount += elem_size );
+ DEBUG( _AnyArr_update_checksum( ret ) );
- mem_set( poison_start, poison_amount, MAGIC_POISONED_MEM );
- )
- return S_SUCCESS;
+end:
+ return ret;
}
-Status AnyArr_move( AnyArr **arr, AnyArr **out, Heap *source_heap, Heap *target_heap, usize maxcount, usize len, usize elem_size ) {
- TRY( AnyArr_copy( *arr, out, source_heap, target_heap, maxcount, len, elem_size ) );
- TRY( Heap_free( source_heap, (void**)arr ) );
- return S_SUCCESS;
-}
+AnyArr* AnyArr_push( Status *s, AnyArr *arr, void* el, Heap *h, usize elem_size ) {
+ AnyArr *ret = arr;
+ END_IF_NOK( *s );
-Status AnyArr_push( AnyArr **arr, void* el, Heap *h, usize elem_size ) {
DEBUG(
- assert( h == (*arr)->heap );
- _AnyArr_validate( *arr );
+ assert( h == arr->heap );
+ _AnyArr_validate( arr );
)
- usize s = Heap_get_asize(h, *arr);
- usize maxcount = (s - sizeof(AnyArr))/elem_size;
+ usize asize = Heap_get_asize(h, arr);
+ usize maxcount = (asize - sizeof(AnyArr))/elem_size;
DEBUG(
maxcount--; /* Additional poisoned element */
);
- if( (*arr)->len >= maxcount ) {
- AnyArr_inflate( arr, (*arr)->len, h, elem_size );
+
+ if( arr->len == maxcount ) {
+ ret = AnyArr_inflate( s, arr, arr->len, h, elem_size );
}
- u8 *data = (u8*)(*arr + 1);
- void *new_elem = data + (*arr)->len*elem_size;
+ END_IF_NOK( *s );
+
+ u8 *data = (u8*)(ret + 1);
+ void *new_elem = data + ret->len*elem_size;
mem_copy( el, new_elem, elem_size );
- (*arr)->len++;
+ ret->len++;
DEBUG(
- _AnyArr_update_checksum( *arr );
- mem_set( data + ((*arr)->len)*elem_size, elem_size, MAGIC_POISONED_MEM );
+ _AnyArr_update_checksum( ret );
+ mem_set( data + (ret->len)*elem_size, elem_size, MAGIC_POISONED_MEM );
)
- return S_SUCCESS;
+end:
+ return ret;
}
-Status AnyArr_pop( AnyArr *arr, void* el_out, usize elem_size ) {
+void AnyArr_pop( Status *s, AnyArr *arr, void* el_out, usize elem_size ) {
+ END_IF_NOK( *s );
+
DEBUG(
_AnyArr_validate( arr );
)
+
if( arr->len == 0 ) {
- DEBUG( assert(0) );
- return ERR_OUT_OF_BOUND;
+ ERRORING_FAIL( S_FAILURE | ERR_OUT_OF_BOUND );
+ return;
}
arr->len--;
@@ -564,17 +583,25 @@ Status AnyArr_pop( AnyArr *arr, void* el_out, usize elem_size ) {
_AnyArr_update_checksum( arr );
mem_set( data + offset, elem_size, MAGIC_POISONED_MEM );
)
- return S_SUCCESS;
+
+end:
+ return;
}
-Status AnyArr_dup( const AnyArr *arr, AnyArr **out_arr, Heap *h, usize elem_size ) {
+AnyArr* AnyArr_dup( Status *s, const AnyArr *arr, Heap *h, usize elem_size ) {
+ AnyArr *ret = 0;
+ END_IF_NOK( *s );
+
DEBUG( _AnyArr_validate( arr );)
usize total_size = arr->len*elem_size + sizeof(AnyArr);
- TRY( Heap_alloc( h, total_size, (void**)out_arr ) );
- mem_copy( arr, *out_arr, total_size );
+ ret = Heap_alloc( s, h, total_size );
+ END_IF_NOK( *s );
+
+ mem_copy( arr, ret, total_size );
- return S_SUCCESS;
+end:
+ return ret;
}
/*================================= String ===================================*/
@@ -588,21 +615,25 @@ u8 Str_equals( const Str *s1, const Str *s2 ) {
return 1;
}
-Status StrSlc_from_Str( StrSlc *out, const Str *s, usize start, usize len ) {
- if( start > s->len ) {
- DEBUG( assert(0) );
- return S_FAILURE | ERR_OUT_OF_BOUND | ERRSRC_ARG_3;
+StrSlc StrSlc_from_Str( Status *s, const Str *str, usize start, usize len ) {
+ StrSlc ret = {0};
+ END_IF_NOK( *s );
+
+ if( start > str->len ) {
+ ERRORING_FAIL( S_FAILURE | ERR_OUT_OF_BOUND | ERRSRC_ARG_3 );
+ goto end;
}
- if( s->len >= len && s->len - len < start ) {
- DEBUG( assert(0) );
- return S_FAILURE | ERR_OUT_OF_BOUND | ERRSRC_ARG_3;
+ if( str->len >= len && str->len - len < start ) {
+ ERRORING_FAIL( S_FAILURE | ERR_OUT_OF_BOUND | ERRSRC_ARG_3 );
+ goto end;
}
- out->data = &s->data[start];
- out->len = len;
+ ret.data = &str->data[start];
+ ret.len = len;
- return S_SUCCESS;
+end:
+ return ret;
}
u8 StrSlc_equals( const StrSlc sl1, const StrSlc sl2 ) {
@@ -667,17 +698,22 @@ u8 StrSlc_equals_Str_by_ref( const StrSlc *sl, const Str *s ) {
return 1;
}
-Status StrSlc_split_by_u8( const StrSlc *sl, u8 separator, StrSlcs **out, Heap *h ) {
+StrSlcs* StrSlc_split_by_u8( Status *s, const StrSlc *sl, u8 separator, Heap *h ) {
+ if( !S_OK(*s) ) return 0;
+
+ StrSlcs *ret = StrSlcs_create( s, h, 16 );
+
+ END_IF_NOK( *s );
+
StrSlc new_sl = {
.data = sl->data,
.len = 0
};
- TRY( StrSlcs_create( h, 16, out ) );
-
for( usize i = 0; i < sl->len; ++i ) {
if( sl->data[i] == separator ) {
- TRY( StrSlcs_push( out, &new_sl, h ) );
+ ret = StrSlcs_push( s, ret, &new_sl, h );
+ if( !S_OK(*s) ) return ret;
new_sl.data = &(sl->data[i+1]);
new_sl.len = 0;
} else {
@@ -685,24 +721,44 @@ Status StrSlc_split_by_u8( const StrSlc *sl, u8 separator, StrSlcs **out, Heap *
}
}
- return S_SUCCESS;
+end:
+ return ret;
}
/* String Assembler */
-Status StrAsm_create( StrAsm *out, usize max_size ) {
- return Arena_create( &out->a, max_size );
+StrAsm StrAsm_create( Status *s, usize max_size ) {
+ StrAsm ret = {0};
+ END_IF_NOK( *s );
+
+ ret.a = Arena_create( s, max_size );
+
+end:
+ return ret;
}
-Status StrAsm_reset( StrAsm *out ) {
- return Arena_give( &out->a, out->a.taken );
+void StrAsm_reset( Status *s, StrAsm *sa ) {
+ END_IF_NOK( *s );
+ Arena_give( s, &sa->a, sa->a.taken );
+end:
+ return;
}
-Status StrAsm_destroy( StrAsm *out ) {
- return Arena_destroy( &out->a );
+void StrAsm_destroy( Status *s, StrAsm *sa ) {
+ Status ls = S_SUCCESS;
+
+ if( sa ) {
+ Arena_destroy( &ls, &sa->a );
+ }
+
+ if( S_OK(*s) && S_NOK(ls) ) {
+ *s = ls;
+ }
}
-Status StrAsm_store_into_arena( StrAsm *sa, Arena *dst, Str **out ) {
+void StrAsm_store_into_arena( Status *s, StrAsm *sa, Arena *dst, Str **out ) {
+ END_IF_NOK( *s );
+
usize len = sa->a.taken;
#if OS != OS_NONE
@@ -710,14 +766,15 @@ Status StrAsm_store_into_arena( StrAsm *sa, Arena *dst, Str **out ) {
#endif
u8 *p = 0;
- TRY( Arena_take( dst, len, &p ) );
+ p = Arena_take( s, dst, len );
+ END_IF_NOK( *s );
#if OS != OS_NONE
p[len] = 0; /* We need the NUL in case this string is used in a syscall
- - it has to be an actual string */
+ - it has to be an actual C string */
#endif
- *out = (Str*)p;
+ *out = (Str*)p;
#if OS != OS_NONE
(*out)->len = len - 1;
@@ -727,10 +784,13 @@ Status StrAsm_store_into_arena( StrAsm *sa, Arena *dst, Str **out ) {
mem_copy( sa->a.start, &(*out)->data, len );
- return S_SUCCESS;
+end:
+ return;
}
-Status StrAsm_store_onto_heap( StrAsm *sa, Heap *dst, Str **out ) {
+void StrAsm_store_onto_heap( Status *s, StrAsm *sa, Heap *dst, Str **out ) {
+ if( !S_OK(*s) ) return;
+
usize len = sa->a.taken;
#if OS != OS_NONE
@@ -738,7 +798,8 @@ Status StrAsm_store_onto_heap( StrAsm *sa, Heap *dst, Str **out ) {
#endif
void *p = 0;
- TRY( Heap_alloc( dst, len, &p ) );
+ p = Heap_alloc( s, dst, len );
+ END_IF_NOK( *s )
#if OS != OS_NONE
((u8*)p)[len] = 0;
@@ -754,7 +815,8 @@ Status StrAsm_store_onto_heap( StrAsm *sa, Heap *dst, Str **out ) {
mem_copy( sa->a.start, &(*out)->data, len );
- return S_SUCCESS;
+end:
+ return;
}
StrSlc StrAsm_as_StrSlc( const StrAsm *sa ) {
@@ -762,36 +824,65 @@ StrSlc StrAsm_as_StrSlc( const StrAsm *sa ) {
}
-Status StrAsm_cat_char ( StrAsm *sa, u8 value ) {
- u8 *data = 0;
- TRY( Arena_take( &sa->a, sizeof(value), &data ) );
- *data = value;
- return S_SUCCESS;
+void StrAsm_cat_char ( Status *s, StrAsm *sa, u8 value ) {
+ END_IF_NOK( *s );
+
+ u8 *data = Arena_take( s, &sa->a, sizeof(value) );
+
+ ENCHAIN( *s,
+ *data = value;
+ )
+
+end:
+ return;
}
-Status StrAsm_cat_Str( StrAsm *sa, const Str *s ) {
- u8 *data = 0;
- TRY( Arena_take( &sa->a, s->len, &data ) );
- mem_copy( &s->data, data, s->len );
- return S_SUCCESS;
+void StrAsm_cat_Str( Status *s, StrAsm *sa, const Str *str ) {
+ END_IF_NOK( *s );
+
+ u8 *data = Arena_take( s, &sa->a, str->len );
+ END_IF_NOK( *s );
+
+ mem_copy( &str->data, data, str->len );
+
+end:
+ return;
}
-Status StrAsm_cat_StrSlc( StrAsm *sa, StrSlc sl ) {
+void StrAsm_cat_StrSlc( Status *s, StrAsm *sa, StrSlc sl ) {
+ END_IF_NOK( *s );
+
+ if( sl.len == 0 ) {
+ *s = S_COMPLETION;
+ return;
+ }
+
u8 *data = 0;
- if( sl.len == 0 ) return S_COMPLETION;
- TRY( Arena_take( &sa->a, sl.len, &data ) );
+ data = Arena_take( s, &sa->a, sl.len );
+ END_IF_NOK( *s );
+
mem_copy( sl.data, data, sl.len );
- return S_SUCCESS;
+
+end:
+ return;
}
-Status StrAsm_cat_StrSlc_by_ref( StrAsm *sa, const StrSlc *sl ) {
- u8 *data = 0;
- if( sl->len == 0 ) return S_COMPLETION;
+void StrAsm_cat_StrSlc_by_ref( Status *s, StrAsm *sa, const StrSlc *sl ) {
+ END_IF_NOK( *s );
+
+ if( sl->len == 0 ) {
+ *s = S_COMPLETION;
+ return;
+ }
+
+ u8 *data = Arena_take( s, &sa->a, sl->len );
+ END_IF_NOK( *s );
- TRY( Arena_take( &sa->a, sl->len, &data ) );
mem_copy( sl->data, data, sl->len );
- return S_SUCCESS;
+
+end:
+ return;
}
@@ -820,32 +911,34 @@ static inline u8* _write_hex_prefix( u8* start ) {
return start + 2;
}
-static inline Status _write_bin_as_hex_into_arena( u8* data, Arena *a, usize len ) {
- u8 *out = 0;
- TRY( Arena_take( a, 2*len + 2, &out ) );
+static inline void _write_bin_as_hex_into_arena( Status *s, u8* data, Arena *a, usize len ) {
+ u8 *out = Arena_take( s, a, 2*len + 2 );
+ END_IF_NOK( *s );
+
out = _write_hex_prefix( out );
_bin_to_hex_ascii( data, out, len );
- return S_SUCCESS;
+end:
+ return;
}
-Status StrAsm_fmtx_u8 ( StrAsm *sa, u8 value) {
- return _write_bin_as_hex_into_arena( &value, &sa->a, sizeof(value) );
+void StrAsm_fmtx_u8 ( Status *s, StrAsm *sa, u8 value) {
+ _write_bin_as_hex_into_arena( s, &value, &sa->a, sizeof(value) );
}
-Status StrAsm_fmtx_u16( StrAsm *sa, u16 value) {
- return _write_bin_as_hex_into_arena( (u8*)&value, &sa->a, sizeof(value) );
+void StrAsm_fmtx_u16( Status *s, StrAsm *sa, u16 value) {
+ _write_bin_as_hex_into_arena( s, (u8*)&value, &sa->a, sizeof(value) );
}
-Status StrAsm_fmtx_u32( StrAsm *sa, u32 value) {
- return _write_bin_as_hex_into_arena( (u8*)&value, &sa->a, sizeof(value) );
+void StrAsm_fmtx_u32( Status *s, StrAsm *sa, u32 value) {
+ _write_bin_as_hex_into_arena( s, (u8*)&value, &sa->a, sizeof(value) );
}
-Status StrAsm_fmtx_u64( StrAsm *sa, u64 value) {
- return _write_bin_as_hex_into_arena( (u8*)&value, &sa->a, sizeof(value) );
+void StrAsm_fmtx_u64( Status *s, StrAsm *sa, u64 value) {
+ _write_bin_as_hex_into_arena( s, (u8*)&value, &sa->a, sizeof(value) );
}
-static inline Status _write_u64_as_dec_into_arena( u64 value, Arena *a ) {
+static inline void _write_u64_as_dec_into_arena( Status *s, u64 value, Arena *a ) {
u8 digits[21] = {0};
u8 *p = &digits[21];
@@ -855,32 +948,31 @@ static inline Status _write_u64_as_dec_into_arena( u64 value, Arena *a ) {
value /= 10;
} while(value);
-
- u8 *out = 0;
usize n = &digits[21] - p;
- TRY( Arena_take( a, n, &out ) );
- mem_copy( p, out, n );
-
- return S_SUCCESS;
+ u8 *out = Arena_take( s, a, n );
+
+ ENCHAIN( *s,
+ mem_copy( p, out, n );
+ )
}
-Status StrAsm_fmtd_u8 ( StrAsm *sa, u8 value) {
- return _write_u64_as_dec_into_arena( value, &sa->a );
+void StrAsm_fmtd_u8 ( Status *s, StrAsm *sa, u8 value) {
+ _write_u64_as_dec_into_arena( s, value, &sa->a );
}
-Status StrAsm_fmtd_u16( StrAsm *sa, u16 value) {
- return _write_u64_as_dec_into_arena( value, &sa->a );
+void StrAsm_fmtd_u16( Status *s, StrAsm *sa, u16 value) {
+ _write_u64_as_dec_into_arena( s, value, &sa->a );
}
-Status StrAsm_fmtd_u32( StrAsm *sa, u32 value) {
- return _write_u64_as_dec_into_arena( value, &sa->a );
+void StrAsm_fmtd_u32( Status *s, StrAsm *sa, u32 value) {
+ _write_u64_as_dec_into_arena( s, value, &sa->a );
}
-Status StrAsm_fmtd_u64( StrAsm *sa, u64 value) {
- return _write_u64_as_dec_into_arena( value, &sa->a );
+void StrAsm_fmtd_u64( Status *s, StrAsm *sa, u64 value) {
+ _write_u64_as_dec_into_arena( s, value, &sa->a );
}
-static inline Status _write_s64_as_dec_into_arena( s64 value, Arena *a ) {
+static inline void _write_s64_as_dec_into_arena( Status *s, s64 value, Arena *a ) {
u8 negative = (value < 0);
u8 digits[21] = {0};
@@ -899,26 +991,26 @@ static inline Status _write_s64_as_dec_into_arena( s64 value, Arena *a ) {
n++;
*--p = '-';
}
- TRY( Arena_take( a, n, &out ) );
- mem_copy( p, out, n );
-
- return S_SUCCESS;
+ out = Arena_take( s, a, n );
+ ENCHAIN( *s,
+ mem_copy( p, out, n );
+ )
}
-Status StrAsm_fmtd_s8 ( StrAsm *sa, s8 value) {
- return _write_s64_as_dec_into_arena( value, &sa->a );
+void StrAsm_fmtd_s8 ( Status *s, StrAsm *sa, s8 value) {
+ _write_s64_as_dec_into_arena( s, value, &sa->a );
}
-Status StrAsm_fmtd_s16( StrAsm *sa, s16 value) {
- return _write_s64_as_dec_into_arena( value, &sa->a );
+void StrAsm_fmtd_s16 ( Status *s, StrAsm *sa, s16 value) {
+ _write_s64_as_dec_into_arena( s, value, &sa->a );
}
-Status StrAsm_fmtd_s32( StrAsm *sa, s32 value) {
- return _write_s64_as_dec_into_arena( value, &sa->a );
+void StrAsm_fmtd_s32 ( Status *s, StrAsm *sa, s32 value) {
+ _write_s64_as_dec_into_arena( s, value, &sa->a );
}
-Status StrAsm_fmtd_s64( StrAsm *sa, s64 value) {
- return _write_s64_as_dec_into_arena( value, &sa->a );
+void StrAsm_fmtd_s64 ( Status *s, StrAsm *sa, s64 value) {
+ _write_s64_as_dec_into_arena( s, value, &sa->a );
}
@@ -956,7 +1048,8 @@ usize c_strlen( const u8* str ) {
return res;
}
-Status _linux_get_args_and_env( Heap *h, StrSlcs **args, StrSlcs **env ) {
+void _linux_get_args_and_env( Status *s, Heap *h, StrSlcs **args, StrSlcs **env ) {
+ if( !S_OK(*s) ) return;
usize *it = (usize*)_linux_startup_sp;
usize argc = *it;
@@ -964,22 +1057,23 @@ Status _linux_get_args_and_env( Heap *h, StrSlcs **args, StrSlcs **env ) {
/* start with args */
it++;
- *args = 0;
- *env = 0;
+ *args = StrSlcs_create( s, h, argc );
- TRY( StrSlcs_create( h, argc, args ) );
+ if( !S_OK(*s) ) return;
- for( usize i = 0; i < (*args)->len; ++i ) {
- (*args)->data[i] = (StrSlc){
+ for( usize i = 0; i < argc; ++i ) {
+ StrSlc arg = (StrSlc){
.data = (u8*)*(it + i),
.len = c_strlen( (u8*)*(it + i) ),
};
+
+ StrSlcs_push( s, *args, &arg, h );
}
it += argc;
if( *it != 0 ) {
- DEBUG( breakpoint(); );
- return S_FAILURE | ERR_GENERIC | ERRSRC_PLATFORM;
+ ERRORING_FAIL( S_FAILURE | ERR_GENERIC | ERRSRC_PLATFORM );
+ return;
}
/* env */
@@ -991,16 +1085,18 @@ Status _linux_get_args_and_env( Heap *h, StrSlcs **args, StrSlcs **env ) {
}
usize envc = it - envptrs;
- TRY( StrSlcs_create( h, envc, env) );
+ *env = StrSlcs_create( s, h, envc );
- for( usize i = 0; i < (*env)->len; ++i ) {
- (*env)->data[i] = (StrSlc){
+ if( !S_OK(*s) ) return;
+
+ for( usize i = 0; i < envc; ++i ) {
+ StrSlc var = (*env)->data[i] = (StrSlc){
.data = (u8*)*(envptrs + i),
.len = c_strlen( (u8*)*(envptrs + i) ),
};
- }
- return S_SUCCESS;
+ StrSlcs_push( s, *env, &var, h );
+ }
}
#ifndef NOTLIBC_NOMAIN
@@ -1010,16 +1106,27 @@ Status _linux_get_args_and_env( Heap *h, StrSlcs **args, StrSlcs **env ) {
StrSlcs *args = 0;
StrSlcs *env = 0;
- if(!S_OK( Heap_create( &_linux_heap, KiB(16) ) )) {
+ Status s = S_SUCCESS;
+
+ _linux_heap = Heap_create( &s, KiB(16) );
+
+ if( !S_OK(s) ) {
DEBUG( breakpoint(); );
terminate(2);
}
- _linux_get_args_and_env( &_linux_heap, &args, &env );
+ _linux_get_args_and_env( &s, &_linux_heap, &args, &env );
+
+ if( !S_OK(s) ) {
+ DEBUG( breakpoint(); );
+ terminate(2);
+ }
Status res = c_main( args, env );
- if(!S_OK( Heap_destroy( &_linux_heap ) )) {
+ Heap_destroy( &s, &_linux_heap );
+
+ if( !S_OK(s) ) {
DEBUG( breakpoint(); );
terminate(2);
}
@@ -1035,52 +1142,67 @@ Status _linux_get_args_and_env( Heap *h, StrSlcs **args, StrSlcs **env ) {
/*=============================== Memory =====================================*/
-Status mem_claim( u32 page_count, Page **ptr_out) {
- TRY( linux_mmap(
+Page* mem_claim( Status *s, u32 page_count) {
+ void *ptr_out = 0;
+ END_IF_NOK( *s );
+
+ *s = linux_mmap(
0,
page_count*sizeof(Page),
LINUX_PROT_NONE,
MMAP_MAP_PRIVATE | MMAP_MAP_ANONYMOUS,
-1,
0,
- (void**)ptr_out
- ));
+ (void**)&ptr_out
+ );
- return S_SUCCESS;
+end:
+ return ptr_out;
}
-Status mem_relinquish( Page *start, u32 page_count ) {
- usize res = linux_munmap( (usize)start, page_count*sizeof(Page) );
+void mem_relinquish( Status *s, Page *start, u32 page_count ) {
+ END_IF_NOK( *s );
- if( LINUX_SYSCALL_ERROR(res) ) {
- return S_FAILURE | ERRSRC_PLATFORM | ERR_MEM_UNMAP_FAILURE;
- }
-
- return S_SUCCESS;
+ *s = linux_munmap( (usize)start, page_count*sizeof(Page) );
+end:
+ return;
}
-Status mem_occupy( Page *start, u32 page_count ) {
- return linux_mprotect(
+void mem_occupy( Status *s, Page *start, u32 page_count ) {
+ END_IF_NOK( *s );
+
+ *s = linux_mprotect(
(usize)start,
page_count*sizeof(Page),
LINUX_PROT_READ | LINUX_PROT_WRITE
);
+ end:
+ return;
}
-Status mem_vacate( Page *start, u32 page_count ) {
+void mem_vacate( Status *s, Page *start, u32 page_count ) {
+ END_IF_NOK( *s );
+
usize amount = page_count*sizeof(Page);
- TRY( linux_mprotect( (usize)start, amount, LINUX_PROT_NONE ) );
- TRY( linux_madvise( (usize)start, amount, MADV_DONTNEED) );
+ END_IF_NOK( *s );
+ *s = linux_mprotect( (usize)start, amount, LINUX_PROT_NONE );
- return S_SUCCESS;
+ END_IF_NOK( *s );
+ *s = linux_madvise( (usize)start, amount, MADV_DONTNEED);
+
+end:
+ return;
}
/*============================= Filesystem ===================================*/
-Status File_open( const Str *name, usize flags, File *out ) {
+File File_open( Status *s, const Str *name, usize flags ) {
+ File ret = { 0 };
+ END_IF_NOK( *s );
+
DEBUG( assert( name->data[name->len] == 0 ) );
if(
@@ -1088,16 +1210,19 @@ Status File_open( const Str *name, usize flags, File *out ) {
!(flags & FILE_ACCESS_APPEND) &&
(flags & FILE_EXISTING_TRUNCATE)
) {
- DEBUG( breakpoint() ); /* Can not truncate a file without write access. */
- return S_FAILURE | ERR_INVALID_ARGUMENT | ERRSRC_ARG_3;
+ /* Can not truncate a file without write access. */
+ ERRORING_FAIL( S_FAILURE | ERR_INVALID_ARGUMENT | ERRSRC_ARG_3 );
+ goto end;
}
if( (flags & FILE_EXISTING_FAIL) && (flags & FILE_MISSING_FAIL) ) {
- DEBUG( breakpoint() ); /* Useless flag combination: error if there is a file, error if there isn't one aka always error */
- return S_FAILURE | ERR_INVALID_ARGUMENT | ERRSRC_ARG_3;
+ /* Useless flag combination: error if there is a file, error if there isn't one aka always error */
+ ERRORING_FAIL( S_FAILURE | ERR_INVALID_ARGUMENT | ERRSRC_ARG_3 );
+ goto end;
}
- TRY( File_open_validate_flags( flags, ERRSRC_ARG_3 ) );
+ File_open_validate_flags( s, flags, ERRSRC_ARG_3 );
+ END_IF_NOK( *s );
usize syscall_flags = O_CLOEXEC; /* Close all files on exec */
@@ -1124,7 +1249,8 @@ Status File_open( const Str *name, usize flags, File *out ) {
default:
UNREACHABLE;
- return S_FAILURE | ERR_INVALID_ARGUMENT | ERRSRC_ARG_3;
+ ERRORING_FAIL( S_FAILURE | ERR_INVALID_ARGUMENT | ERRSRC_ARG_3 );
+ goto end;
}
switch( flags & FILE_EXISTING_MASK ) {
@@ -1139,7 +1265,8 @@ Status File_open( const Str *name, usize flags, File *out ) {
break;
default:
UNREACHABLE;
- return S_FAILURE | ERR_INVALID_ARGUMENT | ERRSRC_ARG_3;
+ ERRORING_FAIL( S_FAILURE | ERR_INVALID_ARGUMENT | ERRSRC_ARG_3);
+ goto end;
}
switch( flags & FILE_MISSING_MASK ) {
@@ -1151,7 +1278,8 @@ Status File_open( const Str *name, usize flags, File *out ) {
break;
default:
UNREACHABLE;
- return S_FAILURE | ERR_INVALID_ARGUMENT | ERRSRC_ARG_3;
+ ERRORING_FAIL( S_FAILURE | ERR_INVALID_ARGUMENT | ERRSRC_ARG_3 );
+ goto end;
}
switch( flags & FILE_LINK_MASK ) {
@@ -1161,108 +1289,163 @@ Status File_open( const Str *name, usize flags, File *out ) {
case FILE_LINK_FAIL:
syscall_flags |= O_NOFOLLOW;
break;
+ default:
+ UNREACHABLE;
+ ERRORING_FAIL( S_FAILURE | ERR_INVALID_ARGUMENT | ERRSRC_ARG_3 );
+ goto end;
}
- return linux_open( &name->data[0], syscall_flags, 0666, &out->fd );
+ *s = linux_open( &name->data[0], syscall_flags, 0666, &ret.fd );
+
+end:
+ return ret;
}
-Status File_close( File *f ) {
- return linux_close( &f->fd );
+void File_close( Status *s, File *f ) {
+
+ if( f && f->fd ) {
+ Status ls = linux_close( &f->fd );
+ f->fd = 0;
+
+ if( S_OK( *s ) ) {
+ *s = ls;
+ }
+ }
}
-Status File_read( const File *f, usize max_amount, usize *out_amount, u8 *out ) {
- return linux_read( f->fd, max_amount, out_amount, out);
+usize File_read( Status *s, const File *f, usize max_amount, u8 *out ) {
+ usize out_amount = 0;
+ END_IF_NOK( *s );
+
+ *s = linux_read( f->fd, max_amount, &out_amount, out);
+
+end:
+ return out_amount;
}
-Status File_write( const File *f, usize amount, usize *out_amount, const u8 *buf ) {
- return linux_write( f->fd, amount, out_amount, buf );
+usize File_write( Status *s, const File *f, usize amount, const u8 *buf ) {
+ usize out_amount = 0;
+ END_IF_NOK( *s );
+
+ *s = linux_write( f->fd, amount, &out_amount, buf );
+end:
+ return out_amount;
}
-Status File_delete( const Str *name ) {
- return linux_unlink( (const u8*)&name->data );
+void File_seek( Status *s, const File *f, usize position ) {
+ END_IF_NOK( *s );
+ *s = linux_lseek( f->fd, position, SEEK_SET );
+
+end:
+ return;
}
-Status File_seek( const File *f, usize position ) {
- return linux_lseek( f->fd, position, SEEK_SET );
+void File_delete( Status *s, const Str *name ) {
+ END_IF_NOK( *s );
+ DEBUG( assert( name->data[name->len] == 0 ));
+
+ *s = linux_unlink( (const u8*)&name->data );
+
+end:
+ return;
}
-Status FileView_from_file( File *file, usize claim_amount, usize flags, FileView *out ) {
+
+FileView FileView_from_file( Status *s, File *file, usize claim_amount, usize flags ) {
+ FileView ret = {0};
+ END_IF_NOK( *s );
+
DEBUG( assert( claim_amount%sizeof(Page) == 0 ) );
if( claim_amount%sizeof(Page) != 0 ) {
- return ERRSRC_ARG_2 | ERR_INVALID_ARGUMENT;
+ ERRORING_FAIL( ERRSRC_ARG_3 | ERR_INVALID_ARGUMENT );
+ goto end;
}
- TRY( mem_claim( claim_amount/sizeof(Page), &out->start ) );
- out->claimed = claim_amount;
+ if( !file->fd ) {
+ ERRORING_FAIL( ERRSRC_ARG_2 | ERR_INVALID_ARGUMENT );
+ goto end;
+ }
+
+ ret.start = mem_claim( s, claim_amount/sizeof(Page) );
+ END_IF_NOK( *s );
+
+ ret.claimed = claim_amount;
/* Get filesize */
- struct stat s = {0};
- TRY( linux_fstat( file->fd, &s ) );
+ struct stat stat = {0};
+ *s = linux_fstat( file->fd, &stat );
+
+ END_IF_NOK( *s );
- out->filesize = s.st_size;
+ ret.filesize = stat.st_size;
void *discard;
- if( out->filesize > 0 ) { /* Nothing to map in an empty file */
- TRY( linux_mmap(
- (usize)out->start,
- out->filesize,
+ if( ret.filesize > 0 ) { /* Nothing to map in an empty file */
+ *s = linux_mmap(
+ (usize)ret.start,
+ ret.filesize,
LINUX_PROT_READ | LINUX_PROT_WRITE,
MMAP_MAP_FIXED | MMAP_MAP_SHARED,
file->fd,
0,
&discard
- ));
+ );
}
+ END_IF_NOK( *s );
/* Finalize output */
- out->file = *file;
- out->flags = flags;
+ ret.file = *file;
+ ret.flags = flags;
if( flags & FILEVIEW_OWN_FILE ) {
- file->fd = -1;
+ file->fd = 0;
}
- return S_SUCCESS;
+end:
+ return ret;
}
-Status FileView_from_path( const Str *path, usize claim_amount, usize flags, FileView *out ) {
+FileView FileView_from_path( Status *s, const Str *path, usize claim_amount, usize flags ) {
File file = {0};
- TRY( File_open( path,
+
+ file = File_open( s, path,
FILE_EXISTING_OPEN |
FILE_MISSING_CREATE |
FILE_LINK_FOLLOW |
- FILE_ACCESS_READ | FILE_ACCESS_WRITE,
- &file
- ));
+ FILE_ACCESS_READ | FILE_ACCESS_WRITE
+ );
- return FileView_from_file(&file, claim_amount, flags, out);
+ return FileView_from_file( s, &file, claim_amount, flags );
}
StrSlc FileView_as_StrSlc( const FileView *fv ) {
return (StrSlc){ .len = fv->filesize, .data = (const u8*)fv->start };
}
-Status FileView_extend_file( FileView *fv, usize amount ) {
+void FileView_extend_file( Status *s, FileView *fv, usize amount ) {
+ END_IF_NOK( *s );
+
if( amount > fv->claimed - fv->filesize ) {
- return S_FAILURE | ERR_OUT_OF_BOUND;
+ ERRORING_FAIL( S_FAILURE | ERR_OUT_OF_BOUND );
}
- usize map_start_offset = 0;
- TRY( usize_round_down( fv->filesize, sizeof(Page), &map_start_offset ) );
+ usize map_start_offset = usize_round_down( s, fv->filesize, sizeof(Page) );
+ END_IF_NOK( *s );
usize map_start_addr = (u64)((u8*)fv->start + map_start_offset);
- TRY( linux_fallocate( fv->file.fd, 0, fv->filesize, amount ) );
+ *s = linux_fallocate( fv->file.fd, 0, fv->filesize, amount );
+ END_IF_NOK( *s );
fv->filesize += amount;
void *discard;
- TRY( linux_mmap(
+ *s = linux_mmap(
map_start_addr,
fv->filesize - map_start_offset + amount,
LINUX_PROT_READ | LINUX_PROT_WRITE,
@@ -1270,24 +1453,34 @@ Status FileView_extend_file( FileView *fv, usize amount ) {
fv->file.fd,
map_start_offset,
&discard
- ));
+ );
- return S_SUCCESS;
+end:
+ return;
}
-Status FileView_destroy( FileView *fv ) {
- if( fv->flags & FILEVIEW_OWN_FILE ) {
- TRY(File_close( &fv->file ));
- fv->file.fd = -1;
+void FileView_destroy( Status *s, FileView *fv ) {
+ if( fv ) {
+ if( fv->flags & FILEVIEW_OWN_FILE ) {
+ File_close( s, &fv->file );
+ }
+ }
+
+ Status ls = linux_munmap( (usize)fv->start, fv->claimed );
+
+ if( S_OK( *s ) && S_NOK( ls ) ) {
+ *s = ls;
}
- TRY( linux_munmap( (usize)fv->start, fv->claimed ) );
+ END_IF_NOK( *s );
fv->flags = 0;
fv->filesize = 0;
fv->claimed = 0;
fv->start = 0;
- return S_SUCCESS;
+
+end:
+ return;
}
notlibc.h
@@ -289,11 +289,11 @@ ASSERT( sizeof( f64 ) == 8 );
void *memset( void* ptr, int value, unsigned long count );
void *memcpy( void *dest, const void *src, unsigned long n );
+
/*========================== Derived Datatypes ===============================*/
-/* Pointers */
-/* Status */
+/* Pointers */
#define GEN_POINTER_TYPE( T ) \
typedef T* T##p
@@ -304,6 +304,8 @@ GEN_POINTER_TYPE( u32 );
GEN_POINTER_TYPE( u64 );
GEN_POINTER_TYPE( usize );
+GEN_POINTER_TYPE( void );
+
GEN_POINTER_TYPE( s8 );
GEN_POINTER_TYPE( s16 );
GEN_POINTER_TYPE( s32 );
@@ -313,6 +315,42 @@ GEN_POINTER_TYPE( ssize );
GEN_POINTER_TYPE( f32 );
GEN_POINTER_TYPE( f64 );
+
+/* Status */
+
+/* Errors work in a very specific way in this library.
+ * All function that can fail take a Status * as their first argument.
+ * If this is already a failure, they must return, usually 0.
+ * Otherwise they execute and optionally store their own errors into
+ * that Status value.
+ * NOTE: When the operation is mutating an object no mutation should be done
+ * if an error is already present, but if the function is expected to return
+ * a reference to the mutated object it should directly return the original.
+ *
+ * Moreover, any _create function (constructor) must return a fully zeroed
+ * return value in such an error case. Also, all types MUST support just
+ * being zeroed. If really necessary there could be an exception here,
+ * but mainly if hardware dictates a different default value.
+ *
+ * All _destroy functions must check their args and if they are all zero
+ * (or default value) then they must just return. Otherwise they must
+ * free said resources, even if the error is set beforehand.
+ * Destroy functions can also set the error if the resource could not be
+ * freed for some reason. (invalid non-zero reference, some other
+ * state got messed up along the way or whatever reason).
+ *
+ * These simple rules allow for very nice error-directed control flow, where
+ * the first failure leads to falling through the rest, but still allowing for
+ * guaranteed resource cleanup.
+ *
+ * Normally such behaviour would be difficult to debug, this is why in debug
+ * mode any error setting code should breakpoint() before returning 0.
+ *
+ * Under the Erroring function helpers below you will find some helper macros
+ * for this creating these functions more easily.
+ *
+ * */
+
typedef u32 Status;
#define S_MASK (3 << 30)
@@ -371,7 +409,6 @@ enum _ErrorReasons {
};
-
#define S_OK(...) ( ((__VA_ARGS__) & S_MASK) != (Status)S_FAILURE ) /* != FAILURE, cause otherwise the expression will appear twice, which is a great footgun when it's stateful... we are having none of that here */
#define S_NOK(...) ( ((__VA_ARGS__) & S_MASK) == (Status)S_FAILURE )
@@ -386,6 +423,63 @@ enum _ErrorReasons {
} \
} while(0)
+/* Erroring function helpers */
+
+/* If the error is already set turn into a no-op.
+ * None of the parameters are usable in this case.
+ * All of them could be just garbage.
+ * */
+#define ERRORING_PROLOGUE( status_varname, ret_type ) \
+ if( S_NOK( *status_varname ) ) { \
+ return (ret_type){0}; \
+ }
+
+/* Destructors must always destroy non-zero values and
+ * never overwrite errors with success.
+ * Success can be overwritten by completion.
+ * Ignoring a zero reference is considered completion.
+ * */
+#define ERRORING_DESTRUCTOR_PROLOGUE( status_varname, destroyed_value ) \
+ if( destroyed_value == 0 ) { \
+ if( S_OK( *status_varname ) ) { \
+ *status_varname = S_COMPLETION; \
+ } \
+ return; \
+ }
+
+/* On failure a breakpoint must be raised in debug builds. */
+#define ERRORING_FAIL( value ) \
+ DEBUG(breakpoint();); \
+ *s = value; \
+
+#define ENCHAIN( status_expr, ... ) \
+ if( S_OK(status_expr) ) { \
+ __VA_ARGS__ \
+ }
+
+#define GEN_VALUE_BY_STATUS( T ) \
+ static inline T T##_by_status( Status *s, T v1, T v2 ) { \
+ return (S_OK(*s))? v1 : v2; \
+ }
+
+#define END_IF_NOK( status_value ) \
+ if( S_NOK( status_value ) ) { \
+ goto end; \
+ }
+
+GEN_VALUE_BY_STATUS( u8 )
+GEN_VALUE_BY_STATUS( u16 )
+GEN_VALUE_BY_STATUS( u32 )
+GEN_VALUE_BY_STATUS( u64 )
+GEN_VALUE_BY_STATUS( usize )
+GEN_VALUE_BY_STATUS( voidp )
+
+GEN_VALUE_BY_STATUS( s8 )
+GEN_VALUE_BY_STATUS( s16 )
+GEN_VALUE_BY_STATUS( s32 )
+GEN_VALUE_BY_STATUS( s64 )
+GEN_VALUE_BY_STATUS( ssize )
+
/******************************************************************************/
/* MATH STUFF */
@@ -423,676 +517,314 @@ ASSERT( u8_MAX == 0xff );
/* Addition */
-static inline Status u8_add(u8 n1, u8 n2, u8 *out);
-static inline Status u16_add(u16 n1, u16 n2, u16 *out);
-static inline Status u32_add(u32 n1, u32 n2, u32 *out);
-static inline Status u64_add(u64 n1, u64 n2, u64 *out);
-
-static inline Status usize_add(usize n1, usize n2, usize *out) {
- #if ARCH == ARCH_X86_64
- return u64_add( n1, n2, out );
- #elif ARCH == ARCH_I386
- return u32_add( n1, n2, out );
- #endif
-}
-
-static inline Status s8_add(s8 n1, s8 n2, s8 *out);
-static inline Status s16_add(s16 n1, s16 n2, s16 *out);
-static inline Status s32_add(s32 n1, s32 n2, s32 *out);
-static inline Status s64_add(s64 n1, s64 n2, s64 *out);
-
-static inline Status ssize_add(ssize n1, ssize n2, ssize *out) {
- #if ARCH == ARCH_X86_64
- return s64_add( n1, n2, out );
- #elif ARCH == ARCH_I386
- return s32_add( n1, n2, out );
- #endif
-}
-
-/* Subtraction */
+#define GEN_ADD_DECLARATION( T ) \
+ static inline T T##_add( Status *s, T n1, T n2 );
-static inline Status u8_sub(u8 n1, u8 n2, u8 *out);
-static inline Status u16_sub(u16 n1, u16 n2, u16 *out);
-static inline Status u32_sub(u32 n1, u32 n2, u32 *out);
-static inline Status u64_sub(u64 n1, u64 n2, u64 *out);
+GEN_ADD_DECLARATION( u8 )
+GEN_ADD_DECLARATION( u16 )
+GEN_ADD_DECLARATION( u32 )
+GEN_ADD_DECLARATION( u64 )
-static inline Status usize_sub(usize n1, usize n2, usize *out) {
- #if ARCH == ARCH_X86_64
- return u64_sub( n1, n2, out );
- #elif ARCH == ARCH_I386
- return u32_sub( n1, n2, out );
- #endif
-}
+GEN_ADD_DECLARATION( s8 )
+GEN_ADD_DECLARATION( s16 )
+GEN_ADD_DECLARATION( s32 )
+GEN_ADD_DECLARATION( s64 )
-static inline Status s8_sub(s8 n1, s8 n2, s8 *out);
-static inline Status s16_sub(s16 n1, s16 n2, s16 *out);
-static inline Status s32_sub(s32 n1, s32 n2, s32 *out);
-static inline Status s64_sub(s64 n1, s64 n2, s64 *out);
-
-static inline Status ssize_sub(ssize n1, ssize n2, ssize *out) {
+static inline usize usize_add( Status *s, usize n1, usize n2 ) {
#if ARCH == ARCH_X86_64
- return s64_sub( n1, n2, out );
+ return u64_add( s, n1, n2 );
#elif ARCH == ARCH_I386
- return s32_sub( n1, n2, out );
+ return u32_add( s, n1, n2 );
#endif
}
-
-
-/* Multiplication */
-
-static inline Status u8_mul(u8 n1, u8 n2, u8 *out);
-static inline Status u16_mul(u16 n1, u16 n2, u16 *out);
-static inline Status u32_mul(u32 n1, u32 n2, u32 *out);
-static inline Status u64_mul(u64 n1, u64 n2, u64 *out);
-
-static inline Status s8_mul( s8 n1, s8 n2, s8 *out);
-static inline Status s16_mul(s16 n1, s16 n2, s16 *out);
-static inline Status s32_mul(s32 n1, s32 n2, s32 *out);
-static inline Status s64_mul(s64 n1, s64 n2, s64 *out);
-
-static inline Status usize_mul(usize n1, usize n2, usize *out) {
+static inline ssize ssize_add( Status *s, ssize n1, ssize n2 ) {
#if ARCH == ARCH_X86_64
- return u64_mul( n1, n2, out );
+ return u64_add( s, n1, n2 );
#elif ARCH == ARCH_I386
- return u32_mul( n1, n2, out );
+ return u32_add( s, n1, n2 );
#endif
}
-
-/* Maximum */
-
-static inline u64 u64_max( u64 n1, u64 n2 ) {
- return (n1 >= n2)? n1 : n2;
-}
-
-static inline u32 u32_max( u32 n1, u32 n2 ) {
- return (n1 >= n2)? n1 : n2;
-}
-
-static inline u16 u16_max( u16 n1, u16 n2 ) {
- return (n1 >= n2)? n1 : n2;
-}
-
-static inline u8 u8_max( u8 n1, u8 n2 ) {
- return (n1 >= n2)? n1 : n2;
-}
-
-static inline usize usize_max( usize n1, usize n2 ) {
- return (n1 >= n2)? n1 : n2;
-}
-
-static inline s64 s64_max( s64 n1, s64 n2 ) {
- return (n1 >= n2)? n1 : n2;
-}
-
-static inline s32 s32_max( s32 n1, s32 n2 ) {
- return (n1 >= n2)? n1 : n2;
-}
-
-static inline s16 s16_max( s16 n1, s16 n2 ) {
- return (n1 >= n2)? n1 : n2;
-}
-
-static inline s8 s8_max( s8 n1, s8 n2 ) {
- return (n1 >= n2)? n1 : n2;
-}
-
-
-/* Minimum */
-
-static inline u64 u64_min( u64 n1, u64 n2 ) {
- return (n2 >= n1)? n1 : n2;
-}
-
-static inline u32 u32_min( u32 n1, u32 n2 ) {
- return (n2 >= n1)? n1 : n2;
-}
-
-static inline u16 u16_min( u16 n1, u16 n2 ) {
- return (n2 >= n1)? n1 : n2;
-}
-
-static inline u8 u8_min( u8 n1, u8 n2 ) {
- return (n2 >= n1)? n1 : n2;
-}
-
-static inline usize usize_min( usize n1, usize n2 ) {
- return (n2 >= n1)? n1 : n2;
-}
-
-static inline s64 s64_min( s64 n1, s64 n2 ) {
- return (n2 >= n1)? n1 : n2;
-}
-
-static inline s32 s32_min( s32 n1, s32 n2 ) {
- return (n2 >= n1)? n1 : n2;
-}
-
-static inline s16 s16_min( s16 n1, s16 n2 ) {
- return (n2 >= n1)? n1 : n2;
-}
-
-static inline s8 s8_min( s8 n1, s8 n2 ) {
- return (n2 >= n1)? n1 : n2;
-}
-
-/* Round Down */
-
-static inline Status u64_round_down(u64 number, u64 multiple, u64 *out) {
- if( multiple == 0 ) return S_FAILURE | ERRSRC_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 | ERRSRC_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 | ERRSRC_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 | ERRSRC_ARG_2 | ERR_INVALID_ARGUMENT;
- *out = number - (number%multiple);
- return S_SUCCESS;
-}
-
-#if ARCH == ARCH_X86_64
-static inline Status usize_round_down( usize number, usize multiple, usize *out ) {
- return u64_round_down(number, multiple, out);
-}
-#elif ARCH == ARCH_I386
-static inline Status usize_round_down( usize number, usize multiple, usize *out ) {
- return u32_round_down(number, multiple, out);
-}
-#endif
-
-
-/* Round Up */
-
-static inline Status u64_round_up( u64 number, u64 multiple, u64 *out ) {
- if( multiple == 0 ) return S_FAILURE | ERRSRC_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;
-}
-
-static inline Status u32_round_up( u32 number, u32 multiple, u32 *out ) {
- if( multiple == 0 ) return S_FAILURE | ERRSRC_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;
-}
-
-static inline Status u16_round_up( u16 number, u16 multiple, u16 *out ) {
- if( multiple == 0 ) return S_FAILURE | ERRSRC_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;
-}
-
-static inline Status u8_round_up( u8 number, u8 multiple, u8 *out ) {
- if( multiple == 0 ) return S_FAILURE | ERRSRC_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;
-}
-
-#if ARCH == ARCH_X86_64
-static inline Status usize_round_up( usize number, usize multiple, usize *out ) {
- return u64_round_up(number, multiple, out);
-}
-#elif ARCH == ARCH_I386
-static inline Status usize_round_up( usize number, usize multiple, usize *out ) {
- return u32_round_up(number, multiple, out);
-}
-#endif
-
-
-/* Is Power Of Two */
-
-static inline u8 u64_is_power_of_two( u64 num ) {
- return num && !(num & (num - 1));
-}
-
-static inline u8 u32_is_power_of_two( u32 num ) {
- return num && !(num & (num - 1));
-}
-
-static inline u8 u16_is_power_of_two( u16 num ) {
- return num && !(num & (num - 1));
-}
-
-static inline u8 u8_is_power_of_two( u8 num ) {
- return num && !(num & (num - 1));
-}
-
-static inline u8 usize_is_power_of_two( usize num ) {
- return num && !(num & (num - 1));
-}
-
-
-#if COMPILER == COPMILER_GCC || COMPILER == COMPILER_CLANG
- 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;
+#if COMPILER == COMPILER_GCC || COMPILER == COMPILER_CLANG
+ #define GEN_UADD_DEFINITION( T ) \
+ static inline T T##_add( Status *s, T n1, T n2 ) { \
+ ERRORING_PROLOGUE( s, T ); \
+ T out; \
+ if( __builtin_add_overflow( n1, n2, &out ) ) { \
+ *s = S_FAILURE | ERR_OVERFLOW; \
+ return 0; \
+ } \
+ *s = S_SUCCESS; \
+ return out; \
}
- 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;
+ #define GEN_SADD_DEFINITION( T ) GEN_UADD_DEFINITION( T )
+
+ #define GEN_USUB_DEFINITION( T ) \
+ static inline T T##_sub( Status *s, T n1, T n2 ) { \
+ ERRORING_PROLOGUE( s, T ); \
+ T out; \
+ if( __builtin_sub_overflow( n1, n2, &out ) ) { \
+ *s = S_FAILURE | ERR_OVERFLOW; \
+ return 0; \
+ } \
+ *s = S_SUCCESS; \
+ return out; \
}
- 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;
+ #define GEN_SSUB_DEFINITION( T ) GEN_USUB_DEFINITION( T )
+
+ #define GEN_UMUL_DEFINITION( T ) \
+ static inline T T##_mul( Status *s, T n1, T n2 ) { \
+ ERRORING_PROLOGUE( s, T ); \
+ T out; \
+ if( __builtin_mul_overflow( n1, n2, &out ) ) { \
+ *s = S_FAILURE | ERR_OVERFLOW; \
+ return 0; \
+ } \
+ *s = S_SUCCESS; \
+ return out; \
}
- 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 */
+ #define GEN_SMUL_DEFINITION( T ) GEN_UMUL_DEFINITION( T )
- 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;
- }
+#else
- static inline Status u32_sub( u32 n1, u32 n2, u32 *out ) {
- if( __builtin_sub_overflow(n1, n2, out) ) {
- return S_FAILURE | ERR_OVERFLOW;
+ #define GEN_UADD_DEFINITION( T ) \
+ static inline T T##_add( Status *s, T n1, T n2 ) { \
+ ERRORING_PROLOGUE( s, T ); \
+ if( n1 > (T##_MAX) - n2 ) { \
+ *s = S_FAILURE | ERR_OVERFLOW; \
+ return 0; \
+ } \
+ *s = S_SUCCESS; \
+ return n1 + n2; \
}
- 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;
+ #define GEN_USUB_DEFINITION( T ) \
+ static inline T T##_sub( Status *s, T n1, T n2 ) { \
+ ERRORING_PROLOGUE( s, T ); \
+ if( n2 > n1 ) { \
+ *s = S_FAILURE | ERR_OVERFLOW; \
+ return 0; \
+ } \
+ *s = S_SUCCESS; \
+ return n1 - n2; \
}
- 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;
+ #define GEN_SADD_DEFINITION( T ) \
+ static inline T T##_add( Status *s, T n1, T n2 ) { \
+ ERRORING_PROLOGUE( s, T ); \
+ if( (n1 >= 0 && n2 > T##_MAX - n1) || (n1 < 0 && n2 < T##_MIN - n1) ) { \
+ *s = S_FAILURE | ERR_OVERFLOW; \
+ return 0; \
+ } \
+ return n1 + n2; \
}
- 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;
+ #define GEN_SSUB_DEFINITION( T ) \
+ static inline T T##_sub( Status *s, T n1, T n2 ) { \
+ if( (n2 > 0 && n1 < T##_MIN + n2) || (n2 < 0 && n1 > T##_MAX + n2) ) { \
+ *s = S_FAILURE | ERR_OVERFLOW; \
+ return 0; \
+ } \
+ return n1 - n2; \
}
- static inline Status s32_sub( s32 n1, s32 n2, s32 *out ) {
- if( __builtin_sub_overflow(n1, n2, out) ) {
- return S_FAILURE | ERR_OVERFLOW;
+ #define GEN_UMUL_DEFINITION( T ) \
+ static inline T T##_mul( Status *s, T n1, T n2 ) { \
+ if( n1 && n2 > (T##_MAX/n1) ) { \
+ *s = S_FAILURE | ERR_OVERFLOW; \
+ return 0; \
+ } \
+ *s = S_SUCCESS; \
+ return n1*n2; \
}
- 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;
+ #define GEN_SMUL_DEFINITION( T ) \
+ static inline T T##_mul( Status *s, T n1, T n2 ) { \
+ ERRORING_PROLOGUE( s, T ); \
+ if( \
+ ( n2 > 0 && n1 >= T##_MIN/n2 && n1 <= T##_MAX/n2 ) || \
+ ( n2 == 0 ) || \
+ ( n2 == -1 && n1 >= -T##_MAX ) || \
+ ( n2 < -1 && n1 >= T##_MAX/n2 && n1 <= T##_MIN/n2 ) \
+ ) { \
+ return n1*n2; \
+ *s = S_SUCCESS; \
+ } \
+ *s = S_FAILURE | ERR_OVERFLOW; \
+ return 0; \
}
- return S_SUCCESS;
- }
+#endif
- 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;
- }
- /* Unsigned multiplication */
+/* Subtraction */
- static inline Status u64_mul( u64 n1, u64 n2, u64 *out ) {
- if( __builtin_mul_overflow(n1, n2, out) ) {
- return S_FAILURE | ERR_OVERFLOW;
- }
- return S_SUCCESS;
- }
+#define GEN_SUB_DECLARATION( T ) \
+ static inline T T##_sub( Status *s, T n1, T n2 );
- static inline Status u32_mul( u32 n1, u32 n2, u32 *out ) {
- if( __builtin_mul_overflow(n1, n2, out) ) {
- return S_FAILURE | ERR_OVERFLOW;
- }
- return S_SUCCESS;
- }
+GEN_SUB_DECLARATION( u8 )
+GEN_SUB_DECLARATION( u16 )
+GEN_SUB_DECLARATION( u32 )
+GEN_SUB_DECLARATION( u64 )
- static inline Status u16_mul( u16 n1, u16 n2, u16 *out ) {
- if( __builtin_mul_overflow(n1, n2, out) ) {
- return S_FAILURE | ERR_OVERFLOW;
- }
- return S_SUCCESS;
- }
+GEN_SUB_DECLARATION( s8 )
+GEN_SUB_DECLARATION( s16 )
+GEN_SUB_DECLARATION( s32 )
+GEN_SUB_DECLARATION( s64 )
- static inline Status u8_mul( u8 n1, u8 n2, u8 *out ) {
- if( __builtin_mul_overflow(n1, n2, out) ) {
- return S_FAILURE | ERR_OVERFLOW;
- }
- return S_SUCCESS;
- }
+static inline usize usize_sub( Status *s, usize n1, usize n2 ) {
+ #if ARCH == ARCH_X86_64
+ return u64_sub( s, n1, n2 );
+ #elif ARCH == ARCH_I386
+ return u32_sub( s, n1, n2 );
+ #endif
+}
- static inline Status s64_mul( s64 n1, s64 n2, s64 *out ) {
- if( __builtin_mul_overflow(n1, n2, out) ) {
- return S_FAILURE | ERR_OVERFLOW;
- }
- return S_SUCCESS;
- }
+static inline ssize ssize_sub( Status *s, ssize n1, ssize n2 ) {
+ #if ARCH == ARCH_X86_64
+ return u64_sub( s, n1, n2 );
+ #elif ARCH == ARCH_I386
+ return u32_sub( s, n1, n2 );
+ #endif
+}
- static inline Status s32_mul( s32 n1, s32 n2, s32 *out ) {
- if( __builtin_mul_overflow(n1, n2, out) ) {
- return S_FAILURE | ERR_OVERFLOW;
- }
- return S_SUCCESS;
- }
- static inline Status s16_mul( s16 n1, s16 n2, s16 *out ) {
- if( __builtin_mul_overflow(n1, n2, out) ) {
- return S_FAILURE | ERR_OVERFLOW;
- }
- return S_SUCCESS;
- }
+/* Multiplication */
- static inline Status s8_mul( s8 n1, s8 n2, s8 *out ) {
- if( __builtin_mul_overflow(n1, n2, out) ) {
- return S_FAILURE | ERR_OVERFLOW;
- }
- return S_SUCCESS;
- }
-#else
- /* 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;
- }
+#define GEN_MUL_DECLARATION( T ) \
+ static inline T T##_mul( Status *s, T n1, T n2 );
- 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;
- }
+GEN_MUL_DECLARATION( u8 )
+GEN_MUL_DECLARATION( u16 )
+GEN_MUL_DECLARATION( u32 )
+GEN_MUL_DECLARATION( u64 )
- 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;
- }
+GEN_MUL_DECLARATION( s8 )
+GEN_MUL_DECLARATION( s16 )
+GEN_MUL_DECLARATION( s32 )
+GEN_MUL_DECLARATION( s64 )
- 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;
- }
+static inline usize usize_mul( Status *s, usize n1, usize n2 ) {
+ #if ARCH == ARCH_X86_64
+ return u64_mul( s, n1, n2 );
+ #elif ARCH == ARCH_I386
+ return u32_mul( s, n1, n2 );
+ #endif
+}
- /* 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 ssize ssize_mul( Status *s, ssize n1, ssize n2 ) {
+ #if ARCH == ARCH_X86_64
+ return u64_mul( s, n1, n2 );
+ #elif ARCH == ARCH_I386
+ return u32_mul( s, n1, n2 );
+ #endif
+}
- 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;
- }
+/* Maximum */
- 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;
+#define GEN_MAX_DEFINITION( T ) \
+ static inline T T##_max( T n1, T n2 ) { \
+ return (n1 >= n2)? n1 : n2; \
}
- /* Unsigned subtraction */
+GEN_MAX_DEFINITION( u8 )
+GEN_MAX_DEFINITION( u16 )
+GEN_MAX_DEFINITION( u32 )
+GEN_MAX_DEFINITION( u64 )
+GEN_MAX_DEFINITION( usize )
- 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;
- }
+GEN_MAX_DEFINITION( s8 )
+GEN_MAX_DEFINITION( s16 )
+GEN_MAX_DEFINITION( s32 )
+GEN_MAX_DEFINITION( s64 )
+GEN_MAX_DEFINITION( ssize )
- 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;
- }
+/* Minimum */
- 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;
+#define GEN_MIN_DEFINITION( T ) \
+ static inline T T##_min( T n1, T n2 ) { \
+ return (n2 >= n1)? n1 : n2; \
}
- /* Signed Subtraction */
+GEN_MIN_DEFINITION( u8 )
+GEN_MIN_DEFINITION( u16 )
+GEN_MIN_DEFINITION( u32 )
+GEN_MIN_DEFINITION( u64 )
+GEN_MIN_DEFINITION( usize )
- 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;
- }
+GEN_MIN_DEFINITION( s8 )
+GEN_MIN_DEFINITION( s16 )
+GEN_MIN_DEFINITION( s32 )
+GEN_MIN_DEFINITION( s64 )
+GEN_MIN_DEFINITION( ssize )
- 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;
- }
+/* Round Down */
- /* Unsigned multiplication */
- static inline Status u64_mul( u64 n1, u64 n2, u64 *out ) {
- if( n1 && n2 > (u64_MAX/n1) ) {
- return S_FAILURE | ERR_OVERFLOW;
- }
- *out = n1*n2;
- return S_SUCCESS;
+#define GEN_UROUND_DOWN_DECLARATION( T ) \
+ static inline T T##_round_down( Status *s, T number, T multiple );
+
+#define GEN_UROUND_DOWN_DEFINITION( T ) \
+ static inline T T##_round_down( Status *s, T number, T multiple ) { \
+ ERRORING_PROLOGUE( s, T ); \
+ if( multiple == 0 ) { \
+ ERRORING_FAIL( S_FAILURE | ERRSRC_ARG_2 | ERR_INVALID_ARGUMENT ); \
+ return (T){0}; \
+ }; \
+ *s = S_SUCCESS; \
+ return number - (number%multiple); \
}
- static inline Status u32_mul( u32 n1, u32 n2, u32 *out ) {
- if( n1 && n2 > (u32_MAX/n1) ) {
- return S_FAILURE | ERR_OVERFLOW;
- }
- *out = n1*n2;
- return S_SUCCESS;
- }
+GEN_UROUND_DOWN_DECLARATION( u8 )
+GEN_UROUND_DOWN_DECLARATION( u16 )
+GEN_UROUND_DOWN_DECLARATION( u32 )
+GEN_UROUND_DOWN_DECLARATION( u64 )
+GEN_UROUND_DOWN_DECLARATION( usize )
- static inline Status u16_mul( u16 n1, u16 n2, u16 *out ) {
- if( n1 && n2 > (u16_MAX/n1) ) {
- return S_FAILURE | ERR_OVERFLOW;
- }
- *out = n1*n2;
- return S_SUCCESS;
- }
- static inline Status u8_mul( u8 n1, u8 n2, u8 *out ) {
- if( n1 && n2 > (u8_MAX/n1) ) {
- return S_FAILURE | ERR_OVERFLOW;
- }
- *out = n1*n2;
- return S_SUCCESS;
- }
+/* Round Up */
- /* Signed multiplication */
- static inline Status s64_mul( s64 n1, s64 n2, s64 *out ) {
- if(
- ( n2 > 0 && n1 >= s64_MIN/n2 && n1 <= s64_MAX/n2 ) ||
- ( n2 == 0 ) ||
- ( n2 == -1 && n1 >= -s64_MAX ) ||
- ( n2 < -1 && n1 >= s64_MAX/n2 && n1 <= s64_MIN/n2 )
- ) {
- *out = n1*n2;
- return S_SUCCESS;
- }
- return S_FAILURE | ERR_OVERFLOW;
+#define GEN_UROUND_UP_DECLARATION( T ) \
+ static inline T T##_round_up( Status *s, T number, T multiple );
+
+#define GEN_UROUND_UP_DEFINITION( T ) \
+ static inline T T##_round_up( Status *s, T number, T multiple ) { \
+ if( multiple == 0 ) { \
+ ERRORING_FAIL( S_FAILURE | ERRSRC_ARG_2 | ERR_INVALID_ARGUMENT ); \
+ return 0; \
+ } \
+ T rem = number%multiple; \
+ if( rem == 0 ) { \
+ *s = S_SUCCESS; \
+ return number; \
+ } else { \
+ return T##_add( s, number, multiple - rem ); \
+ } \
}
- static inline Status s32_mul( s32 n1, s32 n2, s32 *out ) {
- if(
- ( n2 > 0 && n1 >= s32_MIN/n2 && n1 <= s32_MAX/n2 ) ||
- ( n2 == 0 ) ||
- ( n2 == -1 && n1 >= -s32_MAX ) ||
- ( n2 < -1 && n1 >= s32_MAX/n2 && n1 <= s32_MIN/n2 )
- ) {
- *out = n1*n2;
- return S_SUCCESS;
- }
- return S_FAILURE | ERR_OVERFLOW;
- }
+GEN_UROUND_UP_DECLARATION( u8 )
+GEN_UROUND_UP_DECLARATION( u16 )
+GEN_UROUND_UP_DECLARATION( u32 )
+GEN_UROUND_UP_DECLARATION( u64 )
+GEN_UROUND_UP_DECLARATION( usize )
- static inline Status s16_mul( s16 n1, s16 n2, s16 *out ) {
- if(
- ( n2 > 0 && n1 >= s16_MIN/n2 && n1 <= s16_MAX/n2 ) ||
- ( n2 == 0 ) ||
- ( n2 == -1 && n1 >= -s16_MAX ) ||
- ( n2 < -1 && n1 >= s16_MAX/n2 && n1 <= s16_MIN/n2 )
- ) {
- *out = n1*n2;
- return S_SUCCESS;
- }
- return S_FAILURE | ERR_OVERFLOW;
- }
+/* Is Power Of Two */
- static inline Status s8_mul( s8 n1, s8 n2, s8 *out ) {
- if(
- ( n2 > 0 && n1 >= s8_MIN/n2 && n1 <= s8_MAX/n2 ) ||
- ( n2 == 0 ) ||
- ( n2 == -1 && n1 >= -s8_MAX ) ||
- ( n2 < -1 && n1 >= s8_MAX/n2 && n1 <= s8_MIN/n2 )
- ) {
- *out = n1*n2;
- return S_SUCCESS;
- }
- return S_FAILURE | ERR_OVERFLOW;
- }
+#define GEN_IS_POWER_OF_TWO( T ) \
+static inline u8 T##_is_power_of_two( T num ) { \
+ return num && !(num & (num - 1)); \
+}
-#endif
+GEN_IS_POWER_OF_TWO(u8)
+GEN_IS_POWER_OF_TWO(u16)
+GEN_IS_POWER_OF_TWO(u32)
+GEN_IS_POWER_OF_TWO(u64)
+GEN_IS_POWER_OF_TWO(usize)
/* Arena */
@@ -1104,12 +836,12 @@ STRUCT( Arena,
usize taken; /* The top of the arena */
);
-Status Arena_create( Arena *out, usize size );
-Status Arena_destroy( Arena *a );
+Arena Arena_create( Status *s, usize size );
+void Arena_destroy( Status *s, Arena *a );
-Status Arena_take( Arena *a, usize amount, u8 **out );
-Status Arena_give( Arena *a, usize amount );
-Status Arena_align( Arena *a, usize alignment );
+void* Arena_take( Status *s, Arena *a, usize amount );
+void Arena_give( Status *s, Arena *a, usize amount );
+void Arena_align( Status *s, Arena *a, usize alignment );
/* Heap */
@@ -1147,13 +879,12 @@ Status Arena_align( Arena *a, usize alignment );
#endif
ASSERT( sizeof(HeapEntry)%sizeof(usize) == 0 );
-Status Heap_create( Heap *out, usize size ); /* size - size of underlying arena.
+Heap Heap_create( Status *s, usize size ); /* size - size of underlying arena.
The heap will hold less, due to bookkeeping overhead for allocations. */
-Status Heap_destroy( Heap *h );
+void Heap_destroy( Status *s, Heap *h );
-Status Heap_alloc( Heap *h, usize amount, void **out );
-Status Heap_free( Heap *h, void **ptr ); /* u8** cause it zeroes the pointer\
- on success automatically. */
+void* Heap_alloc( Status *s, Heap *h, usize amount );
+void Heap_free( Status *s, Heap *h, void *ptr );
usize Heap_get_asize( Heap *h, const void *ptr );
@@ -1170,19 +901,19 @@ STRUCT( AnyArr,
)
);
-Status AnyArr_create( usize count, AnyArr **out, Heap *h, usize elem_size );
-Status AnyArr_destroy( AnyArr** arr, Heap *h );
+AnyArr* AnyArr_create( Status *s, usize count, Heap *h, usize elem_size );
+void AnyArr_destroy( Status *s, AnyArr** arr, Heap *h );
-Status AnyArr_extend( AnyArr **arr, usize additional_len, Heap *h, usize elem_size );
-Status AnyArr_truncate( AnyArr *arr, usize cutlen, usize elem_size );
+AnyArr* AnyArr_inflate( Status *s, AnyArr *arr, usize additional_count, Heap *h, usize elem_size );
+AnyArr* AnyArr_deflate( Status *s, AnyArr *arr, Heap *h, usize elem_size ); /* reallocate to just fit the currently contained elements - we assume it's on the same heap */
-Status AnyArr_inflate( AnyArr **arr, usize additional_count, Heap *h, usize elem_size );
-Status AnyArr_deflate( AnyArr **arr, Heap *h, usize elem_size );
+void AnyArr_truncate( Status *s, AnyArr *arr, usize cutlen, usize elem_size );
-Status AnyArr_push( AnyArr **arr, void* el, Heap *h, usize elem_size );
-Status AnyArr_pop( AnyArr *arr, void* el_out, usize elem_size );
-Status AnyArr_dup( const AnyArr *arr, AnyArr **out_arr, Heap *h, usize elem_size );
+AnyArr* AnyArr_push( Status *s, AnyArr *arr, void* el, Heap *h, usize elem_size );
+void AnyArr_pop( Status *s, AnyArr *arr, void* el_out, usize elem_size );
+
+AnyArr* AnyArr_dup( Status *s, const AnyArr *arr, Heap *h, usize elem_size );
DEBUG(
void _AnyArr_update_checksum( AnyArr *arr );
@@ -1201,40 +932,36 @@ DEBUG(
ASSERT( sizeof(T##s)%sizeof(usize) == 0 ); \
ASSERT( sizeof(T##s) == sizeof(AnyArr) ); \
\
-static inline Status T##s_create( Heap *h, usize count, T ## s **out ) { \
- return AnyArr_create( count, (AnyArr**) out, h, sizeof(T) ); \
+static inline T##s* T##s_create( Status *s, Heap *h, usize count ) { \
+ return (T##s*)AnyArr_create( s, count, h, sizeof(T) ); \
} \
\
-static inline Status T##s_push( T##s **arr, T* el, Heap *h ) { \
- return AnyArr_push( (AnyArr**)arr, el, h, sizeof(T) ); \
+static inline T##s* T##s_push( Status *s, T##s *arr, T* el, Heap *h ) { \
+ return (T##s*)AnyArr_push( s, (AnyArr*)arr, el, h, sizeof(T) ); \
} \
\
-static inline Status T##s_pop( T##s *arr, T* el ) { \
- return AnyArr_pop( (AnyArr*)arr, el, sizeof(T) ); \
+static inline void T##s_pop( Status *s, T##s *arr, T* el ) { \
+ AnyArr_pop( s, (AnyArr*)arr, el, sizeof(T) ); \
} \
\
-static inline Status T##s_extend( T##s **arr, usize additional_len, Heap *h ) { \
- return AnyArr_extend( (AnyArr**)arr, additional_len, h, sizeof(T) ); \
+static inline void T##s_truncate( Status *s, T##s *arr, usize cutlen ) { \
+ AnyArr_truncate( s, (AnyArr*)arr, cutlen, sizeof(T) ); \
} \
\
-static inline Status T##s_truncate( T##s *arr, usize cutlen ) { \
- return AnyArr_truncate( (AnyArr*)arr, cutlen, sizeof(T) ); \
+static inline T##s* T##s_inflate( Status *s, T##s *arr, usize additional_count, Heap *h ) { \
+ return (T##s*)AnyArr_inflate( s, (AnyArr*)arr, additional_count, h, sizeof(T) ); \
} \
\
-static inline Status T##s_inflate( T##s **arr, usize additional_count, Heap *h ) { \
- return AnyArr_inflate( (AnyArr**)arr, additional_count, h, sizeof(T) ); \
+static inline T##s* T##s_deflate( Status *s, T##s *arr, Heap *h ) { \
+ return (T##s*)AnyArr_deflate( s, (AnyArr*)arr, h, sizeof(T) ); \
} \
\
-static inline Status T##s_deflate( T##s **arr, Heap *h ) { \
- return AnyArr_deflate( (AnyArr**)arr, h, sizeof(T) ); \
-} \
- \
-static inline Status T##s_dup( const T##s *arr, T##s **out_arr, Heap *h ) { \
- return AnyArr_dup( (AnyArr*)arr, (AnyArr**)out_arr, h, sizeof(T) ); \
+static inline T##s* T##s_dup( Status *s, const T##s *arr, Heap *h ) {\
+ return (T##s*)AnyArr_dup( s, (AnyArr*)arr, h, sizeof(T) ); \
} \
\
-static inline Status T ## s_destroy( T##s **arr, Heap *h ) { \
- return AnyArr_destroy( (AnyArr**)arr, h ); \
+static inline void T##s_destroy( Status *s, T##s **arr, Heap *h ) { \
+ AnyArr_destroy( s, (AnyArr**)arr, h ); \
}
GEN_ARRAY_TYPE( u8 )
@@ -1321,7 +1048,7 @@ GEN_ARRAY_TYPE( StrSlc )
u8 Str_equals( const Str *s1, const Str *s2 );
-Status StrSlc_from_Str( StrSlc *out, const Str *s, usize start, usize len );
+StrSlc StrSlc_from_Str( Status *s, const Str *str, usize start, usize len );
u8 StrSlc_equals( const StrSlc sl1, const StrSlc sl2 );
u8 StrSlc_equals_by_ref( const StrSlc *sl1, const StrSlc *sl2 );
@@ -1329,26 +1056,26 @@ u8 StrSlc_equals_by_ref( const StrSlc *sl1, const StrSlc *sl2 );
u8 StrSlc_equals_Str( const StrSlc sl, const Str* s );
u8 StrSlc_equals_Str_by_ref( const StrSlc *sl, const Str *s );
-Status StrSlc_split_by_u8( const StrSlc *sl, u8 separator, StrSlcs **out, Heap *h );
+StrSlcs* StrSlc_split_by_u8( Status *s, const StrSlc *sl, u8 separator, Heap *h );
/* String assembler */
STRUCT( StrAsm,
Arena a;
);
-Status StrAsm_create( StrAsm *out, usize max_size );
-Status StrAsm_reset( StrAsm *out );
-Status StrAsm_destroy( StrAsm *out );
+StrAsm StrAsm_create( Status *s, usize max_size );
+void StrAsm_reset( Status *s, StrAsm *sa );
+void StrAsm_destroy( Status *s, StrAsm *sa );
-Status StrAsm_store_into_arena( StrAsm *sa, Arena *dst, Str **out );
-Status StrAsm_store_onto_heap( StrAsm *sa, Heap *dst, Str **out );
+void StrAsm_store_into_arena( Status *s, StrAsm *sa, Arena *dst, Str **out );
+void StrAsm_store_onto_heap( Status *s, StrAsm *sa, Heap *dst, Str **out );
StrSlc StrAsm_as_StrSlc( const StrAsm *sa );
/* String, character */
-Status StrAsm_cat_char ( StrAsm *sa, u8 value );
-Status StrAsm_cat_Str( StrAsm *sa, const Str *s );
-Status StrAsm_cat_StrSlc( StrAsm *sa, StrSlc sl );
-Status StrAsm_cat_StrSlc_by_ref( StrAsm *sa, const StrSlc *sl );
+void StrAsm_cat_char ( Status *s, StrAsm *sa, u8 value );
+void StrAsm_cat_Str( Status *s, StrAsm *sa, const Str *str );
+void StrAsm_cat_StrSlc( Status *s, StrAsm *sa, StrSlc sl );
+void StrAsm_cat_StrSlc_by_ref( Status *s, StrAsm *sa, const StrSlc *sl );
extern u8 _halfbyte_to_hex_ascii[16];
@@ -1366,44 +1093,45 @@ static inline void _bin_to_hex_ascii( u8 *data, u8 *out, usize count ) {
}
/* Hex */
-Status StrAsm_fmtx_u8 ( StrAsm *sa, u8 value);
-Status StrAsm_fmtx_u16( StrAsm *sa, u16 value);
-Status StrAsm_fmtx_u32( StrAsm *sa, u32 value);
-Status StrAsm_fmtx_u64( StrAsm *sa, u64 value);
-static inline Status StrAsm_fmtx_usize( StrAsm *sa, usize value) {
+void StrAsm_fmtx_u8 ( Status *s, StrAsm *sa, u8 value);
+void StrAsm_fmtx_u16( Status *s, StrAsm *sa, u16 value);
+void StrAsm_fmtx_u32( Status *s, StrAsm *sa, u32 value);
+void StrAsm_fmtx_u64( Status *s, StrAsm *sa, u64 value);
+
+static inline void StrAsm_fmtx_usize( Status *s, StrAsm *sa, usize value) {
#if ARCH == ARCH_X86_64
- return StrAsm_fmtx_u64( sa, value );
+ StrAsm_fmtx_u64( s, sa, value );
#elif ARCH == ARCH_I386
- return StrAsm_fmtx_u32( sa, value );
+ StrAsm_fmtx_u32( s, sa, value );
#else
#error Unimplemented for current arch.
#endif
}
/* Decimal */
-Status StrAsm_fmtd_u8 ( StrAsm *sa, u8 value);
-Status StrAsm_fmtd_u16( StrAsm *sa, u16 value);
-Status StrAsm_fmtd_u32( StrAsm *sa, u32 value);
-Status StrAsm_fmtd_u64( StrAsm *sa, u64 value);
-Status StrAsm_fmtd_usize( StrAsm *sa, usize value) {
+void StrAsm_fmtd_u8 ( Status *s, StrAsm *sa, u8 value);
+void StrAsm_fmtd_u16( Status *s, StrAsm *sa, u16 value);
+void StrAsm_fmtd_u32( Status *s, StrAsm *sa, u32 value);
+void StrAsm_fmtd_u64( Status *s, StrAsm *sa, u64 value);
+void StrAsm_fmtd_usize( Status *s, StrAsm *sa, usize value) {
#if ARCH == ARCH_X86_64
- return StrAsm_fmtd_u64( sa, value );
+ StrAsm_fmtd_u64( s, sa, value );
#elif ARCH == ARCH_I386
- return StrAsm_fmtd_u32( sa, value );
+ StrAsm_fmtd_u32( s, sa, value );
#else
#error Unimplemented for current arch.
#endif
}
-Status StrAsm_fmtd_s8 ( StrAsm *sa, s8 value);
-Status StrAsm_fmtd_s16( StrAsm *sa, s16 value);
-Status StrAsm_fmtd_s32( StrAsm *sa, s32 value);
-Status StrAsm_fmtd_s64( StrAsm *sa, s64 value);
-Status StrAsm_fmtd_ssize( StrAsm *sa, ssize value) {
+void StrAsm_fmtd_s8 ( Status *s, StrAsm *sa, s8 value);
+void StrAsm_fmtd_s16( Status *s, StrAsm *sa, s16 value);
+void StrAsm_fmtd_s32( Status *s, StrAsm *sa, s32 value);
+void StrAsm_fmtd_s64( Status *s, StrAsm *sa, s64 value);
+void StrAsm_fmtd_ssize( Status *s, StrAsm *sa, ssize value) {
#if ARCH == ARCH_X86_64
- return StrAsm_fmtd_s64( sa, value );
+ StrAsm_fmtd_s64( s, sa, value );
#elif ARCH == ARCH_I386
- return StrAsm_fmtd_s32( sa, value );
+ StrAsm_fmtd_s32( s, sa, value );
#else
#error Unimplemented for current arch.
#endif
@@ -1450,18 +1178,17 @@ enum FileOpenFlags {
};
-static inline Status File_open_validate_flags( usize flags, Status err_source );
+static inline void File_open_validate_flags( Status *s, usize flags, Status err_source );
+File File_open( Status *s, const Str *name, usize flags );
+void File_close( Status *s, File *f );
-Status File_open( const Str *name, usize flags, File *out );
-Status File_close( File *f );
+usize File_read( Status *s, const File *f, usize max_amount, u8 *out );
+usize File_write( Status *s, const File *f, usize amount, const u8 *buf );
-Status File_read( const File *f, usize max_amount, usize *out_amount, u8 *out );
-Status File_write( const File *f, usize amount, usize *out_amount, const u8 *buf );
+void File_seek( Status *s, const File *f, usize position );
-Status File_seek( const File *f, usize position );
-
-Status File_delete( const Str *name );
+void File_delete( Status *s, const Str *name );
STRUCT( FileView,
File file;
@@ -1476,19 +1203,19 @@ enum FileViewFlags {
/* FILEVIEW_PAGE_ALIGNED_EXTEND = (1 << 2), */
};
-Status FileView_from_file( File *file, usize claim_amount, usize flags, FileView *out );
+FileView FileView_from_file( Status *s, File *file, usize claim_amount, usize flags );
/* if claim_amount == 0 => claims exact filesize */
/* This is for quick and easy mmaping of files. If you actually want
* control over the opening flags use FileView_from_file */
-Status FileView_from_path( const Str *path, usize claim_amount, usize flags, FileView *out );
+FileView FileView_from_path( Status *s, const Str *path, usize claim_amount, usize flags );
StrSlc FileView_as_StrSlc( const FileView *fv );
/* Extend the file's end by amount */
-Status FileView_extend_file( FileView *fv, usize amount );
+void FileView_extend_file( Status *s, FileView *fv, usize amount );
-Status FileView_destroy( FileView *fv );
+void FileView_destroy( Status *s, FileView *fv );
/*=========================== Core functions =================================*/
@@ -1538,21 +1265,22 @@ static inline void* mem_set( void *start, u64 len, u8 value ) {
}
/* Request virtual memory range */
-Status mem_claim( u32 page_count, Page **ptr_out);
+Page* mem_claim( Status *s, u32 page_count );
/* Free virtual memory range */
-Status mem_relinquish( Page *start, u32 page_count );
+void mem_relinquish( Status *s, Page *start, u32 page_count );
/* Set up physical backing */
-Status mem_occupy( Page *start, u32 page_count );
+void mem_occupy( Status *s, Page *start, u32 page_count );
/* Allow removal of physical backing */
-Status mem_vacate( Page *start, u32 page_count );
+void mem_vacate( Status *s, Page *start, u32 page_count );
/******************************************************************************/
/* COMMON PLATFORM IMPLEMENTATION */
/******************************************************************************/
-static inline Status File_open_validate_flags( usize flags, Status err_source ) {
+static inline void File_open_validate_flags( Status *s, usize flags, Status err_source ) {
+ END_IF_NOK( *s );
usize existing_flags = flags & FILE_EXISTING_MASK;
usize existing_flags_multiple_set = !usize_is_power_of_two( existing_flags );
@@ -1572,12 +1300,61 @@ static inline Status File_open_validate_flags( usize flags, Status err_source )
(write_append_flags && write_append_flags_multiple_set)
) {
DEBUG(breakpoint());
- return S_FAILURE | ERR_INVALID_ARGUMENT | err_source;
+ ERRORING_FAIL( S_FAILURE | ERR_INVALID_ARGUMENT | err_source );
+ return;
}
- return S_SUCCESS;
+end:
+ return;
}
+/******************************************************************************/
+/* MATH STUFF IMPLEMENTATION */
+/******************************************************************************/
+
+GEN_UADD_DEFINITION( u8 )
+GEN_UADD_DEFINITION( u16 )
+GEN_UADD_DEFINITION( u32 )
+GEN_UADD_DEFINITION( u64 )
+
+GEN_SADD_DEFINITION( s8 )
+GEN_SADD_DEFINITION( s16 )
+GEN_SADD_DEFINITION( s32 )
+GEN_SADD_DEFINITION( s64 )
+
+GEN_USUB_DEFINITION( u8 )
+GEN_USUB_DEFINITION( u16 )
+GEN_USUB_DEFINITION( u32 )
+GEN_USUB_DEFINITION( u64 )
+
+GEN_SSUB_DEFINITION( s8 )
+GEN_SSUB_DEFINITION( s16 )
+GEN_SSUB_DEFINITION( s32 )
+GEN_SSUB_DEFINITION( s64 )
+
+GEN_UMUL_DEFINITION( u8 )
+GEN_UMUL_DEFINITION( u16 )
+GEN_UMUL_DEFINITION( u32 )
+GEN_UMUL_DEFINITION( u64 )
+
+GEN_SMUL_DEFINITION( s8 )
+GEN_SMUL_DEFINITION( s16 )
+GEN_SMUL_DEFINITION( s32 )
+GEN_SMUL_DEFINITION( s64 )
+
+GEN_UROUND_DOWN_DEFINITION( u8 )
+GEN_UROUND_DOWN_DEFINITION( u16 )
+GEN_UROUND_DOWN_DEFINITION( u32 )
+GEN_UROUND_DOWN_DEFINITION( u64 )
+GEN_UROUND_DOWN_DEFINITION( usize )
+
+GEN_UROUND_UP_DEFINITION( u8 )
+GEN_UROUND_UP_DEFINITION( u16 )
+GEN_UROUND_UP_DEFINITION( u32 )
+GEN_UROUND_UP_DEFINITION( u64 )
+GEN_UROUND_UP_DEFINITION( usize )
+
+
#if OS == OS_LINUX
/******************************************************************************/
/* LINUX PLATFORM IMPLEMENTATION */