2005-09-12 13:57:35 +00:00
/* NeoStats - IRC Statistical Services
2008-02-24 02:45:41 +00:00
* * Copyright ( c ) 1999 - 2008 Adam Rutter , Justin Hammond , Mark Hetherington
2005-09-12 13:57:35 +00:00
* * 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 $
*/
2007-01-06 05:03:38 +00:00
/* This file is Copyright 2007 Meyer Sound Laboratories Inc. See the included LICENSE.txt file for details. */
2005-09-12 13:57:35 +00:00
/******************************************************************************
/
/ File : MuscleSupport . h
/
/ Description : Standard types , macros , etc , for MUSCLE .
/ Many of them are suspiciously BeOS - like . ; ^ )
/
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# ifndef MuscleSupport_h
# define MuscleSupport_h
2007-01-06 05:03:38 +00:00
# define MUSCLE_VERSION_STRING "3.25b"
2007-01-03 09:35:09 +00:00
# include <string.h> /* for memcpy() */
2005-09-12 13:57:35 +00:00
/* 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 */
2007-01-06 05:03:38 +00:00
# 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_)
2005-09-12 13:57:35 +00:00
# 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. */
2007-01-03 09:35:09 +00:00
# if defined(__BORLANDC__) || defined(__WIN32__) || defined(_MSC_VER)
2005-09-12 13:57:35 +00:00
# ifndef WIN32
# define WIN32 1
# endif
# endif
2007-01-03 09:35:09 +00:00
/* Win32 can't handle this stuff, it's too lame */
2005-09-12 13:57:35 +00:00
# ifdef WIN32
# define UNISTD_H_NOT_AVAILABLE
2007-01-03 09:35:09 +00:00
# ifndef _MSC_VER /* 7/3/2006: Mika's patch allows VC++ to use newnothrow */
# define NEW_H_NOT_AVAILABLE
# endif
2005-09-12 13:57:35 +00:00
# endif
# ifndef UNISTD_H_NOT_AVAILABLE
# include <unistd.h>
# endif
# ifndef NEW_H_NOT_AVAILABLE
# include <new>
# ifndef MUSCLE_AVOID_NAMESPACES
# ifndef __MWERKS__
using std : : bad_alloc ;
using std : : nothrow_t ;
using std : : nothrow ;
2007-01-03 09:35:09 +00:00
# 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
2005-09-12 13:57:35 +00:00
using std : : new_handler ;
using std : : set_new_handler ;
2007-01-03 09:35:09 +00:00
# endif
2005-09-12 13:57:35 +00:00
# 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 <kernel / debugger.h>
# 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 <support / Errors.h>
# include <support / ByteOrder.h> /* might as well use the real thing (and avoid complaints about duplication) */
# include <support / SupportDefs.h>
# include <support / TypeConstants.h>
# 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 < / ainc / atheos / types.h>
# 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 < typename T > inline T muscleSwapBytes ( T swapMe )
{
2007-01-06 05:03:38 +00:00
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 ;
2005-09-12 13:57:35 +00:00
}
/* 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 < typename T > 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 < typename T > 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 < typename T > 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<T>(count)
# else
# define newnothrow_array(T, count) newnothrow T[count]
# endif
/** Returns the smallest of the two arguments */
template < typename T > inline const T & muscleMin ( const T & p1 , const T & p2 ) { return ( p1 < p2 ) ? p1 : p2 ; }
/** Returns the smallest of the three arguments */
template < typename T > 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 < typename T > 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 < typename T > 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 < typename T > inline const T & muscleMax ( const T & p1 , const T & p2 ) { return ( p1 < p2 ) ? p2 : p1 ; }
/** Returns the largest of the three arguments */
template < typename T > 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 < typename T > 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 < typename T > 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 < typename T > 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 < typename T > 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 < typename T > 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 < typename T > inline int muscleCompare ( const T & arg1 , const T & arg2 ) { return ( arg1 > arg2 ) ? 1 : ( ( arg1 < arg2 ) ? - 1 : 0 ) ; }
/** Returns the absolute value of (arg) */
template < typename T > 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 < typename T > 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 <machine/endian.h>
# else
# ifdef linux
# include <endian.h>
# 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) || \
2007-01-06 05:03:38 +00:00
defined ( __i386 ) | | defined ( __ia64 ) | | \
2005-09-12 13:57:35 +00:00
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 .
*/
2007-01-03 09:35:09 +00:00
# error "Undefined or invalid BYTE_ORDER -- you will need to modify MuscleSupport.h to correct this";
2005-09-12 13:57:35 +00:00
# endif
/* End replacement code from Sun/University of California */
2007-01-03 09:35:09 +00:00
2005-09-12 13:57:35 +00:00
# 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 )
{
2007-01-03 09:35:09 +00:00
union {
double _dv ;
uint64 _iv ;
} u ;
u . _dv = val ;
u . _iv = MusclePowerPCSwapInt64 ( u . _iv ) ;
return u . _dv ;
2005-09-12 13:57:35 +00:00
}
# 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
2007-01-03 09:35:09 +00:00
union {
double _dv ;
uint64 _iv ;
} u ;
u . _dv = val ;
u . _iv = MuscleX86SwapInt64 ( u . _iv ) ;
return u . _dv ;
2005-09-12 13:57:35 +00:00
# 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
2007-01-06 05:03:38 +00:00
// 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 ;
}
2005-09-12 13:57:35 +00:00
# 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 <stdio.h>
# include <stdlib.h>
# include <errno.h> /* for errno */
# ifdef WIN32
# include <windows.h>
# include <winsock.h> /* 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 */