Initial commit
This commit is contained in:
54
ZUtil/Makefile
Normal file
54
ZUtil/Makefile
Normal file
@@ -0,0 +1,54 @@
|
||||
# ZUtil//Makefile
|
||||
# Makefile for ZUtil, requires GNU "make"
|
||||
|
||||
BINNAME := $(DIST)/libZUtil.a
|
||||
ifeq ($(TARGET),debug)
|
||||
BINNAME := $(subst .a,_d.a, $(BINNAME))
|
||||
endif
|
||||
|
||||
SRC := \
|
||||
ZAlloc.cpp \
|
||||
ZAllocWindow.cpp \
|
||||
ZBinaryFileReader.cpp \
|
||||
ZBinaryFileWriter.cpp \
|
||||
ZBinaryBufferReader.cpp \
|
||||
ZBinaryBufferWriter.cpp \
|
||||
ZConcurrency.cpp \
|
||||
ZEvent.cpp \
|
||||
ZIniReader.cpp \
|
||||
ZIniWriter.cpp \
|
||||
ZJSONReader.cpp \
|
||||
ZJSONWriter.cpp \
|
||||
ZKVTree.cpp \
|
||||
ZLog.cpp \
|
||||
ZMutex.cpp \
|
||||
ZName.cpp \
|
||||
ZRandomGenerator.cpp \
|
||||
ZReadWriteLock.cpp \
|
||||
ZRegistry.cpp \
|
||||
ZSemaphore.cpp \
|
||||
ZSimplexNoise.cpp \
|
||||
ZSimplexNoiseMap.cpp \
|
||||
ZTaskStream.cpp \
|
||||
ZThread.cpp \
|
||||
ZXMLReader.cpp \
|
||||
ZXMLWriter.cpp
|
||||
|
||||
|
||||
OBJ := $(addprefix obj/$(ARCH)/$(TARGET)/,$(subst .cpp,.o,$(SRC)) )
|
||||
|
||||
$(shell mkdir -p obj/$(ARCH)/$(TARGET))
|
||||
|
||||
$(BINNAME): $(OBJ)
|
||||
$(AR) cru $@ $+
|
||||
$(RANLIB) $@
|
||||
|
||||
# CLEAN
|
||||
clean:
|
||||
@-rm -r -f obj $(DIST)/libZUtil*.a
|
||||
|
||||
|
||||
# *.cpp files to *.o files
|
||||
obj/$(ARCH)/$(TARGET)/%.o: %.cpp
|
||||
@echo CXX $@
|
||||
@$(CXX) $(CXXFLAGS) -c $*.cpp -o obj/$(ARCH)/$(TARGET)/$*.o
|
||||
288
ZUtil/ZAlloc.cpp
Normal file
288
ZUtil/ZAlloc.cpp
Normal file
@@ -0,0 +1,288 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h> /* memmove() */
|
||||
#include <iostream>
|
||||
|
||||
#include <SST/SST_Concurrency.h>
|
||||
|
||||
#include <ZUtil/ZAlloc.hpp>
|
||||
|
||||
SST_Mutex AllocLock = SST_Concurrency_CreateMutex();
|
||||
|
||||
#if ZALLOC_CHECK_ALLOC
|
||||
|
||||
static ZAllocInfo* AllocList = NULL;
|
||||
|
||||
int ZAllocInfo::CurrentAllocCount = 0;
|
||||
int ZAllocInfo::CurrentCheckpoint = 0;
|
||||
|
||||
void ZAllocAddTrack(uintptr_t _address, size_t _size, const char *_file, int _line, int _checkpoint)
|
||||
{
|
||||
ZAllocInfo *info = (ZAllocInfo*)malloc(sizeof(ZAllocInfo));
|
||||
size_t len = strlen(_file);
|
||||
|
||||
info->Address = _address;
|
||||
info->Size = _size;
|
||||
|
||||
if(len > sizeof(info->File)-1)
|
||||
len = sizeof(info->File)-1;
|
||||
|
||||
memcpy(info->File, _file, len);
|
||||
info->File[len] = '\0';
|
||||
|
||||
info->Line = _line;
|
||||
info->Checkpoint = _checkpoint;
|
||||
|
||||
info->Next = NULL;
|
||||
|
||||
//Mutex may be NULL if doing pre-main() init
|
||||
if (AllocLock)
|
||||
SST_Concurrency_LockMutex(AllocLock);
|
||||
|
||||
info->Next = AllocList;
|
||||
AllocList = info;
|
||||
|
||||
#if ZALLOC_EXTRA_SPAMMY
|
||||
std::cerr << "Inc Alloc Count " << ZAllocInfo::CurrentAllocCount << " -> " << (ZAllocInfo::CurrentAllocCount+1) << std::endl;
|
||||
#endif
|
||||
|
||||
ZAllocInfo::CurrentAllocCount++;
|
||||
|
||||
//Mutex may be NULL if doing pre-main() init
|
||||
if (AllocLock)
|
||||
SST_Concurrency_UnlockMutex(AllocLock);
|
||||
}
|
||||
|
||||
void ZAllocRemoveTrack(uintptr_t _address)
|
||||
{
|
||||
//Mutex may be NULL if doing pre-main() init
|
||||
if (AllocLock)
|
||||
SST_Concurrency_LockMutex(AllocLock);
|
||||
|
||||
ZAllocInfo *prev = NULL;
|
||||
ZAllocInfo *cur = AllocList;
|
||||
|
||||
while (cur != NULL)
|
||||
{
|
||||
if (cur->Address == _address)
|
||||
{
|
||||
if (prev == NULL) //i.e. removing head
|
||||
AllocList = cur->Next;
|
||||
else
|
||||
prev->Next = cur->Next; //Remove "this" from the chain. link parent's next pointer to this one's next pointer so nobody has a reference to "this".
|
||||
|
||||
free(cur);
|
||||
|
||||
#if ZALLOC_EXTRA_SPAMMY
|
||||
std::cerr << "Dec Alloc Count " << ZAllocInfo::CurrentAllocCount << " -> " << (ZAllocInfo::CurrentAllocCount-1) << std::endl;
|
||||
#endif
|
||||
|
||||
ZAllocInfo::CurrentAllocCount--;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
prev = cur;
|
||||
cur = cur->Next;
|
||||
}
|
||||
|
||||
//Mutex may be NULL if doing pre-main() init
|
||||
if (AllocLock)
|
||||
SST_Concurrency_UnlockMutex(AllocLock);
|
||||
}
|
||||
|
||||
void ZAllocDumpUnfreed(ZMemState *_state)
|
||||
{
|
||||
SST_Concurrency_LockMutex(AllocLock);
|
||||
|
||||
size_t totalSize = 0;
|
||||
int checkpoint = _state == NULL ? 0 : _state->Checkpoint;
|
||||
|
||||
std::cerr << "--- ZAlloc Unfreed Memory Dump ---" << std::endl << std::endl;
|
||||
std::cerr << ZAllocInfo::CurrentAllocCount << " Current Unfreed Allocations:" << std::endl;
|
||||
|
||||
ZAllocInfo *cur = AllocList;
|
||||
|
||||
while (cur != NULL)
|
||||
{
|
||||
if (cur->Checkpoint >= checkpoint)
|
||||
{
|
||||
std::cerr << cur->File << "\n\tLINE: " << cur->Line << "\n\tADDRESS " << (void*)cur->Address << " (" << cur->Size << " bytes) unfreed!" << std::endl;
|
||||
totalSize += cur->Size;
|
||||
}
|
||||
|
||||
cur = cur->Next;
|
||||
}
|
||||
|
||||
std::cerr << "-----------------------------------------------------------\n";
|
||||
std::cerr << "Total Unfreed: " << totalSize << " bytes" << std::endl << std::endl;
|
||||
|
||||
std::cerr << "--- End Unfreed Memory Dump ---" << std::endl;
|
||||
|
||||
SST_Concurrency_UnlockMutex(AllocLock);
|
||||
}
|
||||
|
||||
//Debug Operator New
|
||||
void * operator new(size_t _size, const char *_file, int _line, int _checkpoint)
|
||||
throw()
|
||||
{
|
||||
void *ptr = (void*)malloc(_size);
|
||||
|
||||
ZAllocAddTrack((uintptr_t)ptr, _size, _file, _line, _checkpoint);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void * operator new[](size_t _size, const char* _file, int _line, int _checkpoint)
|
||||
throw()
|
||||
{
|
||||
void *ptr = (void*)malloc(_size);
|
||||
|
||||
ZAllocAddTrack((uintptr_t)ptr, _size, _file, _line, _checkpoint);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
//Debug Delete
|
||||
void operator delete(void *_ptr, const char* _file, int _line, int _checkpoint)
|
||||
{
|
||||
(void)_file;
|
||||
(void)_line;
|
||||
(void)_checkpoint;
|
||||
|
||||
ZAllocRemoveTrack((uintptr_t)_ptr);
|
||||
|
||||
free(_ptr);
|
||||
}
|
||||
|
||||
void operator delete[](void *_ptr, const char* _file, int _line, int _checkpoint)
|
||||
{
|
||||
(void)_file;
|
||||
(void)_line;
|
||||
(void)_checkpoint;
|
||||
|
||||
ZAllocRemoveTrack((uintptr_t)_ptr);
|
||||
|
||||
free(_ptr);
|
||||
}
|
||||
#ifndef __sun /* TODO: some error with Solaris Studio C++ compiler. */
|
||||
void operator delete(void *_ptr)
|
||||
{
|
||||
ZAllocRemoveTrack((uintptr_t)_ptr);
|
||||
|
||||
free(_ptr);
|
||||
}
|
||||
|
||||
void operator delete[](void *_ptr)
|
||||
{
|
||||
ZAllocRemoveTrack((uintptr_t)_ptr);
|
||||
|
||||
free(_ptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////
|
||||
/* Static New Functions and Fields */
|
||||
/////////////////////////////////////
|
||||
|
||||
//This contains all our statically allocated pointers
|
||||
void **StaticAllocArray = NULL;
|
||||
|
||||
//This is how many we can hold
|
||||
int StaticAllocCapacity = 0;
|
||||
|
||||
//This is how many we've got
|
||||
int StaticAllocSize = 0;
|
||||
|
||||
//This iterates and deletes
|
||||
void ZAllocDeleteStatic(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
//Mutex may be NULL if doing pre-main() init
|
||||
if (AllocLock)
|
||||
SST_Concurrency_LockMutex(AllocLock);
|
||||
|
||||
//Iterate, delete, then delete our static alloc array
|
||||
for (i = 0; i < StaticAllocSize; i++)
|
||||
free(StaticAllocArray[i]);
|
||||
|
||||
free(StaticAllocArray);
|
||||
|
||||
StaticAllocArray = NULL;
|
||||
StaticAllocCapacity = 0;
|
||||
StaticAllocSize = 0;
|
||||
|
||||
//Mutex may be NULL if doing pre-main() init
|
||||
if (AllocLock)
|
||||
SST_Concurrency_UnlockMutex(AllocLock);
|
||||
}
|
||||
|
||||
void ZAllocAddStaticPtr(void *_ptr)
|
||||
{
|
||||
//Mutex may be NULL if doing pre-main() init
|
||||
if (AllocLock)
|
||||
SST_Concurrency_LockMutex(AllocLock);
|
||||
|
||||
//If we need to, register with atexit to call ZAllocDeleteStatic
|
||||
if (StaticAllocArray == NULL)
|
||||
atexit(ZAllocDeleteStatic);
|
||||
|
||||
//Check to see if StaticAllocArray is full
|
||||
if (StaticAllocSize >= StaticAllocCapacity )
|
||||
{
|
||||
//Allocate new one
|
||||
size_t newCapacity = StaticAllocCapacity == 0 ? 128 : StaticAllocCapacity * 2;
|
||||
void *temp = malloc(newCapacity * sizeof(void*));
|
||||
|
||||
//Make sure we don't need to crash hard here
|
||||
if (temp == NULL)
|
||||
{
|
||||
std::cerr << "ZAlloc failed to allocate static tracking array!" << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
//Copy the old data in
|
||||
memmove(temp, StaticAllocArray, StaticAllocSize * sizeof(void*));
|
||||
|
||||
//Free the old pointer
|
||||
free(StaticAllocArray);
|
||||
|
||||
//Reset our pointer
|
||||
StaticAllocArray = (void**)temp;
|
||||
}
|
||||
|
||||
//Add new void*
|
||||
StaticAllocArray[StaticAllocSize] = _ptr;
|
||||
|
||||
//Increment size
|
||||
StaticAllocSize++;
|
||||
|
||||
//Mutex may be NULL if doing pre-main() init
|
||||
if (AllocLock)
|
||||
SST_Concurrency_UnlockMutex(AllocLock);
|
||||
}
|
||||
|
||||
//Static operator new
|
||||
void * operator new(size_t _size, znew_static_t _staticAlloc)
|
||||
{
|
||||
URFP(_staticAlloc);
|
||||
|
||||
void *ptr = (void*)malloc(_size);
|
||||
|
||||
ZAllocAddStaticPtr(ptr);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void * operator new[](size_t _size, znew_static_t _staticAlloc)
|
||||
{
|
||||
URFP(_staticAlloc);
|
||||
|
||||
void *ptr = (void*)malloc(_size);
|
||||
|
||||
ZAllocAddStaticPtr(ptr);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
230
ZUtil/ZAllocWindow.cpp
Normal file
230
ZUtil/ZAllocWindow.cpp
Normal file
@@ -0,0 +1,230 @@
|
||||
#include <ZUtil/ZAllocWindow.hpp>
|
||||
#include <ZUtil/ZAssert.hpp>
|
||||
|
||||
#include <SST/SST_OS.h>
|
||||
|
||||
#define ALLOC_BITS (0xF00D) // Used to flag a section of memory as 'allocated'
|
||||
#define DEALLOC_BITS (0xDEAD) // Used to flag a section of memory as 'deallocated'
|
||||
#define LOOP_BITS (0xCAB0) // Used to flag that the next allocated section is back at the beginning of the buffer
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZAllocWindow::ZAllocWindow()
|
||||
: Buffer(NULL), Begin(NULL), End(NULL),
|
||||
BufferSize(0), bOwnsBuffer(true),
|
||||
NumAllocs(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZAllocWindow::ZAllocWindow( size_t _buffersize )
|
||||
: Buffer(NULL), Begin(NULL), End(NULL),
|
||||
BufferSize(_buffersize), bOwnsBuffer(true),
|
||||
NumAllocs(0)
|
||||
{
|
||||
Resize(_buffersize);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZAllocWindow::~ZAllocWindow()
|
||||
{
|
||||
if (bOwnsBuffer)
|
||||
free(Buffer);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void* ZAllocWindow::Allocate( size_t _size )
|
||||
{
|
||||
// boundary is the location in memory that we cannot write past
|
||||
uintptr_t boundary;
|
||||
|
||||
// determine where our boundary is
|
||||
uintptr_t pool_begin = (uintptr_t)Buffer;
|
||||
uintptr_t pool_end = pool_begin + BufferSize;
|
||||
uintptr_t ptr_begin = (uintptr_t)Begin;
|
||||
uintptr_t ptr_end = (uintptr_t)End;
|
||||
|
||||
boundary = (ptr_begin > ptr_end ? ptr_begin :
|
||||
ptr_begin < ptr_end ? pool_end :
|
||||
( NumAllocs > 0 ? ptr_end :
|
||||
pool_end ) );
|
||||
|
||||
// align segment to word boundary
|
||||
uintptr_t seg_begin = (uintptr_t)End;
|
||||
uintptr_t seg_end = (uintptr_t)SST_OS_AlignPtr((void*)(seg_begin + 2*sizeof(uint32_t) + _size), sizeof(void*));
|
||||
|
||||
// check segment against boundary
|
||||
if (seg_end > boundary) {
|
||||
|
||||
// if the segment has not just run up against the pool end, we are done
|
||||
if (boundary != pool_end) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// signal a loop (if less than 'end') and check again
|
||||
if (seg_begin < pool_end) {
|
||||
uint32_t* ptr_32 = (uint32_t*)seg_begin;
|
||||
ptr_32[0] = (uint32_t)LOOP_BITS;
|
||||
}
|
||||
|
||||
boundary = ptr_begin;
|
||||
|
||||
seg_begin = pool_begin;
|
||||
seg_end = (uintptr_t)SST_OS_AlignPtr((void*)(seg_begin + 2 * sizeof(uint32_t) + _size), sizeof(void*));
|
||||
}
|
||||
|
||||
// check segment against boundary again
|
||||
if (seg_end <= boundary) {
|
||||
NumAllocs++;
|
||||
|
||||
// set size as first element in block
|
||||
uint32_t* ptr_32 = (uint32_t*)seg_begin;
|
||||
ptr_32[0] = (uint32_t)ALLOC_BITS;
|
||||
ptr_32[1] = (uint32_t)(seg_end - seg_begin);
|
||||
|
||||
// set new End pointer to ptr_end
|
||||
End = (void*)seg_end;
|
||||
|
||||
// if End == BufferEnd, End == 0
|
||||
if (End == (void*)((uintptr_t)Buffer + (uintptr_t)BufferSize))
|
||||
End = Buffer;
|
||||
|
||||
// return the address of the first non-reserved element of the segment
|
||||
return &ptr_32[2];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZAllocWindow::Deallocate( void* _data )
|
||||
{
|
||||
// check size before data
|
||||
uint32_t* ptr_32 = (uint32_t*)((uintptr_t)_data - (2*sizeof(uint32_t)));
|
||||
uint32_t flag = ptr_32[0];
|
||||
uint32_t size = ptr_32[1];
|
||||
|
||||
// quick sanity check
|
||||
ZASSERT(flag == ALLOC_BITS, "ZAllocWindow passed invalid pointer to deallocate!");
|
||||
ZASSERT(size < BufferSize, "ZAllocWindow passed corrupted pointer to deallocate!");
|
||||
|
||||
// mark size slot as 'freed'
|
||||
ptr_32[0] = (uint32_t)DEALLOC_BITS;
|
||||
NumAllocs--;
|
||||
|
||||
// see if this was the oldest allocated block, and start rolling up
|
||||
if (ptr_32 == Begin) {
|
||||
while (WHILE_TRUE) {
|
||||
ptr_32 = (uint32_t*)Begin;
|
||||
|
||||
// if begin is at or past end, loop to the beginning
|
||||
if ((uintptr_t)ptr_32 >= ((uintptr_t)Begin + BufferSize)) {
|
||||
Begin = Buffer;
|
||||
continue;
|
||||
}
|
||||
|
||||
// determine flag (size if needed)
|
||||
flag = ptr_32[0];
|
||||
|
||||
// if this is a loop flag, start again at the beginning
|
||||
if (flag == LOOP_BITS) {
|
||||
Begin = Buffer;
|
||||
continue;
|
||||
}
|
||||
|
||||
// if this is a dealloc flag, dealloc the segment, increment Begin
|
||||
if (flag == DEALLOC_BITS) {
|
||||
size = ptr_32[1];
|
||||
|
||||
uintptr_t seg_start = (uintptr_t)ptr_32;
|
||||
uintptr_t seg_end = seg_start + size;
|
||||
|
||||
Begin = (void*)seg_end;
|
||||
|
||||
#ifdef _DEBUG
|
||||
ptr_32[1] = DEALLOC_BITS;
|
||||
#endif
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZAllocWindow::Reset()
|
||||
{
|
||||
NumAllocs = 0;
|
||||
Begin = Buffer;
|
||||
End = Buffer;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
bool ZAllocWindow::Resize( size_t _newsize )
|
||||
{
|
||||
// don't resize if we have allocations or don't own the buffer
|
||||
if (NumAllocs > 0 || !bOwnsBuffer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check newsize is zero to free everything
|
||||
if (_newsize == 0) {
|
||||
if (Buffer != NULL) {
|
||||
free(Buffer);
|
||||
Buffer = NULL;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// free current buffer if not NULL
|
||||
if (Buffer != NULL) {
|
||||
free(Buffer);
|
||||
}
|
||||
|
||||
// allocate new buffer and return success / failure
|
||||
Buffer = malloc(_newsize);
|
||||
Begin = Buffer;
|
||||
End = Buffer;
|
||||
BufferSize = _newsize;
|
||||
|
||||
return Buffer != NULL;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
bool ZAllocWindow::SetBuffer( void* _buffer, size_t _buffersize )
|
||||
{
|
||||
// don't accept buffer if we have allocations
|
||||
if (NumAllocs > 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// if the new buffer is null, just reallocate to buffersize
|
||||
if (_buffer == NULL) {
|
||||
bOwnsBuffer = true;
|
||||
return Resize(_buffersize);
|
||||
}
|
||||
|
||||
// Get rid of the current buffer if we need to
|
||||
if (Buffer != NULL) {
|
||||
free(Buffer);
|
||||
}
|
||||
|
||||
// lose ownership and set parameters, return success
|
||||
bOwnsBuffer = false;
|
||||
Buffer = _buffer;
|
||||
Begin = Buffer;
|
||||
End = Buffer;
|
||||
BufferSize = _buffersize;
|
||||
|
||||
return true;
|
||||
}
|
||||
148
ZUtil/ZBinaryBufferReader.cpp
Normal file
148
ZUtil/ZBinaryBufferReader.cpp
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
ZBinaryBufferReader.cpp
|
||||
Author: Chris Ertel <crertel@762studios.com>, Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 3/6/2013
|
||||
|
||||
Purpose:
|
||||
|
||||
Reads a binary stream from memory.
|
||||
|
||||
License:
|
||||
|
||||
TODO
|
||||
|
||||
*/
|
||||
|
||||
#include <ZUtil/ZBinaryBufferReader.hpp>
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
uint8_t ZBinaryBufferReader::ReadU8()
|
||||
{
|
||||
uint8_t retval = (uint8_t)Data[Offset];
|
||||
|
||||
++Offset;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
uint16_t ZBinaryBufferReader::ReadU16()
|
||||
{
|
||||
uint16_t value;
|
||||
memcpy(&value, GetPosition(), sizeof(uint16_t));
|
||||
|
||||
if(GetStreamByteOrder() != SST_BYTEORDER_HOST)
|
||||
value = SST_OS_ByteSwap16(value);
|
||||
|
||||
Offset += sizeof(uint16_t);
|
||||
return value;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
uint32_t ZBinaryBufferReader::ReadU32()
|
||||
{
|
||||
uint32_t value;
|
||||
memcpy(&value, GetPosition(), sizeof(uint32_t));
|
||||
|
||||
if(GetStreamByteOrder() != SST_BYTEORDER_HOST)
|
||||
value = SST_OS_ByteSwap32(value);
|
||||
|
||||
Offset += sizeof(uint32_t);
|
||||
return value;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
uint64_t ZBinaryBufferReader::ReadU64()
|
||||
{
|
||||
uint64_t value;
|
||||
memcpy(&value, GetPosition(), sizeof(uint64_t));
|
||||
|
||||
if(GetStreamByteOrder() != SST_BYTEORDER_HOST)
|
||||
value = SST_OS_ByteSwap64(value);
|
||||
|
||||
Offset += sizeof(uint64_t);
|
||||
return value;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZBinaryBufferReader::ReadU8Array(uint8_t* ptr, size_t count)
|
||||
{
|
||||
memcpy(ptr, GetPosition(), count);
|
||||
Offset += count;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZBinaryBufferReader::ReadU16Array(uint16_t* ptr, size_t count)
|
||||
{
|
||||
if(GetStreamByteOrder() == SST_BYTEORDER_HOST)
|
||||
{
|
||||
memcpy(ptr, GetPosition(), sizeof(uint16_t) * count);
|
||||
Offset += sizeof(uint16_t) * count;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(size_t i=0; i<count; i++)
|
||||
ptr[i] = ReadU16();
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZBinaryBufferReader::ReadU32Array(uint32_t* ptr, size_t count)
|
||||
{
|
||||
if(GetStreamByteOrder() == SST_BYTEORDER_HOST)
|
||||
{
|
||||
memcpy(ptr, GetPosition(), sizeof(uint32_t) * count);
|
||||
Offset += sizeof(uint32_t) * count;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(size_t i=0; i<count; i++)
|
||||
ptr[i] = ReadU32();
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZBinaryBufferReader::ReadU64Array(uint64_t* ptr, size_t count)
|
||||
{
|
||||
if(GetStreamByteOrder() == SST_BYTEORDER_HOST)
|
||||
{
|
||||
memcpy(ptr, GetPosition(), sizeof(uint64_t) * count);
|
||||
Offset += sizeof(uint64_t) * count;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(size_t i=0; i<count; i++)
|
||||
ptr[i] = ReadU64();
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void* ZBinaryBufferReader::ReadPointer()
|
||||
{
|
||||
uintptr_t value;
|
||||
memcpy(&value, GetPosition(), sizeof(uintptr_t));
|
||||
|
||||
if(GetStreamByteOrder() != SST_BYTEORDER_HOST)
|
||||
{
|
||||
switch(sizeof(uintptr_t))
|
||||
{
|
||||
case sizeof(uint16_t): value = (uintptr_t)SST_OS_ByteSwap16((uint16_t)value); break;
|
||||
case sizeof(uint32_t): value = (uintptr_t)SST_OS_ByteSwap32((uint32_t)value); break;
|
||||
case sizeof(uint64_t): value = (uintptr_t)SST_OS_ByteSwap64((uint64_t)value); break;
|
||||
}
|
||||
}
|
||||
|
||||
Offset += sizeof(uintptr_t);
|
||||
return (void*)value;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
148
ZUtil/ZBinaryBufferWriter.cpp
Normal file
148
ZUtil/ZBinaryBufferWriter.cpp
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
ZBinaryBufferWriter.cpp
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 6/05/2013
|
||||
|
||||
Purpose:
|
||||
|
||||
Writes a binary stream to memory
|
||||
|
||||
License:
|
||||
|
||||
TODO
|
||||
|
||||
*/
|
||||
|
||||
#include <ZUtil/ZBinaryBufferWriter.hpp>
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZBinaryBufferWriter::WriteU8(uint8_t v)
|
||||
{
|
||||
Data[Offset] = v;
|
||||
++Offset;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZBinaryBufferWriter::WriteU16(uint16_t v)
|
||||
{
|
||||
if(GetStreamByteOrder() != SST_BYTEORDER_HOST)
|
||||
v = SST_OS_ByteSwap16(v);
|
||||
|
||||
memcpy(Data+Offset, &v, sizeof(uint16_t));
|
||||
|
||||
Offset += sizeof(uint16_t);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZBinaryBufferWriter::WriteU32(uint32_t v)
|
||||
{
|
||||
if(GetStreamByteOrder() != SST_BYTEORDER_HOST)
|
||||
v = SST_OS_ByteSwap32(v);
|
||||
|
||||
memcpy(Data+Offset, &v, sizeof(uint32_t));
|
||||
|
||||
Offset += sizeof(uint32_t);
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZBinaryBufferWriter::WriteU64(uint64_t v)
|
||||
{
|
||||
if(GetStreamByteOrder() != SST_BYTEORDER_HOST)
|
||||
v = SST_OS_ByteSwap64(v);
|
||||
|
||||
memcpy(Data+Offset, &v, sizeof(uint64_t));
|
||||
|
||||
Offset += sizeof(uint64_t);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZBinaryBufferWriter::WriteU8Array(const uint8_t* v, size_t count)
|
||||
{
|
||||
memcpy(Data+Offset, v, count);
|
||||
|
||||
Offset += sizeof(uint8_t) * count;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZBinaryBufferWriter::WriteU16Array(const uint16_t* v, size_t count)
|
||||
{
|
||||
if(GetStreamByteOrder() == SST_BYTEORDER_HOST)
|
||||
memcpy(Data+Offset, v, count*sizeof(uint16_t));
|
||||
else
|
||||
{
|
||||
for(size_t i=0; i<count; i++)
|
||||
{
|
||||
uint16_t value = SST_OS_ByteSwap16(v[i]);
|
||||
memcpy(Data+Offset+i*sizeof(uint16_t), &value, sizeof(uint16_t));
|
||||
}
|
||||
}
|
||||
|
||||
Offset += sizeof(uint16_t) * count;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZBinaryBufferWriter::WriteU32Array(const uint32_t* v, size_t count)
|
||||
{
|
||||
if(GetStreamByteOrder() == SST_BYTEORDER_HOST)
|
||||
memcpy(Data+Offset, v, count*sizeof(uint32_t));
|
||||
else
|
||||
{
|
||||
for(size_t i=0; i<count; i++)
|
||||
{
|
||||
uint32_t value = SST_OS_ByteSwap32(v[i]);
|
||||
memcpy(Data+Offset+i*sizeof(uint32_t), &value, sizeof(uint32_t));
|
||||
}
|
||||
}
|
||||
|
||||
Offset += sizeof(uint32_t) * count;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZBinaryBufferWriter::WriteU64Array(const uint64_t* v, size_t count)
|
||||
{
|
||||
if(GetStreamByteOrder() == SST_BYTEORDER_HOST)
|
||||
memcpy(Data+Offset, v, count*sizeof(uint16_t));
|
||||
else
|
||||
{
|
||||
for(size_t i=0; i<count; i++)
|
||||
{
|
||||
uint64_t value = SST_OS_ByteSwap64(v[i]);
|
||||
memcpy(Data+Offset+i*sizeof(uint64_t), &value, sizeof(uint64_t));
|
||||
}
|
||||
}
|
||||
|
||||
Offset += sizeof(uint64_t) * count;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZBinaryBufferWriter::WritePointer(void* pointer)
|
||||
{
|
||||
uintptr_t ptrValue = (uintptr_t)pointer;
|
||||
|
||||
if(GetStreamByteOrder() == SST_BYTEORDER_HOST)
|
||||
memcpy(Data+Offset, &ptrValue, sizeof(uintptr_t));
|
||||
else
|
||||
{
|
||||
switch(sizeof(uintptr_t))
|
||||
{
|
||||
case sizeof(uint16_t): WriteU16((uint16_t)ptrValue); break;
|
||||
case sizeof(uint32_t): WriteU32((uint32_t)ptrValue); break;
|
||||
case sizeof(uint64_t): WriteU64((uint64_t)ptrValue); break;
|
||||
}
|
||||
}
|
||||
|
||||
Offset += sizeof(uintptr_t);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
155
ZUtil/ZBinaryFileReader.cpp
Normal file
155
ZUtil/ZBinaryFileReader.cpp
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
ZBinaryFileReader.cpp
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 3/6/2013
|
||||
|
||||
Purpose:
|
||||
|
||||
Reads a binary stream from a SST_File handle. NOTE: On 32-bit platforms, only files up to 4GB are supported.
|
||||
|
||||
License:
|
||||
|
||||
TODO
|
||||
|
||||
*/
|
||||
|
||||
#include <ZUtil/ZBinaryFileReader.hpp>
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZBinaryFileReader::ZBinaryFileReader(SST_File handle, SST_ByteOrder bo)
|
||||
: ZBinaryReader(bo), fp(handle)
|
||||
{
|
||||
uint64_t size64;
|
||||
uint64_t offset64;
|
||||
|
||||
SST_OS_GetFilePointer(fp, &offset64);
|
||||
size64 = SST_OS_GetFileSize(fp);
|
||||
|
||||
//Downcast (potentially) to size_t
|
||||
Size = (size_t)size64;
|
||||
Offset = (size_t)offset64;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
uint8_t ZBinaryFileReader::ReadU8()
|
||||
{
|
||||
uint8_t retval;
|
||||
|
||||
SST_OS_ReadFile(fp, &retval, sizeof(uint8_t));
|
||||
|
||||
++Offset;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
uint16_t ZBinaryFileReader::ReadU16()
|
||||
{
|
||||
uint16_t value;
|
||||
|
||||
SST_OS_ReadFile(fp, &value, sizeof(uint16_t));
|
||||
|
||||
if(GetStreamByteOrder() != SST_BYTEORDER_HOST)
|
||||
value = SST_OS_ByteSwap16(value);
|
||||
|
||||
Offset += sizeof(uint16_t);
|
||||
return value;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
uint32_t ZBinaryFileReader::ReadU32()
|
||||
{
|
||||
uint32_t value;
|
||||
SST_OS_ReadFile(fp, &value, sizeof(uint32_t));
|
||||
|
||||
|
||||
if(GetStreamByteOrder() != SST_BYTEORDER_HOST)
|
||||
value = SST_OS_ByteSwap32(value);
|
||||
|
||||
Offset += sizeof(uint32_t);
|
||||
return value;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
uint64_t ZBinaryFileReader::ReadU64()
|
||||
{
|
||||
uint64_t value;
|
||||
SST_OS_ReadFile(fp, &value, sizeof(uint64_t));
|
||||
|
||||
|
||||
if(GetStreamByteOrder() != SST_BYTEORDER_HOST)
|
||||
value = SST_OS_ByteSwap64(value);
|
||||
|
||||
Offset += sizeof(uint64_t);
|
||||
return value;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZBinaryFileReader::ReadU8Array(uint8_t* ptr, size_t count)
|
||||
{
|
||||
SST_OS_ReadFile(fp, ptr, count);
|
||||
|
||||
Offset += count;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZBinaryFileReader::ReadU16Array(uint16_t* ptr, size_t count)
|
||||
{
|
||||
if(GetStreamByteOrder() == SST_BYTEORDER_HOST)
|
||||
{
|
||||
SST_OS_ReadFile(fp, ptr, sizeof(uint16_t) * count);
|
||||
Offset += sizeof(uint16_t) * count;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(size_t i=0; i<count; i++)
|
||||
ptr[i] = ReadU16();
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZBinaryFileReader::ReadU32Array(uint32_t* ptr, size_t count)
|
||||
{
|
||||
if(GetStreamByteOrder() == SST_BYTEORDER_HOST)
|
||||
{
|
||||
SST_OS_ReadFile(fp, ptr, sizeof(uint32_t) * count);
|
||||
Offset += sizeof(uint32_t) * count;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(size_t i=0; i<count; i++)
|
||||
ptr[i] = ReadU32();
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZBinaryFileReader::ReadU64Array(uint64_t* ptr, size_t count)
|
||||
{
|
||||
if(GetStreamByteOrder() == SST_BYTEORDER_HOST)
|
||||
{
|
||||
SST_OS_ReadFile(fp, ptr, sizeof(uint64_t) * count);
|
||||
Offset += sizeof(uint64_t) * count;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(size_t i=0; i<count; i++)
|
||||
ptr[i] = ReadU64();
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZBinaryFileReader::SeekTo(size_t offset)
|
||||
{
|
||||
SST_OS_SeekFile(fp, (int64_t)offset, SST_SEEK_START);
|
||||
Offset = offset;
|
||||
}
|
||||
160
ZUtil/ZBinaryFileWriter.cpp
Normal file
160
ZUtil/ZBinaryFileWriter.cpp
Normal file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
ZBinaryFileWriter.cpp
|
||||
Author: Chris Ertel <crertel@762studios.com>, Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 3/11/2013
|
||||
|
||||
Purpose:
|
||||
|
||||
Writes a binary stream from a SST_File handle. NOTE: On 32-bit platforms, only files up to 4GB are supported.
|
||||
|
||||
License:
|
||||
|
||||
TODO
|
||||
|
||||
*/
|
||||
|
||||
#include <ZUtil/ZBinaryFileWriter.hpp>
|
||||
|
||||
/*
|
||||
TODO: This implementation makes use of SST_File, which is a thin wrapper over system calls. Because of this,
|
||||
small writes can reduce performance. A 4KB buffer (or better, one that is a multiple of inode size) would
|
||||
help reduce the overhead.
|
||||
*/
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZBinaryFileWriter::ZBinaryFileWriter(SST_File handle, SST_ByteOrder bo) :
|
||||
ZBinaryWriter(bo), fp(handle)
|
||||
{
|
||||
uint64_t offset64;
|
||||
|
||||
SST_OS_GetFilePointer(fp, &offset64);
|
||||
|
||||
Offset = (size_t)offset64;
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZBinaryFileWriter::WriteU8(uint8_t v)
|
||||
{
|
||||
SST_OS_WriteFile(fp, &v, sizeof(uint8_t));
|
||||
|
||||
++Offset;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZBinaryFileWriter::WriteU16(uint16_t v)
|
||||
{
|
||||
if(GetStreamByteOrder() != SST_BYTEORDER_HOST)
|
||||
v = SST_OS_ByteSwap16(v);
|
||||
|
||||
SST_OS_WriteFile(fp, &v, sizeof(uint16_t));
|
||||
|
||||
Offset += sizeof(uint16_t);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZBinaryFileWriter::WriteU32(uint32_t v)
|
||||
{
|
||||
if(GetStreamByteOrder() != SST_BYTEORDER_HOST)
|
||||
v = SST_OS_ByteSwap32(v);
|
||||
|
||||
SST_OS_WriteFile(fp, &v, sizeof(uint32_t));
|
||||
|
||||
Offset += sizeof(uint32_t);
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZBinaryFileWriter::WriteU64(uint64_t v)
|
||||
{
|
||||
if(GetStreamByteOrder() != SST_BYTEORDER_HOST)
|
||||
v = SST_OS_ByteSwap64(v);
|
||||
|
||||
SST_OS_WriteFile(fp, &v, sizeof(uint64_t));
|
||||
|
||||
Offset += sizeof(uint64_t);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZBinaryFileWriter::WriteU8Array(const uint8_t* v, size_t count)
|
||||
{
|
||||
SST_OS_WriteFile(fp, v, count);
|
||||
|
||||
Offset += sizeof(uint8_t) * count;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZBinaryFileWriter::WriteU16Array(const uint16_t* v, size_t count)
|
||||
{
|
||||
if(GetStreamByteOrder() == SST_BYTEORDER_HOST)
|
||||
SST_OS_WriteFile(fp, v, count * sizeof(uint16_t));
|
||||
else
|
||||
{
|
||||
for(size_t i=0; i<count; i++)
|
||||
{
|
||||
uint16_t value = SST_OS_ByteSwap16(v[i]);
|
||||
SST_OS_WriteFile(fp, &value, sizeof(uint16_t));
|
||||
}
|
||||
}
|
||||
|
||||
Offset += sizeof(uint16_t) * count;
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZBinaryFileWriter::WriteU32Array(const uint32_t* v, size_t count)
|
||||
{
|
||||
if(GetStreamByteOrder() == SST_BYTEORDER_HOST)
|
||||
SST_OS_WriteFile(fp, v, count * sizeof(uint32_t));
|
||||
else
|
||||
{
|
||||
for(size_t i=0; i<count; i++)
|
||||
{
|
||||
uint32_t value = SST_OS_ByteSwap32(v[i]);
|
||||
SST_OS_WriteFile(fp, &value, sizeof(uint32_t));
|
||||
}
|
||||
}
|
||||
|
||||
Offset += sizeof(uint32_t) * count;
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZBinaryFileWriter::WriteU64Array(const uint64_t* v, size_t count)
|
||||
{
|
||||
if(GetStreamByteOrder() == SST_BYTEORDER_HOST)
|
||||
SST_OS_WriteFile(fp, v, count * sizeof(uint64_t));
|
||||
else
|
||||
{
|
||||
for(size_t i=0; i<count; i++)
|
||||
{
|
||||
uint64_t value = SST_OS_ByteSwap64(v[i]);
|
||||
SST_OS_WriteFile(fp, &value, sizeof(uint64_t));
|
||||
}
|
||||
}
|
||||
|
||||
Offset += sizeof(uint64_t) * count;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZBinaryFileWriter::SeekTo(size_t offset)
|
||||
{
|
||||
uint64_t offset64 = (uint64_t)offset; //Because size_t can be 32 bits, casting to int64_t can sign extend (bad), cast to uint64_t first so it is zero-extended.
|
||||
SST_OS_SeekFile(fp, (int64_t)offset64, SST_SEEK_START);
|
||||
|
||||
Offset = offset;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
50
ZUtil/ZConcurrency.cpp
Normal file
50
ZUtil/ZConcurrency.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
#include <ZUtil/ZConcurrency.hpp>
|
||||
#include <SST/SST_Concurrency.h>
|
||||
|
||||
ZThreadContext ZConcurrency::CreateThread(int(*_func)(void*), void *_arg)
|
||||
{
|
||||
ZThreadContext context;
|
||||
|
||||
context.Thread = SST_Concurrency_CreateThread(_func, _arg);
|
||||
|
||||
//TODO - this doesn't install the running thread id, just this current thread id
|
||||
//bleargh
|
||||
//context.ThreadId = SST_Concurrency_GetThreadId();
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
void ZConcurrency::DestroyThread(ZThreadContext& _context)
|
||||
{
|
||||
SST_Concurrency_DestroyThread(_context.Thread);
|
||||
|
||||
_context.Thread = NULL;
|
||||
_context.ThreadId = 0;
|
||||
_context.ThreadExitStatus = 0;
|
||||
}
|
||||
|
||||
void ZConcurrency::SleepThread(uint32_t _ms)
|
||||
{
|
||||
SST_Concurrency_SleepThread(_ms);
|
||||
}
|
||||
|
||||
uint32_t ZConcurrency::GetThreadId()
|
||||
{
|
||||
return SST_Concurrency_GetThreadId();
|
||||
}
|
||||
|
||||
uint64_t ZConcurrency::GetTicks()
|
||||
{
|
||||
return SST_Concurrency_GetTicks();
|
||||
}
|
||||
|
||||
bool ZConcurrency::WaitThread(ZThreadContext& _context)
|
||||
{
|
||||
return SST_Concurrency_WaitThread(_context.Thread, &_context.ThreadExitStatus) != 0;
|
||||
}
|
||||
|
||||
void ZConcurrency::YieldThread()
|
||||
{
|
||||
SST_Concurrency_YieldThread();
|
||||
}
|
||||
|
||||
34
ZUtil/ZEvent.cpp
Normal file
34
ZUtil/ZEvent.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#include <ZUtil/ZEvent.hpp>
|
||||
#include <ZUtil/ZAssert.hpp>
|
||||
#include <SST/SST_Concurrency.h> //Need this for SST_WAIT_INFINITE
|
||||
|
||||
ZEvent::ZEvent()
|
||||
: Event(SST_Concurrency_CreateEvent())
|
||||
{
|
||||
ZASSERT_RUNTIME(Event != NULL, "ZEvent failed to allocate event from libsst-concurrency!");
|
||||
}
|
||||
|
||||
ZEvent::~ZEvent()
|
||||
{
|
||||
SST_Concurrency_DestroyEvent(Event);
|
||||
}
|
||||
|
||||
void ZEvent::Notify()
|
||||
{
|
||||
SST_Concurrency_SignalEvent(Event);
|
||||
}
|
||||
|
||||
void ZEvent::Reset()
|
||||
{
|
||||
SST_Concurrency_ResetEvent(Event);
|
||||
}
|
||||
|
||||
bool ZEvent::Wait()
|
||||
{
|
||||
return SST_Concurrency_WaitEvent(Event, SST_WAIT_INFINITE) != 0;
|
||||
}
|
||||
|
||||
bool ZEvent::Wait( uint32_t _ms )
|
||||
{
|
||||
return SST_Concurrency_WaitEvent(Event, _ms) != 0;
|
||||
}
|
||||
256
ZUtil/ZIniReader.cpp
Normal file
256
ZUtil/ZIniReader.cpp
Normal file
@@ -0,0 +1,256 @@
|
||||
#include <ZUtil/ZIniReader.hpp>
|
||||
|
||||
#include <ZSTL/ZBasicStringAlgo.hpp>
|
||||
|
||||
bool ZIniReader::Read(const char* data, size_t length)
|
||||
{
|
||||
/*
|
||||
Algorithm:
|
||||
1) Read a line, ignore blank lines and comment lines
|
||||
2) If line is KVP
|
||||
2.1) No section? -> Error
|
||||
2.2) Section exists? -> Parse KVP
|
||||
2.2.1) Takes form of K = V? -> Add KVP
|
||||
2.2.2) Doesn't? -> Error
|
||||
3) Else if section
|
||||
3.1) If already seen section -> Error
|
||||
3.2) Create section hashtable, insert it
|
||||
4) Next line
|
||||
*/
|
||||
|
||||
ClearData();
|
||||
ErrorMessage.Clear();
|
||||
|
||||
ZHashMap<ZString, ZString>* currentSection = NULL;
|
||||
|
||||
size_t i = 0; //Current index into file data
|
||||
size_t lineStart = 0; //Start of line
|
||||
size_t lineLength;
|
||||
uint32_t lineNumber = 1;
|
||||
|
||||
//Parse loop
|
||||
while(i < length)
|
||||
{
|
||||
char c = data[i];
|
||||
i++;
|
||||
|
||||
//Treat final character as EOL too
|
||||
if(i < length)
|
||||
{
|
||||
//Split on \n or \r
|
||||
if(c != 0x0A && c != 0x0D)
|
||||
continue;
|
||||
else //Found EOL character
|
||||
{
|
||||
//Line length does NOT include EOL character
|
||||
lineLength = i - 1 - lineStart;
|
||||
}
|
||||
}
|
||||
else //Final line, don't remove extra character
|
||||
lineLength = i - lineStart;
|
||||
|
||||
//Line must be non-blank
|
||||
if(lineLength > 0 && data[lineStart] != '\n')
|
||||
{
|
||||
//Get pointer to start of line
|
||||
const char* line = &data[lineStart];
|
||||
|
||||
//Ignore comments
|
||||
if(line[0] != ';' && line [0] != '#')
|
||||
{
|
||||
//Section name
|
||||
if(line[0] == '[')
|
||||
{
|
||||
size_t j=1; //Start after '['
|
||||
//Read until closing '] or EOL
|
||||
while(j<lineLength && line[j] != ']')
|
||||
{
|
||||
if(!isalnum(line[j]) && line[j] != '_' && line[j] != ' ')
|
||||
{
|
||||
SetError("Header must contain alphanumeric, space, or _ only", lineNumber);
|
||||
return false;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
|
||||
//Reached end of line but no terminator
|
||||
if(j == lineLength)
|
||||
{
|
||||
SetError("Missing closing \']\'", lineNumber);
|
||||
return false;
|
||||
}
|
||||
|
||||
//Copy section name to ZString
|
||||
ZString sectionName(line+1, j-1);
|
||||
|
||||
//Check for existence
|
||||
if(StringSectionMap.ContainsKey(sectionName))
|
||||
{
|
||||
SetError("Section already exists", lineNumber);
|
||||
return false;
|
||||
}
|
||||
|
||||
//Construct new table
|
||||
ZHashMap<ZString, ZString>* table = new(std::nothrow) ZHashMap<ZString, ZString>();
|
||||
if(table != NULL)
|
||||
{
|
||||
//Add mapping
|
||||
StringSectionMap.Put(sectionName, table);
|
||||
Sections.PushBack(table);
|
||||
SectionNames.PushBack(sectionName);
|
||||
|
||||
//Save this as the current section
|
||||
currentSection = table;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetError("Out of memory", lineNumber);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if(!isspace(line[0])) //Not a space, not comment, not section -> KVP
|
||||
{
|
||||
//Did we find a section first?
|
||||
if(currentSection != NULL)
|
||||
{
|
||||
size_t j=0; //length of key
|
||||
|
||||
//Scan until space, equals sign, or EOL
|
||||
while(j<lineLength && line[j] != '=' && !isspace(line[j]))
|
||||
{
|
||||
if(!isalnum(line[j]) && line[j] != '_')
|
||||
{
|
||||
SetError("Key must contain alphanumeric or '_' only", lineNumber);
|
||||
return false;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
|
||||
//Didn't find either a space or '='
|
||||
if(j == lineLength)
|
||||
{
|
||||
SetError("Missing '=' after key name", lineNumber);
|
||||
return false;
|
||||
}
|
||||
|
||||
//Copy key to ZString
|
||||
ZString key(line, j);
|
||||
|
||||
if(line[j] != '=')
|
||||
{
|
||||
//Skip remaining whitespace
|
||||
while(j<lineLength && isspace(line[j]))
|
||||
j++;
|
||||
|
||||
if(j == lineLength || line[j] != '=')
|
||||
{
|
||||
SetError("Missing '=' after key name", lineNumber);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//Now we definitely point to a '=' character. Ensure there is data after it
|
||||
if(j+1 == lineLength)
|
||||
{
|
||||
SetError("Expected value after '='", lineNumber);
|
||||
return false;
|
||||
}
|
||||
j++;
|
||||
|
||||
//Skip any whitespace after '='
|
||||
while(j<lineLength && isspace(line[j]))
|
||||
j++;
|
||||
|
||||
//Special case: if we hit EOL, then we have an empty value
|
||||
if(j == lineLength)
|
||||
{
|
||||
currentSection->Put(key, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
ZString val(&line[j], lineLength-j);
|
||||
currentSection->Put(key, val);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetError("Values must be in a section", lineNumber);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
SetError("Invalid line. Must be a section, comment, or value", lineNumber);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} //if(non-blank line)
|
||||
|
||||
//Check for \r \n pattern
|
||||
if(c == '\r') //we expect a \n, but verify
|
||||
{
|
||||
if(i < length && data[i] == '\n')
|
||||
i++;
|
||||
}
|
||||
|
||||
//Start on next line
|
||||
lineStart = i;
|
||||
lineNumber++;
|
||||
}
|
||||
|
||||
return !Sections.Empty();
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
const ZHashMap<ZString, ZString>* ZIniReader::GetSection(const ZString& sectionName)
|
||||
{
|
||||
ZHashMap<ZString, ZHashMap<ZString, ZString>* >::Iterator it = StringSectionMap.Find(sectionName);
|
||||
|
||||
if(it.HasCurrent())
|
||||
return it.GetValue();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZIniReader::SetError(const char* message, uint32_t line)
|
||||
{
|
||||
ZStringAlgo::BuildPrintf(ErrorMessage, "Line %u: %s", line, message);
|
||||
|
||||
//Clear all data
|
||||
ClearData();
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZIniReader::ClearData()
|
||||
{
|
||||
for(size_t i = 0; i < Sections.Size(); i++)
|
||||
delete Sections[i];
|
||||
|
||||
Sections.Clear();
|
||||
SectionNames.Clear();
|
||||
StringSectionMap.Clear();
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZIniReader::GetKVTree(ZKVTree& _kvtree)
|
||||
{
|
||||
for(size_t i = 0; i < Sections.Size(); i++)
|
||||
{
|
||||
ZHashMap<ZString, ZString>* hmap = Sections[i];
|
||||
ZHashMap<ZString, ZString>::Iterator it = hmap->Begin();
|
||||
|
||||
for(; it != hmap->End(); ++it)
|
||||
{
|
||||
ZString key = SectionNames[i]+"."+it.GetKey();
|
||||
ZString& value = it.GetValue();
|
||||
|
||||
_kvtree.Put(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
68
ZUtil/ZIniWriter.cpp
Normal file
68
ZUtil/ZIniWriter.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#include <ZUtil/ZIniWriter.hpp>
|
||||
|
||||
#include <ZSTL/ZString.hpp>
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
const ZString& ZIniWriter::GetErrorString()
|
||||
{
|
||||
return ErrorMessage;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
bool ZIniWriter::Write( const ZKVTree& _kvtree, ZString& _output )
|
||||
{
|
||||
ErrorMessage.Clear();
|
||||
|
||||
ZKVTree::Iterator itr = _kvtree.Begin();
|
||||
|
||||
if (itr == _kvtree.End())
|
||||
{
|
||||
ErrorMessage = "ZIniWriter: KV Tree has no data!";
|
||||
return false;
|
||||
}
|
||||
|
||||
//Each node name at this level is a section
|
||||
for (size_t i = 0; i < itr.GetSiblingCount(); i++)
|
||||
{
|
||||
//Append the name in [Section] form
|
||||
_output.PushBack('[');
|
||||
|
||||
ZStringAlgo::Append(_output, itr.GetName());
|
||||
|
||||
_output.PushBack(']');
|
||||
|
||||
ZStringAlgo::Append(_output, LINE_TERMINATOR);
|
||||
|
||||
//Iterate the kids (the kids!)
|
||||
if (itr.CheckChild())
|
||||
{
|
||||
itr.Child();
|
||||
|
||||
//Each node at this level is a key/value pair
|
||||
for (size_t j = 0; j < itr.GetSiblingCount(); j++)
|
||||
{
|
||||
//Append the kid in key=value form
|
||||
ZStringAlgo::Append(_output, itr.GetName());
|
||||
|
||||
_output.PushBack('=');
|
||||
|
||||
ZStringAlgo::Append(_output, itr.GetValue());
|
||||
ZStringAlgo::Append(_output, LINE_TERMINATOR);
|
||||
|
||||
if (itr.CheckNextSibling())
|
||||
itr.NextSibling();
|
||||
}
|
||||
|
||||
itr.Parent();
|
||||
}
|
||||
|
||||
ZStringAlgo::Append(_output, LINE_TERMINATOR);
|
||||
|
||||
if (itr.CheckNextSibling())
|
||||
itr.NextSibling();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
81
ZUtil/ZJSONReader.cpp
Normal file
81
ZUtil/ZJSONReader.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
#include <ZUtil/ZJSONReader.hpp>
|
||||
|
||||
#include <ZSTL/ZString.hpp>
|
||||
#include <ZSTL/ZBasicStringAlgo.hpp>
|
||||
#include <jansson.h>
|
||||
|
||||
/* iterate over the values, adding to the KVTree as needed */
|
||||
static void recurse_and_populate ( json_t* _object, void* _itr, ZKVTree& _storage, ZString _currPath )
|
||||
{
|
||||
/* for each key-value pair in the object...*/
|
||||
while (_itr != NULL)
|
||||
{
|
||||
json_t* val = json_object_iter_value(_itr);
|
||||
|
||||
if ( json_is_array ( val ) )
|
||||
{
|
||||
|
||||
/*
|
||||
TODO:
|
||||
What happens if we have an array of arrays? An array of objects?
|
||||
*/
|
||||
size_t arraySize = json_array_size(val);
|
||||
for (size_t i = 0; i < arraySize; i++)
|
||||
{
|
||||
ZBasicStringAlgo::BuildPrintf(_currPath,"%s.%s[%d]", _currPath.Data(), json_object_iter_key(_itr), i );
|
||||
json_t* data = json_array_get(val, i);
|
||||
_storage.Put( _currPath, json_string_value(data) );
|
||||
}
|
||||
}
|
||||
else if ( json_is_object( val ) == false)
|
||||
{
|
||||
/* store the pair if it just a value...*/
|
||||
ZBasicStringAlgo::BuildPrintf(_currPath,"%s.%s", _currPath.Data(), json_object_iter_key(_itr) );
|
||||
json_t* data= json_object_iter_value( _itr );
|
||||
_storage.Put( _currPath, json_string_value(data) );
|
||||
}
|
||||
else
|
||||
{
|
||||
/*...or parse it if it isn't */
|
||||
_currPath = ZString( json_object_iter_key(_itr)) + ".";
|
||||
recurse_and_populate( _object, _itr, _storage, _currPath );
|
||||
}
|
||||
|
||||
_itr = json_object_iter_next( _object, _itr );
|
||||
}
|
||||
}
|
||||
|
||||
ZJSONReader::ZJSONReader(const ZString& _jsonData)
|
||||
: ErrorMessage(), JSONData(_jsonData), Registry(new (std::nothrow) ZKVTree())
|
||||
{
|
||||
json_t* rootNode;
|
||||
|
||||
if (Registry == NULL)
|
||||
{
|
||||
ErrorMessage = "ZJSONReader: unable to create registry!";
|
||||
return;
|
||||
}
|
||||
|
||||
/* have Jansson parse the string out and make an object */
|
||||
json_error_t error;
|
||||
rootNode = json_loads( _jsonData.Data(), 0, &error);
|
||||
if (rootNode == NULL)
|
||||
{
|
||||
ZBasicStringAlgo::BuildPrintf(ErrorMessage, "ZJSONReader: %s on line %d", error.text, error.line);
|
||||
return;
|
||||
}
|
||||
|
||||
/* now, we parse it out */
|
||||
void* itr = json_object_iter(rootNode);
|
||||
recurse_and_populate( rootNode, itr, *Registry, "");
|
||||
}
|
||||
|
||||
const ZString& ZJSONReader::GetErrorString()
|
||||
{
|
||||
return this->ErrorMessage;
|
||||
}
|
||||
|
||||
ZPtr<ZKVTree> ZJSONReader::GetKVTree()
|
||||
{
|
||||
return this->Registry;
|
||||
}
|
||||
19
ZUtil/ZJSONWriter.cpp
Normal file
19
ZUtil/ZJSONWriter.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include <ZUtil/ZJSONWriter.hpp>
|
||||
|
||||
#include <ZSTL/ZString.hpp>
|
||||
#include <jansson.h>
|
||||
|
||||
ZJSONWriter::ZJSONWriter(ZPtr<ZKVTree> _registry)
|
||||
: ErrorMessage("No error."), Registry(_registry), NoError("No error.")
|
||||
{
|
||||
}
|
||||
|
||||
const ZString& ZJSONWriter::GetErrorString()
|
||||
{
|
||||
return this->ErrorMessage;
|
||||
}
|
||||
|
||||
bool ZJSONWriter::Write(ZString& _output)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
547
ZUtil/ZKVTree.cpp
Normal file
547
ZUtil/ZKVTree.cpp
Normal file
@@ -0,0 +1,547 @@
|
||||
#include <ZUtil/ZKVTree.hpp>
|
||||
#include <ZUtil/ZLog.hpp>
|
||||
|
||||
#include <ZSTL/ZBasicStringAlgo.hpp>
|
||||
#include <ZSTL/ZArrayAlgo.hpp>
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZKVTree::NodeCheckIn(Node* _node)
|
||||
{
|
||||
for (size_t i = 0; i < _node->Children.Size(); i++)
|
||||
NodeCheckIn(_node->Children[i]);
|
||||
|
||||
_node->Children.Clear();
|
||||
|
||||
NodeAllocator.Deallocate(_node);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZKVTree::ZKVTree()
|
||||
: RootNode()
|
||||
{
|
||||
RootNode.ParentNode = NULL;
|
||||
RootNode.Index = 0;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZKVTree::ZKVTree( const ZKVTree& _other )
|
||||
: RootNode()
|
||||
{
|
||||
RootNode.ParentNode = NULL;
|
||||
RootNode.Index = 0;
|
||||
|
||||
for (ZKVTree::Iterator itr = _other.Begin(); itr != _other.End(); ++itr) {
|
||||
Put(itr, itr.GetValue());
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZKVTree::~ZKVTree()
|
||||
{
|
||||
for (size_t i = 0; i < RootNode.Children.Size(); i++)
|
||||
NodeCheckIn(RootNode.Children[i]);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZKVTree& ZKVTree::operator = ( const ZKVTree& _other )
|
||||
{
|
||||
Clear();
|
||||
|
||||
for (ZKVTree::Iterator itr = _other.Begin(); itr != _other.End(); ++itr) {
|
||||
Put(itr.GetPath(), itr.GetValue());
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
// This will convert to a full path, with subscripts everywhere and path separators. EXAMPLES:
|
||||
//
|
||||
// A.B[2].C.d -> A[0].B[2].C[0].d[0]
|
||||
// A.B[0][1] -> A[0].B[0].[1]
|
||||
//
|
||||
static bool ConvertPath(const ZString& _path, ZString& _out)
|
||||
{
|
||||
const ZString zeroSubscript("[0]");
|
||||
|
||||
size_t i = 0;
|
||||
size_t j = 0;
|
||||
size_t k = 0;
|
||||
|
||||
//We are going to loop, looking for path separator and making sure we have subscripts and proper path separators
|
||||
while (i != ZSTL::InvalidPos) {
|
||||
// find the next path separator or the first occurrence of a nested array access
|
||||
j = ZStringAlgo::FindFirst(_path, ZKVTREE_PATH_SEPARATOR, i, _path.Length());
|
||||
k = ZStringAlgo::FindSub(_path, i, _path.Length(), "][", 0, 2);
|
||||
|
||||
// if a nested array access occurs
|
||||
if (k < j) {
|
||||
// append the first part of it, a path separators, and then process from there
|
||||
ZStringAlgo::Append(_out, _path, i, k + 1);
|
||||
|
||||
_out.PushBack(ZKVTREE_PATH_SEPARATOR);
|
||||
|
||||
i = k + 1;
|
||||
} else if (i == j) {
|
||||
// this means we are dealing with a node without a name (potentially first node)
|
||||
if (_out.Empty() || _out.Back() != ']')
|
||||
ZStringAlgo::Append(_out, zeroSubscript);
|
||||
|
||||
_out.PushBack(ZKVTREE_PATH_SEPARATOR);
|
||||
|
||||
i = j + 1;
|
||||
} else if (j != ZSTL::InvalidPos) {
|
||||
// found a substring between two path separators
|
||||
ZStringAlgo::Append(_out, _path, i, j);
|
||||
|
||||
if (_out.Back() != ']')
|
||||
ZStringAlgo::Append(_out, zeroSubscript);
|
||||
|
||||
_out.PushBack(ZKVTREE_PATH_SEPARATOR);
|
||||
|
||||
i = j + 1;
|
||||
} else {
|
||||
// we have reached the end
|
||||
ZStringAlgo::Append(_out, _path, i, _path.Length());
|
||||
|
||||
if (_out.Empty() || _out.Back() != ']')
|
||||
ZStringAlgo::Append(_out, zeroSubscript);
|
||||
|
||||
i = ZSTL::InvalidPos;
|
||||
}
|
||||
}
|
||||
|
||||
// this method may be expanded later for path verification via regex or some such
|
||||
return true;
|
||||
}
|
||||
|
||||
//This will insert a child node at the given index and increment the indices on the other child values
|
||||
static void InsertNode( ZKVTree::Node* _parent, ZKVTree::Node* _child, size_t _index )
|
||||
{
|
||||
_parent->Children.Insert(_index, _child);
|
||||
|
||||
for (size_t i = _index + 1; i < _parent->Children.Size(); i++)
|
||||
_parent->Children.Data()[i]->Index++;
|
||||
}
|
||||
|
||||
//This will erase a child node at the given index and decrement the indices on the other child values
|
||||
static ZKVTree::Node* EraseChildNode( ZKVTree::Node* _parent, size_t _index )
|
||||
{
|
||||
for (size_t i = _index + 1; i < _parent->Children.Size(); i++)
|
||||
_parent->Children.Data()[i]->Index--;
|
||||
|
||||
return _parent->Children.Erase(_index);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
// gets the value from a completed path (returned from ConvertFullPath)
|
||||
ZKVTree::Node* ZKVTree::GetFromPath(const ZString& _path) const
|
||||
{
|
||||
size_t i, j, k;
|
||||
size_t subscript;
|
||||
|
||||
const Node* node = &RootNode;
|
||||
|
||||
// path[i...j] is our path window (current value we are looking for)
|
||||
// path[subscript].nextpath
|
||||
// ^ ^ ^
|
||||
// i j k
|
||||
// or
|
||||
// path.nextpath
|
||||
// ^ ^
|
||||
// i j,k
|
||||
i = 0;
|
||||
j = 0;
|
||||
k = 0;
|
||||
|
||||
//While we still have a node to look in
|
||||
while (node != NULL)
|
||||
{
|
||||
//See if we have reached the end
|
||||
if (i >= _path.Length())
|
||||
break;
|
||||
|
||||
subscript = 0;
|
||||
|
||||
j = ZStringAlgo::FindFirst(_path, ZKVTREE_PATH_SEPARATOR, i, _path.Length());
|
||||
|
||||
//If we can't find a path separator, go to the end
|
||||
if (j == ZSTL::InvalidPos)
|
||||
j = _path.Length();
|
||||
|
||||
//See if we have found the node
|
||||
if (i >= j)
|
||||
break;
|
||||
|
||||
k = j;
|
||||
|
||||
//Determine if it has a subscript
|
||||
if (_path[j - 1] == ']')
|
||||
{
|
||||
j = ZStringAlgo::FindLast(_path, '[', i, j);
|
||||
|
||||
//Make sure this is bounded correct
|
||||
if (j == ZSTL::InvalidPos || j < i)
|
||||
{
|
||||
node = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
subscript = (size_t)ZStringAlgo::NumericInt(_path, j + 1, k - 1);
|
||||
}
|
||||
|
||||
node = node->GetChildByName(_path, i, j, subscript);
|
||||
|
||||
//Move up our path 'window'
|
||||
i = k + 1;
|
||||
}
|
||||
|
||||
return const_cast<ZKVTree::Node*>(node);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZKVTree::Node* ZKVTree::CreatePath(const ZString& _path)
|
||||
{
|
||||
size_t i, j, k;
|
||||
size_t subscript;
|
||||
|
||||
Node* node = &RootNode;
|
||||
|
||||
// path[i...j] is our path window (current value we are looking for)
|
||||
// path[subscript].nextpath
|
||||
// ^ ^ ^
|
||||
// i j k
|
||||
// or
|
||||
// path.nextpath
|
||||
// ^ ^
|
||||
// i j,k
|
||||
i = 0;
|
||||
j = 0;
|
||||
k = 0;
|
||||
|
||||
// while we still have a node to look in
|
||||
while (node != NULL) {
|
||||
// see if we have reached the end
|
||||
if (i >= _path.Length()) {
|
||||
break;
|
||||
}
|
||||
|
||||
subscript = 0;
|
||||
|
||||
j = ZStringAlgo::FindFirst(_path, ZKVTREE_PATH_SEPARATOR, i, _path.Length());
|
||||
|
||||
//If we can't find a path separator, go to the end
|
||||
if (j == ZSTL::InvalidPos) {
|
||||
j = _path.Length();
|
||||
}
|
||||
|
||||
//See if we are done creating
|
||||
if (i == j) {
|
||||
break;
|
||||
}
|
||||
|
||||
k = j;
|
||||
|
||||
// determine if it has a subscript
|
||||
if (_path[j - 1] == ']') {
|
||||
j = ZStringAlgo::FindLast(_path, '[', i, j);
|
||||
|
||||
// make sure this is bounded correct (if not, bail out)
|
||||
if (j == ZSTL::InvalidPos || j < i) {
|
||||
node = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
subscript = (size_t)ZStringAlgo::NumericInt(_path, j + 1, k - 1);
|
||||
}
|
||||
|
||||
Node* childNode = node->GetChildByName(_path, i, j, subscript);
|
||||
|
||||
// create this node if it doesn't exist
|
||||
if (childNode == NULL) {
|
||||
// get the child count by name at the parent node
|
||||
size_t count = node->GetChildCountByName(_path, i, j);
|
||||
|
||||
// see if the subscript at the end is the 'next' value (if not, bail out)
|
||||
if (count != subscript) {
|
||||
node = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
// get a new node, set the parent node, name, index (leave out the value)
|
||||
childNode = NodeAllocator.Allocate();
|
||||
|
||||
childNode->ParentNode = node;
|
||||
childNode->Name.Resize(j - i);
|
||||
ZStringAlgo::Copy(childNode->Name, 0, childNode->Name.Length(), _path, i, j);
|
||||
|
||||
if (count > 0) {
|
||||
childNode->Index = node->GetLastIndexByName(_path, i, j) + 1;
|
||||
|
||||
// increment the index on the rest of the nodes
|
||||
for (size_t i = childNode->Index; i < node->Children.Size(); i++)
|
||||
node->Children[i]->Index++;
|
||||
|
||||
node->Children.Insert(childNode->Index, childNode);
|
||||
} else {
|
||||
childNode->Index = node->Children.Size();
|
||||
node->Children.PushBack(childNode);
|
||||
}
|
||||
}
|
||||
|
||||
// set our new node
|
||||
node = childNode;
|
||||
|
||||
// move up our 'path window'
|
||||
i = k + 1;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZKVTree::Iterator ZKVTree::Add( const ZString& _name, const ZString& _value )
|
||||
{
|
||||
return Add(End(), _name, _value);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZKVTree::Iterator ZKVTree::Add( const ZString& _parent, const ZString& _name, const ZString& _value )
|
||||
{
|
||||
ZString path;
|
||||
|
||||
if (!ConvertPath(_parent, path))
|
||||
return End();
|
||||
|
||||
Node* node = CreatePath(path);
|
||||
|
||||
return Add(Iterator(node, this), _name, _value);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZKVTree::Iterator ZKVTree::Add( const Iterator& _itr, const ZString& _name, const ZString& _value )
|
||||
{
|
||||
ZKVTree::Node* parentNode = NULL;
|
||||
ZKVTree::Node* childNode = NULL;
|
||||
|
||||
if (_itr.CurrentNode == NULL) {
|
||||
return End();
|
||||
}
|
||||
|
||||
if (_itr.KVTree == this) {
|
||||
parentNode = _itr.CurrentNode;
|
||||
|
||||
// allocate a child node and set values
|
||||
childNode = NodeAllocator.Allocate();
|
||||
childNode->ParentNode = parentNode;
|
||||
childNode->Name = _name;
|
||||
childNode->Value = _value;
|
||||
|
||||
// determine if any other children of the same name exist (grouped on insert)
|
||||
size_t count = parentNode->GetChildCountByName(_name, 0, _name.Length());
|
||||
|
||||
if (count > 0) {
|
||||
childNode->Index = parentNode->GetLastIndexByName(_name, 0, _name.Length()) + 1;
|
||||
} else {
|
||||
childNode->Index = parentNode->Children.Size();
|
||||
}
|
||||
|
||||
InsertNode(parentNode, childNode, childNode->Index);
|
||||
|
||||
return Iterator(childNode, this);
|
||||
} else {
|
||||
// if this is from another tree, just add at the path
|
||||
return Add(_itr.GetPath(), _name, _value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZKVTree::Clear()
|
||||
{
|
||||
for (size_t i = 0; i < RootNode.Children.Size(); i++) {
|
||||
NodeCheckIn(RootNode.Children.Data()[i]);
|
||||
}
|
||||
|
||||
RootNode.Children.Clear();
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZKVTree::Erase( const ZString& _path )
|
||||
{
|
||||
Erase(Find(_path));
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZKVTree::Erase( const Iterator& _itr )
|
||||
{
|
||||
ZASSERT_RUNTIME(_itr.CurrentNode != NULL, "ZKVTree: Unable to erase value from provided iterator!");
|
||||
ZASSERT_RUNTIME(_itr.CurrentNode != &RootNode, "ZKVTree: Unable to erase root node!");
|
||||
|
||||
if (_itr.KVTree == this) {
|
||||
NodeCheckIn(EraseChildNode(_itr.CurrentNode->ParentNode, _itr.CurrentNode->Index));
|
||||
} else {
|
||||
Erase(_itr.GetPath());
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZKVTree::Iterator ZKVTree::Find( const ZString& _path ) const
|
||||
{
|
||||
ZString path;
|
||||
|
||||
if (!ConvertPath(_path, path)) {
|
||||
return End();
|
||||
}
|
||||
|
||||
Node* node = GetFromPath(path);
|
||||
|
||||
if (node == NULL) {
|
||||
return End();
|
||||
}
|
||||
|
||||
return ZKVTree::Iterator(node, const_cast<ZKVTree*>(this));
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZKVTree::Iterator ZKVTree::Find( const Iterator& _itr, const ZString& _path ) const
|
||||
{
|
||||
ZString path;
|
||||
|
||||
if (!ConvertPath(_path, path)) {
|
||||
return End();
|
||||
}
|
||||
|
||||
Node* node = GetFromPath(_itr.GetPath() + ZKVTREE_PATH_SEPARATOR + path);
|
||||
|
||||
if (node == NULL) {
|
||||
return End();
|
||||
}
|
||||
|
||||
return ZKVTree::Iterator(node, const_cast<ZKVTree*>(this));
|
||||
|
||||
}
|
||||
/*************************************************************************/
|
||||
|
||||
const ZString& ZKVTree::Get( const ZString& _path ) const
|
||||
{
|
||||
ZKVTree::Iterator itr = Find(_path);
|
||||
|
||||
ZASSERT_RUNTIME(itr != End(), "ZKVTree: No value mapped to path!");
|
||||
|
||||
return itr.GetValue();
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
const ZString& ZKVTree::Get( const Iterator& _itr, const ZString& _path )
|
||||
{
|
||||
ZKVTree::Iterator itr = Find(_itr, _path);
|
||||
|
||||
ZASSERT_RUNTIME(itr != End(), "ZKVTree: No value mapped to path!");
|
||||
|
||||
return itr.GetValue();
|
||||
}
|
||||
/*************************************************************************/
|
||||
|
||||
void ZKVTree::Merge( const ZKVTree& _other, bool _overwrite )
|
||||
{
|
||||
for (ZKVTree::Iterator itr = _other.Begin(); itr != _other.End(); ++itr) {
|
||||
if (_overwrite) {
|
||||
Put(itr.GetPath(), itr.GetValue());
|
||||
} else {
|
||||
ZKVTree::Iterator found = Find(itr.GetPath());
|
||||
if (found == End()) {
|
||||
Put(itr.GetPath(), itr.GetValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZKVTree::Iterator ZKVTree::Put( const ZString& _path, const ZString& _value )
|
||||
{
|
||||
ZString path;
|
||||
|
||||
if (!ConvertPath(_path, path))
|
||||
return End();
|
||||
|
||||
// create the node at the path given (will return the existing node if there)
|
||||
Node* node = CreatePath(path);
|
||||
|
||||
// if we were able to successfully create the node, set its value
|
||||
if (node != NULL) {
|
||||
node->Value = _value;
|
||||
return Iterator(node, this);
|
||||
} else return End();
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZKVTree::Iterator ZKVTree::Put(const Iterator& _itr, const ZString& _value)
|
||||
{
|
||||
// ensure this iterator belongs to us
|
||||
if (_itr.KVTree == this) {
|
||||
// it does, just set the value
|
||||
_itr.CurrentNode->Value = _value;
|
||||
return _itr;
|
||||
} else {
|
||||
// it does not, just create a new value using the path variant
|
||||
return Put(_itr.GetPath(), _value);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZKVTree::Iterator ZKVTree::Begin() const
|
||||
{
|
||||
if (RootNode.Children.Empty()) {
|
||||
return End();
|
||||
} else return ZKVTree::Iterator(const_cast<Node*>(RootNode.Children.Front()), const_cast<ZKVTree*>(this));
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
const ZKVTree::Iterator ZKVTree::End() const
|
||||
{
|
||||
return ZKVTree::Iterator(const_cast<Node*>(&RootNode), const_cast<ZKVTree*>(this));
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static bool isInvalidKeyNameChar(const char _char)
|
||||
{
|
||||
return ( isspace(_char) != 0) ||
|
||||
( iscntrl(_char) != 0) ||
|
||||
( _char == ZKVTREE_PATH_SEPARATOR ) ||
|
||||
( _char == '[' ) ||
|
||||
( _char == ']' );
|
||||
}
|
||||
|
||||
bool ZKVTree::IsValidKeyName( const ZString& _name ) const
|
||||
{
|
||||
for (size_t i = 0; i < _name.Length(); i++) {
|
||||
if (isInvalidKeyNameChar( _name.Data()[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
306
ZUtil/ZLog.cpp
Normal file
306
ZUtil/ZLog.cpp
Normal file
@@ -0,0 +1,306 @@
|
||||
#include <ZUtil/ZLog.hpp>
|
||||
#include <ZUtil/ZAlloc.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <stdarg.h>
|
||||
#include <algorithm>
|
||||
|
||||
////////////////////////////////////
|
||||
/* Static Variable Initialization */
|
||||
////////////////////////////////////
|
||||
|
||||
ZMutex ZLog::LogLock;
|
||||
|
||||
bool ZLog::bIsInitialized = false;
|
||||
|
||||
ZArray< ZPair<std::ofstream*, bool> > ZLog::LogFiles;
|
||||
|
||||
ZArray< ZPtr<ZLogDelegate> > ZLog::Delegates;
|
||||
|
||||
ZString ZLog::LogFileRoot;
|
||||
|
||||
uint64_t* ZLog::UserTick = NULL;
|
||||
uint64_t* ZLog::UserUpdate = NULL;
|
||||
|
||||
uint64_t ZLog::TickEstimate = 0;
|
||||
uint64_t ZLog::UpdateFrameEstimate = 0;
|
||||
|
||||
///////////////////////////
|
||||
/* Local Helper Function */
|
||||
///////////////////////////
|
||||
|
||||
void writeHeader(std::ofstream& logfile, const char* filename)
|
||||
{
|
||||
|
||||
logfile << filename << " : ZUtil version " << ZUTIL_VERSION_STRING << " default log file\n\n";
|
||||
|
||||
#if ZLOG_LEVEL >= ZLOG_LEVEL_INFO
|
||||
logfile << "+------------+------------+\n";
|
||||
logfile << "| Time (sec) | Update No. |\n";
|
||||
logfile << "+------------+------------+\n";
|
||||
#endif
|
||||
}
|
||||
|
||||
void writeFooter(std::ofstream& logfile)
|
||||
{
|
||||
#if ZLOG_LEVEL >= ZLOG_LEVEL_INFO
|
||||
logfile << "+------------+------------+\n";
|
||||
#endif
|
||||
}
|
||||
|
||||
int logAssertHandler(const char* _msg, void *_arg)
|
||||
{
|
||||
URFP(_arg);
|
||||
|
||||
//Log it!
|
||||
SystemLogError("Assertion Failed: \n");
|
||||
SystemLogError(_msg);
|
||||
|
||||
//Let the error propagate
|
||||
return 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
/* Static Function Declaration */
|
||||
/////////////////////////////////
|
||||
|
||||
void ZLog::Init(const ZString& _logFileRoot, const ZString& _defaultLogFile, uint64_t* _ticks /*= NULL*/, uint64_t* _update /*= NULL*/)
|
||||
{
|
||||
std::ofstream *logfile;
|
||||
|
||||
//Save our root path
|
||||
ZLog::LogFileRoot = _logFileRoot;
|
||||
|
||||
//Create a default log file
|
||||
ZString logFilePath = ZLog::LogFileRoot + _defaultLogFile;
|
||||
|
||||
logfile = znew_notrack std::ofstream();
|
||||
logfile->open(logFilePath.Data(), std::ios::out);
|
||||
|
||||
while (logfile->fail()) {
|
||||
logFilePath += "_";
|
||||
logfile->open(logFilePath.Data(), std::ios::out);
|
||||
}
|
||||
|
||||
//Write the header
|
||||
writeHeader(*logfile, _defaultLogFile.Data());
|
||||
|
||||
//Add the default log file to the set
|
||||
ZLog::LogFiles.Reserve(16);
|
||||
ZLog::LogFiles.Clear();
|
||||
ZLog::LogFiles.PushBack(ZPair<std::ofstream*, bool>(logfile, true));
|
||||
|
||||
//Set our SST_Assert handlers
|
||||
SST_OS_SetDebugAssertHandler(logAssertHandler, NULL);
|
||||
SST_OS_SetRuntimeAssertHandler(logAssertHandler, NULL);
|
||||
|
||||
ZLog::UserTick = _ticks;
|
||||
ZLog::UserUpdate = _update;
|
||||
|
||||
//We're ready to rock and roll
|
||||
ZLog::bIsInitialized = true;
|
||||
}
|
||||
|
||||
void ZLog::Shutdown()
|
||||
{
|
||||
ZArray< ZPair<std::ofstream*, bool> >::Iterator itr;
|
||||
|
||||
//Iterate and close out
|
||||
for (itr = ZLog::LogFiles.Begin(); itr != ZLog::LogFiles.End(); itr++)
|
||||
{
|
||||
writeFooter(*((*itr).First));
|
||||
|
||||
(*itr).First->close();
|
||||
(*itr).Second = false;
|
||||
|
||||
zdelete (*itr).First;
|
||||
}
|
||||
|
||||
//Flush standard outputs
|
||||
std::cout.flush();
|
||||
std::cerr.flush();
|
||||
|
||||
//Clear our set of log files
|
||||
ZLog::LogFiles.Clear();
|
||||
}
|
||||
|
||||
void ZLog::AddLoggingDelegate(ZPtr<ZLogDelegate> _delegate)
|
||||
{
|
||||
ZLog::LogLock.Acquire();
|
||||
|
||||
ZLog::Delegates.PushBack(_delegate);
|
||||
|
||||
ZLog::LogLock.Release();
|
||||
}
|
||||
|
||||
ZLogFile ZLog::CreateLogFile(const ZString& _fileName)
|
||||
{
|
||||
ZLogFile handle;
|
||||
std::ofstream *file;
|
||||
|
||||
//See if we can early out
|
||||
if (!ZLog::bIsInitialized)
|
||||
{
|
||||
std::cerr << "Attempted to create log file (Before call to Init) : " << _fileName.Data() << std::endl;
|
||||
return (ZLogFile)0;
|
||||
}
|
||||
|
||||
ZString logFilePath = ZLog::LogFileRoot + _fileName;
|
||||
|
||||
//Synchronized Section
|
||||
{
|
||||
//Scoped lock
|
||||
ZLock scopedLock(ZLog::LogLock);
|
||||
|
||||
file = znew_notrack std::ofstream();
|
||||
|
||||
if (file == NULL)
|
||||
{
|
||||
fprintf(stderr, "Failed to create log file %s!\n", _fileName.Data());
|
||||
return (ZLogFile)0;
|
||||
}
|
||||
|
||||
file->open(logFilePath.Data(), std::ios::out);
|
||||
|
||||
if (!file->is_open())
|
||||
{
|
||||
//Nope nope nope
|
||||
fprintf(stderr, "Failed to open log file %s!\n", _fileName.Data());
|
||||
zdelete file;
|
||||
return (ZLogFile)0;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Write the header
|
||||
writeHeader(*file, _fileName.Data());
|
||||
|
||||
//This will give us the index where it will be going
|
||||
handle = ZLog::LogFiles.Size();
|
||||
|
||||
//Add to the set of streams already activated
|
||||
ZLog::LogFiles.PushBack(ZPair<std::ofstream*, bool>(file, true));
|
||||
}
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
void ZLog::Resume( ZLogFile _logFile )
|
||||
{
|
||||
//Scoped Lock
|
||||
ZLock scopedLock(ZLog::LogLock);
|
||||
|
||||
ZASSERT_RUNTIME((size_t)_logFile < LogFiles.Size(), "Cannot resume logging to file: file does not exist!");
|
||||
|
||||
ZLog::LogFiles[_logFile].Second = true;
|
||||
}
|
||||
|
||||
void ZLog::Suspend( ZLogFile _logFile )
|
||||
{
|
||||
//Scoped Lock
|
||||
ZLock scopedLock(ZLog::LogLock);
|
||||
|
||||
ZASSERT_RUNTIME((size_t)_logFile < LogFiles.Size(), "Cannot resume logging to file: file does not exist!");
|
||||
|
||||
ZLog::LogFiles[_logFile].Second = false;
|
||||
}
|
||||
|
||||
void ZLog::Printf(ZLogType _type, ZLogFile _file, uint64_t _ticks, uint32_t _updateFrame, const char *_function, const char *_str, ...)
|
||||
{
|
||||
URFP(_function);
|
||||
|
||||
va_list args;
|
||||
|
||||
//Check for easy out
|
||||
if (!ZLog::bIsInitialized)
|
||||
return;
|
||||
|
||||
//Make sure we're null terminated
|
||||
char string[32768];
|
||||
MemSetChar(string, 0, 32768);
|
||||
|
||||
va_start(args, _str);
|
||||
|
||||
#ifdef _MSC_VER
|
||||
vsnprintf_s(string, sizeof(string)-1, sizeof(string)-1, _str, args);
|
||||
#else
|
||||
vsnprintf(string, sizeof(string)-1, _str, args);
|
||||
#endif
|
||||
|
||||
//Write using our existing write function
|
||||
ZLog::WriteLine(_type, _file, _ticks, _updateFrame, string);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void ZLog::WriteLine(ZLogType _type, ZLogFile _file, uint64_t _ticks, uint32_t _updateFrame, const char *_str)
|
||||
{
|
||||
#if ZLOG_LEVEL >= ZLOG_LEVEL_INFO
|
||||
char time[32];
|
||||
char update[32];
|
||||
#endif
|
||||
|
||||
//See if we can early out (should warn)
|
||||
if (!ZLog::bIsInitialized)
|
||||
{
|
||||
std::cerr << "Logging Output (Before call to Init): " << _str << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
//Synchronized Section
|
||||
{
|
||||
//Scoped Lock
|
||||
ZLock scopedLock(ZLog::LogLock);
|
||||
|
||||
ZASSERT_RUNTIME((size_t)_file < LogFiles.Size(), "Cannot log to file: file not created!");
|
||||
|
||||
//Get the file and find out if activated
|
||||
std::ofstream *logfile = ZLog::LogFiles[_file].First;
|
||||
bool enabled = ZLog::LogFiles[_file].Second;
|
||||
|
||||
//If we are not currently enabled, we are no longer needed
|
||||
if (!enabled)
|
||||
return;
|
||||
|
||||
//Get our best guesses
|
||||
if (ZLog::UserTick != NULL) {
|
||||
ZLog::TickEstimate = *ZLog::UserTick;
|
||||
} else if (_ticks > ZLog::TickEstimate) {
|
||||
ZLog::TickEstimate = _ticks;
|
||||
}
|
||||
|
||||
if (ZLog::UserUpdate != NULL) {
|
||||
ZLog::UpdateFrameEstimate = *ZLog::UserUpdate;
|
||||
} else if (_updateFrame > ZLog::UpdateFrameEstimate) {
|
||||
ZLog::UpdateFrameEstimate = _updateFrame;
|
||||
}
|
||||
|
||||
ZASSERT_UTIL(logfile != NULL, "ZLog Error: logfile is NULL!");
|
||||
|
||||
#if ZLOG_LEVEL >= ZLOG_LEVEL_INFO
|
||||
|
||||
//If we are at detailed (or higher) log level, then log the extra details, then the string
|
||||
if (_ticks == 0 && _updateFrame == 0 && ZLog::UserTick == NULL && ZLog::UserUpdate == NULL) {
|
||||
sprintf(time, "?%11.3f", ((float)ZLog::TickEstimate) / 1000.0f);
|
||||
sprintf(update, "?%11lu", ZLog::UpdateFrameEstimate);
|
||||
} else {
|
||||
sprintf(time, "%12.3f", ((float)ZLog::TickEstimate) / 1000.0f);
|
||||
sprintf(update, "%12lu", ZLog::UpdateFrameEstimate);
|
||||
}
|
||||
|
||||
std::cout << _str << std::endl;
|
||||
*logfile << "|" << time << "|" << update << "| " << /*ZConcurrency::GetThreadName() << ": " << */_str << std::endl;
|
||||
|
||||
#else
|
||||
|
||||
std::cout << _str << std::endl;
|
||||
*logfile << _str << std::endl;
|
||||
|
||||
#endif //ZLOG_LEVEL >= ZLOG_LEVEL_DETAILED
|
||||
|
||||
//Let the delegates know what happened
|
||||
for (ZArray< ZPtr<ZLogDelegate> >::Iterator i = ZLog::Delegates.Begin(); i != ZLog::Delegates.End(); i++)
|
||||
(*i)->Execute(_type, _file, _str);
|
||||
}
|
||||
}
|
||||
42
ZUtil/ZMutex.cpp
Normal file
42
ZUtil/ZMutex.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
#include <ZUtil/ZMutex.hpp>
|
||||
#include <ZUtil/ZAssert.hpp>
|
||||
|
||||
//////////////////////////
|
||||
/* ZLock Implementation */
|
||||
//////////////////////////
|
||||
|
||||
ZMutex::ZMutex()
|
||||
: Mutex(SST_Concurrency_CreateMutex())
|
||||
{
|
||||
ZASSERT_RUNTIME(Mutex != NULL, "ZMutex failed to allocate mutex from libsst-concurrency!");
|
||||
}
|
||||
|
||||
ZMutex::~ZMutex()
|
||||
{
|
||||
SST_Concurrency_DestroyMutex(Mutex);
|
||||
}
|
||||
|
||||
void ZMutex::Acquire()
|
||||
{
|
||||
SST_Concurrency_LockMutex(Mutex);
|
||||
}
|
||||
|
||||
void ZMutex::Release()
|
||||
{
|
||||
SST_Concurrency_UnlockMutex(Mutex);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
/* ZScopedLock Implementation */
|
||||
////////////////////////////////
|
||||
|
||||
ZLock::ZLock( ZMutex& _mutex )
|
||||
: Mutex(_mutex)
|
||||
{
|
||||
Mutex.Acquire();
|
||||
}
|
||||
|
||||
ZLock::~ZLock()
|
||||
{
|
||||
Mutex.Release();
|
||||
}
|
||||
207
ZUtil/ZName.cpp
Normal file
207
ZUtil/ZName.cpp
Normal file
@@ -0,0 +1,207 @@
|
||||
#include <ZUtil/ZName.hpp>
|
||||
#include <ZUtil/ZAssert.hpp>
|
||||
#include <ZUtil/ZAlloc.hpp>
|
||||
|
||||
#include <SST/SST_Hash.h>
|
||||
|
||||
ZName::ZName()
|
||||
: Length(0), Hash(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZName::ZName( const char *_string )
|
||||
: Length(0), Hash(0)
|
||||
{
|
||||
Length = _string != NULL ? strlen(_string) : 0;
|
||||
|
||||
if (Length > ZNAME_MAX_LENGTH)
|
||||
{
|
||||
ZASSERT_RUNTIME_FAIL("ZName: Constructed from string with > ZNAME_MAX_LEN characters!");
|
||||
Length = ZNAME_MAX_LENGTH;
|
||||
}
|
||||
|
||||
MemCopyChar(String, _string, Length);
|
||||
MemSetChar(&String[Length], '\0', ZNAME_MAX_LENGTH - Length + 1);
|
||||
|
||||
Hash = SST_Crypto_HashJCR2(String, Length);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZName::ZName( const ZString& _string )
|
||||
{
|
||||
Length = _string.Length();
|
||||
|
||||
if (Length > ZNAME_MAX_LENGTH)
|
||||
{
|
||||
ZASSERT_RUNTIME_FAIL("ZName: Constructed from string with > ZNAME_MAX_LEN characters!");
|
||||
Length = ZNAME_MAX_LENGTH;
|
||||
}
|
||||
|
||||
MemCopyChar(String, _string.Data(), Length);
|
||||
MemSetChar(&String[Length], '\0', ZNAME_MAX_LENGTH - Length + 1);
|
||||
|
||||
Hash = SST_Crypto_HashJCR2(String, Length);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZName::ZName( const ZName& _other )
|
||||
: Length(0), Hash(0)
|
||||
{
|
||||
MemCopyChar(String, _other.String, ZNAME_MAX_LENGTH);
|
||||
|
||||
Length = _other.Length;
|
||||
Hash = _other.Hash;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZName::ZName( uint64_t _hash )
|
||||
: Length(0), Hash(_hash)
|
||||
{
|
||||
const char* precompStr = "<precomputed>";
|
||||
|
||||
MemCopyChar(String, precompStr, sizeof(precompStr));
|
||||
|
||||
Length = sizeof(precompStr) - 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZName::~ZName()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZName& ZName::operator = ( const ZName& _other )
|
||||
{
|
||||
MemCopyChar(String, _other.String, ZNAME_MAX_LENGTH);
|
||||
|
||||
Length = _other.Length;
|
||||
Hash = _other.Hash;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZName& ZName::operator = ( const ZString& _string )
|
||||
{
|
||||
Length = _string.Length();
|
||||
|
||||
if (Length > ZNAME_MAX_LENGTH)
|
||||
{
|
||||
ZASSERT_RUNTIME_FAIL("ZName: Assigned from string with > ZNAME_MAX_LEN characters!");
|
||||
Length = ZNAME_MAX_LENGTH;
|
||||
}
|
||||
|
||||
MemCopyChar(String, _string.Data(), Length);
|
||||
MemSetChar(&String[Length], '\0', ZNAME_MAX_LENGTH - Length + 1);
|
||||
|
||||
Hash = SST_Crypto_HashJCR2(String, Length);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZName& ZName::operator = (const char* _string )
|
||||
{
|
||||
Length = _string != NULL ? strlen(_string) : 0;
|
||||
|
||||
if (Length > ZNAME_MAX_LENGTH)
|
||||
{
|
||||
ZASSERT_RUNTIME_FAIL("ZName: Assigned from string with > ZNAME_MAX_LEN characters!");
|
||||
Length = ZNAME_MAX_LENGTH;
|
||||
}
|
||||
|
||||
MemCopyChar(String, _string, Length);
|
||||
MemSetChar(&String[Length], '\0', ZNAME_MAX_LENGTH - Length + 1);
|
||||
|
||||
Hash = SST_Crypto_HashJCR2(String, Length);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
bool ZName::operator == ( const ZName& _other ) const
|
||||
{
|
||||
#if ZSTL_CHECK_NAME
|
||||
|
||||
bool ret = (Hash == _other.Hash);
|
||||
|
||||
if (ret == true)
|
||||
{
|
||||
int strcmpRet = strcmp(String, _other.String);
|
||||
|
||||
ZASSERT_RUNTIME(strcmpRet == 0, "ZName: Hash reported same, but failed strcmp!\n");
|
||||
|
||||
return (strcmpRet == 0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
#else
|
||||
|
||||
return Hash == _other.Hash;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
bool ZName::operator == ( const ZHashValue hash ) const
|
||||
{
|
||||
return Hash == hash;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
bool ZName::operator==( const ZString& _other ) const
|
||||
{
|
||||
return Hash == ZName(_other);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
bool ZName::operator != ( const ZName& _other ) const
|
||||
{
|
||||
return !((*this) == _other);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZName::operator ZHashValue() const
|
||||
{
|
||||
return (ZHashValue)Hash;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZName::operator ZString() const
|
||||
{
|
||||
return ToString();
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZString ZName::ToString() const
|
||||
{
|
||||
return ZString(String);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
const char* ZName::Data() const
|
||||
{
|
||||
return String;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
213
ZUtil/ZRandomGenerator.cpp
Normal file
213
ZUtil/ZRandomGenerator.cpp
Normal file
@@ -0,0 +1,213 @@
|
||||
#include <ZUtil/ZRandomGenerator.hpp>
|
||||
|
||||
#include <ZUtil/ZAssert.hpp>
|
||||
|
||||
#include <math.h> /* sine and other functions */
|
||||
#include <time.h> /* time function */
|
||||
|
||||
//Helper Function that returns a float distributed normally between a float min and max using random numbers r1, r2
|
||||
float getGaussianHelper(float _min, float _max, float _r1, float _r2)
|
||||
{
|
||||
float deltamid, delta;
|
||||
|
||||
deltamid = (float)(((_max - _min) / 2) * sin(_r1 * 3.14159f)); /* absolute delta from middle value */
|
||||
delta = _max - _min - (2 * deltamid); /* calculate the actual delta */
|
||||
|
||||
return (_min + deltamid + (_r2 * delta));
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZRandomGenerator::ZRandomGenerator()
|
||||
: Type(SST_PRNG_SMALLPRNG), Seed((uint32_t)time(0)), Sequence(0), RNG(NULL)
|
||||
{
|
||||
RNG = SST_Random_CreatePRNGFromSeed(Type, Seed);
|
||||
|
||||
ZASSERT_RUNTIME(RNG != NULL, "ZRandomGenerator: Failure to initialize SST_PRNG instance!");
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZRandomGenerator::ZRandomGenerator(SST_PRNG_TYPE _type, uint32_t _seed, uint64_t _sequence )
|
||||
: Type(_type), Seed(_seed), Sequence(_sequence), RNG(SST_Random_CreatePRNGFromSeed(_type, _seed))
|
||||
{
|
||||
ZASSERT_RUNTIME(RNG != NULL, "ZRandomGenerator: Failure to initialize SST_PRNG instance!");
|
||||
|
||||
//Generate and discard a number of times equal to Sequence
|
||||
for (uint64_t i = 0; i < Sequence; i++)
|
||||
SST_Random_GetPRNGInt(RNG, 0, 1);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZRandomGenerator::~ZRandomGenerator()
|
||||
{
|
||||
if (RNG != NULL)
|
||||
SST_Random_DestroyPRNG(RNG);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
float ZRandomGenerator::GetFloat()
|
||||
{
|
||||
++Sequence;
|
||||
|
||||
return SST_Random_GetPRNGFloat(RNG, 0, 1);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZRandomGenerator::GetFloatArray( float *_array, size_t _count )
|
||||
{
|
||||
Sequence += _count;
|
||||
|
||||
return SST_Random_GetPRNGFloatArray(RNG, _array, _count, 0, 1);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
float ZRandomGenerator::GetFloatInRange( float _min, float _max )
|
||||
{
|
||||
++Sequence;
|
||||
|
||||
return SST_Random_GetPRNGFloat(RNG, _min, _max);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZRandomGenerator::GetFloatArrayInRange( float *_array, size_t _count, float _min, float _max )
|
||||
{
|
||||
Sequence += _count;
|
||||
|
||||
return SST_Random_GetPRNGFloatArray(RNG, _array, _count, _min, _max);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
float ZRandomGenerator::GetGaussianFloat( float _min, float _max )
|
||||
{
|
||||
float r1, r2;
|
||||
|
||||
r1 = GetFloat();
|
||||
r2 = GetFloat();
|
||||
|
||||
return getGaussianHelper(_min, _max, r1, r2);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZRandomGenerator::GetGaussianFloatArray( float *_array, size_t _count, float _min, float _max )
|
||||
{
|
||||
size_t i;
|
||||
float r1, r2;
|
||||
|
||||
for (i = 0; i < _count; ++i)
|
||||
{
|
||||
r1 = GetFloat();
|
||||
r2 = GetFloat();
|
||||
|
||||
_array[i] = getGaussianHelper(_min, _max, r1, r2);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int ZRandomGenerator::GetGaussianInt( int _min, int _max )
|
||||
{
|
||||
return (int)GetGaussianFloat((float)_min + 0.5f, (float)_max + 0.5f);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZRandomGenerator::GetGaussianIntArray( int *_array, size_t _count, int _min, int _max )
|
||||
{
|
||||
size_t i;
|
||||
float r1, r2;
|
||||
|
||||
for (i = 0; i < _count; ++i)
|
||||
{
|
||||
r1 = GetFloat();
|
||||
r2 = GetFloat();
|
||||
|
||||
_array[i] = (int)getGaussianHelper((float)_min + 0.5f, (float)_max + 0.5f, r1, r2);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int ZRandomGenerator::GetInt()
|
||||
{
|
||||
++Sequence;
|
||||
|
||||
return SST_Random_GetPRNGInt(RNG, STDINT_MIN, STDINT_MAX);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZRandomGenerator::GetIntArray( int *_array, size_t _count )
|
||||
{
|
||||
Sequence += _count;
|
||||
|
||||
return SST_Random_GetPRNGIntArray(RNG, _array, _count, STDINT_MIN, STDINT_MAX);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int ZRandomGenerator::GetIntInRange( int _min, int _max )
|
||||
{
|
||||
++Sequence;
|
||||
|
||||
return SST_Random_GetPRNGInt(RNG, _min, _max);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZRandomGenerator::GetIntArrayInRange( int *_array, size_t _count, int _min, int _max )
|
||||
{
|
||||
Sequence += _count;
|
||||
|
||||
return SST_Random_GetPRNGIntArray(RNG, _array, _count, _min, _max);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
uint32_t ZRandomGenerator::GetSeed()
|
||||
{
|
||||
return Seed;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
uint64_t ZRandomGenerator::GetSequence()
|
||||
{
|
||||
return Sequence;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZRandomGenerator::SetSequence( uint64_t _seq )
|
||||
{
|
||||
//If less than, new instance
|
||||
if (_seq < Sequence)
|
||||
SetSeed(Seed);
|
||||
|
||||
while (Sequence < _seq)
|
||||
{
|
||||
SST_Random_GetPRNGInt(RNG, 0, 1);
|
||||
++Sequence;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZRandomGenerator::SetSeed( uint32_t _seed )
|
||||
{
|
||||
if (RNG != NULL) SST_Random_DestroyPRNG(RNG);
|
||||
|
||||
Seed = _seed;
|
||||
Sequence = 0;
|
||||
|
||||
RNG = SST_Random_CreatePRNGFromSeed(Type, Seed);
|
||||
|
||||
ZASSERT_RUNTIME(RNG != NULL, "ZRandomGenerator: Failure to initialize SST_PRNG_Instance!");
|
||||
}
|
||||
33
ZUtil/ZReadWriteLock.cpp
Normal file
33
ZUtil/ZReadWriteLock.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#include <ZUtil/ZReadWriteLock.hpp>
|
||||
#include <ZUtil/ZAssert.hpp>
|
||||
|
||||
ZReadWriteLock::ZReadWriteLock()
|
||||
: Lock(SST_Concurrency_CreateReadWriteLock())
|
||||
{
|
||||
ZASSERT_RUNTIME(Lock != NULL, "ZReadWriteLock failed to allocate lock from libsst-concurrency!");
|
||||
}
|
||||
|
||||
ZReadWriteLock::~ZReadWriteLock()
|
||||
{
|
||||
SST_Concurrency_DestroyReadWriteLock(Lock);
|
||||
}
|
||||
|
||||
bool ZReadWriteLock::LockForReading( uint32_t ticks ) const
|
||||
{
|
||||
return SST_Concurrency_LockForReading(Lock, ticks) != 0;
|
||||
}
|
||||
|
||||
bool ZReadWriteLock::LockForWriting( uint32_t ticks )
|
||||
{
|
||||
return SST_Concurrency_LockForWriting(Lock, ticks) != 0;
|
||||
}
|
||||
|
||||
void ZReadWriteLock::EndReading( ) const
|
||||
{
|
||||
SST_Concurrency_EndReading(Lock);
|
||||
}
|
||||
|
||||
void ZReadWriteLock::EndWriting( )
|
||||
{
|
||||
SST_Concurrency_EndWriting(Lock);
|
||||
}
|
||||
104
ZUtil/ZRegistry.cpp
Normal file
104
ZUtil/ZRegistry.cpp
Normal file
@@ -0,0 +1,104 @@
|
||||
#include <ZUtil/ZRegistry.hpp>
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZRegistry::ZRegistry()
|
||||
: Lock(), Tree()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZRegistry::ZRegistry( const ZKVTree& _tree )
|
||||
: Lock(), Tree(_tree)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZRegistry::~ZRegistry()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZRegistry::Erase( const ZString& _key )
|
||||
{
|
||||
Lock.LockForWriting(SST_WAIT_INFINITE);
|
||||
|
||||
ZKVTree::Iterator itr = Tree.Find(_key);
|
||||
|
||||
if (itr != Tree.End()) {
|
||||
Tree.Erase(itr);
|
||||
}
|
||||
|
||||
Lock.EndWriting();
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
const ZRegistry::Value ZRegistry::Get( const ZString& _key ) const
|
||||
{
|
||||
Lock.LockForReading(SST_WAIT_INFINITE);
|
||||
|
||||
ZKVTree::Iterator itr = Tree.Find(_key);
|
||||
|
||||
if (itr != Tree.End()) {
|
||||
ZRegistry::Value val(itr.GetValue(), true);
|
||||
Lock.EndReading();
|
||||
return val;
|
||||
}
|
||||
|
||||
Lock.EndReading();
|
||||
return ZRegistry::Value("", false);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
bool ZRegistry::Put( const ZString& _key, const ZString& _value )
|
||||
{
|
||||
size_t i = _key.Length();
|
||||
|
||||
//ZRegistry does not support sibling nodes with the same name
|
||||
if (ZStringAlgo::FindFirstOf(_key, "[]") != ZSTL::InvalidPos)
|
||||
return false;
|
||||
|
||||
Lock.LockForWriting(SST_WAIT_INFINITE);
|
||||
|
||||
/*
|
||||
NOTE: This algorithm is not currently needed with the way ZKVTree works, but
|
||||
that may change - placing value-less nodes in KV tree may be incorrect. If that
|
||||
changes, this should work.
|
||||
|
||||
Algorithm:
|
||||
|
||||
attempt to place full key
|
||||
if it succeeds, return true
|
||||
else
|
||||
while (valid path)
|
||||
attempt key - child (i.e., A.B.C.d -> A.B.C, A.B.C -> A.B, A.B -> A, A -> '')
|
||||
if success, attempt full key
|
||||
else repeat
|
||||
*/
|
||||
while (i > 0) {
|
||||
Tree.Put(ZString(_key, 0, i), _value);
|
||||
|
||||
if (i == _key.Length()) {
|
||||
break;
|
||||
} else {
|
||||
i = _key.Length();
|
||||
}
|
||||
|
||||
i = ZStringAlgo::FindLast(_key, ZKVTREE_PATH_SEPARATOR, 0, i);
|
||||
|
||||
if (i == ZSTL::InvalidPos)
|
||||
break;
|
||||
}
|
||||
|
||||
Lock.EndWriting();
|
||||
|
||||
return i > 0;
|
||||
}
|
||||
35
ZUtil/ZSemaphore.cpp
Normal file
35
ZUtil/ZSemaphore.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#include <ZUtil/ZSemaphore.hpp>
|
||||
#include <ZUtil/ZAssert.hpp>
|
||||
#include <SST/SST_Concurrency.h> //For SST_WAIT_INFINITE
|
||||
|
||||
ZSemaphore::ZSemaphore(int _initialCount)
|
||||
: Semaphore(SST_Concurrency_CreateSemaphore(_initialCount))
|
||||
{
|
||||
ZASSERT_RUNTIME(Semaphore != NULL, "ZSemaphore failed to allocate semaphore from libsst-concurrency!");
|
||||
}
|
||||
|
||||
ZSemaphore::~ZSemaphore()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ZSemaphore::Post()
|
||||
{
|
||||
SST_Concurrency_PostSemaphore(Semaphore, 1);
|
||||
}
|
||||
|
||||
void ZSemaphore::Post( uint32_t _count )
|
||||
{
|
||||
SST_Concurrency_PostSemaphore(Semaphore, _count);
|
||||
}
|
||||
|
||||
bool ZSemaphore::Wait()
|
||||
{
|
||||
return SST_Concurrency_WaitSemaphore(Semaphore, SST_WAIT_INFINITE) != 0;
|
||||
}
|
||||
|
||||
bool ZSemaphore::Wait( uint32_t _ms )
|
||||
{
|
||||
return SST_Concurrency_WaitSemaphore(Semaphore, _ms) != 0;
|
||||
}
|
||||
|
||||
38
ZUtil/ZSimplexNoise.cpp
Normal file
38
ZUtil/ZSimplexNoise.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#include <ZUtil/ZUtil.hpp>
|
||||
#include <ZUtil/ZSimplexNoise.hpp>
|
||||
#include <SST/SST_SimplexNoise.h>
|
||||
|
||||
ZSimplexNoise::ZSimplexNoise()
|
||||
{
|
||||
this->simplexGenerator = SST_Random_CreateSimplexNoise();
|
||||
}
|
||||
|
||||
void ZSimplexNoise::reseed(const int _seed)
|
||||
{
|
||||
SST_Random_ReseedSimplexNoise(this->simplexGenerator, _seed);
|
||||
}
|
||||
|
||||
float ZSimplexNoise::noise1(const float _x)
|
||||
{
|
||||
return SST_Random_MapSimplexNoise1D(this->simplexGenerator, _x);
|
||||
}
|
||||
|
||||
// 2D simplex noise
|
||||
float ZSimplexNoise::noise2(const float _x, const float _y)
|
||||
{
|
||||
return SST_Random_MapSimplexNoise2D(this->simplexGenerator, _x, _y);
|
||||
}
|
||||
|
||||
// 3D simplex noise
|
||||
float ZSimplexNoise::noise3(const float _x, const float _y, const float _z)
|
||||
{
|
||||
return SST_Random_MapSimplexNoise3D(this->simplexGenerator, _x, _y, _z);
|
||||
}
|
||||
|
||||
// 4D simplex noise
|
||||
float ZSimplexNoise::noise4(const float _x, const float _y, const float _z, const float _w)
|
||||
{
|
||||
return SST_Random_MapSimplexNoise4D(this->simplexGenerator, _x, _y, _z, _w);
|
||||
}
|
||||
|
||||
|
||||
218
ZUtil/ZSimplexNoiseMap.cpp
Normal file
218
ZUtil/ZSimplexNoiseMap.cpp
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
ZSimplexNoiseMap.cpp
|
||||
Author : Chris Ertel
|
||||
|
||||
Purpose : Implementation of 2D, 3D, and 4D simplex noise maps.
|
||||
|
||||
Changelog
|
||||
2/20/11 - Creation (crertel)
|
||||
*/
|
||||
|
||||
#include <ZUtil/ZSimplexNoise.hpp>
|
||||
#include <ZUtil/ZSimplexNoiseMap.hpp>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
bool ZSimplexNoiseMap2D::Generate(int _seed)
|
||||
{
|
||||
int buffsize;
|
||||
int currOctave;
|
||||
float b_coeff;
|
||||
float a_coeff;
|
||||
float u,v;
|
||||
int xstride;
|
||||
|
||||
noiseGen.reseed(_seed);
|
||||
|
||||
/* allocate buffer */
|
||||
if (this->values != NULL)
|
||||
{
|
||||
delete [] this->values;
|
||||
this->values = NULL;
|
||||
}
|
||||
|
||||
buffsize = this->numberSamplesInX * this->numberSamplesInY;
|
||||
this->values = znew float[buffsize];
|
||||
if (this->values == NULL)
|
||||
return false;
|
||||
|
||||
memset(this->values, 0, buffsize * sizeof(float));
|
||||
|
||||
/* fill in the noise */
|
||||
/* for good reference, consult http://local.wasp.uwa.edu.au/~pbourke/texture_colour/perlin/ */
|
||||
for (currOctave = 0; currOctave < this->numberofoctaves; currOctave++)
|
||||
{
|
||||
b_coeff = pow(this->lacunarity, currOctave);
|
||||
a_coeff = pow(this->persistence, currOctave);
|
||||
|
||||
for (int i = 0; i < this->numberSamplesInX; i++)
|
||||
{
|
||||
u = ((float) i)/((float) this->numberSamplesInX);
|
||||
xstride = i * this->numberSamplesInY;
|
||||
for (int j = 0; j < this->numberSamplesInY; j++)
|
||||
{
|
||||
v = ((float) j)/((float) this->numberSamplesInY);
|
||||
this->values[ xstride + j ] += ((float) this->noiseGen.noise2(b_coeff * u, b_coeff * v))/a_coeff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ZSimplexNoiseMap2D::Cleanup()
|
||||
{
|
||||
delete [] this->values;
|
||||
this->values = NULL;
|
||||
}
|
||||
|
||||
float ZSimplexNoiseMap2D::getValue(int _x, int _y)
|
||||
{
|
||||
float ret;
|
||||
int xstride = _x * this->numberSamplesInY;
|
||||
ret = this->values[ xstride + _y];
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ZSimplexNoiseMap3D::Generate(int _seed)
|
||||
{
|
||||
int buffsize;
|
||||
int currOctave;
|
||||
float b_coeff;
|
||||
float a_coeff;
|
||||
float u,v,w;
|
||||
int xstride, ystride;
|
||||
|
||||
noiseGen.reseed(_seed);
|
||||
|
||||
/* allocate buffer */
|
||||
if (this->values != NULL)
|
||||
{
|
||||
delete [] this->values;
|
||||
this->values = NULL;
|
||||
}
|
||||
|
||||
buffsize = this->numberSamplesInX * this->numberSamplesInY * this->numberSamplesInZ;
|
||||
this->values = znew float[buffsize];
|
||||
if (this->values == NULL)
|
||||
return false;
|
||||
|
||||
memset(this->values, 0, buffsize * sizeof(float));
|
||||
|
||||
/* fill in the noise */
|
||||
for (currOctave = 0; currOctave < this->numberofoctaves; currOctave++)
|
||||
{
|
||||
b_coeff = pow(this->lacunarity, currOctave);
|
||||
a_coeff = pow(this->persistence, currOctave);
|
||||
|
||||
for (int i = 0; i < this->numberSamplesInX; i++)
|
||||
{
|
||||
u = ((float) i)/((float) this->numberSamplesInX);
|
||||
xstride = i * this->numberSamplesInY * this->numberSamplesInZ;
|
||||
|
||||
for (int j = 0; j < this->numberSamplesInY; j++)
|
||||
{
|
||||
v = ((float) j)/((float) this->numberSamplesInY);
|
||||
|
||||
ystride = j * this->numberSamplesInZ ;
|
||||
for (int k = 0; k < this->numberSamplesInZ; k++)
|
||||
{
|
||||
w = ((float) k)/((float) this->numberSamplesInZ);
|
||||
this->values[xstride+ystride+k] += ((float) this->noiseGen.noise3(b_coeff * u, b_coeff * v, b_coeff * w))/a_coeff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ZSimplexNoiseMap3D::Cleanup()
|
||||
{
|
||||
delete [] this->values;
|
||||
this->values = NULL;
|
||||
}
|
||||
|
||||
float ZSimplexNoiseMap3D::getValue(int _x, int _y, int _z)
|
||||
{
|
||||
float ret;
|
||||
int xstride = _x * this->numberSamplesInY * this->numberSamplesInZ;
|
||||
int ystride = _y * this->numberSamplesInZ;
|
||||
ret = this->values[ xstride + ystride + _z];
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ZSimplexNoiseMap4D::Generate(int _seed)
|
||||
{
|
||||
int buffsize;
|
||||
int currOctave;
|
||||
float b_coeff;
|
||||
float a_coeff;
|
||||
float u,v,w,r;
|
||||
int xstride, ystride, zstride;
|
||||
|
||||
noiseGen.reseed(_seed);
|
||||
|
||||
/* allocate buffer */
|
||||
if (this->values != NULL)
|
||||
{
|
||||
delete [] this->values;
|
||||
this->values = NULL;
|
||||
}
|
||||
|
||||
buffsize = this->numberSamplesInX * this->numberSamplesInY * this->numberSamplesInZ * this->numberSamplesInW;
|
||||
this->values = znew float[buffsize];
|
||||
if (this->values == NULL)
|
||||
return false;
|
||||
|
||||
/* fill in the noise */
|
||||
for (currOctave = 0; currOctave < this->numberofoctaves; currOctave++)
|
||||
{
|
||||
b_coeff = pow(this->lacunarity, currOctave);
|
||||
a_coeff = pow(this->persistence, currOctave);
|
||||
|
||||
for (int i = 0; i < this->numberSamplesInX; i++)
|
||||
{
|
||||
u = ((float) i)/((float) this->numberSamplesInX);
|
||||
xstride = i * this->numberSamplesInY * this->numberSamplesInZ * this->numberSamplesInW;
|
||||
|
||||
for (int j = 0; j < this->numberSamplesInY; j++)
|
||||
{
|
||||
v = ((float) j)/((float) this->numberSamplesInY);
|
||||
ystride = j * this->numberSamplesInZ * this->numberSamplesInW;
|
||||
|
||||
for (int k = 0; k < this->numberSamplesInZ; k++)
|
||||
{
|
||||
w = ((float) k)/((float) this->numberSamplesInZ);
|
||||
zstride = k * this->numberSamplesInW;
|
||||
|
||||
for (int l = 0; l < this->numberSamplesInW; l++)
|
||||
{
|
||||
r = ((float) l)/((float) this->numberSamplesInW);
|
||||
this->values[xstride+ystride+zstride+l] += ((float) this->noiseGen.noise4(b_coeff * u, b_coeff * v, b_coeff * w, b_coeff*r))/a_coeff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ZSimplexNoiseMap4D::Cleanup()
|
||||
{
|
||||
delete [] this->values;
|
||||
this->values = NULL;
|
||||
}
|
||||
|
||||
float ZSimplexNoiseMap4D::getValue(int _x, int _y, int _z, int _w)
|
||||
{
|
||||
float ret;
|
||||
int xstride = _x * this->numberSamplesInY * this->numberSamplesInZ * this->numberSamplesInW;
|
||||
int ystride = _y * this->numberSamplesInZ * this->numberSamplesInW;
|
||||
int zstride = _z * this->numberSamplesInW;
|
||||
ret = this->values[ xstride + ystride + zstride + _w];
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
360
ZUtil/ZTaskStream.cpp
Normal file
360
ZUtil/ZTaskStream.cpp
Normal file
@@ -0,0 +1,360 @@
|
||||
#include <ZUtil/ZTaskStream.hpp>
|
||||
|
||||
#include <ZUtil/ZAlloc.hpp>
|
||||
|
||||
/////////////////
|
||||
/* ZTaskThread */
|
||||
/////////////////
|
||||
|
||||
ZThreadReturn ZTaskThread::run( uint64_t _dt )
|
||||
{
|
||||
URFP(_dt);
|
||||
|
||||
ZPtr<ZTask> task;
|
||||
|
||||
//Check if a task is available. If it isn't set our status as waiting, then do an full wait
|
||||
if(!TaskSema.Wait(0)) {
|
||||
this->ThrStatus = ZTTS_WAITING;
|
||||
TaskSema.Wait();
|
||||
}
|
||||
|
||||
//At this point, we've decremented the semaphore. There should be a task waiting
|
||||
TaskLock.Acquire();
|
||||
|
||||
//No tasks -> a) Logic error b) time to exit. Gracefully handle this
|
||||
if(Tasks.Size() == 0) {
|
||||
TaskLock.Release();
|
||||
return ZTR_TERMINATE;
|
||||
}
|
||||
|
||||
//Ok, we're executing tasks
|
||||
ThrStatus = ZTTS_EXECUTING;
|
||||
|
||||
task = Tasks.PopBack();
|
||||
|
||||
//Save the priority of the task that is executing
|
||||
CurrentTaskPriority = task->Priority;
|
||||
|
||||
TaskLock.Release();
|
||||
|
||||
//If the task has not been canceled
|
||||
if (!task->bCancelTask) {
|
||||
//Execute it and check task return status
|
||||
if (task->Execute(task->TaskArgument) == ZTRS_FAILURE)
|
||||
task->OnTaskFailed(task->TaskArgument);
|
||||
} else {
|
||||
//Reset the cancel flag
|
||||
task->bCancelTask = false;
|
||||
}
|
||||
|
||||
return ZTR_LOOP;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
ZTaskThread::ZTaskThread( ZTaskStream *_stream, ZTaskThreadId _id )
|
||||
: TaskLock(), TaskSema(0), Stream(_stream), Id(_id), ThrStatus(ZTTS_UNINITIALIZED)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
ZTaskThread::~ZTaskThread()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void ZTaskThread::PushTask( ZPtr<ZTask> _task )
|
||||
{
|
||||
//Add a task while the mutex is locked
|
||||
TaskLock.Acquire();
|
||||
|
||||
Tasks.PushBack(_task);
|
||||
|
||||
TaskLock.Release();
|
||||
|
||||
//1 new task available.
|
||||
TaskSema.Post();
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/////////////////
|
||||
/* ZTaskStream */
|
||||
/////////////////
|
||||
|
||||
ZTaskStream::ZTaskStream()
|
||||
: TaskStreamLock(), TaskStreamSema(0),
|
||||
FrameCompletedEvent(), PausedEvent(),
|
||||
Tasks(ZTS_DEFAULT_BUFFER_SIZE), bPaused(false), bShouldHalt(false)
|
||||
{
|
||||
//Initially unpaused
|
||||
PausedEvent.Notify();
|
||||
|
||||
SetTaskThreadCount(1);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
ZTaskStream::~ZTaskStream()
|
||||
{
|
||||
SetTaskThreadCount(0);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void ZTaskStream::PushTask( ZPtr<ZTask> _task )
|
||||
{
|
||||
TaskStreamLock.Acquire();
|
||||
|
||||
Tasks.PushBack(_task);
|
||||
|
||||
TaskStreamLock.Release();
|
||||
|
||||
TaskStreamSema.Post(); // 1 new task to schedule
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void ZTaskStream::PushTask( ZTask* _task )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void ZTaskStream::PushTasks( ZArray< ZPtr<ZTask> >& _tasks )
|
||||
{
|
||||
size_t count = _tasks.Size();
|
||||
|
||||
TaskStreamLock.Acquire();
|
||||
|
||||
ZArrayAlgo::Append(Tasks, _tasks);
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
Tasks.PushBack( _tasks[i]);
|
||||
TaskStreamSema.Post(); // 1 new task to schedule
|
||||
}
|
||||
|
||||
TaskStreamLock.Release();
|
||||
}
|
||||
|
||||
void ZTaskStream::PushTasks( ZTask* _tasks, size_t _count )
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void ZTaskStream::ExecuteTasks(int _frameTime)
|
||||
{
|
||||
ZPtr<ZTask> curTask;
|
||||
ZArray< ZPtr<ZTask> > tmp;
|
||||
ZArray< ZPtr<ZTask> > delayed;
|
||||
|
||||
//Wait for the paused event to be signaled.
|
||||
//When it isn't, this code blocks.
|
||||
PausedEvent.Wait();
|
||||
|
||||
uint64_t timeStart = ZConcurrency::GetTicks();
|
||||
uint64_t timeEnd = timeStart + _frameTime;
|
||||
uint64_t timeNow = timeStart;
|
||||
|
||||
//Schedule tasks until timer elapsed
|
||||
for (;;) {
|
||||
//If we need to halt, do so
|
||||
if (bShouldHalt) {
|
||||
bShouldHalt = false;
|
||||
return;
|
||||
}
|
||||
|
||||
//Check if we've run out of time
|
||||
timeNow = ZConcurrency::GetTicks();
|
||||
|
||||
if (timeEnd < timeNow) {
|
||||
break;
|
||||
}
|
||||
|
||||
//Empty task queue into a temporary array so we minimize time held with lock
|
||||
TaskStreamLock.Acquire();
|
||||
|
||||
while(TaskStreamSema.Wait(0)) {
|
||||
tmp.PushBack(Tasks.PopBack());
|
||||
}
|
||||
|
||||
TaskStreamLock.Release();
|
||||
|
||||
//Check each task
|
||||
while (tmp.Size() > 0) {
|
||||
//Start assigning tasks to threads
|
||||
curTask = tmp.PopBack();
|
||||
|
||||
//If our task can be delayed
|
||||
if (curTask->Priority > 0) {
|
||||
size_t newPriority;
|
||||
uint64_t tickDelta = ZConcurrency::GetTicks() - timeStart;
|
||||
if (tickDelta > curTask->Priority) {
|
||||
newPriority = 0;
|
||||
} else {
|
||||
newPriority = curTask->Priority - (size_t)tickDelta;
|
||||
}
|
||||
|
||||
curTask->Priority = newPriority;
|
||||
|
||||
delayed.PushBack(curTask); //delay the current task until after priority zero tasks are executed
|
||||
} else {
|
||||
//Assign to be executed immediately
|
||||
TaskThreads[AssignTask(curTask.Pointer())]->PushTask(curTask);
|
||||
}
|
||||
}
|
||||
|
||||
//Check what priority tasks are executing
|
||||
bool execP0 = false; //Priority 0 tasks are executing
|
||||
bool execPN = false; //Priority N > 0 tasks are executing
|
||||
|
||||
for (ZArray<ZTaskThread*>::Iterator itr = TaskThreads.Begin(); itr != TaskThreads.End(); itr++) {
|
||||
ZTaskThread* thr = *itr;
|
||||
|
||||
if(thr->ThrStatus != ZTTS_WAITING) {
|
||||
if(thr->CurrentTaskPriority == 0) {
|
||||
execP0 = true;
|
||||
} else {
|
||||
execPN = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//No priority 0 tasks executing -> schedule lower priority stuff now
|
||||
if (!execP0) {
|
||||
//At least one delayed task to assign?
|
||||
if(delayed.Size() != 0) {
|
||||
//Schedule a delayed task now
|
||||
ZPtr<ZTask> task = delayed.PopBack();
|
||||
TaskThreads[AssignTask(task.Pointer())]->PushTask(task);
|
||||
execPN = true;
|
||||
}
|
||||
}
|
||||
|
||||
//No priority N tasks executing -> wait for something to do
|
||||
if(!execPN) {
|
||||
//Check if we've run out of time
|
||||
timeNow = ZConcurrency::GetTicks();
|
||||
|
||||
if (timeEnd < timeNow) {
|
||||
break;
|
||||
}
|
||||
|
||||
//Compute remaining time, and wait for up to that amount or
|
||||
//the scheduler wait period, whichever is less.
|
||||
uint64_t timeLeft = timeEnd - timeNow;
|
||||
|
||||
bool newTasks = TaskStreamSema.Wait((uint32_t)timeLeft);
|
||||
|
||||
if (newTasks) {
|
||||
//Calling WaitSemaphore() actually decreased the count but since we won't
|
||||
//duplicate code here, we'll just re-increment it because next loop
|
||||
//iteration will do another WaitSemaphore() that won't block.
|
||||
TaskStreamSema.Post();
|
||||
} else {
|
||||
//Timeout -> Time to exit
|
||||
break;
|
||||
}
|
||||
}
|
||||
} //main scheduling loop
|
||||
|
||||
// return delayed tasks to the task stream
|
||||
PushTasks(delayed);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
size_t ZTaskStream::GetTaskThreadCount()
|
||||
{
|
||||
return TaskThreads.Size();
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void ZTaskStream::HaltFrame()
|
||||
{
|
||||
bShouldHalt = true;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void ZTaskStream::PauseFrame( bool _pause )
|
||||
{
|
||||
if (_pause)
|
||||
{
|
||||
this->bPaused = true;
|
||||
PausedEvent.Reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
this->bPaused = false;
|
||||
PausedEvent.Notify();
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void ZTaskStream::SetTaskThreadCount( size_t _count )
|
||||
{
|
||||
size_t i, j;
|
||||
|
||||
TaskStreamLock.Acquire();
|
||||
|
||||
//If there are n task threads and the user wants n + k threads, there is no point in killing all n
|
||||
//threads just to create n + k more all over again. Similarly, if the user has n threads but wants
|
||||
//n - k (> 0), then only k threads need to be shut down.
|
||||
if (_count > TaskThreads.Size())
|
||||
{
|
||||
//In with the new
|
||||
for (i = TaskThreads.Size(); i < _count; ++i)
|
||||
{
|
||||
ZTaskThread* thr = znew ZTaskThread(this, i);
|
||||
TaskThreads.PushBack(thr);
|
||||
thr->StartThread();
|
||||
while(!thr->ThreadInitialized())
|
||||
thr->WaitInitialized();
|
||||
}
|
||||
|
||||
}
|
||||
else if (_count < TaskThreads.Size())
|
||||
{
|
||||
//KILLAMANJARO!
|
||||
size_t killCount = TaskThreads.Size() - _count;
|
||||
|
||||
//Out with the old
|
||||
for (i = TaskThreads.Size() - 1, j = 0; j < killCount; --i, ++j)
|
||||
KillTaskThread(i);
|
||||
}
|
||||
|
||||
TaskStreamLock.Release();
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
ZTaskThreadId ZTaskStream::AssignTask( ZTask *_task )
|
||||
{
|
||||
URFP(_task);
|
||||
|
||||
static int next = 0;
|
||||
|
||||
int taskThread = next++ % TaskThreads.Size();
|
||||
|
||||
return TaskThreads[taskThread]->Id;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void ZTaskStream::KillTaskThread( size_t _idx )
|
||||
{
|
||||
//Post a task that does not exist, task thread will shut down
|
||||
TaskThreads[_idx]->TaskSema.Post();
|
||||
TaskThreads[_idx]->ShutdownThread();
|
||||
zdelete TaskThreads[_idx];
|
||||
}
|
||||
322
ZUtil/ZThread.cpp
Normal file
322
ZUtil/ZThread.cpp
Normal file
@@ -0,0 +1,322 @@
|
||||
#include <ZUtil/ZThread.hpp>
|
||||
#include <ZUtil/ZLog.hpp>
|
||||
#include <ZSTL/ZString.hpp>
|
||||
|
||||
#ifdef _MSC_VER //begin Microsoft Visual C++ specific code
|
||||
#include <windows.h>
|
||||
#undef CreateMutex
|
||||
#undef CreateEvent
|
||||
const DWORD MS_VC_EXCEPTION=0x406D1388;
|
||||
|
||||
#pragma pack(push,8)
|
||||
typedef struct tagTHREADNAME_INFO
|
||||
{
|
||||
DWORD dwType; // Must be 0x1000.
|
||||
LPCSTR szName; // Pointer to name (in user addr space).
|
||||
DWORD dwThreadID; // Thread ID (-1=caller thread).
|
||||
DWORD dwFlags; // Reserved for future use, must be zero.
|
||||
} THREADNAME_INFO;
|
||||
#pragma pack(pop)
|
||||
|
||||
//This disgusting little hack sets the thread's name in the MSVC debugger
|
||||
void NativeSetThreadName(const char* threadName)
|
||||
{
|
||||
THREADNAME_INFO info;
|
||||
info.dwType = 0x1000;
|
||||
info.szName = threadName;
|
||||
info.dwThreadID = (DWORD)~0;
|
||||
info.dwFlags = 0;
|
||||
|
||||
__try
|
||||
{
|
||||
RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info );
|
||||
}
|
||||
__except(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
#define NativeSetThreadName(name)
|
||||
#endif //end Microsoft Visual C++ specific code
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZThread::ZThread(ZString _threadName)
|
||||
:
|
||||
ThreadName(_threadName),
|
||||
bShouldShutdown(false), bShouldPause(false),
|
||||
ThreadContext(),
|
||||
ThreadLock(),
|
||||
InitEvent(),
|
||||
PreviousTickCount(0), CurrentTickCount(0),
|
||||
bIsRunning(false), bIsInitialized(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZThread::~ZThread()
|
||||
{
|
||||
ShutdownThread();
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int ZThread::InitThread(void *_runnable)
|
||||
{
|
||||
ZThread *thr = ((ZThread*)_runnable);
|
||||
|
||||
NativeSetThreadName(thr->GetThreadName().Data());
|
||||
|
||||
//TODO - hack for now, need to fix CreateThread
|
||||
thr->ThreadContext.ThreadId = ZConcurrency::GetThreadId();
|
||||
|
||||
thr->initThread();
|
||||
|
||||
thr->bIsInitialized = true;
|
||||
|
||||
thr->InitEvent.Notify();
|
||||
|
||||
thr->Run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZThread::Run()
|
||||
{
|
||||
uint64_t dt;
|
||||
|
||||
bIsRunning = true;
|
||||
|
||||
while (!bShouldShutdown)
|
||||
{
|
||||
while (bShouldPause)
|
||||
ZConcurrency::YieldThread();
|
||||
|
||||
ExecuteThreadRequests();
|
||||
|
||||
PreviousTickCount = CurrentTickCount;
|
||||
CurrentTickCount = ZConcurrency::GetTicks();
|
||||
dt = CurrentTickCount - PreviousTickCount;
|
||||
|
||||
switch (run(dt))
|
||||
{
|
||||
case ZTR_LOOP: continue;
|
||||
case ZTR_PAUSE: bShouldPause = true; break;
|
||||
case ZTR_TERMINATE: bShouldShutdown = true; break;
|
||||
default: bShouldShutdown = true; break;
|
||||
}
|
||||
}
|
||||
|
||||
ExecuteThreadRequests();
|
||||
|
||||
shutdownThread();
|
||||
|
||||
bIsInitialized = false;
|
||||
bIsRunning = false;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZThread::AddThreadRequest(ZPtr<ZThreadRequest> _request, bool _wait)
|
||||
{
|
||||
|
||||
//If this is thread adding a request to itself, don't deadlock
|
||||
if(IsCallerTheThread()) {
|
||||
_request->Execute(this);
|
||||
return;
|
||||
}
|
||||
|
||||
ThreadLock.Acquire();
|
||||
{
|
||||
ZTRCallbacks.PushBack(_request);
|
||||
}
|
||||
ThreadLock.Release();
|
||||
|
||||
if (_wait)
|
||||
_request->Wait();
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZThread::AddCallbackRequest(ZThreadCallbackFunc function, void* arg, bool async)
|
||||
{
|
||||
ZThreadCallbackRequest req;
|
||||
|
||||
//If this is the thread adding a callback to itself, don't deadlock
|
||||
if(IsCallerTheThread()) {
|
||||
function(this, arg);
|
||||
return;
|
||||
}
|
||||
|
||||
req.arg = arg;
|
||||
req.callback = function;
|
||||
req.doneEvent = (async ? NULL : SST_Concurrency_CreateEvent());
|
||||
|
||||
ThreadLock.Acquire();
|
||||
{
|
||||
Callbacks.PushBack(req);
|
||||
}
|
||||
ThreadLock.Release();
|
||||
|
||||
//Non-async -> wait for done
|
||||
if(!async) {
|
||||
SST_Concurrency_WaitEvent(req.doneEvent, SST_WAIT_INFINITE);
|
||||
SST_Concurrency_DestroyEvent(req.doneEvent);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZThread::ExecuteThreadRequests()
|
||||
{
|
||||
ZList< ZPtr<ZThreadRequest> > persistentRequests;
|
||||
|
||||
ThreadLock.Acquire();
|
||||
|
||||
while (!ZTRCallbacks.Empty())
|
||||
{
|
||||
//Don't execute if we are told to stop
|
||||
if (ZTRCallbacks.Front()->Stop)
|
||||
{
|
||||
ZTRCallbacks.Front()->Persist = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ZTRCallbacks.Front()->CompletedEvent.Reset();
|
||||
|
||||
ZTRCallbacks.Front()->Execute(this);
|
||||
|
||||
ZTRCallbacks.Front()->CompletedEvent.Notify();
|
||||
}
|
||||
|
||||
//If we are to persist, do so
|
||||
if (ZTRCallbacks.Front()->Persist)
|
||||
persistentRequests.PushBack(ZTRCallbacks.PopFront());
|
||||
else
|
||||
ZTRCallbacks.PopFront();
|
||||
}
|
||||
|
||||
while(!Callbacks.Empty()) {
|
||||
ZThreadCallbackRequest& req = Callbacks.Front();
|
||||
|
||||
req.callback(this, req.arg);
|
||||
if(req.doneEvent) {
|
||||
SST_Concurrency_SignalEvent(req.doneEvent);
|
||||
}
|
||||
|
||||
Callbacks.PopFront();
|
||||
}
|
||||
|
||||
|
||||
//Swap back in persistent requests
|
||||
ZTRCallbacks.Swap(persistentRequests);
|
||||
|
||||
ThreadLock.Release();
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
bool ZThread::StartThread()
|
||||
{
|
||||
bShouldShutdown = false;
|
||||
bShouldPause = false;
|
||||
|
||||
ThreadContext = ZConcurrency::CreateThread(ZThread::InitThread, this);
|
||||
|
||||
if (!ThreadContext.IsValid())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZThread::ShutdownThread()
|
||||
{
|
||||
bShouldShutdown = true;
|
||||
|
||||
if (ThreadContext.IsValid())
|
||||
{
|
||||
ZConcurrency::WaitThread(ThreadContext);
|
||||
ZConcurrency::DestroyThread(ThreadContext);
|
||||
ThreadContext.Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZThread::PauseThread()
|
||||
{
|
||||
bShouldPause = true;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZThread::RestartThread()
|
||||
{
|
||||
bShouldPause = false;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
bool ZThread::ThreadRunning()
|
||||
{
|
||||
return bIsRunning;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
bool ZThread::ThreadInitialized()
|
||||
{
|
||||
return bIsInitialized;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
uint32_t ZThread::GetThreadId()
|
||||
{
|
||||
return ThreadContext.ThreadId;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZString ZThread::GetThreadName()
|
||||
{
|
||||
ZString name;
|
||||
|
||||
ThreadLock.Acquire();
|
||||
|
||||
name = ThreadName;
|
||||
|
||||
ThreadLock.Release();
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZThread::WaitInitialized()
|
||||
{
|
||||
InitEvent.Wait();
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZThread::WaitShutdown()
|
||||
{
|
||||
if (ThreadContext.IsValid())
|
||||
ZConcurrency::WaitThread(ThreadContext);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
bool ZThread::IsCallerTheThread()
|
||||
{
|
||||
uint32_t callerThreadID = SST_Concurrency_GetThreadId();
|
||||
|
||||
return (callerThreadID == this->GetThreadId());
|
||||
}
|
||||
252
ZUtil/ZUtil.vcxproj
Normal file
252
ZUtil/ZUtil.vcxproj
Normal file
@@ -0,0 +1,252 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{49E96A5C-AC79-412B-BBBA-4653795D5EDC}</ProjectGuid>
|
||||
<RootNamespace>Util</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>11.0.50727.1</_ProjectFileVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>$(SolutionDir)Bin\x86\</OutDir>
|
||||
<IntDir>$(SolutionDir)Intermediate\$(Configuration)\$(Platform)\$(ProjectName)\</IntDir>
|
||||
<TargetName>$(ProjectName)-debug</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutDir>$(SolutionDir)Bin\x64\</OutDir>
|
||||
<IntDir>$(SolutionDir)Intermediate\$(Configuration)\$(Platform)\$(ProjectName)\</IntDir>
|
||||
<TargetName>$(ProjectName)-debug</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>$(SolutionDir)Bin\x86\</OutDir>
|
||||
<IntDir>$(SolutionDir)Intermediate\$(Configuration)\$(Platform)\$(ProjectName)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<OutDir>$(SolutionDir)Bin\x64\</OutDir>
|
||||
<IntDir>$(SolutionDir)Intermediate\$(Configuration)\$(Platform)\$(ProjectName)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)Include;$(SolutionDir)Lib/Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_DEBUG ZASSERT_ENABLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<DisableLanguageExtensions>false</DisableLanguageExtensions>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>false</TreatWarningAsError>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</ClCompile>
|
||||
<Lib />
|
||||
<Lib>
|
||||
<LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Midl>
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)Include;$(SolutionDir)Lib/Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_DEBUG ZASSERT_ENABLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<DisableLanguageExtensions>false</DisableLanguageExtensions>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>false</TreatWarningAsError>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</ClCompile>
|
||||
<Lib />
|
||||
<Lib>
|
||||
<LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)Include;$(SolutionDir)Lib/Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_RELEASE; _CRT_SECURE_NO_WARNINGS=1; SST_ASSERT_NODEBUG=1; ZSTL_DISABLE_RUNTIME_CHECKS=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Lib>
|
||||
<OutputFile>$(OutDir)$(ProjectName).lib</OutputFile>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Midl>
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)Include;$(SolutionDir)Lib/Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_RELEASE; _CRT_SECURE_NO_WARNINGS=1; SST_ASSERT_NODEBUG=1; ZSTL_DISABLE_RUNTIME_CHECKS=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="ZAllocWindow.cpp" />
|
||||
<ClCompile Include="ZBinaryBufferReader.cpp" />
|
||||
<ClCompile Include="ZBinaryBufferWriter.cpp" />
|
||||
<ClCompile Include="ZBinaryFileReader.cpp" />
|
||||
<ClCompile Include="ZBinaryFileWriter.cpp" />
|
||||
<ClCompile Include="ZJSONReader.cpp" />
|
||||
<ClCompile Include="ZJSONWriter.cpp" />
|
||||
<ClCompile Include="ZRegistry.cpp" />
|
||||
<ClCompile Include="ZLog.cpp" />
|
||||
<ClCompile Include="ZXMLReader.cpp" />
|
||||
<ClCompile Include="ZXMLWriter.cpp" />
|
||||
<ClCompile Include="ZConcurrency.cpp" />
|
||||
<ClCompile Include="ZEvent.cpp" />
|
||||
<ClCompile Include="ZMutex.cpp" />
|
||||
<ClCompile Include="ZReadWriteLock.cpp" />
|
||||
<ClCompile Include="ZSemaphore.cpp" />
|
||||
<ClCompile Include="ZTaskStream.cpp" />
|
||||
<ClCompile Include="ZThread.cpp" />
|
||||
<ClCompile Include="ZKVTree.cpp" />
|
||||
<ClCompile Include="ZAlloc.cpp" />
|
||||
<ClCompile Include="ZName.cpp" />
|
||||
<ClCompile Include="ZIniReader.cpp" />
|
||||
<ClCompile Include="ZIniWriter.cpp" />
|
||||
<ClCompile Include="ZRandomGenerator.cpp" />
|
||||
<ClCompile Include="ZSimplexNoise.cpp" />
|
||||
<ClCompile Include="ZSimplexNoiseMap.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\Include\ZUtil\ZAssert.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZAllocWindow.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZBinaryBufferReader.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZBinaryBufferWriter.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZBinaryFileReader.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZBinaryFileWriter.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZBinaryReader.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZBinaryWriter.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZJSONReader.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZJSONWriter.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZRegistry.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZUtil.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZUtilBuild.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZLog.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZXMLReader.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZXMLWriter.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZConcurrency.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZEvent.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZMutex.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZReadWriteLock.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZSemaphore.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZTaskStream.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZThread.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZKVTree.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZAlloc.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZReferenceCounter.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZSlabAllocator.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZSmartPointer.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZWeakPointer.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZBitmap.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZIniReader.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZIniWriter.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZNoise.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZNoiseMap.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZRandomGenerator.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZSimplexNoise.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZSimplexNoiseMap.hpp" />
|
||||
<ClInclude Include="..\Include\ZUtil\ZName.hpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\libsst-atomic\libsst-atomic.vcxproj">
|
||||
<Project>{43ed481f-c4a3-40ed-81a3-46c43dc4eb1e}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\libsst-concurrency\libsst-concurrency.vcxproj">
|
||||
<Project>{7af55ff8-2f78-42ec-8a05-7fa1ae514814}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\libsst-crypto\libsst-crypto.vcxproj">
|
||||
<Project>{e5172b73-ab9a-4702-998f-84c841b30c02}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\libsst-os\libsst-os.vcxproj">
|
||||
<Project>{4bac6d63-c2e8-43f7-87ea-ef953cbfddd3}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\libsst-random\libsst-random.vcxproj">
|
||||
<Project>{8aa34f81-4045-4613-88b7-6ff58d7e0a7a}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
278
ZUtil/ZUtil.vcxproj.filters
Normal file
278
ZUtil/ZUtil.vcxproj.filters
Normal file
@@ -0,0 +1,278 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\IO">
|
||||
<UniqueIdentifier>{0c1f31dc-02e7-4854-b43b-f34122d54aef}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\Concurrency">
|
||||
<UniqueIdentifier>{fad6c8b5-e651-439c-bb10-da7549c3489a}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\Memory">
|
||||
<UniqueIdentifier>{fdf92c2b-f4b3-4897-b3cb-fce4bfa6ab2c}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\Parsing">
|
||||
<UniqueIdentifier>{46ffdb11-088a-42e1-b6e4-d48521f8bbe8}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\Name">
|
||||
<UniqueIdentifier>{56d072e1-ad9b-4f1e-ba27-69ac3e6aa033}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\Random">
|
||||
<UniqueIdentifier>{1310d55f-38d1-4da8-a565-2d7f9d40a4f1}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\IO">
|
||||
<UniqueIdentifier>{c778d68f-0696-43bd-834c-a83f3e4e7926}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\Concurrency">
|
||||
<UniqueIdentifier>{99043719-ca05-4069-b7b4-c3a572f562bf}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\Memory">
|
||||
<UniqueIdentifier>{4b31f2cf-ae99-47a6-a73f-70917c38affb}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\Images">
|
||||
<UniqueIdentifier>{5792b217-d26d-4330-89f3-03afdec0dbf9}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\Parsing">
|
||||
<UniqueIdentifier>{c17952c6-c398-4dd0-8cf6-b101e689d7ab}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\Random">
|
||||
<UniqueIdentifier>{15ff240d-bda5-4b0e-890d-5c0c3504f1e3}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\Name">
|
||||
<UniqueIdentifier>{dd5284dc-acb7-43c6-985f-978b37eaa30d}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\Data Structures">
|
||||
<UniqueIdentifier>{5ba7ebcc-9121-466d-a20b-48433acc9793}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\Data Structures">
|
||||
<UniqueIdentifier>{ea8e988f-3565-46fb-bff7-a2a1b71be4be}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\Parsing\Binary">
|
||||
<UniqueIdentifier>{dc488f2c-c725-4010-a94a-3b2f16316e18}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\Parsing\Ini">
|
||||
<UniqueIdentifier>{8dddf8b2-5d9e-44d7-ae81-80e24681e795}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\Parsing\XML">
|
||||
<UniqueIdentifier>{45c76189-9994-4ae5-a18f-2f741f9f5054}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\Parsing\Binary">
|
||||
<UniqueIdentifier>{bc955f80-4159-4f9d-9baa-b30619e94f40}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\Parsing\Ini">
|
||||
<UniqueIdentifier>{e7c88882-2e0b-49a8-beb5-7bcf6ba6f9d1}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\Parsing\XML">
|
||||
<UniqueIdentifier>{e27c228e-1536-49ce-b79b-a2b25e224594}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\Parsing\JSON">
|
||||
<UniqueIdentifier>{8e4d71c0-00fb-4508-9498-d73ec0762ea7}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\Parsing\JSON">
|
||||
<UniqueIdentifier>{ace79183-f13f-4f5f-905f-2d5c7b80391d}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="ZLog.cpp">
|
||||
<Filter>Source Files\IO</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZXMLReader.cpp">
|
||||
<Filter>Source Files\Parsing\XML</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZXMLWriter.cpp">
|
||||
<Filter>Source Files\Parsing\XML</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZConcurrency.cpp">
|
||||
<Filter>Source Files\Concurrency</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZEvent.cpp">
|
||||
<Filter>Source Files\Concurrency</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZMutex.cpp">
|
||||
<Filter>Source Files\Concurrency</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZReadWriteLock.cpp">
|
||||
<Filter>Source Files\Concurrency</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZSemaphore.cpp">
|
||||
<Filter>Source Files\Concurrency</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZTaskStream.cpp">
|
||||
<Filter>Source Files\Concurrency</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZThread.cpp">
|
||||
<Filter>Source Files\Concurrency</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZAlloc.cpp">
|
||||
<Filter>Source Files\Memory</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZName.cpp">
|
||||
<Filter>Source Files\Name</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZIniReader.cpp">
|
||||
<Filter>Source Files\Parsing\Ini</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZIniWriter.cpp">
|
||||
<Filter>Source Files\Parsing\Ini</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZRandomGenerator.cpp">
|
||||
<Filter>Source Files\Random</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZSimplexNoise.cpp">
|
||||
<Filter>Source Files\Random</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZSimplexNoiseMap.cpp">
|
||||
<Filter>Source Files\Random</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZKVTree.cpp">
|
||||
<Filter>Source Files\Data Structures</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZRegistry.cpp">
|
||||
<Filter>Source Files\Data Structures</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZBinaryBufferReader.cpp">
|
||||
<Filter>Source Files\Parsing\Binary</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZBinaryFileReader.cpp">
|
||||
<Filter>Source Files\Parsing\Binary</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZAllocWindow.cpp">
|
||||
<Filter>Source Files\Memory</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZBinaryFileWriter.cpp">
|
||||
<Filter>Source Files\Parsing\Binary</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZJSONWriter.cpp">
|
||||
<Filter>Source Files\Parsing\JSON</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZJSONReader.cpp">
|
||||
<Filter>Source Files\Parsing\JSON</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZBinaryBufferWriter.cpp">
|
||||
<Filter>Source Files\Parsing\Binary</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\Include\ZUtil\ZAssert.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZUtil.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZUtilBuild.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZLog.hpp">
|
||||
<Filter>Header Files\IO</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZXMLReader.hpp">
|
||||
<Filter>Header Files\Parsing\XML</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZXMLWriter.hpp">
|
||||
<Filter>Header Files\Parsing\XML</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZConcurrency.hpp">
|
||||
<Filter>Header Files\Concurrency</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZEvent.hpp">
|
||||
<Filter>Header Files\Concurrency</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZMutex.hpp">
|
||||
<Filter>Header Files\Concurrency</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZReadWriteLock.hpp">
|
||||
<Filter>Header Files\Concurrency</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZSemaphore.hpp">
|
||||
<Filter>Header Files\Concurrency</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZTaskStream.hpp">
|
||||
<Filter>Header Files\Concurrency</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZThread.hpp">
|
||||
<Filter>Header Files\Concurrency</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZAlloc.hpp">
|
||||
<Filter>Header Files\Memory</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZReferenceCounter.hpp">
|
||||
<Filter>Header Files\Memory</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZSlabAllocator.hpp">
|
||||
<Filter>Header Files\Memory</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZSmartPointer.hpp">
|
||||
<Filter>Header Files\Memory</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZWeakPointer.hpp">
|
||||
<Filter>Header Files\Memory</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZBitmap.hpp">
|
||||
<Filter>Header Files\Images</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZIniReader.hpp">
|
||||
<Filter>Header Files\Parsing\Ini</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZIniWriter.hpp">
|
||||
<Filter>Header Files\Parsing\Ini</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZNoise.hpp">
|
||||
<Filter>Header Files\Random</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZNoiseMap.hpp">
|
||||
<Filter>Header Files\Random</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZRandomGenerator.hpp">
|
||||
<Filter>Header Files\Random</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZSimplexNoise.hpp">
|
||||
<Filter>Header Files\Random</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZSimplexNoiseMap.hpp">
|
||||
<Filter>Header Files\Random</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZName.hpp">
|
||||
<Filter>Header Files\Name</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZKVTree.hpp">
|
||||
<Filter>Header Files\Data Structures</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZRegistry.hpp">
|
||||
<Filter>Header Files\Data Structures</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZBinaryBufferReader.hpp">
|
||||
<Filter>Header Files\Parsing\Binary</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZBinaryFileReader.hpp">
|
||||
<Filter>Header Files\Parsing\Binary</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZBinaryReader.hpp">
|
||||
<Filter>Header Files\Parsing\Binary</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZAllocWindow.hpp">
|
||||
<Filter>Header Files\Memory</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZBinaryWriter.hpp">
|
||||
<Filter>Header Files\Parsing\Binary</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZBinaryFileWriter.hpp">
|
||||
<Filter>Header Files\Parsing\Binary</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZJSONReader.hpp">
|
||||
<Filter>Header Files\Parsing\JSON</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZJSONWriter.hpp">
|
||||
<Filter>Header Files\Parsing\JSON</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\ZUtil\ZBinaryBufferWriter.hpp">
|
||||
<Filter>Header Files\Parsing\Binary</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
109
ZUtil/ZXMLReader.cpp
Normal file
109
ZUtil/ZXMLReader.cpp
Normal file
@@ -0,0 +1,109 @@
|
||||
#include <ZUtil/ZXMLReader.hpp>
|
||||
|
||||
//We don't want rapidxml throwing exceptions at us, let the parse handler do it
|
||||
#ifndef RAPIDXML_NO_EXCEPTIONS
|
||||
#define RAPIDXML_NO_EXCEPTIONS
|
||||
#endif
|
||||
|
||||
#include <rapidxml/rapidxml.hpp>
|
||||
|
||||
namespace rapidxml
|
||||
{
|
||||
void parse_error_handler(const char *what, void *where, void *arg)
|
||||
{
|
||||
URFP(where); //For now
|
||||
|
||||
ZString& errorMsg = *((ZString*)arg);
|
||||
|
||||
errorMsg = "ZXMLReader (rapidxml): ";
|
||||
ZStringAlgo::Append(errorMsg, what);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
bool ZXMLReader::Read(const char* data, size_t length)
|
||||
{
|
||||
Tree.Clear();
|
||||
|
||||
ZString name; // current node name
|
||||
ZString value; // current node value
|
||||
|
||||
// make a copy of xml data so we can use rapidxml in destructive mode
|
||||
ZString xmlData(data, length);
|
||||
rapidxml::xml_document<> doc(&ErrorMessage); // character type is 'char'
|
||||
|
||||
// 0 is default flags (error message will be set by handler)
|
||||
if (!doc.parse<rapidxml::parse_no_data_nodes>(xmlData.Data())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// iterate the nodes and set data in the tree
|
||||
rapidxml::xml_node<> *node = doc.first_node();
|
||||
ZKVTree::Iterator itr = Tree.Begin();
|
||||
|
||||
while (node != NULL) {
|
||||
name = node->name();
|
||||
value = node->value();
|
||||
|
||||
// xml often contains a lot of control characters within the 'body'
|
||||
ZStringAlgo::Trim(value);
|
||||
|
||||
// add this node under the root node
|
||||
ZKVTree::Iterator node_itr = Tree.Add(itr, name, value);
|
||||
|
||||
// iterate the attributes and set data in the kvtree
|
||||
for (rapidxml::xml_attribute<> *attr = node->first_attribute(); attr != NULL; attr = attr->next_attribute()) {
|
||||
ZString attr_name = attr->name();
|
||||
ZString attr_value = attr->value();
|
||||
|
||||
// add this node under the newly created node
|
||||
Tree.Add(node_itr, attr_name, attr_value);
|
||||
}
|
||||
|
||||
// iterate to next node (check child first, then sibling, then go up to parent)
|
||||
if (node->first_node() != NULL) {
|
||||
node = node->first_node();
|
||||
itr = node_itr;
|
||||
} else if (node->next_sibling() != NULL) {
|
||||
node = node->next_sibling();
|
||||
} else {
|
||||
|
||||
// go to next element (up and out)
|
||||
while (node->parent() != NULL) {
|
||||
node = node->parent();
|
||||
|
||||
if (node->type() != rapidxml::node_document) {
|
||||
itr = itr.Parent();
|
||||
} else break;
|
||||
|
||||
if (node->next_sibling() != NULL) {
|
||||
node = node->next_sibling();
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// if we end up NULL or back at the 'document' node by going to parent, then we are done.
|
||||
if (node == NULL || node->parent() == NULL || node->type() == rapidxml::node_document) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
const ZString& ZXMLReader::GetErrorString()
|
||||
{
|
||||
return ErrorMessage;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZXMLReader::GetKVTree(ZKVTree& _kvtree)
|
||||
{
|
||||
_kvtree = Tree;
|
||||
}
|
||||
96
ZUtil/ZXMLWriter.cpp
Normal file
96
ZUtil/ZXMLWriter.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
#include <ZUtil/ZXMLWriter.hpp>
|
||||
|
||||
#define APPEND_NEWLINE \
|
||||
if (_useNewlines) { \
|
||||
ZStringAlgo::Append(_output, LINE_TERMINATOR); \
|
||||
} \
|
||||
|
||||
const ZString& ZXMLWriter::GetErrorString()
|
||||
{
|
||||
return ErrorMessage;
|
||||
}
|
||||
|
||||
bool ZXMLWriter::writeAttributes(ZString& _output, const ZKVTree::Iterator& _itr)
|
||||
{
|
||||
bool found_sub = false; // indicates we have sub-elements
|
||||
|
||||
for (size_t i = 0; i < _itr.GetChildCount(); i++) {
|
||||
|
||||
const ZKVTree::Iterator itr = _itr.ChildItr(i);
|
||||
|
||||
if (itr.GetChildCount() > 0) { // attributes have no children
|
||||
found_sub = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
const ZString& name = itr.GetName(); // attrib name
|
||||
const ZString& val = itr.GetValue(); // attrib value
|
||||
|
||||
_output.PushBack(' '); // start with a space
|
||||
ZStringAlgo::Append(_output, name); // append attribute name
|
||||
_output.PushBack('='); // equals
|
||||
_output.PushBack('\"'); // escaped quote
|
||||
ZStringAlgo::Append(_output, val); // attribute value
|
||||
_output.PushBack('\"'); // escaped quote
|
||||
}
|
||||
|
||||
return found_sub;
|
||||
}
|
||||
|
||||
bool ZXMLWriter::writeElements(ZString& _output, bool _useNewlines, const ZKVTree::Iterator& _itr)
|
||||
{
|
||||
if (_itr.GetChildCount() == 0) { // indicates an attribute
|
||||
return true;
|
||||
}
|
||||
|
||||
const ZString& name = _itr.GetName(); // element name
|
||||
const ZString& val = _itr.GetValue(); // element value
|
||||
|
||||
_output.PushBack('<'); // open tag
|
||||
ZStringAlgo::Append(_output, name); // element name
|
||||
|
||||
bool found_sub = writeAttributes(_output, _itr); // write all attributes
|
||||
|
||||
if (val.Empty() && !found_sub) { // close the tag, no body, no sub-elements
|
||||
_output.PushBack('/');
|
||||
_output.PushBack('>');
|
||||
|
||||
APPEND_NEWLINE;
|
||||
|
||||
} else { // keep tag open for sub-elements and body
|
||||
_output.PushBack('>');
|
||||
|
||||
APPEND_NEWLINE;
|
||||
|
||||
// write all sub-elements (this does nothing on an attribute)
|
||||
for (size_t i = 0; i < _itr.GetChildCount(); i++) {
|
||||
writeElements(_output, _useNewlines, _itr.ChildItr(i));
|
||||
}
|
||||
|
||||
if (!val.Empty()) {
|
||||
ZStringAlgo::Append(_output, val); // write element body
|
||||
APPEND_NEWLINE;
|
||||
}
|
||||
|
||||
_output.PushBack('<'); // closing tag begin
|
||||
_output.PushBack('/');
|
||||
ZStringAlgo::Append(_output, name);
|
||||
_output.PushBack('>'); // closing tag end
|
||||
|
||||
APPEND_NEWLINE;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ZXMLWriter::Write( const ZKVTree& _input, ZString& _output, bool _useNewlines )
|
||||
{
|
||||
ZKVTree::Iterator itr = _input.Begin();
|
||||
|
||||
if (itr == _input.End()) {
|
||||
ErrorMessage = "ZXMLWriter: key value tree has no data!";
|
||||
return false;
|
||||
}
|
||||
|
||||
return writeElements(_output, _useNewlines, itr);
|
||||
}
|
||||
BIN
ZUtil/obj/x86-64/release/ZAlloc.o
Normal file
BIN
ZUtil/obj/x86-64/release/ZAlloc.o
Normal file
Binary file not shown.
BIN
ZUtil/obj/x86-64/release/ZAllocWindow.o
Normal file
BIN
ZUtil/obj/x86-64/release/ZAllocWindow.o
Normal file
Binary file not shown.
BIN
ZUtil/obj/x86-64/release/ZBinaryBufferReader.o
Normal file
BIN
ZUtil/obj/x86-64/release/ZBinaryBufferReader.o
Normal file
Binary file not shown.
BIN
ZUtil/obj/x86-64/release/ZBinaryBufferWriter.o
Normal file
BIN
ZUtil/obj/x86-64/release/ZBinaryBufferWriter.o
Normal file
Binary file not shown.
BIN
ZUtil/obj/x86-64/release/ZBinaryFileReader.o
Normal file
BIN
ZUtil/obj/x86-64/release/ZBinaryFileReader.o
Normal file
Binary file not shown.
BIN
ZUtil/obj/x86-64/release/ZBinaryFileWriter.o
Normal file
BIN
ZUtil/obj/x86-64/release/ZBinaryFileWriter.o
Normal file
Binary file not shown.
BIN
ZUtil/obj/x86-64/release/ZConcurrency.o
Normal file
BIN
ZUtil/obj/x86-64/release/ZConcurrency.o
Normal file
Binary file not shown.
BIN
ZUtil/obj/x86-64/release/ZEvent.o
Normal file
BIN
ZUtil/obj/x86-64/release/ZEvent.o
Normal file
Binary file not shown.
BIN
ZUtil/obj/x86-64/release/ZIniReader.o
Normal file
BIN
ZUtil/obj/x86-64/release/ZIniReader.o
Normal file
Binary file not shown.
BIN
ZUtil/obj/x86-64/release/ZIniWriter.o
Normal file
BIN
ZUtil/obj/x86-64/release/ZIniWriter.o
Normal file
Binary file not shown.
BIN
ZUtil/obj/x86-64/release/ZJSONReader.o
Normal file
BIN
ZUtil/obj/x86-64/release/ZJSONReader.o
Normal file
Binary file not shown.
BIN
ZUtil/obj/x86-64/release/ZJSONWriter.o
Normal file
BIN
ZUtil/obj/x86-64/release/ZJSONWriter.o
Normal file
Binary file not shown.
BIN
ZUtil/obj/x86-64/release/ZKVTree.o
Normal file
BIN
ZUtil/obj/x86-64/release/ZKVTree.o
Normal file
Binary file not shown.
BIN
ZUtil/obj/x86-64/release/ZLog.o
Normal file
BIN
ZUtil/obj/x86-64/release/ZLog.o
Normal file
Binary file not shown.
BIN
ZUtil/obj/x86-64/release/ZMutex.o
Normal file
BIN
ZUtil/obj/x86-64/release/ZMutex.o
Normal file
Binary file not shown.
BIN
ZUtil/obj/x86-64/release/ZName.o
Normal file
BIN
ZUtil/obj/x86-64/release/ZName.o
Normal file
Binary file not shown.
BIN
ZUtil/obj/x86-64/release/ZRandomGenerator.o
Normal file
BIN
ZUtil/obj/x86-64/release/ZRandomGenerator.o
Normal file
Binary file not shown.
BIN
ZUtil/obj/x86-64/release/ZReadWriteLock.o
Normal file
BIN
ZUtil/obj/x86-64/release/ZReadWriteLock.o
Normal file
Binary file not shown.
BIN
ZUtil/obj/x86-64/release/ZRegistry.o
Normal file
BIN
ZUtil/obj/x86-64/release/ZRegistry.o
Normal file
Binary file not shown.
BIN
ZUtil/obj/x86-64/release/ZSemaphore.o
Normal file
BIN
ZUtil/obj/x86-64/release/ZSemaphore.o
Normal file
Binary file not shown.
BIN
ZUtil/obj/x86-64/release/ZSimplexNoise.o
Normal file
BIN
ZUtil/obj/x86-64/release/ZSimplexNoise.o
Normal file
Binary file not shown.
BIN
ZUtil/obj/x86-64/release/ZSimplexNoiseMap.o
Normal file
BIN
ZUtil/obj/x86-64/release/ZSimplexNoiseMap.o
Normal file
Binary file not shown.
BIN
ZUtil/obj/x86-64/release/ZTaskStream.o
Normal file
BIN
ZUtil/obj/x86-64/release/ZTaskStream.o
Normal file
Binary file not shown.
BIN
ZUtil/obj/x86-64/release/ZThread.o
Normal file
BIN
ZUtil/obj/x86-64/release/ZThread.o
Normal file
Binary file not shown.
BIN
ZUtil/obj/x86-64/release/ZXMLReader.o
Normal file
BIN
ZUtil/obj/x86-64/release/ZXMLReader.o
Normal file
Binary file not shown.
BIN
ZUtil/obj/x86-64/release/ZXMLWriter.o
Normal file
BIN
ZUtil/obj/x86-64/release/ZXMLWriter.o
Normal file
Binary file not shown.
Reference in New Issue
Block a user