Import all sources from perforce.

This commit is contained in:
castano
2007-04-17 08:49:19 +00:00
commit 7543dd1efa
197 changed files with 49819 additions and 0 deletions

168
src/nvcore/BitArray.h Normal file
View File

@ -0,0 +1,168 @@
// This code is in the public domain -- castanyo@yahoo.es
#ifndef NV_CORE_BITARRAY_H
#define NV_CORE_BITARRAY_H
#include <nvcore/nvcore.h>
#include <nvcore/Containers.h>
namespace nv
{
/// Count the bits of @a x.
inline uint bitsSet(uint8 x) {
uint count = 0;
for(; x != 0; x >>= 1) {
count += (x & 1);
}
return count;
}
/// Count the bits of @a x.
inline uint bitsSet(uint32 x, int bits) {
uint count = 0;
for(; x != 0 && bits != 0; x >>= 1, bits--) {
count += (x & 1);
}
return count;
}
/// Simple bit array.
class BitArray
{
public:
/// Default ctor.
BitArray() {}
/// Ctor with initial m_size.
BitArray(uint sz)
{
resize(sz);
}
/// Get array m_size.
uint size() const { return m_size; }
/// Clear array m_size.
void clear() { resize(0); }
/// Set array m_size.
void resize(uint sz)
{
m_size = sz;
m_bitArray.resize( (m_size + 7) >> 3 );
}
/// Get bit.
bool bitAt(uint b) const
{
nvDebugCheck( b < m_size );
return (m_bitArray[b >> 3] & (1 << (b & 7))) != 0;
}
/// Set a bit.
void setBitAt(uint b)
{
nvDebugCheck( b < m_size );
m_bitArray[b >> 3] |= (1 << (b & 7));
}
/// Clear a bit.
void clearBitAt( uint b )
{
nvDebugCheck( b < m_size );
m_bitArray[b >> 3] &= ~(1 << (b & 7));
}
/// Clear all the bits.
void clearAll()
{
memset(m_bitArray.unsecureBuffer(), 0, m_bitArray.size());
}
/// Set all the bits.
void setAll()
{
memset(m_bitArray.unsecureBuffer(), 0xFF, m_bitArray.size());
}
/// Toggle all the bits.
void toggleAll()
{
const uint byte_num = m_bitArray.size();
for(uint b = 0; b < byte_num; b++) {
m_bitArray[b] ^= 0xFF;
}
}
/// Get a byte of the bit array.
const uint8 & byteAt(uint index) const
{
return m_bitArray[index];
}
/// Set the given byte of the byte array.
void setByteAt(uint index, uint8 b)
{
m_bitArray[index] = b;
}
/// Count the number of bits set.
uint countSetBits() const
{
const uint num = m_bitArray.size();
if( num == 0 ) {
return 0;
}
uint count = 0;
for(uint i = 0; i < num - 1; i++) {
count += bitsSet(m_bitArray[i]);
}
count += bitsSet(m_bitArray[num-1], m_size & 0x7);
//piDebugCheck(count + countClearBits() == m_size);
return count;
}
/// Count the number of bits clear.
uint countClearBits() const {
const uint num = m_bitArray.size();
if( num == 0 ) {
return 0;
}
uint count = 0;
for(uint i = 0; i < num - 1; i++) {
count += bitsSet(~m_bitArray[i]);
}
count += bitsSet(~m_bitArray[num-1], m_size & 0x7);
//piDebugCheck(count + countSetBits() == m_size);
return count;
}
friend void swap(BitArray & a, BitArray & b)
{
swap(a.m_size, b.m_size);
swap(a.m_bitArray, b.m_bitArray);
}
private:
/// Number of bits stored.
uint m_size;
/// Array of bits.
Array<uint8> m_bitArray;
};
} // nv namespace
#endif // _PI_CORE_BITARRAY_H_

36
src/nvcore/CMakeLists.txt Normal file
View File

@ -0,0 +1,36 @@
PROJECT(nvcore)
ADD_SUBDIRECTORY(poshlib)
SET(CORE_SRCS
nvcore.h
BitArray.h
Memory.h
Memory.cpp
Debug.h
Debug.cpp
Containers.h
StrLib.h
StrLib.cpp
Stream.h
StdStream.h
TextReader.h
TextReader.cpp
TextWriter.h
Tokenizer.h
Tokenizer.cpp
Radix.h
Radix.cpp)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
# targets
ADD_DEFINITIONS(-DNVCORE_EXPORTS)
IF(NVCORE_SHARED)
ADD_LIBRARY(nvcore SHARED ${CORE_SRCS})
ELSE(NVCORE_SHARED)
ADD_LIBRARY(nvcore ${CORE_SRCS})
ENDIF(NVCORE_SHARED)
TARGET_LINK_LIBRARIES(nvcore ${LIBS})

1054
src/nvcore/Containers.h Normal file

File diff suppressed because it is too large Load Diff

456
src/nvcore/Debug.cpp Normal file
View File

