Initial commit

This commit is contained in:
2026-04-03 00:22:39 -05:00
commit eca1e8c458
945 changed files with 218160 additions and 0 deletions

54
ZUtil/Makefile Normal file
View 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
View 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
View 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;
}

View 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;
}
/*************************************************************************/

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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);
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.