Import all sources from perforce.
This commit is contained in:
168
src/nvcore/BitArray.h
Normal file
168
src/nvcore/BitArray.h
Normal 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
36
src/nvcore/CMakeLists.txt
Normal 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
1054
src/nvcore/Containers.h
Normal file
File diff suppressed because it is too large
Load Diff
456
src/nvcore/Debug.cpp
Normal file
456
src/nvcore/Debug.cpp
Normal 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
129
src/nvcore/Debug.h
Normal 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
|
66
src/nvcore/DefsGnucDarwin.h
Normal file
66
src/nvcore/DefsGnucDarwin.h
Normal 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;
|
63
src/nvcore/DefsGnucLinux.h
Normal file
63
src/nvcore/DefsGnucLinux.h
Normal 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;
|
58
src/nvcore/DefsGnucWin32.h
Normal file
58
src/nvcore/DefsGnucWin32.h
Normal 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
94
src/nvcore/DefsVcWin32.h
Normal 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
34
src/nvcore/Memory.cpp
Normal 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
186
src/nvcore/Memory.h
Normal 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 Apple’s
|
||||
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
24
src/nvcore/Prefetch.h
Normal 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
420
src/nvcore/Ptr.h
Normal 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
429
src/nvcore/Radix.cpp
Normal 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
69
src/nvcore/Radix.h
Normal 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
336
src/nvcore/StdStream.h
Normal 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
632
src/nvcore/StrLib.cpp
Normal 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
348
src/nvcore/StrLib.h
Normal 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
165
src/nvcore/Stream.h
Normal 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
85
src/nvcore/TextReader.cpp
Normal 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
38
src/nvcore/TextReader.h
Normal 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
44
src/nvcore/TextWriter.h
Normal 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
245
src/nvcore/Tokenizer.cpp
Normal 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
95
src/nvcore/Tokenizer.h
Normal 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
172
src/nvcore/nvcore.h
Normal 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
|
14
src/nvcore/poshlib/CMakeLists.txt
Normal file
14
src/nvcore/poshlib/CMakeLists.txt
Normal 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
926
src/nvcore/poshlib/posh.c
Normal 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
989
src/nvcore/poshlib/posh.h
Normal 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 */
|
29
src/nvcore/poshlib/tests/arch/archtest.c
Normal file
29
src/nvcore/poshlib/tests/arch/archtest.c
Normal 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;
|
||||
}
|
23
src/nvcore/poshlib/tests/linktest/linktest.cpp
Normal file
23
src/nvcore/poshlib/tests/linktest/linktest.cpp
Normal 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;
|
||||
}
|
20
src/nvcore/poshlib/tests/linktest/testdll.h
Normal file
20
src/nvcore/poshlib/tests/linktest/testdll.h
Normal 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 */
|
11
src/nvcore/poshlib/tests/linktest/testlib.cpp
Normal file
11
src/nvcore/poshlib/tests/linktest/testlib.cpp
Normal 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" );
|
||||
}
|
||||
|
||||
|
19
src/nvcore/poshlib/tests/linktest/testlib.hpp
Normal file
19
src/nvcore/poshlib/tests/linktest/testlib.hpp
Normal 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 */
|
Reference in New Issue
Block a user