@ -0,0 +1,456 @@
// This code is in the public domain -- castanyo@yahoo.es
#include <nvcore/Debug.h>
#include <nvcore/StrLib.h>
// Extern
#if NV_OS_WIN32 //&& NV_CC_MSVC
# define WIN32_LEAN_AND_MEAN
# define VC_EXTRALEAN
# include <windows.h>
# include <direct.h>
# if NV_CC_MSVC
# include <crtdbg.h>
# if _MSC_VER < 1300
# define DECLSPEC_DEPRECATED
// VC6: change this path to your Platform SDK headers
# include <dbghelp.h> // must be XP version of file
// include "M:\\dev7\\vs\\devtools\\common\\win32sdk\\include\\dbghelp.h"
# else
// VC7: ships with updated headers
# include <dbghelp.h>
# endif
# endif
#endif
#if !NV_OS_WIN32 && defined(HAVE_SIGNAL_H)
# include <signal.h>
#endif
#if NV_OS_LINUX && defined(HAVE_EXECINFO_H)
# include <execinfo.h>
# if NV_CC_GNUC // defined(HAVE_CXXABI_H)
# include <cxxabi.h>
# endif
#endif
#if NV_OS_DARWIN
# include <unistd.h> // getpid
# include <sys/types.h>
# include <sys/sysctl.h> // sysctl
#endif
#include <stdexcept> // std::runtime_error
#undef assert // defined on mingw
using namespace nv;
namespace
{
static MessageHandler * s_message_handler = NULL;
static AssertHandler * s_assert_handler = NULL;
static bool s_sig_handler_enabled = false;
#if NV_OS_WIN32 && NV_CC_MSVC
// Old exception filter.
static LPTOP_LEVEL_EXCEPTION_FILTER s_old_exception_filter = NULL;
#elif !NV_OS_WIN32 && defined(HAVE_SIGNAL_H)
// Old signal handlers.
struct sigaction s_old_sigsegv;
struct sigaction s_old_sigtrap;
struct sigaction s_old_sigfpe;
struct sigaction s_old_sigbus;
#endif
#if NV_OS_WIN32 && NV_CC_MSVC
// TODO write minidump
static LONG WINAPI nvTopLevelFilter( struct _EXCEPTION_POINTERS *pExceptionInfo ) {
/* BOOL (WINAPI * Dump) (HANDLE, DWORD, HANDLE, MINIDUMP_TYPE, PMINIDUMP_EXCEPTION_INFORMATION, PMINIDUMP_USER_STREAM_INFORMATION, PMINIDUMP_CALLBACK_INFORMATION );
AutoString dbghelp_path(512);
getcwd(dbghelp_path, 512);
dbghelp_path.Append("\\DbgHelp.dll");
nvTranslatePath(dbghelp_path);
PiLibrary DbgHelp_lib(dbghelp_path, true);
if( !DbgHelp_lib.IsValid() ) {
nvDebug("*** 'DbgHelp.dll' not found.\n");
return EXCEPTION_CONTINUE_SEARCH;
}
if( !DbgHelp_lib.BindSymbol( (void **)&Dump, "MiniDumpWriteDump" ) ) {
nvDebug("*** 'DbgHelp.dll' too old.\n");
return EXCEPTION_CONTINUE_SEARCH;
}
// create the file
HANDLE hFile = ::CreateFile( "nv.dmp", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if( hFile == INVALID_HANDLE_VALUE ) {
nvDebug("*** Failed to create dump file.\n");
return EXCEPTION_CONTINUE_SEARCH;
}
_MINIDUMP_EXCEPTION_INFORMATION ExInfo;
ExInfo.ThreadId = ::GetCurrentThreadId();
ExInfo.ExceptionPointers = pExceptionInfo;
ExInfo.ClientPointers = NULL;
// write the dump
bool ok = Dump( GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &ExInfo, NULL, NULL )!=0;
::CloseHandle(hFile);
if( !ok ) {
nvDebug("*** Failed to save dump file.\n");
return EXCEPTION_CONTINUE_SEARCH;
}
nvDebug("--- Dump file saved.\n");
*/
return EXCEPTION_CONTINUE_SEARCH;
}
#elif !NV_OS_WIN32 && defined(HAVE_SIGNAL_H) // NV_OS_LINUX || NV_OS_OSX
#if defined(HAVE_EXECINFO_H) // NV_OS_LINUX
static void nvPrintStackTrace(void * trace[], int size, int start=0) {
char ** string_array = backtrace_symbols(trace, size);
nvDebug( "\nDumping stacktrace:\n" );
for(int i = start; i < size-1; i++ ) {
# if NV_CC_GNUC // defined(HAVE_CXXABI_H)
char * begin = strchr(string_array[i], '(');
char * end = strchr(string_array[i], '+');
if( begin != 0 && begin < end ) {
int stat;
*end = '\0';
*begin = '\0';
char * module = string_array[i];
char * name = abi::__cxa_demangle(begin+1, 0, 0, &stat);
if( name == NULL || begin[1] != '_' || begin[2] != 'Z' ) {
nvDebug( " In: [%s] '%s'\n", module, begin+1 );
}
else {
nvDebug( " In: [%s] '%s'\n", module, name );
}
free(name);
}
else {
nvDebug( " In: '%s'\n", string_array[i] );
}
# else
nvDebug( " In: '%s'\n", string_array[i] );
# endif
}
nvDebug("\n");
free(string_array);
}
#endif // defined(HAVE_EXECINFO_H)
static void nvSigHandler(int sig, siginfo_t *info, void *secret)
{
// Do something useful with siginfo_t
if (sig == SIGSEGV) {
# if NV_CPU_X86
ucontext_t * uc = (ucontext_t *)secret;
nvDebug("Got signal %d, faulty address is %p, from %p\n", sig, info->si_addr, (void *)uc->uc_mcontext.gregs[REG_EIP]);
# else
nvDebug("Got signal %d, faulty address is %p\n", sig, info->si_addr);
# endif
}
else if(sig == SIGTRAP) {
nvDebug("Breakpoint hit.\n");
}
else {
nvDebug("Got signal %d\n", sig);
}
# if defined(HAVE_EXECINFO_H)
void * trace[64];
int size = backtrace(trace, 64);
# if NV_CPU_X86
// Overwrite sigaction with caller's address.
ucontext_t * uc = (ucontext_t *)secret;
trace[1] = (void *) uc->uc_mcontext.gregs[REG_EIP];
# endif // NV_CPU_X86
nvPrintStackTrace(trace, size, 1);
# endif // defined(HAVE_EXECINFO_H)
exit(0);
}
#endif // defined(HAVE_SIGNAL_H)
#if NV_OS_WIN32 //&& NV_CC_MSVC
/** Win32 asset handler. */
struct Win32AssertHandler : public AssertHandler
{
// Code from Daniel Vogel.
static bool isDebuggerPresent()
{
bool result = false;
HINSTANCE kern_lib = LoadLibraryEx( "kernel32.dll", NULL, 0 );
if( kern_lib ) {
FARPROC lIsDebuggerPresent = GetProcAddress( kern_lib, "IsDebuggerPresent" );
if( lIsDebuggerPresent && lIsDebuggerPresent() ) {
result = true;
}
FreeLibrary( kern_lib );
}
return result;
}
// Flush the message queue. This is necessary for the message box to show up.
static void flushMessageQueue()
{
MSG msg;
while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) {
if( msg.message == WM_QUIT ) break;
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
// Assert handler method.
virtual int assert( const char * exp, const char * file, int line, const char * func/*=NULL*/ )
{
int ret = NV_ABORT_EXIT;
StringBuilder error_string;
if( func != NULL ) {
error_string.format( "*** Assertion failed: %s\n On file: %s\n On function: %s\n On line: %d\n ", exp, file, func, line );
nvDebug( error_string );
}
else {
error_string.format( "*** Assertion failed: %s\n On file: %s\n On line: %d\n ", exp, file, line );
nvDebug( error_string );
}
#if _DEBUG
if( isDebuggerPresent() ) {
return NV_ABORT_DEBUG;
}
flushMessageQueue();
int action = MessageBox(NULL, error_string, "Assertion failed", MB_ABORTRETRYIGNORE|MB_ICONERROR);
switch( action ) {
case IDRETRY:
ret = NV_ABORT_DEBUG;
break;
case IDIGNORE:
ret = NV_ABORT_IGNORE;
break;
case IDABORT:
default:
ret = NV_ABORT_EXIT;
break;
}
/*if( _CrtDbgReport( _CRT_ASSERT, file, line, module, exp ) == 1 ) {
return NV_ABORT_DEBUG;
}*/
#endif
if( ret == NV_ABORT_EXIT ) {
// Exit cleanly.
throw std::runtime_error("Assertion failed");
}
return ret;
}
};
#else
/** Unix asset handler. */
struct UnixAssertHandler : public AssertHandler
{
bool isDebuggerPresent()
{
# if NV_OS_DARWIN
int mib[4];
struct kinfo_proc info;
size_t size;
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PID;
mib[3] = getpid();
size = sizeof(info);
info.kp_proc.p_flag = 0;
sysctl(mib,4,&info,&size,NULL,0);
return ((info.kp_proc.p_flag & P_TRACED) == P_TRACED);
# else
// if ppid != sid, some process spawned our app, probably a debugger.
return getsid(getpid()) != getppid();
# endif
}
// Assert handler method.
virtual int assert(const char * exp, const char * file, int line, const char * func)
{
if( func != NULL ) {
nvDebug( "*** Assertion failed: %s\n On file: %s\n On function: %s\n On line: %d\n ", exp, file, func, line );
}
else {
nvDebug( "*** Assertion failed: %s\n On file: %s\n On line: %d\n ", exp, file, line );
}
# if _DEBUG
if( isDebuggerPresent() ) {
return NV_ABORT_DEBUG;
}
# endif
# if defined(HAVE_EXECINFO_H)
void * trace[64];
int size = backtrace(trace, 64);
nvPrintStackTrace(trace, size, 3);
# endif
// Exit cleanly.
throw std::runtime_error("Assertion failed");
}
};
#endif
} // namespace
/// Handle assertion through the asset handler.
int nvAbort(const char * exp, const char * file, int line, const char * func)
{
#if NV_OS_WIN32 //&& NV_CC_MSVC
static Win32AssertHandler s_default_assert_handler;
#else
static UnixAssertHandler s_default_assert_handler;
#endif
if( s_assert_handler != NULL ) {
return s_assert_handler->assert( exp, file, line, func );
}
else {
return s_default_assert_handler.assert( exp, file, line, func );
}
}
/// Shows a message through the message handler.
void NV_CDECL nvDebug(const char *msg, ...)
{
va_list arg;
va_start(arg,msg);
if( s_message_handler != NULL ) {
s_message_handler->log( msg, arg );
}
va_end(arg);
}
/// Dump debug info.
void debug::dumpInfo()
{
#if defined(HAVE_EXECINFO_H)
void * trace[64];
int size = backtrace(trace, 64);
nvPrintStackTrace(trace, size, 1);
#endif
}
/// Set the debug message handler.
void debug::setMessageHandler(MessageHandler * message_handler)
{
s_message_handler = message_handler;
}
/// Reset the debug message handler.
void debug::resetMessageHandler()
{
s_message_handler = NULL;
}
/// Set the assert handler.
void debug::setAssertHandler(AssertHandler * assert_handler)
{
s_assert_handler = assert_handler;
}
/// Reset the assert handler.
void debug::resetAssertHandler()
{
s_assert_handler = NULL;
}
/// Enable signal handler.
void debug::enableSigHandler()
{
nvCheck(s_sig_handler_enabled != true);
s_sig_handler_enabled = true;
#if NV_OS_WIN32 && NV_CC_MSVC
s_old_exception_filter = ::SetUnhandledExceptionFilter( nvTopLevelFilter );
#elif !NV_OS_WIN32 && defined(HAVE_SIGNAL_H)
// Install our signal handler
struct sigaction sa;
sa.sa_sigaction = nvSigHandler;
sigemptyset (&sa.sa_mask);
sa.sa_flags = SA_RESTART | SA_SIGINFO;
sigaction(SIGSEGV, &sa, &s_old_sigsegv);
sigaction(SIGTRAP, &sa, &s_old_sigtrap);
sigaction(SIGFPE, &sa, &s_old_sigfpe);
sigaction(SIGBUS, &sa, &s_old_sigbus);
#endif
}
/// Disable signal handler.
void debug::disableSigHandler()
{
nvCheck(s_sig_handler_enabled == true);
s_sig_handler_enabled = false;
#if NV_OS_WIN32 && NV_CC_MSVC
::SetUnhandledExceptionFilter( s_old_exception_filter );
s_old_exception_filter = NULL;
#elif !NV_OS_WIN32 && defined(HAVE_SIGNAL_H)
sigaction(SIGSEGV, &s_old_sigsegv, NULL);
sigaction(SIGTRAP, &s_old_sigtrap, NULL);
sigaction(SIGFPE, &s_old_sigfpe, NULL);
sigaction(SIGBUS, &s_old_sigbus, NULL);
#endif
}

129
src/nvcore/Debug.h Normal file
View File

@ -0,0 +1,129 @@
// This code is in the public domain -- castanyo@yahoo.es
#ifndef NV_CORE_DEBUG_H
#define NV_CORE_DEBUG_H
#include <nvcore/nvcore.h>
#if defined(HAVE_STDARG_H)
# include <stdarg.h> // va_list
#endif
#define NV_ABORT_DEBUG 1
#define NV_ABORT_IGNORE 2
#define NV_ABORT_EXIT 3
#if NV_CC_MSVC
#define nvNoAssert __noop
#else
#define nvNoAssert(exp)
#endif
#if NV_NO_ASSERT
# define nvAssert(exp) nvNoAssert()
# define nvCheck(exp) nvNoAssert()
# define nvDebugAssert(exp) nvNoAssert()
# define nvDebugCheck(exp) nvNoAssert()
# define nvDebugBreak()
#else // NV_NO_ASSERT
# if NV_CC_MSVC && NV_CPU_X86 && 0
# define nvDebugBreak() __asm int 3
# elif NV_CC_MSVC // this is only on recent versions...
// Do I have to include <intrin.h> ?
# define nvDebugBreak() __debugbreak()
# elif NV_CC_GNUC && NV_CPU_PPC && NV_OS_DARWIN
# define nvDebugBreak() __asm__ volatile ("trap");
# elif NV_CC_GNUC && NV_CPU_X86 && NV_OS_DARWIN
# define nvDebugBreak() __asm__ volatile ("int3");
# elif NV_CC_GNUC && NV_CPU_X86
# define nvDebugBreak() __asm__ ( "int %0" : :"I"(3) )
# else
# include <signal.h>
# define nvDebugBreak() raise(SIGTRAP); //*((int *)(0)) = 0
# endif
# define nvAssertMacro(exp) \
do { \
if(!(exp)) { \
if( nvAbort(#exp, __FILE__, __LINE__, __FUNC__) == NV_ABORT_DEBUG ) { \
nvDebugBreak(); \
} \
} \
} while(false)
# define nvAssert(exp) nvAssertMacro(exp)
# define nvCheck(exp) nvAssertMacro(exp)
# if defined(_DEBUG)
# define nvDebugAssert(exp) nvAssertMacro(exp)
# define nvDebugCheck(exp) nvAssertMacro(exp)
# else // _DEBUG
# define nvDebugAssert(exp) nvNoAssert(exp)
# define nvDebugCheck(exp) nvNoAssert(exp)
# endif // _DEBUG
#endif // NV_NO_ASSERT
// Use nvAssume for very simple expresions only: piAssume(0), piAssume(value == true), etc.
#if defined(_DEBUG)
# if NV_CC_MSVC
# define nvAssume(exp) __assume(exp)
# else
# define nvAssume(exp) nvCheck(exp)
# endif
#else
# define nvAssume(exp) nvCheck(exp)
#endif
#define nvError(x) nvAbort(x, __FILE__, __LINE__, __FUNC__)
#define nvWarning(x) nvDebug("*** Warning %s/%d: %s\n", __FILE__, __LINE__, (x))
#if PI_CC_MSVC
// I'm not sure it's a good idea to use the default static assert.
#define nvStaticCheck(x) _STATIC_ASSERT(x)
#else
#define nvStaticCheck(x) typedef char NV_DO_STRING_JOIN2(__static_assert_,__LINE__)[(x)]
//#define nvStaticCheck(x) switch(0) { case 0: case x:; }
#endif
NVCORE_API int nvAbort(const char *exp, const char *file, int line, const char * func = 0);
NVCORE_API void NV_CDECL nvDebug( const char *msg, ... ) __attribute__((format (printf, 1, 2)));
namespace nv
{
/** Message handler interface. */
struct MessageHandler {
virtual void log(const char * str, va_list arg) = 0;
virtual ~MessageHandler() {}
};
/** Assert handler interface. */
struct AssertHandler {
virtual int assert(const char *exp, const char *file, int line, const char *func = 0) = 0;
virtual ~AssertHandler() {}
};
namespace debug
{
NVCORE_API void dumpInfo();
NVCORE_API void setMessageHandler( MessageHandler * messageHandler );
NVCORE_API void resetMessageHandler();
NVCORE_API void setAssertHandler( AssertHandler * assertHanlder );
NVCORE_API void resetAssertHandler();
NVCORE_API void enableSigHandler();
NVCORE_API void disableSigHandler();
}
} // nv namespace
#endif // NV_CORE_DEBUG_H

View File

@ -0,0 +1,66 @@
#ifndef NV_CORE_H
#error "Do not include this file directly."
#endif
#include <stdlib.h> // uint8_t, int8_t, ...
// Function linkage
#define DLL_IMPORT
#if __GNUC__ >= 4
# define DLL_EXPORT __attribute__((visibility("default")))
# define DLL_EXPORT_CLASS DLL_EXPORT
#else
# define DLL_EXPORT
# define DLL_EXPORT_CLASS
#endif
// Function calling modes
#if NV_CPU_X86
# define NV_CDECL __attribute__((cdecl))
# define NV_STDCALL __attribute__((stdcall))
#else
# define NV_CDECL
# define NV_STDCALL
#endif
#define NV_FASTCALL __attribute__((fastcall))
#define NV_FORCEINLINE __attribute__((always_inline))
#if __GNUC__ > 2
#define NV_PURE __attribute__((pure))
#define NV_CONST __attribute__((const))
#else
#define NV_PURE
#define NV_CONST
#endif
// Define __FUNC__ properly.
#if __STDC_VERSION__ < 199901L
# if __GNUC__ >= 2
# define __FUNC__ __PRETTY_FUNCTION__ // __FUNCTION__
# else
# define __FUNC__ "<unknown>"
# endif
#else
# define __FUNC__ __PRETTY_FUNCTION__
#endif
#define restrict __restrict__
// Type definitions
typedef uint8_t uint8;
typedef int8_t int8;
typedef uint16_t uint16;
typedef int16_t int16;
typedef uint32_t uint32;
typedef int32_t int32;
typedef uint64_t uint64;
typedef int64_t int64;
// Aliases
typedef uint32 uint;

View File

@ -0,0 +1,63 @@
#ifndef NV_CORE_H
#error "Do not include this file directly."
#endif
// Function linkage
#define DLL_IMPORT
#if __GNUC__ >= 4
# define DLL_EXPORT __attribute__((visibility("default")))
# define DLL_EXPORT_CLASS DLL_EXPORT
#else
# define DLL_EXPORT
# define DLL_EXPORT_CLASS
#endif
// Function calling modes
#if NV_CPU_X86
# define NV_CDECL __attribute__((cdecl))
# define NV_STDCALL __attribute__((stdcall))
#else
# define NV_CDECL
# define NV_STDCALL
#endif
#define NV_FASTCALL __attribute__((fastcall))
#define NV_FORCEINLINE __attribute__((always_inline))
#if __GNUC__ > 2
#define NV_PURE __attribute__((pure))
#define NV_CONST __attribute__((const))
#else
#define NV_PURE
#define NV_CONST
#endif
// Define __FUNC__ properly.
#if __STDC_VERSION__ < 199901L
# if __GNUC__ >= 2
# define __FUNC__ __PRETTY_FUNCTION__ // __FUNCTION__
# else
# define __FUNC__ "<unknown>"
# endif
#else
# define __FUNC__ __PRETTY_FUNCTION__
#endif
#define restrict __restrict__
// Type definitions
typedef unsigned char uint8;
typedef signed char int8;
typedef unsigned short uint16;
typedef signed short int16;
typedef unsigned int uint32;
typedef signed int int32;
typedef unsigned long long uint64;
typedef signed long long int64;
// Aliases
typedef uint32 uint;

View File

@ -0,0 +1,58 @@
#ifndef NV_CORE_H
#error "Do not include this file directly."
#endif
// Function linkage
#define DLL_IMPORT __declspec(dllimport)
#define DLL_EXPORT __declspec(dllexport)
#define DLL_EXPORT_CLASS DLL_EXPORT
// Function calling modes
#if NV_CPU_X86
# define NV_CDECL __attribute__((cdecl))
# define NV_STDCALL __attribute__((stdcall))
#else
# define NV_CDECL
# define NV_STDCALL
#endif
#define NV_FASTCALL __attribute__((fastcall))
#define NV_FORCEINLINE __attribute__((always_inline))
#if __GNUC__ > 2
#define NV_PURE __attribute__((pure))
#define NV_CONST __attribute__((const))
#else
#define NV_PURE
#define NV_CONST
#endif
// Define __FUNC__ properly.
#if __STDC_VERSION__ < 199901L
# if __GNUC__ >= 2
# define __FUNC__ __PRETTY_FUNCTION__ // __FUNCTION__
# else
# define __FUNC__ "<unknown>"
# endif
#else
# define __FUNC__ __PRETTY_FUNCTION__
#endif
#define restrict __restrict__
// Type definitions
typedef unsigned char uint8;
typedef signed char int8;
typedef unsigned short uint16;
typedef signed short int16;
typedef unsigned int uint32;
typedef signed int int32;
typedef unsigned long long uint64;
typedef signed long long int64;
// Aliases
typedef uint32 uint;

94
src/nvcore/DefsVcWin32.h Normal file
View File

@ -0,0 +1,94 @@
#ifndef NV_CORE_H
#error "Do not include this file directly."
#endif
// Function linkage
#define DLL_IMPORT __declspec(dllimport)
#define DLL_EXPORT __declspec(dllexport)
#define DLL_EXPORT_CLASS DLL_EXPORT
// Function calling modes
#define NV_CDECL __cdecl
#define NV_STDCALL __stdcall
#define NV_FASTCALL __fastcall
#define NV_FORCEINLINE __forceinline
#define NV_PURE
#define NV_CONST
// Set standard function names.
#define snprintf _snprintf
#define vsnprintf _vsnprintf
#define vsscanf _vsscanf
#define chdir _chdir
#define getcwd _getcwd
#define va_copy(a, b) a = b
#if !defined restrict
#define restrict
#endif
#if !defined __attribute__
#define __attribute__(X)
#endif
#if !defined __FUNC__
#define __FUNC__ __FUNCTION__
#endif
// Type definitions
typedef unsigned char uint8;
typedef signed char int8;
typedef unsigned short uint16;
typedef signed short int16;
typedef unsigned int uint32;
typedef signed int int32;
typedef unsigned __int64 uint64;
typedef signed __int64 int64;
// Aliases
typedef uint32 uint;
// Unwanted VC++ warnings to disable.
#pragma warning(disable : 4244) // conversion to float, possible loss of data
#pragma warning(disable : 4245) // conversion from 'enum ' to 'unsigned long', signed/unsigned mismatch
#pragma warning(disable : 4100) // unreferenced formal parameter
#pragma warning(disable : 4514) // unreferenced inline function has been removed
#pragma warning(disable : 4710) // inline function not expanded
#pragma warning(disable : 4127) // Conditional expression is constant
#pragma warning(disable : 4305) // truncation from 'const double' to 'float'
#pragma warning(disable : 4505) // unreferenced local function has been removed
//#pragma warning(disable : 4699) // creating precompiled header
//#pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union
#pragma warning(disable : 4702) // unreachable code in inline expanded function
#pragma warning(disable : 4711) // function selected for automatic inlining
#pragma warning(disable : 4725) // Pentium fdiv bug
//#pragma warning(disable : 4512) // assignment operator could not be generated
//#pragma warning(disable : 4530) // C++ exception handler used, but unwind semantics are not enabled
//#pragma warning(disable : 4238) // nonstandard extension used : class rvalue used as lvalue
//#pragma warning(disable : 4251) // needs to have dll-interface to be used by clients of class 'ULinker'
//#pragma warning(disable : 4275) // non dll-interface class used as base for dll-interface class
//#pragma warning(disable : 4511) // copy constructor could not be generated
//#pragma warning(disable : 4284) // return type is not a UDT or reference to a UDT
//#pragma warning(disable : 4355) // this used in base initializer list
//#pragma warning(disable : 4097) // typedef-name '' used as synonym for class-name ''
//#pragma warning(disable : 4291) // typedef-name '' used as synonym for class-name ''
#pragma warning(disable : 4345) // behavior change: an object of POD type constructed with an initializer of the form () will be default-initialized
#pragma warning(disable : 4786) // Identifier was truncated and cannot be debugged.
//#pragma warning(disable : 4996) // function was declared deprecated.
//#pragma warning(disable : 4146) // unary minus operator applied to unsigned type, result still unsigned
#pragma warning(disable : 4675) // resolved overload was found by argument-dependent lookup

34
src/nvcore/Memory.cpp Normal file
View File

@ -0,0 +1,34 @@
#include "Memory.h"
#include "Debug.h"
//#if HAVE_MALLOC_H
//#include <malloc.h>
//#endif
#include <stdlib.h>
using namespace nv;
void * nv::mem::malloc(size_t size)
{
return ::malloc(size);
}
void * nv::mem::malloc(size_t size, const char * file, int line)
{
return ::malloc(size);
}
void nv::mem::free(const void * ptr)
{
::free(const_cast<void *>(ptr));
}
void * nv::mem::realloc(void * ptr, size_t size)
{
nvDebugCheck(ptr != NULL || size != 0); // undefined realloc behavior.
return ::realloc(ptr, size);
}

186
src/nvcore/Memory.h Normal file
View File

@ -0,0 +1,186 @@
// This code is in the public domain -- castanyo@yahoo.es
#ifndef NV_CORE_MEMORY_H
#define NV_CORE_MEMORY_H
#include <nvcore/nvcore.h>
#include <stdlib.h> // malloc(), realloc() and free()
#include <stddef.h> // size_t
#include <new> // new and delete
// Custom memory allocator
namespace nv
{
namespace mem
{
NVCORE_API void * malloc(size_t size);
NVCORE_API void * malloc(size_t size, const char * file, int line);
NVCORE_API void free(const void * ptr);
NVCORE_API void * realloc(void * ptr, size_t size);
} // mem namespace
} // nv namespace
// Override new/delete
inline void * operator new (size_t size) throw()
{
return nv::mem::malloc(size);
}
inline void operator delete (void *p) throw()
{
nv::mem::free(p);
}
inline void * operator new [] (size_t size) throw()
{
return nv::mem::malloc(size);
}
inline void operator delete [] (void * p) throw()
{
nv::mem::free(p);
}
/*
#ifdef _DEBUG
#define new new(__FILE__, __LINE__)
#define malloc(i) malloc(i, __FILE__, __LINE__)
#endif
*/
#if 0
/*
File: main.cpp
Version: 1.0
Abstract: Overrides the C++ 'operator new' and 'operator delete'.
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
("Apple") in consideration of your agreement to the following terms, and your
use, installation, modification or redistribution of this Apple software
constitutes acceptance of these terms. If you do not agree with these terms,
please do not use, install, modify or redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and subject
to these terms, Apple grants you a personal, non-exclusive license, under Apples
copyrights in this original Apple software (the "Apple Software"), to use,
reproduce, modify and redistribute the Apple Software, with or without
modifications, in source and/or binary forms; provided that if you redistribute
the Apple Software in its entirety and without modifications, you must retain
this notice and the following text and disclaimers in all such redistributions of
the Apple Software. Neither the name, trademarks, service marks or logos of
Apple Computer, Inc. may be used to endorse or promote products derived from the
Apple Software without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or implied,
are granted by Apple herein, including but not limited to any patent rights that
may be infringed by your derivative works or by other works in which the Apple
Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Copyright © 2006 Apple Computer, Inc., All Rights Reserved
*/
/* This sample shows how to override the C++ global 'new' and 'delete' operators. */
#include <new>
#include <iostream>
#include <cstdlib>
#include <stdexcept>
#include <locale>
/* Some variables and code to make the example do something. */
namespace {
unsigned long long gNewCounter; // number of times 'new' was called
unsigned long long gDeleteCounter; // number of times 'delete' was called
void printCounters() // print the counters above
{
std::cout << "new was called " << gNewCounter << " times and delete was called " << gDeleteCounter << " times\n";
}
}
/* These are the overridden new and delete routines.
Most applications will want to override at least these four versions of new/delete if they override any of them.
In Mac OS, it's not necessary to override the array versions of operator new and delete if all
they would do is call the non-array versions; the C++ standard library, as an extension
to the C++ standard, does this for you.
Developers should consult the section [lib.support.dynamic] in the C++ standard to see the requirements
on the generic operators new and delete; the system may expect that your overridden operators meet all these
requirements.
Your operators may be called by the system, even early in start-up before constructors have been executed. */
void* operator new(std::size_t sz) throw (std::bad_alloc)
{
void *result = std::malloc (sz == 0 ? 1 : sz);
if (result == NULL)
throw std::bad_alloc();
gNewCounter++;
return result;
}
void operator delete(void* p) throw()
{
if (p == NULL)
return;
std::free (p);
gDeleteCounter++;
}
/* These are the 'nothrow' versions of the above operators.
The system version will try to call a std::new_handler if they
fail, but your overriding versions are not required to do this. */
void* operator new(std::size_t sz, const std::nothrow_t&) throw()
{
try {
void * result = ::operator new (sz); // calls our overridden operator new
return result;
} catch (std::bad_alloc &) {
return NULL;
}
}
void operator delete(void* p, const std::nothrow_t&) throw()
{
::operator delete (p);
}
/* Bug 4067110 is that if your program has no weak symbols at all, the linker will not set the
WEAK_DEFINES bit in the Mach-O header and as a result the new and delete operators above won't
be seen by system libraries. This is mostly a problem for test programs and small examples,
since almost all real C++ programs complicated enough to override new and delete will have at
least one weak symbol. However, this is a small example, so: */
void __attribute__((weak, visibility("default"))) workaroundFor4067110 () { }
/* This is a simple test program that causes the runtime library to call new and delete. */
int main()
{
atexit (printCounters);
try {
std::locale example("does_not_exist");
} catch (std::runtime_error &x) {
}
return 0;
}
#endif // 0
#endif // NV_CORE_MEMORY_H

24
src/nvcore/Prefetch.h Normal file
View File

@ -0,0 +1,24 @@
// nvPrefetch
#if NV_CC_GNUC
#define nvPrefetch(ptr) __builtin_prefetch(ptr)
#elif NV_CC_MSVC
#if NV_CPU_X86
__forceinline void nvPrefetch(const void * mem)
{
__asm mov ecx, mem
__asm prefetcht0 [ecx];
// __asm prefetchnta [ecx];
}
#endif // NV_CPU_X86
#else // NV_CC_MSVC
// do nothing in other case.
#define piPrefetch(ptr)
#endif // NV_CC_MSVC

420
src/nvcore/Ptr.h Normal file
View File

@ -0,0 +1,420 @@
// This code is in the public domain -- castanyo@yahoo.es
#ifndef NV_CORE_PTR_H
#define NV_CORE_PTR_H
#include <nvcore/nvcore.h>
#include <nvcore/Debug.h>
#include <stdio.h> // NULL
namespace nv
{
/** Simple auto pointer template class.
*
* This is very similar to the standard auto_ptr class, but with some
* additional limitations to make its use less error prone:
* - Copy constructor and assignment operator are disabled.
* - reset method is removed.
*
* The semantics of the standard auto_ptr are not clear and change depending
* on the std implementation. For a discussion of the problems of auto_ptr read:
* http://www.awprofessional.com/content/images/020163371X/autoptrupdate\auto_ptr_update.html
*/
template <class T>
class AutoPtr
{
NV_FORBID_COPY(AutoPtr);
NV_FORBID_HEAPALLOC();
public:
/** Ctor. */
explicit AutoPtr( T * p ) {
m_ptr = p;
}
/** Dtor. Deletes owned pointer. */
~AutoPtr() {
delete m_ptr;
m_ptr = NULL;
}
/** Delete owned pointer and assign new one. */
void operator=( T * p ) {
delete m_ptr;
m_ptr = p;
}
/** Member access. */
T * operator -> () const {
nvDebugCheck(m_ptr != NULL);
return m_ptr;
}
/** Get reference. */
T & operator*() const {
nvDebugCheck(m_ptr != NULL);
return *m_ptr;
}
/** Get pointer. */
T * ptr() const { return m_ptr; }
/** Relinquish ownership of the underlying pointer and returns that pointer. */
T * release() {
T * tmp = m_ptr;
m_ptr = NULL;
return tmp;
}
/** Const pointer equal comparation. */
bool operator == (const T * const p) const {
return (m_ptr == p);
}
/** Const pointer nequal comparation. */
bool operator != (const T * const p) const {
return (m_ptr != p);
}
private:
T * m_ptr;
};
#if 0
/** Reference counted base class to be used with Pointer.
*
* The only requirement of the Pointer class is that the RefCounted class implements the
* addRef and release methods.
*/
class RefCounted
{
NV_FORBID_COPY(RefCounted);
public:
/// Ctor.
RefCounted() : m_count(0), m_weak_proxy(NULL)
{
s_total_obj_count++;
}
/// Virtual dtor.
virtual ~RefCounted()
{
nvCheck( m_count == 0 );
nvCheck( s_total_obj_count > 0 );
s_total_obj_count--;
}
/// Increase reference count.
uint addRef() const
{
s_total_ref_count++;
m_count++;
return m_count;
}
/// Decrease reference count and remove when 0.
uint release() const
{
nvCheck( m_count > 0 );
s_total_ref_count--;
m_count--;
if( m_count == 0 ) {
releaseWeakProxy();
delete this;
return 0;
}
return m_count;
}
/// Get weak proxy.
WeakProxy * getWeakProxy() const
{
if (m_weak_proxy == NULL) {
m_weak_proxy = new WeakProxy;
m_weak_proxy->AddRef();
}
return m_weak_proxy;
}
/// Release the weak proxy.
void releaseWeakProxy() const
{
if (m_weak_proxy != NULL) {
m_weak_proxy->NotifyObjectDied();
m_weak_proxy->Release();
m_weak_proxy = NULL;
}
}
/** @name Debug methods: */
//@{
/// Get reference count.
int refCount() const
{
return m_count;
}
/// Get total number of objects.
static int totalObjectCount()
{
return s_total_obj_count;
}
/// Get total number of references.
static int totalReferenceCount()
{
return s_total_ref_count;
}
//@}
private:
NVCORE_API static int s_total_ref_count;
NVCORE_API static int s_total_obj_count;
mutable int m_count;
mutable WeakProxy * weak_proxy;
};
#endif
/// Smart pointer template class.
template <class BaseClass>
class Pointer {
public:
// BaseClass must implement addRef() and release().
typedef Pointer<BaseClass> ThisType;
/// Default ctor.
Pointer() : m_ptr(NULL)
{
}
/** Other type assignment. */
template <class OtherBase>
Pointer( const Pointer<OtherBase> & tc )
{
m_ptr = static_cast<BaseClass *>( tc.ptr() );
if( m_ptr ) {
m_ptr->addRef();
}
}
/** Copy ctor. */
Pointer( const ThisType & bc )
{
m_ptr = bc.ptr();
if( m_ptr ) {
m_ptr->addRef();
}
}
/** Copy cast ctor. Pointer(NULL) is valid. */
explicit Pointer( BaseClass * bc )
{
m_ptr = bc;
if( m_ptr ) {
m_ptr->addRef();
}
}
/** Dtor. */
~Pointer()
{
set(NULL);
}
/** @name Accessors: */
//@{
/** -> operator. */
BaseClass * operator -> () const
{
piCheck( m_ptr != NULL );
return m_ptr;
}
/** * operator. */
BaseClass & operator*() const
{
piCheck( m_ptr != NULL );
return *m_ptr;
}
/** Get pointer. */
BaseClass * ptr() const
{
return m_ptr;
}
//@}
/** @name Mutators: */
//@{
/** Other type assignment. */
template <class OtherBase>
void operator = ( const Pointer<OtherBase> & tc )
{
set( static_cast<BaseClass *>(tc.ptr()) );
}
/** This type assignment. */
void operator = ( const ThisType & bc )
{
set( bc.ptr() );
}
/** Pointer assignment. */
void operator = ( BaseClass * bc )
{
set( bc );
}
//@}
/** @name Comparators: */
//@{
/** Other type equal comparation. */
template <class OtherBase>
bool operator == ( const Pointer<OtherBase> & other ) const
{
return m_ptr == other.ptr();
}
/** This type equal comparation. */
bool operator == ( const ThisType & bc ) const
{
return m_ptr == bc.ptr();
}
/** Const pointer equal comparation. */
bool operator == ( const BaseClass * const bc ) const
{
return m_ptr == bc;
}
/** Other type not equal comparation. */
template <class OtherBase>
bool operator != ( const Pointer<OtherBase> & other ) const
{
return m_ptr != other.ptr();
}
/** Other type not equal comparation. */
bool operator != ( const ThisType & bc ) const
{
return m_ptr != bc.ptr();
}
/** Const pointer not equal comparation. */
bool operator != (const BaseClass * const bc) const
{
return m_ptr != bc;
}
/** This type lower than comparation. */
bool operator < (const ThisType & p) const
{
return m_ptr < p.ptr();
}
//@}
private:
/** Set this pointer. */
void set( BaseClass * p )
{
if( m_ptr != p ) {
if( m_ptr ) m_ptr->release();
if( p ) p->addRef();
m_ptr = p;
}
}
private:
BaseClass * m_ptr;
};
/*
template <class T>
class QSharedDataPointer
{
public:
inline void detach() { if (d && d->ref != 1) detach_helper(); }
inline T &operator*() { detach(); return *d; }
inline const T &operator*() const { return *d; }
inline T *operator->() { detach(); return d; }
inline const T *operator->() const { return d; }
inline operator T *() { detach(); return d; }
inline operator const T *() const { return d; }
inline T *data() { detach(); return d; }
inline const T *data() const { return d; }
inline const T *constData() const { return d; }
inline bool operator==(const QSharedDataPointer<T> &other) const { return d == other.d; }
inline bool operator!=(const QSharedDataPointer<T> &other) const { return d != other.d; }
inline QSharedDataPointer() { d = 0; }
inline ~QSharedDataPointer() { if (d && !d->ref.deref()) delete d; }
explicit QSharedDataPointer(T *data);
inline QSharedDataPointer(const QSharedDataPointer<T> &o) : d(o.d) { if (d) d->ref.ref(); }
inline QSharedDataPointer<T> & operator=(const QSharedDataPointer<T> &o) {
if (o.d != d) {
T *x = o.d;
if (x) x->ref.ref();
x = qAtomicSetPtr(&d, x);
if (x && !x->ref.deref())
delete x;
}
return *this;
}
inline QSharedDataPointer &operator=(T *o) {
if (o != d) {
T *x = o;
if (x) x->ref.ref();
x = qAtomicSetPtr(&d, x);
if (x && !x->ref.deref())
delete x;
}
return *this;
}
inline bool operator!() const { return !d; }
private:
void detach_helper();
T *d;
};
template <class T>
Q_INLINE_TEMPLATE QSharedDataPointer<T>::QSharedDataPointer(T *adata) : d(adata)
{ if (d) d->ref.ref(); }
template <class T>
Q_OUTOFLINE_TEMPLATE void QSharedDataPointer<T>::detach_helper()
{
T *x = new T(*d);
x->ref.ref();
x = qAtomicSetPtr(&d, x);
if (!x->ref.deref())
delete x;
}
*/
} // nv namespace
#endif // NV_CORE_PTR_H

429
src/nvcore/Radix.cpp Normal file
View File

@ -0,0 +1,429 @@
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains source code from the article "Radix Sort Revisited".
* \file Radix.cpp
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Revisited Radix Sort.
* This is my new radix routine:
* - it uses indices and doesn't recopy the values anymore, hence wasting less ram
* - it creates all the histograms in one run instead of four
* - it sorts words faster than dwords and bytes faster than words
* - it correctly sorts negative floating-point values by patching the offsets
* - it automatically takes advantage of temporal coherence
* - multiple keys support is a side effect of temporal coherence
* - it may be worth recoding in asm... (mainly to use FCOMI, FCMOV, etc) [it's probably memory-bound anyway]
*
* History:
* - 08.15.98: very first version
* - 04.04.00: recoded for the radix article
* - 12.xx.00: code lifting
* - 09.18.01: faster CHECK_PASS_VALIDITY thanks to Mark D. Shattuck (who provided other tips, not included here)
* - 10.11.01: added local ram support
* - 01.20.02: bugfix! In very particular cases the last pass was skipped in the float code-path, leading to incorrect sorting......
*
* \class RadixSort
* \author Pierre Terdiman
* \version 1.3
* \date August, 15, 1998
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
To do:
- add an offset parameter between two input values (avoid some data recopy sometimes)
- unroll ? asm ?
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Header
#include <nvcore/Radix.h>
#include <string.h> // memset
//using namespace IceCore;
#define DELETEARRAY(a) { delete [] a; a = NULL; }
#define CHECKALLOC(a)
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Constructor.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
RadixSort::RadixSort() : mCurrentSize(0), mPreviousSize(0), mIndices(NULL), mIndices2(NULL), mTotalCalls(0), mNbHits(0)
{
#ifndef RADIX_LOCAL_RAM
// Allocate input-independent ram
mHistogram = new uint32[256*4];
mOffset = new uint32[256];
#endif
// Initialize indices
resetIndices();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Destructor.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
RadixSort::~RadixSort()
{
// Release everything
#ifndef RADIX_LOCAL_RAM
DELETEARRAY(mOffset);
DELETEARRAY(mHistogram);
#endif
DELETEARRAY(mIndices2);
DELETEARRAY(mIndices);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Resizes the inner lists.
* \param nb [in] new size (number of dwords)
* \return true if success
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool RadixSort::resize(uint32 nb)
{
// Free previously used ram
DELETEARRAY(mIndices2);
DELETEARRAY(mIndices);
// Get some fresh one
mIndices = new uint32[nb]; CHECKALLOC(mIndices);
mIndices2 = new uint32[nb]; CHECKALLOC(mIndices2);
mCurrentSize = nb;
// Initialize indices so that the input buffer is read in sequential order
resetIndices();
return true;
}
#define CHECK_RESIZE(n) \
if(n!=mPreviousSize) \
{ \
if(n>mCurrentSize) resize(n); \
else resetIndices(); \
mPreviousSize = n; \
}
#define CREATE_HISTOGRAMS(type, buffer) \
/* Clear counters */ \
memset(mHistogram, 0, 256*4*sizeof(uint32)); \
\
/* Prepare for temporal coherence */ \
type PrevVal = (type)buffer[mIndices[0]]; \
bool AlreadySorted = true; /* Optimism... */ \
uint32* Indices = mIndices; \
\
/* Prepare to count */ \
uint8* p = (uint8*)input; \
uint8* pe = &p[nb*4]; \
uint32* h0= &mHistogram[0]; /* Histogram for first pass (LSB) */ \
uint32* h1= &mHistogram[256]; /* Histogram for second pass */ \
uint32* h2= &mHistogram[512]; /* Histogram for third pass */ \
uint32* h3= &mHistogram[768]; /* Histogram for last pass (MSB) */ \
\
while(p!=pe) \
{ \
/* Read input buffer in previous sorted order */ \
type Val = (type)buffer[*Indices++]; \
/* Check whether already sorted or not */ \
if(Val<PrevVal) { AlreadySorted = false; break; } /* Early out */ \
/* Update for next iteration */ \
PrevVal = Val; \
\
/* Create histograms */ \
h0[*p++]++; h1[*p++]++; h2[*p++]++; h3[*p++]++; \
} \
\
/* If all input values are already sorted, we just have to return and leave the */ \
/* previous list unchanged. That way the routine may take advantage of temporal */ \
/* coherence, for example when used to sort transparent faces. */ \
if(AlreadySorted) { mNbHits++; return *this; } \
\
/* Else there has been an early out and we must finish computing the histograms */ \
while(p!=pe) \
{ \
/* Create histograms without the previous overhead */ \
h0[*p++]++; h1[*p++]++; h2[*p++]++; h3[*p++]++; \
}
#define CHECK_PASS_VALIDITY(pass) \
/* Shortcut to current counters */ \
uint32* CurCount = &mHistogram[pass<<8]; \
\
/* Reset flag. The sorting pass is supposed to be performed. (default) */ \
bool PerformPass = true; \
\
/* Check pass validity */ \
\
/* If all values have the same byte, sorting is useless. */ \
/* It may happen when sorting bytes or words instead of dwords. */ \
/* This routine actually sorts words faster than dwords, and bytes */ \
/* faster than words. Standard running time (O(4*n))is reduced to O(2*n) */ \
/* for words and O(n) for bytes. Running time for floats depends on actual values... */ \
\
/* Get first byte */ \
uint8 UniqueVal = *(((uint8*)input)+pass); \
\
/* Check that byte's counter */ \
if(CurCount[UniqueVal]==nb) PerformPass=false;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Main sort routine.
* This one is for integer values. After the call, mIndices contains a list of indices in sorted order, i.e. in the order you may process your data.
* \param input [in] a list of integer values to sort
* \param nb [in] number of values to sort
* \param signedvalues [in] true to handle negative values, false if you know your input buffer only contains positive values
* \return Self-Reference
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
RadixSort& RadixSort::sort(const uint32* input, uint32 nb, bool signedvalues)
{
uint32 i, j;
// Checkings
if(!input || !nb) return *this;
// Stats
mTotalCalls++;
// Resize lists if needed
CHECK_RESIZE(nb);
#ifdef RADIX_LOCAL_RAM
// Allocate histograms & offsets on the stack
uint32 mHistogram[256*4];
uint32 mOffset[256];
#endif
// Create histograms (counters). Counters for all passes are created in one run.
// Pros: read input buffer once instead of four times
// Cons: mHistogram is 4Kb instead of 1Kb
// We must take care of signed/unsigned values for temporal coherence.... I just
// have 2 code paths even if just a single opcode changes. Self-modifying code, someone?
if(!signedvalues) { CREATE_HISTOGRAMS(uint32, input); }
else { CREATE_HISTOGRAMS(int32, input); }
// Compute #negative values involved if needed
uint32 NbNegativeValues = 0;
if(signedvalues)
{
// An efficient way to compute the number of negatives values we'll have to deal with is simply to sum the 128
// last values of the last histogram. Last histogram because that's the one for the Most Significant Byte,
// responsible for the sign. 128 last values because the 128 first ones are related to positive numbers.
uint32* h3= &mHistogram[768];
for( i=128;i<256;i++) NbNegativeValues += h3[i]; // 768 for last histogram, 128 for negative part
}
// Radix sort, j is the pass number (0=LSB, 3=MSB)
for( j=0;j<4;j++)
{
CHECK_PASS_VALIDITY(j);
// Sometimes the fourth (negative) pass is skipped because all numbers are negative and the MSB is 0xFF (for example). This is
// not a problem, numbers are correctly sorted anyway.
if(PerformPass)
{
// Should we care about negative values?
if(j!=3 || !signedvalues)
{
// Here we deal with positive values only
// Create offsets
mOffset[0] = 0;
for(i=1;i<256;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1];
}
else
{
// This is a special case to correctly handle negative integers. They're sorted in the right order but at the wrong place.
// Create biased offsets, in order for negative numbers to be sorted as well
mOffset[0] = NbNegativeValues; // First positive number takes place after the negative ones
for(i=1;i<128;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1]; // 1 to 128 for positive numbers
// Fixing the wrong place for negative values
mOffset[128] = 0;
for(i=129;i<256;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1];
}
// Perform Radix Sort
uint8* InputBytes = (uint8*)input;
uint32* Indices = mIndices;
uint32* IndicesEnd = &mIndices[nb];
InputBytes += j;
while(Indices!=IndicesEnd)
{
uint32 id = *Indices++;
mIndices2[mOffset[InputBytes[id<<2]]++] = id;
}
// Swap pointers for next pass. Valid indices - the most recent ones - are in mIndices after the swap.
uint32* Tmp = mIndices; mIndices = mIndices2; mIndices2 = Tmp;
}
}
return *this;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Main sort routine.
* This one is for floating-point values. After the call, mIndices contains a list of indices in sorted order, i.e. in the order you may process your data.
* \param input [in] a list of floating-point values to sort
* \param nb [in] number of values to sort
* \return Self-Reference
* \warning only sorts IEEE floating-point values
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
RadixSort& RadixSort::sort(const float* input2, uint32 nb)
{
uint32 i, j;
// Checkings
if(!input2 || !nb) return *this;
// Stats
mTotalCalls++;
uint32* input = (uint32*)input2;
// Resize lists if needed
CHECK_RESIZE(nb);
#ifdef RADIX_LOCAL_RAM
// Allocate histograms & offsets on the stack
uint32 mHistogram[256*4];
uint32 mOffset[256];
#endif
// Create histograms (counters). Counters for all passes are created in one run.
// Pros: read input buffer once instead of four times
// Cons: mHistogram is 4Kb instead of 1Kb
// Floating-point values are always supposed to be signed values, so there's only one code path there.
// Please note the floating point comparison needed for temporal coherence! Although the resulting asm code
// is dreadful, this is surprisingly not such a performance hit - well, I suppose that's a big one on first
// generation Pentiums....We can't make comparison on integer representations because, as Chris said, it just
// wouldn't work with mixed positive/negative values....
{ CREATE_HISTOGRAMS(float, input2); }
// Compute #negative values involved if needed
uint32 NbNegativeValues = 0;
// An efficient way to compute the number of negatives values we'll have to deal with is simply to sum the 128
// last values of the last histogram. Last histogram because that's the one for the Most Significant Byte,
// responsible for the sign. 128 last values because the 128 first ones are related to positive numbers.
uint32* h3= &mHistogram[768];
for( i=128;i<256;i++) NbNegativeValues += h3[i]; // 768 for last histogram, 128 for negative part
// Radix sort, j is the pass number (0=LSB, 3=MSB)
for( j=0;j<4;j++)
{
// Should we care about negative values?
if(j!=3)
{
// Here we deal with positive values only
CHECK_PASS_VALIDITY(j);
if(PerformPass)
{
// Create offsets
mOffset[0] = 0;
for( i=1;i<256;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1];
// Perform Radix Sort
uint8* InputBytes = (uint8*)input;
uint32* Indices = mIndices;
uint32* IndicesEnd = &mIndices[nb];
InputBytes += j;
while(Indices!=IndicesEnd)
{
uint32 id = *Indices++;
mIndices2[mOffset[InputBytes[id<<2]]++] = id;
}
// Swap pointers for next pass. Valid indices - the most recent ones - are in mIndices after the swap.
uint32* Tmp = mIndices; mIndices = mIndices2; mIndices2 = Tmp;
}
}
else
{
// This is a special case to correctly handle negative values
CHECK_PASS_VALIDITY(j);
if(PerformPass)
{
// Create biased offsets, in order for negative numbers to be sorted as well
mOffset[0] = NbNegativeValues; // First positive number takes place after the negative ones
for(i=1;i<128;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1]; // 1 to 128 for positive numbers
// We must reverse the sorting order for negative numbers!
mOffset[255] = 0;
for(i=0;i<127;i++) mOffset[254-i] = mOffset[255-i] + CurCount[255-i]; // Fixing the wrong order for negative values
for(i=128;i<256;i++) mOffset[i] += CurCount[i]; // Fixing the wrong place for negative values
// Perform Radix Sort
for(i=0;i<nb;i++)
{
uint32 Radix = input[mIndices[i]]>>24; // Radix byte, same as above. AND is useless here (uint32).
// ### cmp to be killed. Not good. Later.
if(Radix<128) mIndices2[mOffset[Radix]++] = mIndices[i]; // Number is positive, same as above
else mIndices2[--mOffset[Radix]] = mIndices[i]; // Number is negative, flip the sorting order
}
// Swap pointers for next pass. Valid indices - the most recent ones - are in mIndices after the swap.
uint32* Tmp = mIndices; mIndices = mIndices2; mIndices2 = Tmp;
}
else
{
// The pass is useless, yet we still have to reverse the order of current list if all values are negative.
if(UniqueVal>=128)
{
for(i=0;i<nb;i++) mIndices2[i] = mIndices[nb-i-1];
// Swap pointers for next pass. Valid indices - the most recent ones - are in mIndices after the swap.
uint32* Tmp = mIndices; mIndices = mIndices2; mIndices2 = Tmp;
}
}
}
}
return *this;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Resets the inner indices. After the call, mIndices is reset.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void RadixSort::resetIndices()
{
for(uint32 i=0;i<mCurrentSize;i++) mIndices[i] = i;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Gets the ram used.
* \return memory used in bytes
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
uint32 RadixSort::usedRam() const
{
uint32 UsedRam = sizeof(RadixSort);
#ifndef RADIX_LOCAL_RAM
UsedRam += 256*4*sizeof(uint32); // Histograms
UsedRam += 256*sizeof(uint32); // Offsets
#endif
UsedRam += 2*mCurrentSize*sizeof(uint32); // 2 lists of indices
return UsedRam;
}

69
src/nvcore/Radix.h Normal file
View File

@ -0,0 +1,69 @@
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains source code from the article "Radix Sort Revisited".
* \file Radix.h
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef NV_CORE_RADIXSORT_H
#define NV_CORE_RADIXSORT_H
#include <nvcore/nvcore.h>
#define RADIX_LOCAL_RAM
class NVCORE_API RadixSort {
NV_FORBID_COPY(RadixSort);
public:
// Constructor/Destructor
RadixSort();
~RadixSort();
// Sorting methods
RadixSort & sort(const uint32* input, uint32 nb, bool signedvalues=true);
RadixSort & sort(const float* input, uint32 nb);
//! Access to results. mIndices is a list of indices in sorted order, i.e. in the order you may further process your data
inline uint32 * indices() const { return mIndices; }
//! mIndices2 gets trashed on calling the sort routine, but otherwise you can recycle it the way you want.
inline uint32 * recyclable() const { return mIndices2; }
// Stats
uint32 usedRam() const;
//! Returns the total number of calls to the radix sorter.
inline uint32 totalCalls() const { return mTotalCalls; }
//! Returns the number of premature exits due to temporal coherence.
inline uint32 hits() const { return mNbHits; }
private:
#ifndef RADIX_LOCAL_RAM
uint32* mHistogram; //!< Counters for each byte
uint32* mOffset; //!< Offsets (nearly a cumulative distribution function)
#endif
uint32 mCurrentSize; //!< Current size of the indices list
uint32 mPreviousSize; //!< Size involved in previous call
uint32* mIndices; //!< Two lists, swapped each pass
uint32* mIndices2;
// Stats
uint32 mTotalCalls;
uint32 mNbHits;
// Internal methods
bool resize(uint32 nb);
void resetIndices();
};
#endif // NV_CORE_RADIXSORT_H

336
src/nvcore/StdStream.h Normal file
View File

@ -0,0 +1,336 @@
#ifndef NV_STDSTREAM_H
#define NV_STDSTREAM_H
#include <nvcore/Stream.h>
#include <stdio.h> // fopen
#include <string.h> // memcpy
#include <exception> // std::exception
namespace nv
{
// Portable version of fopen.
inline FILE * fileOpen(const char * fileName, const char * mode)
{
#if NV_CC_MSVC && _MSC_VER >= 1400
FILE * fp;
if (fopen_s(&fp, fileName, mode) == 0) {
return fp;
}
return NULL;
#else
return fopen(fileName, mode);
#endif
}
/// Base stdio stream.
class StdStream : public Stream
{
public:
/// Ctor.
StdStream( FILE * fp, bool autoclose=true ) :
m_fp(fp), m_autoclose(autoclose) { }
/// Dtor.
virtual ~StdStream()
{
if( m_fp != NULL && m_autoclose ) {
fclose( m_fp );
}
}
/** @name Stream implementation. */
//@{
virtual void seek( int pos )
{
nvDebugCheck(m_fp != NULL);
fseek(m_fp, pos, SEEK_SET);
}
virtual int tell() const
{
nvDebugCheck(m_fp != NULL);
return ftell(m_fp);
}
virtual int size() const
{
int pos = ftell(m_fp);
fseek(m_fp, 0, SEEK_END);
int end = ftell(m_fp);
fseek(m_fp, pos, SEEK_SET);
return end;
}
virtual bool isError() const
{
return m_fp == NULL || ferror( m_fp ) != 0;
}
virtual bool isAtEnd() const
{
nvDebugCheck(m_fp != NULL);
return feof( m_fp ) != 0;
}
/// Always true.
virtual bool isSeekable() const { return true; }
//@}
protected:
FILE * m_fp;
bool m_autoclose;
};
/// Standard output stream.
class StdOutputStream : public StdStream
{
public:
/// Construct stream by file name.
StdOutputStream( const char * name ) :
StdStream(fileOpen(name, "wb")) { }
/// Construct stream by file handle.
StdOutputStream( FILE * fp, bool autoclose=true ) : StdStream(fp, autoclose)
{
}
/** @name Stream implementation. */
//@{
/// Write data.
virtual void serialize( void * data, int len )
{
nvDebugCheck(data != NULL);
nvDebugCheck(m_fp != NULL);
fwrite(data, len, 1, m_fp);
}
virtual bool isLoading() const
{
return false;
}
virtual bool isSaving() const
{
return true;
}
//@}
};
/// Standard input stream.
class StdInputStream : public StdStream
{
public:
/// Construct stream by file name.
StdInputStream( const char * name ) :
StdStream(fileOpen(name, "rb")) { }
/// Construct stream by file handle.
StdInputStream( FILE * fp, bool autoclose=true ) : StdStream(fp, autoclose)
{
}
/** @name Stream implementation. */
//@{
/// Read data.
virtual void serialize( void * data, int len )
{
nvDebugCheck(data != NULL);
nvDebugCheck(m_fp != NULL);
fread(data, len, 1, m_fp);
}
virtual bool isLoading() const
{
return true;
}
virtual bool isSaving() const
{
return false;
}
//@}
};
/// Memory input stream.
class MemoryInputStream : public Stream
{
public:
/// Ctor.
MemoryInputStream( const uint8 * mem, int size ) :
m_mem(mem), m_ptr(mem), m_size(size) { }
/** @name Stream implementation. */
//@{
/// Read data.
virtual void serialize( void * data, int len )
{
nvDebugCheck(data != NULL);
nvDebugCheck(!isError());
memcpy( data, m_ptr, len );
m_ptr += len;
}
virtual void seek( int pos )
{
nvDebugCheck(!isError());
m_ptr = m_mem + pos;
nvDebugCheck(!isError());
}
virtual int tell() const
{
return m_ptr - m_mem;
}
virtual int size() const
{
return m_size;
}
virtual bool isError() const
{
return m_mem == NULL || m_ptr > m_mem + m_size || m_ptr < m_mem;
}
virtual bool isAtEnd() const
{
return m_ptr == m_mem + m_size;
}
/// Always true.
virtual bool isSeekable() const
{
return true;
}
virtual bool isLoading() const
{
return true;
}
virtual bool isSaving() const
{
return false;
}
//@}
private:
const uint8 * m_mem;
const uint8 * m_ptr;
int m_size;
};
/// Protected input stream.
class ProtectedStream : public Stream
{
public:
/// Ctor.
ProtectedStream( Stream & s ) : m_s(&s), m_autodelete(false)
{
}
/// Ctor.
ProtectedStream( Stream * s, bool autodelete = true ) :
m_s(s), m_autodelete(autodelete)
{
nvDebugCheck(m_s != NULL);
}
/// Dtor.
virtual ~ProtectedStream()
{
if( m_autodelete ) {
delete m_s;
}
}
/** @name Stream implementation. */
//@{
/// Read data.
virtual void serialize( void * data, int len )
{
nvDebugCheck(data != NULL);
m_s->serialize( data, len );
if( m_s->isError() ) {
throw std::exception();
}
}
virtual void seek( int pos )
{
m_s->seek( pos );
if( m_s->isError() ) {
throw std::exception();
}
}
virtual int tell() const
{
return m_s->tell();
}
virtual int size() const
{
return m_s->size();
}
virtual bool isError() const
{
return m_s->isError();
}
virtual bool isAtEnd() const
{
return m_s->isAtEnd();
}
virtual bool isSeekable() const
{
return m_s->isSeekable();
}
virtual bool isLoading() const
{
return m_s->isLoading();
}
virtual bool isSaving() const
{
return m_s->isSaving();
}
//@}
private:
Stream * m_s;
bool m_autodelete;
};
} // nv namespace
#endif // NV_STDSTREAM_H

632
src/nvcore/StrLib.cpp Normal file
View File

@ -0,0 +1,632 @@
// This code is in the public domain -- castanyo@yahoo.es
#include <nvcore/StrLib.h>
#include <math.h> // log
#include <stdio.h> // vsnprintf
#if NV_CC_MSVC
#include <stdarg.h> // vsnprintf
#endif
#if NV_OS_WIN32
#define NV_PATH_SEPARATOR '\\'
#else
#define NV_PATH_SEPARATOR '/'
#endif
using namespace nv;
namespace
{
static char * strAlloc(uint size)
{
return static_cast<char *>(mem::malloc(size));
}
static char * strReAlloc(char * str, uint size)
{
return static_cast<char *>(mem::realloc(str, size));
}
static void strFree(const char * str)
{
return mem::free(const_cast<char *>(str));
}
/*static char * strDup( const char * str )
{
nvDebugCheck( str != NULL );
uint len = uint(strlen( str ) + 1);
char * dup = strAlloc( len );
memcpy( dup, str, len );
return dup;
}*/
// helper function for integer to string conversion.
static char * i2a( uint i, char *a, uint r )
{
if( i / r > 0 ) {
a = i2a( i / r, a, r );
}
*a = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i % r];
return a + 1;
}
// Locale independent functions.
static inline char toUpper( char c ) {
return (c<'a' || c>'z') ? (c) : (c+'A'-'a');
}
static inline char toLower( char c ) {
return (c<'A' || c>'Z') ? (c) : (c+'a'-'A');
}
static inline bool isAlpha( char c ) {
return (c>='a' && c<='z') || (c>='A' && c<='Z');
}
static inline bool isDigit( char c ) {
return c>='0' && c<='9';
}
static inline bool isAlnum( char c ) {
return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9');
}
}
int nv::strCmp(const char * s1, const char * s2)
{
nvDebugCheck(s1 != NULL);
nvDebugCheck(s2 != NULL);
return strcmp(s1, s2);
}
int nv::strCaseCmp(const char * s1, const char * s2)
{
nvDebugCheck(s1 != NULL);
nvDebugCheck(s1 != NULL);
#if NV_CC_MSVC
return _stricmp(s1, s2);
#else
return strcasecmp(s1, s2);
#endif
}
void nv::strCpy(char * dst, int size, const char * src)
{
nvDebugCheck(dst != NULL);
nvDebugCheck(src != NULL);
#if NV_CC_MSVC && _MSC_VER >= 1400
strcpy_s(dst, size, src);
#else
NV_UNUSED(size);
strcpy(dst, src);
#endif
}
void nv::strCat(char * dst, int size, const char * src)
{
nvDebugCheck(dst != NULL);
nvDebugCheck(src != NULL);
#if NV_CC_MSVC && _MSC_VER >= 1400
strcat_s(dst, size, src);
#else
NV_UNUSED(size);
strcat(dst, src);
#endif
}
/** Pattern matching routine. I don't remember where did I get this. */
bool nv::strMatch(const char * str, const char * pat)
{
nvDebugCheck(str != NULL);
nvDebugCheck(pat != NULL);
char c2;
while (true) {
if (*pat==0) {
if (*str==0) return true;
else return false;
}
if ((*str==0) && (*pat!='*')) return false;
if (*pat=='*') {
pat++;
if (*pat==0) return true;
while (true) {
if (strMatch(str, pat)) return true;
if (*str==0) return false;
str++;
}
}
if (*pat=='?') goto match;
if (*pat=='[') {
pat++;
while (true) {
if ((*pat==']') || (*pat==0)) return false;
if (*pat==*str) break;
if (pat[1] == '-') {
c2 = pat[2];
if (c2==0) return false;
if ((*pat<=*str) && (c2>=*str)) break;
if ((*pat>=*str) && (c2<=*str)) break;
pat+=2;
}
pat++;
}
while (*pat!=']') {
if (*pat==0) {
pat--;
break;
}
pat++;
}
goto match;
}
if (*pat == NV_PATH_SEPARATOR) {
pat++;
if (*pat==0) return false;
}
if (*pat!=*str) return false;
match:
pat++;
str++;
}
}
/** Empty string. */
StringBuilder::StringBuilder() : m_size(0), m_str(NULL)
{
}
/** Preallocate space. */
StringBuilder::StringBuilder( int size_hint ) : m_size(size_hint)
{
nvDebugCheck(m_size > 0);
m_str = strAlloc(m_size);
*m_str = '\0';
}
/** Copy ctor. */
StringBuilder::StringBuilder( const StringBuilder & s ) : m_size(0), m_str(NULL)
{
copy(s);
}
/** Allocate and copy string. */
StringBuilder::StringBuilder( int size_hint, const StringBuilder & s) : m_size(size_hint), m_str(NULL)
{
nvDebugCheck(m_size > 0);
m_str = strAlloc(m_size);
copy(s);
}
/** Allocate and format string. */
StringBuilder::StringBuilder( const char * fmt, ... ) : m_size(0), m_str(NULL)
{
nvDebugCheck(fmt != NULL);
va_list arg;
va_start( arg, fmt );
format( fmt, arg );
va_end( arg );
}
/** Allocate and format string. */
StringBuilder::StringBuilder( int size_hint, const char * fmt, ... ) : m_size(size_hint), m_str(NULL)
{
nvDebugCheck(m_size > 0);
nvDebugCheck(fmt != NULL);
m_str = strAlloc(m_size);
va_list arg;
va_start( arg, fmt );
format( fmt, arg );
va_end( arg );
}
/** Delete the string. */
StringBuilder::~StringBuilder()
{
m_size = 0;
strFree(m_str);
m_str = NULL;
}
/** Format a string safely. */
StringBuilder & StringBuilder::format( const char * fmt, ... )
{
nvDebugCheck(fmt != NULL);
va_list arg;
va_start( arg, fmt );
format( fmt, arg );
va_end( arg );
return *this;
}
/** Format a string safely. */
StringBuilder & StringBuilder::format( const char * fmt, va_list arg )
{
nvCheck(fmt != NULL);
nvCheck(m_size >= 0);
if( m_size == 0 ) {
m_size = 64;
m_str = strAlloc( m_size );
}
va_list tmp;
va_copy(tmp, arg);
#if NV_CC_MSVC && _MSC_VER >= 1400
int n = vsnprintf_s(m_str, m_size, _TRUNCATE, fmt, tmp);
#else
int n = vsnprintf(m_str, m_size, fmt, tmp);
#endif
va_end(tmp);
while( n < 0 || n >= int(m_size) ) {
if( n > -1 ) {
m_size = n + 1;
}
else {
m_size *= 2;
}
m_str = strReAlloc(m_str, m_size);
va_copy(tmp, arg);
#if NV_CC_MSVC && _MSC_VER >= 1400
n = vsnprintf_s(m_str, m_size, _TRUNCATE, fmt, tmp);
#else
n = vsnprintf(m_str, m_size, fmt, tmp);
#endif
va_end(tmp);
}
nvDebugCheck(n < int(m_size));
// Make sure it's null terminated.
nvDebugCheck(m_str[n] == '\0');
//str[n] = '\0';
return *this;
}
/** Append a string. */
StringBuilder & StringBuilder::append( const char * s )
{
nvCheck(s != NULL);
nvCheck(m_size >= 0);
const uint slen = uint(strlen( s ));
if( m_str == NULL ) {
m_size = slen + 1;
m_str = strAlloc(m_size);
strCpy( m_str, m_size, s );
}
else {
const uint len = uint(strlen( m_str ));
if( m_size < len + slen + 1 ) {
m_size = len + slen + 1;
m_str = strReAlloc(m_str, m_size);
}
strCat( m_str, m_size, s );
}
return *this;
}
/** Append a formatted string. */
StringBuilder & StringBuilder::appendFormat( const char * format, ... )
{
nvDebugCheck( format != NULL );
va_list arg;
va_start( arg, format );
appendFormat( format, arg );
va_end( arg );
return *this;
}
/** Append a formatted string. */
StringBuilder & StringBuilder::appendFormat( const char * format, va_list arg )
{
nvDebugCheck( format != NULL );
va_list tmp;
va_copy(tmp, arg);
StringBuilder tmp_str;
tmp_str.format( format, tmp );
append( tmp_str );
va_end(tmp);
return *this;
}
/** Convert number to string in the given base. */
StringBuilder & StringBuilder::number( int i, int base )
{
nvCheck( base >= 2 );
nvCheck( base <= 36 );
// @@ This needs to be done correctly.
// length = floor(log(i, base));
uint len = uint(log(float(i)) / log(float(base)) + 2); // one more if negative
reserve(len);
if( i < 0 ) {
*m_str = '-';
*i2a(uint(-i), m_str+1, base) = 0;
}
else {
*i2a(i, m_str, base) = 0;
}
return *this;
}
/** Convert number to string in the given base. */
StringBuilder & StringBuilder::number( uint i, int base )
{
nvCheck( base >= 2 );
nvCheck( base <= 36 );
// @@ This needs to be done correctly.
// length = floor(log(i, base));
uint len = uint(log(float(i)) / log(float(base)) - 0.5f + 1);
reserve(len);
*i2a(i, m_str, base) = 0;
return *this;
}
/** Resize the string preserving the contents. */
StringBuilder & StringBuilder::reserve( uint size_hint )
{
nvCheck(size_hint != 0);
if( size_hint > m_size ) {
m_str = strReAlloc(m_str, size_hint);
m_size = size_hint;
}
return *this;
}
/** Copy a string safely. */
StringBuilder & StringBuilder::copy( const char * s )
{
nvCheck( s != NULL );
uint str_size = uint(strlen( s )) + 1;
reserve(str_size);
strCpy( m_str, str_size, s );
return *this;
}
/** Copy an StringBuilder. */
StringBuilder & StringBuilder::copy( const StringBuilder & s )
{
if( s.m_str == NULL ) {
nvCheck( s.m_size == 0 );
m_size = 0;
strFree( m_str );
m_str = NULL;
}
else {
reserve( s.m_size );
strCpy( m_str, s.m_size, s.m_str );
}
return *this;
}
/** Reset the string. */
void StringBuilder::reset()
{
m_size = 0;
strFree( m_str );
m_str = NULL;
}
Path::Path(const char * fmt, ...)
{
nvDebugCheck( fmt != NULL );
va_list arg;
va_start( arg, fmt );
format( fmt, arg );
va_end( arg );
}
Path::Path(int size_hint, const char * fmt, ...) : StringBuilder(size_hint)
{
nvDebugCheck( fmt != NULL );
va_list arg;
va_start( arg, fmt );
format( fmt, arg );
va_end( arg );
}
/// Get the file name from a path.
const char * Path::fileName() const
{
return fileName(m_str);
}
/// Get the extension from a file path.
const char * Path::extension() const
{
return extension(m_str);
}
/// Toggles path separators (ie. \\ into /).
void Path::translatePath()
{
nvCheck( m_str != NULL );
for(int i = 0; ; i++) {
if( m_str[i] == '\0' ) break;
#if NV_PATH_SEPARATOR == '/'
if( m_str[i] == '\\' ) m_str[i] = NV_PATH_SEPARATOR;
#else
if( m_str[i] == '/' ) m_str[i] = NV_PATH_SEPARATOR;
#endif
}
}
/**
* Strip the file name from a path.
* @warning path cannot end with '/' o '\\', can't it?
*/
void Path::stripFileName()
{
nvCheck( m_str != NULL );
int length = (int)strlen(m_str) - 1;
while (length > 0 && m_str[length] != '/' && m_str[length] != '\\'){
length--;
}
if( length ) {
m_str[length+1] = 0;
}
else {
m_str[0] = 0;
}
}
/// Strip the extension from a path name.
void Path::stripExtension()
{
nvCheck( m_str != NULL );
int length = (int)strlen(m_str) - 1;
while( length > 0 && m_str[length] != '.' ) {
length--;
if( m_str[length] == NV_PATH_SEPARATOR ) {
return; // no extension
}
}
if( length ) {
m_str[length] = 0;
}
}
/// Get the path separator.
// static
char Path::separator()
{
return NV_PATH_SEPARATOR;
}
// static
const char * Path::fileName(const char * str)
{
nvCheck( str != NULL );
int length = (int)strlen(str) - 1;
while( length >= 0 && str[length] != separator() ) {
length--;
}
return &str[length+1];
}
// static
const char * Path::extension(const char * str)
{
nvCheck( str != NULL );
int length, l;
l = length = (int)strlen( str );
while( length > 0 && str[length] != '.' ) {
length--;
if( str[length] == separator() ) {
return &str[l]; // no extension
}
}
if( length == 0 ) {
return &str[l];
}
return &str[length];
}
// static
String String::s_null(String::null);
/// Clone this string
String String::clone() const
{
String str(data);
return str;
}
void String::setString(const char * str)
{
if( str == NULL ) {
data = s_null.data;
}
else {
allocString( str );
}
addRef();
}
void String::setString(const char * str, int length)
{
nvDebugCheck(str != NULL);
allocString(str, length);
addRef();
}
void String::setString(const StringBuilder & str)
{
if( str.str() == NULL ) {
data = s_null.data;
}
else {
allocString(str);
}
addRef();
}

348
src/nvcore/StrLib.h Normal file
View File

@ -0,0 +1,348 @@
// This code is in the public domain -- castanyo@yahoo.es
#ifndef NV_CORE_STRING_H
#define NV_CORE_STRING_H
#include <nvcore/nvcore.h>
#include <nvcore/Containers.h> // swap
#include <string.h> // strlen, strcmp, etc.
namespace nv
{
uint strHash(const char * str, uint h) NV_PURE;
/// String hash vased on Bernstein's hash.
inline uint strHash(const char * data, uint h = 5381)
{
uint i;
while(data[i] != 0) {
h = (33 * h) ^ uint(data[i]);
i++;
}
return h;
}
template <> struct hash<const char *> {
uint operator()(const char * str) const { return strHash(str); }
};
NVCORE_API int strCaseCmp(const char * s1, const char * s2) NV_PURE;
NVCORE_API int strCmp(const char * s1, const char * s2) NV_PURE;
NVCORE_API void strCpy(char * dst, int size, const char * src);
NVCORE_API void strCat(char * dst, int size, const char * src);
NVCORE_API bool strMatch(const char * str, const char * pat) NV_PURE;
/// String builder.
class StringBuilder
{
public:
NVCORE_API StringBuilder();
NVCORE_API explicit StringBuilder( int size_hint );
NVCORE_API StringBuilder( const StringBuilder & );
NVCORE_API StringBuilder( int size_hint, const StringBuilder & );
NVCORE_API StringBuilder( const char * format, ... ) __attribute__((format (printf, 2, 3)));
NVCORE_API StringBuilder( int size_hint, const char * format, ... ) __attribute__((format (printf, 3, 4)));
NVCORE_API ~StringBuilder();
NVCORE_API StringBuilder & format( const char * format, ... ) __attribute__((format (printf, 2, 3)));
NVCORE_API StringBuilder & format( const char * format, va_list arg );
NVCORE_API StringBuilder & append( const char * str );
NVCORE_API StringBuilder & appendFormat( const char * format, ... ) __attribute__((format (printf, 2, 3)));
NVCORE_API StringBuilder & appendFormat( const char * format, va_list arg );
NVCORE_API StringBuilder & number( int i, int base = 10 );
NVCORE_API StringBuilder & number( uint i, int base = 10 );
NVCORE_API StringBuilder & reserve( uint size_hint );
NVCORE_API StringBuilder & copy( const char * str );
NVCORE_API StringBuilder & copy( const StringBuilder & str );
NVCORE_API StringBuilder & toLower();
NVCORE_API StringBuilder & toUpper();
NVCORE_API void reset();
NVCORE_API bool empty() const { return m_size == 0; }
// const char * accessors
operator const char * () const { return m_str; }
operator char * () { return m_str; }
const char * str() const { return m_str; }
char * str() { return m_str; }
/// Implement value semantics.
StringBuilder & operator=( const StringBuilder & s ) {
return copy(s);
}
/// Equal operator.
bool operator==( const StringBuilder & s ) const {
nvCheck(m_str != NULL);
nvCheck(s.m_str != NULL);
return strcmp(s.m_str, m_str) != 0;
}
/// Return the exact length.
uint length() const { nvCheck(m_str != NULL); return uint(strlen(m_str)); }
/// Return the size of the string container.
uint capacity() const { nvCheck(m_str != NULL); return m_size; }
/// Return the hash of the string.
uint hash() const { nvCheck(m_str != NULL); return strHash(m_str); }
/// Swap strings.
friend void swap(StringBuilder & a, StringBuilder & b) {
nv::swap(a.m_size, b.m_size);
nv::swap(a.m_str, b.m_str);
}
static char separator();
protected:
/// Size of the string container.
uint m_size;
/// String.
char * m_str;
};
/// Path string.
class Path : public StringBuilder
{
public:
Path() : StringBuilder() {}
explicit Path(int size_hint) : StringBuilder(size_hint) {}
Path(const StringBuilder & str) : StringBuilder(str) {}
Path(int size_hint, const StringBuilder & str) : StringBuilder(size_hint, str) {}
NVCORE_API Path(const char * format, ...) __attribute__((format (printf, 2, 3)));
NVCORE_API Path(int size_hint, const char * format, ...) __attribute__((format (printf, 3, 4)));
NVCORE_API const char * fileName() const;
NVCORE_API const char * extension() const;
NVCORE_API void translatePath();
NVCORE_API void stripFileName();
NVCORE_API void stripExtension();
// statics
NVCORE_API static char separator();
NVCORE_API static const char * fileName(const char *);
NVCORE_API static const char * extension(const char *);
};
/// String class.
class String
{
public:
/// Constructs a null string. @sa isNull()
String()
{
data = s_null.data;
addRef();
}
/// Constructs a shared copy of str.
String(const String & str)
{
data = str.data;
addRef();
}
/// Constructs a shared string from a standard string.
String(const char * str)
{
setString(str);
}
/// Constructs a shared string from a standard string.
String(const char * str, int length)
{
setString(str, length);
}
/// Constructs a shared string from a StringBuilder.
String(const StringBuilder & str)
{
setString(str);
}
/// Dtor.
~String()
{
nvDebugCheck(data != NULL);
release();
}
NVCORE_API String clone() const;
/// Release the current string and allocate a new one.
const String & operator=( const char * str )
{
release();
setString( str );
return *this;
}
/// Release the current string and allocate a new one.
const String & operator=( const StringBuilder & str )
{
release();
setString( str );
return *this;
}
/// Implement value semantics.
String & operator=( const String & str )
{
release();
data = str.data;
addRef();
return *this;
}
/// Equal operator.
bool operator==( const String & str ) const
{
nvDebugCheck(data != NULL);
nvDebugCheck(str.data != NULL);
if( str.data == data ) {
return true;
}
return strcmp(data, str.data) == 0;
}
/// Equal operator.
bool operator==( const char * str ) const
{
nvDebugCheck(data != NULL);
nvCheck(str != NULL); // Use isNull!
return strcmp(data, str) == 0;
}
/// Not equal operator.
bool operator!=( const String & str ) const
{
nvDebugCheck(data != NULL);
nvDebugCheck(str.data != NULL);
if( str.data == data ) {
return false;
}
return strcmp(data, str.data) != 0;
}
/// Not equal operator.
bool operator!=( const char * str ) const
{
nvDebugCheck(data != NULL);
nvCheck(str != NULL); // Use isNull!
return strcmp(data, str) != 0;
}
/// Returns true if this string is the null string.
bool isNull() const { nvDebugCheck(data != NULL); return data == s_null.data; }
/// Return the exact length.
uint length() const { nvDebugCheck(data != NULL); return uint(strlen(data)); }
/// Return the hash of the string.
uint hash() const { nvDebugCheck(data != NULL); return strHash(data); }
/// const char * cast operator.
operator const char * () const { nvDebugCheck(data != NULL); return data; }
/// Get string pointer.
const char * str() const { nvDebugCheck(data != NULL); return data; }
private:
enum null_t { null };
// Private constructor for null string.
String(null_t) {
setString("");
}
// Add reference count.
void addRef() {
nvDebugCheck(data != NULL);
setRefCount(getRefCount() + 1);
}
// Decrease reference count.
void release() {
nvDebugCheck(data != NULL);
const uint16 count = getRefCount();
setRefCount(count - 1);
if( count - 1 == 0 ) {
mem::free(data - 2);
data = NULL;
}
}
uint16 getRefCount() const {
return *reinterpret_cast<const uint16 *>(data - 2);
}
void setRefCount(uint16 count) {
nvCheck(count < 0xFFFF);
*reinterpret_cast<uint16 *>(const_cast<char *>(data - 2)) = uint16(count);
}
void setData(const char * str) {
data = str + 2;
}
void allocString(const char * str)
{
allocString(str, (int)strlen(str));
}
void allocString(const char * str, int len)
{
const char * ptr = static_cast<const char *>(mem::malloc(2 + len + 1));
setData( ptr );
setRefCount( 0 );
// Copy string.
strCpy(const_cast<char *>(data), len + 1, str);
}
NVCORE_API void setString(const char * str);
NVCORE_API void setString(const char * str, int length);
NVCORE_API void setString(const StringBuilder & str);
/// Swap strings.
friend void swap(String & a, String & b) {
swap(a.data, b.data);
}
private:
NVCORE_API static String s_null;
const char * data;
};
} // nv namespace
#endif // NV_CORE_STRING_H

165
src/nvcore/Stream.h Normal file
View File

@ -0,0 +1,165 @@
// This code is in the public domain -- castanyo@yahoo.es
#ifndef NVCORE_STREAM_H
#define NVCORE_STREAM_H
#include <nvcore/nvcore.h>
#include <nvcore/Debug.h>
namespace nv
{
/** Base stream class. */
class Stream {
public:
enum ByteOrder {
LittleEndian = false,
BigEndian = true,
};
/// Get the byte order of the system.
static ByteOrder getSystemByteOrder() {
# if NV_LITTLE_ENDIAN
return LittleEndian;
# else
return BigEndian;
# endif
}
/// Ctor.
Stream() : m_byteOrder(LittleEndian) { }
/// Virtual destructor.
virtual ~Stream() {}
/// Set byte order.
void setByteOrder(ByteOrder bo) { m_byteOrder = bo; }
/// Get byte order.
ByteOrder byteOrder() const { return m_byteOrder; }
/// Serialize the given data.
virtual void serialize( void * data, int len ) = 0;
/// Move to the given position in the archive.
virtual void seek( int pos ) = 0;
/// Return the current position in the archive.
virtual int tell() const = 0;
/// Return the current size of the archive.
virtual int size() const = 0;
/// Determine if there has been any error.
virtual bool isError() const = 0;
/// Return true if the stream is at the end.
virtual bool isAtEnd() const = 0;
/// Return true if the stream is seekable.
virtual bool isSeekable() const = 0;
/// Return true if this is an input stream.
virtual bool isLoading() const = 0;
/// Return true if this is an output stream.
virtual bool isSaving() const = 0;
// friends
friend Stream & operator<<( Stream & s, bool & c ) {
# if NV_OS_DARWIN
nvStaticCheck(sizeof(bool) == 4);
uint8 b = c ? 1 : 0;
s.serialize( &b, 1 );
c = (b == 1);
# else
nvStaticCheck(sizeof(bool) == 1);
s.serialize( &c, 1 );
# endif
return s;
}
friend Stream & operator<<( Stream & s, char & c ) {
nvStaticCheck(sizeof(char) == 1);
s.serialize( &c, 1 );
return s;
}
friend Stream & operator<<( Stream & s, uint8 & c ) {
nvStaticCheck(sizeof(uint8) == 1);
s.serialize( &c, 1 );
return s;
}
friend Stream & operator<<( Stream & s, int8 & c ) {
nvStaticCheck(sizeof(int8) == 1);
s.serialize( &c, 1 );
return s;
}
friend Stream & operator<<( Stream & s, uint16 & c ) {
nvStaticCheck(sizeof(uint16) == 2);
s.byteOrderSerialize( &c, 2 );
return s;
}
friend Stream & operator<<( Stream & s, int16 & c ) {
nvStaticCheck(sizeof(int16) == 2);
s.byteOrderSerialize( &c, 2 );
return s;
}
friend Stream & operator<<( Stream & s, uint32 & c ) {
nvStaticCheck(sizeof(uint32) == 4);
s.byteOrderSerialize( &c, 4 );
return s;
}
friend Stream & operator<<( Stream & s, int32 & c ) {
nvStaticCheck(sizeof(int32) == 4);
s.byteOrderSerialize( &c, 4 );
return s;
}
friend Stream & operator<<( Stream & s, uint64 & c ) {
nvStaticCheck(sizeof(uint64) == 8);
s.byteOrderSerialize( &c, 8 );
return s;
}
friend Stream & operator<<( Stream & s, int64 & c ) {
nvStaticCheck(sizeof(int64) == 8);
s.byteOrderSerialize( &c, 8 );
return s;
}
friend Stream & operator<<( Stream & s, float & c ) {
nvStaticCheck(sizeof(float) == 4);
s.byteOrderSerialize( &c, 4 );
return s;
}
friend Stream & operator<<( Stream & s, double & c ) {
nvStaticCheck(sizeof(double) == 8);
s.byteOrderSerialize( &c, 8 );
return s;
}
protected:
/** Serialize in the stream byte order. */
Stream & byteOrderSerialize( void * v, int len ) {
if( m_byteOrder == getSystemByteOrder() ) {
serialize( v, len );
}
else {
for( int i=len-1; i>=0; i-- ) {
serialize( (uint8 *)v + i, 1 );
}
}
return *this;
}
private:
ByteOrder m_byteOrder;
};
} // nv namespace
#endif // NV_STREAM_H

85
src/nvcore/TextReader.cpp Normal file
View File

@ -0,0 +1,85 @@
// This code is in the public domain -- castanyo@yahoo.es
#include <nvcore/TextReader.h>
using namespace nv;
/// Peek next character.
char TextReader::peek()
{
nvDebugCheck(m_stream != NULL);
nvDebugCheck(m_stream->isSeekable());
if (m_stream->isAtEnd()) {
return 0;
}
uint pos = m_stream->tell();
char c;
m_stream->serialize(&c, 1);
m_stream->seek(pos);
return c;
}
/// Read a single char.
char TextReader::read()
{
nvDebugCheck(m_stream != NULL);
if( m_stream->isAtEnd() ) {
return 0;
}
char c;
m_stream->serialize(&c, 1);
return c;
}
/// Read from the current location to the end of the stream.
const char * TextReader::readToEnd()
{
nvDebugCheck(m_stream != NULL);
const int size = m_stream->size();
m_text.clear();
m_text.reserve(size + 1);
m_text.resize(size);
m_stream->serialize(m_text.unsecureBuffer(), size);
m_text.pushBack('\0');
return m_text.buffer();
}
/// Read from the current location to the end of the line.
const char * TextReader::readLine()
{
m_text.clear();
if (m_stream->isAtEnd()) {
return NULL;
}
while (true) {
char c = read();
if (c == 0 || c == '\n') {
break;
}
else if (c == '\r') {
if( peek() == '\n' ) {
read();
}
break;
}
m_text.pushBack(c);
}
m_text.pushBack('\0');
return m_text.buffer();
}

38
src/nvcore/TextReader.h Normal file
View File

@ -0,0 +1,38 @@
// This code is in the public domain -- castanyo@yahoo.es
#ifndef NVCORE_TEXTREADER_H
#define NVCORE_TEXTREADER_H
#include <nvcore/nvcore.h>
#include <nvcore/Stream.h>
#include <nvcore/Containers.h>
namespace nv
{
/// Text reader.
class NVCORE_CLASS TextReader {
public:
/// Ctor.
TextReader(Stream * stream) : m_stream(stream), m_text(512) {
nvCheck(stream != NULL);
nvCheck(stream->isLoading());
}
char peek();
char read();
const char *readToEnd();
// Returns a temporary string.
const char * readLine();
private:
Stream * m_stream;
Array<char> m_text;
};
} // nv namespace
#endif // NVCORE_TEXTREADER_H

44
src/nvcore/TextWriter.h Normal file
View File

@ -0,0 +1,44 @@
// This code is in the public domain -- castanyo@yahoo.es
#ifndef NVCORE_TEXTWRITER_H
#define NVCORE_TEXTWRITER_H
#include <nvcore/nvcore.h>
#include <nvcore/Stream.h>
#include <nvcore/StrLib.h>
// @@ NOT IMPLEMENTED !!!
namespace nv
{
/// Text writer.
class NVCORE_CLASS TextWriter
{
public:
/// Ctor.
TextWriter(Stream * s) : s(s), str(1024) {
nvDebugCheck(s != NULL);
nvCheck(s->IsSaving());
}
void write( const char * str, uint len );
void write( const char * format, ... ) __attribute__((format (printf, 2, 3)));
void write( const char * format, va_list arg );
private:
Stream * s;
// Temporary string.
StringBuilder str;
};
} // nv namespace
#endif // NVCORE_TEXTWRITER_H

245
src/nvcore/Tokenizer.cpp Normal file
View File

@ -0,0 +1,245 @@
// This code is in the public domain -- castanyo@yahoo.es
#include <nvcore/Tokenizer.h>
#include <nvcore/StrLib.h>
#include <stdio.h> // vsscanf
#include <stdarg.h> // va_list
#include <stdlib.h> // atof, atoi
#if NV_CC_MSVC
/* vsscanf for Win32
* Written 5/2003 by <mgix@mgix.com>
* This code is in the Public Domain
*/
#include <malloc.h> // alloca
//#include <string.h>
static int vsscanf(const char * buffer, const char * format, va_list argPtr)
{
// Get an upper bound for the # of args
size_t count = 0;
const char *p = format;
while(1) {
char c = *(p++);
if(c==0) break;
if(c=='%' && (p[0]!='*' && p[0]!='%')) ++count;
}
// Make a local stack
size_t stackSize = (2+count)*sizeof(void*);
void **newStack = (void**)alloca(stackSize);
// Fill local stack the way sscanf likes it
newStack[0] = (void*)buffer;
newStack[1] = (void*)format;
memcpy(newStack+2, argPtr, count*sizeof(void*));
// @@ Use: CALL DWORD PTR [sscanf]
// Warp into system sscanf with new stack
int result;
void *savedESP;
__asm
{
mov savedESP, esp
mov esp, newStack
#if _MSC_VER >= 1400
call DWORD PTR [sscanf_s]
#else
call DWORD PTR [sscanf]
#endif
mov esp, savedESP
mov result, eax
}
return result;
}
/*
int hacky_vsscanf(const char *str, int count, const char *format, va_list ap) {
nvCheck(count < 8)
if (count == 0) {
}
void * arg0 = va_arg(ap, void *);
void * arg1 = va_arg(ap, void *);
void * arg2 = va_arg(ap, void *);
void * arg3 = va_arg(ap, void *);
void * arg4 = va_arg(ap, void *);
void * arg5 = va_arg(ap, void *);
void * arg6 = va_arg(ap, void *);
void * arg7 = va_arg(ap, void *);
return sscanf(str, format, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
}
*/
#endif
using namespace nv;
Token::Token() :
m_str(""), m_len(0)
{
}
Token::Token(const Token & token) :
m_str(token.m_str), m_len(token.m_len)
{
}
Token::Token(const char * str, int len) :
m_str(str), m_len(len)
{
}
bool Token::operator==(const char * str) const
{
return strncmp(m_str, str, m_len) == 0;
}
bool Token::operator!=(const char * str) const
{
return strncmp(m_str, str, m_len) != 0;
}
bool Token::isNull()
{
return m_len != 0;
}
float Token::toFloat() const
{
return float(atof(m_str));
}
int Token::toInt() const
{
return atoi(m_str);
}
uint Token::toUnsignedInt() const
{
// @@ TBD
return uint(atoi(m_str));
}
String Token::toString() const
{
return String(m_str, m_len);
}
bool Token::parse(const char * format, int count, ...) const
{
va_list arg;
va_start(arg, count);
int readCount = vsscanf(m_str, format, arg);
va_end(arg);
return readCount == count;
}
Tokenizer::Tokenizer(Stream * stream) :
m_reader(stream), m_lineNumber(0), m_columnNumber(0), m_delimiters("{}()="), m_spaces(" \t")
{
}
bool Tokenizer::nextLine(bool skipEmptyLines /*= true*/)
{
do {
if (!readLine()) {
return false;
}
}
while (!readToken() && skipEmptyLines);
return true;
}
bool Tokenizer::nextToken(bool skipEndOfLine /*= false*/)
{
if (!readToken()) {
if (!skipEndOfLine) {
return false;
}
else {
return nextLine(true);
}
}
return true;
}
bool Tokenizer::readToken()
{
skipSpaces();
const char * begin = m_line + m_columnNumber;
if (*begin == '\0') {
return false;
}
char c = readChar();
if (isDelimiter(c)) {
m_token = Token(begin, 1);
return true;
}
// @@ Add support for quoted tokens "", ''
int len = 0;
while (!isDelimiter(c) && !isSpace(c) && c != '\0') {
c = readChar();
len++;
}
m_columnNumber--;
m_token = Token(begin, len);
return true;
}
char Tokenizer::readChar()
{
return m_line[m_columnNumber++];
}
bool Tokenizer::readLine()
{
m_lineNumber++;
m_columnNumber = 0;
m_line = m_reader.readLine();
return m_line != NULL;
}
void Tokenizer::skipSpaces()
{
while (isSpace(readChar())) {}
m_columnNumber--;
}
bool Tokenizer::isSpace(char c)
{
uint i = 0;
while (m_spaces[i] != '\0') {
if (c == m_spaces[i]) {
return true;
}
i++;
}
return false;
}
bool Tokenizer::isDelimiter(char c)
{
uint i = 0;
while (m_delimiters[i] != '\0') {
if (c == m_delimiters[i]) {
return true;
}
i++;
}
return false;
}

95
src/nvcore/Tokenizer.h Normal file
View File

@ -0,0 +1,95 @@
// This code is in the public domain -- castanyo@yahoo.es
#ifndef NV_CORE_TOKENIZER_H
#define NV_CORE_TOKENIZER_H
#include <nvcore/nvcore.h>
#include <nvcore/Stream.h>
#include <nvcore/TextReader.h>
#include <nvcore/StrLib.h>
namespace nv
{
/// A token produced by the Tokenizer.
class NVCORE_CLASS Token
{
public:
Token();
Token(const Token & token);
Token(const char * str, int len);
bool operator==(const char * str) const;
bool operator!=(const char * str) const;
bool isNull();
float toFloat() const;
int toInt() const;
uint toUnsignedInt() const;
String toString() const;
bool parse(const char * format, int count, ...) const __attribute__((format (scanf, 2, 4)));
private:
const char * m_str;
int m_len;
};
/// Exception thrown by the tokenizer.
class TokenizerException
{
public:
TokenizerException(int line, int column) : m_line(line), m_column(column) {}
int line() const { return m_line; }
int column() const { return m_column; }
private:
int m_line;
int m_column;
};
/// A simple stream tokenizer.
class NVCORE_CLASS Tokenizer
{
public:
Tokenizer(Stream * stream);
bool nextLine(bool skipEmptyLines = true);
bool nextToken(bool skipEndOfLine = false);
const Token & token() const { return m_token; }
int lineNumber() const { return m_lineNumber; }
int columnNumber() const { return m_columnNumber; }
void setDelimiters(const char * str) { m_delimiters = str; }
const char * delimiters() const { return m_delimiters; }
void setSpaces(const char * str) { m_spaces = str; }
const char * spaces() const { return m_spaces; }
private:
char readChar();
bool readLine();
bool readToken();
void skipSpaces();
bool isSpace(char c);
bool isDelimiter(char c);
private:
TextReader m_reader;
const char * m_line;
Token m_token;
int m_lineNumber;
int m_columnNumber;
const char * m_delimiters;
const char * m_spaces;
};
} // nv namespace
#endif // NV_CORE_TOKENIZER_H

172
src/nvcore/nvcore.h Normal file
View File

@ -0,0 +1,172 @@
// This code is in the public domain -- castanyo@yahoo.es
#ifndef NV_CORE_H
#define NV_CORE_H
// cmake config
#include <nvconfig.h>
// Function linkage
#if NVCORE_SHARED
#ifdef NVCORE_EXPORTS
#define NVCORE_API DLL_EXPORT
#define NVCORE_CLASS DLL_EXPORT_CLASS
#else
#define NVCORE_API DLL_IMPORT
#define NVCORE_CLASS DLL_IMPORT
#endif
#else // NVCORE_SHARED
#define NVCORE_API
#define NVCORE_CLASS
#endif // NVCORE_SHARED
// Platform definitions
#include "poshlib/posh.h"
// OS:
// NV_OS_WIN32
// NV_OS_WIN64
// NV_OS_MINGW
// NV_OS_CYGWIN
// NV_OS_LINUX
// NV_OS_UNIX
// NV_OS_DARWIN
#define NV_OS_STRING POSH_OS_STRING
#if defined POSH_OS_LINUX
# define NV_OS_LINUX 1
# define NV_OS_UNIX 1
#elif defined POSH_OS_CYGWIN32
# define NV_OS_CYGWIN 1
#elif defined POSH_OS_MINGW
# define NV_OS_MINGW 1
# define NV_OS_WIN32 1
#elif defined POSH_OS_OSX
# define NV_OS_DARWIN 1
# define NV_OS_UNIX 1
#elif defined POSH_OS_UNIX
# define NV_OS_UNIX 1
#elif defined POSH_OS_WIN32
# define NV_OS_WIN32 1
#elif defined POSH_OS_WIN64
# define NV_OS_WIN64 1
#else
# error "Unsupported OS"
#endif
// CPUs:
// NV_CPU_X86
// NV_CPU_X86_64
// NV_CPU_PPC
#define NV_CPU_STRING POSH_CPU_STRING
#if defined POSH_CPU_X86_64
# define NV_CPU_X86_64 1
#elif defined POSH_CPU_X86
# define NV_CPU_X86 1
#elif defined POSH_CPU_PPC
# define NV_CPU_PPC 1
#else
# error "Unsupported CPU"
#endif
// Compiler:
// NV_CC_GNUC
// NV_CC_MSVC
// @@ NV_CC_MSVC6
// @@ NV_CC_MSVC7
// @@ NV_CC_MSVC8
#if defined POSH_COMPILER_GCC
# define NV_CC_GNUC 1
# define NV_CC_STRING "gcc"
#elif defined POSH_COMPILER_MSVC
# define NV_CC_MSVC 1
# define NV_CC_STRING "msvc"
#else
# error "Unsupported compiler"
#endif
// Endiannes:
#define NV_LITTLE_ENDIAN POSH_LITTLE_ENDIAN
#define NV_BIG_ENDIAN POSH_BIG_ENDIAN
#define NV_ENDIAN_STRING POSH_ENDIAN_STRING
// Version string:
#define NV_VERSION_STRING \
NV_OS_STRING "/" NV_CC_STRING "/" NV_CPU_STRING"/" \
NV_ENDIAN_STRING"-endian - " __DATE__ "-" __TIME__
/// Disable copy constructor and assignment operator.
/// @hideinitializer
#define NV_FORBID_COPY(C) \
private: \
C( const C & ); \
C &operator=( const C & );
/// Disable dynamic allocation on the heap.
/// See Prohibiting Heap-Based Objects in More Effective C++.
/// @hideinitializer
#define NV_FORBID_HEAPALLOC() \
private: \
static void *operator new(size_t size); \
static void *operator new[](size_t size);
// String concatenation macros.
#define NV_STRING_JOIN2(arg1, arg2) NV_DO_STRING_JOIN2(arg1, arg2)
#define NV_DO_STRING_JOIN2(arg1, arg2) arg1 ## arg2
#define NV_STRING_JOIN3(arg1, arg2, arg3) NV_DO_STRING_JOIN3(arg1, arg2, arg3)
#define NV_DO_STRING_JOIN3(arg1, arg2, arg3) arg1 ## arg2 ## arg3
// Startup initialization macro.
#define NV_AT_STARTUP(some_code) \
namespace { \
static struct NV_STRING_JOIN2(AtStartup_, __LINE__) { \
NV_STRING_JOIN2(AtStartup_, __LINE__)() { some_code; } \
} \
NV_STRING_JOIN3(AtStartup_, __LINE__, Instance); \
};
/// Indicate the compiler that the parameter is not used to suppress compier warnings.
/// @hideinitializer
#define NV_UNUSED(a) ((a)=(a))
/// Null index. @@ Move this somewhere else... This could have collisions with other definitions!
#define NIL uint(~0)
/// Null pointer.
#ifndef NULL
#define NULL 0
#endif
// Platform includes
#if NV_CC_MSVC
# if NV_OS_WIN32
# include "DefsVcWin32.h"
# else
# error "MSVC: Platform not supported"
# endif
#elif NV_CC_GNUC
# if NV_OS_LINUX
# include "DefsGnucLinux.h"
# elif NV_OS_DARWIN
# include "DefsGnucDarwin.h"
# elif NV_OS_MINGW
# include "DefsGnucWin32.h"
# elif NV_OS_CYGWIN
# error "GCC: Cygwin not supported"
# else
# error "GCC: Platform not supported"
# endif
#endif
#endif // NV_CORE_H

View File

@ -0,0 +1,14 @@
SET(POSHLIB_SRCS
posh.c
posh.h)
ADD_LIBRARY(posh STATIC ${POSHLIB_SRCS})
ADD_EXECUTABLE(archtest tests/arch/archtest.c)
TARGET_LINK_LIBRARIES(archtest posh)
#ADD_EXECUTABLE(linktest tests/linktest/linktest.cpp tests/linktest/testlib.cpp)
#TARGET_LINK_LIBRARIES(linktest posh)
ADD_TEST(POSHTEST archtest)

926
src/nvcore/poshlib/posh.c Normal file
View File

@ -0,0 +1,926 @@
/*
LICENSE:
Copyright (c) 2004, Brian Hook
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* 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.
* The names of this package'ss contributors contributors may not
be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
OWNER 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.
*/
/**
@file posh.c
@author Brian Hook
@date 2002
@brief Portable Open Source Harness primary source file
*/
#include "posh.h"
#if !defined FORCE_DOXYGEN
#if !defined POSH_NO_FLOAT
# define POSH_FLOAT_STRING "enabled"
#else
# define POSH_FLOAT_STRING "disabled"
#endif
#if defined POSH_64BIT_INTEGER
# define POSH_64BIT_INTEGER_STRING "yes"
#else
# define POSH_64BIT_INTEGER_STRING "no"
#endif
#if defined POSH_64BIT_POINTER
# define POSH_POINTER_STRING "64-bits"
#else
# define POSH_POINTER_STRING "32-bits"
#endif
#if defined POSH_LITTLE_ENDIAN
# define IS_BIG_ENDIAN 0
# define NATIVE16 POSH_LittleU16
# define NATIVE32 POSH_LittleU32
# define NATIVE64 POSH_LittleU64
# define FOREIGN16 POSH_BigU16
# define FOREIGN32 POSH_BigU32
# define FOREIGN64 POSH_BigU64
#else
# define IS_BIG_ENDIAN 1
# define NATIVE16 POSH_BigU16
# define NATIVE32 POSH_BigU32
# define NATIVE64 POSH_BigU64
# define FOREIGN16 POSH_LittleU16
# define FOREIGN32 POSH_LittleU32
# define FOREIGN64 POSH_LittleU64
#endif /* POSH_LITTLE_ENDIAN */
static
int
s_testBigEndian( void )
{
union
{
posh_byte_t c[ 4 ];
posh_u32_t i;
} u;
u.i= 1;
if ( u.c[ 0 ] == 1 )
{
return 0;
}
return 1;
}
static
const char *
s_testSerialization( void )
{
posh_byte_t serbuf[ 8 ];
posh_u16_t tmp16;
posh_u32_t tmp32;
/* 16-bit serialization */
POSH_WriteU16ToLittle( serbuf, 0xABCD );
if ( ( tmp16 = POSH_ReadU16FromLittle( serbuf ) ) != 0xABCD )
{
return "*ERROR: failed little-endian 16-bit serialization test";
}
POSH_WriteU16ToBig( serbuf, 0xABCD );
if ( ( tmp16 = POSH_ReadU16FromBig( serbuf ) ) != 0xABCD )
{
return "*ERROR: failed big-endian 16-bit serialization test";
}
/* 32-bit serialization */
POSH_WriteU32ToLittle( serbuf, 0xABCD1234L );
if ( ( tmp32 = POSH_ReadU32FromLittle( serbuf ) ) != 0xABCD1234 )
{
return "*ERROR: failed little-endian 32-bit serialization test";
}
POSH_WriteU32ToBig( serbuf, 0xABCD1234L );
if ( ( tmp32 = POSH_ReadU32FromBig( serbuf ) ) != 0xABCD1234 )
{
return "*ERROR: failed big-endian 32-bit serialization test";
}
#if defined POSH_64BIT_INTEGER
{
#define REF64 POSH_U64(0xFEDCBA9876543210)
posh_u64_t tmp64;
POSH_WriteU64ToLittle( serbuf, REF64 );
if ( ( tmp64 = POSH_ReadU64FromLittle( serbuf ) ) != REF64 )
{
return "*ERROR: failed little-endian 64-bit serialization test";
}
POSH_WriteU64ToBig( serbuf, REF64 );
if ( ( tmp64 = POSH_ReadU64FromBig( serbuf ) ) != REF64 )
{
return "*ERROR: failed big-endian 64-bit serialization test";
}
}
#endif
return 0;
}
#if !defined POSH_NO_FLOAT
static
const char *
s_testFloatingPoint( void )
{
float fRef = 10.0f/30.0f;
double dRef = 10.0/30.0;
posh_byte_t dbuf[ 8 ];
float fTmp;
double dTmp;
fTmp = POSH_FloatFromLittleBits( POSH_LittleFloatBits( fRef ) );
if ( fTmp != fRef )
{
return "*ERROR: POSH little endian floating point conversion failed. Please report this to poshlib@poshlib.org!\n";
}
fTmp = POSH_FloatFromBigBits( POSH_BigFloatBits( fRef ) );
if ( fTmp != fRef )
{
return "*ERROR: POSH big endian floating point conversion failed. Please report this to poshlib@poshlib.org!\n";
}
POSH_DoubleBits( dRef, dbuf );
dTmp = POSH_DoubleFromBits( dbuf );
if ( dTmp != dRef )
{
return "*ERROR: POSH double precision floating point serialization failed. Please report this to poshlib@poshlib.org!\n";
}
return 0;
}
#endif /* !defined POSH_NO_FLOAT */
static
const char *
s_testEndianess( void )
{
/* check endianess */
if ( s_testBigEndian() != IS_BIG_ENDIAN )
{
return "*ERROR: POSH compile time endianess does not match run-time endianess verification. Please report this to poshlib@poshlib.org!\n";
}
/* make sure our endian swap routines work */
if ( ( NATIVE32( 0x11223344L ) != 0x11223344L ) ||
( FOREIGN32( 0x11223344L ) != 0x44332211L ) ||
( NATIVE16( 0x1234 ) != 0x1234 ) ||
( FOREIGN16( 0x1234 ) != 0x3412 ) )
{
return "*ERROR: POSH endianess macro selection failed. Please report this to poshlib@poshlib.org!\n";
}
/* test serialization routines */
return 0;
}
#endif /* !defined FORCE_DOXYGEN */
/**
Returns a string describing this platform's basic attributes.
POSH_GetArchString() reports on an architecture's statically determined
attributes. In addition, it will perform run-time verification checks
to make sure the various platform specific functions work. If an error
occurs, please contact me at poshlib@poshlib.org so we can try to resolve
what the specific failure case is.
@returns a string describing this platform on success, or a string in the
form "*ERROR: [text]" on failure. You can simply check to see if
the first character returned is '*' to verify an error condition.
*/
const char *
POSH_GetArchString( void )
{
const char *err;
const char *s = "OS:.............."POSH_OS_STRING"\n"
"CPU:............."POSH_CPU_STRING"\n"
"endian:.........."POSH_ENDIAN_STRING"\n"
"ptr size:........"POSH_POINTER_STRING"\n"
"64-bit ints......"POSH_64BIT_INTEGER_STRING"\n"
"floating point..."POSH_FLOAT_STRING"\n"
"compiler........."POSH_COMPILER_STRING"\n";
/* test endianess */
err = s_testEndianess();
if ( err != 0 )
{
return err;
}
/* test serialization */
err = s_testSerialization();
if ( err != 0 )
{
return err;
}
#if !defined POSH_NO_FLOAT
/* check that our floating point support is correct */
err = s_testFloatingPoint();
if ( err != 0 )
{
return err;
}
#endif
return s;
}
/* ---------------------------------------------------------------------------*/
/* BYTE SWAPPING SUPPORT */
/* ---------------------------------------------------------------------------*/
/**
* Byte swaps a 16-bit unsigned value
*
@param v [in] unsigned 16-bit input value to swap
@returns a byte swapped version of v
*/
posh_u16_t
POSH_SwapU16( posh_u16_t v )
{
posh_u16_t swapped;
swapped = v << 8;
swapped |= v >> 8;
return swapped;
}
/**
* Byte swaps a 16-bit signed value
*
@param v [in] signed 16-bit input value to swap
@returns a byte swapped version of v
@remarks This just calls back to the unsigned version, since byte swapping
is independent of sign. However, we still provide this function to
avoid signed/unsigned mismatch compiler warnings.
*/
posh_i16_t
POSH_SwapI16( posh_i16_t v )
{
return ( posh_i16_t ) POSH_SwapU16( v );
}
/**
* Byte swaps a 32-bit unsigned value
*
@param v [in] unsigned 32-bit input value to swap
@returns a byte swapped version of v
*/
posh_u32_t
POSH_SwapU32( posh_u32_t v )
{
posh_u32_t swapped;
swapped = ( v & 0xFF ) << 24;
swapped |= ( v & 0xFF00 ) << 8;
swapped |= ( v >> 8 ) & 0xFF00;
swapped |= ( v >> 24 );
return swapped;
}
/**
* Byte swaps a 32-bit signed value
*
@param v [in] signed 32-bit input value to swap
@returns a byte swapped version of v
@remarks This just calls back to the unsigned version, since byte swapping
is independent of sign. However, we still provide this function to
avoid signed/unsigned mismatch compiler warnings.
*/
posh_i32_t
POSH_SwapI32( posh_i32_t v )
{
return ( posh_i32_t ) POSH_SwapU32( ( posh_u32_t ) v );
}
#if defined POSH_64BIT_INTEGER
/**
* Byte swaps a 64-bit unsigned value
@param v [in] a 64-bit input value to swap
@ingroup SixtyFourBit
@returns a byte swapped version of v
*/
posh_u64_t
POSH_SwapU64( posh_u64_t v )
{
posh_byte_t tmp;
union {
posh_byte_t bytes[ 8 ];
posh_u64_t u64;
} u;
u.u64 = v;
tmp = u.bytes[ 0 ]; u.bytes[ 0 ] = u.bytes[ 7 ]; u.bytes[ 7 ] = tmp;
tmp = u.bytes[ 1 ]; u.bytes[ 1 ] = u.bytes[ 6 ]; u.bytes[ 6 ] = tmp;
tmp = u.bytes[ 2 ]; u.bytes[ 2 ] = u.bytes[ 5 ]; u.bytes[ 5 ] = tmp;
tmp = u.bytes[ 3 ]; u.bytes[ 3 ] = u.bytes[ 4 ]; u.bytes[ 4 ] = tmp;
return u.u64;
}
/**
* Byte swaps a 64-bit signed value
@param v [in] a 64-bit input value to swap
@ingroup SixtyFourBit
@returns a byte swapped version of v
*/
posh_i64_t
POSH_SwapI64( posh_i64_t v )
{
return ( posh_i64_t ) POSH_SwapU64( ( posh_u64_t ) v );
}
#endif /* defined POSH_64BIT_INTEGER */
/* ---------------------------------------------------------------------------*/
/* IN-MEMORY SERIALIZATION */
/* ---------------------------------------------------------------------------*/
/**
* Writes an unsigned 16-bit value to a little endian buffer
@param dst [out] pointer to the destination buffer, may not be NULL
@param value [in] host-endian unsigned 16-bit value
@returns a pointer to the location two bytes after dst
@remarks does no validation of the inputs
*/
posh_u16_t *
POSH_WriteU16ToLittle( void *dst, posh_u16_t value )
{
posh_u16_t *p16 = ( posh_u16_t * ) dst;
*p16 = POSH_LittleU16(value);
return p16 + 1;
}
/**
* Writes a signed 16-bit value to a little endian buffer
@param dst [out] pointer to the destination buffer, may not be NULL
@param value [in] host-endian signed 16-bit value
@returns a pointer to the location two bytes after dst
@remarks does no validation of the inputs. This simply calls
POSH_WriteU16ToLittle() with appropriate casting.
*/
posh_i16_t *
POSH_WriteI16ToLittle( void *dst, posh_i16_t value )
{
return ( posh_i16_t * ) POSH_WriteU16ToLittle( dst, ( posh_u16_t ) value );
}
/**
* Writes an unsigned 32-bit value to a little endian buffer
@param dst [out] pointer to the destination buffer, may not be NULL
@param value [in] host-endian signed 32-bit value
@returns a pointer to the location four bytes after dst
@remarks does no validation of the inputs.
*/
posh_u32_t *
POSH_WriteU32ToLittle( void *dst, posh_u32_t value )
{
posh_u32_t *p32 = ( posh_u32_t * ) dst;
*p32 = POSH_LittleU32(value);
return p32 + 1;
}
/**
* Writes a signed 32-bit value to a little endian buffer
@param dst [out] pointer to the destination buffer, may not be NULL
@param value [in] host-endian signed 32-bit value
@returns a pointer to the location four bytes after dst
@remarks does no validation of the inputs. This simply calls
POSH_WriteU32ToLittle() with appropriate casting.
*/
posh_i32_t *
POSH_WriteI32ToLittle( void *dst, posh_i32_t value )
{
return ( posh_i32_t * ) POSH_WriteU32ToLittle( dst, ( posh_u32_t ) value );
}
/**
* Writes an unsigned 16-bit value to a big endian buffer
@param dst [out] pointer to the destination buffer, may not be NULL
@param value [in] host-endian unsigned 16-bit value
@returns a pointer to the location two bytes after dst
@remarks does no validation of the inputs
*/
posh_u16_t *
POSH_WriteU16ToBig( void *dst, posh_u16_t value )
{
posh_u16_t *p16 = ( posh_u16_t * ) dst;
*p16 = POSH_BigU16(value);
return p16 + 1;
}
/**
* Writes a signed 16-bit value to a big endian buffer
@param dst [out] pointer to the destination buffer, may not be NULL
@param value [in] host-endian signed 16-bit value
@returns a pointer to the location two bytes after dst
@remarks does no validation of the inputs. This simply calls
POSH_WriteU16ToLittle() with appropriate casting.
*/
posh_i16_t *
POSH_WriteI16ToBig( void *dst, posh_i16_t value )
{
return ( posh_i16_t * ) POSH_WriteU16ToBig( dst, ( posh_u16_t ) value );
}
/**
* Writes an unsigned 32-bit value to a big endian buffer
@param dst [out] pointer to the destination buffer, may not be NULL
@param value [in] host-endian unsigned 32-bit value
@returns a pointer to the location four bytes after dst
@remarks does no validation of the inputs.
*/
posh_u32_t *
POSH_WriteU32ToBig( void *dst, posh_u32_t value )
{
posh_u32_t *p32 = ( posh_u32_t * ) dst;
*p32 = POSH_BigU32(value);
return p32 + 1;
}
/**
* Writes a signed 32-bit value to a big endian buffer
@param dst [out] pointer to the destination buffer, may not be NULL
@param value [in] host-endian signed 32-bit value
@returns a pointer to the location four bytes after dst
@remarks does no validation of the inputs. This simply calls
POSH_WriteU32ToBig() with appropriate casting.
*/
posh_i32_t *
POSH_WriteI32ToBig( void *dst, posh_i32_t value )
{
return ( posh_i32_t * ) POSH_WriteU32ToBig( dst, ( posh_u32_t ) value );
}
#if defined POSH_64BIT_INTEGER
/**
* Writes an unsigned 64-bit value to a little-endian buffer
@ingroup SixtyFourBit
@param dst [out] pointer to the destination buffer, may not be NULL
@param value [in] host-endian unsigned 64-bit value
@returns a pointer to the location eight bytes after dst
@remarks does no validation of the inputs.
*/
posh_u64_t *
POSH_WriteU64ToLittle( void *dst, posh_u64_t value )
{
posh_u64_t *p64 = ( posh_u64_t * ) dst;
*p64 = POSH_LittleU64(value);
return p64 + 1;
}
/**
* Writes a signed 64-bit value to a little-endian buffer
@ingroup SixtyFourBit
@param dst [out] pointer to the destination buffer, may not be NULL
@param value [in] host-endian unsigned 64-bit value
@returns a pointer to the location eight bytes after dst
@remarks does no validation of the inputs.
*/
posh_i64_t *
POSH_WriteI64ToLittle( void *dst, posh_i64_t value )
{
return ( posh_i64_t * ) POSH_WriteU64ToLittle( dst, ( posh_u64_t ) value );
}
/**
* Writes an unsigned 64-bit value to a big-endian buffer
@ingroup SixtyFourBit
@param dst [out] pointer to the destination buffer, may not be NULL
@param value [in] host-endian unsigned 64-bit value
@returns a pointer to the location eight bytes after dst
@remarks does no validation of the inputs.
*/
posh_u64_t *
POSH_WriteU64ToBig( void *dst, posh_u64_t value )
{
posh_u64_t *p64 = ( posh_u64_t * ) dst;
*p64 = POSH_BigU64(value);
return p64 + 8;
}
/**
* Writes a signed 64-bit value to a big-endian buffer
@ingroup SixtyFourBit
@param dst [out] pointer to the destination buffer, may not be NULL
@param value [in] host-endian signed 64-bit value
@returns a pointer to the location eight bytes after dst
@remarks does no validation of the inputs.
*/
posh_i64_t *
POSH_WriteI64ToBig( void *dst, posh_i64_t value )
{
return ( posh_i64_t * ) POSH_WriteU64ToBig( dst, ( posh_u64_t ) value );
}
#endif /* POSH_64BIT_INTEGER */
/* ---------------------------------------------------------------------------*/
/* IN-MEMORY DESERIALIZATION */
/* ---------------------------------------------------------------------------*/
/**
* Reads an unsigned 16-bit value from a little-endian buffer
@param src [in] source buffer
@returns host-endian unsigned 16-bit value
*/
posh_u16_t
POSH_ReadU16FromLittle( const void *src )
{
return POSH_LittleU16( (*(const posh_u16_t*)src) );
}
/**
* Reads a signed 16-bit value from a little-endian buffer
@param src [in] source buffer
@returns host-endian signed 16-bit value
*/
posh_i16_t
POSH_ReadI16FromLittle( const void *src )
{
return POSH_LittleI16( (*(const posh_i16_t*)src) );
}
/**
* Reads an unsigned 32-bit value from a little-endian buffer
@param src [in] source buffer
@returns host-endian unsigned 32-bit value
*/
posh_u32_t
POSH_ReadU32FromLittle( const void *src )
{
return POSH_LittleU32( (*(const posh_u32_t*)src) );
}
/**
* Reads a signed 32-bit value from a little-endian buffer
@param src [in] source buffer
@returns host-endian signed 32-bit value
*/
posh_i32_t
POSH_ReadI32FromLittle( const void *src )
{
return POSH_LittleI32( (*(const posh_i32_t*)src) );
}
/**
* Reads an unsigned 16-bit value from a big-endian buffer
@param src [in] source buffer
@returns host-endian unsigned 16-bit value
*/
posh_u16_t
POSH_ReadU16FromBig( const void *src )
{
return POSH_BigU16( (*(const posh_u16_t*)src) );
}
/**
* Reads a signed 16-bit value from a big-endian buffer
@param src [in] source buffer
@returns host-endian signed 16-bit value
*/
posh_i16_t
POSH_ReadI16FromBig( const void *src )
{
return POSH_BigI16( (*(const posh_i16_t*)src));
}
/**
* Reads an unsigned 32-bit value from a big-endian buffer
@param src [in] source buffer
@returns host-endian unsigned 32-bit value
*/
posh_u32_t
POSH_ReadU32FromBig( const void *src )
{
return POSH_BigU32( (*(const posh_u32_t*)src) );
}
/**
* Reads a signed 32-bit value from a big-endian buffer
@param src [in] source buffer
@returns host-endian signed 32-bit value
*/
posh_i32_t
POSH_ReadI32FromBig( const void *src )
{
return POSH_BigI32( (*(const posh_i32_t*)src ) );
}
#if defined POSH_64BIT_INTEGER
/**
* Reads an unsigned 64-bit value from a little-endian buffer
@param src [in] source buffer
@returns host-endian unsigned 32-bit value
*/
posh_u64_t
POSH_ReadU64FromLittle( const void *src )
{
return POSH_LittleU64( (*(const posh_u64_t*)src) );
}
/**
* Reads a signed 64-bit value from a little-endian buffer
@param src [in] source buffer
@returns host-endian signed 32-bit value
*/
posh_i64_t
POSH_ReadI64FromLittle( const void *src )
{
return POSH_LittleI64( (*(const posh_i64_t*)src) );
}
/**
* Reads an unsigned 64-bit value from a big-endian buffer
@param src [in] source buffer
@returns host-endian unsigned 32-bit value
*/
posh_u64_t
POSH_ReadU64FromBig( const void *src )
{
return POSH_BigU64( (*(const posh_u64_t*)src) );
}
/**
* Reads an signed 64-bit value from a big-endian buffer
@param src [in] source buffer
@returns host-endian signed 32-bit value
*/
posh_i64_t
POSH_ReadI64FromBig( const void *src )
{
return POSH_BigI64( (*(const posh_i64_t*)src) );
}
#endif /* POSH_64BIT_INTEGER */
/* ---------------------------------------------------------------------------*/
/* FLOATING POINT SUPPORT */
/* ---------------------------------------------------------------------------*/
#if !defined POSH_NO_FLOAT
/** @ingroup FloatingPoint
@param[in] f floating point value
@returns a little-endian bit representation of f
*/
posh_u32_t
POSH_LittleFloatBits( float f )
{
union
{
float f32;
posh_u32_t u32;
} u;
u.f32 = f;
#if defined POSH_LITTLE_ENDIAN
return u.u32;
#else
return POSH_SwapU32( u.u32 );
#endif
}
/**
* Extracts raw big-endian bits from a 32-bit floating point value
*
@ingroup FloatingPoint
@param f [in] floating point value
@returns a big-endian bit representation of f
*/
posh_u32_t
POSH_BigFloatBits( float f )
{
union
{
float f32;
posh_u32_t u32;
} u;
u.f32 = f;
#if defined POSH_LITTLE_ENDIAN
return POSH_SwapU32( u.u32 );
#else
return u.u32;
#endif
}
/**
* Extracts raw, little-endian bit representation from a 64-bit double.
*
@param d [in] 64-bit double precision value
@param dst [out] 8-byte storage buffer
@ingroup FloatingPoint
@returns the raw bits used to represent the value 'd', in the form dst[0]=LSB
*/
void
POSH_DoubleBits( double d, posh_byte_t dst[ 8 ] )
{
union
{
double d64;
posh_byte_t bytes[ 8 ];
} u;
u.d64 = d;
#if defined POSH_LITTLE_ENDIAN
dst[ 0 ] = u.bytes[ 0 ];
dst[ 1 ] = u.bytes[ 1 ];
dst[ 2 ] = u.bytes[ 2 ];
dst[ 3 ] = u.bytes[ 3 ];
dst[ 4 ] = u.bytes[ 4 ];
dst[ 5 ] = u.bytes[ 5 ];
dst[ 6 ] = u.bytes[ 6 ];
dst[ 7 ] = u.bytes[ 7 ];
#else
dst[ 0 ] = u.bytes[ 7 ];
dst[ 1 ] = u.bytes[ 6 ];
dst[ 2 ] = u.bytes[ 5 ];
dst[ 3 ] = u.bytes[ 4 ];
dst[ 4 ] = u.bytes[ 3 ];
dst[ 5 ] = u.bytes[ 2 ];
dst[ 6 ] = u.bytes[ 1 ];
dst[ 7 ] = u.bytes[ 0 ];
#endif
}
/**
* Creates a double-precision, 64-bit floating point value from a set of raw,
* little-endian bits
@ingroup FloatingPoint
@param src [in] little-endian byte representation of 64-bit double precision
floating point value
@returns double precision floating point representation of the raw bits
@remarks No error checking is performed, so there are no guarantees that the
result is a valid number, nor is there any check to ensure that src is
non-NULL. BE CAREFUL USING THIS.
*/
double
POSH_DoubleFromBits( const posh_byte_t src[ 8 ] )
{
union
{
double d64;
posh_byte_t bytes[ 8 ];
} u;
#if defined POSH_LITTLE_ENDIAN
u.bytes[ 0 ] = src[ 0 ];
u.bytes[ 1 ] = src[ 1 ];
u.bytes[ 2 ] = src[ 2 ];
u.bytes[ 3 ] = src[ 3 ];
u.bytes[ 4 ] = src[ 4 ];
u.bytes[ 5 ] = src[ 5 ];
u.bytes[ 6 ] = src[ 6 ];
u.bytes[ 7 ] = src[ 7 ];
#else
u.bytes[ 0 ] = src[ 7 ];
u.bytes[ 1 ] = src[ 6 ];
u.bytes[ 2 ] = src[ 5 ];
u.bytes[ 3 ] = src[ 4 ];
u.bytes[ 4 ] = src[ 3 ];
u.bytes[ 5 ] = src[ 2 ];
u.bytes[ 6 ] = src[ 1 ];
u.bytes[ 7 ] = src[ 0 ];
#endif
return u.d64;
}
/**
* Creates a floating point number from little endian bits
*
@ingroup FloatingPoint
@param bits [in] raw floating point bits in little-endian form
@returns a floating point number based on the given bit representation
@remarks No error checking is performed, so there are no guarantees that the
result is a valid number. BE CAREFUL USING THIS.
*/
float
POSH_FloatFromLittleBits( posh_u32_t bits )
{
union
{
float f32;
posh_u32_t u32;
} u;
u.u32 = bits;
#if defined POSH_BIG_ENDIAN
u.u32 = POSH_SwapU32( u.u32 );
#endif
return u.f32;
}
/**
* Creates a floating point number from big-endian bits
*
@ingroup FloatingPoint
@param bits [in] raw floating point bits in big-endian form
@returns a floating point number based on the given bit representation
@remarks No error checking is performed, so there are no guarantees that the
result is a valid number. BE CAREFUL USING THIS.
*/
float
POSH_FloatFromBigBits( posh_u32_t bits )
{
union
{
float f32;
posh_u32_t u32;
} u;
u.u32 = bits;
#if defined POSH_LITTLE_ENDIAN
u.u32 = POSH_SwapU32( u.u32 );
#endif
return u.f32;
}
#endif /* !defined POSH_NO_FLOAT */

989
src/nvcore/poshlib/posh.h Normal file
View File

@ -0,0 +1,989 @@
/**
@file posh.h
@author Brian Hook
Header file for POSH, the Portable Open Source Harness project.
NOTE: Unlike most header files, this one is designed to be included
multiple times, which is why it does not have the @#ifndef/@#define
preamble.
POSH relies on environment specified preprocessor symbols in order
to infer as much as possible about the target OS/architecture and
the host compiler capabilities.
NOTE: POSH is simple and focused. It attempts to provide basic
functionality and information, but it does NOT attempt to emulate
missing functionality. I am also not willing to make POSH dirty
and hackish to support truly ancient and/or outmoded and/or bizarre
technologies such as non-ANSI compilers, systems with non-IEEE
floating point formats, segmented 16-bit operating systems, etc.
Please refer to the accompanying HTML documentation or visit
http://www.poshlib.org for more information on how to use POSH.
LICENSE:
Copyright (c) 2004, Brian Hook
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* 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.
* The names of this package'ss contributors contributors may not
be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
OWNER 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.
*/
/*
I have yet to find an authoritative reference on preprocessor
symbols, but so far this is what I've gleaned:
GNU GCC/G++:
- __GNUC__: GNU C version
- __GNUG__: GNU C++ compiler
- __sun__ : on Sun platforms
- __svr4__: on Solaris and other SysV R4 platforms
- __mips__: on MIPS processor platforms
- __sparc_v9__: on Sparc 64-bit CPUs
- __sparcv9: 64-bit Solaris
- __MIPSEL__: mips processor, compiled for little endian
- __MIPSEB__: mips processor, compiled for big endian
- _R5900: MIPS/Sony/Toshiba R5900 (PS2)
- mc68000: 68K
- m68000: 68K
- m68k: 68K
- __palmos__: PalmOS
Intel C/C++ Compiler:
- __ECC : compiler version, IA64 only
- __EDG__
- __ELF__
- __GXX_ABI_VERSION
- __i386 : IA-32 only
- __i386__ : IA-32 only
- i386 : IA-32 only
- __ia64 : IA-64 only
- __ia64__ : IA-64 only
- ia64 : IA-64 only
- __ICC : IA-32 only
- __INTEL_COMPILER : IA-32 or IA-64, newer versions only
Apple's C/C++ Compiler for OS X:
- __APPLE_CC__
- __APPLE__
- __BIG_ENDIAN__
- __APPLE__
- __ppc__
- __MACH__
DJGPP:
- __MSDOS__
- __unix__
- __unix
- __GNUC__
- __GO32
- DJGPP
- __i386, __i386, i386
Cray's C compiler:
- _ADDR64: if 64-bit pointers
- _UNICOS:
- __unix:
SGI's CC compiler predefines the following (and more) with -ansi:
- __sgi
- __unix
- __host_mips
- _SYSTYPE_SVR4
- __mips
- _MIPSEB
- anyone know if there is a predefined symbol for the compiler?!
MinGW:
- as GnuC but also defines _WIN32, __WIN32, WIN32, _X86_, __i386, __i386__, and several others
- __MINGW32__
Cygwin:
- as Gnu C, but also
- __unix__
- __CYGWIN32__
Microsoft Visual Studio predefines the following:
- _MSC_VER
- _WIN32: on Win32
- _M_IX6 (on x86 systems)
- _M_ALPHA (on DEC AXP systems)
- _SH3: WinCE, Hitachi SH-3
- _MIPS: WinCE, MIPS
- _ARM: WinCE, ARM
Sun's C Compiler:
- sun and _sun
- unix and _unix
- sparc and _sparc (SPARC systems only)
- i386 and _i386 (x86 systems only)
- __SVR4 (Solaris only)
- __sparcv9: 64-bit solaris
- __SUNPRO_C
- _LP64: defined in 64-bit LP64 mode, but only if <sys/types.h> is included
Borland C/C++ predefines the following:
- __BORLANDC__:
DEC/Compaq C/C++ on Alpha:
- __alpha
- __arch64__
- __unix__ (on Tru64 Unix)
- __osf__
- __DECC
- __DECCXX (C++ compilation)
- __DECC_VER
- __DECCXX_VER
IBM's AIX compiler:
- __64BIT__ if 64-bit mode
- _AIX
- __IBMC__: C compiler version
- __IBMCPP__: C++ compiler version
- _LONG_LONG: compiler allows long long
Watcom:
- __WATCOMC__
- __DOS__ : if targeting DOS
- __386__ : if 32-bit support
- __WIN32__ : if targetin 32-bit Windows
HP-UX C/C++ Compiler:
- __hpux
- __unix
- __hppa (on PA-RISC)
- __LP64__: if compiled in 64-bit mode
Metrowerks:
- __MWERKS__
- __powerpc__
- _powerc
- __MC68K__
- macintosh when compiling for MacOS
- __INTEL__ for x86 targets
- __POWERPC__
*/
#ifndef HAVE_POSH_H
#define HAVE_POSH_H
/*
** ----------------------------------------------------------------------------
** Include <limits.h> optionally
** ----------------------------------------------------------------------------
*/
#ifdef POSH_USE_LIMITS_H
# include <limits.h>
#endif
/*
** ----------------------------------------------------------------------------
** Determine compilation environment
** ----------------------------------------------------------------------------
*/
#if defined __ECC || defined __ICC || defined __INTEL_COMPILER
# define POSH_COMPILER_STRING "Intel C/C++"
# define POSH_COMPILER_INTEL 1
#endif
#if ( defined __host_mips || defined __sgi ) && !defined __GNUC__
# define POSH_COMPILER_STRING "MIPSpro C/C++"
# define POSH_COMPILER_MIPSPRO 1
#endif
#if defined __hpux && !defined __GNUC__
# define POSH_COMPILER_STRING "HP-UX CC"
# define POSH_COMPILER_HPCC 1
#endif
#if defined __GNUC__
# define POSH_COMPILER_STRING "Gnu GCC"
# define POSH_COMPILER_GCC 1
#endif
#if defined __APPLE_CC__
/* we don't define the compiler string here, let it be GNU */
# define POSH_COMPILER_APPLECC 1
#endif
#if defined __IBMC__ || defined __IBMCPP__
# define POSH_COMPILER_STRING "IBM C/C++"
# define POSH_COMPILER_IBM 1
#endif
#if defined _MSC_VER
# define POSH_COMPILER_STRING "Microsoft Visual C++"
# define POSH_COMPILER_MSVC 1
#endif
#if defined __SUNPRO_C
# define POSH_COMPILER_STRING "Sun Pro"
# define POSH_COMPILER_SUN 1
#endif
#if defined __BORLANDC__
# define POSH_COMPILER_STRING "Borland C/C++"
# define POSH_COMPILER_BORLAND 1
#endif
#if defined __MWERKS__
# define POSH_COMPILER_STRING "MetroWerks CodeWarrior"
# define POSH_COMPILER_METROWERKS 1
#endif
#if defined __DECC || defined __DECCXX
# define POSH_COMPILER_STRING "Compaq/DEC C/C++"
# define POSH_COMPILER_DEC 1
#endif
#if defined __WATCOMC__
# define POSH_COMPILER_STRING "Watcom C/C++"
# define POSH_COMPILER_WATCOM 1
#endif
#if !defined POSH_COMPILER_STRING
# define POSH_COMPILER_STRING "Unknown compiler"
#endif
/*
** ----------------------------------------------------------------------------
** Determine target operating system
** ----------------------------------------------------------------------------
*/
#if defined linux || defined __linux__
# define POSH_OS_LINUX 1
# define POSH_OS_STRING "Linux"
#endif
#if defined __CYGWIN32__
# define POSH_OS_CYGWIN32 1
# define POSH_OS_STRING "Cygwin"
#endif
#if defined __MINGW32__
# define POSH_OS_MINGW 1
# define POSH_OS_STRING "MinGW"
#endif
#if defined GO32 && defined DJGPP && defined __MSDOS__
# define POSH_OS_GO32 1
# define POSH_OS_STRING "GO32/MS-DOS"
#endif
/* NOTE: make sure you use /bt=DOS if compiling for 32-bit DOS,
otherwise Watcom assumes host=target */
#if defined __WATCOMC__ && defined __386__ && defined __DOS__
# define POSH_OS_DOS32 1
# define POSH_OS_STRING "DOS/32-bit"
#endif
#if defined _UNICOS
# define POSH_OS_UNICOS 1
# define POSH_OS_STRING "UNICOS"
#endif
#if ( defined __MWERKS__ && defined __powerc && !defined macintosh ) || defined __APPLE_CC__ || defined macosx
# define POSH_OS_OSX 1
# define POSH_OS_STRING "MacOS X"
#endif
#if defined __sun__ || defined sun || defined __sun || defined __solaris__
# if defined __SVR4 || defined __svr4__ || defined __solaris__
# define POSH_OS_STRING "Solaris"
# define POSH_OS_SOLARIS 1
# endif
# if !defined POSH_OS_STRING
# define POSH_OS_STRING "SunOS"
# define POSH_OS_SUNOS 1
# endif
#endif
#if defined __sgi__ || defined sgi || defined __sgi
# define POSH_OS_IRIX 1
# define POSH_OS_STRING "Irix"
#endif
#if defined __hpux__ || defined __hpux
# define POSH_OS_HPUX 1
# define POSH_OS_STRING "HP-UX"
#endif
#if defined _AIX
# define POSH_OS_AIX 1
# define POSH_OS_STRING "AIX"
#endif
#if ( defined __alpha && defined __osf__ )
# define POSH_OS_TRU64 1
# define POSH_OS_STRING "Tru64"
#endif
#if defined __BEOS__ || defined __beos__
# define POSH_OS_BEOS 1
# define POSH_OS_STRING "BeOS"
#endif
#if defined amiga || defined amigados || defined AMIGA || defined _AMIGA
# define POSH_OS_AMIGA 1
# define POSH_OS_STRING "Amiga"
#endif
#if defined __unix__
# define POSH_OS_UNIX 1
# if !defined POSH_OS_STRING
# define POSH_OS_STRING "Unix-like(generic)"
# endif
#endif
#if defined _WIN32_WCE
# define POSH_OS_WINCE 1
# define POSH_OS_STRING "Windows CE"
#endif
#if defined _XBOX_VER == 200
# define POSH_OS_XBOX360 1
# define POSH_OS_STRING "XBOX-360"
#elif defined _XBOX
# define POSH_OS_XBOX 1
# define POSH_OS_STRING "XBOX"
#endif
#if defined _WIN32 || defined WIN32 || defined __NT__ || defined __WIN32__
# define POSH_OS_WIN32 1
# if !defined POSH_OS_XBOX
# if defined _WIN64
# define POSH_OS_WIN64 1
# define POSH_OS_STRING "Win64"
# else
# if !defined POSH_OS_STRING
# define POSH_OS_STRING "Win32"
# endif
# endif
# endif
#endif
#if defined __palmos__
# define POSH_OS_PALM 1
# define POSH_OS_STRING "PalmOS"
#endif
#if defined THINK_C || defined macintosh
# define POSH_OS_MACOS 1
# define POSH_OS_STRING "MacOS"
#endif
/*
** -----------------------------------------------------------------------------
** Determine target CPU
** -----------------------------------------------------------------------------
*/
#if defined mc68000 || defined m68k || defined __MC68K__ || defined m68000
# define POSH_CPU_68K 1
# define POSH_CPU_STRING "MC68000"
#endif
#if defined __PPC__ || defined __POWERPC__ || defined powerpc || defined _POWER || defined __ppc__ || defined __powerpc__
# define POSH_CPU_PPC 1
# if defined __powerpc64__
# define POSH_CPU_STRING "PowerPC64"
# else
# define POSH_CPU_STRING "PowerPC"
# endif
#endif
#if defined _CRAYT3E || defined _CRAYMPP
# define POSH_CPU_CRAYT3E 1 /* target processor is a DEC Alpha 21164 used in a Cray T3E*/
# define POSH_CPU_STRING "Cray T3E (Alpha 21164)"
#endif
#if defined CRAY || defined _CRAY && !defined _CRAYT3E
# error Non-AXP Cray systems not supported
#endif
#if defined _SH3
# define POSH_CPU_SH3 1
# define POSH_CPU_STRING "Hitachi SH-3"
#endif
#if defined __sh4__ || defined __SH4__
# define POSH_CPU_SH3 1
# define POSH_CPU_SH4 1
# define POSH_CPU_STRING "Hitachi SH-4"
#endif
#if defined __sparc__ || defined __sparc
# if defined __arch64__ || defined __sparcv9 || defined __sparc_v9__
# define POSH_CPU_SPARC64 1
# define POSH_CPU_STRING "Sparc/64"
# else
# define POSH_CPU_STRING "Sparc/32"
# endif
# define POSH_CPU_SPARC 1
#endif
#if defined ARM || defined __arm__ || defined _ARM
# define POSH_CPU_STRONGARM 1
# define POSH_CPU_STRING "ARM"
#endif
#if defined mips || defined __mips__ || defined __MIPS__ || defined _MIPS
# define POSH_CPU_MIPS 1
# if defined _R5900
# define POSH_CPU_STRING "MIPS R5900 (PS2)"
# else
# define POSH_CPU_STRING "MIPS"
# endif
#endif
#if defined __ia64 || defined _M_IA64 || defined __ia64__
# define POSH_CPU_IA64 1
# define POSH_CPU_STRING "IA64"
#endif
#if defined __X86__ || defined __i386__ || defined i386 || defined _M_IX86 || defined __386__ || defined __x86_64__ || defined _M_X64
# define POSH_CPU_X86 1
# if defined __x86_64__ || defined _M_X64
# define POSH_CPU_X86_64 1
# endif
# if defined POSH_CPU_X86_64
# define POSH_CPU_STRING "AMD x86-64"
# else
# define POSH_CPU_STRING "Intel 386+"
# endif
#endif
#if defined __alpha || defined alpha || defined _M_ALPHA || defined __alpha__
# define POSH_CPU_AXP 1
# define POSH_CPU_STRING "AXP"
#endif
#if defined __hppa || defined hppa
# define POSH_CPU_HPPA 1
# define POSH_CPU_STRING "PA-RISC"
#endif
#if !defined POSH_CPU_STRING
# error POSH cannot determine target CPU
# define POSH_CPU_STRING "Unknown" /* this is here for Doxygen's benefit */
#endif
/*
** -----------------------------------------------------------------------------
** Attempt to autodetect building for embedded on Sony PS2
** -----------------------------------------------------------------------------
*/
#if !defined POSH_OS_STRING
# if !defined FORCE_DOXYGEN
# define POSH_OS_EMBEDDED 1
# endif
# if defined _R5900
# define POSH_OS_STRING "Sony PS2(embedded)"
# else
# define POSH_OS_STRING "Embedded/Unknown"
# endif
#endif
/*
** ---------------------------------------------------------------------------
** Handle cdecl, stdcall, fastcall, etc.
** ---------------------------------------------------------------------------
*/
#if defined POSH_CPU_X86 && !defined POSH_CPU_X86_64
# if defined __GNUC__
# define POSH_CDECL __attribute__((cdecl))
# define POSH_STDCALL __attribute__((stdcall))
# define POSH_FASTCALL __attribute__((fastcall))
# elif ( defined _MSC_VER || defined __WATCOMC__ || defined __BORLANDC__ || defined __MWERKS__ )
# define POSH_CDECL __cdecl
# define POSH_STDCALL __stdcall
# define POSH_FASTCALL __fastcall
# endif
#else
# define POSH_CDECL
# define POSH_STDCALL
# define POSH_FASTCALL
#endif
/*
** ---------------------------------------------------------------------------
** Define POSH_IMPORTEXPORT signature based on POSH_DLL and POSH_BUILDING_LIB
** ---------------------------------------------------------------------------
*/
/*
** We undefine this so that multiple inclusions will work
*/
#if defined POSH_IMPORTEXPORT
# undef POSH_IMPORTEXPORT
#endif
#if defined POSH_DLL
# if defined POSH_OS_WIN32
# if defined _MSC_VER
# if ( _MSC_VER >= 800 )
# if defined POSH_BUILDING_LIB
# define POSH_IMPORTEXPORT __declspec( dllexport )
# else
# define POSH_IMPORTEXPORT __declspec( dllimport )
# endif
# else
# if defined POSH_BUILDING_LIB
# define POSH_IMPORTEXPORT __export
# else
# define POSH_IMPORTEXPORT
# endif
# endif
# endif /* defined _MSC_VER */
# if defined __BORLANDC__
# if ( __BORLANDC__ >= 0x500 )
# if defined POSH_BUILDING_LIB
# define POSH_IMPORTEXPORT __declspec( dllexport )
# else
# define POSH_IMPORTEXPORT __declspec( dllimport )
# endif
# else
# if defined POSH_BUILDING_LIB
# define POSH_IMPORTEXPORT __export
# else
# define POSH_IMPORTEXPORT
# endif
# endif
# endif /* defined __BORLANDC__ */
/* for all other compilers, we're just making a blanket assumption */
# if defined __GNUC__ || defined __WATCOMC__ || defined __MWERKS__
# if defined POSH_BUILDING_LIB
# define POSH_IMPORTEXPORT __declspec( dllexport )
# else
# define POSH_IMPORTEXPORT __declspec( dllimport )
# endif
# endif /* all other compilers */
# if !defined POSH_IMPORTEXPORT
# error Building DLLs not supported on this compiler (poshlib@poshlib.org if you know how)
# endif
# endif /* defined POSH_OS_WIN32 */
#endif
/* On pretty much everything else, we can thankfully just ignore this */
#if !defined POSH_IMPORTEXPORT
# define POSH_IMPORTEXPORT
#endif
#if defined FORCE_DOXYGEN
# define POSH_DLL
# define POSH_BUILDING_LIB
# undef POSH_DLL
# undef POSH_BUILDING_LIB
#endif
/*
** ----------------------------------------------------------------------------
** (Re)define POSH_PUBLIC_API export signature
** ----------------------------------------------------------------------------
*/
#ifdef POSH_PUBLIC_API
# undef POSH_PUBLIC_API
#endif
#if ( ( defined _MSC_VER ) && ( _MSC_VER < 800 ) ) || ( defined __BORLANDC__ && ( __BORLANDC__ < 0x500 ) )
# define POSH_PUBLIC_API(rtype) extern rtype POSH_IMPORTEXPORT
#else
# define POSH_PUBLIC_API(rtype) extern POSH_IMPORTEXPORT rtype
#endif
/*
** ----------------------------------------------------------------------------
** Try to infer endianess. Basically we just go through the CPUs we know are
** little endian, and assume anything that isn't one of those is big endian.
** As a sanity check, we also do this with operating systems we know are
** little endian, such as Windows. Some processors are bi-endian, such as
** the MIPS series, so we have to be careful about those.
** ----------------------------------------------------------------------------
*/
#if defined POSH_CPU_X86 || defined POSH_CPU_AXP || defined POSH_CPU_STRONGARM || defined POSH_OS_WIN32 || defined POSH_OS_WINCE || defined __MIPSEL__
# define POSH_ENDIAN_STRING "little"
# define POSH_LITTLE_ENDIAN 1
#else
# define POSH_ENDIAN_STRING "big"
# define POSH_BIG_ENDIAN 1
#endif
#if defined FORCE_DOXYGEN
# define POSH_LITTLE_ENDIAN
#endif
/*
** ----------------------------------------------------------------------------
** Cross-platform compile time assertion macro
** ----------------------------------------------------------------------------
*/
#define POSH_COMPILE_TIME_ASSERT(name, x) typedef int _POSH_dummy_ ## name[(x) ? 1 : -1 ]
/*
** ----------------------------------------------------------------------------
** 64-bit Integer
**
** We don't require 64-bit support, nor do we emulate its functionality, we
** simply export it if it's available. Since we can't count on <limits.h>
** for 64-bit support, we ignore the POSH_USE_LIMITS_H directive.
** ----------------------------------------------------------------------------
*/
#if defined ( __LP64__ ) || defined ( __powerpc64__ ) || defined POSH_CPU_SPARC64
# define POSH_64BIT_INTEGER 1
typedef long posh_i64_t;
typedef unsigned long posh_u64_t;
# define POSH_I64( x ) ((posh_i64_t)x)
# define POSH_U64( x ) ((posh_u64_t)x)
# define POSH_I64_PRINTF_PREFIX "l"
#elif defined _MSC_VER || defined __BORLANDC__ || defined __WATCOMC__ || ( defined __alpha && defined __DECC )
# define POSH_64BIT_INTEGER 1
typedef __int64 posh_i64_t;
typedef unsigned __int64 posh_u64_t;
# define POSH_I64( x ) ((posh_i64_t)x)
# define POSH_U64( x ) ((posh_u64_t)x)
# define POSH_I64_PRINTF_PREFIX "I64"
#elif defined __GNUC__ || defined __MWERKS__ || defined __SUNPRO_C || defined __SUNPRO_CC || defined __APPLE_CC__ || defined POSH_OS_IRIX || defined _LONG_LONG || defined _CRAYC
# define POSH_64BIT_INTEGER 1
typedef long long posh_i64_t;
typedef unsigned long long posh_u64_t;
# define POSH_U64( x ) ((posh_u64_t)(x##LL))
# define POSH_I64( x ) ((posh_i64_t)(x##LL))
# define POSH_I64_PRINTF_PREFIX "ll"
#endif
/* hack */
#ifdef __MINGW32__
# undef POSH_I64
# undef POSH_U64
# undef POSH_I64_PRINTF_PREFIX
# define POSH_U64( x ) ((posh_u64_t)(x##LL))
# define POSH_I64( x ) ((posh_i64_t)(x##LL))
# define POSH_I64_PRINTF_PREFIX "I64"
#endif
#ifdef FORCE_DOXYGEN
typedef long long posh_i64_t;
typedef unsigned long posh_u64_t;
# define POSH_64BIT_INTEGER
# define POSH_I64_PRINTF_PREFIX
# define POSH_I64(x)
# define POSH_U64(x)
#endif
/** Minimum value for a 64-bit signed integer */
#define POSH_I64_MIN POSH_I64(0x8000000000000000)
/** Maximum value for a 64-bit signed integer */
#define POSH_I64_MAX POSH_I64(0x7FFFFFFFFFFFFFFF)
/** Minimum value for a 64-bit unsigned integer */
#define POSH_U64_MIN POSH_U64(0)
/** Maximum value for a 64-bit unsigned integer */
#define POSH_U64_MAX POSH_U64(0xFFFFFFFFFFFFFFFF)
/* ----------------------------------------------------------------------------
** Basic Sized Types
**
** These types are expected to be EXACTLY sized so you can use them for
** serialization.
** ----------------------------------------------------------------------------
*/
#define POSH_FALSE 0
#define POSH_TRUE 1
typedef int posh_bool_t;
typedef unsigned char posh_byte_t;
/* NOTE: These assume that CHAR_BIT is 8!! */
typedef unsigned char posh_u8_t;
typedef signed char posh_i8_t;
#if defined POSH_USE_LIMITS_H
# if CHAR_BITS > 8
# error This machine uses 9-bit characters. This is a warning, you can comment this out now.
# endif /* CHAR_BITS > 8 */
/* 16-bit */
# if ( USHRT_MAX == 65535 )
typedef unsigned short posh_u16_t;
typedef short posh_i16_t;
# else
/* Yes, in theory there could still be a 16-bit character type and shorts are
32-bits in size...if you find such an architecture, let me know =P */
# error No 16-bit type found
# endif
/* 32-bit */
# if ( INT_MAX == 2147483647 )
typedef unsigned posh_u32_t;
typedef int posh_i32_t;
# elif ( LONG_MAX == 2147483647 )
typedef unsigned long posh_u32_t;
typedef long posh_i32_t;
# else
error No 32-bit type found
# endif
#else /* POSH_USE_LIMITS_H */
typedef unsigned short posh_u16_t;
typedef short posh_i16_t;
# if !defined POSH_OS_PALM
typedef unsigned posh_u32_t;
typedef int posh_i32_t;
# else
typedef unsigned long posh_u32_t;
typedef long posh_i32_t;
# endif
#endif
/** Minimum value for a byte */
#define POSH_BYTE_MIN 0
/** Maximum value for an 8-bit unsigned value */
#define POSH_BYTE_MAX 255
/** Minimum value for a byte */
#define POSH_I16_MIN ( ( posh_i16_t ) 0x8000 )
/** Maximum value for a 16-bit signed value */
#define POSH_I16_MAX ( ( posh_i16_t ) 0x7FFF )
/** Minimum value for a 16-bit unsigned value */
#define POSH_U16_MIN 0
/** Maximum value for a 16-bit unsigned value */
#define POSH_U16_MAX ( ( posh_u16_t ) 0xFFFF )
/** Minimum value for a 32-bit signed value */
#define POSH_I32_MIN ( ( posh_i32_t ) 0x80000000 )
/** Maximum value for a 32-bit signed value */
#define POSH_I32_MAX ( ( posh_i32_t ) 0x7FFFFFFF )
/** Minimum value for a 32-bit unsigned value */
#define POSH_U32_MIN 0
/** Maximum value for a 32-bit unsigned value */
#define POSH_U32_MAX ( ( posh_u32_t ) 0xFFFFFFFF )
/*
** ----------------------------------------------------------------------------
** Sanity checks on expected sizes
** ----------------------------------------------------------------------------
*/
#if !defined FORCE_DOXYGEN
POSH_COMPILE_TIME_ASSERT(posh_byte_t, sizeof(posh_byte_t) == 1);
POSH_COMPILE_TIME_ASSERT(posh_u8_t, sizeof(posh_u8_t) == 1);
POSH_COMPILE_TIME_ASSERT(posh_i8_t, sizeof(posh_i8_t) == 1);
POSH_COMPILE_TIME_ASSERT(posh_u16_t, sizeof(posh_u16_t) == 2);
POSH_COMPILE_TIME_ASSERT(posh_i16_t, sizeof(posh_i16_t) == 2);
POSH_COMPILE_TIME_ASSERT(posh_u32_t, sizeof(posh_u32_t) == 4);
POSH_COMPILE_TIME_ASSERT(posh_i32_t, sizeof(posh_i32_t) == 4);
#if !defined POSH_NO_FLOAT
POSH_COMPILE_TIME_ASSERT(posh_testfloat_t, sizeof(float)==4 );
POSH_COMPILE_TIME_ASSERT(posh_testdouble_t, sizeof(double)==8);
#endif
#if defined POSH_64BIT_INTEGER
POSH_COMPILE_TIME_ASSERT(posh_u64_t, sizeof(posh_u64_t) == 8);
POSH_COMPILE_TIME_ASSERT(posh_i64_t, sizeof(posh_i64_t) == 8);
#endif
#endif
/*
** ----------------------------------------------------------------------------
** 64-bit pointer support
** ----------------------------------------------------------------------------
*/
#if defined POSH_CPU_AXP && ( defined POSH_OS_TRU64 || defined POSH_OS_LINUX )
# define POSH_64BIT_POINTER 1
#endif
#if defined POSH_CPU_X86_64 && defined POSH_OS_LINUX
# define POSH_64BIT_POINTER 1
#endif
#if defined POSH_CPU_SPARC64 || defined POSH_OS_WIN64 || defined __64BIT__ || defined __LP64 || defined _LP64 || defined __LP64__ || defined _ADDR64 || defined _CRAYC
# define POSH_64BIT_POINTER 1
#endif
#if defined POSH_64BIT_POINTER
POSH_COMPILE_TIME_ASSERT( posh_64bit_pointer, sizeof( void * ) == 8 );
#elif !defined FORCE_DOXYGEN
/* if this assertion is hit then you're on a system that either has 64-bit
addressing and we didn't catch it, or you're on a system with 16-bit
pointers. In the latter case, POSH doesn't actually care, we're just
triggering this assertion to make sure you're aware of the situation,
so feel free to delete it.
If this assertion is triggered on a known 32 or 64-bit platform,
please let us know (poshlib@poshlib.org) */
POSH_COMPILE_TIME_ASSERT( posh_32bit_pointer, sizeof( void * ) == 4 );
#endif
#if defined FORCE_DOXYGEN
# define POSH_64BIT_POINTER
#endif
/*
** ----------------------------------------------------------------------------
** POSH Utility Functions
**
** These are optional POSH utility functions that are not required if you don't
** need anything except static checking of your host and target environment.
**
** These functions are NOT wrapped with POSH_PUBLIC_API because I didn't want
** to enforce their export if your own library is only using them internally.
** ----------------------------------------------------------------------------
*/
#ifdef __cplusplus
extern "C" {
#endif
const char *POSH_GetArchString( void );
#if !defined POSH_NO_FLOAT
posh_u32_t POSH_LittleFloatBits( float f );
posh_u32_t POSH_BigFloatBits( float f );
float POSH_FloatFromLittleBits( posh_u32_t bits );
float POSH_FloatFromBigBits( posh_u32_t bits );
void POSH_DoubleBits( double d, posh_byte_t dst[ 8 ] );
double POSH_DoubleFromBits( const posh_byte_t src[ 8 ] );
/* unimplemented
float *POSH_WriteFloatToLittle( void *dst, float f );
float *POSH_WriteFloatToBig( void *dst, float f );
float POSH_ReadFloatFromLittle( const void *src );
float POSH_ReadFloatFromBig( const void *src );
double *POSH_WriteDoubleToLittle( void *dst, double d );
double *POSH_WriteDoubleToBig( void *dst, double d );
double POSH_ReadDoubleFromLittle( const void *src );
double POSH_ReadDoubleFromBig( const void *src );
*/
#endif /* !defined POSH_NO_FLOAT */
#if defined FORCE_DOXYGEN
# define POSH_NO_FLOAT
# undef POSH_NO_FLOAT
#endif
extern posh_u16_t POSH_SwapU16( posh_u16_t u );
extern posh_i16_t POSH_SwapI16( posh_i16_t u );
extern posh_u32_t POSH_SwapU32( posh_u32_t u );
extern posh_i32_t POSH_SwapI32( posh_i32_t u );
#if defined POSH_64BIT_INTEGER
extern posh_u64_t POSH_SwapU64( posh_u64_t u );
extern posh_i64_t POSH_SwapI64( posh_i64_t u );
#endif /*POSH_64BIT_INTEGER */
extern posh_u16_t *POSH_WriteU16ToLittle( void *dst, posh_u16_t value );
extern posh_i16_t *POSH_WriteI16ToLittle( void *dst, posh_i16_t value );
extern posh_u32_t *POSH_WriteU32ToLittle( void *dst, posh_u32_t value );
extern posh_i32_t *POSH_WriteI32ToLittle( void *dst, posh_i32_t value );
extern posh_u16_t *POSH_WriteU16ToBig( void *dst, posh_u16_t value );
extern posh_i16_t *POSH_WriteI16ToBig( void *dst, posh_i16_t value );
extern posh_u32_t *POSH_WriteU32ToBig( void *dst, posh_u32_t value );
extern posh_i32_t *POSH_WriteI32ToBig( void *dst, posh_i32_t value );
extern posh_u16_t POSH_ReadU16FromLittle( const void *src );
extern posh_i16_t POSH_ReadI16FromLittle( const void *src );
extern posh_u32_t POSH_ReadU32FromLittle( const void *src );
extern posh_i32_t POSH_ReadI32FromLittle( const void *src );
extern posh_u16_t POSH_ReadU16FromBig( const void *src );
extern posh_i16_t POSH_ReadI16FromBig( const void *src );
extern posh_u32_t POSH_ReadU32FromBig( const void *src );
extern posh_i32_t POSH_ReadI32FromBig( const void *src );
#if defined POSH_64BIT_INTEGER
extern posh_u64_t *POSH_WriteU64ToLittle( void *dst, posh_u64_t value );
extern posh_i64_t *POSH_WriteI64ToLittle( void *dst, posh_i64_t value );
extern posh_u64_t *POSH_WriteU64ToBig( void *dst, posh_u64_t value );
extern posh_i64_t *POSH_WriteI64ToBig( void *dst, posh_i64_t value );
extern posh_u64_t POSH_ReadU64FromLittle( const void *src );
extern posh_i64_t POSH_ReadI64FromLittle( const void *src );
extern posh_u64_t POSH_ReadU64FromBig( const void *src );
extern posh_i64_t POSH_ReadI64FromBig( const void *src );
#endif /* POSH_64BIT_INTEGER */
#if defined POSH_LITTLE_ENDIAN
# define POSH_LittleU16(x) (x)
# define POSH_LittleU32(x) (x)
# define POSH_LittleI16(x) (x)
# define POSH_LittleI32(x) (x)
# if defined POSH_64BIT_INTEGER
# define POSH_LittleU64(x) (x)
# define POSH_LittleI64(x) (x)
# endif /* defined POSH_64BIT_INTEGER */
# define POSH_BigU16(x) POSH_SwapU16(x)
# define POSH_BigU32(x) POSH_SwapU32(x)
# define POSH_BigI16(x) POSH_SwapI16(x)
# define POSH_BigI32(x) POSH_SwapI32(x)
# if defined POSH_64BIT_INTEGER
# define POSH_BigU64(x) POSH_SwapU64(x)
# define POSH_BigI64(x) POSH_SwapI64(x)
# endif /* defined POSH_64BIT_INTEGER */
#else
# define POSH_BigU16(x) (x)
# define POSH_BigU32(x) (x)
# define POSH_BigI16(x) (x)
# define POSH_BigI32(x) (x)
# if defined POSH_64BIT_INTEGER
# define POSH_BigU64(x) (x)
# define POSH_BigI64(x) (x)
# endif /* POSH_64BIT_INTEGER */
# define POSH_LittleU16(x) POSH_SwapU16(x)
# define POSH_LittleU32(x) POSH_SwapU32(x)
# define POSH_LittleI16(x) POSH_SwapI16(x)
# define POSH_LittleI32(x) POSH_SwapI32(x)
# if defined POSH_64BIT_INTEGER
# define POSH_LittleU64(x) POSH_SwapU64(x)
# define POSH_LittleI64(x) POSH_SwapI64(x)
# endif /* POSH_64BIT_INTEGER */
#endif
#ifdef __cplusplus
}
#endif
#endif /* HAVE_POSH_H */

View File

@ -0,0 +1,29 @@
#include "../../posh.c"
#include <stdio.h>
int main( void )
{
printf( "archtest:\n" );
printf( "--------\n" );
printf( "%s", POSH_GetArchString() );
printf( "byte min: %d\n", POSH_BYTE_MIN );
printf( "byte max: %d\n", POSH_BYTE_MAX );
printf( "i16 min: %d\n", POSH_I16_MIN );
printf( "i16 max: %d\n", POSH_I16_MAX );
printf( "i32 min: %d\n", POSH_I32_MIN );
printf( "i32 max: %d\n", POSH_I32_MAX );
printf( "u16 min: %u\n", POSH_U16_MIN );
printf( "u16 max: %u\n", POSH_U16_MAX );
printf( "u32 min: %u\n", POSH_U32_MIN );
printf( "u32 max: %u\n", POSH_U32_MAX );
#ifdef POSH_64BIT_INTEGER
printf( "i64 min: %"POSH_I64_PRINTF_PREFIX"d\n", POSH_I64_MIN );
printf( "i64 max: %"POSH_I64_PRINTF_PREFIX"d\n", POSH_I64_MAX );
printf( "u64 min: %"POSH_I64_PRINTF_PREFIX"u\n", POSH_U64_MIN );
printf( "u64 max: %"POSH_I64_PRINTF_PREFIX"u\n", POSH_U64_MAX );
#endif
return 0;
}

View File

@ -0,0 +1,23 @@
#include "testlib.hpp"
#include "testdll.h"
#include <stdio.h>
int main( void )
{
printf( "linktest:\n" );
printf( "---------\n" );
printf( "linktest is a simple verification test that tests:\n" );
printf( " * correct linkage between C and C++\n" );
printf( " * proper handling when multiple libs use posh\n" );
printf( " * correct handling of DLL vs. LIB linkage (Windows)\n" );
printf( "\n\n" );
printf( "POSH_GetArchString() reporting:\n%s\n\n", POSH_GetArchString() );
TestLib_Foo();
TestDLL_Foo();
printf( "\n\nlinktest succeeded!\n" );
return 0;
}

View File

@ -0,0 +1,20 @@
#ifndef TESTDLL_H
#define TESTDLL_H
#define POSH_DLL 1 //define this since poshtestdll is a DLL
#include "../../posh.h"
#undef POSH_DLL //undefine so that another include of posh.h doesn't cause problems
#define TESTDLL_PUBLIC_API POSH_PUBLIC_API
#if defined __cplusplus
extern "C" {
#endif
TESTDLL_PUBLIC_API(void) TestDLL_Foo( void );
#if defined __cplusplus
}
#endif
#endif /* TESTDLL_H */

View File

@ -0,0 +1,11 @@
#define POSH_BUILDING_LIB 1
#include "testlib.hpp"
#include <stdio.h>
void TestLib_Foo( void )
{
printf( "...TestLib_Foo called successfully!\n" );
}

View File

@ -0,0 +1,19 @@
#ifndef TESTLIB_HPP
#define TESTLIB_HPP
#undef POSH_DLL
#include "../../posh.h"
#define TESTLIB_PUBLIC_API POSH_PUBLIC_API
#if defined __cplusplus && defined POSH_DLL
extern "C" {
#endif
TESTLIB_PUBLIC_API(void) TestLib_Foo( void );
#if defined __cplusplus && defined POSH_DLL
}
#endif
#endif /* POSHTESTLIB_H */