Merge changes from The Witness.

This commit is contained in:
Ignacio
2018-02-05 18:55:07 -08:00
parent 2075d740c9
commit 9489aed825
88 changed files with 8924 additions and 5025 deletions

View File

@ -148,7 +148,7 @@ namespace nv
NV_FORCEINLINE bool isDone(const PseudoIndex & i) const { nvDebugCheck(i <= this->m_size); return i == this->m_size; }
NV_FORCEINLINE void advance(PseudoIndex & i) const { nvDebugCheck(i <= this->m_size); i++; }
#if NV_CC_MSVC
#if NV_NEED_PSEUDOINDEX_WRAPPER
NV_FORCEINLINE T & operator[]( const PseudoIndexWrapper & i ) {
return m_buffer[i(this)];
}

View File

@ -27,7 +27,7 @@
#define NV_FASTCALL __attribute__((fastcall))
#define NV_FORCEINLINE __attribute__((always_inline)) inline
#define NV_DEPRECATED __attribute__((deprecated))
#define NV_THREAD_LOCAL //ACS: there's no "__thread" or equivalent on iOS/OSX
#define NV_THREAD_LOCAL __thread
#if __GNUC__ > 2
#define NV_PURE __attribute__((pure))

View File

@ -31,11 +31,6 @@ 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"))
{
@ -78,3 +73,31 @@ bool FileSystem::removeFile(const char * path)
// @@ Use unlink or remove?
return remove(path) == 0;
}
#include "StdStream.h" // for fileOpen
bool FileSystem::copyFile(const char * src, const char * dst) {
FILE * fsrc = fileOpen(src, "rb");
if (fsrc == NULL) return false;
NV_ON_RETURN(fclose(fsrc));
FILE * fdst = fileOpen(dst, "wb");
if (fdst == NULL) return false;
NV_ON_RETURN(fclose(fdst));
char buffer[1024];
size_t n;
while ((n = fread(buffer, sizeof(char), sizeof(buffer), fsrc)) > 0) {
if (fwrite(buffer, sizeof(char), n, fdst) != n) {
return false;
}
}
return true;
}

View File

@ -15,7 +15,7 @@ namespace nv
NVCORE_API bool createDirectory(const char * path);
NVCORE_API bool changeDirectory(const char * path);
NVCORE_API bool removeFile(const char * path);
NVCORE_API bool copyFile(const char * src, const char * dst);
} // FileSystem namespace
} // nv namespace

View File

