Merge changes from the witness.

This commit is contained in:
castano
2014-11-04 17:49:29 +00:00
parent 4cb60cc5ba
commit d019cd7080
86 changed files with 3534 additions and 882 deletions

View File

@ -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 );

View File

@ -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--;
}

View File

@ -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;

View File

@ -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

View File

@ -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__

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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;
}

View File

@ -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

View File

@ -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 );

View File

@ -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);

View File

@ -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;
}

View File

@ -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
}
}

View File

@ -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