Every program using LibUCW should start with #include <ucw/lib.h> which brings in the most frequently used library functions, macros and types. This should be done before you include any of the system headers, since lib.h defines the feature macros of the system C library.

Portability

LibUCW is written in C99 with a couple of GNU extensions mixed in where needed. It currently requires the GNU C compiler version 4.0 or newer, but most modules should be very easy to adapt to a different C99 compiler. (A notable exception is stkstring.h, which is heavily tied to GNU extensions.)

The library has been developed on Linux with the GNU libc and it is known to run on Darwin, too. The authors did not try using it on other systems, but most of the code is written for a generic POSIX system, so porting to any UNIX-like system should be a piece of cake.

Threads

Generally, functions in the UCW library are reentrant as long as you call them on different data. Accessing the same object from different threads is not supported, unless otherwise told. This also applies to functions acting on any kind of global state.

ucw/lib.h

Macros for handling structures, offsets and alignment


#define CHECK_PTR_TYPE(x, type) ((x)-(type)(x) + (type)(x))

Check that a pointer x is of type type. Fail compilation if not.


#define PTR_TO(s, i) &((s*)0)->i

Return OFFSETOF() in form of a pointer.


#define OFFSETOF(s, i) ((uint)offsetof(s, i))

Offset of item i from the start of structure s


#define SKIP_BACK(s, i, p) ((s *)((char *)p - OFFSETOF(s, i)))

Given a pointer p to item i of structure s, return a pointer to the start of the struct.


#define ALIGN_TO(s, a) (((s)+a-1)&~(a-1))

Align an integer s to the nearest higher multiple of a (which should be a power of two)


#define ALIGN_PTR(p, s) ((uintptr_t)(p) % (s) ? (typeof(p))((uintptr_t)(p) + (s) - (uintptr_t)(p) % (s)) : (p))

Align a pointer p to the nearest higher multiple of s.

Other utility macros


#define MIN(a,b) (((a)<(b))?(a):(b))

Minimum of two numbers


#define MAX(a,b) (((a)>(b))?(a):(b))

Maximum of two numbers


#define CLAMP(x,min,max) ({ typeof(x) _t=x; (_t < min) ? min : (_t > max) ? max : _t; })

Clip a number x to interval [min,max]


#define ABS(x) ((x) < 0 ? -(x) : (x))

Absolute value


#define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a)))

The number of elements of an array


#define STRINGIFY(x) #x

Convert macro parameter to a string


#define STRINGIFY_EXPANDED(x) STRINGIFY(x)

Convert an expanded macro parameter to a string


#define GLUE(x,y) x##y

Glue two tokens together


#define GLUE_(x,y) x##_##y

Glue two tokens together, separating them by an underscore


#define COMPARE(x,y) do { if ((x)<(y)) return -1; if ((x)>(y)) return 1; } while(0)

Numeric comparison function for qsort()


#define REV_COMPARE(x,y) COMPARE(y,x)

Reverse numeric comparison


#define ROL(x, bits) (((x) << (bits)) | ((uint)(x) >> (sizeof(uint)*8 - (bits))))

Bitwise rotation of an unsigned int to the left


#define ROR(x, bits) (((uint)(x) >> (bits)) | ((x) << (sizeof(uint)*8 - (bits))))

Bitwise rotation of an unsigned int to the right

Shortcuts for GCC Extensions


#define NONRET __attribute__((noreturn))

Function does not return


#define UNUSED __attribute__((unused))

Variable/parameter is knowingly unused


#define CONSTRUCTOR __attribute__((constructor))

Call function upon start of program


#define CONSTRUCTOR_WITH_PRIORITY(p) __attribute__((constructor(p)))

Define constructor with a given priority


#define PACKED __attribute__((packed))

Structure should be packed


#define CONST __attribute__((const))

Function depends only on arguments


#define PURE __attribute__((pure))

Function depends only on arguments and global vars


#define FORMAT_CHECK(x,y,z) __attribute__((format(x,y,z)))

Checking of printf-like format strings


#define likely(x) __builtin_expect((x),1)

Use if (likely(@x)) if x is almost always true


#define unlikely(x) __builtin_expect((x),0)

Use if (unlikely(@x)) to hint that x is almost always false


#define ALWAYS_INLINE inline __attribute__((always_inline))

Forcibly inline


#define NO_INLINE __attribute__((noinline))

Forcibly uninline


#define LIKE_MALLOC __attribute__((malloc))

Function returns a "new" pointer


#define SENTINEL_CHECK __attribute__((sentinel))

The last argument must be NULL

Basic logging functions (see Logging and <ucw/log.h> for more)


enum log_levels {
  L_DEBUG=0,                            // 'D' - Debugging
  L_INFO,                               // 'I' - Informational
  L_WARN,                               // 'W' - Warning
  L_ERROR,                              // 'E' - Error, but non-critical
  L_INFO_R,                             // 'i' - An alternative set of levels for messages caused by remote events
  L_WARN_R,                             // 'w' (e.g., a packet received via network)
  L_ERROR_R,                            // 'e'
  L_FATAL,                              // '!' - Fatal error
  L_MAX
};

