Merge changes from the witness.
This commit is contained in:
@ -96,8 +96,11 @@ namespace nv
|
||||
/// Get vector pointer.
|
||||
NV_FORCEINLINE T * buffer() { return m_buffer; }
|
||||
|
||||
/// Provide begin/end pointers for C++11 range-based for loops.
|
||||
NV_FORCEINLINE T * begin() { return m_buffer; }
|
||||
NV_FORCEINLINE T * end() { return m_buffer + m_size; }
|
||||
NV_FORCEINLINE const T * begin() const { return m_buffer; }
|
||||
NV_FORCEINLINE const T * end() const { return m_buffer + m_size; }
|
||||
|
||||
/// Is vector empty.
|
||||
NV_FORCEINLINE bool isEmpty() const { return m_size == 0; }
|
||||
@ -106,6 +109,7 @@ namespace nv
|
||||
NV_FORCEINLINE bool isNull() const { return m_buffer == NULL; }
|
||||
|
||||
|
||||
T & append();
|
||||
void push_back( const T & val );
|
||||
void pushBack( const T & val );
|
||||
Array<T> & append( const T & val );
|
||||
|
@ -16,6 +16,18 @@
|
||||
|
||||
namespace nv
|
||||
{
|
||||
template <typename T>
|
||||
NV_FORCEINLINE T & Array<T>::append()
|
||||
{
|
||||
uint old_size = m_size;
|
||||
uint new_size = m_size + 1;
|
||||
|
||||
setArraySize(new_size);
|
||||
|
||||
construct_range(m_buffer, new_size, old_size);
|
||||
|
||||
return m_buffer[old_size]; // Return reference to last element.
|
||||
}
|
||||
|
||||
// Push an element at the end of the vector.
|
||||
template <typename T>
|
||||
@ -211,7 +223,7 @@ namespace nv
|
||||
void Array<T>::replaceWithLast(uint index)
|
||||
{
|
||||
nvDebugCheck( index < m_size );
|
||||
nv::swap(m_buffer[index], back());
|
||||
nv::swap(m_buffer[index], back()); // @@ Is this OK when index == size-1?
|
||||
(m_buffer+m_size-1)->~T();
|
||||
m_size--;
|
||||
}
|
||||
|
@ -66,6 +66,10 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if NV_OS_ORBIS
|
||||
#include <libdbg.h>
|
||||
#endif
|
||||
|
||||
#define NV_USE_SEPARATE_THREAD 1
|
||||
|
||||
|
||||
@ -263,7 +267,7 @@ namespace
|
||||
}
|
||||
|
||||
/*static NV_NOINLINE int backtrace(void * trace[], int maxcount) {
|
||||
|
||||
|
||||
// In Windows XP and Windows Server 2003, the sum of the FramesToSkip and FramesToCapture parameters must be less than 63.
|
||||
int xp_maxcount = min(63-1, maxcount);
|
||||
|
||||
@ -274,7 +278,7 @@ namespace
|
||||
}*/
|
||||
|
||||
static NV_NOINLINE int backtraceWithSymbols(CONTEXT * ctx, void * trace[], int maxcount, int skip = 0) {
|
||||
|
||||
|
||||
// Init the stack frame for this function
|
||||
STACKFRAME64 stackFrame = { 0 };
|
||||
|
||||
@ -344,74 +348,74 @@ namespace
|
||||
StringBuilder builder(512);
|
||||
|
||||
HANDLE hProcess = GetCurrentProcess();
|
||||
|
||||
// Resolve PC to function names
|
||||
for (int i = start; i < size; i++)
|
||||
{
|
||||
// Check for end of stack walk
|
||||
DWORD64 ip = (DWORD64)trace[i];
|
||||
if (ip == NULL)
|
||||
break;
|
||||
|
||||
// Resolve PC to function names
|
||||
for (int i = start; i < size; i++)
|
||||
{
|
||||
// Check for end of stack walk
|
||||
DWORD64 ip = (DWORD64)trace[i];
|
||||
if (ip == NULL)
|
||||
break;
|
||||
|
||||
// Get function name
|
||||
#define MAX_STRING_LEN (512)
|
||||
unsigned char byBuffer[sizeof(IMAGEHLP_SYMBOL64) + MAX_STRING_LEN] = { 0 };
|
||||
IMAGEHLP_SYMBOL64 * pSymbol = (IMAGEHLP_SYMBOL64*)byBuffer;
|
||||
pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
|
||||
pSymbol->MaxNameLength = MAX_STRING_LEN;
|
||||
// Get function name
|
||||
#define MAX_STRING_LEN (512)
|
||||
unsigned char byBuffer[sizeof(IMAGEHLP_SYMBOL64) + MAX_STRING_LEN] = { 0 };
|
||||
IMAGEHLP_SYMBOL64 * pSymbol = (IMAGEHLP_SYMBOL64*)byBuffer;
|
||||
pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
|
||||
pSymbol->MaxNameLength = MAX_STRING_LEN;
|
||||
|
||||
DWORD64 dwDisplacement;
|
||||
|
||||
if (SymGetSymFromAddr64(hProcess, ip, &dwDisplacement, pSymbol))
|
||||
{
|
||||
pSymbol->Name[MAX_STRING_LEN-1] = 0;
|
||||
|
||||
/*
|
||||
// Make the symbol readable for humans
|
||||
UnDecorateSymbolName( pSym->Name, lpszNonUnicodeUnDSymbol, BUFFERSIZE,
|
||||
UNDNAME_COMPLETE |
|
||||
UNDNAME_NO_THISTYPE |
|
||||
UNDNAME_NO_SPECIAL_SYMS |
|
||||
UNDNAME_NO_MEMBER_TYPE |
|
||||
UNDNAME_NO_MS_KEYWORDS |
|
||||
UNDNAME_NO_ACCESS_SPECIFIERS );
|
||||
*/
|
||||
|
||||
// pSymbol->Name
|
||||
const char * pFunc = pSymbol->Name;
|
||||
|
||||
// Get file/line number
|
||||
IMAGEHLP_LINE64 theLine = { 0 };
|
||||
theLine.SizeOfStruct = sizeof(theLine);
|
||||
DWORD64 dwDisplacement;
|
||||
|
||||
if (SymGetSymFromAddr64(hProcess, ip, &dwDisplacement, pSymbol))
|
||||
{
|
||||
pSymbol->Name[MAX_STRING_LEN-1] = 0;
|
||||
|
||||
/*
|
||||
// Make the symbol readable for humans
|
||||
UnDecorateSymbolName( pSym->Name, lpszNonUnicodeUnDSymbol, BUFFERSIZE,
|
||||
UNDNAME_COMPLETE |
|
||||
UNDNAME_NO_THISTYPE |
|
||||
UNDNAME_NO_SPECIAL_SYMS |
|
||||
UNDNAME_NO_MEMBER_TYPE |
|
||||
UNDNAME_NO_MS_KEYWORDS |
|
||||
UNDNAME_NO_ACCESS_SPECIFIERS );
|
||||
*/
|
||||
|
||||
// pSymbol->Name
|
||||
const char * pFunc = pSymbol->Name;
|
||||
|
||||
DWORD dwDisplacement;
|
||||
if (!SymGetLineFromAddr64(hProcess, ip, &dwDisplacement, &theLine))
|
||||
{
|
||||
// Get file/line number
|
||||
IMAGEHLP_LINE64 theLine = { 0 };
|
||||
theLine.SizeOfStruct = sizeof(theLine);
|
||||
|
||||
DWORD dwDisplacement;
|
||||
if (!SymGetLineFromAddr64(hProcess, ip, &dwDisplacement, &theLine))
|
||||
{
|
||||
// Do not print unknown symbols anymore.
|
||||
break;
|
||||
//builder.format("unknown(%08X) : %s\n", (uint32)ip, pFunc);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
const char* pFile = strrchr(theLine.FileName, '\\');
|
||||
if ( pFile == NULL ) pFile = theLine.FileName;
|
||||
else pFile++;
|
||||
*/
|
||||
const char * pFile = theLine.FileName;
|
||||
|
||||
int line = theLine.LineNumber;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
const char* pFile = strrchr(theLine.FileName, '\\');
|
||||
if ( pFile == NULL ) pFile = theLine.FileName;
|
||||
else pFile++;
|
||||
*/
|
||||
const char * pFile = theLine.FileName;
|
||||
|
||||
int line = theLine.LineNumber;
|
||||
|
||||
builder.format("%s(%d) : %s\n", pFile, line, pFunc);
|
||||
}
|
||||
}
|
||||
|
||||
lines.append(builder.release());
|
||||
|
||||
if (pFunc != NULL && strcmp(pFunc, "WinMain") == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -479,41 +483,36 @@ namespace
|
||||
TerminateProcess(GetCurrentProcess(), EXIT_FAILURE + 8);
|
||||
}
|
||||
|
||||
static void handleInvalidParameter(const wchar_t * expresion, const wchar_t * function, const wchar_t * file, unsigned int line, uintptr_t reserved) {
|
||||
static void handleInvalidParameter(const wchar_t * wexpresion, const wchar_t * wfunction, const wchar_t * wfile, unsigned int line, uintptr_t reserved) {
|
||||
|
||||
size_t convertedCharCount = 0;
|
||||
StringBuilder tmp;
|
||||
|
||||
if (expresion != NULL) {
|
||||
uint size = toU32(wcslen(expresion) + 1);
|
||||
tmp.reserve(size);
|
||||
wcstombs_s(&convertedCharCount, tmp.str(), size, expresion, _TRUNCATE);
|
||||
|
||||
nvDebug("*** Invalid parameter: %s\n", tmp.str());
|
||||
|
||||
if (file != NULL) {
|
||||
size = toU32(wcslen(file) + 1);
|
||||
tmp.reserve(size);
|
||||
wcstombs_s(&convertedCharCount, tmp.str(), size, file, _TRUNCATE);
|
||||
|
||||
nvDebug(" On file: %s\n", tmp.str());
|
||||
|
||||
if (function != NULL) {
|
||||
size = toU32(wcslen(function) + 1);
|
||||
tmp.reserve(size);
|
||||
wcstombs_s(&convertedCharCount, tmp.str(), size, function, _TRUNCATE);
|
||||
|
||||
nvDebug(" On function: %s\n", tmp.str());
|
||||
}
|
||||
|
||||
nvDebug(" On line: %u\n", line);
|
||||
}
|
||||
|
||||
StringBuilder expresion;
|
||||
if (wexpresion != NULL) {
|
||||
uint size = U32(wcslen(wexpresion) + 1);
|
||||
expresion.reserve(size);
|
||||
wcstombs_s(&convertedCharCount, expresion.str(), size, wexpresion, _TRUNCATE);
|
||||
}
|
||||
|
||||
nvDebugBreak();
|
||||
TerminateProcess(GetCurrentProcess(), EXIT_FAILURE + 8);
|
||||
}
|
||||
StringBuilder file;
|
||||
if (wfile != NULL) {
|
||||
uint size = U32(wcslen(wfile) + 1);
|
||||
file.reserve(size);
|
||||
wcstombs_s(&convertedCharCount, file.str(), size, wfile, _TRUNCATE);
|
||||
}
|
||||
|
||||
StringBuilder function;
|
||||
if (wfunction != NULL) {
|
||||
uint size = U32(wcslen(wfunction) + 1);
|
||||
function.reserve(size);
|
||||
wcstombs_s(&convertedCharCount, function.str(), size, wfunction, _TRUNCATE);
|
||||
}
|
||||
|
||||
int result = nvAbort(expresion.str(), file.str(), line, function.str());
|
||||
if (result == NV_ABORT_DEBUG) {
|
||||
nvDebugBreak();
|
||||
}
|
||||
}
|
||||
|
||||
#elif !NV_OS_WIN32 && defined(HAVE_SIGNAL_H) // NV_OS_LINUX || NV_OS_DARWIN
|
||||
|
||||
@ -770,7 +769,7 @@ namespace
|
||||
|
||||
if (s_interactive) {
|
||||
flushMessageQueue();
|
||||
int action = MessageBoxA(NULL, error_string.str(), "Assertion failed", MB_ABORTRETRYIGNORE|MB_ICONERROR);
|
||||
int action = MessageBoxA(NULL, error_string.str(), "Assertion failed", MB_ABORTRETRYIGNORE | MB_ICONERROR | MB_TOPMOST);
|
||||
switch( action ) {
|
||||
case IDRETRY:
|
||||
ret = NV_ABORT_DEBUG;
|
||||
@ -851,11 +850,10 @@ namespace
|
||||
printStackTrace(trace, size, 2);
|
||||
}*/
|
||||
|
||||
//SBtodoORBIS check for debugger present
|
||||
//if (debug::isDebuggerPresent())
|
||||
nvDebugBreak();
|
||||
if (debug::isDebuggerPresent())
|
||||
return NV_ABORT_DEBUG;
|
||||
|
||||
return NV_ABORT_DEBUG;
|
||||
return NV_ABORT_IGNORE;
|
||||
}
|
||||
};
|
||||
|
||||
@ -892,9 +890,9 @@ namespace
|
||||
#endif
|
||||
|
||||
if( ret == NV_ABORT_EXIT ) {
|
||||
// Exit cleanly.
|
||||
exit(EXIT_FAILURE + 1);
|
||||
}
|
||||
// Exit cleanly.
|
||||
exit(EXIT_FAILURE + 1);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -1190,6 +1188,12 @@ bool debug::isDebuggerPresent()
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
#elif NV_OS_ORBIS
|
||||
#if PS4_FINAL_REQUIREMENTS
|
||||
return false;
|
||||
#else
|
||||
return sceDbgIsDebuggerAttached() == 1;
|
||||
#endif
|
||||
#elif NV_OS_DARWIN
|
||||
int mib[4];
|
||||
struct kinfo_proc info;
|
||||
|
@ -34,7 +34,9 @@
|
||||
# if NV_CC_MSVC
|
||||
// @@ Does this work in msvc-6 and earlier?
|
||||
# define nvDebugBreak() __debugbreak()
|
||||
//#define nvDebugBreak() __asm { int 3 }
|
||||
//# define nvDebugBreak() __asm { int 3 }
|
||||
# elif NV_OS_ORBIS
|
||||
# define nvDebugBreak() __debugbreak()
|
||||
# elif NV_CC_GNUC
|
||||
# define nvDebugBreak() __builtin_trap()
|
||||
# else
|
||||
@ -158,7 +160,7 @@
|
||||
#endif
|
||||
|
||||
|
||||
NVCORE_API int nvAbort(const char *exp, const char *file, int line, const char * func = NULL, const char * msg = NULL, ...);
|
||||
NVCORE_API int nvAbort(const char *exp, const char *file, int line, const char * func = NULL, const char * msg = NULL, ...) __attribute__((format (printf, 5, 6)));
|
||||
NVCORE_API void NV_CDECL nvDebugPrint( const char *msg, ... ) __attribute__((format (printf, 1, 2)));
|
||||
|
||||
namespace nv
|
||||
|
@ -8,24 +8,30 @@
|
||||
// Function linkage
|
||||
#define DLL_IMPORT
|
||||
#if __GNUC__ >= 4
|
||||
# define DLL_EXPORT __attribute__((visibility("default")))
|
||||
# define DLL_EXPORT_CLASS DLL_EXPORT
|
||||
# define DLL_EXPORT __attribute__((visibility("default")))
|
||||
# define DLL_EXPORT_CLASS DLL_EXPORT
|
||||
#else
|
||||
# define DLL_EXPORT
|
||||
# define DLL_EXPORT_CLASS
|
||||
# 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))
|
||||
# define NV_CDECL __attribute__((cdecl))
|
||||
# define NV_STDCALL __attribute__((stdcall))
|
||||
#else
|
||||
# define NV_CDECL
|
||||
# define NV_STDCALL
|
||||
# define NV_CDECL
|
||||
# define NV_STDCALL
|
||||
#endif
|
||||
|
||||
#define NV_FASTCALL __attribute__((fastcall))
|
||||
#define NV_FORCEINLINE __attribute__((always_inline)) inline
|
||||
//#if __GNUC__ > 3
|
||||
// It seems that GCC does not assume always_inline implies inline. I think this depends on the GCC version :(
|
||||
#define NV_FORCEINLINE inline __attribute__((always_inline))
|
||||
//#else
|
||||
// Some compilers complain that inline and always_inline are redundant.
|
||||
//#define NV_FORCEINLINE __attribute__((always_inline))
|
||||
//#endif
|
||||
#define NV_DEPRECATED __attribute__((deprecated))
|
||||
#define NV_THREAD_LOCAL __thread
|
||||
|
||||
@ -41,13 +47,13 @@
|
||||
|
||||
// Define __FUNC__ properly.
|
||||
#if __STDC_VERSION__ < 199901L
|
||||
# if __GNUC__ >= 2
|
||||
# define __FUNC__ __PRETTY_FUNCTION__ // __FUNCTION__
|
||||
# else
|
||||
# define __FUNC__ "<unknown>"
|
||||
# endif
|
||||
# if __GNUC__ >= 2
|
||||
# define __FUNC__ __PRETTY_FUNCTION__ // __FUNCTION__
|
||||
# else
|
||||
# define __FUNC__ "<unknown>"
|
||||
# endif
|
||||
#else
|
||||
# define __FUNC__ __PRETTY_FUNCTION__
|
||||
# define __FUNC__ __PRETTY_FUNCTION__
|
||||
#endif
|
||||
|
||||
#define restrict __restrict__
|
||||
|
@ -26,7 +26,7 @@
|
||||
#define chdir _chdir
|
||||
#define getcwd _getcwd
|
||||
|
||||
#if _MSC_VER < 1800 // Not sure what version introduced this.
|
||||
#if _MSC_VER < 1800 // Not sure what version introduced this.
|
||||
#define va_copy(a, b) (a) = (b)
|
||||
#endif
|
||||
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include <direct.h> // _mkdir
|
||||
#elif NV_OS_XBOX
|
||||
#include <Xtl.h>
|
||||
#elif NV_OS_ORBIS
|
||||
#include <fios2.h>
|
||||
#else
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
@ -29,6 +31,11 @@ bool FileSystem::exists(const char * path)
|
||||
// PathFileExists requires linking to shlwapi.lib
|
||||
//return PathFileExists(path) != 0;
|
||||
return GetFileAttributesA(path) != INVALID_FILE_ATTRIBUTES;
|
||||
#elif NV_OS_ORBIS
|
||||
const int BUFFER_SIZE = 2048;
|
||||
char file_fullpath[BUFFER_SIZE];
|
||||
snprintf(file_fullpath, BUFFER_SIZE, "/app0/%s", path);
|
||||
return sceFiosExistsSync(NULL, file_fullpath);
|
||||
#else
|
||||
if (FILE * fp = fopen(path, "r"))
|
||||
{
|
||||
@ -43,6 +50,9 @@ bool FileSystem::createDirectory(const char * path)
|
||||
{
|
||||
#if NV_OS_WIN32 || NV_OS_XBOX
|
||||
return CreateDirectoryA(path, NULL) != 0;
|
||||
#elif NV_OS_ORBIS
|
||||
// not implemented
|
||||
return false;
|
||||
#else
|
||||
return mkdir(path, 0777) != -1;
|
||||
#endif
|
||||
@ -55,6 +65,9 @@ bool FileSystem::changeDirectory(const char * path)
|
||||
#elif NV_OS_XBOX
|
||||
// Xbox doesn't support Current Working Directory!
|
||||
return false;
|
||||
#elif NV_OS_ORBIS
|
||||
// Orbis doesn't support Current Working Directory!
|
||||
return false;
|
||||
#else
|
||||
return chdir(path) != -1;
|
||||
#endif
|
||||
|
@ -50,6 +50,7 @@ struct PseudoIndexWrapper {
|
||||
// Declare foreach keyword.
|
||||
#if !defined NV_NO_USE_KEYWORDS
|
||||
# define foreach NV_FOREACH
|
||||
# define foreach_index NV_FOREACH
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -55,6 +55,10 @@ namespace nv {
|
||||
::free((void *)ptr);
|
||||
}
|
||||
|
||||
template <typename T> NV_FORCEINLINE void zero(T & data) {
|
||||
memset(&data, 0, sizeof(T));
|
||||
}
|
||||
|
||||
} // nv namespace
|
||||
|
||||
#endif // NV_CORE_MEMORY_H
|
||||
|
@ -37,7 +37,7 @@ namespace nv
|
||||
public:
|
||||
|
||||
/// Ctor.
|
||||
StdStream( FILE * fp, bool autoclose=true ) : m_fp(fp), m_autoclose(autoclose) { }
|
||||
StdStream( FILE * fp, bool autoclose ) : m_fp(fp), m_autoclose(autoclose) { }
|
||||
|
||||
/// Dtor.
|
||||
virtual ~StdStream()
|
||||
@ -108,7 +108,8 @@ namespace nv
|
||||
// implementation uses use ftell and fseek to determine our location within the file.
|
||||
virtual bool isAtEnd() const
|
||||
{
|
||||
nvDebugCheck(m_fp != NULL);
|
||||
if (m_fp == NULL) return true;
|
||||
//nvDebugCheck(m_fp != NULL);
|
||||
//return feof( m_fp ) != 0;
|
||||
#if NV_OS_WIN32
|
||||
uint pos = _ftell_nolock(m_fp);
|
||||
@ -143,10 +144,10 @@ namespace nv
|
||||
public:
|
||||
|
||||
/// Construct stream by file name.
|
||||
StdOutputStream( const char * name ) : StdStream(fileOpen(name, "wb")) { }
|
||||
StdOutputStream( const char * name ) : StdStream(fileOpen(name, "wb"), /*autoclose=*/true) { }
|
||||
|
||||
/// Construct stream by file handle.
|
||||
StdOutputStream( FILE * fp, bool autoclose=true ) : StdStream(fp, autoclose)
|
||||
StdOutputStream( FILE * fp, bool autoclose ) : StdStream(fp, autoclose)
|
||||
{
|
||||
}
|
||||
|
||||
@ -193,7 +194,7 @@ namespace nv
|
||||
public:
|
||||
|
||||
/// Construct stream by file name.
|
||||
StdInputStream( const char * name ) : StdStream(fileOpen(name, "rb")) { }
|
||||
StdInputStream( const char * name ) : StdStream(fileOpen(name, "rb"), /*autoclose=*/true) { }
|
||||
|
||||
/// Construct stream by file handle.
|
||||
StdInputStream( FILE * fp, bool autoclose=true ) : StdStream(fp, autoclose)
|
||||
|
@ -73,17 +73,17 @@ namespace
|
||||
uint nv::strLen(const char * str)
|
||||
{
|
||||
nvDebugCheck(str != NULL);
|
||||
return toU32(strlen(str));
|
||||
return U32(strlen(str));
|
||||
}
|
||||
|
||||
int nv::strCmp(const char * s1, const char * s2)
|
||||
int nv::strDiff(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)
|
||||
int nv::strCaseDiff(const char * s1, const char * s2)
|
||||
{
|
||||
nvDebugCheck(s1 != NULL);
|
||||
nvDebugCheck(s1 != NULL);
|
||||
@ -98,14 +98,14 @@ bool nv::strEqual(const char * s1, const char * s2)
|
||||
{
|
||||
if (s1 == s2) return true;
|
||||
if (s1 == NULL || s2 == NULL) return false;
|
||||
return strCmp(s1, s2) == 0;
|
||||
return strcmp(s1, s2) == 0;
|
||||
}
|
||||
|
||||
bool nv::strCaseEqual(const char * s1, const char * s2)
|
||||
{
|
||||
if (s1 == s2) return true;
|
||||
if (s1 == NULL || s2 == NULL) return false;
|
||||
return strCaseCmp(s1, s2) == 0;
|
||||
return strCaseDiff(s1, s2) == 0;
|
||||
}
|
||||
|
||||
bool nv::strBeginsWith(const char * str, const char * prefix)
|
||||
@ -122,7 +122,7 @@ bool nv::strEndsWith(const char * str, const char * suffix)
|
||||
return strncmp(str + ml - sl, suffix, sl) == 0;
|
||||
}
|
||||
|
||||
|
||||
// @@ Add asserts to detect overlap between dst and src?
|
||||
void nv::strCpy(char * dst, uint size, const char * src)
|
||||
{
|
||||
nvDebugCheck(dst != NULL);
|
||||
@ -142,8 +142,9 @@ void nv::strCpy(char * dst, uint size, const char * src, uint len)
|
||||
#if NV_CC_MSVC && _MSC_VER >= 1400
|
||||
strncpy_s(dst, size, src, len);
|
||||
#else
|
||||
NV_UNUSED(size);
|
||||
strncpy(dst, src, len);
|
||||
int n = min(len+1, size);
|
||||
strncpy(dst, src, n);
|
||||
dst[n-1] = '\0';
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -220,6 +221,13 @@ match:
|
||||
}
|
||||
}
|
||||
|
||||
bool nv::isNumber(const char * str) {
|
||||
while(*str != '\0') {
|
||||
if (!isDigit(*str)) return false;
|
||||
str++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/** Empty string. */
|
||||
@ -325,25 +333,20 @@ StringBuilder & StringBuilder::formatList( const char * fmt, va_list arg )
|
||||
|
||||
/** Append a string. */
|
||||
StringBuilder & StringBuilder::append( const char * s )
|
||||
{
|
||||
return append(s, U32(strlen( s )));
|
||||
}
|
||||
|
||||
|
||||
/** Append a string. */
|
||||
StringBuilder & StringBuilder::append(const char * s, uint len)
|
||||
{
|
||||
nvDebugCheck(s != NULL);
|
||||
|
||||
const uint slen = uint(strlen( s ));
|
||||
|
||||
if (m_str == NULL) {
|
||||
m_size = slen + 1;
|
||||
m_str = strAlloc(m_size);
|
||||
memcpy(m_str, s, m_size);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
memcpy(m_str + len, s, slen + 1);
|
||||
}
|
||||
uint offset = length();
|
||||
const uint size = offset + len + 1;
|
||||
reserve(size);
|
||||
strCpy(m_str + offset, len + 1, s, len);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
@ -35,11 +35,11 @@ namespace nv
|
||||
uint operator()(const char * str) const { return strHash(str); }
|
||||
};
|
||||
|
||||
NVCORE_API uint strLen(const char * str) NV_PURE;
|
||||
NVCORE_API uint strLen(const char * str) NV_PURE; // Asserts on NULL strings.
|
||||
|
||||
NVCORE_API int strCmp(const char * s1, const char * s2) NV_PURE;
|
||||
NVCORE_API int strCaseCmp(const char * s1, const char * s2) NV_PURE;
|
||||
NVCORE_API bool strEqual(const char * s1, const char * s2) NV_PURE; // Accepts NULL strings.
|
||||
NVCORE_API int strDiff(const char * s1, const char * s2) NV_PURE; // Asserts on NULL strings.
|
||||
NVCORE_API int strCaseDiff(const char * s1, const char * s2) NV_PURE; // Asserts on NULL strings.
|
||||
NVCORE_API bool strEqual(const char * s1, const char * s2) NV_PURE; // Accepts NULL strings.
|
||||
NVCORE_API bool strCaseEqual(const char * s1, const char * s2) NV_PURE; // Accepts NULL strings.
|
||||
|
||||
template <> struct Equal<const char *> {
|
||||
@ -56,6 +56,35 @@ namespace nv
|
||||
|
||||
NVCORE_API bool strMatch(const char * str, const char * pat) NV_PURE;
|
||||
|
||||
NVCORE_API bool isNumber(const char * str) NV_PURE;
|
||||
|
||||
/* @@ Implement these two functions and modify StringBuilder to use them?
|
||||
NVCORE_API void strFormat(const char * dst, const char * fmt, ...);
|
||||
NVCORE_API void strFormatList(const char * dst, const char * fmt, va_list arg);
|
||||
|
||||
template <size_t count> void strFormatSafe(char (&buffer)[count], const char *fmt, ...) __attribute__((format (printf, 2, 3)));
|
||||
template <size_t count> void strFormatSafe(char (&buffer)[count], const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
strFormatList(buffer, count, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
template <size_t count> void strFormatListSafe(char (&buffer)[count], const char *fmt, va_list arg) {
|
||||
va_list tmp;
|
||||
va_copy(tmp, args);
|
||||
strFormatList(buffer, count, fmt, tmp);
|
||||
va_end(tmp);
|
||||
}*/
|
||||
|
||||
template <int count> void strCpySafe(char (&buffer)[count], const char *src) {
|
||||
strCpy(buffer, count, src);
|
||||
}
|
||||
|
||||
template <int count> void strCatSafe(char (&buffer)[count], const char * src) {
|
||||
strCat(buffer, count, src);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// String builder.
|
||||
class NVCORE_CLASS StringBuilder
|
||||
@ -73,9 +102,10 @@ namespace nv
|
||||
StringBuilder & format( const char * format, ... ) __attribute__((format (printf, 2, 3)));
|
||||
StringBuilder & formatList( const char * format, va_list arg );
|
||||
|
||||
StringBuilder & append( const char * str );
|
||||
StringBuilder & appendFormat( const char * format, ... ) __attribute__((format (printf, 2, 3)));
|
||||
StringBuilder & appendFormatList( const char * format, va_list arg );
|
||||
StringBuilder & append(const char * str);
|
||||
StringBuilder & append(const char * str, uint len);
|
||||
StringBuilder & appendFormat(const char * format, ...) __attribute__((format (printf, 2, 3)));
|
||||
StringBuilder & appendFormatList(const char * format, va_list arg);
|
||||
|
||||
StringBuilder & appendSpace(uint n);
|
||||
|
||||
@ -162,9 +192,9 @@ namespace nv
|
||||
void stripExtension();
|
||||
|
||||
// statics
|
||||
static char separator();
|
||||
static const char * fileName(const char *);
|
||||
static const char * extension(const char *);
|
||||
NVCORE_API static char separator();
|
||||
NVCORE_API static const char * fileName(const char *);
|
||||
NVCORE_API static const char * extension(const char *);
|
||||
};
|
||||
|
||||
|
||||
@ -328,6 +358,66 @@ namespace nv
|
||||
uint operator()(const String & str) const { return str.hash(); }
|
||||
};
|
||||
|
||||
|
||||
// Like AutoPtr, but for const char strings.
|
||||
class AutoString
|
||||
{
|
||||
NV_FORBID_COPY(AutoString);
|
||||
NV_FORBID_HEAPALLOC();
|
||||
public:
|
||||
|
||||
// Ctor.
|
||||
AutoString(const char * p = NULL) : m_ptr(p) { }
|
||||
|
||||
#if NV_CC_CPP11
|
||||
// Move ctor.
|
||||
AutoString(AutoString && ap) : m_ptr(ap.m_ptr) { ap.m_ptr = NULL; }
|
||||
#endif
|
||||
|
||||
// Dtor. Deletes owned pointer.
|
||||
~AutoString() {
|
||||
delete [] m_ptr;
|
||||
m_ptr = NULL;
|
||||
}
|
||||
|
||||
// Delete owned pointer and assign new one.
|
||||
void operator=(const char * p) {
|
||||
if (p != m_ptr)
|
||||
{
|
||||
delete [] m_ptr;
|
||||
m_ptr = p;
|
||||
}
|
||||
}
|
||||
|
||||
// Get pointer.
|
||||
const char * ptr() const { return m_ptr; }
|
||||
operator const char *() const { return m_ptr; }
|
||||
|
||||
// Relinquish ownership of the underlying pointer and returns that pointer.
|
||||
const char * release() {
|
||||
const char * tmp = m_ptr;
|
||||
m_ptr = NULL;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// comparison operators.
|
||||
friend bool operator == (const AutoString & ap, const char * const p) {
|
||||
return (ap.ptr() == p);
|
||||
}
|
||||
friend bool operator != (const AutoString & ap, const char * const p) {
|
||||
return (ap.ptr() != p);
|
||||
}
|
||||
friend bool operator == (const char * const p, const AutoString & ap) {
|
||||
return (ap.ptr() == p);
|
||||
}
|
||||
friend bool operator != (const char * const p, const AutoString & ap) {
|
||||
return (ap.ptr() != p);
|
||||
}
|
||||
|
||||
private:
|
||||
const char * m_ptr;
|
||||
};
|
||||
|
||||
} // nv namespace
|
||||
|
||||
#endif // NV_CORE_STRING_H
|
||||
|
@ -78,7 +78,7 @@ namespace nv
|
||||
|
||||
// friends
|
||||
friend Stream & operator<<( Stream & s, bool & c ) {
|
||||
#if NV_OS_DARWIN
|
||||
#if NV_OS_DARWIN && !NV_CC_CPP11
|
||||
nvStaticCheck(sizeof(bool) == 4);
|
||||
uint8 b = c ? 1 : 0;
|
||||
s.serialize( &b, 1 );
|
||||
|
@ -26,7 +26,7 @@ void TextWriter::writeString(const char * str, uint len)
|
||||
s->serialize(const_cast<char *>(str), len);
|
||||
}
|
||||
|
||||
void TextWriter::write(const char * format, ...)
|
||||
void TextWriter::format(const char * format, ...)
|
||||
{
|
||||
va_list arg;
|
||||
va_start(arg,format);
|
||||
@ -35,7 +35,7 @@ void TextWriter::write(const char * format, ...)
|
||||
va_end(arg);
|
||||
}
|
||||
|
||||
void TextWriter::write(const char * format, va_list arg)
|
||||
void TextWriter::formatList(const char * format, va_list arg)
|
||||
{
|
||||
va_list tmp;
|
||||
va_copy(tmp, arg);
|
||||
|
@ -20,8 +20,8 @@ namespace nv
|
||||
|
||||
void writeString(const char * str);
|
||||
void writeString(const char * str, uint len);
|
||||
void write(const char * format, ...) __attribute__((format (printf, 2, 3)));
|
||||
void write(const char * format, va_list arg);
|
||||
void format(const char * format, ...) __attribute__((format (printf, 2, 3)));
|
||||
void formatList(const char * format, va_list arg);
|
||||
|
||||
private:
|
||||
|
||||
@ -35,19 +35,19 @@ namespace nv
|
||||
|
||||
inline TextWriter & operator<<( TextWriter & tw, int i)
|
||||
{
|
||||
tw.write("%d", i);
|
||||
tw.format("%d", i);
|
||||
return tw;
|
||||
}
|
||||
|
||||
inline TextWriter & operator<<( TextWriter & tw, uint i)
|
||||
{
|
||||
tw.write("%u", i);
|
||||
tw.format("%u", i);
|
||||
return tw;
|
||||
}
|
||||
|
||||
inline TextWriter & operator<<( TextWriter & tw, float f)
|
||||
{
|
||||
tw.write("%f", f);
|
||||
tw.format("%f", f);
|
||||
return tw;
|
||||
}
|
||||
|
||||
|
@ -29,78 +29,96 @@
|
||||
#define NV_HALF_MAX 65504.0F
|
||||
#define NV_FLOAT_MAX 3.402823466e+38F
|
||||
|
||||
#define NV_INTEGER_TO_FLOAT_MAX 16777217 // Largest integer such that it and all smaller integers can be stored in a 32bit float.
|
||||
|
||||
|
||||
namespace nv
|
||||
{
|
||||
// Less error prone than casting. From CB:
|
||||
// http://cbloomrants.blogspot.com/2011/06/06-17-11-c-casting-is-devil.html
|
||||
|
||||
// These intentionally look like casts.
|
||||
|
||||
// uint32 casts:
|
||||
template <typename T> inline uint32 toU32(T x) { return x; }
|
||||
template <> inline uint32 toU32<uint64>(uint64 x) { nvDebugCheck(x <= NV_UINT32_MAX); return (uint32)x; }
|
||||
template <> inline uint32 toU32<int64>(int64 x) { nvDebugCheck(x >= 0 && x <= NV_UINT32_MAX); return (uint32)x; }
|
||||
//template <> inline uint32 toU32<uint32>(uint32 x) { return x; }
|
||||
template <> inline uint32 toU32<int32>(int32 x) { nvDebugCheck(x >= 0); return (uint32)x; }
|
||||
//template <> inline uint32 toU32<uint16>(uint16 x) { return x; }
|
||||
template <> inline uint32 toU32<int16>(int16 x) { nvDebugCheck(x >= 0); return (uint32)x; }
|
||||
//template <> inline uint32 toU32<uint8>(uint8 x) { return x; }
|
||||
template <> inline uint32 toU32<int8>(int8 x) { nvDebugCheck(x >= 0); return (uint32)x; }
|
||||
template <typename T> inline uint32 U32(T x) { return x; }
|
||||
template <> inline uint32 U32<uint64>(uint64 x) { nvDebugCheck(x <= NV_UINT32_MAX); return (uint32)x; }
|
||||
template <> inline uint32 U32<int64>(int64 x) { nvDebugCheck(x >= 0 && x <= NV_UINT32_MAX); return (uint32)x; }
|
||||
//template <> inline uint32 U32<uint32>(uint32 x) { return x; }
|
||||
template <> inline uint32 U32<int32>(int32 x) { nvDebugCheck(x >= 0); return (uint32)x; }
|
||||
//template <> inline uint32 U32<uint16>(uint16 x) { return x; }
|
||||
template <> inline uint32 U32<int16>(int16 x) { nvDebugCheck(x >= 0); return (uint32)x; }
|
||||
//template <> inline uint32 U32<uint8>(uint8 x) { return x; }
|
||||
template <> inline uint32 U32<int8>(int8 x) { nvDebugCheck(x >= 0); return (uint32)x; }
|
||||
|
||||
// int32 casts:
|
||||
template <typename T> inline int32 toI32(T x) { return x; }
|
||||
template <> inline int32 toI32<uint64>(uint64 x) { nvDebugCheck(x <= NV_INT32_MAX); return (int32)x; }
|
||||
template <> inline int32 toI32<int64>(int64 x) { nvDebugCheck(x >= NV_INT32_MIN && x <= NV_UINT32_MAX); return (int32)x; }
|
||||
template <> inline int32 toI32<uint32>(uint32 x) { nvDebugCheck(x <= NV_INT32_MAX); return (int32)x; }
|
||||
//template <> inline int32 toI32<int32>(int32 x) { return x; }
|
||||
//template <> inline int32 toI32<uint16>(uint16 x) { return x; }
|
||||
//template <> inline int32 toI32<int16>(int16 x) { return x; }
|
||||
//template <> inline int32 toI32<uint8>(uint8 x) { return x; }
|
||||
//template <> inline int32 toI32<int8>(int8 x) { return x; }
|
||||
template <typename T> inline int32 I32(T x) { return x; }
|
||||
template <> inline int32 I32<uint64>(uint64 x) { nvDebugCheck(x <= NV_INT32_MAX); return (int32)x; }
|
||||
template <> inline int32 I32<int64>(int64 x) { nvDebugCheck(x >= NV_INT32_MIN && x <= NV_UINT32_MAX); return (int32)x; }
|
||||
template <> inline int32 I32<uint32>(uint32 x) { nvDebugCheck(x <= NV_INT32_MAX); return (int32)x; }
|
||||
//template <> inline int32 I32<int32>(int32 x) { return x; }
|
||||
//template <> inline int32 I32<uint16>(uint16 x) { return x; }
|
||||
//template <> inline int32 I32<int16>(int16 x) { return x; }
|
||||
//template <> inline int32 I32<uint8>(uint8 x) { return x; }
|
||||
//template <> inline int32 I32<int8>(int8 x) { return x; }
|
||||
|
||||
// uint16 casts:
|
||||
template <typename T> inline uint16 toU16(T x) { return x; }
|
||||
template <> inline uint16 toU16<uint64>(uint64 x) { nvDebugCheck(x <= NV_UINT16_MAX); return (uint16)x; }
|
||||
template <> inline uint16 toU16<int64>(int64 x) { nvDebugCheck(x >= 0 && x <= NV_UINT16_MAX); return (uint16)x; }
|
||||
template <> inline uint16 toU16<uint32>(uint32 x) { nvDebugCheck(x <= NV_UINT16_MAX); return (uint16)x; }
|
||||
template <> inline uint16 toU16<int32>(int32 x) { nvDebugCheck(x >= 0 && x <= NV_UINT16_MAX); return (uint16)x; }
|
||||
//template <> inline uint16 toU16<uint16>(uint16 x) { return x; }
|
||||
template <> inline uint16 toU16<int16>(int16 x) { nvDebugCheck(x >= 0); return (uint16)x; }
|
||||
//template <> inline uint16 toU16<uint8>(uint8 x) { return x; }
|
||||
template <> inline uint16 toU16<int8>(int8 x) { nvDebugCheck(x >= 0); return (uint16)x; }
|
||||
template <typename T> inline uint16 U16(T x) { return x; }
|
||||
template <> inline uint16 U16<uint64>(uint64 x) { nvDebugCheck(x <= NV_UINT16_MAX); return (uint16)x; }
|
||||
template <> inline uint16 U16<int64>(int64 x) { nvDebugCheck(x >= 0 && x <= NV_UINT16_MAX); return (uint16)x; }
|
||||
template <> inline uint16 U16<uint32>(uint32 x) { nvDebugCheck(x <= NV_UINT16_MAX); return (uint16)x; }
|
||||
template <> inline uint16 U16<int32>(int32 x) { nvDebugCheck(x >= 0 && x <= NV_UINT16_MAX); return (uint16)x; }
|
||||
//template <> inline uint16 U16<uint16>(uint16 x) { return x; }
|
||||
template <> inline uint16 U16<int16>(int16 x) { nvDebugCheck(x >= 0); return (uint16)x; }
|
||||
//template <> inline uint16 U16<uint8>(uint8 x) { return x; }
|
||||
template <> inline uint16 U16<int8>(int8 x) { nvDebugCheck(x >= 0); return (uint16)x; }
|
||||
|
||||
// int16 casts:
|
||||
template <typename T> inline int16 toI16(T x) { return x; }
|
||||
template <> inline int16 toI16<uint64>(uint64 x) { nvDebugCheck(x <= NV_INT16_MAX); return (int16)x; }
|
||||
template <> inline int16 toI16<int64>(int64 x) { nvDebugCheck(x >= NV_INT16_MIN && x <= NV_UINT16_MAX); return (int16)x; }
|
||||
template <> inline int16 toI16<uint32>(uint32 x) { nvDebugCheck(x <= NV_INT16_MAX); return (int16)x; }
|
||||
template <> inline int16 toI16<int32>(int32 x) { nvDebugCheck(x >= NV_INT16_MIN && x <= NV_UINT16_MAX); return (int16)x; }
|
||||
template <> inline int16 toI16<uint16>(uint16 x) { nvDebugCheck(x <= NV_INT16_MAX); return (int16)x; }
|
||||
//template <> inline int16 toI16<int16>(int16 x) { return x; }
|
||||
//template <> inline int16 toI16<uint8>(uint8 x) { return x; }
|
||||
//template <> inline int16 toI16<int8>(int8 x) { return x; }
|
||||
template <typename T> inline int16 I16(T x) { return x; }
|
||||
template <> inline int16 I16<uint64>(uint64 x) { nvDebugCheck(x <= NV_INT16_MAX); return (int16)x; }
|
||||
template <> inline int16 I16<int64>(int64 x) { nvDebugCheck(x >= NV_INT16_MIN && x <= NV_UINT16_MAX); return (int16)x; }
|
||||
template <> inline int16 I16<uint32>(uint32 x) { nvDebugCheck(x <= NV_INT16_MAX); return (int16)x; }
|
||||
template <> inline int16 I16<int32>(int32 x) { nvDebugCheck(x >= NV_INT16_MIN && x <= NV_UINT16_MAX); return (int16)x; }
|
||||
template <> inline int16 I16<uint16>(uint16 x) { nvDebugCheck(x <= NV_INT16_MAX); return (int16)x; }
|
||||
//template <> inline int16 I16<int16>(int16 x) { return x; }
|
||||
//template <> inline int16 I16<uint8>(uint8 x) { return x; }
|
||||
//template <> inline int16 I16<int8>(int8 x) { return x; }
|
||||
|
||||
// uint8 casts:
|
||||
template <typename T> inline uint8 toU8(T x) { return x; }
|
||||
template <> inline uint8 toU8<uint64>(uint64 x) { nvDebugCheck(x <= NV_UINT8_MAX); return (uint8)x; }
|
||||
template <> inline uint8 toU8<int64>(int64 x) { nvDebugCheck(x >= 0 && x <= NV_UINT8_MAX); return (uint8)x; }
|
||||
template <> inline uint8 toU8<uint32>(uint32 x) { nvDebugCheck(x <= NV_UINT8_MAX); return (uint8)x; }
|
||||
template <> inline uint8 toU8<int32>(int32 x) { nvDebugCheck(x >= 0 && x <= NV_UINT8_MAX); return (uint8)x; }
|
||||
template <> inline uint8 toU8<uint16>(uint16 x) { nvDebugCheck(x <= NV_UINT8_MAX); return (uint8)x; }
|
||||
template <> inline uint8 toU8<int16>(int16 x) { nvDebugCheck(x >= 0 && x <= NV_UINT8_MAX); return (uint8)x; }
|
||||
//template <> inline uint8 toU8<uint8>(uint8 x) { return x; }
|
||||
template <> inline uint8 toU8<int8>(int8 x) { nvDebugCheck(x >= 0); return (uint8)x; }
|
||||
template <typename T> inline uint8 U8(T x) { return x; }
|
||||
template <> inline uint8 U8<uint64>(uint64 x) { nvDebugCheck(x <= NV_UINT8_MAX); return (uint8)x; }
|
||||
template <> inline uint8 U8<int64>(int64 x) { nvDebugCheck(x >= 0 && x <= NV_UINT8_MAX); return (uint8)x; }
|
||||
template <> inline uint8 U8<uint32>(uint32 x) { nvDebugCheck(x <= NV_UINT8_MAX); return (uint8)x; }
|
||||
template <> inline uint8 U8<int32>(int32 x) { nvDebugCheck(x >= 0 && x <= NV_UINT8_MAX); return (uint8)x; }
|
||||
template <> inline uint8 U8<uint16>(uint16 x) { nvDebugCheck(x <= NV_UINT8_MAX); return (uint8)x; }
|
||||
template <> inline uint8 U8<int16>(int16 x) { nvDebugCheck(x >= 0 && x <= NV_UINT8_MAX); return (uint8)x; }
|
||||
//template <> inline uint8 U8<uint8>(uint8 x) { return x; }
|
||||
template <> inline uint8 U8<int8>(int8 x) { nvDebugCheck(x >= 0); return (uint8)x; }
|
||||
//template <> inline uint8 U8<float>(int8 x) { nvDebugCheck(x >= 0.0f && x <= 255.0f); return (uint8)x; }
|
||||
|
||||
// int8 casts:
|
||||
template <typename T> inline int8 toI8(T x) { return x; }
|
||||
template <> inline int8 toI8<uint64>(uint64 x) { nvDebugCheck(x <= NV_INT8_MAX); return (int8)x; }
|
||||
template <> inline int8 toI8<int64>(int64 x) { nvDebugCheck(x >= NV_INT8_MIN && x <= NV_UINT8_MAX); return (int8)x; }
|
||||
template <> inline int8 toI8<uint32>(uint32 x) { nvDebugCheck(x <= NV_INT8_MAX); return (int8)x; }
|
||||
template <> inline int8 toI8<int32>(int32 x) { nvDebugCheck(x >= NV_INT8_MIN && x <= NV_UINT8_MAX); return (int8)x; }
|
||||
template <> inline int8 toI8<uint16>(uint16 x) { nvDebugCheck(x <= NV_INT8_MAX); return (int8)x; }
|
||||
template <> inline int8 toI8<int16>(int16 x) { nvDebugCheck(x >= NV_INT8_MIN && x <= NV_UINT8_MAX); return (int8)x; }
|
||||
template <> inline int8 toI8<uint8>(uint8 x) { nvDebugCheck(x <= NV_INT8_MAX); return (int8)x; }
|
||||
//template <> inline int8 toI8<int8>(int8 x) { return x; }
|
||||
|
||||
template <typename T> inline int8 I8(T x) { return x; }
|
||||
template <> inline int8 I8<uint64>(uint64 x) { nvDebugCheck(x <= NV_INT8_MAX); return (int8)x; }
|
||||
template <> inline int8 I8<int64>(int64 x) { nvDebugCheck(x >= NV_INT8_MIN && x <= NV_UINT8_MAX); return (int8)x; }
|
||||
template <> inline int8 I8<uint32>(uint32 x) { nvDebugCheck(x <= NV_INT8_MAX); return (int8)x; }
|
||||
template <> inline int8 I8<int32>(int32 x) { nvDebugCheck(x >= NV_INT8_MIN && x <= NV_UINT8_MAX); return (int8)x; }
|
||||
template <> inline int8 I8<uint16>(uint16 x) { nvDebugCheck(x <= NV_INT8_MAX); return (int8)x; }
|
||||
template <> inline int8 I8<int16>(int16 x) { nvDebugCheck(x >= NV_INT8_MIN && x <= NV_UINT8_MAX); return (int8)x; }
|
||||
template <> inline int8 I8<uint8>(uint8 x) { nvDebugCheck(x <= NV_INT8_MAX); return (int8)x; }
|
||||
//template <> inline int8 I8<int8>(int8 x) { return x; }
|
||||
|
||||
// float casts:
|
||||
template <typename T> inline float F32(T x) { return x; }
|
||||
template <> inline float F32<uint64>(uint64 x) { nvDebugCheck(x <= NV_INTEGER_TO_FLOAT_MAX); return (float)x; }
|
||||
template <> inline float F32<int64>(int64 x) { nvDebugCheck(x >= -NV_INTEGER_TO_FLOAT_MAX && x <= NV_INTEGER_TO_FLOAT_MAX); return (float)x; }
|
||||
template <> inline float F32<uint32>(uint32 x) { nvDebugCheck(x <= NV_INTEGER_TO_FLOAT_MAX); return (float)x; }
|
||||
template <> inline float F32<int32>(int32 x) { nvDebugCheck(x >= -NV_INTEGER_TO_FLOAT_MAX && x <= NV_INTEGER_TO_FLOAT_MAX); return (float)x; }
|
||||
// The compiler should not complain about these conversions:
|
||||
//template <> inline float F32<uint16>(uint16 x) { nvDebugCheck(return (float)x; }
|
||||
//template <> inline float F32<int16>(int16 x) { nvDebugCheck(return (float)x; }
|
||||
//template <> inline float F32<uint8>(uint8 x) { nvDebugCheck(return (float)x; }
|
||||
//template <> inline float F32<int8>(int8 x) { nvDebugCheck(return (float)x; }
|
||||
|
||||
|
||||
/// Swap two values.
|
||||
template <typename T>
|
||||
inline void swap(T & a, T & b)
|
||||
@ -112,35 +130,40 @@ namespace nv
|
||||
|
||||
/// Return the maximum of the two arguments. For floating point values, it returns the second value if the first is NaN.
|
||||
template <typename T>
|
||||
inline const T & max(const T & a, const T & b)
|
||||
//inline const T & max(const T & a, const T & b)
|
||||
inline T max(const T & a, const T & b)
|
||||
{
|
||||
return (b < a) ? a : b;
|
||||
}
|
||||
|
||||
/// Return the maximum of the three arguments.
|
||||
template <typename T>
|
||||
inline const T & max3(const T & a, const T & b, const T & c)
|
||||
//inline const T & max3(const T & a, const T & b, const T & c)
|
||||
inline T max3(const T & a, const T & b, const T & c)
|
||||
{
|
||||
return max(a, max(b, c));
|
||||
}
|
||||
|
||||
/// Return the minimum of two values.
|
||||
template <typename T>
|
||||
inline const T & min(const T & a, const T & b)
|
||||
//inline const T & min(const T & a, const T & b)
|
||||
inline T min(const T & a, const T & b)
|
||||
{
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
|
||||
/// Return the maximum of the three arguments.
|
||||
template <typename T>
|
||||
inline const T & min3(const T & a, const T & b, const T & c)
|
||||
//inline const T & min3(const T & a, const T & b, const T & c)
|
||||
inline T min3(const T & a, const T & b, const T & c)
|
||||
{
|
||||
return min(a, min(b, c));
|
||||
}
|
||||
|
||||
/// Clamp between two values.
|
||||
template <typename T>
|
||||
inline const T & clamp(const T & x, const T & a, const T & b)
|
||||
//inline const T & clamp(const T & x, const T & a, const T & b)
|
||||
inline T clamp(const T & x, const T & a, const T & b)
|
||||
{
|
||||
return min(max(x, a), b);
|
||||
}
|
||||
@ -217,7 +240,6 @@ namespace nv
|
||||
template <typename T>
|
||||
void destroy_range(T * restrict ptr, uint new_size, uint old_size) {
|
||||
for (uint i = new_size; i < old_size; i++) {
|
||||
nvDebugCheck(ptr != NULL && isValidPtr(ptr));
|
||||
(ptr+i)->~T(); // Explicit call to the destructor
|
||||
}
|
||||
}
|
||||
|
@ -127,6 +127,12 @@
|
||||
# error "Unsupported compiler"
|
||||
#endif
|
||||
|
||||
#if NV_CC_MSVC
|
||||
#define NV_CC_CPP11 (__cplusplus > 199711L)
|
||||
#else
|
||||
// @@ IC: This works in CLANG, about GCC?
|
||||
#define NV_CC_CPP11 (__has_feature(cxx_deleted_functions) && __has_feature(cxx_rvalue_references) && __has_feature(cxx_static_assert))
|
||||
#endif
|
||||
|
||||
// Endiannes:
|
||||
#define NV_LITTLE_ENDIAN POSH_LITTLE_ENDIAN
|
||||
@ -170,11 +176,16 @@ typedef uint32 uint;
|
||||
|
||||
|
||||
// Disable copy constructor and assignment operator.
|
||||
#if NV_CC_CPP11
|
||||
#define NV_FORBID_COPY(C) \
|
||||
C( const C & ) = delete; \
|
||||
C &operator=( const C & ) = delete
|
||||
#else
|
||||
#define NV_FORBID_COPY(C) \
|
||||
private: \
|
||||
C( const C & ); \
|
||||
C &operator=( const C & )
|
||||
|
||||
#endif
|
||||
|
||||
// Disable dynamic allocation on the heap.
|
||||
// See Prohibiting Heap-Based Objects in More Effective C++.
|
||||
@ -205,8 +216,8 @@ typedef uint32 uint;
|
||||
#define NV_MULTI_LINE_MACRO_END } while(false)
|
||||
#endif
|
||||
|
||||
#if __cplusplus > 199711L
|
||||
#define nvStaticCheck(x) static_assert(x, "Static assert "#x" failed")
|
||||
#if NV_CC_CPP11
|
||||
#define nvStaticCheck(x) static_assert((x), "Static assert "#x" failed")
|
||||
#else
|
||||
#define nvStaticCheck(x) typedef char NV_STRING_JOIN2(__static_assert_,__LINE__)[(x)]
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user