Merge changes from The Witness.

import/raw
castano 12 years ago
parent 5c2a857adc
commit 6fa3f99afd

@ -9,8 +9,8 @@ This array class requires the elements to be relocable; it uses memmove and real
using swap, but I honestly don't care. The only thing that you should be aware of is that internal pointers
are not supported.
The foreach macros that I use are very non-standard and somewhat confusing. It would be nice to have
standard foreach as in Qt.
Note also that push_back and resize does not support inserting arguments elements that are in the same
container. This is forbidden to prevent an extra copy.
*/
@ -19,7 +19,7 @@ standard foreach as in Qt.
#include "Debug.h"
#include "Stream.h"
#include "Utils.h" // swap
#include "ForEach.h" // swap
#include "ForEach.h" // PseudoIndex
#include <string.h> // memmove
#include <new> // for placement new
@ -27,69 +27,6 @@ standard foreach as in Qt.
namespace nv
{
// @@ Move this to utils?
/// Delete all the elements of a container.
template <typename T>
void deleteAll(T & container)
{
for (typename T::PseudoIndex i = container.start(); !container.isDone(i); container.advance(i))
{
delete container[i];
}
}
// @@ Move these templates to Utils.h
// @@ Specialize these methods for numeric, pointer, and pod types.
template <typename T>
void construct_range(T * restrict ptr, uint new_size, uint old_size) {
for (uint i = old_size; i < new_size; i++) {
new(ptr+i) T; // placement new
}
}
template <typename T>
void construct_range(T * restrict ptr, uint new_size, uint old_size, const T & elem) {
for (uint i = old_size; i < new_size; i++) {
new(ptr+i) T(elem); // placement new
}
}
template <typename T>
void destroy_range(T * restrict ptr, uint new_size, uint old_size) {
for (uint i = new_size; i < old_size; i++) {
(ptr+i)->~T(); // Explicit call to the destructor
}
}
template <typename T>
void fill(T * restrict dst, uint count, const T & value) {
for (uint i = 0; i < count; i++) {
dst[i] = value;
}
}
template <typename T>
void copy(T * restrict dst, const T * restrict src, uint count) {
for (uint i = 0; i < count; i++) {
dst[i] = src[i];
}
}
template <typename T>
bool find(const T & element, const T * restrict ptr, uint begin, uint end, uint * index) {
for (uint i = begin; i < end; i++) {
if (ptr[i] == element) {
if (index != NULL) *index = i;
return true;
}
}
return false;
}
/**
* Replacement for std::vector that is easier to debug and provides
* some nice foreach enumerators.
@ -107,7 +44,7 @@ namespace nv
}
// Constructor that initializes the vector with the given elements.
NV_FORCEINLINE Array(const T * ptr, int num) : m_buffer(NULL), m_capacity(0), m_size(0) {
NV_FORCEINLINE Array(const T * ptr, uint num) : m_buffer(NULL), m_capacity(0), m_size(0) {
copy(ptr, num);
}
@ -172,8 +109,12 @@ namespace nv
#if 1
nvDebugCheck(&val < m_buffer || &val > m_buffer+m_size);
setArraySize(m_size+1);
new(m_buffer+m_size-1) T(val);
uint old_size = m_size;
uint new_size = m_size + 1;
setArraySize(new_size);
construct_range(m_buffer, new_size, old_size, val);
#else
uint new_size = m_size + 1;
@ -205,7 +146,7 @@ namespace nv
}
/// Qt like push operator.
NV_FORCEINLINE Array<T> & operator<< ( const T & t )
NV_FORCEINLINE Array<T> & operator<< ( T & t )
{
push_back(t);
return *this;
@ -360,6 +301,8 @@ namespace nv
/// new ones with the given value.
void resize(uint new_size, const T & elem)
{
nvDebugCheck(&elem < m_buffer || &elem > m_buffer+m_size);
uint old_size = m_size;
// Destruct old elements (if we're shrinking).
@ -397,10 +340,13 @@ namespace nv
}
/// Copy elements to this array. Resizes it if needed.
NV_FORCEINLINE void copy(const T * ptr, uint num)
NV_FORCEINLINE void copy(const T * data, uint count)
{
resize( num ); // @@ call copy operator from 0 to min(num,m_size) and copy constructor from min(num,m_size) to num
::nv::copy(m_buffer, ptr, num);
destroy_range(m_buffer, count, m_size);
setArraySize(count);
::nv::copy(m_buffer, data, count);
}
/// Assignment operator.
@ -456,13 +402,14 @@ namespace nv
#endif
// Swap the members of this vector and the given vector.
friend void swap(Array & a, Array & b)
friend void swapMembers(Array & a, Array & b)
{
swap(a.m_buffer, b.m_buffer);
swap(a.m_capacity, b.m_capacity);
swap(a.m_size, b.m_size);
nv::swap(a.m_buffer, b.m_buffer);
nv::swap(a.m_capacity, b.m_capacity);
nv::swap(a.m_size, b.m_size);
}
protected:
// Change array size.
@ -510,6 +457,14 @@ protected:
};
template <typename T>
inline void swap(Array<T> & a, Array<T> & b)
{
swapMembers(a, b);
}
} // nv namespace
#endif // NV_CORE_ARRAY_H

@ -756,3 +756,50 @@ bool debug::isDebuggerPresent()
return getsid(getpid()) != getppid();
#endif
}
bool debug::attachToDebugger()
{
#if NV_OS_WIN32
if (isDebuggerPresent() == FALSE) {
Path process(1024);
process.copy("\"");
GetSystemDirectory(process.str() + 1, 1024 - 1);
process.appendSeparator();
process.appendFormat("VSJitDebugger.exe\" -p %lu", ::GetCurrentProcessId());
STARTUPINFO sSi;
memset(&sSi, 0, sizeof(sSi));
PROCESS_INFORMATION sPi;
memset(&sPi, 0, sizeof(sPi));
BOOL b = CreateProcess(NULL, process.str(), NULL, NULL, FALSE, 0, NULL, NULL, &sSi, &sPi);
if (b != FALSE) {
::WaitForSingleObject(sPi.hProcess, INFINITE);
DWORD dwExitCode;
::GetExitCodeProcess(sPi.hProcess, &dwExitCode);
if (dwExitCode != 0) //if exit code is zero, a debugger was selected
b = FALSE;
}
if (sPi.hThread != NULL) ::CloseHandle(sPi.hThread);
if (sPi.hProcess != NULL) ::CloseHandle(sPi.hProcess);
if (b == FALSE)
return false;
for (int i = 0; i < 5*60; i++) {
if (isDebuggerPresent())
break;
::Sleep(200);
}
}
nvDebugBreak();
#endif // NV_OS_WIN32
return true;
}

@ -18,9 +18,9 @@
#define NV_ABORT_EXIT 3
#define nvNoAssert(exp) \
do { \
(void)sizeof(exp); \
} while(0)
NV_MULTI_LINE_MACRO_BEGIN \
(void)sizeof(exp); \
NV_MULTI_LINE_MACRO_END
#if NV_NO_ASSERT
@ -50,42 +50,43 @@
# endif
#define nvDebugBreakOnce() \
do { \
static bool firstTime = true; \
if (firstTime) { firstTime = false; nvDebugBreak(); } \
} while(false)
# define nvAssertMacro(exp) \
do { \
if (!(exp)) { \
if (nvAbort(#exp, __FILE__, __LINE__, __FUNC__) == NV_ABORT_DEBUG) { \
nvDebugBreak(); \
} \
NV_MULTI_LINE_MACRO_BEGIN \
static bool firstTime = true; \
if (firstTime) { firstTime = false; nvDebugBreak(); } \
NV_MULTI_LINE_MACRO_END
#define nvAssertMacro(exp) \
NV_MULTI_LINE_MACRO_BEGIN \
if (!(exp)) { \
if (nvAbort(#exp, __FILE__, __LINE__, __FUNC__) == NV_ABORT_DEBUG) { \
nvDebugBreak(); \
} \
} while(false)
} \
NV_MULTI_LINE_MACRO_END
# define nvAssertMacroWithIgnoreAll(exp) \
do { \
#define nvAssertMacroWithIgnoreAll(exp) \
NV_MULTI_LINE_MACRO_BEGIN \
static bool ignoreAll = false; \
if (!ignoreAll && !(exp)) { \
if (nvAbort(#exp, __FILE__, __LINE__, __FUNC__) == NV_ABORT_DEBUG) { \
int result = nvAbort(#exp, __FILE__, __LINE__, __FUNC__); \
if (result == NV_ABORT_DEBUG) { \
nvDebugBreak(); \
} else { \
} else if (result == NV_ABORT_IGNORE) { \
ignoreAll = true; \
} \
} \
} while(false)
NV_MULTI_LINE_MACRO_END
# define nvAssert(exp) nvAssertMacro(exp)
# define nvCheck(exp) nvAssertMacro(exp)
#define nvAssert(exp) nvAssertMacro(exp)
#define nvCheck(exp) nvAssertMacro(exp)
# if defined(_DEBUG)
# define nvDebugAssert(exp) nvAssertMacro(exp)
# define nvDebugCheck(exp) nvAssertMacro(exp)
# else // _DEBUG
# define nvDebugAssert(exp) nvNoAssert(exp)
# define nvDebugCheck(exp) nvNoAssert(exp)
# endif // _DEBUG
#if defined(_DEBUG)
# define nvDebugAssert(exp) nvAssertMacro(exp)
# define nvDebugCheck(exp) nvAssertMacro(exp)
#else // _DEBUG
# define nvDebugAssert(exp) nvNoAssert(exp)
# define nvDebugCheck(exp) nvNoAssert(exp)
#endif // _DEBUG
#endif // NV_NO_ASSERT
@ -165,6 +166,7 @@ namespace nv
NVCORE_API void disableSigHandler();
NVCORE_API bool isDebuggerPresent();
NVCORE_API bool attachToDebugger();
}
} // nv namespace

@ -5,7 +5,7 @@
#define NV_CORE_FOREACH_H
/*
The foreach macros that I use are very non-standard and somewhat confusing, but I like them.
These foreach macros are very non-standard and somewhat confusing, but I like them.
*/
@ -32,10 +32,10 @@ struct PseudoIndexWrapper {
}
// PseudoIndex cannot have a dtor!
template <typename T> typename T::PseudoIndex & operator()(const T * container) {
template <typename T> typename T::PseudoIndex & operator()(const T * /*container*/) {
return *reinterpret_cast<typename T::PseudoIndex *>(memory);
}
template <typename T> const typename T::PseudoIndex & operator()(const T * container) const {
template <typename T> const typename T::PseudoIndex & operator()(const T * /*container*/) const {
return *reinterpret_cast<const typename T::PseudoIndex *>(memory);
}

@ -88,7 +88,7 @@ namespace nv
uint pos = (uint)ftell(m_fp);
fseek(m_fp, 0, SEEK_END);
uint end = (uint)ftell(m_fp);
fseek(m_fp, pos, SEEK_SET);
fseek(m_fp, pos, SEEK_SET);
#endif
return end;
}
@ -326,7 +326,7 @@ namespace nv
return len;
}
virtual void seek( uint pos ) { /*Not implemented*/ }
virtual void seek( uint /*pos*/ ) { /*Not implemented*/ }
virtual uint tell() const { return m_buffer.size(); }
virtual uint size() const { return m_buffer.size(); }

@ -483,7 +483,7 @@ const char * Path::extension() const
/// Toggles path separators (ie. \\ into /).
void Path::translatePath(char pathSeparator /*= NV_PATH_SEPARATOR*/)
void Path::translatePath(char pathSeparator/*=NV_PATH_SEPARATOR*/)
{
nvCheck( m_str != NULL );
@ -493,6 +493,18 @@ void Path::translatePath(char pathSeparator /*= NV_PATH_SEPARATOR*/)
}
}
void Path::appendSeparator(char pathSeparator/*=NV_PATH_SEPARATOR*/)
{
nvCheck(!isNull());
const uint l = length();
if (m_str[l] != '\\' && m_str[l] != '/') {
char separatorString[] = { pathSeparator, '\0' };
append(separatorString);
}
}
/**
* Strip the file name from a path.

@ -155,6 +155,8 @@ namespace nv
void translatePath(char pathSeparator = NV_PATH_SEPARATOR);
void appendSeparator(char pathSeparator = NV_PATH_SEPARATOR);
void stripFileName();
void stripExtension();

@ -73,6 +73,9 @@ namespace nv
virtual bool isSaving() const = 0;
void advance(uint offset) { seek(tell() + offset); }
// friends
friend Stream & operator<<( Stream & s, bool & c ) {
#if NV_OS_DARWIN

@ -13,6 +13,7 @@
#define NV_INT8_MIN (-128)
#define NV_INT8_MAX 127
#define NV_UINT8_MAX 255
#define NV_INT16_MIN (-32767-1)
#define NV_INT16_MAX 32767
#define NV_UINT16_MAX 0xffff
@ -27,16 +28,6 @@ namespace nv
{
// Less error prone than casting. From CB:
// http://cbloomrants.blogspot.com/2011/06/06-17-11-c-casting-is-devil.html
inline int8 asSigned(uint8 x) { return (int8) x; }
inline int16 asSigned(uint16 x) { return (int16) x; }
inline int32 asSigned(uint32 x) { return (int32) x; }
inline int64 asSigned(uint64 x) { return (int64) x; }
inline uint8 asUnsigned(int8 x) { return (uint8) x; }
inline uint16 asUnsigned(int16 x) { return (uint16) x; }
inline uint32 asUnsigned(int32 x) { return (uint32) x; }
inline uint64 asUnsigned(int64 x) { return (uint64) x; }
// uint32 casts:
template <typename T> inline uint32 toU32(T x) { return x; }
@ -60,12 +51,55 @@ namespace nv
//template <> inline int32 toI32<uint8>(uint8 x) { return x; }
//template <> inline int32 toI32<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; }
// 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; }
// 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 && x <= NV_UINT8_MAX); 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; }
/// Swap two values.
template <typename T>
inline void swap(T & a, T & b)
{
T temp = a;
T temp(a);
a = b;
b = temp;
}
@ -191,6 +225,67 @@ namespace nv
};
// @@ Move this to utils?
/// Delete all the elements of a container.
template <typename T>
void deleteAll(T & container)
{
for (typename T::PseudoIndex i = container.start(); !container.isDone(i); container.advance(i))
{
delete container[i];
}
}
// @@ Specialize these methods for numeric, pointer, and pod types.
template <typename T>
void construct_range(T * restrict ptr, uint new_size, uint old_size) {
for (uint i = old_size; i < new_size; i++) {
new(ptr+i) T; // placement new
}
}
template <typename T>
void construct_range(T * restrict ptr, uint new_size, uint old_size, const T & elem) {
for (uint i = old_size; i < new_size; i++) {
new(ptr+i) T(elem); // placement new
}
}
template <typename T>
void destroy_range(T * restrict ptr, uint new_size, uint old_size) {
for (uint i = new_size; i < old_size; i++) {
(ptr+i)->~T(); // Explicit call to the destructor
}
}
template <typename T>
void fill(T * restrict dst, uint count, const T & value) {
for (uint i = 0; i < count; i++) {
dst[i] = value;
}
}
template <typename T>
void copy(T * restrict dst, const T * restrict src, uint count) {
for (uint i = 0; i < count; i++) {
dst[i] = src[i];
}
}
template <typename T>
bool find(const T & element, const T * restrict ptr, uint begin, uint end, uint * index) {
for (uint i = begin; i < end; i++) {
if (ptr[i] == element) {
if (index != NULL) *index = i;
return true;
}
}
return false;
}
} // nv namespace
#endif // NV_CORE_UTILS_H

@ -90,7 +90,7 @@
#if defined POSH_COMPILER_CLANG
# define NV_CC_CLANG 1
# define NV_CC_GCC 1 // Clang is compatible with GCC.
# define NV_CC_GNUC 1 // Clang is compatible with GCC.
# define NV_CC_STRING "clang"
#elif defined POSH_COMPILER_GCC
# define NV_CC_GNUC 1
@ -168,6 +168,17 @@ typedef uint32 uint;
#define NV_STRING2(x) #x
#define NV_STRING(x) NV_STRING2(x)
#if NV_CC_MSVC
#define NV_MULTI_LINE_MACRO_BEGIN do {
#define NV_MULTI_LINE_MACRO_END \
__pragma(warning(push)) \
__pragma(warning(disable:4127)) \
} while(false) \
__pragma(warning(pop))
#else
#define NV_MULTI_LINE_MACRO_BEGIN do {
#define NV_MULTI_LINE_MACRO_END } while(false)
#endif
#if __cplusplus > 199711L
#define nvStaticCheck(x) static_assert(x)

Loading…
Cancel
Save