The available log levels to pass to msg() and friends.


#define L_SIGHANDLER    0x80000000

Avoid operations that are unsafe in signal handlers


#define L_LOGGER_ERR    0x40000000

Used internally to avoid infinite reporting of logging errors


void msg(uint flags, const char *fmt, ...) FORMAT_CHECK(printf,2,3);

This is the basic printf-like function for logging a message. The flags contain the log level and possibly other flag bits (like L_SIGHANDLER).


void vmsg(uint flags, const char *fmt, va_list args);

A vararg version of msg().


void die(const char *, ...) NONRET FORMAT_CHECK(printf,1,2);

Log a fatal error message and exit the program.


void vdie(const char *fmt, va_list args) NONRET;

va_list version of die()


extern char *log_title;

An optional log message title. Set to program name by log_init().


extern int log_pid;

An optional PID printed in each log message. Set to 0 if it shouldn’t be logged.


extern void (*log_die_hook)(void);

An optional function called just before die() exists.


void log_init(const char *argv0);

Set log_title to the program name extracted from argv[0].


void log_fork(void);

Call after fork() to update log_pid.


void log_file(const char *name);

Establish logging to the named file. Also redirect stderr there.


#define ASSERT(x) ({ if (unlikely(!(x))) assert_failed(#x, __FILE__, __LINE__); 1; })

Check an assertion. If the condition x is false, stop the program with a fatal error. Assertion checks are compiled only when DEBUG_ASSERTS is defined.


#define ASSERT_MSG(cond,str,x...) ({ if (unlikely(!(cond))) assert_failed_msg(#cond, __FILE__, __LINE__, str,##x); 1; })

Check an assertion with a debug message. If the condition cond is false, print the message and stop the program with fatal error. Assertion checks are compiled only when DEBUG_ASSERTS is defined.


#define DBG(x,y...) msg(L_DEBUG, x,##y)

If LOCAL_DEBUG is defined before including <ucw/lib.h>, log a debug message. Otherwise do nothing.


#define DBG_SPOT msg(L_DEBUG, "%s:%d (%s)", __FILE__, __LINE__, __func__)

If LOCAL_DEBUG is defined before including <ucw/lib.h>, log current file name and line number. Otherwise do nothing.


#define ASSERT_READABLE(ptr) ({ volatile char *__p = (ptr); *__p; })

Sometimes, we may want to check that a pointer points to a valid memory location before we start using it for anything more complicated. This macro checks pointer validity by reading the byte it points to.


#define ASSERT_WRITEABLE(ptr) ({ volatile char *__p = (ptr); *__p = *__p; })

Like the previous macro, but it checks writeability, too.

Memory allocation


void *xmalloc(size_t) LIKE_MALLOC;

Allocate memory and die() if there is none.


void *xrealloc(void *, size_t);

Reallocate memory and die() if there is none.


void xfree(void *);

Free memory allocated by xmalloc() or xrealloc().


void *xmalloc_zero(size_t) LIKE_MALLOC;

Allocate memory and fill it by zeroes.


char *xstrdup(const char *) LIKE_MALLOC;

Make a xmalloc()'ed copy of a string. Returns NULL for NULL string.


void *big_alloc(u64 len) LIKE_MALLOC;

Allocate a large memory block in the most efficient way available.


void *big_alloc_zero(u64 len) LIKE_MALLOC;

Allocate and clear a large memory block.


void big_free(void *start, u64 len);

Free block allocated by big_alloc() or big_alloc_zero().

Random numbers (random.c)


uint random_u32(void);

Return a pseudorandom 32-bit number.


uint random_max(uint max);

Return a pseudorandom 32-bit number in range [0,max).


u64 random_u64(void);

Return a pseudorandom 64-bit number.


u64 random_max_u64(u64 max);

Return a pseudorandom 64-bit number in range [0,max).

ucw/config.h

This header contains the standard set of types used by LibUCW. It is automatically included by ucw/lib.h.


typedef uint8_t byte;

Exactly 8 bits, unsigned


typedef uint8_t u8;

Exactly 8 bits, unsigned


typedef int8_t s8;

Exactly 8 bits, signed


typedef uint16_t u16;

Exactly 16 bits, unsigned


typedef int16_t s16;

Exactly 16 bits, signed


typedef uint32_t u32;

Exactly 32 bits, unsigned


typedef int32_t s32;

Exactly 32 bits, signed


typedef uint64_t u64;

Exactly 64 bits, unsigned


typedef int64_t s64;

Exactly 64 bits, signed


typedef unsigned int uint;

A better pronounceable alias for unsigned int


typedef s64 timestamp_t;

Milliseconds since an unknown epoch


typedef uint uns;

Backwards compatible alias for ‘uint’ *


typedef s64 ucw_off_t;

File position (either 32- or 64-bit, depending on CONFIG_UCW_LARGE_FILES).