diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2022-06-02 22:29:58 +0300 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2022-06-02 22:29:58 +0300 |
| commit | fb8d4be0b18b4c239e4a1eeb93a13e03515fc030 (patch) | |
| tree | ab8d234c99cefa6ae9dbc04eb248b7d50cdba5d6 /include/apos | |
| parent | b5e6a74635eba8e6c5fe0a614c6f578380fb1196 (diff) | |
| download | kmi-fb8d4be0b18b4c239e4a1eeb93a13e03515fc030.tar.gz kmi-fb8d4be0b18b4c239e4a1eeb93a13e03515fc030.zip | |
continue documentation
Diffstat (limited to 'include/apos')
| -rw-r--r-- | include/apos/utils.h | 463 |
1 files changed, 460 insertions, 3 deletions
diff --git a/include/apos/utils.h b/include/apos/utils.h index 24a67f6..c5cdaad 100644 --- a/include/apos/utils.h +++ b/include/apos/utils.h @@ -6,56 +6,232 @@ * Misc utils and helpers. */ +/** + * Get absolute value of expression. + * + * @param a Value to take the absolute value of. + * @return \c a if \c a >= 0, \c -a otherwise. + * \sideeffects + */ #define ABS(a) (a < 0 ? -a : a) +/** + * Get the larger of two values. + * + * @param a First value. + * @param b Second value. + * @return \c a if \code a >= b \endcode, \c b otherwise. + * \sideeffects + */ #define MAX(a, b) ((a) >= (b) ? (a) : (b)) + +/** + * Get the largest of three values. + * + * @param a First value. + * @param b Second value. + * @param c Third value. + * @return Largest of the three values. + * \sideeffects + */ #define MAX3(a, b, c) (MAX(a, b) >= MAX(b, c) ? MAX(a, b) : MAX(b, c)) + +/** + * Get the largest of four values. + * + * @param a First value. + * @param b Second value. + * @param c Third value. + * @param d Fourth value. + * @return Largest of the four values. + * \sideeffects + */ #define MAX4(a, b, c, d) \ (MAX3(a, b, c) >= MAX3(b, c, d) ? MAX3(a, b, c) : MAX3(b, c, d)) /* etc... */ +/** + * Get the smaller of two values. + * + * @param a First value. + * @param b Second value. + * @return The larger of the two values. + * \sideeffects + */ #define MIN(a, b) ((a) <= (b) ? (a) : (b)) + +/** + * Get the smallest of three values. + * + * @param a First value. + * @param b Second value. + * @param c Third value. + * @return The largest of the three values. + * \sideeffects + */ #define MIN3(a, b, c) (MIN(a, b) <= MIN(b, c) ? MIN(a, b) : MIN(b, c)) + +/** + * Get the largest of four values. + * + * @param a First value. + * @param b Second value. + * @param c Third value. + * @param d Fourth value. + * @return The largest of the three values. + * \sideeffects + */ #define MIN4(a, b, c, d) \ (MIN3(a, b, c) <= MIN3(b, c, d) ? MIN3(a, b, c) : MIN3(b, c, d)) /* etc... */ +/** + * Helper for \ref GLUE(). + * Makes sure any macros are expanded all the way. + * + * @param x Head part of the string. + * @param y Tail part of the string. + * \see GLUE(). + */ #define GLUE2(x, y) x##y + +/** + * Glue two strings together. + * + * @param x Head part of the string. + * @param y Tail part of the string. + */ #define GLUE(x, y) GLUE2(x, y) +/** + * Helper for \ref QUOTE(). + * Makes sure any macros are expanded all the way. + * + * @param x String to be quoted. + * \see QUOTE(). + */ #define QUOTE2(x) #x + +/** + * Quote string. + * + * @param x String to be quoted. + */ #define QUOTE(x) QUOTE2(x) +/** + * Silence warnings about unused parameters. + * + * @param x Parameter that is unused. + */ #define UNUSED(x) ((void)(x)) + +/** + * Semantic wrapper around \ref UNUSED(). + * If something might be unused, depending on the configuration, it's more + * accurate to say that it might be unused rather than stating that it is + * unused. + * + * @param x Symbol that might be unused. + */ #define MAYBE_UNUSED(x) UNUSED(x) #include <apos/builtin.h> +/** + * Get offset of member inside structure. + * + * @param type Structure to look in. + * @param member Member whose offset to get. + * @return Offset of \c member in \c type. + */ #if __has_builtin(__builtin_offsetof) #define offsetof(type, member) __builtin_offsetof(type, member) #else #define offsetof(type, member) ((uintptr_t) &((type *)0)->member) #endif +/** + * Signal to the compiler that some expression is likely to be true. + * Might aid in optimisation and branch prediction manipulation. + * + * @param x Expression that is likely to be true. + * @return Value of \c x. + * + * Example: + * \code if (likely(x)) { ... } \endcode + * + * \see unlikely() + */ #if __has_builtin(__builtin_expect) #define likely(x) __builtin_expect(!!(x), 1) -#define unlikely(x) __builtin_expect(!!(x), 0) #else #define likely(x) (x) +#endif + +/** + * Signal to the compiler that some expression is unlikely to be true. + * + * @param x Expression that is unlikely to be true. + * @return Value of \c x. + * + * \see likely(). + */ +#if __has_builtin(__builtin_expect) +#define unlikely(x) __builtin_expect(!!(x), 0) +#else #define unlikely(x) (x) #endif +/** + * Get container of some member. + * + * @param ptr Pointer to member in some structure. + * @param type Structure member is part of. + * @param member Member pointer is pointing to. + * @return Pointer to structure itself instead of member. + */ #define container_of(ptr, type, member) \ ((type *)((char *)(ptr)-offsetof(type, member))) +/** + * Get array size in number of elements. + * + * @param x Array whose size should be calculated. + * @return Number of elements in array. + */ #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +/** + * Check if value is aligned to some other value. + * + * @param x Value whose alignment to check. + * @param a Value to check alignment to. + * @return \ref true if \c x is aligned, \ref false otherwise. + */ #define ALIGNED(x, a) ((x) % a == 0) +/** + * Add value to pointer in bytes instead of elements. + * + * @param x Pointer to add value to. + * @param y Value to add to pointer. + * @return \c x with \c y added to it. + */ #define ptradd(x, y) (((vm_t)(x)) + ((vm_t)(y))) #include <apos/types.h> -/* clang-format doesn't like _Generic, but I guess that's fine. */ +/* clang-format doesn't like _Generic, but I guess that's fine. + * Uncrustify just ignores it, as far as I can tell. */ +/** + * Align value upwards. + * Type is deduced from \c x. + * + * @param x Value to align up. + * @param y Value to align to. + * @return \c x aligned to \c y. + */ #define align_up(x, y) \ _Generic((x), signed char \ : align_up_c, signed short \ @@ -71,6 +247,12 @@ : align_up_ul, unsigned long long \ : align_up_ull)((x), (y)) +/** + * Helper macro for defining type specific aligning. + * + * @param name Name of type in function name. + * @param type Actual type. + */ #define DEFINE_ALIGN_UP(name, type) \ static inline type align_up_##name(type val, type a) \ { \ @@ -87,18 +269,104 @@ return val + a - rem; \ } +/** + * Align signed char up. + * + * @param val Value to align. + * @param a Value to align to. + * @return \c val aligned up to nearest multiple of \c a. + */ DEFINE_ALIGN_UP(c, signed char); + +/** + * Align signed short up. + * + * @param val Value to align. + * @param a Value to align to. + * @return \c val aligned up to nearest multiple of \c a. + */ DEFINE_ALIGN_UP(s, signed short); + +/** + * Align signed int up. + * + * @param val Value to align. + * @param a Value to align to. + * @return \c val aligned up to nearest multiple of \c a. + */ DEFINE_ALIGN_UP(i, signed int); + +/** + * Align signed long up. + * + * @param val Value to align. + * @param a Value to align to. + * @return \c val aligned up to nearest multiple of \c a. + */ DEFINE_ALIGN_UP(l, signed long); + +/** + * Align signed long long up. + * + * @param val Value to align. + * @param a Value to align to. + * @return \c val aligned up to nearest multiple of \c a. + */ DEFINE_ALIGN_UP(ll, signed long long); +/** + * Align unsigned char up. + * + * @param val Value to align. + * @param a Value to align to. + * @return \c val aligned up to nearest multiple of \c a. + */ DEFINE_ALIGN_UP(uc, unsigned char); + +/** + * Align unsigned short up. + * + * @param val Value to align. + * @param a Value to align to. + * @return \c val aligned up to nearest multiple of \c a. + */ DEFINE_ALIGN_UP(us, unsigned short); + +/** + * Align unsigned int up. + * + * @param val Value to align. + * @param a Value to align to. + * @return \c val aligned up to nearest multiple of \c a. + */ DEFINE_ALIGN_UP(ui, unsigned int); + +/** + * Align unsigned long up. + * + * @param val Value to align. + * @param a Value to align to. + * @return \c val aligned up to nearest multiple of \c a. + */ DEFINE_ALIGN_UP(ul, unsigned long); + +/** + * Align unsigned long long up. + * + * @param val Value to align. + * @param a Value to align to. + * @return \c val aligned up to nearest multiple of \c a. + */ DEFINE_ALIGN_UP(ull, unsigned long long); +/** + * Align value downwards. + * Type is deduced from \c x. + * + * @param x Value to align. + * @param y Value to align to. + * @return \c x aligned to down \c y. + */ #define align_down(x, y) \ _Generic((x), signed char \ : align_down_c, signed short \ @@ -114,6 +382,12 @@ DEFINE_ALIGN_UP(ull, unsigned long long); : align_down_ul, unsigned long long \ : align_down_ull)((x), (y)) +/** + * Helper macro for defining type specific aligning. + * + * @param name Name of type in function name. + * @param type Actual type. + */ #define DEFINE_ALIGN_DOWN(name, type) \ static inline type align_down_##name(type val, type a) \ { \ @@ -124,18 +398,103 @@ DEFINE_ALIGN_UP(ull, unsigned long long); return val - (val % a); \ } +/** + * Align signed char down. + * + * @param val Value to align. + * @param a Value to align to. + * @return \c val aligned down to nearest multiple of \c a. + */ DEFINE_ALIGN_DOWN(c, signed char); + +/** + * Align signed short down. + * + * @param val Value to align. + * @param a Value to align to. + * @return \c val aligned down to nearest multiple of \c a. + */ DEFINE_ALIGN_DOWN(s, signed short); + +/** + * Align signed int down. + * + * @param val Value to align. + * @param a Value to align to. + * @return \c val aligned down to nearest multiple of \c a. + */ DEFINE_ALIGN_DOWN(i, signed int); + +/** + * Align signed long down. + * + * @param val Value to align. + * @param a Value to align to. + * @return \c val aligned down to nearest multiple of \c a. + */ DEFINE_ALIGN_DOWN(l, signed long); + +/** + * Align signed long long down. + * + * @param val Value to align. + * @param a Value to align to. + * @return \c val aligned down to nearest multiple of \c a. + */ DEFINE_ALIGN_DOWN(ll, signed long long); +/** + * Align unsigned char down. + * + * @param val Value to align. + * @param a Value to align to. + * @return \c val aligned down to nearest multiple of \c a. + */ DEFINE_ALIGN_DOWN(uc, unsigned char); + +/** + * Align unsigned short down. + * + * @param val Value to align. + * @param a Value to align to. + * @return \c val aligned down to nearest multiple of \c a. + */ DEFINE_ALIGN_DOWN(us, unsigned short); + +/** + * Align unsigned int down. + * + * @param val Value to align. + * @param a Value to align to. + * @return \c val aligned down to nearest multiple of \c a. + */ DEFINE_ALIGN_DOWN(ui, unsigned int); + +/** + * Align unsigned long down. + * + * @param val Value to align. + * @param a Value to align to. + * @return \c val aligned down to nearest multiple of \c a. + */ DEFINE_ALIGN_DOWN(ul, unsigned long); + +/** + * Align unsigned long long down. + * + * @param val Value to align. + * @param a Value to align to. + * @return \c val aligned down to nearest multiple of \c a. + */ DEFINE_ALIGN_DOWN(ull, unsigned long long); +/** + * Check if value is aligned. + * + * @param x Value to check. + * @param y Alignment to check to. + * @return \ref true if \c x is aligned to \c y, \ref false otherwise. + */ #define is_aligned(x, y) \ _Generic((x), signed char \ : is_aligned_c, signed short \ @@ -151,6 +510,12 @@ DEFINE_ALIGN_DOWN(ull, unsigned long long); : is_aligned_ul, unsigned long long \ : is_aligned_ll)((x), (y)) +/** + * Helper macro for defining type specific alignment checks. + * + * @param name Name of type in function name. + * @param type Actual type. + */ #define DEFINE_ALIGNED(name, type) \ static inline bool is_aligned_##name(type val, type a) \ { \ @@ -161,18 +526,102 @@ DEFINE_ALIGN_DOWN(ull, unsigned long long); return val % a == 0; \ } +/** + * Check if signed char is aligned. + * + * @param val Value to check. + * @param a Alignment to check to. + * @return \ref true if \c val is aligned to \c a, \ref false otherwise. + */ DEFINE_ALIGNED(c, signed char); + +/** + * Check if signed short is aligned. + * + * @param val Value to check. + * @param a Alignment to check to. + * @return \ref true if \c val is aligned to \c a, \ref false otherwise. + */ DEFINE_ALIGNED(s, signed short); + +/** + * Check if signed int is aligned. + * + * @param val Value to check. + * @param a Alignment to check to. + * @return \ref true if \c val is aligned to \c a, \ref false otherwise. + */ DEFINE_ALIGNED(i, signed int); + +/** + * Check if signed long is aligned. + * + * @param val Value to check. + * @param a Alignment to check to. + * @return \ref true if \c val is aligned to \c a, \ref false otherwise. + */ DEFINE_ALIGNED(l, signed long); + +/** + * Check if signed long long is aligned. + * + * @param val Value to check. + * @param a Alignment to check to. + * @return \ref true if \c val is aligned to \c a, \ref false otherwise. + */ DEFINE_ALIGNED(ll, signed long long); +/** + * Check if unsigned char is aligned. + * + * @param val Value to check. + * @param a Alignment to check to. + * @return \ref true if \c val is aligned to \c a, \ref false otherwise. + */ DEFINE_ALIGNED(uc, unsigned char); + +/** + * Check if unsigned short is aligned. + * + * @param val Value to check. + * @param a Alignment to check to. + * @return \ref true if \c val is aligned to \c a, \ref false otherwise. + */ DEFINE_ALIGNED(us, unsigned short); + +/** + * Check if unsigned int is aligned. + * + * @param val Value to check. + * @param a Alignment to check to. + * @return \ref true if \c val is aligned to \c a, \ref false otherwise. + */ DEFINE_ALIGNED(ui, unsigned int); + +/** + * Check if unsigned long is aligned. + * + * @param val Value to check. + * @param a Alignment to check to. + * @return \ref true if \c val is aligned to \c a, \ref false otherwise. + */ DEFINE_ALIGNED(ul, unsigned long); + +/** + * Check if unsigned long long is aligned. + * + * @param val Value to check. + * @param a Alignment to check to. + * @return \ref true if \c val is aligned to \c a, \ref false otherwise. + */ DEFINE_ALIGNED(ull, unsigned long long); +/** + * Get numeric value of ASCII character. + * + * @param c Character representing a number. + * @return Corresponding number. -1 if parsing failed. + */ static inline int asciinum(char c) { if (c >= '0' && c <= '9') @@ -182,9 +631,17 @@ static inline int asciinum(char c) else if (c >= 'a' && c <= 'f') return c - 'a' + 10; else - return 0; + return -1; } +/** + * Convert string representing number to actual number. + * + * @param c String representing number. + * @param len Length of \c str. + * @param base Base of number. + * @return Corresponding number. + */ static inline uintmax_t convnum(const char *c, size_t len, size_t base) { size_t multiplier = 1; |