@ -33,6 +33,8 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=6709
#else // If typeof not available:
#define NV_NEED_PSEUDOINDEX_WRAPPER 1
#include <new> // placement new
struct PseudoIndexWrapper {

View File

@ -2,6 +2,7 @@
#include "Memory.h"
#include "Debug.h"
#include "Utils.h"
#include <stdlib.h>
@ -56,6 +57,7 @@ void * realloc(void * ptr, size_t size)
#endif
}
/* No need to override this unless we want line info.
void * operator new (size_t size) throw()
{
@ -116,4 +118,32 @@ void operator delete(void* p, const std::nothrow_t&) throw()
#endif // NV_OVERRIDE_ALLOC
void * nv::aligned_malloc(size_t size, size_t alignment)
{
// alignment must be a power of two, multiple of sizeof(void*)
nvDebugCheck(isPowerOfTwo(alignment));
nvDebugCheck((alignment & (sizeof(void*) - 1)) == 0);
#if NV_OS_WIN32 || NV_OS_DURANGO
return _aligned_malloc(size, alignment);
#elif NV_OS_DARWIN && !NV_OS_IOS
void * ptr = NULL;
posix_memalign(&ptr, alignment, size);
return ptr;
#elif NV_OS_LINUX
return memalign(alignment, size)
#else // NV_OS_ORBIS || NV_OS_IOS
// @@ IC: iOS appears to be 16 byte aligned, should we check alignment and assert if we request a higher alignment factor?
return ::malloc(size);
#endif
}
void nv::aligned_free(void * ptr)
{
#if NV_OS_WIN32 || NV_OS_DURANGO
_aligned_free(ptr);
#else
::free(ptr);
#endif
}

View File

@ -7,10 +7,16 @@
#include "nvcore.h"
#include <stdlib.h> // malloc(), realloc() and free()
#include <string.h> // memset
//#include <stddef.h> // size_t
//#include <new> // new and delete
#define TRACK_MEMORY_LEAKS 0
#if TRACK_MEMORY_LEAKS
#include <vld.h>
#endif
#if NV_CC_GNUC
# define NV_ALIGN_16 __attribute__ ((__aligned__ (16)))
@ -41,6 +47,8 @@ extern "C" {
#endif
namespace nv {
NVCORE_API void * aligned_malloc(size_t size, size_t alignment);
NVCORE_API void aligned_free(void * );
// C++ helpers.
template <typename T> NV_FORCEINLINE T * malloc(size_t count) {

View File

@ -113,7 +113,7 @@ namespace nv
public:
// BaseClass must implement addRef() and release().
typedef SmartPtr<BaseClass> ThisType;
typedef SmartPtr<BaseClass> ThisType;
/// Default ctor.
SmartPtr() : m_ptr(NULL)

View File

@ -213,9 +213,12 @@ namespace nv
#elif NV_OS_LINUX
return (uint)fread_unlocked(data, 1, len, m_fp);
#elif NV_OS_DARWIN
// @@ No error checking, always returns len.
// This is rather lame. Not sure if it's faster than the locked version.
for (uint i = 0; i < len; i++) {
((char *)data)[i] = getc_unlocked(m_fp);
if (feof_unlocked(m_fp) != 0) {
return i;
}
}
return len;
#else

View File

@ -347,26 +347,36 @@ StringBuilder & StringBuilder::formatList( const char * fmt, va_list arg )
}
/** Append a string. */
StringBuilder & StringBuilder::append( const char * s )
// Append a character.
StringBuilder & StringBuilder::append( char c )
{
return append(s, U32(strlen( s )));
return append(&c, 1);
}
// Append a string.
StringBuilder & StringBuilder::append( const char * s )
{
return append(s, U32(strlen( s )));
}
/** Append a string. */
// Append a string.
StringBuilder & StringBuilder::append(const char * s, uint len)
{
nvDebugCheck(s != NULL);
uint offset = length();
const uint size = offset + len + 1;
reserve(size);
strCpy(m_str + offset, len + 1, s, len);
uint offset = length();
const uint size = offset + len + 1;
reserve(size);
strCpy(m_str + offset, len + 1, s, len);
return *this;
}
StringBuilder & StringBuilder::append(const StringBuilder & str)
{
return append(str.m_str, str.length());
}
/** Append a formatted string. */
StringBuilder & StringBuilder::appendFormat( const char * fmt, ... )
@ -516,6 +526,19 @@ StringBuilder & StringBuilder::copy( const StringBuilder & s )
return *this;
}
void StringBuilder::removeChar(char c)
{
char * src = strchr(m_str, c);
if (src) {
char * dst = src;
src++;
while (*src) {
*dst++ = *src++;
}
*dst = '\0';
}
}
bool StringBuilder::endsWith(const char * str) const
{
uint l = uint(strlen(str));
@ -530,7 +553,7 @@ bool StringBuilder::beginsWith(const char * str) const
return strncmp(m_str, str, l) == 0;
}
// Find given char starting from the end.
// Find given char starting from the end. Why not use strrchr!?
char * StringBuilder::reverseFind(char c)
{
int length = (int)strlen(m_str) - 1;
@ -563,6 +586,19 @@ char * StringBuilder::release()
return str;
}
// Take ownership of string.
void StringBuilder::acquire(char * str)
{
if (str) {
m_size = strLen(str) + 1;
m_str = str;
}
else {
m_size = 0;
m_str = NULL;
}
}
// Swap strings.
void nv::swap(StringBuilder & a, StringBuilder & b) {
swap(a.m_size, b.m_size);
@ -585,19 +621,20 @@ const char * Path::extension() const
/*static */void Path::translatePath(char * path, char pathSeparator/*= NV_PATH_SEPARATOR*/) {
nvCheck(path != NULL);
for (int i = 0;; i++) {
if (path[i] == '\0') break;
if (path[i] == '\\' || path[i] == '/') path[i] = pathSeparator;
if (path != NULL) {
for (int i = 0;; i++) {
if (path[i] == '\0') break;
if (path[i] == '\\' || path[i] == '/') path[i] = pathSeparator;
}
}
}
/// Toggles path separators (ie. \\ into /).
void Path::translatePath(char pathSeparator/*=NV_PATH_SEPARATOR*/)
{
nvCheck(!isNull());
translatePath(m_str, pathSeparator);
if (!isNull()) {
translatePath(m_str, pathSeparator);
}
}
void Path::appendSeparator(char pathSeparator/*=NV_PATH_SEPARATOR*/)

View File

@ -105,8 +105,10 @@ namespace nv
StringBuilder & format( const char * format, ... ) __attribute__((format (printf, 2, 3)));
StringBuilder & formatList( const char * format, va_list arg );
StringBuilder & append(char c);
StringBuilder & append(const char * str);
StringBuilder & append(const char * str, uint len);
StringBuilder & append(const char * str, uint len);
StringBuilder & append(const StringBuilder & str);
StringBuilder & appendFormat(const char * format, ...) __attribute__((format (printf, 2, 3)));
StringBuilder & appendFormatList(const char * format, va_list arg);
@ -122,6 +124,8 @@ namespace nv
StringBuilder & toLower();
StringBuilder & toUpper();
void removeChar(char c);
bool endsWith(const char * str) const;
bool beginsWith(const char * str) const;
@ -129,15 +133,16 @@ namespace nv
char * reverseFind(char c);
void reset();
bool isNull() const { return m_size == 0; }
NV_FORCEINLINE bool isNull() 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; }
NV_FORCEINLINE const char * str() const { return m_str; }
NV_FORCEINLINE char * str() { return m_str; }
char * release();
char * release(); // Release ownership of string.
void acquire(char *); // Take ownership of string.
/// Implement value semantics.
StringBuilder & operator=( const StringBuilder & s ) {
@ -280,25 +285,25 @@ namespace nv
/// Equal operator.
bool operator==( const String & str ) const
{
return strMatch(str.data, data);
return strEqual(str.data, data);
}
/// Equal operator.
bool operator==( const char * str ) const
{
return strMatch(str, data);
return strEqual(str, data);
}
/// Not equal operator.
bool operator!=( const String & str ) const
{
return !strMatch(str.data, data);
return !strEqual(str.data, data);
}
/// Not equal operator.
bool operator!=( const char * str ) const
{
return !strMatch(str, data);
return !strEqual(str, data);
}
/// Returns true if this string is the null string.

View File

@ -76,13 +76,13 @@ namespace nv
void advance(uint offset) { seek(tell() + offset); }
// friends
// friends
friend Stream & operator<<( Stream & s, bool & c ) {
#if NV_OS_DARWIN && !NV_CC_CPP11
nvStaticCheck(sizeof(bool) == 4);
uint8 b = c ? 1 : 0;
s.serialize( &b, 1 );
c = (b == 1);
c = (b != 0);
#else
nvStaticCheck(sizeof(bool) == 1);
s.serialize( &c, 1 );

View File

@ -39,6 +39,28 @@ namespace nv
// These intentionally look like casts.
// uint64 casts:
template <typename T> inline uint64 U64(T x) { return x; }
//template <> inline uint64 U64<uint64>(uint64 x) { return x; }
template <> inline uint64 U64<int64>(int64 x) { nvDebugCheck(x >= 0); return (uint64)x; }
//template <> inline uint64 U32<uint32>(uint32 x) { return x; }
template <> inline uint64 U64<int32>(int32 x) { nvDebugCheck(x >= 0); return (uint64)x; }
//template <> inline uint64 U64<uint16>(uint16 x) { return x; }
template <> inline uint64 U64<int16>(int16 x) { nvDebugCheck(x >= 0); return (uint64)x; }
//template <> inline uint64 U64<uint8>(uint8 x) { return x; }
template <> inline uint64 U64<int8>(int8 x) { nvDebugCheck(x >= 0); return (uint64)x; }
// int64 casts:
template <typename T> inline int64 I64(T x) { return x; }
template <> inline int64 I64<uint64>(uint64 x) { nvDebugCheck(x <= NV_INT64_MAX); return (int64)x; }
//template <> inline uint64 U64<int64>(int64 x) { return x; }
//template <> inline uint64 U32<uint32>(uint32 x) { return x; }
//template <> inline uint64 U64<int32>(int32 x) { return x; }
//template <> inline uint64 U64<uint16>(uint16 x) { return x; }
//template <> inline uint64 U64<int16>(int16 x) { return x; }
//template <> inline uint64 U64<uint8>(uint8 x) { return x; }
//template <> inline uint64 U64<int8>(int8 x) { return x; }
// uint32 casts:
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; }
@ -50,6 +72,11 @@ namespace nv
//template <> inline uint32 U32<uint8>(uint8 x) { return x; }
template <> inline uint32 U32<int8>(int8 x) { nvDebugCheck(x >= 0); return (uint32)x; }
#if NV_OS_DARWIN
template <> inline uint32 U32<unsigned long>(unsigned long x) { nvDebugCheck(x <= NV_UINT32_MAX); return (uint32)x; }
template <> inline uint32 U32<long>(long x) { nvDebugCheck(x >= 0 && x <= NV_UINT32_MAX); return (uint32)x; }
#endif
// int32 casts:
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; }
@ -182,7 +209,7 @@ namespace nv
* @note isPowerOfTwo(x) == true -> nextPowerOfTwo(x) == x
* @note nextPowerOfTwo(x) = 2 << log2(x-1)
*/
inline uint nextPowerOfTwo( uint x )
inline uint32 nextPowerOfTwo(uint32 x)
{
nvDebugCheck( x != 0 );
#if 1 // On modern CPUs this is supposed to be as fast as using the bsr instruction.
@ -202,8 +229,19 @@ namespace nv
#endif
}
/// Return true if @a n is a power of two.
inline bool isPowerOfTwo( uint n )
inline uint64 nextPowerOfTwo(uint64 x)
{
nvDebugCheck(x != 0);
uint p = 1;
while (x > p) {
p += p;
}
return p;
}
// @@ Should I just use a macro instead?
template <typename T>
inline bool isPowerOfTwo(T n)
{
return (n & (n-1)) == 0;
}

View File

@ -56,6 +56,7 @@
# define NV_OS_MINGW 1
# define NV_OS_WIN32 1
#elif defined POSH_OS_OSX
# define NV_OS_OSX 1 // IC: Adding this, because iOS defines NV_OS_DARWIN too.
# define NV_OS_DARWIN 1
# define NV_OS_UNIX 1
#elif defined POSH_OS_IOS
@ -78,9 +79,9 @@
// Threading:
// some platforms don't implement __thread or similar for thread-local-storage
#if NV_OS_UNIX || NV_OS_ORBIS || NV_OS_IOS //ACStodoIOS darwin instead of ios?
#if NV_OS_UNIX || NV_OS_ORBIS || NV_OS_IOS
# define NV_OS_USE_PTHREAD 1
# if NV_OS_DARWIN || NV_OS_IOS
# if 0 //Apple finally added TLS support to iOS!// NV_OS_IOS
# define NV_OS_HAS_TLS_QUALIFIER 0
# else
# define NV_OS_HAS_TLS_QUALIFIER 1
@ -96,7 +97,7 @@
// NV_CPU_X86_64
// NV_CPU_PPC
// NV_CPU_ARM
// NV_CPU_AARCH64
// NV_CPU_ARM_64
#define NV_CPU_STRING POSH_CPU_STRING
@ -110,7 +111,7 @@
#elif defined POSH_CPU_STRONGARM
# define NV_CPU_ARM 1
#elif defined POSH_CPU_AARCH64
# define NV_CPU_AARCH64 1
# define NV_CPU_ARM_64 1
#else
# error "Unsupported CPU"
#endif
@ -148,10 +149,16 @@
#endif
// Endiannes:
#define NV_LITTLE_ENDIAN POSH_LITTLE_ENDIAN
#define NV_BIG_ENDIAN POSH_BIG_ENDIAN
#define NV_ENDIAN_STRING POSH_ENDIAN_STRING
// @@ POSH endian detection is broken for arm64 on iOS. They are bi-endian and iOS sets all their processors to little endian by default.
#if NV_OS_IOS
# define NV_LITTLE_ENDIAN 1
# define NV_BIG_ENDIAN 0
# define NV_ENDIAN_STRING "little"
#else
# define NV_LITTLE_ENDIAN POSH_LITTLE_ENDIAN
# define NV_BIG_ENDIAN POSH_BIG_ENDIAN
# define NV_ENDIAN_STRING POSH_ENDIAN_STRING
#endif
// Define the right printf prefix for size_t arguments:
#if POSH_64BIT_POINTER
@ -164,6 +171,28 @@
// cmake config
#include "nvconfig.h"
#if NV_OS_DARWIN
#include <stdint.h>
//#include <inttypes.h>
// 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;
// POSH gets this wrong due to __LP64__
#undef POSH_I64_PRINTF_PREFIX
#define POSH_I64_PRINTF_PREFIX "ll"
#else
// Type definitions:
typedef posh_u8_t uint8;
@ -175,8 +204,23 @@ typedef posh_i16_t int16;
typedef posh_u32_t uint32;
typedef posh_i32_t int32;
//#if NV_OS_DARWIN
// OSX-64 is supposed to be LP64 (longs and pointers are 64 bits), thus uint64 is defined as
// unsigned long. However, some OSX headers define it as unsigned long long, producing errors,
// even though both types are 64 bit. Ideally posh should handle that, but it has not been
// updated in ages, so here I'm just falling back to the standard C99 types defined in inttypes.h
//#include <inttypes.h>
//typedef posh_u64_t uint64_t;
//typedef posh_i64_t int64_t;
//#else
typedef posh_u64_t uint64;
typedef posh_i64_t int64;
//#endif
#if NV_OS_DARWIN
// To avoid duplicate definitions.
#define _UINT64
#endif
#endif
// Aliases
typedef uint32 uint;
@ -246,8 +290,10 @@ NV_COMPILER_CHECK(sizeof(uint32) == 4);
NV_COMPILER_CHECK(sizeof(int32) == 4);
NV_COMPILER_CHECK(sizeof(uint32) == 4);
#define NV_ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
#include <stddef.h> // for size_t
template <typename T, size_t N> char (&ArraySizeHelper(T (&array)[N]))[N];
#define NV_ARRAY_SIZE(x) sizeof(ArraySizeHelper(x))
//#define NV_ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
#if 0 // Disabled in The Witness.
#if NV_CC_MSVC
@ -269,8 +315,38 @@ NV_COMPILER_CHECK(sizeof(uint32) == 4);
NV_STRING_JOIN3(AtStartup_, __LINE__, Instance); \
}
namespace nv {
template <typename F>
struct ScopeExit {
ScopeExit(F f) : f(f) {}
~ScopeExit() { f(); }
F f;
};
template <typename F>
ScopeExit<F> MakeScopeExit(F f) {
return ScopeExit<F>(f);
};
}
#define NV_ON_RETURN(code) \
auto NV_STRING_JOIN2(scope_exit_, __LINE__) = nv::MakeScopeExit([=](){code;})
// Indicate the compiler that the parameter is not used to suppress compier warnings.
#if NV_CC_MSVC
#define NV_UNUSED(a) ((a)=(a))
#else
#define NV_UNUSED(a) _Pragma(NV_STRING(unused(a)))
#endif
#if NV_CC_GNUC || NV_CC_CLANG
#define NV_LIKELY(x) __builtin_expect(!!(x), 1)
#define NV_UNLIKELY(x) __builtin_expect(!!(x), 0)
#else
#define NV_LIKELY(x) x
#define NV_UNLIKELY(x) x
#endif
// Null index. @@ Move this somewhere else... it's only used by nvmesh.
//const unsigned int NIL = unsigned int(~0);