2006-04-12 01:59:08 +02:00
|
|
|
/**
|
|
|
|
* =========================================================================
|
|
|
|
* File : lib.h
|
|
|
|
* Project : 0 A.D.
|
|
|
|
* Description : various utility functions.
|
|
|
|
*
|
|
|
|
* @author Jan.Wassenberg@stud.uni-karlsruhe.de
|
|
|
|
* =========================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (c) 2003-2005 Jan Wassenberg
|
|
|
|
*
|
|
|
|
* Redistribution and/or modification are also permitted under the
|
|
|
|
* terms of the GNU General Public License as published by the
|
|
|
|
* Free Software Foundation (version 2 or later, at your option).
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
*/
|
2004-03-03 00:56:51 +01:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
2005-03-18 23:07:55 +01:00
|
|
|
|
|
|
|
low-level aka "lib"
|
|
|
|
-------------------
|
|
|
|
|
|
|
|
this codebase was grown from modules shared between several projects,
|
|
|
|
i.e. my personal library; hence the name "lib". it has been expanded to
|
|
|
|
fit the needs of 0ad - in particular, resource loading.
|
|
|
|
|
|
|
|
owing to the dual-use situation, the 0ad coding conventions are not met;
|
|
|
|
also, major changes are ill-advised because they may break other projects.
|
|
|
|
|
|
|
|
|
|
|
|
design goals
|
|
|
|
------------
|
|
|
|
|
|
|
|
- fast and low-overhead, including startup time
|
|
|
|
- portable: must run on Win32, Mac OS X and Linux
|
|
|
|
- reusable across projects, i.e. no dependency on a
|
|
|
|
central 'manager' that ties modules together.
|
|
|
|
|
|
|
|
|
|
|
|
scope
|
|
|
|
-----
|
|
|
|
|
|
|
|
- POSIX definitions
|
|
|
|
- resource management
|
|
|
|
- debugging tools (including memory tracker)
|
|
|
|
- low-level helper functions, e.g. ADTs, endian conversion and timing
|
|
|
|
- platform-dependent system/feature detection
|
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
**/
|
2005-03-18 23:07:55 +01:00
|
|
|
|
|
|
|
#ifndef LIB_H__
|
|
|
|
#define LIB_H__
|
2004-03-03 00:56:51 +01:00
|
|
|
|
|
|
|
#include <stddef.h>
|
2005-10-12 06:16:41 +02:00
|
|
|
#include <math.h> // fabsf
|
2005-06-28 06:12:50 +02:00
|
|
|
|
2004-03-03 00:56:51 +01:00
|
|
|
#include "config.h"
|
2005-02-26 16:15:36 +01:00
|
|
|
#include "lib/types.h"
|
2004-03-03 00:56:51 +01:00
|
|
|
|
|
|
|
|
2005-05-30 06:51:47 +02:00
|
|
|
#if defined(__cplusplus)
|
2006-05-31 06:01:59 +02:00
|
|
|
# define EXTERN_C extern "C"
|
2005-05-30 06:51:47 +02:00
|
|
|
#else
|
2006-05-31 06:01:59 +02:00
|
|
|
# define EXTERN_C extern
|
2005-05-30 06:51:47 +02:00
|
|
|
#endif
|
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
|
|
|
|
const size_t KiB = 1ul << 10;
|
|
|
|
const size_t MiB = 1ul << 20;
|
|
|
|
const size_t GiB = 1ul << 30;
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// code-generating macros
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
/**
|
|
|
|
* package code into a single statement.
|
|
|
|
*
|
|
|
|
* @param STMT_code__ code to be bundled. (must be interpretable as
|
|
|
|
* a macro argument, i.e. sequence of tokens).
|
|
|
|
* the argument name is chosen to avoid conflicts.
|
|
|
|
*
|
|
|
|
* notes:
|
|
|
|
* - for(;;) { break; } and {} don't work because invocations of macros
|
|
|
|
* implemented with STMT often end with ";", thus breaking if() expressions.
|
|
|
|
* - we'd really like to eliminate "conditional expression is constant"
|
|
|
|
* warnings. replacing 0 literals with extern volatile variables fools
|
|
|
|
* VC7 but isn't guaranteed to be free of overhead. we will just
|
|
|
|
* squelch the warning (unfortunately non-portable).
|
|
|
|
**/
|
2005-08-09 18:23:19 +02:00
|
|
|
#define STMT(STMT_code__) do { STMT_code__; } while(false)
|
2004-03-03 00:56:51 +01:00
|
|
|
|
2005-12-11 23:23:55 +01:00
|
|
|
// must come after definition of STMT
|
|
|
|
#include "lib/lib_errors.h"
|
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
|
|
|
* execute the code passed as a parameter only the first time this is
|
|
|
|
* reached.
|
|
|
|
* may be called at any time (in particular before main), but is not
|
|
|
|
* thread-safe. if that's important, use pthread_once() instead.
|
|
|
|
**/
|
2004-03-03 00:56:51 +01:00
|
|
|
#define ONCE(ONCE_code__)\
|
2004-05-06 19:14:30 +02:00
|
|
|
STMT(\
|
2004-03-03 00:56:51 +01:00
|
|
|
static bool ONCE_done__ = false;\
|
2004-06-01 19:34:12 +02:00
|
|
|
if(!ONCE_done__)\
|
2004-03-03 00:56:51 +01:00
|
|
|
{\
|
|
|
|
ONCE_done__ = true;\
|
|
|
|
ONCE_code__;\
|
|
|
|
}\
|
2004-05-06 19:14:30 +02:00
|
|
|
)
|
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
|
|
|
* execute the code passed as a parameter except the first time this is
|
|
|
|
* reached.
|
|
|
|
* may be called at any time (in particular before main), but is not
|
|
|
|
* thread-safe.
|
|
|
|
**/
|
2005-10-19 05:06:54 +02:00
|
|
|
#define ONCE_NOT(ONCE_code__)\
|
|
|
|
STMT(\
|
|
|
|
static bool ONCE_done__ = false;\
|
|
|
|
if(!ONCE_done__)\
|
|
|
|
ONCE_done__ = true;\
|
|
|
|
else\
|
|
|
|
ONCE_code__;\
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
|
|
|
* C++ new wrapper: allocates an instance of the given type and stores a
|
|
|
|
* pointer to it. sets pointer to 0 on allocation failure.
|
|
|
|
*
|
|
|
|
* this simplifies application code when on VC6, which may or
|
|
|
|
* may not throw/return 0 on failure.
|
|
|
|
**/
|
2004-06-08 14:10:51 +02:00
|
|
|
#define SAFE_NEW(type, ptr)\
|
|
|
|
type* ptr;\
|
|
|
|
try\
|
|
|
|
{\
|
|
|
|
ptr = new type();\
|
|
|
|
}\
|
|
|
|
catch(std::bad_alloc)\
|
|
|
|
{\
|
|
|
|
ptr = 0;\
|
2004-06-18 15:24:59 +02:00
|
|
|
}
|
2004-06-08 14:10:51 +02:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
|
|
|
* delete memory ensuing from new and set the pointer to zero
|
|
|
|
* (thus making double-frees safe / a no-op)
|
|
|
|
**/
|
2005-09-08 19:14:19 +02:00
|
|
|
#define SAFE_DELETE(p)\
|
|
|
|
STMT(\
|
2005-10-12 06:16:41 +02:00
|
|
|
delete (p); /* if p == 0, delete is a no-op */ \
|
|
|
|
(p) = 0;\
|
2005-09-08 03:47:45 +02:00
|
|
|
)
|
2004-06-08 14:10:51 +02:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
|
|
|
* delete memory ensuing from new[] and set the pointer to zero
|
|
|
|
* (thus making double-frees safe / a no-op)
|
|
|
|
**/
|
|
|
|
#define SAFE_ARRAY_DELETE(p)\
|
|
|
|
STMT(\
|
|
|
|
delete[] (p); /* if p == 0, delete is a no-op */ \
|
|
|
|
(p) = 0;\
|
|
|
|
)
|
2004-07-14 05:06:15 +02:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
|
|
|
* free memory ensuing from malloc and set the pointer to zero
|
|
|
|
* (thus making double-frees safe / a no-op)
|
|
|
|
**/
|
2006-01-23 08:59:20 +01:00
|
|
|
#define SAFE_FREE(p)\
|
|
|
|
STMT(\
|
|
|
|
free(p); /* if p == 0, free is a no-op */ \
|
|
|
|
(p) = 0;\
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// source code annotation
|
|
|
|
//-----------------------------------------------------------------------------
|
2004-11-23 22:08:59 +01:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
|
|
|
* mark a function local variable or parameter as unused and avoid
|
|
|
|
* the corresponding compiler warning.
|
|
|
|
* use inside the function body, e.g. void f(int x) { UNUSED2(x); }
|
|
|
|
**/
|
2005-08-09 18:23:19 +02:00
|
|
|
#define UNUSED2(param) (void)param;
|
2006-05-31 06:01:59 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* mark a function parameter as unused and avoid
|
|
|
|
* the corresponding compiler warning.
|
|
|
|
* wrap around the parameter name, e.g. void f(int UNUSED(x))
|
|
|
|
**/
|
2005-08-09 18:23:19 +02:00
|
|
|
#define UNUSED(param)
|
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
|
|
|
* mark the copy constructor as inaccessible. this squelches
|
|
|
|
* "cannot be generated" warnings for classes with const members.
|
|
|
|
*
|
|
|
|
* intended to be used at end of class definition.
|
|
|
|
* must be followed by semicolon.
|
|
|
|
**/
|
2006-05-17 18:47:49 +02:00
|
|
|
#define NO_COPY_CTOR(class_name)\
|
|
|
|
private:\
|
2006-08-21 23:27:12 +02:00
|
|
|
class_name& operator=(const class_name&);\
|
|
|
|
class_name(const class_name&)
|
2006-05-17 18:47:49 +02:00
|
|
|
|
2006-04-10 08:44:54 +02:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
2006-04-10 08:44:54 +02:00
|
|
|
"unreachable code" helpers
|
|
|
|
|
|
|
|
unreachable lines of code are often the source or symptom of subtle bugs.
|
|
|
|
they are flagged by compiler warnings; however, the opposite problem -
|
|
|
|
erroneously reaching certain spots (e.g. due to missing return statement)
|
|
|
|
is worse and not detected automatically.
|
|
|
|
|
|
|
|
to defend against this, the programmer can annotate their code to
|
|
|
|
indicate to humans that a particular spot should never be reached.
|
|
|
|
however, that isn't much help; better is a sentinel that raises an
|
|
|
|
error if if it is actually reached. hence, the UNREACHABLE macro.
|
|
|
|
|
|
|
|
ironically, if the code guarded by UNREACHABLE works as it should,
|
|
|
|
compilers may flag the macro's code as unreachable. this would
|
|
|
|
distract from genuine warnings, which is unacceptable.
|
|
|
|
|
|
|
|
even worse, compilers differ in their code checking: GCC only complains if
|
|
|
|
non-void functions end without returning a value (i.e. missing return
|
|
|
|
statement), while VC checks if lines are unreachable (e.g. if they are
|
|
|
|
preceded by a return on all paths).
|
|
|
|
|
|
|
|
our implementation of UNREACHABLE solves this dilemna as follows:
|
|
|
|
- on GCC: call abort(); since it has the noreturn attributes, the
|
|
|
|
"non-void" warning disappears.
|
|
|
|
- on VC: avoid generating any code. we allow the compiler to assume the
|
|
|
|
spot is actually unreachable, which incidentally helps optimization.
|
|
|
|
if reached after all, a crash usually results. in that case, compile with
|
|
|
|
CONFIG_PARANOIA, which will cause an error message to be displayed.
|
|
|
|
|
|
|
|
this approach still allows for the possiblity of automated
|
|
|
|
checking, but does not cause any compiler warnings.
|
2006-05-31 06:01:59 +02:00
|
|
|
**/
|
|
|
|
#define UNREACHABLE // actually defined below.. this is for
|
|
|
|
# undef UNREACHABLE // CppDoc's benefit only.
|
2006-04-10 08:44:54 +02:00
|
|
|
|
|
|
|
// 1) final build: optimize assuming this location cannot be reached.
|
|
|
|
// may crash if that turns out to be untrue, but removes checking overhead.
|
|
|
|
#if CONFIG_FINAL
|
|
|
|
# define UNREACHABLE SYS_UNREACHABLE
|
|
|
|
// 2) normal build:
|
|
|
|
#else
|
|
|
|
// a) normal implementation: includes "abort", which is declared with
|
|
|
|
// noreturn attribute and therefore avoids GCC's "execution reaches
|
|
|
|
// end of non-void function" warning.
|
|
|
|
# if !MSC_VERSION || CONFIG_PARANOIA
|
|
|
|
# define UNREACHABLE\
|
|
|
|
STMT(\
|
|
|
|
debug_warn("hit supposedly unreachable code");\
|
|
|
|
abort();\
|
|
|
|
)
|
|
|
|
// b) VC only: don't generate any code; squelch the warning and optimize.
|
2005-11-09 05:11:13 +01:00
|
|
|
# else
|
2006-04-10 08:44:54 +02:00
|
|
|
# define UNREACHABLE SYS_UNREACHABLE
|
2005-11-09 05:11:13 +01:00
|
|
|
# endif
|
2005-09-13 01:37:52 +02:00
|
|
|
#endif
|
2004-03-03 00:56:51 +01:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
2006-04-10 08:44:54 +02:00
|
|
|
convenient specialization of UNREACHABLE for switch statements whose
|
|
|
|
default can never be reached. example usage:
|
|
|
|
int x;
|
|
|
|
switch(x % 2)
|
|
|
|
{
|
|
|
|
case 0: break;
|
|
|
|
case 1: break;
|
|
|
|
NODEFAULT;
|
|
|
|
}
|
2006-05-31 06:01:59 +02:00
|
|
|
**/
|
2006-04-10 08:44:54 +02:00
|
|
|
#define NODEFAULT default: UNREACHABLE
|
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// cassert
|
2004-03-03 00:56:51 +01:00
|
|
|
|
|
|
|
// generate a symbol containing the line number of the macro invocation.
|
|
|
|
// used to give a unique name (per file) to types made by cassert.
|
2004-05-06 19:14:30 +02:00
|
|
|
// we can't prepend __FILE__ to make it globally unique - the filename
|
|
|
|
// may be enclosed in quotes. need the 2 macro expansions to make sure
|
|
|
|
// __LINE__ is expanded correctly.
|
2004-03-03 00:56:51 +01:00
|
|
|
#define MAKE_UID2__(l) LINE_ ## l
|
|
|
|
#define MAKE_UID1__(l) MAKE_UID2__(l)
|
|
|
|
#define UID__ MAKE_UID1__(__LINE__)
|
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
|
|
|
* compile-time debug_assert. causes a compile error if the expression
|
|
|
|
* evaluates to zero/false.
|
|
|
|
*
|
|
|
|
* no runtime overhead; may be used anywhere, including file scope.
|
|
|
|
* especially useful for testing sizeof types.
|
|
|
|
*
|
|
|
|
* this version has a more descriptive error message, but may cause a
|
|
|
|
* struct redefinition warning if used from the same line in different files.
|
|
|
|
*
|
|
|
|
* note: alternative method in C++: specialize a struct only for true;
|
|
|
|
* using it will raise 'incomplete type' errors if instantiated with false.
|
|
|
|
*
|
|
|
|
* @param expression that is expected to evaluate to non-zero at compile-time.
|
|
|
|
**/
|
2004-06-22 15:22:46 +02:00
|
|
|
#define cassert(expr) struct UID__ { int CASSERT_FAILURE: (expr); }
|
2004-03-03 00:56:51 +01:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
|
|
|
* compile-time debug_assert. causes a compile error if the expression
|
|
|
|
* evaluates to zero/false.
|
|
|
|
*
|
|
|
|
* no runtime overhead; may be used anywhere, including file scope.
|
|
|
|
* especially useful for testing sizeof types.
|
|
|
|
*
|
|
|
|
* this version has a less helpful error message, but redefinition doesn't
|
|
|
|
* trigger warnings.
|
|
|
|
*
|
|
|
|
* @param expression that is expected to evaluate to non-zero at compile-time.
|
|
|
|
**/
|
2004-06-22 15:22:46 +02:00
|
|
|
#define cassert2(expr) extern char CASSERT_FAILURE[1][(expr)]
|
2004-03-03 00:56:51 +01:00
|
|
|
|
2005-12-10 08:04:31 +01:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// bit bashing
|
|
|
|
//-----------------------------------------------------------------------------
|
2005-12-10 08:04:31 +01:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
|
|
|
* value of bit number <n>.
|
|
|
|
*
|
|
|
|
* @param n bit index (0..CHAR_BIT*sizeof(int)-1)
|
|
|
|
**/
|
2004-03-03 00:56:51 +01:00
|
|
|
#define BIT(n) (1ul << (n))
|
|
|
|
|
|
|
|
|
2005-09-20 01:40:33 +02:00
|
|
|
// these are declared in the header and inlined to aid compiler optimizations
|
|
|
|
// (they can easily end up being time-critical).
|
2006-05-31 06:01:59 +02:00
|
|
|
// note: GCC can't inline extern functions, while VC's "Whole Program
|
|
|
|
// Optimization" can.
|
2005-09-20 01:40:33 +02:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
|
|
|
* a mask that includes the lowest N bits
|
|
|
|
*
|
|
|
|
* @param num_bits number of bits in mask
|
|
|
|
**/
|
2005-09-20 01:40:33 +02:00
|
|
|
inline uint bit_mask(uint num_bits)
|
|
|
|
{
|
|
|
|
return (1u << num_bits)-1;
|
|
|
|
}
|
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
|
|
|
* extract the value of bits hi_idx:lo_idx within num
|
|
|
|
*
|
|
|
|
* example: bits(0x69, 2, 5) == 0x0A
|
|
|
|
*
|
|
|
|
* @param num number whose bits are to be extracted
|
|
|
|
* @param lo_idx bit index of lowest bit to include
|
|
|
|
* @param hi_idx bit index of highest bit to include
|
|
|
|
* @return value of extracted bits.
|
|
|
|
**/
|
2005-09-20 01:40:33 +02:00
|
|
|
inline uint bits(uint num, uint lo_idx, uint hi_idx)
|
|
|
|
{
|
|
|
|
const uint count = (hi_idx - lo_idx)+1; // # bits to return
|
|
|
|
uint result = num >> lo_idx;
|
|
|
|
result &= bit_mask(count);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/// is the given number a power of two?
|
|
|
|
extern bool is_pow2(uint n);
|
2004-03-03 00:56:51 +01:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
2006-06-24 12:44:08 +02:00
|
|
|
* base-2 logarithm; return -1 for non-integral powers of 2.
|
2006-05-31 06:01:59 +02:00
|
|
|
**/
|
|
|
|
extern int ilog2(uint n);
|
2004-06-01 19:34:12 +02:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
2006-06-24 12:44:08 +02:00
|
|
|
* base-2 logarithm, rounded up.
|
|
|
|
*
|
|
|
|
* @param n input; MUST be > 0, else results are undefined.
|
2006-05-31 06:01:59 +02:00
|
|
|
**/
|
|
|
|
extern uint log2(uint x);
|
2005-03-27 03:31:39 +02:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
2006-06-24 12:44:08 +02:00
|
|
|
* base-2 logarithm (uses the FPU normalization hardware).
|
2006-05-31 06:01:59 +02:00
|
|
|
*
|
2006-06-24 12:44:08 +02:00
|
|
|
* @param n input; MUST be > 0, else results are undefined.
|
2006-05-31 06:01:59 +02:00
|
|
|
**/
|
|
|
|
extern int ilog2(const float x);
|
2004-06-01 19:34:12 +02:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
2006-06-24 12:44:08 +02:00
|
|
|
* round up to next larger power of two.
|
2006-05-31 06:01:59 +02:00
|
|
|
**/
|
|
|
|
extern uint round_up_to_pow2(uint x);
|
2004-06-01 19:34:12 +02:00
|
|
|
|
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// misc arithmetic
|
2005-05-27 06:40:29 +02:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/// canonical minimum macro
|
|
|
|
#ifndef MIN
|
|
|
|
#define MIN(a, b) (((a) < (b))? (a) : (b))
|
|
|
|
#endif
|
2004-06-01 19:34:12 +02:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/// canonical maximum macro
|
|
|
|
#ifndef MAX
|
|
|
|
#define MAX(a, b) (((a) > (b))? (a) : (b))
|
|
|
|
#endif
|
2004-06-01 19:34:12 +02:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/// number of array elements
|
|
|
|
#define ARRAY_SIZE(name) (sizeof(name) / sizeof(name[0]))
|
2004-06-01 19:34:12 +02:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
|
|
|
* round number up/down to the next given multiple.
|
|
|
|
*
|
|
|
|
* @param multiple: must be a power of two.
|
|
|
|
**/
|
|
|
|
extern uintptr_t round_up (uintptr_t n, uintptr_t multiple);
|
|
|
|
extern uintptr_t round_down(uintptr_t n, uintptr_t multiple);
|
2004-06-01 19:34:12 +02:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/// 16-bit saturating (does not overflow) addition.
|
|
|
|
extern u16 addusw(u16 x, u16 y);
|
|
|
|
/// 16-bit saturating (does not underflow) subtraction.
|
|
|
|
extern u16 subusw(u16 x, u16 y);
|
2004-06-19 16:43:31 +02:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
|
|
|
* are the given floats nearly "equal"?
|
|
|
|
*
|
|
|
|
* @return whether the numbers are within "epsilon" of each other.
|
|
|
|
*
|
|
|
|
* notes:
|
|
|
|
* - the epsilon magic number varies with the magnitude of the inputs.
|
|
|
|
* we use a sane default, but don't use this routine for very
|
|
|
|
* large/small comparands.
|
|
|
|
* - floating-point numbers don't magically lose precision. addition,
|
|
|
|
* subtraction and multiplication results are precise up to the mantissa's
|
|
|
|
* least-significant bit. only division, sqrt, sin/cos and other
|
|
|
|
* trancendental operations introduce error.
|
|
|
|
**/
|
|
|
|
inline bool feq(float f1, float f2)
|
|
|
|
{
|
|
|
|
const float epsilon = 0.00001f;
|
|
|
|
return fabsf(f1 - f2) < epsilon;
|
|
|
|
}
|
2005-10-19 19:16:34 +02:00
|
|
|
|
2004-06-01 19:34:12 +02:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
|
|
|
* return random integer in [min, max).
|
|
|
|
* avoids several common pitfalls; see discussion at
|
|
|
|
* http://www.azillionmonkeys.com/qed/random.html
|
|
|
|
**/
|
|
|
|
extern uint rand(uint min_inclusive, uint max_exclusive);
|
2004-06-01 19:34:12 +02:00
|
|
|
|
2006-02-09 06:59:33 +01:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// type conversion
|
2005-08-09 18:23:19 +02:00
|
|
|
|
2005-08-12 19:06:53 +02:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
// note: these avoid a common mistake in using >> (ANSI requires
|
|
|
|
// shift count be less than the bit width of the type).
|
2006-03-15 06:18:32 +01:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
extern u32 u64_hi(u64 x); /// return upper 32-bits
|
|
|
|
extern u32 u64_lo(u64 x); /// return lower 32-bits
|
|
|
|
extern u16 u32_hi(u32 x); /// return upper 16-bits
|
|
|
|
extern u16 u32_lo(u32 x); /// return lower 16-bits
|
2006-03-15 06:18:32 +01:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
extern u64 u64_from_u32(u32 hi, u32 lo); /// assemble u64 from u32
|
|
|
|
extern u32 u32_from_u16(u16 hi, u16 lo); /// assemble u32 from u16
|
2005-08-09 18:23:19 +02:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
|
|
|
* zero-extend <size> (truncated to 8) bytes of little-endian data to u64,
|
|
|
|
* starting at address <p> (need not be aligned).
|
|
|
|
**/
|
|
|
|
extern u64 movzx_64le(const u8* p, size_t size);
|
2005-10-12 06:16:41 +02:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
|
|
|
* sign-extend <size> (truncated to 8) bytes of little-endian data to i64,
|
|
|
|
* starting at address <p> (need not be aligned).
|
|
|
|
**/
|
|
|
|
extern i64 movsx_64le(const u8* p, size_t size);
|
2005-10-12 06:16:41 +02:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/// convert double to u8; verifies number is in range.
|
|
|
|
extern u8 fp_to_u8 (double in);
|
|
|
|
/// convert double to u16; verifies number is in range.
|
2004-06-01 19:34:12 +02:00
|
|
|
extern u16 fp_to_u16(double in);
|
|
|
|
|
2005-04-26 18:47:48 +02:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// string processing
|
|
|
|
|
|
|
|
/**
|
|
|
|
* this is strcpy, but indicates that the programmer checked usage and
|
|
|
|
* promises it is safe.
|
|
|
|
**/
|
|
|
|
#define SAFE_STRCPY strcpy
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* generate the base32 textual representation of a buffer.
|
|
|
|
*
|
|
|
|
* @param len size [bytes] of input
|
|
|
|
* @param big-endian input data (assumed to be integral number of bytes)
|
|
|
|
* @param output string; zero-terminated. must be big enough
|
|
|
|
* (i.e. at least ceil(len*CHAR_BIT/5) + 1 chars)
|
|
|
|
**/
|
|
|
|
extern void base32(const size_t len, const u8* in, u8* out);
|
2004-06-01 19:34:12 +02:00
|
|
|
|
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
|
|
|
* partial regex implementation: see if string matches pattern.
|
|
|
|
*
|
|
|
|
* @param s input string
|
|
|
|
* @param w pseudo-regex to match against. case-insensitive;
|
|
|
|
* may contain '?' and/or '*' wildcards. if NULL, matches everything.
|
|
|
|
*
|
|
|
|
* @return 1 if they match, otherwise 0.
|
|
|
|
*
|
|
|
|
* algorithmfrom http://www.codeproject.com/string/wildcmp.asp.
|
|
|
|
**/
|
2004-11-23 21:52:03 +01:00
|
|
|
extern int match_wildcard(const char* s, const char* w);
|
2006-05-31 06:01:59 +02:00
|
|
|
/// unicode version of match_wildcard.
|
2005-06-28 06:12:50 +02:00
|
|
|
extern int match_wildcardw(const wchar_t* s, const wchar_t* w);
|
2004-03-03 00:56:51 +01:00
|
|
|
|
2006-01-23 08:59:20 +01:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
|
|
|
* calculate FNV1-A hash.
|
|
|
|
*
|
|
|
|
* @param buf input buffer.
|
|
|
|
* @param len if 0 (default), treat buf as a C-string; otherwise,
|
|
|
|
* indicates how many bytes of buffer to hash.
|
|
|
|
* @return hash result. note: results are distinct for buffers containing
|
|
|
|
* differing amounts of zero bytes because the hash value is seeded.
|
|
|
|
*
|
|
|
|
* rationale: this algorithm was chosen because it delivers 'good' results
|
|
|
|
* for string data and is relatively simple. other good alternatives exist;
|
|
|
|
* see Ozan Yigit's hash roundup.
|
|
|
|
**/
|
|
|
|
extern u32 fnv_hash(const void* buf, size_t len = 0);
|
|
|
|
/// 64-bit version of fnv_hash.
|
|
|
|
extern u64 fnv_hash64(const void* buf, size_t len = 0);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* special version of fnv_hash for strings: first converts to lowercase
|
|
|
|
* (useful for comparing mixed-case filenames)
|
|
|
|
**/
|
|
|
|
extern u32 fnv_lc_hash(const char* str, size_t len = 0);
|
2006-02-03 05:02:53 +01:00
|
|
|
|
2005-03-18 23:07:55 +01:00
|
|
|
#endif // #ifndef LIB_H__
|