summaryrefslogtreecommitdiff
path: root/cesar/lib/utils.h
diff options
context:
space:
mode:
Diffstat (limited to 'cesar/lib/utils.h')
-rw-r--r--cesar/lib/utils.h258
1 files changed, 258 insertions, 0 deletions
diff --git a/cesar/lib/utils.h b/cesar/lib/utils.h
new file mode 100644
index 0000000000..cfee107585
--- /dev/null
+++ b/cesar/lib/utils.h
@@ -0,0 +1,258 @@
+#ifndef lib_utils_h
+#define lib_utils_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib/utils.h
+ * \brief Common utilities header.
+ * \ingroup lib
+ *
+ * Define useful utilities used almost everywhere.
+ *
+ * Do not add or modify any macro unless you own the special skills needed to
+ * prevent the creation of a mass destruction weapon from a nice looking
+ * macro.
+ */
+#include "lib/preproc.h"
+
+/** Count the number of element of a table. */
+#define COUNT(table) (sizeof (table) / sizeof ((table)[0]))
+
+/** Count the number of element of a table which is a member of a structure. */
+#define COUNT_MEMBER(parent, table) (COUNT (((parent *) NULL)->table))
+
+/** Return true iff \p a is before \p b modulo 2^32. This is useful to compare two
+ * values of a overflowing counter. This only works iff \p a and \p b are
+ * distant no more than 2^31. */
+extern inline bool
+less_mod2p32 (u32 a, u32 b)
+{
+ return (s32) (a - b) < 0;
+}
+
+/** Return true iff \p a is before or equal to \p b modulo 2^32. This is
+ * useful to compare two values of a overflowing counter. This only works iff
+ * \p a and \p b are distant no more than 2^31. */
+extern inline bool
+lesseq_mod2p32 (u32 a, u32 b)
+{
+ return (s32) (a - b) <= 0;
+}
+
+/** Return true iff \p a is before \p b modulo 2^16. This is useful to compare two
+ * values of a overflowing counter. This only works iff \p a and \p b are
+ * distant no more than 2^15. */
+extern inline bool
+less_mod2p16 (u16 a, u16 b)
+{
+ return (s16) (a - b) < 0;
+}
+
+/** Return true iff \p a is before or equal to \p b modulo 2^16. This is
+ * useful to compare two values of a overflowing counter. This only works iff
+ * \p a and \p b are distant no more than 2^15. */
+extern inline bool
+lesseq_mod2p16 (u16 a, u16 b)
+{
+ return (s16) (a - b) <= 0;
+}
+
+/** Return the absolute value. */
+#define ABS(v) ({ typeof (v) _v = (v); _v > 0 ? _v : -_v; })
+
+/** Return the maximum value. */
+#define MAX(a, b) ({ typeof (a) _a = (a); typeof (b) _b = (b); \
+ _a > _b ? _a : _b; })
+
+/** Return the minimum value. */
+#define MIN(a, b) ({ typeof (a) _a = (a); typeof (b) _b = (b); \
+ _a < _b ? _a : _b; })
+
+/** Exchange two value. */
+#define XCH(a, b) do { \
+ typeof (b) _tmp = (a); \
+ (a) = (b); \
+ (b) = _tmp; \
+} while (0)
+
+/** Return a bit mask composed of a number of LSB ones.
+ * \param b number of one bits, 1 to 31
+ *
+ * - BITS_ONES (0) => error
+ * - BITS_ONES (1) => 0x00000001
+ * - BITS_ONES (15) => 0x00007fff
+ * - BITS_ONES (31) => 0xffffffff
+ */
+#define BITS_ONES(b) ((1u << ((b) - 1) << 1) - 1)
+
+/** Return a bit mask composed of a number of LSB ones, corresponding to the
+ * given bit field.
+ * \param f bit field define
+ *
+ * The bit field is a preprocessor symbol composed of MSB and LSB separated by
+ * a comma.
+ */
+#define BF_ONES(f) BF_ONES_ (f)
+#define BF_ONES_(m, l) BITS_ONES ((m) - (l) + 1)
+
+/** Return a bit mask composed of a number of shifted ones.
+ * \param b number of one bits, 1 to 31
+ * \param s shift, 0 to 30
+ *
+ * - BITS_MASK (0, 0) => error
+ * - BITS_MASK (1, 14) => 0x00004000
+ * - BITS_MASK (15, 7) => 0x003fff80
+ * - BITS_MASK (31, 0) => 0xffffffff
+ */
+#define BITS_MASK(b, s) (BITS_ONES (b) << (s))
+
+/** Return a bit mask composed of a number of shifted ones, corresponding to
+ * the given bit field.
+ * \param f bit field define
+ *
+ * \see BF_ONES.
+ */
+#define BF_MASK(f) BF_MASK_ (f)
+#define BF_MASK_(m, l) BITS_MASK ((m) - (l) + 1, (l))
+
+/** Return true if the given value is small enough to fit in the given bit
+ * field.
+ * \param f bit field define
+ * \param v value to check
+ *
+ * \see BF_ONES.
+ */
+#define BF_CHECK(f, v) BF_CHECK_ (f, (v))
+#define BF_CHECK_(m, l, v) !((v) & ~BF_ONES_ ((m), (l)))
+
+/** Shift the given value to OR it at the right position in the given bit
+ * field.
+ * \param f bit field define
+ * \param v value to shift
+ *
+ * The value is not masked, it should be masked or checked before.
+ * \see BF_ONES.
+ */
+#define BF_SHIFT(f, v) BF_SHIFT_ (f, (v))
+#define BF_SHIFT_(m, l, v) ((v) << (l))
+
+/** Extract the given bit field.
+ * \param f bit field define
+ * \param v value to extract from
+ *
+ * \see BF_ONES.
+ */
+#define BF_GET(f, v) BF_GET_ (f, (v))
+#define BF_GET_(m, l, v) ((v) << (31 - (m)) >> (31 - (m) + (l)))
+
+/** Pack different bit fields together.
+ * \param reg register name (prefix)
+ * \param fv pair of (field, value)
+ *
+ * Example:
+ * \code
+ * #define MYREG__A 7, 0
+ * #define MYREG__B 23, 12
+ * BF_FILL (MYREG, (A, 0x42), (B, 0x123)) => 0x00123042
+ * \endcode
+ */
+#define BF_FILL(reg, fv...) \
+ (0 PREPROC_FOR_EACH_PARAM (BF_FILL_FIELD_, reg ## __, fv))
+#define BF_FILL_FIELD_(reg, fv) \
+ BF_FILL_FIELD__ (reg, PREPROC_UNPACK (fv))
+#define BF_FILL_FIELD__(reg, fv) \
+ BF_FILL_FIELD___ (reg, fv)
+#define BF_FILL_FIELD___(reg, f, v) \
+ | BF_SHIFT (reg ## f, v)
+
+/** Return the number of one bits. */
+#define BITS_ONES_COUNT(x) ({ \
+ typeof (x) _x = (x); \
+ uint i, c = 0; \
+ for (i = sizeof (_x) * 8; i; i--) \
+ { \
+ if (_x & 1) \
+ c++; \
+ _x >>= 1; \
+ } \
+ c; \
+})
+
+/** Return the offset of the given \p member in the given \p parent struct. */
+#define OFFSET_OF(parent, member) ((uint) &((parent *) NULL)->member)
+
+/** When \p member is a member of \p parent struct and \p p a pointer to this
+ * member, return a pointer to the containing struct. */
+#define PARENT_OF(parent, member, p) \
+ ((parent *) ((u8 *) (p) - OFFSET_OF (parent, member)))
+
+/** Cast to the corresponding volatile type. */
+#define VOLATILE(v) ((volatile typeof (*(v)) *) (v))
+
+/** Stop the compiler to reorder instructions across this barrier. You may
+ * consider using volatile instead. */
+#define REORDER_BARRIER() __asm__ __volatile__ ("" : : : "memory")
+
+/** Reverse bitfields if needed to have the first field using the least
+ * significant bit. */
+#define BITFIELDS_WORD(args...) BITFIELDS_WORD_ (args)
+
+#define BITFIELDS_WORD_ECHO(x) x
+#if DEFS_REVERSE_BITFIELDS
+# define BITFIELDS_WORD_(args...) \
+ PREPROC_FOR_EACH (BITFIELDS_WORD_ECHO, PREPROC_REVERSE (args))
+#else
+# define BITFIELDS_WORD_(args...) \
+ PREPROC_FOR_EACH (BITFIELDS_WORD_ECHO, args)
+#endif
+
+/** Define a fixed point number from a double, with 32 bits precision. */
+#define CONST_UF32(d) ((u32) ((1ull << 32) * (d) + 0.5))
+
+/**
+ * Generic dichotomy search.
+ * \param min minimum index
+ * \param max maximum index (past the end)
+ * \param index index unsigned integer variable
+ * \param less comparison expression
+ *
+ * This will expand to a code block which make a dichotomy search in any
+ * indexable object.
+ *
+ * In the following example, the variable \c i gets the found index. It may
+ * index a value greater than the looked up value or be equal to max if all
+ * elements are smaller than the looked up element.
+ *
+ * \code
+ * extern int table[256];
+ * uint i;
+ * int looked_up;
+ * DICHOTOMY_SEARCH (0, COUNT (table), i, looked_up < table[i]);
+ * \endcode
+ */
+#define DICHOTOMY_SEARCH(min, max, index, less) \
+ do { \
+ uint a_, b_; \
+ a_ = (min); \
+ b_ = (max); \
+ while (a_ != b_) \
+ { \
+ index = (a_ + b_) / 2; \
+ if (less) \
+ { \
+ b_ = index; \
+ } \
+ else \
+ { \
+ a_ = index + 1; \
+ } \
+ } \
+ index = a_; \
+ } while (0)
+
+#endif /* lib_utils_h */