// Copyright (c) 2003 Jan Wassenberg // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // 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. See the GNU // General Public License for more details. // // Contact info: // Jan.Wassenberg@stud.uni-karlsruhe.de // http://www.stud.uni-karlsruhe.de/~urkt/ #ifndef LIB_H #define LIB_H #include #include "config.h" #include "posix.h" #include "types.h" #include "sysdep/sysdep.h" #include "sdl.h" // for endian stuff // tell STL not to generate exceptions, if compiling without exceptions // (usually done for performance reasons). #ifdef CONFIG_DISABLE_EXCEPTIONS # ifdef _WIN32 # define _HAS_EXCEPTIONS 0 # else # define STL_NO_EXCEPTIONS # endif #endif #define STMT(STMT_code__) do { STMT_code__; } while(0) // must not be used before main entered! (i.e. not from NLS constructors / functions) #define ONCE(ONCE_code__)\ STMT(\ /* static pthread_mutex_t ONCE_mutex__ = PTHREAD_MUTEX_INITIALIZER;\ if(pthread_mutex_trylock(&ONCE_mutex__) == 0)\*/\ static bool ONCE_done__ = false;\ if(!ONCE_done__)\ {\ ONCE_done__ = true;\ ONCE_code__;\ }\ ) #ifdef _WIN32 #define CHECK_ERR(func)\ STMT(\ int err = (int)(func);\ if(err < 0)\ {\ assert(0 && "FYI: CHECK_ERR reports that a function failed."\ "feel free to ignore or suppress this warning.");\ return err;\ }\ ) #else #define CHECK_ERR(func)\ STMT(\ int err = (int)(func);\ if(err < 0)\ {\ debug_out("%s:%d: FYI: CHECK_ERR reports that a function failed."\ "feel free to ignore or suppress this warning.", __FILE__, __LINE__);\ return err;\ }\ ) #endif // useful because VC6 returns 0 on failure, instead of throwing. // causes calling function to return a negative error code on failure. #define SAFE_NEW(type, ptr)\ type* ptr;\ try\ {\ ptr = new type();\ }\ catch(std::bad_alloc)\ {\ ptr = 0;\ }\ if(!ptr)\ return ERR_NO_MEM; enum LibError { ERR_INVALID_HANDLE = -1000, ERR_NO_MEM = -1001, ERR_EOF = -1002, // attempted to read beyond EOF ERR_INVALID_PARAM = -1003, ERR_FILE_NOT_FOUND = -1004, ERR_PATH_NOT_FOUND = -1005, ERR_VFS_PATH_LENGTH = -1006, ERR_LAST }; #ifndef MIN #define MIN(a, b) (((a) < (b))? (a) : (b)) #endif #ifndef MAX #define MAX(a, b) (((a) > (b))? (a) : (b)) #endif #define UNUSED(param) (void)param; // // compile-time assert, especially useful for testing sizeof(). // no runtime overhead; may be used anywhere, including file scope. // // generate a symbol containing the line number of the macro invocation. // used to give a unique name (per file) to types made by cassert. // 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. #define MAKE_UID2__(l) LINE_ ## l #define MAKE_UID1__(l) MAKE_UID2__(l) #define UID__ MAKE_UID1__(__LINE__) // more descriptive error message, but may cause a struct redefinition // warning if used from the same line in different files. #define cassert(expr) struct UID__ { int CASSERT_FAILURE: (expr); }; // less helpful error message, but redefinition doesn't trigger warnings. #define cassert2(expr) extern char CASSERT_FAILURE[1][(expr)]; // note: alternative method in C++: specialize a struct only for true; // using it will raise 'incomplete type' errors if instantiated with false. #define debug_warn(str) assert(0 && (str)) // converts 4 character string to u32 for easy comparison // can't pass code as string, and use s[0]..s[3], because // VC6/7 don't realize the macro is constant // (it should be useable as a switch{} expression) #if SDL_BYTE_ORDER == SDL_BIG_ENDIAN #define FOURCC(a,b,c,d) ( ((u32)a << 24) | ((u32)b << 16) | \ ((u32)c << 8 ) | ((u32)d << 0 ) ) #else #define FOURCC(a,b,c,d) ( ((u32)a << 0 ) | ((u32)b << 8 ) | \ ((u32)c << 16) | ((u32)d << 24) ) #endif const size_t KB = 1ul << 10; const size_t MB = 1ul << 20; #ifdef _WIN32 #define DIR_SEP '\\' #else #define DIR_SEP '/' #endif #define BIT(n) (1ul << (n)) // call from main as early as possible. extern void lib_init(); enum CallConvention // number of parameters and convention { CC_CDECL_0, CC_CDECL_1, #ifdef _WIN32 CC_STDCALL_0, CC_STDCALL_1, #endif CC_UNUSED // get rid of trailing comma when !_WIN32 }; // more powerful atexit: registers an exit handler, with 0 or 1 parameters. // callable before libc initialized, and frees up the real atexit table. // stdcall convention is provided on Windows to call APIs (e.g. WSACleanup). // for these to be called at exit, lib_main must be invoked after _cinit. extern int atexit2(void* func, uintptr_t arg, CallConvention cc = CC_CDECL_1); // no parameters, cdecl (CC_CDECL_0) extern int atexit2(void* func); inline int atexit2(void (*func)()) { return atexit2((void *)func); } // FNV1-A hash - good for strings. // if len = 0 (default), treat buf as a C-string; // otherwise, hash bytes of buf. extern u32 fnv_hash(const void* buf, const size_t len = 0); extern u64 fnv_hash64(const void* buf, const size_t len); // hash (currently FNV) of a filename typedef u32 FnHash; #ifndef min inline int min(int a, int b) { return (a < b)? a : b; } inline int max(int a, int b) { return (a > b)? a : b; } #endif extern u16 addusw(u16 x, u16 y); extern u16 subusw(u16 x, u16 y); extern u16 read_le16(const void* p); extern u32 read_le32(const void* p); extern bool is_pow2(long n); // return -1 if not an integral power of 2, // otherwise the base2 logarithm extern int ilog2(const int n); extern uintptr_t round_up(uintptr_t val, uintptr_t multiple); extern u16 fp_to_u16(double in); // big endian! extern void base32(const int len, const u8* in, u8* out); #ifndef _WIN32 char *_itoa(int, char *, int radix); char *_ultoa(unsigned long int, char*, int radix); char *_ltoa(long, char *, int radix); #endif #endif // #ifndef LIB_H