/* NeoStats - IRC Statistical Services ** Copyright (c) 1999-2008 Adam Rutter, Justin Hammond, Mark Hetherington ** http://www.neostats.net/ ** ** Portions Copyright (c) 2000 - 2001 ^Enigma^ ** ** 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. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ** USA ** ** NeoStats CVS Identification ** $Id$ */ /* This file is Copyright 2007 Meyer Sound Laboratories Inc. See the included LICENSE.txt file for details. */ /****************************************************************************** / / File: MuscleSupport.h / / Description: Standard types, macros, etc, for MUSCLE. / Many of them are suspiciously BeOS-like. ;^) / *******************************************************************************/ #ifndef MuscleSupport_h #define MuscleSupport_h #define MUSCLE_VERSION_STRING "3.25b" #include /* for memcpy() */ /* Define this if the default FD_SETSIZE is too small for you (i.e. under Windows it's only 64) */ #if defined(MUSCLE_FD_SETSIZE) # if defined(FD_SETSIZE) # error "MuscleSupport.h: Can't redefine FD_SETSIZE, someone else has already defined it! You need to include MuscleSupport.h before including any other header files that define FD_SETSIZE." # else # define FD_SETSIZE MUSCLE_FD_SETSIZE # endif #endif /* If we are in an environment where known assembly is available, make a note of that fact */ #ifndef MUSCLE_AVOID_INLINE_ASSEMBLY # if defined(__GNUC__) # if defined(__i386__) # define MUSCLE_USE_X86_INLINE_ASSEMBLY 1 # elif defined(__PPC__) || defined(__POWERPC__) # define MUSCLE_USE_POWERPC_INLINE_ASSEMBLY 1 # endif # endif # if defined(_MSC_VER) && defined(_X86_) # define MUSCLE_USE_X86_INLINE_ASSEMBLY 1 # endif #endif #ifndef __cplusplus # define MUSCLE_AVOID_NAMESPACES # define NEW_H_NOT_AVAILABLE #endif /* Since certain antique compilers don't support namespaces, we * do all namespace-related declarations via macros which can * be no-op'd out by declaring -DMUSCLE_AVOID_NAMESPACES in the Makefile. */ #ifdef MUSCLE_AVOID_NAMESPACES # define DECLARE_NAMESPACE(x) # define BEGIN_NAMESPACE(x) # define END_NAMESPACE(x) # define USING_NAMESPACE(x) #else # define DECLARE_NAMESPACE(x) namespace x {}; # define BEGIN_NAMESPACE(x) namespace x { # define END_NAMESPACE(x) }; # define USING_NAMESPACE(x) using namespace x; #endif /* Just declare the muscle namespace as existing. * If we ever decide to make the muscle namespace a superset * of another namespace, we would add a 'using namespace' line here. */ DECLARE_NAMESPACE(muscle); /* these CPUs can't handle non-aligned word reads, so we'll accomodate them by using memcpy() instead. */ #if defined(MIPS) || defined(mc68000) || defined(sparc) || defined(__sparc) || defined(m68k) || defined(__68k__) || defined(__sparc__) # define MUSCLE_CPU_REQUIRES_DATA_ALIGNMENT #endif /* Borland C++ builder also runs under Win32, but it doesn't set this flag So we'd better set it ourselves. */ #if defined(__BORLANDC__) || defined(__WIN32__) || defined(_MSC_VER) # ifndef WIN32 # define WIN32 1 # endif #endif /* Win32 can't handle this stuff, it's too lame */ #ifdef WIN32 # define UNISTD_H_NOT_AVAILABLE # ifndef _MSC_VER /* 7/3/2006: Mika's patch allows VC++ to use newnothrow */ # define NEW_H_NOT_AVAILABLE # endif #endif #ifndef UNISTD_H_NOT_AVAILABLE # include #endif #ifndef NEW_H_NOT_AVAILABLE # include # ifndef MUSCLE_AVOID_NAMESPACES # ifndef __MWERKS__ using std::bad_alloc; using std::nothrow_t; using std::nothrow; # if (defined(_MSC_VER)) // VC++ 6.0 and earlier lack this definition # if (_MSC_VER <= 1200) inline void __cdecl operator delete(void *p, const std::nothrow_t&) _THROW0() {delete(p);} # endif # else using std::new_handler; using std::set_new_handler; # endif # endif # endif #else # define MUSCLE_AVOID_NEWNOTHROW #endif #ifndef newnothrow # ifdef MUSCLE_AVOID_NEWNOTHROW # define newnothrow new # else # define newnothrow new (nothrow) # endif #endif /* Unfortunately, the 64-bit printf() format specifier is different for different compilers :^P */ #if defined(__MWERKS__) || defined(WIN32) || defined(__BORLANDC__) || defined(__BEOS__) # if (_MSC_VER == 1200) # define INT64_FORMAT_SPEC "%I64i" # define UINT64_FORMAT_SPEC "%I64u" # else # define INT64_FORMAT_SPEC "%Li" # define UINT64_FORMAT_SPEC "%Lu" # endif #else # define INT64_FORMAT_SPEC "%lli" # define UINT64_FORMAT_SPEC "%llu" #endif #ifdef __BEOS__ # include # define MCRASH_IMPL debugger("muscle assertion failure") #elif defined(WIN32) # if defined(UNICODE) # define MCRASH_IMPL FatalAppExit(0, L"muscle assertion failure") # else # define MCRASH_IMPL FatalAppExit(0, "muscle assertion failure") # endif #else # define MCRASH_IMPL *((uint32*)NULL) = 0x666 #endif #ifdef MUSCLE_AVOID_ASSERTIONS # define MASSERT(x,msg) #else # define MASSERT(x,msg) {if(!(x)) MCRASH(msg)} #endif #ifdef MUSCLE_AVOID_NAMESPACES # define MCRASH(msg) {LogTime(MUSCLE_LOG_CRITICALERROR, "ASSERTION FAILED: (%s:%i) %s\n", __FILE__,__LINE__,msg); LogStackTrace(MUSCLE_LOG_CRITICALERROR); MCRASH_IMPL;} # define WARN_OUT_OF_MEMORY LogTime(MUSCLE_LOG_CRITICALERROR, "ERROR--OUT OF MEMORY! (%s:%i)\n",__FILE__,__LINE__) # define MCHECKPOINT LogTime(MUSCLE_LOG_WARNING, "Reached checkpoint at %s:%i\n", __FILE__, __LINE__) #else # define MCRASH(msg) {muscle::LogTime(muscle::MUSCLE_LOG_CRITICALERROR, "ASSERTION FAILED: (%s:%i) %s\n", __FILE__,__LINE__,msg); muscle::LogStackTrace(MUSCLE_LOG_CRITICALERROR); MCRASH_IMPL;} # define WARN_OUT_OF_MEMORY muscle::LogTime(muscle::MUSCLE_LOG_CRITICALERROR, "ERROR--OUT OF MEMORY! (%s:%i)\n",__FILE__,__LINE__) # define MCHECKPOINT muscle::LogTime(muscle::MUSCLE_LOG_WARNING, "Reached checkpoint at %s:%i\n", __FILE__, __LINE__) #endif #define UNLESS(x) if(!(x)) #define ARRAYITEMS(x) (sizeof(x)/sizeof(x[0])) /* returns # of items in array */ typedef void * muscleVoidPointer; /* it's a bit easier, syntax-wise, to use this type than (void *) directly in some cases. */ #ifdef __BEOS__ # include # include /* might as well use the real thing (and avoid complaints about duplication) */ # include # include # ifdef BONE # define closesocket close # else # define BEOS_OLD_NETSERVER # endif #else # define B_ERROR -1 # define B_NO_ERROR 0 # define B_OK B_NO_ERROR # ifndef WIN32 # define closesocket close # endif # ifdef __ATHEOS__ # include # else # ifndef MUSCLE_TYPES_PREDEFINED /* certain (ahem) projects already set these themselves... */ # define true 1 # define false 0 typedef signed char int8; typedef unsigned char uint8; typedef short int16; typedef unsigned short uint16; # if defined(__osf__) /* some 64bit systems will have long=64-bit, int=32-bit */ typedef int int32; typedef unsigned int uint32; # elif defined(__amd64__) /* some 64bit systems will have long=64-bit, int=32-bit */ typedef int int32; typedef unsigned int uint32; # else typedef long int32; typedef unsigned long uint32; # endif # if defined(WIN32) && !defined(__GNUWIN32__) typedef __int64 int64; typedef unsigned __int64 uint64; # else typedef long long int64; typedef unsigned long long uint64; # endif typedef unsigned char uchar; typedef unsigned short unichar; typedef int32 status_t; # endif /* !MUSCLE_TYPES_PREDEFINED */ # endif /* !__ATHEOS__*/ #endif /* __BEOS__*/ #define MAKETYPE(x) ((((unsigned long)(x[0])) << 24) | \ (((unsigned long)(x[1])) << 16) | \ (((unsigned long)(x[2])) << 8) | \ (((unsigned long)(x[3])) << 0)) #ifndef __BEOS__ /* Be-style message-field type codes. * I've calculated the integer equivalents for these codes * because gcc whines like a little girl about the four-byte * constants when compiling under Linux --jaf */ enum { B_ANY_TYPE = 1095653716, /* 'ANYT' = wild card */ B_BOOL_TYPE = 1112493900, /* 'BOOL' = boolean (1 byte per bool) */ B_DOUBLE_TYPE = 1145195589, /* 'DBLE' = double-precision float (8 bytes per double) */ B_FLOAT_TYPE = 1179406164, /* 'FLOT' = single-precision float (4 bytes per float) */ B_INT64_TYPE = 1280069191, /* 'LLNG' = long long integer (8 bytes per int) */ B_INT32_TYPE = 1280265799, /* 'LONG' = long integer (4 bytes per int) */ B_INT16_TYPE = 1397248596, /* 'SHRT' = short integer (2 bytes per int) */ B_INT8_TYPE = 1113150533, /* 'BYTE' = byte integer (1 byte per int) */ B_MESSAGE_TYPE = 1297303367, /* 'MSGG' = sub Message objects (reference counted) */ B_POINTER_TYPE = 1347310674, /* 'PNTR' = pointers (will not be flattened) */ B_POINT_TYPE = 1112559188, /* 'BPNT' = Point objects (each Point has two floats) */ B_RECT_TYPE = 1380270932, /* 'RECT' = Rect objects (each Rect has four floats) */ B_STRING_TYPE = 1129534546, /* 'CSTR' = String objects (variable length) */ B_OBJECT_TYPE = 1330664530, /* 'OPTR' = Flattened user objects (obsolete) */ B_RAW_TYPE = 1380013908, /* 'RAWT' = Raw data (variable number of bytes) */ B_MIME_TYPE = 1296649541 /* 'MIME' = MIME strings (obsolete) */ }; #endif /* This one isn't defined by BeOS, so we have to enumerate it separately. */ enum { B_TAG_TYPE = 1297367367 /* 'MTAG' = new for v2.00; for in-mem-only tags */ }; /* This constant is used in various places to mean 'as much as you want' */ #define MUSCLE_NO_LIMIT ((uint32)-1) #ifdef __cplusplus /** A handy little method to swap the bytes of any int-style datatype around */ template inline T muscleSwapBytes(T swapMe) { union {T _iWide; uint8 _i8[sizeof(T)];} u1, u2; u1._iWide = swapMe; int i = 0; int numBytes = sizeof(T); while(numBytes>0) u2._i8[i++] = u1._i8[--numBytes]; return u2._iWide; } /* This template safely copies a value in from an untyped byte buffer to a typed value. * (Make sure MUSCLE_CPU_REQUIRES_DATA_ALIGNMENT is defined if you are on a CPU * that doesn't like non-word-aligned data reads and writes) */ template inline void muscleCopyIn(T & dest, const void * source) { #ifdef MUSCLE_CPU_REQUIRES_DATA_ALIGNMENT memcpy(&dest, source, sizeof(dest)); #else dest = *((const T*)source); #endif } /** This template safely copies a value in from a typed value to an untyped byte buffer. * (Make sure MUSCLE_CPU_REQUIRES_DATA_ALIGNMENT is defined if you are on a CPU * that doesn't like non-word-aligned data reads and writes) */ template inline void muscleCopyOut(void * dest, const T & source) { #ifdef MUSCLE_CPU_REQUIRES_DATA_ALIGNMENT memcpy(dest, &source, sizeof(source)); #else *((T*)dest) = source; #endif } /** This macro should be used instead of "newnothrow T[count]". It works the * same, except that it hacks around an ugly bug in gcc 3.x where newnothrow * would return ((T*)0x4) on memory failure instead of NULL. * See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=10300 */ #if __GNUC__ == 3 template inline T * broken_gcc_newnothrow_array(size_t count) { T * ret = newnothrow T[count]; return (ret <= (T *)(sizeof(void *))) ? NULL : ret; } # define newnothrow_array(T, count) broken_gcc_newnothrow_array(count) #else # define newnothrow_array(T, count) newnothrow T[count] #endif /** Returns the smallest of the two arguments */ template inline const T & muscleMin(const T & p1, const T & p2) {return (p1 < p2) ? p1 : p2;} /** Returns the smallest of the three arguments */ template inline const T & muscleMin(const T & p1, const T & p2, const T & p3) {return muscleMin(p3, muscleMin(p1, p2));} /** Returns the smallest of the four arguments */ template inline const T & muscleMin(const T & p1, const T & p2, const T & p3, const T & p4) {return muscleMin(p3, p4, muscleMin(p1, p2));} /** Returns the smallest of the five arguments */ template inline const T & muscleMin(const T & p1, const T & p2, const T & p3, const T & p4, const T & p5) {return muscleMin(p3, p4, p5, muscleMin(p1, p2));} /** Returns the largest of the two arguments */ template inline const T & muscleMax(const T & p1, const T & p2) {return (p1 < p2) ? p2 : p1;} /** Returns the largest of the three arguments */ template inline const T & muscleMax(const T & p1, const T & p2, const T & p3) {return muscleMax(p3, muscleMax(p1, p2));} /** Returns the largest of the four arguments */ template inline const T & muscleMax(const T & p1, const T & p2, const T & p3, const T & p4) {return muscleMax(p3, p4, muscleMax(p1, p2));} /** Returns the largest of the five arguments */ template inline const T & muscleMax(const T & p1, const T & p2, const T & p3, const T & p4, const T & p5) {return muscleMax(p3, p4, p5, muscleMax(p1, p2));} /** Swaps the two arguments */ template inline void muscleSwap(T & p1, T & p2) {T t = p1; p1 = p2; p2 = t;} /** Returns the value nearest to (v) that is still in the range [lo, hi]. */ template inline const T & muscleClamp(const T & v, const T & lo, const T & hi) {return (v < lo) ? lo : ((v > hi) ? hi : v);} /** Returns true iff (v) is in the range [lo,hi]. */ template inline bool muscleInRange(const T & v, const T & lo, const T & hi) {return ((v >= lo)&&(v <= hi));} /** Returns -1 if arg1 is larger, or 1 if arg2 is larger, or 0 if they are equal. */ template inline int muscleCompare(const T & arg1, const T & arg2) {return (arg1>arg2) ? 1 : ((arg1 inline T muscleAbs(const T & arg) {return (arg<0)?(-arg):arg;} /** Rounds the given float to the nearest integer value. */ inline int muscleRintf(float f) {return (f>=0.0f) ? ((int)(f+0.5f)) : -((int)((-f)+0.5f));} /** Returns -1 if the value is less than zero, +1 if it is greater than zero, or 0 otherwise. */ template inline int muscleSgn(const T & arg) {return (arg<0)?-1:((arg>0)?1:0);} #endif /* __cplusplus */ #ifndef __BEOS__ /* * Copyright(c) 1983, 1989 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * from nameser.h 8.1 (Berkeley) 6/2/93 */ #ifndef BYTE_ORDER #if (BSD >= 199103) #include #else #ifdef linux #include #else #define LITTLE_ENDIAN 1234 /* least-significant byte first (vax, pc) */ #define BIG_ENDIAN 4321 /* most-significant byte first (IBM, net) */ #if defined(vax) || defined(ns32000) || defined(sun386) || defined(i386) || \ defined(__i386) || defined(__ia64) || \ defined(MIPSEL) || defined(_MIPSEL) || defined(BIT_ZERO_ON_RIGHT) || \ defined(__alpha__) || defined(__alpha) || defined(__CYGWIN__) || \ defined(_M_IX86) || defined(__GNUWIN32__) || defined(__LITTLEENDIAN__) || \ (defined(__Lynx__) && defined(__x86__)) #define BYTE_ORDER LITTLE_ENDIAN #endif #if defined(sel) || defined(pyr) || defined(mc68000) || defined(sparc) || \ defined(__sparc) || \ defined(is68k) || defined(tahoe) || defined(ibm032) || defined(ibm370) || \ defined(MIPSEB) || defined(_MIPSEB) || defined(_IBMR2) || defined(DGUX) ||\ defined(apollo) || defined(__convex__) || defined(_CRAY) || \ defined(__hppa) || defined(__hp9000) || \ defined(__hp9000s300) || defined(__hp9000s700) || \ defined(__hp3000s900) || defined(MPE) || \ defined(BIT_ZERO_ON_LEFT) || defined(m68k) || \ (defined(__Lynx__) && \ (defined(__68k__) || defined(__sparc__) || defined(__powerpc__))) #define BYTE_ORDER BIG_ENDIAN #endif #endif /* linux */ #endif /* BSD */ #endif /* BYTE_ORDER */ #if !defined(BYTE_ORDER) || (BYTE_ORDER != BIG_ENDIAN && BYTE_ORDER != LITTLE_ENDIAN) /* * you must determine what the correct bit order is for * your compiler - the next line is an intentional error * which will force your compiles to bomb until you fix * the above macros. */ # error "Undefined or invalid BYTE_ORDER -- you will need to modify MuscleSupport.h to correct this"; #endif /* End replacement code from Sun/University of California */ # if defined(MUSCLE_USE_POWERPC_INLINE_ASSEMBLY) static inline uint16 MusclePowerPCSwapInt16(uint16 val) { uint16 a; uint16 * addr = &a; __asm__ ("sthbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr)); return a; } static inline uint32 MusclePowerPCSwapInt32(uint32 val) { uint32 a; uint32 * addr = &a; __asm__ ("stwbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr)); return a; } static inline float MusclePowerPCSwapFloat(float val) { float a; float * addr = &a; __asm__ ("stwbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr)); return a; } static inline uint64 MusclePowerPCSwapInt64(uint64 val) { return ((uint64)(MusclePowerPCSwapInt32((uint32)((val>>32)&0xFFFFFFFF))))|(((uint64)(MusclePowerPCSwapInt32((uint32)(val&0xFFFFFFFF))))<<32); } static inline double MusclePowerPCSwapDouble(double val) { union { double _dv; uint64 _iv; } u; u._dv = val; u._iv = MusclePowerPCSwapInt64(u._iv); return u._dv; } # define B_SWAP_DOUBLE(arg) MusclePowerPCSwapDouble((double)(arg)) # define B_SWAP_FLOAT(arg) MusclePowerPCSwapFloat((float)(arg)) # define B_SWAP_INT64(arg) MusclePowerPCSwapInt64((uint64)(arg)) # define B_SWAP_INT32(arg) MusclePowerPCSwapInt32((uint32)(arg)) # define B_SWAP_INT16(arg) MusclePowerPCSwapInt16((uint16)(arg)) # elif defined(MUSCLE_USE_X86_INLINE_ASSEMBLY) static inline uint16 MuscleX86SwapInt16(uint16 val) { #ifdef _MSC_VER __asm { mov ax, val; xchg al, ah; mov val, ax; }; #else __asm__ ("xchgb %b0,%h0" : "=q" (val) : "0" (val)); #endif return val; } static inline uint32 MuscleX86SwapInt32(uint32 val) { #ifdef _MSC_VER __asm { mov eax, val; bswap eax; mov val, eax; }; #else __asm__ ("bswap %0" : "+r" (val)); #endif return val; } static inline float MuscleX86SwapFloat(float val) { #ifdef _MSC_VER __asm { mov eax, val; bswap eax; mov val, eax; }; #else __asm__ ("bswap %0" : "+r" (val)); #endif return val; } static inline uint64 MuscleX86SwapInt64(uint64 val) { #ifdef _MSC_VER __asm { mov eax, DWORD PTR val; mov edx, DWORD PTR val + 4; bswap eax; bswap edx; mov DWORD PTR val, edx; mov DWORD PTR val + 4, eax; }; return val; #else return ((uint64)(MuscleX86SwapInt32((uint32)((val>>32)&0xFFFFFFFF))))|(((uint64)(MuscleX86SwapInt32((uint32)(val&0xFFFFFFFF))))<<32); #endif } static inline double MuscleX86SwapDouble(double val) { #ifdef _MSC_VER __asm { mov eax, DWORD PTR val; mov edx, DWORD PTR val + 4; bswap eax; bswap edx; mov DWORD PTR val, edx; mov DWORD PTR val + 4, eax; }; return val; #else union { double _dv; uint64 _iv; } u; u._dv = val; u._iv = MuscleX86SwapInt64(u._iv); return u._dv; #endif } # define B_SWAP_DOUBLE(arg) MuscleX86SwapDouble((double)(arg)) # define B_SWAP_FLOAT(arg) MuscleX86SwapFloat((float)(arg)) # define B_SWAP_INT64(arg) MuscleX86SwapInt64((uint64)(arg)) # define B_SWAP_INT32(arg) MuscleX86SwapInt32((uint32)(arg)) # define B_SWAP_INT16(arg) MuscleX86SwapInt16((uint16)(arg)) # else // No assembly language available... so we'll use inline C # if defined(__cplusplus) # define MUSCLE_INLINE inline # else # define MUSCLE_INLINE static inline # endif MUSCLE_INLINE int64 B_SWAP_INT64(int64 arg) { union {int64 _i64; uint8 _i8[8];} u1, u2; u1._i64 = arg; u2._i8[0] = u1._i8[7]; u2._i8[1] = u1._i8[6]; u2._i8[2] = u1._i8[5]; u2._i8[3] = u1._i8[4]; u2._i8[4] = u1._i8[3]; u2._i8[5] = u1._i8[2]; u2._i8[6] = u1._i8[1]; u2._i8[7] = u1._i8[0]; return u2._i64; } MUSCLE_INLINE int32 B_SWAP_INT32(int32 arg) { union {int32 _i32; uint8 _i8[4];} u1, u2; u1._i32 = arg; u2._i8[0] = u1._i8[3]; u2._i8[1] = u1._i8[2]; u2._i8[2] = u1._i8[1]; u2._i8[3] = u1._i8[0]; return u2._i32; } MUSCLE_INLINE int16 B_SWAP_INT16(int16 arg) { union {int16 _i16; uint8 _i8[2];} u1, u2; u1._i16 = arg; u2._i8[0] = u1._i8[1]; u2._i8[1] = u1._i8[0]; return u2._i16; } MUSCLE_INLINE double B_SWAP_DOUBLE(double arg) { union {double _f64; uint8 _i8[8];} u1, u2; u1._f64 = arg; u2._i8[0] = u1._i8[7]; u2._i8[1] = u1._i8[6]; u2._i8[2] = u1._i8[5]; u2._i8[3] = u1._i8[4]; u2._i8[4] = u1._i8[3]; u2._i8[5] = u1._i8[2]; u2._i8[6] = u1._i8[1]; u2._i8[7] = u1._i8[0]; return u2._f64; } MUSCLE_INLINE float B_SWAP_FLOAT(float arg) { union {float _f32; uint8 _i8[4];} u1, u2; u1._f32 = arg; u2._i8[0] = u1._i8[3]; u2._i8[1] = u1._i8[2]; u2._i8[2] = u1._i8[1]; u2._i8[3] = u1._i8[0]; return u2._f32; } # endif # if BYTE_ORDER == LITTLE_ENDIAN # define B_HOST_IS_LENDIAN 1 # define B_HOST_IS_BENDIAN 0 # define B_HOST_TO_LENDIAN_DOUBLE(arg) ((double)(arg)) # define B_HOST_TO_LENDIAN_FLOAT(arg) ((float)(arg)) # define B_HOST_TO_LENDIAN_INT64(arg) ((uint64)(arg)) # define B_HOST_TO_LENDIAN_INT32(arg) ((uint32)(arg)) # define B_HOST_TO_LENDIAN_INT16(arg) ((uint16)(arg)) # define B_HOST_TO_BENDIAN_DOUBLE(arg) B_SWAP_DOUBLE(arg) # define B_HOST_TO_BENDIAN_FLOAT(arg) B_SWAP_FLOAT(arg) # define B_HOST_TO_BENDIAN_INT64(arg) B_SWAP_INT64(arg) # define B_HOST_TO_BENDIAN_INT32(arg) B_SWAP_INT32(arg) # define B_HOST_TO_BENDIAN_INT16(arg) B_SWAP_INT16(arg) # define B_LENDIAN_TO_HOST_DOUBLE(arg) ((double)(arg)) # define B_LENDIAN_TO_HOST_FLOAT(arg) ((float)(arg)) # define B_LENDIAN_TO_HOST_INT64(arg) ((uint64)(arg)) # define B_LENDIAN_TO_HOST_INT32(arg) ((uint32)(arg)) # define B_LENDIAN_TO_HOST_INT16(arg) ((uint16)(arg)) # define B_BENDIAN_TO_HOST_DOUBLE(arg) B_SWAP_DOUBLE(arg) # define B_BENDIAN_TO_HOST_FLOAT(arg) B_SWAP_FLOAT(arg) # define B_BENDIAN_TO_HOST_INT64(arg) B_SWAP_INT64(arg) # define B_BENDIAN_TO_HOST_INT32(arg) B_SWAP_INT32(arg) # define B_BENDIAN_TO_HOST_INT16(arg) B_SWAP_INT16(arg) # else /* LITTLE_ENDIAN */ # define B_HOST_IS_LENDIAN 0 # define B_HOST_IS_BENDIAN 1 # define B_HOST_TO_LENDIAN_DOUBLE(arg) B_SWAP_DOUBLE(arg) # define B_HOST_TO_LENDIAN_FLOAT(arg) B_SWAP_FLOAT(arg) # define B_HOST_TO_LENDIAN_INT64(arg) B_SWAP_INT64(arg) # define B_HOST_TO_LENDIAN_INT32(arg) B_SWAP_INT32(arg) # define B_HOST_TO_LENDIAN_INT16(arg) B_SWAP_INT16(arg) # define B_HOST_TO_BENDIAN_DOUBLE(arg) ((double)(arg)) # define B_HOST_TO_BENDIAN_FLOAT(arg) ((float)(arg)) # define B_HOST_TO_BENDIAN_INT64(arg) ((uint64)(arg)) # define B_HOST_TO_BENDIAN_INT32(arg) ((uint32)(arg)) # define B_HOST_TO_BENDIAN_INT16(arg) ((uint16)(arg)) # define B_LENDIAN_TO_HOST_DOUBLE(arg) B_SWAP_DOUBLE(arg) # define B_LENDIAN_TO_HOST_FLOAT(arg) B_SWAP_FLOAT(arg) # define B_LENDIAN_TO_HOST_INT64(arg) B_SWAP_INT64(arg) # define B_LENDIAN_TO_HOST_INT32(arg) B_SWAP_INT32(arg) # define B_LENDIAN_TO_HOST_INT16(arg) B_SWAP_INT16(arg) # define B_BENDIAN_TO_HOST_DOUBLE(arg) ((double)(arg)) # define B_BENDIAN_TO_HOST_FLOAT(arg) ((float)(arg)) # define B_BENDIAN_TO_HOST_INT64(arg) ((uint64)(arg)) # define B_BENDIAN_TO_HOST_INT32(arg) ((uint32)(arg)) # define B_BENDIAN_TO_HOST_INT16(arg) ((uint16)(arg)) # endif /* !LITTLE_ENDIAN */ #endif /* !__BEOS__ */ /* Macro to turn a type code into a string representation. * (typecode) is the type code to get the string for * (buf) is a (char *) to hold the output string; it must be >= 5 bytes long. */ #define MakePrettyTypeCodeString(typecode, buf) \ { \ uint32 __bigEndian = B_HOST_TO_BENDIAN_INT32(typecode); \ memcpy(buf, (const char *)&__bigEndian, sizeof(__bigEndian)); \ buf[sizeof(__bigEndian)] = '\0'; \ } #include #include #include /* for errno */ #ifdef WIN32 # include # include /* for WSAGetLastError() */ #endif #ifdef __cplusplus # include "syslog/SysLog.h" /* for LogTime() */ #endif /* __cplusplus */ /** Checks errno and returns true iff the last I/O operation * failed because it would have had to block otherwise. * NOTE: Returns int so that it will compile even in C environments where no bool type is defined. */ static inline int PreviousOperationWouldBlock() { #ifdef WIN32 return (WSAGetLastError() == WSAEWOULDBLOCK); #else return (errno == EWOULDBLOCK); #endif } /** Checks errno and returns true iff the last I/O operation * failed because it was interrupted by a signal or etc. * NOTE: Returns int so that it will compile even in C environments where no bool type is defined. */ static inline int PreviousOperationWasInterrupted() { #ifdef WIN32 return (WSAGetLastError() == WSAEINTR); #else return (errno == EINTR); #endif } /** This function applies semi-standard logic to convert the return value * of a system I/O call and (errno) into a proper MUSCLE-standard return value. * (A MUSCLE-standard return value's semantics are: Negative on error, * otherwise the return value is the number of bytes that were transferred) * @param origRet The return value of the original system call (e.g. to read()/write()/send()/recv()) * @param maxSize The maximum number of bytes that the system call was permitted to send during that call. * @param blocking True iff the socket/file descriptor is in blocking I/O mode. (Type is int for C compatibility -- it's really a boolean parameter) * @returns The system call's return value equivalent in MUSCLE return value semantics. */ static inline int32 ConvertReturnValueToMuscleSemantics(int origRet, uint32 maxSize, int blocking) { int32 retForBlocking = ((origRet > 0)||(maxSize == 0)) ? origRet : -1; return blocking ? retForBlocking : ((origRet<0)&&((PreviousOperationWouldBlock())||(PreviousOperationWasInterrupted()))) ? 0 : retForBlocking; } BEGIN_NAMESPACE(muscle); #if MUSCLE_TRACE_CHECKPOINTS > 0 /** Exposed as an implementation detail. Please ignore! */ extern volatile uint32 * _muscleTraceValues; /** Exposed as an implementation detail. Please ignore! */ extern uint32 _muscleNextTraceValueIndex; /** Sets the location of the trace-checkpoints array to store trace checkpoints into. * @param location A pointer to an array of at least (MUSCLE_TRACE_CHECKPOINTS) uint32s, or NULL. * If NULL (or if this function is never called), the default array will be used. */ void SetTraceValuesLocation(volatile uint32 * location); /** Set this process's current trace value to (v). This can be used as a primitive debugging tool, to determine * where this process was last seen executing -- useful for determining where the process is spinning at. * @note this function is a no-op if MUSCLE_TRACE_CHECKPOINTS is not defined to a value greater than zero. */ static inline void StoreTraceValue(uint32 v) { _muscleTraceValues[_muscleNextTraceValueIndex] = v; /* store the current value */ _muscleNextTraceValueIndex = (_muscleNextTraceValueIndex+1)%MUSCLE_TRACE_CHECKPOINTS; /* move the pointer */ _muscleTraceValues[_muscleNextTraceValueIndex] = ((uint32)-1); /* mark the next position with a special tag to show that it's next */ } /** Returns a pointer to the first value in the trace-values array. */ static inline const volatile uint32 * GetTraceValues() {return _muscleTraceValues;} /** A macro for automatically setting a trace checkpoint value based on current code location. * The value will be the two characters of the function or file name, left-shifted by 16 bits, * and then OR'd together with the current line number. This should give the debugging person a * fairly good clue as to where the checkpoint was located, while still being very cheap to implement. * * @note This function will be a no-op unless MUSCLE_TRACE_CHECKPOINTS is defined to be greater than zero. */ #if defined(__GNUC__) #define TCHECKPOINT \ { \ const char * d = __FUNCTION__; \ StoreTraceValue((d[0]<<24)|(d[1]<<16)|(__LINE__)); \ } #else #define TCHECKPOINT \ { \ const char * d = __FILE__; \ StoreTraceValue((d[0]<<24)|(d[1]<<16)|(__LINE__)); \ } #endif #else /* no-op implementations for when we aren't using the trace facility */ static inline void SetTraceValuesLocation(volatile uint32 * location) {(void) location;} /* named param is necessary for C compatibility */ static inline void StoreTraceValue(uint32 v) {(void) v;} /* named param is necessary for C compatibility */ #define TCHECKPOINT {/* empty */} #endif END_NAMESPACE(muscle); #endif /* _MUSCLE_SUPPORT_H */