Initial commit
This commit is contained in:
161
Include/ZUtil/ZAlloc.hpp
Normal file
161
Include/ZUtil/ZAlloc.hpp
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
ZAlloc.hpp (created 9/12/10)
|
||||
Author : James Russell
|
||||
|
||||
Purpose :
|
||||
|
||||
Memory allocation library and memory allocation tracker for ZEngine. If ZALLOC_EXTRA_SPAMMY is defined,
|
||||
then allocations will log a message to stderr when allocation occurs indicating how much.
|
||||
|
||||
License:
|
||||
|
||||
TODO
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _ZALLOC_H
|
||||
#define _ZALLOC_H
|
||||
|
||||
#include <ZUtil/ZUtilBuild.hpp>
|
||||
|
||||
#include <new>
|
||||
|
||||
//The compiler really should be smart enough to include size_t in the global
|
||||
//namespace by default. But, on some Linux configurations, it will drop
|
||||
//it in std. Explicitly including this doesn't hurt anything.
|
||||
#include <stddef.h>
|
||||
|
||||
#if ZALLOC_CHECK_ALLOC
|
||||
|
||||
//Memory Checkpoint Struct
|
||||
struct ZMemState
|
||||
{
|
||||
int Checkpoint; //Checkpoint Number
|
||||
};
|
||||
|
||||
//Allocation Info Struct
|
||||
struct ZAllocInfo
|
||||
{
|
||||
static int CurrentAllocCount; //Current number of unfreed allocations
|
||||
static int CurrentCheckpoint; //Static current checkpoint tracker
|
||||
|
||||
ZAllocInfo* Next; //Next Info Node
|
||||
uintptr_t Address; //Address assigned
|
||||
size_t Size; //Size of the allocation
|
||||
int Line; //Line Number
|
||||
int Checkpoint; //Checkpoint Integer
|
||||
char File[128]; //File String
|
||||
};
|
||||
|
||||
//Adds a tracking node for an allocation
|
||||
extern void ZAllocAddTrack(uintptr_t _address, size_t _size, const char *_file, int _line, int _checkpoint);
|
||||
|
||||
//Removes a tracking node for an allocation
|
||||
extern void ZAllocRemoveTrack(uintptr_t _address);
|
||||
|
||||
//Dumps unfreed memory string containing a list of memory leaks
|
||||
extern void ZAllocDumpUnfreed(ZMemState *_state);
|
||||
|
||||
//Debug Placement Operator New
|
||||
extern void* operator new(size_t _size, const char *_file, int _line, int _checkpoint) throw();
|
||||
extern void* operator new[](size_t _size, const char *_file, int _line, int _checkpoint) throw();
|
||||
|
||||
//Debug Placement Delete
|
||||
extern void operator delete(void *_ptr, const char* _file, int _line, int _checkpoint);
|
||||
extern void operator delete[](void *_ptr, const char* _file, int _line, int _checkpoint);
|
||||
|
||||
//Our arguments to znew
|
||||
#define ZNEW_ARGS (__FILE__, __LINE__, ZAllocInfo::CurrentCheckpoint)
|
||||
|
||||
//Macros for declaring a memory 'checkpoint' and
|
||||
//dumping memory leaks to stderr
|
||||
#define ZALLOC_MEM_CHECKPOINT(stateP) stateP->Checkpoint = AtomicAddReturn((volatile int*)&ZAllocInfo::CurrentCheckpoint, 1)
|
||||
#define ZALLOC_MEM_DUMP_LEAKS(stateP) ZAllocDumpUnfreed(stateP)
|
||||
|
||||
#else //!ZALLOC_CHECK_ALLOC
|
||||
|
||||
#define ZNEW_ARGS (std::nothrow)
|
||||
|
||||
#define ZALLOC_MEM_CHECKPOINT(stateP)
|
||||
#define ZALLOC_MEM_DUMP_LEAKS(stateP)
|
||||
|
||||
#endif //ZALLOC_CHECK_ALLOC
|
||||
|
||||
/* Some definitions we need for znew_static */
|
||||
|
||||
//This is used to indicate a static allocation (basically a type flag)
|
||||
struct znew_static_t { };
|
||||
|
||||
//Our actual static allocation overrides
|
||||
extern void* operator new(size_t _size, znew_static_t _staticAlloc);
|
||||
extern void* operator new[](size_t _size, znew_static_t _staticAlloc);
|
||||
|
||||
/* Some Memory Management Macros */
|
||||
|
||||
//znew loves you!
|
||||
#define znew new ZNEW_ARGS //Allocate with params
|
||||
#define znew_notrack new (std::nothrow) //Allocate without tracking
|
||||
#define znew_static new (znew_static_t()) //Allocate, but register for delete onexit
|
||||
#define zdelete delete //Delete
|
||||
|
||||
#define zalloc(_type, _size) ZAlloc::Alloc<_type>(_size) //Allocates an array (block of memory) using the ZAlloc allocation library
|
||||
#define zfree(_data) ZAlloc::Free(_data) //Frees an array (block of memory) using the ZAlloc allocation library
|
||||
|
||||
#define MemCopy(_type, _dest, _src, _count) memcpy(_dest, _src, _count * sizeof(_type))
|
||||
#define MemCopyFloat(_dest, _src, _count) memcpy(_dest, _src, _count * sizeof(float))
|
||||
#define MemCopyInt(_dest, _src, _count) memcpy(_dest, _src, _count * sizeof(int))
|
||||
#define MemCopyChar(_dest, _src, _count) memcpy(_dest, _src, _count * sizeof(char))
|
||||
|
||||
#define MemMove(_type, _dest, _src, _count) memmove(_dest, _src, _count * sizeof(_type))
|
||||
#define MemMoveFloat(_dest, _src, _count) memmove(_dest, _src, _count * sizeof(float))
|
||||
#define MemMoveInt(_dest, _src, _count) memmove(_dest, _src, _count * sizeof(int))
|
||||
#define MemMoveChar(_dest, _src, _count) memmove(_dest, _src, _count * sizeof(char))
|
||||
|
||||
#define MemSet(_type, _dest, _val, _count) memset(_dest, _val, _count * sizeof(_type))
|
||||
#define MemSetFloat(_dest, _val, _count) memset(_dest, _val, _count * sizeof(float))
|
||||
#define MemSetInt(_dest, _val, _count) memset(_dest, _val, _count * sizeof(int))
|
||||
#define MemSetChar(_dest, _val, _count) memset(_dest, _val, _count * sizeof(char))
|
||||
|
||||
class ZAlloc
|
||||
{
|
||||
public:
|
||||
/*
|
||||
static public Alloc
|
||||
Allocation function. Gives back an allocated array of at least _size in length.
|
||||
|
||||
@param _size - the size of the block of type T
|
||||
|
||||
@return (T*) - an array of T of at least _size in length
|
||||
*/
|
||||
template <class T>
|
||||
static T* Alloc(size_t _size);
|
||||
|
||||
/*
|
||||
public static Free
|
||||
|
||||
Free function.
|
||||
|
||||
@param _data - an array allocated through the use of Alloc
|
||||
|
||||
@return (void)
|
||||
*/
|
||||
template <class T>
|
||||
static void Free(T *_data);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
T* ZAlloc::Alloc(size_t _size)
|
||||
{
|
||||
return new (std::nothrow) T[_size];
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void ZAlloc::Free(T *_data)
|
||||
{
|
||||
delete [] _data;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
205
Include/ZUtil/ZAllocWindow.hpp
Normal file
205
Include/ZUtil/ZAllocWindow.hpp
Normal file
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
ZAllocWindow.hpp
|
||||
Author: James Russell <jcrussell@762studios.com>
|
||||
Created: 3/7/2013
|
||||
|
||||
Purpose:
|
||||
|
||||
Buffer used to maintain a sliding window of allocations in a buffer. Primary
|
||||
use case is sliding packet windows, but could also be used for other forms
|
||||
of data.
|
||||
|
||||
Able to allocate raw memory blocks or perform in-place construction using
|
||||
default constructors. Destructor calls can be omitted or performed.
|
||||
|
||||
License:
|
||||
|
||||
TODO
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _ZALLOCWINDOW_HPP
|
||||
#define _ZALLOCWINDOW_HPP
|
||||
|
||||
#include <new> // for placement new
|
||||
|
||||
#include <ZUtil/ZUtilBuild.hpp>
|
||||
|
||||
/*
|
||||
Allocation window class. Operating on a contiguous array of backing memory,
|
||||
this will allocate chunks of that memory, increasing the window until the
|
||||
entire block would be used.
|
||||
|
||||
When deallocations are performed, no memory is actually freed from the buffer
|
||||
unless the earliest allocation is deallocated, which will shrink the window.
|
||||
|
||||
As an example, consider the following:
|
||||
|
||||
buffer.Allocate(A);
|
||||
buffer.Allocate(B);
|
||||
buffer.Allocate(C);
|
||||
buffer.Allocate(D);
|
||||
|
||||
A large enough buffer would return four pointers and would have the following
|
||||
layout (a = allocated flag, d = deallocated flag, f = free memory):
|
||||
|
||||
+-----------------------------------+
|
||||
| a | A | a | B | a | C | a | D | f |
|
||||
+-----------------------------------+
|
||||
^ ^
|
||||
buffer begin buffer end
|
||||
|
||||
buffer.Deallocate(B);
|
||||
|
||||
+-----------------------------------+
|
||||
| a | A | d | B | a | C | a | D | f |
|
||||
+-----------------------------------+
|
||||
^ ^
|
||||
buffer begin buffer end
|
||||
|
||||
buffer.Deallocate(A);
|
||||
|
||||
+-----------------------------------+
|
||||
| f | f | f | f | a | C | a | D | f |
|
||||
+-----------------------------------+
|
||||
^ ^
|
||||
buffer begin buffer end
|
||||
|
||||
Notice that when B was deallocated, no space was actually made available
|
||||
in the buffer until A was deallocated. If a further attempt had been made
|
||||
to allocate data, it would have returned NULL, indicating that the allocation
|
||||
window was full. The only way to free data at that point would have been to
|
||||
deallocate the earliest allocation (A, in this case).
|
||||
|
||||
The allocation window will automatically handle wrapping around when the end
|
||||
of the buffer is reached.
|
||||
*/
|
||||
class ZAllocWindow
|
||||
{
|
||||
public:
|
||||
// c'tor
|
||||
ZAllocWindow();
|
||||
|
||||
// parameterized c'tor
|
||||
ZAllocWindow(size_t _buffersize);
|
||||
|
||||
// d'tor
|
||||
~ZAllocWindow();
|
||||
|
||||
/*
|
||||
void* ZAllocWindow::Allocate
|
||||
|
||||
Allocates a contiguous block of memory from the buffer. If this
|
||||
would wrap around such that the previously allocated data (that has
|
||||
not been deallocated) would be overwritten, then it returns NULL.
|
||||
|
||||
An additional 8 bytes are used per allocation from the buffer for
|
||||
allocation metadata.
|
||||
|
||||
This will always return a word aligned pointer.
|
||||
|
||||
The template version will default construct an object of type T.
|
||||
|
||||
@param _size - number of bytes to allocate
|
||||
@return (void*) - the allocated block of memory (NULL if not possible)
|
||||
*/
|
||||
void* Allocate(size_t _size);
|
||||
template <typename T> T* Allocate()
|
||||
{ T* obj = (T*)Allocate(sizeof(T)); return (obj != NULL ? new (obj) T() : NULL); }
|
||||
|
||||
/*
|
||||
void ZAllocWindow::Deallocate
|
||||
|
||||
Deallocates a previously allocated block of memory from the binary buffer. Since
|
||||
allocation is done in a sliding window, this only moves frees up memory if this
|
||||
is the oldest currently allocated block of data. Any other data that is deallocated
|
||||
will be marked as freed to be made available when the oldest allocated block is freed.
|
||||
|
||||
The template version will call the destructor for the object.
|
||||
|
||||
@param _data - the data to be deallocated
|
||||
@param _obj - the object to deallocate (destructor is called)
|
||||
@return (void)
|
||||
*/
|
||||
void Deallocate(void* _data);
|
||||
template <typename T> void Deallocate(T* _obj)
|
||||
{ _obj->~T(); Deallocate((void*)_obj); }
|
||||
|
||||
/*
|
||||
size_t ZAllocWindow::GetAllocCount
|
||||
|
||||
Gets the current number of allocations out on this allocation window.
|
||||
|
||||
@return (size_t) - the number of allocations
|
||||
*/
|
||||
size_t GetAllocCount() const
|
||||
{ return NumAllocs; }
|
||||
|
||||
/*
|
||||
void ZAllocWindow::Reset
|
||||
|
||||
Completely resets the allocation window, completely invalidating all
|
||||
existing allocations.
|
||||
|
||||
@return (void)
|
||||
*/
|
||||
void Reset();
|
||||
|
||||
/*
|
||||
bool ZAllocWindow::Resize
|
||||
|
||||
Attempts to resize the buffer. This will fail if data is currently allocated in
|
||||
the buffer.
|
||||
|
||||
The template version will set the buffer to enough room for N objects of type T.
|
||||
|
||||
@param _newsize - the new desired size of the buffer
|
||||
@param _count - the number of objects of type T to resize the buffer for
|
||||
@return (bool) - true if able to resize, false otherwise
|
||||
*/
|
||||
bool Resize(size_t _newsize);
|
||||
template <typename T> bool Resize(size_t _count)
|
||||
{ return Resize((sizeof(T) + 8) * _count); }
|
||||
|
||||
/*
|
||||
void ZAllocWindow::SetBuffer
|
||||
|
||||
Sets the backing buffer for this binary buffer. This will fail if data is currently
|
||||
allocated in the buffer. If NULL, will release ownership of any previous set buffer
|
||||
and allocate a new one equal to the current size.
|
||||
|
||||
Does not assume ownership of the buffer - will not delete it upon destruction of this
|
||||
buffer.
|
||||
|
||||
@param _buffer - the buffer to use as backing
|
||||
@param _buffersize - the size of the buffer being set
|
||||
@return (bool) - true if able to use, false otherwise
|
||||
*/
|
||||
bool SetBuffer(void* _buffer, size_t _buffersize);
|
||||
|
||||
/*
|
||||
size_t ZAllocWindow::Size
|
||||
|
||||
Returns the current size of the buffer.
|
||||
|
||||
@return (size_t) - size (in bytes) of the buffer
|
||||
*/
|
||||
size_t Size() const
|
||||
{ return BufferSize; }
|
||||
|
||||
private:
|
||||
DISABLE_COPY_AND_ASSIGN(ZAllocWindow);
|
||||
|
||||
void* Buffer; // The allocated buffer
|
||||
void* Begin; // The (moving) front pointer of the buffer
|
||||
void* End; // The (moving) back pointer of the buffer
|
||||
|
||||
size_t BufferSize; // The current allocated size of the buffer
|
||||
bool bOwnsBuffer; // Flag indicating we own the buffer (and should free when done)
|
||||
size_t NumAllocs; // The number of allocations we've done
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
53
Include/ZUtil/ZAssert.hpp
Normal file
53
Include/ZUtil/ZAssert.hpp
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
ZAssert.hpp
|
||||
Author : Chris Ertel
|
||||
|
||||
Purpose : Asserts for debugging and error checking purposes.
|
||||
|
||||
Changelog
|
||||
8/16/2010 - creation (crertel)
|
||||
12/4/2011 - Updated to use libsst-os asserts (jcrussell)
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _ZASSERT_H
|
||||
#define _ZASSERT_H
|
||||
|
||||
#include <SST/SST_Assert.h>
|
||||
|
||||
/*****************/
|
||||
/* Assert Macros */
|
||||
/*****************/
|
||||
|
||||
//ZASSERT_RUNTIME macro, which will raise an error with debug output if the condition is not true after logging the message
|
||||
#define ZASSERT_RUNTIME(_condition, _message) SST_OS_RuntimeAssert(_condition, _message)
|
||||
|
||||
//ZASSERT_RUNTIME_FAIL macro, which will raise an error with debug output
|
||||
#define ZASSERT_RUNTIME_FAIL(_message) SST_OS_RuntimeError(_message)
|
||||
|
||||
#if ZASSERT_ENABLE
|
||||
|
||||
//ZASSERT macro, which will trigger a breakpoint if the condition is not met
|
||||
#define ZASSERT(_condition, _message) SST_OS_DebugAssert(_condition, _message)
|
||||
|
||||
//ZASSERT_FAIL macro, which triggers a breakpoint
|
||||
#define ZASSERT_FAIL(_message) SST_OS_DebugError(_message)
|
||||
|
||||
#else /* ZASSERT is disabled */
|
||||
#define ZASSERT(_condition, _message)
|
||||
#define ZASSERT_FAIL(_message)
|
||||
#endif //ZASSERT_ENABLE
|
||||
|
||||
#if ZASSERT_UTIL_ENABLE
|
||||
|
||||
//ZASSERT_UTIL macro, which will trigger a breakpoint if the condition is not met
|
||||
//ZASSERT_UTIL is meant to be used within the ZUtil project for internal assertion debugging
|
||||
//ZASSERT should be used when the error condition can be caused by user actions
|
||||
#define ZASSERT_UTIL(_condition, _message) SST_OS_DebugAssert(_condition, _message)
|
||||
|
||||
#else /* ZASSERT_UTIL is disabled */
|
||||
#define ZASSERT_UTIL(_condition, _message) ((void)0)
|
||||
#endif //ZASSERT_UTIL_ENABLE
|
||||
|
||||
#endif
|
||||
87
Include/ZUtil/ZBinaryBufferReader.hpp
Normal file
87
Include/ZUtil/ZBinaryBufferReader.hpp
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
ZBinaryBufferReader.hpp
|
||||
Author: Chris Ertel <crertel@762studios.com>, Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 3/6/2013
|
||||
|
||||
Purpose:
|
||||
|
||||
Reads a binary stream from memory.
|
||||
|
||||
License:
|
||||
|
||||
TODO
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _ZBINARYBUFFERREADER_HPP
|
||||
#define _ZBINARYBUFFERREADER_HPP
|
||||
|
||||
#include <stddef.h>
|
||||
#include <pstdint.h>
|
||||
|
||||
#include <ZUtil/ZBinaryReader.hpp>
|
||||
|
||||
class ZBinaryBufferReader : public ZBinaryReader
|
||||
{
|
||||
private:
|
||||
const char* Data;
|
||||
size_t Size;
|
||||
size_t Offset;
|
||||
|
||||
//This is typed to char* so pointer arithmetic can occur
|
||||
const char* GetPosition() const { return &Data[Offset]; }
|
||||
public:
|
||||
ZBinaryBufferReader(const void* _data, size_t _size, SST_ByteOrder bo)
|
||||
: ZBinaryReader(bo), Data( (const char*) _data), Size(_size), Offset(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//Subclass implementation
|
||||
uint8_t ReadU8();
|
||||
|
||||
//Subclass implementation
|
||||
uint16_t ReadU16();
|
||||
|
||||
//Subclass implementation
|
||||
uint32_t ReadU32();
|
||||
|
||||
//Subclass implementation
|
||||
uint64_t ReadU64();
|
||||
|
||||
//Subclass implementation
|
||||
void ReadU8Array(uint8_t* ptr, size_t count);
|
||||
|
||||
//Subclass implementation
|
||||
void ReadU16Array(uint16_t* ptr, size_t count);
|
||||
|
||||
//Subclass implementation
|
||||
void ReadU32Array(uint32_t* ptr, size_t count);
|
||||
|
||||
//Subclass implementation
|
||||
void ReadU64Array(uint64_t* ptr, size_t count);
|
||||
|
||||
//Subclass implementation
|
||||
size_t GetLength() const { return Size; }
|
||||
|
||||
//Subclass implementation
|
||||
size_t GetOffset() const { return Offset; }
|
||||
|
||||
//Subclass implementation
|
||||
void SeekTo(size_t offset) { Offset = offset; }
|
||||
|
||||
//New to ZBinaryBufferReader. Returns the current address that would be read by the next ReadXxx() call.
|
||||
//Since 'const void*' is the constructor type, this returns 'const void*' as well. See [private] GetPosition().
|
||||
const void* GetBufferReadAddress() const { return (const void*)GetPosition(); }
|
||||
|
||||
//New to ZBinaryBufferReader. Returns the original buffer address
|
||||
const void* GetBufferBaseAddress() const { return (const void*)Data; }
|
||||
|
||||
//New to ZBinaryBufferReader. Reads a pointer
|
||||
void* ReadPointer();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
78
Include/ZUtil/ZBinaryBufferWriter.hpp
Normal file
78
Include/ZUtil/ZBinaryBufferWriter.hpp
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
ZBinaryBufferWriter.hpp
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 6/05/2013
|
||||
|
||||
Purpose:
|
||||
|
||||
Writes a binary stream to memory
|
||||
|
||||
License:
|
||||
|
||||
TODO
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _ZBINARYBUFFERWRITER_HPP
|
||||
#define _ZBINARYBUFFERWRITER_HPP
|
||||
|
||||
#include <ZUtil/ZBinaryWriter.hpp>
|
||||
|
||||
class ZBinaryBufferWriter : public ZBinaryWriter
|
||||
{
|
||||
public:
|
||||
ZBinaryBufferWriter(void* data, size_t _size, SST_ByteOrder bo) :
|
||||
ZBinaryWriter(bo), Data((uint8_t*)data), Size(_size), Offset(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//Subclass implementation
|
||||
void WriteU8(uint8_t v);
|
||||
|
||||
//Subclass implementation
|
||||
void WriteU16(uint16_t v);
|
||||
|
||||
//Subclass implementation
|
||||
void WriteU32(uint32_t v);
|
||||
|
||||
//Subclass implementation
|
||||
void WriteU64(uint64_t v);
|
||||
|
||||
//Subclass implementation
|
||||
void WriteU8Array(const uint8_t* v, size_t count);
|
||||
|
||||
//Subclass implementation
|
||||
void WriteU16Array(const uint16_t* v, size_t count);
|
||||
|
||||
//Subclass implementation
|
||||
void WriteU32Array(const uint32_t* v, size_t count);
|
||||
|
||||
//Subclass implementation
|
||||
void WriteU64Array(const uint64_t* v, size_t count);
|
||||
|
||||
//Subclass implementation
|
||||
size_t GetOffset() const { return Offset; }
|
||||
|
||||
//Subclass implementation
|
||||
void SeekTo(size_t offset) { Offset = offset; }
|
||||
|
||||
//Specific to ZBinaryBufferWriter, returns next write address
|
||||
const void* GetBufferWriteAddress() const { return &Data[Offset]; }
|
||||
|
||||
//Specific to ZBinaryBufferWriter, returns base address
|
||||
void* GetBufferBaseAddress() const { return Data; }
|
||||
|
||||
//Specific to ZBinaryBufferWriter, writes a pointer
|
||||
void WritePointer(void* pointer);
|
||||
|
||||
private:
|
||||
uint8_t* Data;
|
||||
size_t Size; //TODO: no safe ops ?
|
||||
size_t Offset;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
72
Include/ZUtil/ZBinaryFileReader.hpp
Normal file
72
Include/ZUtil/ZBinaryFileReader.hpp
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
ZBinaryFileReader.hpp
|
||||
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
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _ZBINARYFILEREADER_HPP
|
||||
#define _ZBINARYFILEREADER_HPP
|
||||
|
||||
#include <SST/SST_File.h>
|
||||
#include <ZUtil/ZBinaryReader.hpp>
|
||||
|
||||
class ZBinaryFileReader : public ZBinaryReader
|
||||
{
|
||||
private:
|
||||
SST_File fp;
|
||||
size_t Size;
|
||||
size_t Offset;
|
||||
|
||||
public:
|
||||
ZBinaryFileReader(SST_File handle, SST_ByteOrder bo);
|
||||
|
||||
//Subclass implementation
|
||||
uint8_t ReadU8();
|
||||
|
||||
//Subclass implementation
|
||||
uint16_t ReadU16();
|
||||
|
||||
//Subclass implementation
|
||||
uint32_t ReadU32();
|
||||
|
||||
//Subclass implementation
|
||||
uint64_t ReadU64();
|
||||
|
||||
//Subclass implementation
|
||||
void ReadU8Array(uint8_t* ptr, size_t count);
|
||||
|
||||
//Subclass implementation
|
||||
void ReadU16Array(uint16_t* ptr, size_t count);
|
||||
|
||||
//Subclass implementation
|
||||
void ReadU32Array(uint32_t* ptr, size_t count);
|
||||
|
||||
//Subclass implementation
|
||||
void ReadU64Array(uint64_t* ptr, size_t count);
|
||||
|
||||
//Subclass implementation
|
||||
size_t GetLength() const { return Size; }
|
||||
|
||||
//Subclass implementation
|
||||
size_t GetOffset() const { return Offset; }
|
||||
|
||||
//Subclass implementation
|
||||
void SeekTo(size_t offset);
|
||||
|
||||
//Unique to ZBinaryFileReader
|
||||
SST_File GetFileHandle() { return fp; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
68
Include/ZUtil/ZBinaryFileWriter.hpp
Normal file
68
Include/ZUtil/ZBinaryFileWriter.hpp
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
ZBinaryFileWriter.hpp
|
||||
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
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _ZBINARYFILEWRITER_HPP
|
||||
#define _ZBINARYFILEWRITER_HPP
|
||||
|
||||
#include <SST/SST_File.h>
|
||||
#include <ZUtil/ZBinaryWriter.hpp>
|
||||
|
||||
class ZBinaryFileWriter : public ZBinaryWriter
|
||||
{
|
||||
public:
|
||||
ZBinaryFileWriter(SST_File handle, SST_ByteOrder bo);
|
||||
|
||||
//Subclass implementation
|
||||
void WriteU8(uint8_t v);
|
||||
|
||||
//Subclass implementation
|
||||
void WriteU16(uint16_t v);
|
||||
|
||||
//Subclass implementation
|
||||
void WriteU32(uint32_t v);
|
||||
|
||||
//Subclass implementation
|
||||
void WriteU64(uint64_t v);
|
||||
|
||||
//Subclass implementation
|
||||
void WriteU8Array(const uint8_t* v, size_t count);
|
||||
|
||||
//Subclass implementation
|
||||
void WriteU16Array(const uint16_t* v, size_t count);
|
||||
|
||||
//Subclass implementation
|
||||
void WriteU32Array(const uint32_t* v, size_t count);
|
||||
|
||||
//Subclass implementation
|
||||
void WriteU64Array(const uint64_t* v, size_t count);
|
||||
|
||||
//Subclass implementation
|
||||
size_t GetOffset() const { return Offset; }
|
||||
|
||||
//Subclass implementation
|
||||
void SeekTo(size_t offset);
|
||||
|
||||
//Unique to ZBinaryFileWriter
|
||||
SST_File GetFileHandle() { return fp; }
|
||||
|
||||
private:
|
||||
SST_File fp;
|
||||
size_t Offset;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
749
Include/ZUtil/ZBinaryReader.hpp
Normal file
749
Include/ZUtil/ZBinaryReader.hpp
Normal file
@@ -0,0 +1,749 @@
|
||||
/*
|
||||
ZBinaryReader.hpp
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com
|
||||
Created: 3/6/2013
|
||||
|
||||
Purpose:
|
||||
|
||||
Binary stream reader interface
|
||||
|
||||
License:
|
||||
|
||||
TODO
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _ZBINARYREADER_HPP
|
||||
#define _ZBINARYREADER_HPP
|
||||
|
||||
|
||||
#include <pstdint.h>
|
||||
#include <SST/SST_Endian.h>
|
||||
|
||||
class ZBinaryReader
|
||||
{
|
||||
public:
|
||||
ZBinaryReader(SST_ByteOrder streamOrder) :
|
||||
streamByteOrder(streamOrder)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//SINGLE ELEMENT READ
|
||||
/*
|
||||
virtual public ZBinaryReader::ReadU8
|
||||
|
||||
Reads a single unsigned 8-bit value from the stream.
|
||||
No validation is performed.
|
||||
|
||||
@return (uint8_t) - value read from the stream
|
||||
*/
|
||||
virtual uint8_t ReadU8() = 0;
|
||||
|
||||
/*
|
||||
virtual public ZBinaryReader::ReadU16
|
||||
|
||||
Reads a single unsigned 16-bit value from the stream.
|
||||
No validation is performed.
|
||||
|
||||
@return (uint16_t) - value read from the stream
|
||||
*/
|
||||
virtual uint16_t ReadU16() = 0;
|
||||
|
||||
/*
|
||||
virtual public ZBinaryReader::ReadU32
|
||||
|
||||
Reads a single unsigned 32-bit value from the stream.
|
||||
No validation is performed.
|
||||
|
||||
@return (uint32_t) - value read from the stream
|
||||
*/
|
||||
virtual uint32_t ReadU32() = 0;
|
||||
|
||||
/*
|
||||
virtual public ZBinaryReader::ReadU64
|
||||
|
||||
Reads a single unsigned 64-bit value from the stream.
|
||||
No validation is performed.
|
||||
|
||||
@return (uint64_t) - value read from the stream
|
||||
*/
|
||||
virtual uint64_t ReadU64() = 0;
|
||||
|
||||
/*
|
||||
public ZBinaryReader::ReadF32
|
||||
|
||||
Reads a single 32-bit floating point value from the stream.
|
||||
No validation is performed.
|
||||
|
||||
@return (float) - value read from the stream
|
||||
*/
|
||||
float ReadF32() { return cast_i2f(ReadU32()); }
|
||||
|
||||
/*
|
||||
public ZBinaryReader::ReadF64
|
||||
|
||||
Reads a single 64-bit floating point value from the stream.
|
||||
No validation is performed.
|
||||
|
||||
@return (double) - value read from the stream
|
||||
*/
|
||||
double ReadF64() { return cast_i2d(ReadU64()); }
|
||||
|
||||
|
||||
//=====================================================================
|
||||
//ARRAY READ
|
||||
//=====================================================================
|
||||
|
||||
/*
|
||||
virtual public ZBinaryReader::ReadU8Array
|
||||
|
||||
Reads an array of 8-bit unsigned values from the stream.
|
||||
No validation is performed.
|
||||
|
||||
@param ptr - The base of the array
|
||||
@param count - Number of elements to read
|
||||
@return (void)
|
||||
*/
|
||||
virtual void ReadU8Array(uint8_t* ptr, size_t count) = 0;
|
||||
|
||||
/*
|
||||
virtual public ZBinaryReader::ReadU16Array
|
||||
|
||||
Reads an array of 16-bit unsigned values from the stream.
|
||||
No validation is performed.
|
||||
|
||||
@param ptr - The base of the array
|
||||
@param count - Number of elements to read
|
||||
@return (void)
|
||||
*/
|
||||
virtual void ReadU16Array(uint16_t* ptr, size_t count) = 0;
|
||||
|
||||
/*
|
||||
virtual public ZBinaryReader::ReadU32Array
|
||||
|
||||
Reads an array of 32-bit unsigned values from the stream.
|
||||
No validation is performed.
|
||||
|
||||
@param ptr - The base of the array
|
||||
@param count - Number of elements to read
|
||||
@return (void)
|
||||
*/
|
||||
virtual void ReadU32Array(uint32_t* ptr, size_t count) = 0;
|
||||
|
||||
/*
|
||||
virtual public ZBinaryReader::ReadU64Array
|
||||
|
||||
Reads an array of 64-bit unsigned values from the stream.
|
||||
No validation is performed.
|
||||
|
||||
@param ptr - The base of the array
|
||||
@param count - Number of elements to read
|
||||
@return (void)
|
||||
*/
|
||||
virtual void ReadU64Array(uint64_t* ptr, size_t count) = 0;
|
||||
|
||||
/*
|
||||
public ZBinaryReader::ReadF32Array
|
||||
|
||||
Reads an array of 32-bit floating point values from the stream.
|
||||
No validation is performed.
|
||||
|
||||
@param ptr - The base of the array
|
||||
@param count - Number of elements to read
|
||||
@return (void)
|
||||
*/
|
||||
void ReadF32Array(float* ptr, size_t count) { ReadU32Array((uint32_t*)ptr, count); }
|
||||
|
||||
/*
|
||||
public ZBinaryReader::ReadF64Array
|
||||
|
||||
Reads an array of 64-bit floating point values from the stream.
|
||||
No validation is performed.
|
||||
|
||||
@param ptr - The base of the array
|
||||
@param count - Number of elements to read
|
||||
@return (void)
|
||||
*/
|
||||
void ReadF64Array(double* ptr, size_t count) { ReadU64Array((uint64_t*)ptr, count); }
|
||||
|
||||
//=====================================================================
|
||||
//STREAM SEEKING / POSITIONING
|
||||
//=====================================================================
|
||||
|
||||
/*
|
||||
virtual public ZBinaryReader::GetLength
|
||||
|
||||
Gets the total length of the stream in bytes.
|
||||
|
||||
@return (size_t) - The total length of the stream
|
||||
*/
|
||||
virtual size_t GetLength() const = 0;
|
||||
|
||||
/*
|
||||
virtual public ZBinaryReader::GetOffset
|
||||
|
||||
Gets the current (zero-based) offset into the stream from which the next read will
|
||||
be performed.
|
||||
|
||||
@return (size_t) - The offset.
|
||||
*/
|
||||
virtual size_t GetOffset() const = 0;
|
||||
|
||||
/*
|
||||
public ZBinaryReader::SeekForward
|
||||
|
||||
Advances the offset into the stream by the given number of bytes.
|
||||
No validation is performed.
|
||||
|
||||
@param amount - The amount of seek forward by.
|
||||
@return (void)
|
||||
*/
|
||||
void SeekForward(size_t amount) { SeekTo(GetOffset() + amount); }
|
||||
|
||||
/*
|
||||
public ZBinaryReader::SeekBackward
|
||||
|
||||
Rewinds the offset into the stream by the given number of bytes.
|
||||
No validation is performed.
|
||||
|
||||
@param amount - The amount of seek backward by.
|
||||
@return (void)
|
||||
*/
|
||||
void SeekBackward(size_t amount) { SeekTo(GetOffset() - amount); }
|
||||
|
||||
/*
|
||||
virtual public ZBinaryReader::SeekTo
|
||||
|
||||
Directly sets the offset into the stream from which reads will occur.
|
||||
No validation is performed.
|
||||
|
||||
@param offset - The new offset
|
||||
@return (void)
|
||||
*/
|
||||
virtual void SeekTo(size_t offset) = 0;
|
||||
|
||||
/*
|
||||
public ZBinaryReader::Rewind
|
||||
|
||||
Sets the offset to the start of the stream
|
||||
|
||||
@param offset - The new offset
|
||||
@return (void)
|
||||
*/
|
||||
void Rewind() { SeekTo(0); }
|
||||
|
||||
/*
|
||||
public ZBinaryReader::CanRead
|
||||
|
||||
Checks if the given number of bytes can be read
|
||||
|
||||
@param bytes - The number of bytes that wish to be read
|
||||
@return (void)
|
||||
*/
|
||||
bool CanRead(size_t bytes) const { return (GetLength() - GetOffset() >= bytes); }
|
||||
|
||||
//=====================================================================
|
||||
//SAFE SEEK FUNCTIONS
|
||||
//=====================================================================
|
||||
/*
|
||||
public ZBinaryReader::SafeSeekForward
|
||||
|
||||
Attempts to advance the offset into the stream by the given number of bytes. If
|
||||
this would produce an out-of-bounds result, then false is returned and the offset
|
||||
is not adjusted, otherwise, the offset is adjusted and true is returned.
|
||||
|
||||
@param amount - The amount to seek forward by
|
||||
@return (bool) - True if the seek operation succeeded, false if the value was invalid
|
||||
*/
|
||||
bool SafeSeekForward(size_t amount)
|
||||
{
|
||||
bool ok = (GetLength() - GetOffset() > amount); //i.e. length > offset + amount
|
||||
if(ok)
|
||||
SeekTo(GetOffset() + amount);
|
||||
return ok;
|
||||
}
|
||||
|
||||
/*
|
||||
public ZBinaryReader::SafeSeekBackward
|
||||
|
||||
Attempts to rewind the offset into the stream by the given number of bytes. If
|
||||
this would produce an out-of-bounds result, then false is returned and the offset
|
||||
is not adjusted, otherwise, the offset is adjusted and true is returned.
|
||||
|
||||
@param amount - The amount to seek backward by
|
||||
@return (bool) - True if the seek operation succeeded, false if the value was invalid
|
||||
*/
|
||||
bool SafeSeekBackward(size_t amount)
|
||||
{
|
||||
bool ok = (GetOffset() >= amount); //i.e. offset - amount >= 0
|
||||
if(ok)
|
||||
SeekTo(GetOffset() - amount);
|
||||
return ok;
|
||||
}
|
||||
|
||||
/*
|
||||
public ZBinaryReader::SafeSeekTo
|
||||
|
||||
Attempts to set the offset into the stream directly. If the new offset is
|
||||
out-of-bounds, then false is returned and the offset is not adjusted,
|
||||
otherwise, the offset is adjusted and true is returned.
|
||||
|
||||
@return (bool) - True if the seek operation succeeded, false if the value was invalid
|
||||
*/
|
||||
bool SafeSeekTo(size_t offset)
|
||||
{
|
||||
bool ok = (offset < GetLength());
|
||||
if(ok) SeekTo(offset);
|
||||
return ok;
|
||||
}
|
||||
|
||||
//=====================================================================
|
||||
//SAFE READ FUNCTIONS
|
||||
//=====================================================================
|
||||
/*
|
||||
public ZBinaryReader::SafeReadU8
|
||||
|
||||
Attempt to reads a single unsigned 8-bit value from the stream. If this would
|
||||
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
|
||||
the value is read and stored at *ptr and true is returned.
|
||||
No validation is performed.
|
||||
|
||||
@param ptr - The address to store the read value at
|
||||
@return (bool) - If the value was successfully read
|
||||
*/
|
||||
bool SafeReadU8(uint8_t* ptr)
|
||||
{
|
||||
bool ok = CanRead(sizeof(uint8_t));
|
||||
if(ok) *ptr = ReadU8();
|
||||
return ok;
|
||||
}
|
||||
|
||||
/*
|
||||
public ZBinaryReader::SafeReadU16
|
||||
|
||||
Attempt to reads a single unsigned 16-bit value from the stream. If this would
|
||||
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
|
||||
the value is read and stored at *ptr and true is returned.
|
||||
No validation is performed.
|
||||
|
||||
@param ptr - The address to store the read value at
|
||||
@return (bool) - If the value was successfully read
|
||||
*/
|
||||
bool SafeReadU16(uint16_t* ptr)
|
||||
{
|
||||
bool ok = CanRead(sizeof(uint16_t));
|
||||
if(ok) *ptr = ReadU16();
|
||||
return ok;
|
||||
}
|
||||
|
||||
/*
|
||||
public ZBinaryReader::SafeReadU32
|
||||
|
||||
Attempt to reads a single unsigned 32-bit value from the stream. If this would
|
||||
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
|
||||
the value is read and stored at *ptr and true is returned.
|
||||
No validation is performed.
|
||||
|
||||
@param ptr - The address to store the read value at
|
||||
@return (bool) - If the value was successfully read
|
||||
*/
|
||||
bool SafeReadU32(uint32_t* ptr)
|
||||
{
|
||||
bool ok = CanRead(sizeof(uint32_t));
|
||||
if(ok) *ptr = ReadU32();
|
||||
return ok;
|
||||
}
|
||||
|
||||
/*
|
||||
public ZBinaryReader::SafeReadU64
|
||||
|
||||
Attempt to reads a single unsigned 64-bit value from the stream. If this would
|
||||
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
|
||||
the value is read and stored at *ptr and true is returned.
|
||||
No validation is performed.
|
||||
|
||||
@param ptr - The address to store the read value at
|
||||
@return (bool) - If the value was successfully read
|
||||
*/
|
||||
bool SafeReadU64(uint64_t* ptr)
|
||||
{
|
||||
bool ok = CanRead(sizeof(uint64_t));
|
||||
if(ok) *ptr = ReadU64();
|
||||
return ok;
|
||||
}
|
||||
|
||||
/*
|
||||
public ZBinaryReader::SafeReadF32
|
||||
|
||||
Attempt to reads a single 32-bit floating point value from the stream. If this would
|
||||
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
|
||||
the value is read and stored at *ptr and true is returned.
|
||||
No validation is performed.
|
||||
|
||||
@param ptr - The address to store the read value at
|
||||
@return (bool) - If the value was successfully read
|
||||
*/
|
||||
bool SafeReadF32(float* ptr)
|
||||
{
|
||||
bool ok = CanRead(sizeof(float));
|
||||
if(ok) *ptr = ReadF32();
|
||||
return ok;
|
||||
}
|
||||
|
||||
/*
|
||||
public ZBinaryReader::SafeReadF64
|
||||
|
||||
Attempt to reads a single 64-bit floating point value from the stream. If this would
|
||||
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
|
||||
the value is read and stored at *ptr and true is returned.
|
||||
No validation is performed.
|
||||
|
||||
@param ptr - The address to store the read value at
|
||||
@return (bool) - If the value was successfully read
|
||||
*/
|
||||
bool SafeReadF64(double* ptr)
|
||||
{
|
||||
bool ok = CanRead(sizeof(double));
|
||||
if(ok) *ptr = ReadF64();
|
||||
return ok;
|
||||
}
|
||||
|
||||
/*
|
||||
public ZBinaryReader::SafeReadU8Array
|
||||
|
||||
Attempt to reads an array of unsigned 8-bit values from the stream. If this would
|
||||
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
|
||||
the values are read and stored at *ptr and true is returned.
|
||||
No validation is performed.
|
||||
|
||||
@param ptr - The address to store the values
|
||||
@param count - The number of values to read
|
||||
@return (bool) - If the array was successfully read
|
||||
*/
|
||||
bool SafeReadU8Array(uint8_t* ptr, size_t count)
|
||||
{
|
||||
bool ok = CanRead(count);
|
||||
if(ok) ReadU8Array(ptr, count);
|
||||
return ok;
|
||||
}
|
||||
|
||||
/*
|
||||
public ZBinaryReader::SafeReadU16Array
|
||||
|
||||
Attempt to reads an array of unsigned 16-bit values from the stream. If this would
|
||||
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
|
||||
the values are read and stored at *ptr and true is returned.
|
||||
No validation is performed.
|
||||
|
||||
@param ptr - The address to store the values
|
||||
@param count - The number of values to read
|
||||
@return (bool) - If the array was successfully read
|
||||
*/
|
||||
bool SafeReadU16Array(uint16_t* ptr, size_t count)
|
||||
{
|
||||
bool ok = (SIZE_MAX / count > sizeof(uint16_t)); //i.e. SIZE_MAX > count * size
|
||||
ok = ok && CanRead(count * sizeof(uint16_t));
|
||||
if(ok) ReadU16Array(ptr, count);
|
||||
return ok;
|
||||
}
|
||||
|
||||
/*
|
||||
public ZBinaryReader::SafeReadU32Array
|
||||
|
||||
Attempt to reads an array of unsigned 32-bit values from the stream. If this would
|
||||
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
|
||||
the values are read and stored at *ptr and true is returned.
|
||||
No validation is performed.
|
||||
|
||||
@param ptr - The address to store the values
|
||||
@param count - The number of values to read
|
||||
@return (bool) - If the array was successfully read
|
||||
*/
|
||||
bool SafeReadU32Array(uint32_t* ptr, size_t count)
|
||||
{
|
||||
bool ok = (SIZE_MAX / count > sizeof(uint32_t)); //i.e. SIZE_MAX > count * size
|
||||
ok = ok && CanRead(count * sizeof(uint32_t));
|
||||
if(ok) ReadU32Array(ptr, count);
|
||||
return ok;
|
||||
}
|
||||
|
||||
/*
|
||||
public ZBinaryReader::SafeReadU64Array
|
||||
|
||||
Attempt to reads an array of unsigned 64-bit values from the stream. If this would
|
||||
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
|
||||
the values are read and stored at *ptr and true is returned.
|
||||
No validation is performed.
|
||||
|
||||
@param ptr - The address to store the values
|
||||
@param count - The number of values to read
|
||||
@return (bool) - If the array was successfully read
|
||||
*/
|
||||
bool SafeReadU64Array(uint64_t* ptr, size_t count)
|
||||
{
|
||||
bool ok = (SIZE_MAX / count > sizeof(uint64_t)); //i.e. SIZE_MAX > count * size
|
||||
ok = ok && CanRead(count * sizeof(uint64_t));
|
||||
if(ok) ReadU64Array(ptr, count);
|
||||
return ok;
|
||||
}
|
||||
|
||||
/*
|
||||
public ZBinaryReader::SafeReadF32Array
|
||||
|
||||
Attempt to reads an array of 32-bit floating point values from the stream. If this would
|
||||
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
|
||||
the values are read and stored at *ptr and true is returned.
|
||||
No validation is performed.
|
||||
|
||||
@param ptr - The address to store the values
|
||||
@param count - The number of values to read
|
||||
@return (bool) - If the array was successfully read
|
||||
*/
|
||||
bool SafeReadF32Array(float* ptr, size_t count) { return SafeReadU32Array((uint32_t*)ptr, count); }
|
||||
|
||||
/*
|
||||
public ZBinaryReader::SafeReadF64Array
|
||||
|
||||
Attempt to reads an array of 64-bit floating point values from the stream. If this would
|
||||
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
|
||||
the values are read and stored at *ptr and true is returned.
|
||||
No validation is performed.
|
||||
|
||||
@param ptr - The address to store the values
|
||||
@param count - The number of values to read
|
||||
@return (bool) - If the array was successfully read
|
||||
*/
|
||||
bool SafeReadF64Array(double* ptr, size_t count) { return SafeReadU64Array((uint64_t*)ptr, count); }
|
||||
|
||||
//=====================================================================
|
||||
//TYPED ALIASES
|
||||
//=====================================================================
|
||||
/*
|
||||
public ZBinaryReader::ReadI8
|
||||
|
||||
Reads a single signed 8-bit value from the stream.
|
||||
No validation is performed.
|
||||
|
||||
@return (int8_t) - value read from the stream
|
||||
*/
|
||||
int8_t ReadI8() { return (int8_t)ReadU8(); }
|
||||
|
||||
/*
|
||||
public ZBinaryReader::ReadI16
|
||||
|
||||
Reads a single signed 16-bit value from the stream.
|
||||
No validation is performed.
|
||||
|
||||
@return (int16_t) - value read from the stream
|
||||
*/
|
||||
int16_t ReadI16() { return (int16_t)ReadU16(); }
|
||||
|
||||
/*
|
||||
public ZBinaryReader::ReadI32
|
||||
|
||||
Reads a single signed 32-bit value from the stream.
|
||||
No validation is performed.
|
||||
|
||||
@return (int32_t) - value read from the stream
|
||||
*/
|
||||
int32_t ReadI32() { return (int32_t)ReadU32(); }
|
||||
|
||||
/*
|
||||
public ZBinaryReader::ReadI64
|
||||
|
||||
Reads a single signed 64-bit value from the stream.
|
||||
No validation is performed.
|
||||
|
||||
@return (int64_t) - value read from the stream
|
||||
*/
|
||||
int64_t ReadI64() { return (int64_t)ReadU64(); }
|
||||
|
||||
/*
|
||||
public ZBinaryReader::ReadI8Array
|
||||
|
||||
Reads an array of 8-bit signed values from the stream.
|
||||
No validation is performed.
|
||||
|
||||
@param ptr - The base of the array
|
||||
@param count - Number of elements to read
|
||||
@return (void)
|
||||
*/
|
||||
void ReadI8Array(int8_t* ptr, size_t count) { return ReadU8Array((uint8_t*)ptr, count); }
|
||||
|
||||
/*
|
||||
public ZBinaryReader::ReadI16Array
|
||||
|
||||
Reads an array of 16-bit signed values from the stream.
|
||||
No validation is performed.
|
||||
|
||||
@param ptr - The base of the array
|
||||
@param count - Number of elements to read
|
||||
@return (void)
|
||||
*/
|
||||
void ReadI16Array(int16_t* ptr, size_t count) { return ReadU16Array((uint16_t*)ptr, count); }
|
||||
|
||||
/*
|
||||
public ZBinaryReader::ReadI32Array
|
||||
|
||||
Reads an array of 32-bit signed values from the stream.
|
||||
No validation is performed.
|
||||
|
||||
@param ptr - The base of the array
|
||||
@param count - Number of elements to read
|
||||
@return (void)
|
||||
*/
|
||||
void ReadI32Array(int32_t* ptr, size_t count) { return ReadU32Array((uint32_t*)ptr, count); }
|
||||
|
||||
/*
|
||||
public ZBinaryReader::ReadI64Array
|
||||
|
||||
Reads an array of 64-bit signed values from the stream.
|
||||
No validation is performed.
|
||||
|
||||
@param ptr - The base of the array
|
||||
@param count - Number of elements to read
|
||||
@return (void)
|
||||
*/
|
||||
void ReadI64Array(int64_t* ptr, size_t count) { return ReadU64Array((uint64_t*)ptr, count); }
|
||||
|
||||
/*
|
||||
public ZBinaryReader::SafeReadI8
|
||||
|
||||
Attempt to reads a single signed 8-bit value from the stream. If this would
|
||||
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
|
||||
the value is read and stored at *ptr and true is returned.
|
||||
No validation is performed.
|
||||
|
||||
@param ptr - The address to store the read value at
|
||||
@return (bool) - If the value was successfully read
|
||||
*/
|
||||
bool SafeReadI8(int8_t* ptr) { return SafeReadU8((uint8_t*)ptr); }
|
||||
|
||||
/*
|
||||
public ZBinaryReader::SafeReadI16
|
||||
|
||||
Attempt to reads a single signed 16-bit value from the stream. If this would
|
||||
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
|
||||
the value is read and stored at *ptr and true is returned.
|
||||
No validation is performed.
|
||||
|
||||
@param ptr - The address to store the read value at
|
||||
@return (bool) - If the value was successfully read
|
||||
*/
|
||||
bool SafeReadI16(int16_t* ptr) { return SafeReadU16((uint16_t*)ptr); }
|
||||
|
||||
/*
|
||||
public ZBinaryReader::SafeReadI32
|
||||
|
||||
Attempt to reads a single signed 32-bit value from the stream. If this would
|
||||
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
|
||||
the value is read and stored at *ptr and true is returned.
|
||||
No validation is performed.
|
||||
|
||||
@param ptr - The address to store the read value at
|
||||
@return (bool) - If the value was successfully read
|
||||
*/
|
||||
bool SafeReadI32(int32_t* ptr) { return SafeReadU32((uint32_t*)ptr); }
|
||||
|
||||
/*
|
||||
public ZBinaryReader::SafeReadI64
|
||||
|
||||
Attempt to reads a single signed 64-bit value from the stream. If this would
|
||||
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
|
||||
the value is read and stored at *ptr and true is returned.
|
||||
No validation is performed.
|
||||
|
||||
@param ptr - The address to store the read value at
|
||||
@return (bool) - If the value was successfully read
|
||||
*/
|
||||
bool SafeReadI64(int64_t* ptr) { return SafeReadU64((uint64_t*)ptr); }
|
||||
|
||||
/*
|
||||
public ZBinaryReader::SafeReadI8Array
|
||||
|
||||
Attempt to reads an array of signed 8-bit values from the stream. If this would
|
||||
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
|
||||
the values are read and stored at *ptr and true is returned.
|
||||
No validation is performed.
|
||||
|
||||
@param ptr - The address to store the values
|
||||
@param count - The number of values to read
|
||||
@return (bool) - If the array was successfully read
|
||||
*/
|
||||
bool SafeReadI8Array(int8_t* ptr, size_t count) { return SafeReadU8Array((uint8_t*)ptr, count); }
|
||||
|
||||
/*
|
||||
public ZBinaryReader::SafeReadI16Array
|
||||
|
||||
Attempt to reads an array of signed 16-bit values from the stream. If this would
|
||||
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
|
||||
the values are read and stored at *ptr and true is returned.
|
||||
No validation is performed.
|
||||
|
||||
@param ptr - The address to store the values
|
||||
@param count - The number of values to read
|
||||
@return (bool) - If the array was successfully read
|
||||
*/
|
||||
bool SafeReadI16Array(int16_t* ptr, size_t count) { return SafeReadU16Array((uint16_t*)ptr, count); }
|
||||
|
||||
/*
|
||||
public ZBinaryReader::SafeReadI32Array
|
||||
|
||||
Attempt to reads an array of signed 32-bit values from the stream. If this would
|
||||
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
|
||||
the values are read and stored at *ptr and true is returned.
|
||||
No validation is performed.
|
||||
|
||||
@param ptr - The address to store the values
|
||||
@param count - The number of values to read
|
||||
@return (bool) - If the array was successfully read
|
||||
*/
|
||||
bool SafeReadI32Array(int32_t* ptr, size_t count) { return SafeReadU32Array((uint32_t*)ptr, count); }
|
||||
|
||||
/*
|
||||
public ZBinaryReader::SafeReadI64Array
|
||||
|
||||
Attempt to reads an array of signed 64-bit values from the stream. If this would
|
||||
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
|
||||
the values are read and stored at *ptr and true is returned.
|
||||
No validation is performed.
|
||||
|
||||
@param ptr - The address to store the values
|
||||
@param count - The number of values to read
|
||||
@return (bool) - If the array was successfully read
|
||||
*/
|
||||
bool SafeReadI64Array(int64_t* ptr, size_t count) { return SafeReadU64Array((uint64_t*)ptr, count); }
|
||||
|
||||
|
||||
//=====================================================================
|
||||
//GETTERS / SETTERS
|
||||
//=====================================================================
|
||||
/*
|
||||
public ZBinaryReader::GetStreamByteOrder
|
||||
|
||||
Gets the byte order in which the stream (source data) is read as.
|
||||
|
||||
@return (SST_ByteOrder) - The byte order
|
||||
*/
|
||||
SST_ByteOrder GetStreamByteOrder() const { return streamByteOrder; }
|
||||
|
||||
/*
|
||||
public ZBinaryReader::SetStreamByteOrder
|
||||
|
||||
Sets the byte order in which the stream (source data) is read as.
|
||||
|
||||
@param newOrder - The new byte order
|
||||
@return (void)
|
||||
*/
|
||||
void SetStreamByteOrder(SST_ByteOrder newOrder) { streamByteOrder = newOrder; }
|
||||
|
||||
private:
|
||||
SST_ByteOrder streamByteOrder; //The current byte order the stream is being read in.
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
279
Include/ZUtil/ZBinaryWriter.hpp
Normal file
279
Include/ZUtil/ZBinaryWriter.hpp
Normal file
@@ -0,0 +1,279 @@
|
||||
/*
|
||||
ZBinaryWriter.hpp
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 3/11/2013
|
||||
|
||||
Purpose:
|
||||
|
||||
Binary stream writer interface
|
||||
|
||||
License:
|
||||
|
||||
TODO
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _ZBINARYWRITER_HPP
|
||||
#define _ZBINARYWRITER_HPP
|
||||
|
||||
#include <SST/SST_Endian.h>
|
||||
#include <pstdint.h>
|
||||
|
||||
class ZBinaryWriter
|
||||
{
|
||||
|
||||
public:
|
||||
ZBinaryWriter(SST_ByteOrder streamOrder) :
|
||||
streamByteOrder(streamOrder)
|
||||
{
|
||||
}
|
||||
|
||||
//=====================================================================
|
||||
//SINGLE ELEMENT WRITE
|
||||
//=====================================================================
|
||||
virtual void WriteU8(uint8_t v) = 0;
|
||||
virtual void WriteU16(uint16_t v) = 0;
|
||||
virtual void WriteU32(uint32_t v) = 0;
|
||||
virtual void WriteU64(uint64_t v) = 0;
|
||||
void WriteF32(float v) { WriteU32(cast_f2i(v)); }
|
||||
void WriteF64(double v) { WriteU64(cast_d2i(v)); }
|
||||
|
||||
//=====================================================================
|
||||
//ARRAY WRITE
|
||||
//=====================================================================
|
||||
/*
|
||||
virtual public ZBinaryWriter::WriteU8Array
|
||||
|
||||
Writes an array of 8-bit unsigned values to the stream.
|
||||
|
||||
@param v - The base of the array
|
||||
@param count - Number of elements to write
|
||||
@return (void)
|
||||
*/
|
||||
virtual void WriteU8Array(const uint8_t* v, size_t count) = 0;
|
||||
|
||||
/*
|
||||
virtual public ZBinaryWriter::WriteU16Array
|
||||
|
||||
Writes an array of 16-bit unsigned values to the stream.
|
||||
|
||||
@param v - The base of the array
|
||||
@param count - Number of elements to write
|
||||
@return (void)
|
||||
*/
|
||||
virtual void WriteU16Array(const uint16_t* v, size_t count) = 0;
|
||||
|
||||
/*
|
||||
virtual public ZBinaryWriter::WriteU32Array
|
||||
|
||||
Writes an array of 32-bit unsigned values to the stream.
|
||||
|
||||
@param v - The base of the array
|
||||
@param count - Number of elements to write
|
||||
@return (void)
|
||||
*/
|
||||
virtual void WriteU32Array(const uint32_t* v, size_t count) = 0;
|
||||
|
||||
/*
|
||||
virtual public ZBinaryWriter::WriteU64Array
|
||||
|
||||
Writes an array of 64-bit unsigned values to the stream.
|
||||
|
||||
@param v - The base of the array
|
||||
@param count - Number of elements to write
|
||||
@return (void)
|
||||
*/
|
||||
virtual void WriteU64Array(const uint64_t* v, size_t count) = 0;
|
||||
|
||||
/*
|
||||
public ZBinaryWriter::WriteF32Array
|
||||
|
||||
Writes an array of 32-bit floating point values to the stream.
|
||||
|
||||
@param v - The base of the array
|
||||
@param count - Number of elements to write
|
||||
@return (void)
|
||||
*/
|
||||
void WriteF32Array(const float* v, size_t count) { WriteU32Array((uint32_t*)v, count); }
|
||||
|
||||
/*
|
||||
public ZBinaryWriter::WriteF64Array
|
||||
|
||||
Writes an array of 64-bit floating point values to the stream.
|
||||
|
||||
@param v - The base of the array
|
||||
@param count - Number of elements to write
|
||||
@return (void)
|
||||
*/
|
||||
void WriteF64Array(const double* v, size_t count) { WriteU64Array((uint64_t*)v, count); }
|
||||
|
||||
//=====================================================================
|
||||
//STREAM SEEKING / POSITIONING
|
||||
//=====================================================================
|
||||
/*
|
||||
virtual public ZBinaryReader::GetOffset
|
||||
|
||||
Gets the current (zero-based) offset into the stream from which the next read will
|
||||
be performed.
|
||||
|
||||
@return (size_t) - The offset.
|
||||
*/
|
||||
virtual size_t GetOffset() const = 0;
|
||||
|
||||
/*
|
||||
public ZBinaryReader::SeekForward
|
||||
|
||||
Advances the offset into the stream by the given number of bytes.
|
||||
No validation is performed.
|
||||
|
||||
@param amount - The amount of seek forward by.
|
||||
@return (void)
|
||||
*/
|
||||
void SeekForward(size_t amount) { SeekTo(GetOffset() + amount); }
|
||||
|
||||
/*
|
||||
public ZBinaryReader::SeekBackward
|
||||
|
||||
Rewinds the offset into the stream by the given number of bytes.
|
||||
No validation is performed.
|
||||
|
||||
@param amount - The amount of seek backward by.
|
||||
@return (void)
|
||||
*/
|
||||
void SeekBackward(size_t amount) { SeekTo(GetOffset() - amount); }
|
||||
|
||||
/*
|
||||
virtual public ZBinaryReader::SeekTo
|
||||
|
||||
Directly sets the offset into the stream from which reads will occur.
|
||||
No validation is performed.
|
||||
|
||||
@param offset - The new offset
|
||||
@return (void)
|
||||
*/
|
||||
virtual void SeekTo(size_t offset) = 0;
|
||||
|
||||
/*
|
||||
public ZBinaryReader::Rewind
|
||||
|
||||
Sets the offset to the start of the stream
|
||||
|
||||
@param offset - The new offset
|
||||
@return (void)
|
||||
*/
|
||||
void Rewind() { SeekTo(0); }
|
||||
|
||||
//=====================================================================
|
||||
//TYPED ALIASES
|
||||
//=====================================================================
|
||||
/*
|
||||
public ZBinaryWriter::WriteI8
|
||||
|
||||
Writes a single signed 8-bit value to the stream.
|
||||
|
||||
@param v - value read to write to the stream
|
||||
*/
|
||||
void WriteI8(int8_t v) { return WriteU8((uint8_t)v); }
|
||||
|
||||
/*
|
||||
public ZBinaryWriter::WriteI16
|
||||
|
||||
Writes a single signed 16-bit value to the stream.
|
||||
|
||||
@param v - value read to write to the stream
|
||||
*/
|
||||
void WriteI16(int16_t v) { return WriteU16((uint16_t)v); }
|
||||
|
||||
/*
|
||||
public ZBinaryWriter::WriteI32
|
||||
|
||||
Writes a single signed 32-bit value to the stream.
|
||||
|
||||
@param v - value read to write to the stream
|
||||
*/
|
||||
void WriteI32(int32_t v) { return WriteU32((uint32_t)v); }
|
||||
|
||||
/*
|
||||
public ZBinaryWriter::WriteI64
|
||||
|
||||
Writes a single signed 64-bit value to the stream.
|
||||
|
||||
@param v - value read to write to the stream
|
||||
*/
|
||||
void WriteI64(int64_t v) { return WriteU64((uint64_t)v); }
|
||||
|
||||
/*
|
||||
public ZBinaryWriter::WriteI8Array
|
||||
|
||||
Writes an array of 8-bit signed values to the stream.
|
||||
|
||||
@param v - The base of the array
|
||||
@param count - Number of elements to write
|
||||
@return (void)
|
||||
*/
|
||||
void WriteI8Array(const int8_t* v, size_t count) { return WriteU8Array((const uint8_t*)v, count); }
|
||||
|
||||
/*
|
||||
public ZBinaryWriter::WriteI16Array
|
||||
|
||||
Writes an array of 16-bit signed values to the stream.
|
||||
|
||||
@param v - The base of the array
|
||||
@param count - Number of elements to write
|
||||
@return (void)
|
||||
*/
|
||||
void WriteI16Array(const int16_t* v, size_t count) { return WriteU16Array((const uint16_t*)v, count); }
|
||||
|
||||
/*
|
||||
public ZBinaryWriter::WriteI32Array
|
||||
|
||||
Writes an array of 32-bit signed values to the stream.
|
||||
|
||||
@param v - The base of the array
|
||||
@param count - Number of elements to write
|
||||
@return (void)
|
||||
*/
|
||||
void WriteI32Array(const int32_t* v, size_t count) { return WriteU32Array((const uint32_t*)v, count); }
|
||||
|
||||
/*
|
||||
public ZBinaryWriter::WriteI64Array
|
||||
|
||||
Writes an array of 64-bit signed values to the stream.
|
||||
|
||||
@param v - The base of the array
|
||||
@param count - Number of elements to write
|
||||
@return (void)
|
||||
*/
|
||||
void WriteI64Array(const int64_t* v, size_t count) { return WriteU64Array((const uint64_t*)v, count); }
|
||||
|
||||
//=====================================================================
|
||||
//GETTERS / SETTERS
|
||||
//=====================================================================
|
||||
/*
|
||||
public ZBinaryReader::GetStreamByteOrder
|
||||
|
||||
Gets the byte order in which the stream (source data) is read as.
|
||||
|
||||
@return (SST_ByteOrder) - The byte order
|
||||
*/
|
||||
SST_ByteOrder GetStreamByteOrder() const { return streamByteOrder; }
|
||||
|
||||
/*
|
||||
public ZBinaryReader::SetStreamByteOrder
|
||||
|
||||
Sets the byte order in which the stream (source data) is read as.
|
||||
|
||||
@param newOrder - The new byte order
|
||||
@return (void)
|
||||
*/
|
||||
void SetStreamByteOrder(SST_ByteOrder newOrder) { streamByteOrder = newOrder; }
|
||||
|
||||
private:
|
||||
SST_ByteOrder streamByteOrder; //The current byte order the stream is being read in.
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
253
Include/ZUtil/ZBitmap.hpp
Normal file
253
Include/ZUtil/ZBitmap.hpp
Normal file
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
ZBitmap.hpp
|
||||
Author: Chris Ertel <crertel@762studios.com>,
|
||||
James Russell <jcrussell@762studios.com>
|
||||
Created: 12/09/2010
|
||||
|
||||
Purpose:
|
||||
|
||||
Bitmap metadata class. This is designed as a metadata package for the data, and
|
||||
does not assume ownership of the data. By passing around a ZBitmap instead of a raw
|
||||
pointer to byte data we always have metadata about the byte data on hand.
|
||||
|
||||
License:
|
||||
|
||||
TODO
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _ZBITMAP_H
|
||||
#define _ZBITMAP_H
|
||||
|
||||
#include <ZUtil/ZUtilBuild.hpp>
|
||||
|
||||
//This is the format of the bitmap, which describes color layout and bits per channel
|
||||
enum ZBitmapFormat
|
||||
{
|
||||
ZBF_UNKNOWN, //Unknown Format (usually uninitialized)
|
||||
|
||||
ZBF_R8, //8-bit Red Channel
|
||||
ZBF_R8I, //8-bit Signed Red Channel
|
||||
ZBF_R16, //16-bit Red Channel
|
||||
ZBF_R16I, //16-bit Signed Red Channel
|
||||
ZBF_R32, //32-bit Red Channel
|
||||
ZBF_R32I, //32-bit Signed Red Channel
|
||||
ZBF_R32F, //32-bit Floating Point Red Channel
|
||||
|
||||
ZBF_RG8, //8-bit Red, Green Channel
|
||||
ZBF_RG8I, //8-bit Signed Red, Green Channel
|
||||
ZBF_RG16, //16-bit Red, Green Channel
|
||||
ZBF_RG16I, //16-bit Signed Red, Green Channel
|
||||
ZBF_RG32, //32-bit Red, Green Channel
|
||||
ZBF_RG32I, //32-bit Signed Red, Green Channel
|
||||
ZBF_RG32F, //32-bit Floating Point Red, Green Channel
|
||||
|
||||
ZBF_RGB8, //8-bit Red, Green, Blue Channel
|
||||
ZBF_RGB8I, //8-bit Signed Red, Green, Blue Channel
|
||||
ZBF_RGB16, //16-bit Red, Green, Blue Channel
|
||||
ZBF_RGB16I, //16-bit Signed Red, Green, Blue Channel
|
||||
ZBF_RGB32, //32-bit Red, Green, Blue Channel
|
||||
ZBF_RGB32I, //32-bit Signed Red, Green, Blue Channel
|
||||
ZBF_RGB32F, //32-bit Floating Point Red, Green, Blue Channel
|
||||
|
||||
ZBF_RGBA8, //8-bit Red, Green, Blue, Alpha Channel
|
||||
ZBF_RGBA8I, //8-bit Signed Red, Green, Blue, Alpha Channel
|
||||
ZBF_RGBA16, //16-bit Red, Green, Blue, Alpha Channel
|
||||
ZBF_RGBA16I, //16-bit Signed Red, Green, Blue, Alpha Channel
|
||||
ZBF_RGBA32, //32-bit Red, Green, Blue, Alpha Channel
|
||||
ZBF_RGBA32I, //32-bit Signed Red, Green, Blue, Alpha Channel
|
||||
ZBF_RGBA32F, //32-bit Floating Point Red, Green, Blue, Alpha Channel
|
||||
|
||||
ZBF_BGR8, //8-bit Blue, Green, Red Channel
|
||||
ZBF_BGR8I, //8-bit Signed Blue, Green, Red Channel
|
||||
ZBF_BGR16, //16-bit Blue, Green, Red Channel
|
||||
ZBF_BGR16I, //16-bit Signed Blue, Green, Red Channel
|
||||
ZBF_BGR32, //32-bit Blue, Green, Red Channel
|
||||
ZBF_BGR32I, //32-bit Signed Blue, Green, Red Channel
|
||||
ZBF_BGR32F, //32-bit Floating Point Blue, Green, Red Channel
|
||||
|
||||
ZBF_BGRA8, //8-bit Blue, Green, Red, Alpha Channel
|
||||
ZBF_BGRA8I, //8-bit Signed Blue, Green, Red, Alpha Channel
|
||||
ZBF_BGRA16, //16-bit Blue, Green, Red, Alpha Channel
|
||||
ZBF_BGRA16I, //16-bit Signed Blue, Green, Red, Alpha Channel
|
||||
ZBF_BGRA32, //32-bit Blue, Green, Red, Alpha Channel
|
||||
ZBF_BGRA32I, //32-bit Signed Blue, Green, Red, Alpha Channel
|
||||
ZBF_BGRA32F, //32-bit Floating Point Blue, Green, Red, Alpha Channel
|
||||
|
||||
ZBF_DEPTH32, //32-bit Unsigned Depth
|
||||
|
||||
ZBCM_SIZE
|
||||
};
|
||||
|
||||
/*
|
||||
Bitmap data class.
|
||||
*/
|
||||
class ZBitmap
|
||||
{
|
||||
protected:
|
||||
ZBitmapFormat Format; //Format of the bitmap
|
||||
uint32_t Width; //Width of the bitmap
|
||||
uint32_t Height; //Height of the bitmap
|
||||
uint32_t Depth; //Depth of the bitmap
|
||||
void* Data; //Pointer to the bitmap data (can be NULL)
|
||||
|
||||
public:
|
||||
|
||||
/*
|
||||
Default Constructor
|
||||
*/
|
||||
ZBitmap()
|
||||
: Format(ZBF_UNKNOWN),
|
||||
Width(1),
|
||||
Height(1),
|
||||
Depth(1),
|
||||
Data(NULL)
|
||||
{ }
|
||||
|
||||
/*
|
||||
Constructor.
|
||||
|
||||
@param _format - the bitmap format
|
||||
@param _width - the width (pixels)
|
||||
@param _height - the height (pixels)
|
||||
*/
|
||||
ZBitmap(ZBitmapFormat _format, uint32_t _width, uint32_t _height)
|
||||
: Format(_format),
|
||||
Width(_width),
|
||||
Height(_height),
|
||||
Depth(1),
|
||||
Data(NULL)
|
||||
{ }
|
||||
|
||||
/*
|
||||
Constructor.
|
||||
|
||||
@param _format - the bitmap format
|
||||
@param _width - the width (pixels)
|
||||
@param _height - the height (pixels)
|
||||
@param _depth - the depth (pixels)
|
||||
*/
|
||||
ZBitmap(ZBitmapFormat _format, uint32_t _width, uint32_t _height, uint32_t _depth)
|
||||
: Format(_format),
|
||||
Width(_width),
|
||||
Height(_height),
|
||||
Depth(_depth),
|
||||
Data(NULL)
|
||||
{ }
|
||||
|
||||
/*
|
||||
Constructor.
|
||||
|
||||
@param _format - the bitmap format
|
||||
@param _width - the width (pixels)
|
||||
@param _height - the height (pixels)
|
||||
@param _depth - the depth (pixels)
|
||||
@param _data - the bitmap data
|
||||
*/
|
||||
ZBitmap(ZBitmapFormat _format, uint32_t _width, uint32_t _height, uint32_t _depth, void* _data)
|
||||
: Format(_format),
|
||||
Width(_width),
|
||||
Height(_height),
|
||||
Depth(_depth),
|
||||
Data(_data)
|
||||
{ }
|
||||
|
||||
//Determines (based off Format) the Bits Per Pixel of this bitmap
|
||||
size_t GetBPP() const
|
||||
{
|
||||
switch(Format)
|
||||
{
|
||||
case ZBF_R8: return 8;
|
||||
case ZBF_R8I: return 8;
|
||||
case ZBF_R16: return 16;
|
||||
case ZBF_R16I: return 16;
|
||||
case ZBF_R32: return 32;
|
||||
case ZBF_R32I: return 32;
|
||||
case ZBF_R32F: return 32;
|
||||
|
||||
case ZBF_RG8: return 16;
|
||||
case ZBF_RG8I: return 16;
|
||||
case ZBF_RG16: return 32;
|
||||
case ZBF_RG16I: return 32;
|
||||
case ZBF_RG32: return 64;
|
||||
case ZBF_RG32I: return 64;
|
||||
case ZBF_RG32F: return 64;
|
||||
|
||||
case ZBF_RGB8: return 24;
|
||||
case ZBF_RGB8I: return 24;
|
||||
case ZBF_RGB16: return 48;
|
||||
case ZBF_RGB16I: return 48;
|
||||
case ZBF_RGB32: return 96;
|
||||
case ZBF_RGB32I: return 96;
|
||||
case ZBF_RGB32F: return 96;
|
||||
|
||||
case ZBF_RGBA8: return 32;
|
||||
case ZBF_RGBA8I: return 32;
|
||||
case ZBF_RGBA16: return 64;
|
||||
case ZBF_RGBA16I: return 64;
|
||||
case ZBF_RGBA32: return 128;
|
||||
case ZBF_RGBA32I: return 128;
|
||||
case ZBF_RGBA32F: return 128;
|
||||
|
||||
case ZBF_BGR8: return 24;
|
||||
case ZBF_BGR8I: return 24;
|
||||
case ZBF_BGR16: return 48;
|
||||
case ZBF_BGR16I: return 48;
|
||||
case ZBF_BGR32: return 96;
|
||||
case ZBF_BGR32I: return 96;
|
||||
case ZBF_BGR32F: return 96;
|
||||
|
||||
case ZBF_BGRA8: return 32;
|
||||
case ZBF_BGRA8I: return 32;
|
||||
case ZBF_BGRA16: return 64;
|
||||
case ZBF_BGRA16I: return 64;
|
||||
case ZBF_BGRA32: return 128;
|
||||
case ZBF_BGRA32I: return 128;
|
||||
case ZBF_BGRA32F: return 128;
|
||||
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//Determines (based off of Width, Height, and Depth) the dimension of this bitmap (1, 2, or 3, 0 if inconsistent values)
|
||||
size_t GetDimension() const
|
||||
{
|
||||
if (Width > 1 && Height > 1 && Depth > 1)
|
||||
return 3;
|
||||
else if (Width > 1 && Height > 1 && Depth <= 1)
|
||||
return 2;
|
||||
else if (Width > 1 && Height <= 1 && Depth <= 1)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Computes and returns the size of the bitmap (in bytes)
|
||||
size_t GetSize() const
|
||||
{
|
||||
return (Width * Depth * Height * GetBPP()) / 8;
|
||||
}
|
||||
|
||||
//Getter and Settter for 'Format'
|
||||
inline ZBitmapFormat GetFormat() const { return this->Format; }
|
||||
inline void SetFormat(ZBitmapFormat _format) { this->Format = _format; }
|
||||
|
||||
//Getter and Setter for 'Width', in pixels
|
||||
inline uint32_t GetWidth() const { return this->Width; }
|
||||
inline void SetWidth(uint32_t _width) { this->Width = _width; }
|
||||
|
||||
//Getter and Setter for 'Height', in pixels
|
||||
inline uint32_t GetHeight() const { return this->Height; }
|
||||
inline void SetHeight(uint32_t _height) { this->Height = _height; }
|
||||
|
||||
//Getter and Setter for 'Depth', in pixels
|
||||
inline uint32_t GetDepth() const { return this->Depth; }
|
||||
inline void SetDepth(uint32_t _depth) { this->Depth = _depth; }
|
||||
|
||||
//Getter and Setter for 'Data'
|
||||
inline void* GetData() const { return this->Data; }
|
||||
inline void SetData(void* _data) { this->Data = _data; }
|
||||
};
|
||||
|
||||
#endif
|
||||
137
Include/ZUtil/ZConcurrency.hpp
Normal file
137
Include/ZUtil/ZConcurrency.hpp
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
ZConcurrency.hpp
|
||||
Author : James Russell, Patrick Baggett
|
||||
|
||||
Purpose : Provides a number of primitives for building concurrent programs. Each supported
|
||||
platform has a separate implementation.
|
||||
|
||||
Changelog
|
||||
1/24/11 - Creation (jcrussell)
|
||||
3/17/11 - Major change to support events, mutexes, thread local storage, and semaphores. (ptbaggett)
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _ZCONCURRENCY_HPP
|
||||
#define _ZCONCURRENCY_HPP
|
||||
|
||||
#include <ZUtil/ZUtilBuild.hpp>
|
||||
#include <ZUtil/ZSemaphore.hpp>
|
||||
#include <ZUtil/ZMutex.hpp>
|
||||
#include <ZUtil/ZEvent.hpp>
|
||||
#include <ZUtil/ZReadWriteLock.hpp>
|
||||
|
||||
//Used to indicate an indefinite wait
|
||||
#define ZWAIT_INFINITE (~((uint32_t)0))
|
||||
|
||||
//Typedef for a thread handle
|
||||
typedef void* ZThreadHandle;
|
||||
|
||||
/*
|
||||
ZEngine thread data, used as a context for threads. The fields here should not be accessed directly.
|
||||
*/
|
||||
struct ZThreadContext
|
||||
{
|
||||
//The handle to this thread
|
||||
ZThreadHandle Thread;
|
||||
|
||||
//The id given to this thread. Unique, but may be reused after thread is destroyed
|
||||
uint32_t ThreadId;
|
||||
|
||||
//The return status this thread exited with (invalid unless Thread == NULL)
|
||||
int ThreadExitStatus;
|
||||
|
||||
//Default Constructor
|
||||
ZThreadContext() { Invalidate(); }
|
||||
|
||||
//Returns if it's valid
|
||||
bool IsValid() const { return Thread != NULL; }
|
||||
|
||||
//Marks a thread context as invalid
|
||||
void Invalidate() { Thread = NULL; ThreadId = 0; ThreadExitStatus = 0; }
|
||||
};
|
||||
|
||||
/*
|
||||
Namespace used for static access to low-level thread functionality.
|
||||
*/
|
||||
namespace ZConcurrency
|
||||
{
|
||||
/*
|
||||
ZThreadContext CreateThread()
|
||||
|
||||
Creates a thread instance that will begin running the provided function.
|
||||
The thread context should be cleaned up with DestroyThread() after the
|
||||
thread exits (use WaitThread() to ensure it is exited).
|
||||
|
||||
@param _func - function that the thread will execute. Should be of return type
|
||||
int and take a void* as an argument.
|
||||
@param _arg - the argument that is passed to the function.
|
||||
|
||||
@return (ZThreadContext) - thread context, used as a handle to the thread
|
||||
*/
|
||||
ZThreadContext CreateThread(int(*_func)(void*), void *_arg);
|
||||
|
||||
/*
|
||||
void DestroyThread()
|
||||
|
||||
Frees memory associated with a thread context. This should only be called
|
||||
after the thread is known to be dead (e.g. using WaitThread()). As implied
|
||||
by the last comment, this does not kill the OS thread if it was already
|
||||
running.
|
||||
|
||||
@param _context - Thread context to be cleaned up
|
||||
@return (void)
|
||||
*/
|
||||
void DestroyThread(ZThreadContext& _context);
|
||||
|
||||
/*
|
||||
void SleepThread()
|
||||
|
||||
Causes the calling thread to sleep for a minimum of the specified time (in ms).
|
||||
|
||||
@param _ms - the specified time to sleep (in ms)
|
||||
@return (void)
|
||||
*/
|
||||
void SleepThread(uint32_t _ms);
|
||||
|
||||
/*
|
||||
int GetThreadId()
|
||||
|
||||
Gets the thread ID of the calling thread.
|
||||
|
||||
@return (uint32_t) - int that is the thread id of the calling thread
|
||||
*/
|
||||
uint32_t GetThreadId();
|
||||
|
||||
/*
|
||||
unsigned int GetTicks()
|
||||
|
||||
Gets the tick count since the last call to GetTicks.
|
||||
|
||||
@return (uint64_t) - the count (in ms) since program start.
|
||||
*/
|
||||
uint64_t GetTicks();
|
||||
|
||||
/*
|
||||
int WaitThread()
|
||||
|
||||
Waits for a thread to terminate. This is the only way to ensure thread resources are
|
||||
returned. The termination code from the thread is stored in the thread context.
|
||||
|
||||
@param _context - the handle returned from CreateThread (the termination code is stored here)
|
||||
@return (bool) - true if the thread terminated, false otherwise
|
||||
*/
|
||||
bool WaitThread(ZThreadContext& _context);
|
||||
|
||||
/*
|
||||
void YieldThread()
|
||||
|
||||
Causes the calling thread to yield execution to another thread.
|
||||
|
||||
@return (void)
|
||||
*/
|
||||
void YieldThread();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
86
Include/ZUtil/ZEvent.hpp
Normal file
86
Include/ZUtil/ZEvent.hpp
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
ZEvent.hpp
|
||||
Author: James Russell <jcrussell@762studios.com>
|
||||
|
||||
Purpose: RAII wrapper for SST_Event from libsst-concurrency.
|
||||
|
||||
Changelog
|
||||
2011/11/27 - creation (jcrussell)
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _ZEVENT_H
|
||||
#define _ZEVENT_H
|
||||
|
||||
#include <ZUtil/ZUtilBuild.hpp>
|
||||
#include <SST/SST_Event.h>
|
||||
|
||||
/*
|
||||
Event class. Used to manage allocation and deallocation of events.
|
||||
Cannot be copied or assigned, which prevents it from being used in stl-like containers.
|
||||
*/
|
||||
class ZEvent
|
||||
{
|
||||
private:
|
||||
DISABLE_COPY_AND_ASSIGN(ZEvent);
|
||||
|
||||
//libsst Event
|
||||
SST_Event Event;
|
||||
|
||||
public:
|
||||
/*
|
||||
Constructor. Creates an event from libsst-concurrency.
|
||||
*/
|
||||
ZEvent();
|
||||
|
||||
/*
|
||||
Destructor. Frees our event from libsst-concurrency.
|
||||
*/
|
||||
~ZEvent();
|
||||
|
||||
/*
|
||||
public ZSignal::Notify
|
||||
|
||||
Signals event, waking up all waiting threads. Until this event is reset, waiting threads will return.
|
||||
|
||||
@return (void)
|
||||
@context (all)
|
||||
*/
|
||||
void Notify();
|
||||
|
||||
/*
|
||||
public ZSignal::Reset
|
||||
|
||||
Signals reset, which causes threads that call Wait to block until signaled.
|
||||
|
||||
@return (void)
|
||||
@context (all)
|
||||
*/
|
||||
void Reset();
|
||||
|
||||
/*
|
||||
public ZSignal::Wait
|
||||
|
||||
Waits on a signal. Blocks until Signal is called.
|
||||
|
||||
@return (bool) - true if the event was signaled, false if returned before a signal (such as event not reset)
|
||||
@context (all)
|
||||
*/
|
||||
bool Wait();
|
||||
|
||||
/*
|
||||
public ZSignal::Wait
|
||||
|
||||
Waits on a signal for an amount of time.
|
||||
|
||||
@param _ms - the amount of time (in ms) to wait.
|
||||
@return (bool) - true if the event was signaled, false if returned before a signal (event not reset our out of time).
|
||||
@context (all)
|
||||
*/
|
||||
bool Wait(uint32_t _ms);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
184
Include/ZUtil/ZIniReader.hpp
Normal file
184
Include/ZUtil/ZIniReader.hpp
Normal file
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
ZIniReader.hpp
|
||||
Author: James Russell <jcrussell@762studios.com>
|
||||
Created: 4/27/2012
|
||||
|
||||
Purpose:
|
||||
|
||||
Parses INI file format in memory.
|
||||
|
||||
(File Begin)
|
||||
|
||||
# This is a commented line
|
||||
; This is too
|
||||
|
||||
[SectionA]
|
||||
Key1=Value1
|
||||
Key2 =Value2
|
||||
Key3= Value3
|
||||
Key4 = Value4
|
||||
|
||||
[SectionB]
|
||||
Key1 = Value1
|
||||
|
||||
...
|
||||
|
||||
(File End)
|
||||
|
||||
Comments must be on their own line. Sections must be unique to a file. Keys can be repeated,
|
||||
but the final value seen is the value recorded.
|
||||
|
||||
ZIniReader class does no I/O - it merely parses in-memory representations.
|
||||
|
||||
The data structures it provides a read-only, but you can get a mutable copy of its data as
|
||||
a ZRegistry object. The data above would be loaded into a registry with the following layout:
|
||||
|
||||
Root
|
||||
|
|
||||
+-> SectionA
|
||||
| |
|
||||
| +-> Key1 (Value1)
|
||||
| +-> Key2 (Value2)
|
||||
| +-> Key3 (Value3)
|
||||
| +-> Key4 (Value4)
|
||||
|
|
||||
+-> SectionB
|
||||
|
|
||||
+-> Key1 (Value1)
|
||||
|
||||
License:
|
||||
|
||||
TODO
|
||||
*/
|
||||
|
||||
#ifndef _ZINIREADER_HPP
|
||||
#define _ZINIREADER_HPP
|
||||
|
||||
#include <ZUtil/ZKVTree.hpp>
|
||||
|
||||
/*
|
||||
IniReader class.
|
||||
*/
|
||||
class ZIniReader
|
||||
{
|
||||
public:
|
||||
/*
|
||||
Default constructor.
|
||||
*/
|
||||
ZIniReader()
|
||||
: ErrorMessage() { }
|
||||
|
||||
/*
|
||||
Destructor.
|
||||
*/
|
||||
~ZIniReader()
|
||||
{ ClearData(); }
|
||||
|
||||
/*
|
||||
public ZIniReader::Read
|
||||
|
||||
Reads an INI file stored as a ZString.
|
||||
|
||||
@param _iniData - string holding the data of an ini file, which will be parsed
|
||||
@return (bool) - True if successful, false if failure. Use GetErrorString() to get the message
|
||||
*/
|
||||
bool Read(const ZString& _iniData)
|
||||
{ return Read(_iniData.Data(), _iniData.Length()); }
|
||||
|
||||
/*
|
||||
public ZIniReader::Read
|
||||
|
||||
Reads an INI file stored as memory block
|
||||
|
||||
@param data - Pointer to INI data
|
||||
@param length - Length of INI data
|
||||
@return (bool) - true if successful, false if failure (use GetErrorString() to get the message)
|
||||
*/
|
||||
bool Read(const char* data, size_t length);
|
||||
|
||||
/*
|
||||
public ZIniReader::GetErrorString
|
||||
|
||||
Gets the error message generated while loading the data if loading failed. If loading
|
||||
the data was successful, this returns an empty string.
|
||||
|
||||
@return (const ZString&) - error message string
|
||||
*/
|
||||
const ZString& GetErrorString()
|
||||
{ return ErrorMessage; }
|
||||
|
||||
/*
|
||||
public ZIniReader::GetSection
|
||||
|
||||
Looks up a section by name and returns a pointer to the ZHashMap object. If the
|
||||
section does not exist, NULL is returned. The hashmap contains a list of key-value pairs
|
||||
found for that section
|
||||
|
||||
@param sectionName - The name of the section
|
||||
@return (const ZHashMap<ZString, ZString>*) - The section, or NULL if it does not exist
|
||||
*/
|
||||
const ZHashMap<ZString, ZString>* GetSection(const ZString& sectionName);
|
||||
|
||||
/*
|
||||
public ZIniReader::GetSection
|
||||
|
||||
Looks up a section by ordinal and returns a pointer to the ZHashMap object. Sections
|
||||
are given in order of appearance in the file. The hashmap contains a list of key-value pairs
|
||||
found for that section.
|
||||
|
||||
@param index - The index of the section, between 0 and GetSectionCount() - 1
|
||||
@return (const ZHashMap<ZString, ZString>*) - The section
|
||||
*/
|
||||
const ZHashMap<ZString, ZString>* GetSection(size_t index)
|
||||
{ return Sections[index]; }
|
||||
|
||||
/*
|
||||
public ZIniReader::GetSectionCount
|
||||
|
||||
Gets the number of sections parsed. If Read() returned true, this will be at least one.
|
||||
@return (size_t) - The number of sections parsed.
|
||||
*/
|
||||
size_t GetSectionCount()
|
||||
{ return Sections.Size(); }
|
||||
|
||||
/*
|
||||
public ZIniReader::GetSectionName
|
||||
|
||||
Gets the name for a section by ordinal. Sections names are given in order of appearance
|
||||
in the file.
|
||||
|
||||
@param index - The index of the section, between 0 and GetSectionCount()-1
|
||||
@return (const ZString&) - The section name
|
||||
*/
|
||||
const ZString& GetSectionName(size_t index)
|
||||
{ return SectionNames[index]; }
|
||||
|
||||
/*
|
||||
public ZIniReader::GetKVTree
|
||||
|
||||
Populates a ZKVTree using the read values. If loading the data has failed,
|
||||
no data is entered.
|
||||
|
||||
To get values in the kv-tree, use the path string 'Section.Key'.
|
||||
|
||||
@param _kvtree - the kv-tree to contain the parsed ini values
|
||||
@return (void)
|
||||
*/
|
||||
void GetKVTree(ZKVTree& _kvtree);
|
||||
|
||||
private:
|
||||
DISABLE_COPY_AND_ASSIGN(ZIniReader);
|
||||
|
||||
ZString ErrorMessage; // Error Message (if an error has happened)
|
||||
|
||||
ZHashMap<ZString, ZHashMap<ZString, ZString>*> StringSectionMap; // String -> Hashmap table
|
||||
ZArray<ZHashMap<ZString, ZString>*> Sections; // Linear order in which sections were found
|
||||
ZArray<ZString> SectionNames; // Name of sections parsed
|
||||
|
||||
void SetError(const char* message, uint32_t line); // Sets the error message
|
||||
void ClearData(); // Clears previously read section data
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
69
Include/ZUtil/ZIniWriter.hpp
Normal file
69
Include/ZUtil/ZIniWriter.hpp
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
ZIniWriter.hpp
|
||||
Author: James Russell <jcrussell@762studios.com>
|
||||
Created: 5/6/2012
|
||||
|
||||
Purpose:
|
||||
|
||||
The 'inverse' of ZIniReader, this will take a kvtree of values (like the one given by
|
||||
ZIniReader) and write to an output string in the .ini format specified in ZIniReader.hpp.
|
||||
|
||||
License:
|
||||
|
||||
TODO
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _ZINIWRITER_HPP
|
||||
#define _ZINIWRITER_HPP
|
||||
|
||||
#include <ZUtil/ZKVTree.hpp>
|
||||
#include <ZUtil/ZSmartPointer.hpp>
|
||||
|
||||
/*
|
||||
IniWriter class.
|
||||
*/
|
||||
class ZIniWriter
|
||||
{
|
||||
public:
|
||||
/*
|
||||
Default Constructor.
|
||||
*/
|
||||
ZIniWriter() { }
|
||||
|
||||
/*
|
||||
Destructor.
|
||||
*/
|
||||
~ZIniWriter() { }
|
||||
|
||||
/*
|
||||
public ZIniWriter::GetErrorString
|
||||
|
||||
Gets the error message generated while writing the data if writing failed. If writing
|
||||
the data was successful, this returns an empty string.
|
||||
|
||||
@return (const ZString&)
|
||||
*/
|
||||
const ZString& GetErrorString();
|
||||
|
||||
/*
|
||||
public ZIniWriter::Write
|
||||
|
||||
Writes the data from the provided kvtree into the provided output string in the 'ini' format.
|
||||
|
||||
@param _input - the tree to read values from
|
||||
@param _output - the string to write the data into (the data is appended)
|
||||
@return (bool) - true if successful, false otherwise
|
||||
*/
|
||||
bool Write(const ZKVTree& _input, ZString& _output);
|
||||
|
||||
private:
|
||||
DISABLE_COPY_AND_ASSIGN(ZIniWriter);
|
||||
|
||||
//Error message (if an error has happened)
|
||||
ZString ErrorMessage;
|
||||
};
|
||||
|
||||
#endif
|
||||
69
Include/ZUtil/ZJSONReader.hpp
Normal file
69
Include/ZUtil/ZJSONReader.hpp
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
ZJSONReader.hpp
|
||||
Author: Chris Ertel <crertel@762studios.com>
|
||||
Created: 3/26/2013
|
||||
|
||||
Purpose:
|
||||
|
||||
JSON reading support, to convert JSON strings into ZKVTrees.
|
||||
|
||||
License:
|
||||
|
||||
TODO
|
||||
|
||||
*/
|
||||
#pragma once
|
||||
#ifndef _ZJSONREADER_H
|
||||
#define _ZJSONREADER_H
|
||||
|
||||
#include <ZUtil/ZKVTree.hpp>
|
||||
#include <ZUtil/ZSmartPointer.hpp>
|
||||
|
||||
/*
|
||||
ZJSONReader class, which converts JSON data into a ZKVTree that can be used to access / iterate
|
||||
the data.
|
||||
*/
|
||||
class ZJSONReader
|
||||
{
|
||||
private:
|
||||
DISABLE_COPY_AND_ASSIGN(ZJSONReader);
|
||||
|
||||
//Error Message (if an error has happened)
|
||||
ZString ErrorMessage;
|
||||
const ZString JSONData;
|
||||
|
||||
//Registry of data
|
||||
ZPtr<ZKVTree> Registry;
|
||||
|
||||
public:
|
||||
/*
|
||||
Parameterized Constructor.
|
||||
|
||||
@param _jsonData - string containing JSON data to parse
|
||||
*/
|
||||
ZJSONReader(const ZString& _jsonData);
|
||||
|
||||
/*
|
||||
public ZJSONReader::GetErrorString
|
||||
|
||||
Gets the error message generated while loading the data if loading failed. If loading
|
||||
the data was successful, this returns an empty string.
|
||||
|
||||
@return (const ZString&) - error message string
|
||||
*/
|
||||
const ZString& GetErrorString();
|
||||
|
||||
/*
|
||||
public ZJSONReader::GetKVTree
|
||||
|
||||
Gets the registry that was constructed from the parsed JSON data. If the loading failed,
|
||||
the pointer returned is NULL.
|
||||
|
||||
TODO - describe the format
|
||||
|
||||
@return (ZPtr<ZRegistry>) - registry containing the parsed JSON data
|
||||
*/
|
||||
ZPtr<ZKVTree> GetKVTree();
|
||||
};
|
||||
|
||||
#endif
|
||||
64
Include/ZUtil/ZJSONWriter.hpp
Normal file
64
Include/ZUtil/ZJSONWriter.hpp
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
ZJSONWriter.hpp
|
||||
Author: Chris Ertel <crertel@762studios.com>
|
||||
Created: 3/26/2013
|
||||
|
||||
Purpose:
|
||||
|
||||
JSON writing support, to convert ZKVTrees into JSON strings.
|
||||
|
||||
License:
|
||||
|
||||
TODO
|
||||
|
||||
*/
|
||||
#pragma once
|
||||
#ifndef _ZJSONWRITER_H
|
||||
#define _ZJSONWRITER_H
|
||||
|
||||
#include <ZUtil/ZSmartPointer.hpp>
|
||||
#include <ZUtil/ZKVTree.hpp>
|
||||
|
||||
class ZJSONWriter
|
||||
{
|
||||
private:
|
||||
DISABLE_COPY_AND_ASSIGN(ZJSONWriter);
|
||||
|
||||
//Error message (if an error has happened)
|
||||
ZString ErrorMessage;
|
||||
|
||||
//The registry we will be getting values from
|
||||
ZPtr<ZKVTree> Registry;
|
||||
|
||||
const ZString NoError;
|
||||
|
||||
public:
|
||||
/*
|
||||
Parameterized Constructor.
|
||||
|
||||
@param _registry - the registry to generate XML data from
|
||||
*/
|
||||
ZJSONWriter(ZPtr<ZKVTree> _registry);
|
||||
|
||||
/*
|
||||
public ZJSONWriter::GetErrorString
|
||||
|
||||
Gets the error message generated while writing the data if writing failed. If writing
|
||||
the data was successful, this returns an empty string.
|
||||
|
||||
@return (const ZString&) - a string describing an error that occurred
|
||||
*/
|
||||
const ZString& GetErrorString();
|
||||
|
||||
/*
|
||||
public ZJSONWriter::Write
|
||||
|
||||
Writes the data from the registry into the provided output string in XML format.
|
||||
|
||||
@param _output - the string to write the data into (the data is appended)
|
||||
@return (bool) - true if successful, false otherwise
|
||||
*/
|
||||
bool Write(ZString& _output);
|
||||
};
|
||||
|
||||
#endif
|
||||
821
Include/ZUtil/ZKVTree.hpp
Normal file
821
Include/ZUtil/ZKVTree.hpp
Normal file
@@ -0,0 +1,821 @@
|
||||
/*
|
||||
ZKVTree.hpp
|
||||
Author: James Russell <jcrussell@762studios.com>
|
||||
Created: 3/22/2012
|
||||
|
||||
Purpose:
|
||||
|
||||
ZKVTree defines a KV-Tree that uses strings as both keys and values. The model
|
||||
supported is hierarchical with no nesting limit, and individual nodes can be addressed
|
||||
directly or the tree can be iterated. This makes ZKVTree's typical use case as an
|
||||
in memory representation of hierarchical text formats such as XML and JSON, and can
|
||||
be used for simpler formats such as INI. When the layout and keys are known
|
||||
(such as with most INI files), lookup via path string is the easiest route. When the layout
|
||||
is not known (such as with an XML file with variable numbers of children and attributes),
|
||||
then iteration is the preferred method of getting access to the data.
|
||||
|
||||
Multiple nodes of the same name existing at the same level in the tree is supported.
|
||||
When a path is given that does not contain the number, then it is assumed to be
|
||||
referencing the first sibling node at that location (index 0).
|
||||
|
||||
Unnamed tree nodes are supported, with the key used to access those being omitted from the
|
||||
path string but the subscript being required.
|
||||
|
||||
If the tree has the following layout, with the values at each node contained
|
||||
in parenthesis:
|
||||
|
||||
Root
|
||||
|
|
||||
+-> A (0)
|
||||
| |
|
||||
| +-> B (8)
|
||||
| | |
|
||||
| | +-> c (16)
|
||||
| | +-> c (32)
|
||||
| | +-> (100)
|
||||
| | +-> (200)
|
||||
| |
|
||||
| +-> B (8)
|
||||
| | |
|
||||
| | +-> c (64)
|
||||
| | +-> d (128)
|
||||
| | +-> (10)
|
||||
| | +-> (20)
|
||||
| |
|
||||
| +-> b (5)
|
||||
| +-> b (10)
|
||||
| +-> c (15)
|
||||
| +-> d (20)
|
||||
|
|
||||
+-> B (8)
|
||||
| |
|
||||
| +-> c (50)
|
||||
| +-> d (100)
|
||||
|
|
||||
+-> a (1)
|
||||
+-> a (2)
|
||||
+-> a (3)
|
||||
+-> b (4)
|
||||
|
||||
Then valid path strings include (but are not limited to):
|
||||
|
||||
A.B - would get the value of node 'B[0]' (8) with parent node 'A[0]'
|
||||
A.B.c - would get the value of node 'c[0]' (16) with parent node 'A[0].B[0]'
|
||||
A.B.c[1] - would get the value of node 'c[1]' (32) with parent node 'A[0].B[0]'
|
||||
A.B[1].c - would get the value of node 'c[0]' (64) with parent node 'A[0].B[1]'
|
||||
A.B[1].c[1] - would get the value of node 'c[1]' (128) with parent node 'A[0].B[1]'
|
||||
A.b[1] - would get the value of node 'b[1]' (10) with parent node 'A[0]'
|
||||
B.c - would get the value of node 'c[0]' (50) with parent node 'B[0]'
|
||||
a - would get the value of node 'a[0]' (1) with root parent node ''
|
||||
a[2] - would get the value of node 'a[2]' (3) with root parent node ''
|
||||
|
||||
If this KVTree were to be iterated using ZKVTree::Iterator::Next(), a depth first
|
||||
traversal of the structure would take place, giving us the following order:
|
||||
|
||||
A
|
||||
A.B[0]
|
||||
A.B[0].c[0]
|
||||
A.B[0].c[1]
|
||||
A.B[0].[0]
|
||||
A.B[0].[1]
|
||||
A.B[1].c
|
||||
A.B[1].d
|
||||
A.B[1].[0]
|
||||
A.B[1].[1]
|
||||
A.b[0]
|
||||
A.b[1]
|
||||
A.c
|
||||
A.d
|
||||
B
|
||||
B.c
|
||||
B.d
|
||||
a[0]
|
||||
a[1]
|
||||
a[2]
|
||||
|
||||
A special syntax for accessing unnamed children is supported, which enables nested array behavior
|
||||
for values:
|
||||
|
||||
A.B[0][0] - would get the value of (unnamed) node '[0]' (100) with parent node 'A.B[0]'
|
||||
A.B[1][0] - would get the value of (unnamed) node '[0]' (10) with parent node 'A.B[0]'
|
||||
A.B[1][1] - would get the value of (unnamed) node '[1]' (20) with parent node 'A.B[1]'
|
||||
|
||||
Note that these are syntactic sugar for:
|
||||
|
||||
A.B[0].[0] (could also be expressed as A.B[0]. or A.B. due to the implicit [0])
|
||||
A.B[1].[0] (could also be expressed as A.B[1]. due to the implicit [0])
|
||||
A.B[1].[1]
|
||||
|
||||
License:
|
||||
|
||||
TODO
|
||||
*/
|
||||
|
||||
#ifndef _ZREGISTRY_H
|
||||
#define _ZREGISTRY_H
|
||||
|
||||
#include <SST/SST_Hash.h>
|
||||
|
||||
#include <ZSTL/ZHashMap.hpp>
|
||||
#include <ZSTL/ZString.hpp>
|
||||
#include <ZSTL/ZBasicStringAlgo.hpp>
|
||||
|
||||
#include <ZUtil/ZConcurrency.hpp>
|
||||
#include <ZUtil/ZSlabAllocator.hpp>
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
//Valid path separator for ZKVTree
|
||||
#ifndef ZKVTREE_PATH_SEPARATOR
|
||||
#define ZKVTREE_PATH_SEPARATOR '.'
|
||||
#endif
|
||||
|
||||
//Default number of nodes preallocated
|
||||
#ifndef ZKVTREE_NODE_COUNT
|
||||
#define ZKVTREE_NODE_COUNT (128)
|
||||
#endif
|
||||
|
||||
//Invalid characters for a path ([] valid on subscript only)
|
||||
#define ZKVTREE_INVALID_PATH_CHARS "%[]"
|
||||
|
||||
/*
|
||||
ZKVTree class.
|
||||
*/
|
||||
class ZKVTree
|
||||
{
|
||||
public:
|
||||
//KVTree node structure
|
||||
struct Node
|
||||
{
|
||||
ZString Name; //Name of the node
|
||||
ZString Value; //Value held by this node
|
||||
Node* ParentNode; //Pointer to our parent node
|
||||
size_t Index; //Index of this node in the parent's children array
|
||||
ZArray< Node* > Children; //Children of this node
|
||||
|
||||
//Determines if this is the root node
|
||||
bool IsRootNode() const {
|
||||
if (ParentNode == NULL) {
|
||||
return true;
|
||||
} else return false;
|
||||
}
|
||||
|
||||
//Finds the node with the given name in the child array
|
||||
Node* GetChildByName(const ZString& _name, size_t _start, size_t _end, size_t _subscript) const {
|
||||
for (size_t i = 0; i < Children.Size(); i++) {
|
||||
Node* child = Children.Data()[i];
|
||||
if (child->Name.Length() == (_end - _start)) {
|
||||
if (ZStringAlgo::Equal(child->Name, 0, child->Name.Length(), _name, _start, _end)) {
|
||||
if (_subscript-- == 0) {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//Finds the number of children with the given name
|
||||
size_t GetChildCountByName(const ZString& _name, size_t _start, size_t _end) const {
|
||||
size_t num = 0;
|
||||
for (size_t i = 0; i < Children.Size(); i++) {
|
||||
Node* child = Children.Data()[i];
|
||||
if (child->Name.Length() == (_end - _start)) {
|
||||
if (ZStringAlgo::Equal(child->Name, 0, child->Name.Length(), _name, _start, _end)) {
|
||||
num++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
//Finds the index of the last occurrence of a node with the given name
|
||||
size_t GetLastIndexByName(const ZString& _name, size_t _start, size_t _end) const {
|
||||
size_t idx = 0;
|
||||
for (size_t i = 0; i < Children.Size(); i++) {
|
||||
Node* child = Children.Data()[i];
|
||||
if (child->Name.Length() == (_end - _start)) {
|
||||
if (ZStringAlgo::Equal(child->Name, 0, child->Name.Length(), _name, _start, _end)) {
|
||||
idx = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
//Gets the path to this node
|
||||
void GetPath(ZString& _out, Node* _end = NULL) const {
|
||||
if (this != _end && ParentNode != NULL) {
|
||||
ParentNode->GetPath(_out, _end);
|
||||
} else return;
|
||||
|
||||
if (!_out.Empty()) {
|
||||
_out.PushBack(ZKVTREE_PATH_SEPARATOR);
|
||||
}
|
||||
|
||||
if (!IsRootNode()) {
|
||||
size_t siblings = ParentNode->GetChildCountByName(Name, 0, Name.Length());
|
||||
size_t last_idx = ParentNode->GetLastIndexByName(Name, 0, Name.Length());
|
||||
|
||||
_out += Name;
|
||||
|
||||
if (ParentNode != _end) {
|
||||
ZString subscript;
|
||||
ZStringAlgo::BuildPrintf(subscript, "[%i]", siblings - (1 + last_idx - Index));
|
||||
|
||||
_out += subscript;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// gets the simple path to this node (avoids [0] subscript)
|
||||
void GetSimplePath(ZString& _out, Node* _end = NULL) const {
|
||||
if (this != _end && ParentNode != NULL) {
|
||||
ParentNode->GetSimplePath(_out, _end);
|
||||
} else return;
|
||||
|
||||
if (!_out.Empty()) {
|
||||
_out.PushBack(ZKVTREE_PATH_SEPARATOR);
|
||||
}
|
||||
|
||||
if (!IsRootNode()) {
|
||||
size_t siblings = ParentNode->GetChildCountByName(Name, 0, Name.Length());
|
||||
size_t last_idx = ParentNode->GetLastIndexByName(Name, 0, Name.Length());
|
||||
|
||||
_out += Name;
|
||||
|
||||
if (ParentNode != _end && siblings - (1 + last_idx - Index) != 0) {
|
||||
ZString subscript;
|
||||
ZStringAlgo::BuildPrintf(subscript, "[%i]", siblings - (1 + last_idx - Index));
|
||||
|
||||
_out += subscript;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
KVTree iterator, used to directly iterate the nodes in the KVTree.
|
||||
*/
|
||||
class Iterator
|
||||
{
|
||||
friend class ZKVTree;
|
||||
public:
|
||||
/*
|
||||
Parameterized Constructor.
|
||||
|
||||
@param _node - the node to start the iterator at
|
||||
@param _tree - the KVTree we are iterating (reference needed for locking / unlocking)
|
||||
*/
|
||||
Iterator(Node* _node, ZKVTree* _tree)
|
||||
: CurrentNode(_node), KVTree(_tree) { }
|
||||
|
||||
/*
|
||||
Copy Constructor.
|
||||
|
||||
@param _other - the other iterator
|
||||
*/
|
||||
Iterator(const Iterator& _other)
|
||||
:CurrentNode(_other.CurrentNode), KVTree(_other.KVTree) { }
|
||||
|
||||
/*
|
||||
Destructor. Releases the lock (when 'Lock' is destructed).
|
||||
*/
|
||||
~Iterator() { }
|
||||
|
||||
/*
|
||||
Gets the path to the current iterator location.
|
||||
|
||||
@return (ZString) - path to this node
|
||||
*/
|
||||
ZString GetPath() const
|
||||
{ ZString path; CurrentNode->GetPath(path); return path; }
|
||||
|
||||
/*
|
||||
Gets the path to the current iterator from an end node. If the end node
|
||||
is not on the parent path, functionally equivalent to GetPath.
|
||||
|
||||
@param _end - node we should get path from
|
||||
@return (ZString) - path to this node from provided node
|
||||
*/
|
||||
ZString GetPath(Iterator end) const
|
||||
{ ZString path; CurrentNode->GetPath(path, end.CurrentNode); return path; }
|
||||
|
||||
/*
|
||||
As GetPath, but avoids the [0] subscript.
|
||||
|
||||
@return (ZString) - path to this node
|
||||
*/
|
||||
ZString GetSimplePath() const
|
||||
{ ZString path; CurrentNode->GetSimplePath(path); return path; }
|
||||
|
||||
/*
|
||||
As GetPath, but avoids the [0] subscript.
|
||||
|
||||
@param _end - node we should get path from
|
||||
@return (ZString) - path to this node from provided node
|
||||
*/
|
||||
ZString GetSimplePath(Iterator end) const
|
||||
{ ZString path; CurrentNode->GetSimplePath(path, end.CurrentNode); return path; }
|
||||
|
||||
/*
|
||||
Gets a reference to the name of the current node.
|
||||
|
||||
@return (const ZString&) - reference to the name of the current node
|
||||
*/
|
||||
const ZString& GetName() const
|
||||
{ ZASSERT(!CurrentNode->IsRootNode(), "Cannot get name on root node!"); return CurrentNode->Name; }
|
||||
|
||||
/*
|
||||
Gets a reference to the value of the current node.
|
||||
|
||||
@return (ZString&) - reference to the value of the current node
|
||||
*/
|
||||
const ZString& GetValue() const
|
||||
{ ZASSERT(!CurrentNode->IsRootNode(), "Cannot get value on root node!"); return CurrentNode->Value; }
|
||||
|
||||
/*
|
||||
Gets the index of the current node (sibling index).
|
||||
|
||||
@return (size_t) - the index of the current node.
|
||||
*/
|
||||
size_t GetIndex() const
|
||||
{ return CurrentNode->Index; }
|
||||
|
||||
/*
|
||||
Gets the number of children contained by this node.
|
||||
*/
|
||||
size_t GetChildCount() const
|
||||
{ return CurrentNode->Children.Size(); }
|
||||
|
||||
/*
|
||||
Gets the number of children of this node with the given name.
|
||||
*/
|
||||
size_t GetChildCountByName(const ZString& _name) const
|
||||
{ return CurrentNode->GetChildCountByName(_name, 0, _name.Length()); }
|
||||
|
||||
/*
|
||||
Gets the index of the nth child of the given name (ZSTL::InvalidPos if not found).
|
||||
*/
|
||||
size_t GetChildIndexByName(const ZString& _name, size_t _n = 0) const
|
||||
{
|
||||
Node* childNode = CurrentNode->GetChildByName(_name, 0, _name.Length(), _n);
|
||||
|
||||
return (childNode == NULL ? ZSTL::InvalidPos : childNode->Index);
|
||||
}
|
||||
|
||||
/*
|
||||
Gets the number of siblings to the current node, including the current node.
|
||||
*/
|
||||
size_t GetSiblingCount() const
|
||||
{
|
||||
if (CurrentNode->ParentNode == NULL)
|
||||
return 0;
|
||||
|
||||
return CurrentNode->ParentNode->Children.Size();
|
||||
}
|
||||
|
||||
/*
|
||||
Gets the number of siblings to the current node with the given name (can
|
||||
include this node if name is equivalent).
|
||||
*/
|
||||
size_t GetSiblingCountByName(const ZString& _name) const
|
||||
{
|
||||
if (CurrentNode->ParentNode == NULL)
|
||||
return 0;
|
||||
|
||||
return CurrentNode->ParentNode->GetChildCountByName(_name, 0, _name.Length());
|
||||
}
|
||||
|
||||
/*
|
||||
Gets the index of the nth sibling of the given name (ZSTL::InvalidPos if not found, can
|
||||
be the node this iterator points to).
|
||||
*/
|
||||
size_t GetSiblingIndexByName(const ZString& _name, size_t _n = 0) const
|
||||
{
|
||||
if (CurrentNode->ParentNode == NULL)
|
||||
return ZSTL::InvalidPos;
|
||||
|
||||
Node* siblingNode = CurrentNode->ParentNode->GetChildByName(_name, 0, _name.Length(), _n);
|
||||
|
||||
return (siblingNode == NULL ? ZSTL::InvalidPos : siblingNode->Index);
|
||||
}
|
||||
|
||||
//Checks to see if this is an end node
|
||||
bool CheckEnd()
|
||||
{ return CurrentNode->IsRootNode(); }
|
||||
|
||||
//Checks to see if we can move to the parent node
|
||||
bool CheckParent()
|
||||
{ return CurrentNode->ParentNode != NULL; }
|
||||
|
||||
//Checks to see if we can move to the child node
|
||||
bool CheckChild(size_t _index = 0)
|
||||
{ return _index < CurrentNode->Children.Size(); }
|
||||
|
||||
//Checks to see if we can move to the sibling node
|
||||
bool CheckSibling(size_t _index = 0)
|
||||
{ return CurrentNode->ParentNode != NULL && _index < CurrentNode->ParentNode->Children.Size() - 1; }
|
||||
|
||||
//Checks to see if we can move to the next sibling node
|
||||
bool CheckNextSibling()
|
||||
{ return CurrentNode->ParentNode != NULL && CurrentNode->Index < CurrentNode->ParentNode->Children.Size() - 1; }
|
||||
|
||||
//Checks to see if we can move to the previous sibling node
|
||||
bool CheckPrevSibling()
|
||||
{ return CurrentNode->Index > 0; }
|
||||
|
||||
/*
|
||||
Sets the value of the current node.
|
||||
|
||||
@param (ZString&) - value to set this node to
|
||||
*/
|
||||
void SetValue(const ZString& _value)
|
||||
{ CurrentNode->Value = _value; }
|
||||
|
||||
/*
|
||||
public ZKVTree::Iterator::Next
|
||||
|
||||
This operation attempts to move this iterator to the first child of this node. If this
|
||||
is an invalid move, then it attempts to iterate to the next sibling. If this is invalid,
|
||||
it will attempt to iterate to the next sibling of the parent, and will continue to
|
||||
attempt this until it has either reached the end or it can do so.
|
||||
|
||||
This basically means using nothing but 'Next' from beginning to end will result in
|
||||
a depth-first traversal of the KVTree.
|
||||
|
||||
@return (Iterator&) - this iterator
|
||||
*/
|
||||
Iterator& Next()
|
||||
{
|
||||
if (CheckChild())
|
||||
Child();
|
||||
else if (CheckNextSibling())
|
||||
NextSibling();
|
||||
else {
|
||||
while (CurrentNode->ParentNode != NULL) {
|
||||
if (CheckParent()) {
|
||||
Parent();
|
||||
if (CheckNextSibling()) {
|
||||
NextSibling();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*
|
||||
public ZKVTree::Iterator::Parent
|
||||
|
||||
This operation attempts to move the iterator to the parent node of this node.
|
||||
|
||||
@return (Iterator&) - this iterator
|
||||
*/
|
||||
Iterator& Parent()
|
||||
{
|
||||
if (CheckParent()) {
|
||||
CurrentNode = CurrentNode->ParentNode;
|
||||
} else *this = KVTree->End();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*
|
||||
public ZKVTree::Iterator::Child
|
||||
|
||||
This operation moves the iterator to child node at the given index.
|
||||
|
||||
@param _index - the child number to move to
|
||||
@return (Iterator&) - this iterator
|
||||
*/
|
||||
Iterator& Child(size_t _index = 0)
|
||||
{
|
||||
if (CheckChild(_index)) {
|
||||
CurrentNode = CurrentNode->Children[_index];
|
||||
} else *this = KVTree->End();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*
|
||||
public ZKVTree::Iterator::Sibling
|
||||
|
||||
This operation moves the iterator to the sibling node at the given index.
|
||||
|
||||
@param _index - the sibling index
|
||||
@return (Iterator&) - this iterator
|
||||
*/
|
||||
Iterator& Sibling(size_t _index = 0)
|
||||
{
|
||||
ZASSERT(CheckSibling(_index), "ZKVTree::Iterator unable to move to sibling node!");
|
||||
|
||||
if (CheckSibling(_index)) {
|
||||
CurrentNode = CurrentNode->ParentNode->Children[_index];
|
||||
} else *this = KVTree->End();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*
|
||||
public ZKVTree::Iterator::PrevSibling
|
||||
|
||||
This operation moves the iterator to the previous sibling node of this node.
|
||||
|
||||
@return (Iterator&) - this iterator
|
||||
*/
|
||||
Iterator& PrevSibling()
|
||||
{
|
||||
if (CheckPrevSibling()) {
|
||||
CurrentNode = CurrentNode->ParentNode->Children[CurrentNode->Index - 1];
|
||||
} else *this = KVTree->End();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*
|
||||
public ZKVTree::Iterator::NextSibling
|
||||
|
||||
This operation moves the iterator to the next sibling node of this node.
|
||||
|
||||
@return (Iterator&) - this iterator
|
||||
*/
|
||||
Iterator& NextSibling()
|
||||
{
|
||||
if (CheckNextSibling()) {
|
||||
CurrentNode = CurrentNode->ParentNode->Children[CurrentNode->Index + 1];
|
||||
} else *this = KVTree->End();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*
|
||||
public ZKVTree::Iterator::ParentItr
|
||||
|
||||
This operation returns an iterator to the parent node.
|
||||
|
||||
@return (ZKVTree::Iterator) - iterator to the parent node
|
||||
*/
|
||||
Iterator ParentItr() const
|
||||
{
|
||||
ZASSERT(CurrentNode->ParentNode != NULL, "Unable to get KVTree parent!");
|
||||
|
||||
return Iterator(CurrentNode->ParentNode, KVTree);
|
||||
}
|
||||
|
||||
/*
|
||||
public ZKVTree::Iterator::ChildItr
|
||||
|
||||
This operation returns an iterator to the first child node of this iterator,
|
||||
or the end iterator if no child is found.
|
||||
|
||||
@param _index - the child node index to get an iterator to
|
||||
@return (Iterator) - iterator to the child node
|
||||
*/
|
||||
Iterator ChildItr() const
|
||||
{
|
||||
return ChildItr(0);
|
||||
}
|
||||
|
||||
/*
|
||||
public ZKVTree::Iterator::ChildItr
|
||||
|
||||
This operation returns an iterator to the child node at the given index.
|
||||
|
||||
@param _index - the child node index to get an iterator to
|
||||
@return (Iterator) - iterator to the child node
|
||||
*/
|
||||
Iterator ChildItr(size_t _index) const
|
||||
{
|
||||
if (_index == ZSTL::InvalidPos || _index >= CurrentNode->Children.Size()) {
|
||||
return KVTree->End();
|
||||
} else return Iterator(CurrentNode->Children.Data()[_index], KVTree);
|
||||
}
|
||||
|
||||
/*
|
||||
public ZKVTree::Iterator::ChildItr
|
||||
|
||||
This returns an iterator to the nth child of the given name.
|
||||
|
||||
@param _name - the name of the child to get an iterator to
|
||||
@param _n - the occurrence of the child to get (0 = first occurrence)
|
||||
@return (Iterator) - iterator to the child node
|
||||
*/
|
||||
Iterator ChildItr(const ZString& name, size_t _n = 0) const
|
||||
{
|
||||
return ChildItr(GetChildIndexByName(name, _n));
|
||||
}
|
||||
|
||||
/*
|
||||
public ZKVTree::Iterator::GetSibling
|
||||
|
||||
This operation returns an iterator to the sibling node at the given index.
|
||||
|
||||
@param _index - the child node index to get an iterator to
|
||||
@return (Iterator) - iterator to the child node
|
||||
*/
|
||||
Iterator SiblingItr(size_t _index) const
|
||||
{
|
||||
if (_index == ZSTL::InvalidPos || _index >= CurrentNode->ParentNode->Children.Size()) {
|
||||
return KVTree->End();
|
||||
} else return Iterator(CurrentNode->ParentNode->Children.Data()[_index], KVTree);
|
||||
}
|
||||
|
||||
/*
|
||||
public ZKVTree::Iterator::GetSibling
|
||||
|
||||
This operation returns an iterator to the nth sibling of the given name.
|
||||
|
||||
@param _name - the name of the sibling to get an iterator to
|
||||
@param _n - the occurrence of the sibling to get (0 = first occurrence)
|
||||
@return (Iterator) - iterator to the sibling node
|
||||
*/
|
||||
Iterator SiblingItr(const ZString& name, size_t _n = 0) const
|
||||
{
|
||||
return SiblingItr(GetSiblingIndexByName(name, _n));
|
||||
}
|
||||
|
||||
//Operator Overloads
|
||||
Iterator& operator ++ () { return Next(); }
|
||||
Iterator operator ++ (int) { Iterator itr = *this; Next(); return itr; }
|
||||
|
||||
Iterator& operator = (const Iterator& _other) { CurrentNode = _other.CurrentNode; KVTree = _other.KVTree; return *this; }
|
||||
|
||||
bool operator == (const Iterator& _other) const { return CurrentNode == _other.CurrentNode; }
|
||||
bool operator != (const Iterator& _other) const { return !(*this == _other); }
|
||||
|
||||
private:
|
||||
Node* CurrentNode; //Our current KVTree node
|
||||
ZKVTree* KVTree; //The KVTree we are iterating
|
||||
};
|
||||
|
||||
/*
|
||||
Constructor.
|
||||
*/
|
||||
ZKVTree();
|
||||
|
||||
/*
|
||||
Copy Constructor.
|
||||
*/
|
||||
ZKVTree(const ZKVTree& _other);
|
||||
|
||||
/*
|
||||
Destructor.
|
||||
*/
|
||||
~ZKVTree();
|
||||
|
||||
/*
|
||||
= operator. Performs a copy of node names and data.
|
||||
|
||||
@param _other - the KVTree to copy from
|
||||
*/
|
||||
ZKVTree& operator = (const ZKVTree& _other);
|
||||
|
||||
/*
|
||||
public ZKVTree::Add
|
||||
|
||||
Adds a node to the tree under the given parent node. The version that takes no parent path
|
||||
will add the child under the root node. The iterator returned is used to directly address the
|
||||
node.
|
||||
|
||||
The two parameter version of this function adds children to the root node.
|
||||
|
||||
@param _parent - the path to the parent node
|
||||
@param _itr - iterator to the parent node
|
||||
@param _name - the name of the child node
|
||||
@param _value - the value of the child node
|
||||
@return (Iterator) - iterator to the created node
|
||||
*/
|
||||
Iterator Add(const ZString& _name, const ZString& _value);
|
||||
Iterator Add(const ZString& _parent, const ZString& _name, const ZString& _value);
|
||||
Iterator Add(const Iterator& _itr, const ZString& _name, const ZString& _value);
|
||||
|
||||
/*
|
||||
public ZKVTree::Begin
|
||||
|
||||
Gets a ZKVTree::Iterator to the first child of the root node of this KVTree. If there
|
||||
are no children, returns ZKVTree::End().
|
||||
|
||||
@return (ZKVTree::Iterator) - iterator to the beginning of the KVTree (first child node)
|
||||
*/
|
||||
Iterator Begin() const;
|
||||
|
||||
/*
|
||||
public ZKVTree::Clear
|
||||
|
||||
Clears the KVTree of all values.
|
||||
|
||||
@return (void)
|
||||
*/
|
||||
void Clear();
|
||||
|
||||
/*
|
||||
public ZKVTree::End
|
||||
|
||||
Gets a ZKVTree::Iterator to the end of the KVTree.
|
||||
|
||||
@return (ZKVTree::Iterator) - iterator to the end of the KVTree
|
||||
*/
|
||||
const Iterator End() const;
|
||||
|
||||
/*
|
||||
public ZKVTree::Erase
|
||||
|
||||
Erases the node at the given position and all children.
|
||||
|
||||
@param _path - the path to the node
|
||||
@param _itr - iterator to the node (invalidated by this call)
|
||||
@return (void)
|
||||
*/
|
||||
void Erase(const ZString& _path);
|
||||
void Erase(const Iterator& _itr);
|
||||
|
||||
/*
|
||||
public ZKVTree::Find
|
||||
|
||||
Gets a ZKVTree::Iterator to the given element if found. Returns an iterator
|
||||
equivalent to ZKVTree::End() if not found.
|
||||
|
||||
@param _path - path to the node to get an iterator to
|
||||
@param _itr - parent iterator to search from (path will be searched from this node as root)
|
||||
@return (ZKVTree::Iterator) - iterator to value if found, End() otherwise
|
||||
*/
|
||||
Iterator Find(const ZString& _path) const;
|
||||
Iterator Find(const Iterator& _itr, const ZString& _path) const;
|
||||
|
||||
/*
|
||||
public ZKVTree::Get
|
||||
|
||||
Gets a value from the KVTree that held by the node at the provided path.
|
||||
|
||||
@param _path - the path to the node to get the value from (if no subscript, [0] is assumed)
|
||||
@return (const ZString&) - reference to the value held by the node at the provided path
|
||||
@assert - if no value exists at the provided path
|
||||
*/
|
||||
const ZString& Get(const ZString& _path) const;
|
||||
const ZString& Get(const Iterator& _itr, const ZString& _path);
|
||||
|
||||
/*
|
||||
public ZKVTree::Merge
|
||||
|
||||
Merges this KVTree with another, bringing in the values defined in the other
|
||||
KVTree.
|
||||
|
||||
@param _other - the KVTree to merge values from
|
||||
@param _overwrite - if true, values will be overwritten when a conflict occurs
|
||||
@return (void)
|
||||
*/
|
||||
void Merge(const ZKVTree& _other, bool _overwrite);
|
||||
|
||||
/*
|
||||
public ZKVTree::Put
|
||||
|
||||
Puts a node with the given value into the KVTree at the provided path. Will overwrite
|
||||
any existing value at that location.
|
||||
|
||||
If the path string has a child node that does not exist, it will be created so long as the
|
||||
subscript is for the next child node, i.e., if A.B.c[1] is passed in, it will be created so
|
||||
long as A.B.c[0] exists.
|
||||
|
||||
The iterator version overwrites the data at that location if the iterator was created by this
|
||||
tree, and will attempt to create it as above if not from this tree.
|
||||
|
||||
@param _path - the path to the KVTree value (if no index, [0] is assumed)
|
||||
@param _itr - iterator to the node to assign the value to (will overwrite)
|
||||
@param _value - the value to assign to the node
|
||||
@return (Iterator) - iterator to the created value
|
||||
*/
|
||||
Iterator Put(const ZString& _key, const ZString& _value);
|
||||
Iterator Put(const Iterator& _itr, const ZString& _value);
|
||||
|
||||
/*
|
||||
public ZKVTree::IsValidKeyName
|
||||
|
||||
Checks that a key name is able to be put into the KVTree.
|
||||
|
||||
This basically ensures that a key will be valid for use in pathing.
|
||||
A valid key name doesn't contain whitespace, square brackets, or periods.
|
||||
|
||||
@param _name - the name being considered for validity.
|
||||
@return (bool) - true if the keyname would be valid in a path, false otherwise
|
||||
*/
|
||||
bool IsValidKeyName( const ZString& _key ) const;
|
||||
|
||||
protected:
|
||||
ZSlabAllocator<Node, ZKVTREE_NODE_COUNT> NodeAllocator;
|
||||
|
||||
Node RootNode; // The root node of the KVTree (also acts as the end node)
|
||||
|
||||
//Gets a node from the KVTree given a path (NULL if not found)
|
||||
Node* GetFromPath(const ZString& _path) const;
|
||||
|
||||
//Creates all the nodes needed along a path to be able to get and set the value, returning the node
|
||||
Node* CreatePath(const ZString& _path);
|
||||
|
||||
//Helper function used to check in all nodes
|
||||
void NodeCheckIn(Node* _node);
|
||||
};
|
||||
|
||||
#endif
|
||||
269
Include/ZUtil/ZLog.hpp
Normal file
269
Include/ZUtil/ZLog.hpp
Normal file
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
ZLog.hpp
|
||||
Author: James Russell
|
||||
|
||||
Purpose:
|
||||
|
||||
Logging utility. The logging class cannot be instantiated, but instead is utilized through
|
||||
static public method calls. The logging system must be initialized before use and can be
|
||||
shutdown at any time. Any logging calls placed after the system has been shutdown amount
|
||||
to a no-op.
|
||||
|
||||
The logging system is thread-safe.
|
||||
|
||||
License:
|
||||
|
||||
TODO
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _ZLOG_HPP
|
||||
#define _ZLOG_HPP
|
||||
|
||||
#include <ZSTL/ZPair.hpp>
|
||||
#include <ZSTL/ZString.hpp>
|
||||
|
||||
#include <ZUtil/ZMutex.hpp>
|
||||
#include <ZUtil/ZSmartPointer.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
//Typedef to define a log file handle
|
||||
typedef size_t ZLogFile;
|
||||
|
||||
//Logging type enumeration used to specify which level of log is being performed
|
||||
enum ZLogType
|
||||
{
|
||||
LOG_ERROR, //Used when an error condition has occurred
|
||||
LOG_WARNING, //Used when a recoverable error condition has occurred
|
||||
LOG_INFO, //Used when significant events have occurred
|
||||
LOG_SPAM, //Used for insignificant events and process flow notification
|
||||
LOG_SIZE
|
||||
};
|
||||
|
||||
//Overall Logging Levels
|
||||
#define ZLOG_LEVEL_NONE 0
|
||||
#define ZLOG_LEVEL_ERROR 1
|
||||
#define ZLOG_LEVEL_WARNING 2
|
||||
#define ZLOG_LEVEL_INFO 3
|
||||
#define ZLOG_LEVEL_SPAM 4
|
||||
|
||||
//If the log level is not defined by the user, then ensure all logging is handled
|
||||
#ifndef ZLOG_LEVEL
|
||||
#define ZLOG_LEVEL ZLOG_LEVEL_SPAM
|
||||
#endif
|
||||
|
||||
//Define used to enumerate the default log file
|
||||
#define ZLOGFILE_DEFAULT 0
|
||||
|
||||
#if defined(_MSC_VER) || defined(__GNUC__) || defined(__SUNPRO_CC) //C99 style variadic macros
|
||||
|
||||
#define SystemLogError(...) ZLog::Printf(LOG_ERROR, ZLOGFILE_DEFAULT, 0, 0, __FUNCTION__, __VA_ARGS__)
|
||||
#define SystemLogWarning(...) ZLog::Printf(LOG_WARNING, ZLOGFILE_DEFAULT, 0, 0, __FUNCTION__, __VA_ARGS__)
|
||||
#define SystemLogInfo(...) ZLog::Printf(LOG_INFO, ZLOGFILE_DEFAULT, 0, 0, __FUNCTION__, __VA_ARGS__)
|
||||
#define SystemLogSpam(...) ZLog::Printf(LOG_SPAM, ZLOGFILE_DEFAULT, 0, 0, __FUNCTION__, __VA_ARGS__)
|
||||
|
||||
#if ZLOG_LEVEL < ZLOG_LEVEL_SPAM
|
||||
#undef SystemLogSpam
|
||||
#define SystemLogSpam(...)
|
||||
#endif
|
||||
#if ZLOG_LEVEL < ZLOG_LEVEL_INFO
|
||||
#undef SystemLogInfo
|
||||
#define SystemLogInfo(...)
|
||||
#endif
|
||||
#if ZLOG_LEVEL < ZLOG_LEVEL_WARNING
|
||||
#undef SystemLogWarning
|
||||
#define SystemLogWarning(...)
|
||||
#endif
|
||||
#if ZLOG_LEVEL < ZLOG_LEVEL_ERROR
|
||||
#undef SystemLogError
|
||||
#define SystemLogError(...)
|
||||
#endif
|
||||
#if (ZLOG_LEVEL < ZLOG_LEVEL_NONE) || (ZLOG_LEVEL > ZLOG_LEVEL_SPAM)
|
||||
#error ZLOG_LEVEL Set to Invalid Value!
|
||||
#endif
|
||||
|
||||
#else //Not C99-style variadic macro
|
||||
|
||||
#error Define variadic macro flavor for your compiler in ZLog.hpp
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
Logging delegate. Called when a log entry has been made.
|
||||
*/
|
||||
class ZLogDelegate
|
||||
{
|
||||
public:
|
||||
virtual ~ZLogDelegate() { }
|
||||
/*
|
||||
virtual public ZLogDelegate::Execute
|
||||
|
||||
Delegate execute method. This is called whenever a logging entry has been made.
|
||||
|
||||
@param _type - the type of logging entry
|
||||
@param _file - the log file written to
|
||||
@param _logEntry - the logging entry made
|
||||
@return (void)
|
||||
*/
|
||||
virtual void Execute(ZLogType _type, ZLogFile _file, const ZString& _logEntry) = 0;
|
||||
};
|
||||
|
||||
/*
|
||||
ZEngine logging class.
|
||||
*/
|
||||
class ZLog
|
||||
{
|
||||
private:
|
||||
//Mutex for logging system
|
||||
static ZMutex LogLock;
|
||||
|
||||
//Boolean indicating the logging system is activated
|
||||
static bool bIsInitialized;
|
||||
|
||||
//Array of logging output streams (second pair parameter indicates active / suspended)
|
||||
static ZArray< ZPair<std::ofstream*, bool> > LogFiles;
|
||||
|
||||
//Array of logging delegates
|
||||
static ZArray< ZPtr<ZLogDelegate> > Delegates;
|
||||
|
||||
//Root path for logging
|
||||
static ZString LogFileRoot;
|
||||
|
||||
//Maintained Tick Count
|
||||
static uint64_t *UserTick;
|
||||
|
||||
//Maintained Update Frame Count
|
||||
static uint64_t *UserUpdate;
|
||||
|
||||
//Tick Estimate when NULL is passed in as Tick
|
||||
static uint64_t TickEstimate;
|
||||
|
||||
//Update Frame estimate when NULL is passed in as Update tick
|
||||
static uint64_t UpdateFrameEstimate;
|
||||
|
||||
//Private Constructor
|
||||
ZLog() { }
|
||||
|
||||
//Private Copy Constructor
|
||||
ZLog(const ZLog& _other) { URFP(_other); }
|
||||
|
||||
//Private Destructor
|
||||
~ZLog() { }
|
||||
|
||||
public:
|
||||
|
||||
/////////////////////////////////
|
||||
/* Initialization and Shutdown */
|
||||
/////////////////////////////////
|
||||
|
||||
/*
|
||||
static public ZFileSystem::Init
|
||||
|
||||
Initialization method for ZLog. Until this is called, all logging calls return immediately.
|
||||
|
||||
@param _logFileRoot - the directory to place log files in
|
||||
@param _defaultLogFile - log file name for the 'default' log file (NULL log file)
|
||||
@param _ticks - pointer to a value that will be updated with tick count (NULL to use parameter value only)
|
||||
@param _update - pointer to a value that will be updated with update frame count (NULL to use parameter value only)
|
||||
@return (void)
|
||||
*/
|
||||
static void Init(const ZString& _logFileRoot, const ZString& _defaultLogFile, uint64_t* _ticks = NULL, uint64_t* _update = NULL);
|
||||
|
||||
/*
|
||||
static public ZFileSystem::Shutdown
|
||||
|
||||
Shutdown method for ZLog. Closes out the opened log files and flushes the output buffers. After
|
||||
this is called, all logging operations return immediately.
|
||||
|
||||
@return (void)
|
||||
*/
|
||||
static void Shutdown();
|
||||
|
||||
///////////////////////////////
|
||||
/* Logging System Operations */
|
||||
///////////////////////////////
|
||||
|
||||
/*
|
||||
static public ZFileSystem::AddLoggingDelegate
|
||||
|
||||
Adds a logging delegate to the system which is called whenever logging takes
|
||||
place.
|
||||
|
||||
@param _delegate - the logging delegate to call when logging takes place
|
||||
@return (void)
|
||||
*/
|
||||
static void AddLoggingDelegate(ZPtr<ZLogDelegate> _delegate);
|
||||
|
||||
/*
|
||||
static public ZFileSystem::CreateLogFile
|
||||
|
||||
Creates a log file for use in the system.
|
||||
|
||||
@param _fileName - the name to use for the log file
|
||||
@return (ZLOG_FILE) - the created log file (will be NULL if could not create)
|
||||
*/
|
||||
static ZLogFile CreateLogFile(const ZString& _fileName);
|
||||
|
||||
/*
|
||||
public static ZLog::Resume
|
||||
|
||||
Resumes logging operations on a given log file.
|
||||
|
||||
@param _logFile - the file to suspend logging operations on
|
||||
@return (void)
|
||||
*/
|
||||
static void Resume(ZLogFile _logFile);
|
||||
|
||||
/*
|
||||
public static ZLog::SuspendLogging
|
||||
|
||||
Suspends logging operations on a given log file.
|
||||
|
||||
@param _logFile - the file to suspend logging operations on
|
||||
@return (void)
|
||||
*/
|
||||
static void Suspend(ZLogFile _logFile);
|
||||
|
||||
/////////////////////
|
||||
/* Logging Methods */
|
||||
/////////////////////
|
||||
|
||||
/*
|
||||
static public ZFileSystem::Printf
|
||||
|
||||
Varardic logging function, which writes the given string out to the log file. This version takes varargs in the
|
||||
same way as printf. This logging function has a limit on the length of the output string of 4096 characters - excess
|
||||
characters will be truncated.
|
||||
|
||||
@param _type - the logging type
|
||||
@param _file - the file to write to (if ZLOG_DEFAULT, uses the default file)
|
||||
@param _ticks - the tick count at which the log file is written
|
||||
@param _updateFrame - the update 'frame' during which the log is written
|
||||
@param _str - the string to write to the log file
|
||||
@param ... - the variable arguments to provide to format _str
|
||||
@param args - parsed va_list
|
||||
@return (void)
|
||||
*/
|
||||
static void Printf(ZLogType _type, ZLogFile _file, uint64_t _ticks, uint32_t _updateFrame, const char *_function, const char *_str, ...);
|
||||
|
||||
/*
|
||||
static public ZFileSystem::WriteLine
|
||||
|
||||
Writes a string out to the given log file.
|
||||
|
||||
@param _type - the logging type
|
||||
@param _file - the file to write to (if ZLOG_DEFAULT, uses the default file)
|
||||
@param _ticks - the tick count at which the log file is written
|
||||
@param _updateFrame - the update 'frame' during which the log is written
|
||||
@param _renderFrame - the render 'frame' during which the log is written
|
||||
@param _str - the string to write to the log file
|
||||
@return (void)
|
||||
*/
|
||||
static void WriteLine(ZLogType _type, ZLogFile _file, uint64_t _ticks, uint32_t _updateFrame, const char* _str);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
91
Include/ZUtil/ZMutex.hpp
Normal file
91
Include/ZUtil/ZMutex.hpp
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
ZMutex.hpp
|
||||
Author: James Russell <jcrussell@762studios.com>
|
||||
|
||||
Purpose: RAII Wrapper for libsst-concurrency SST_Mutex objects.
|
||||
|
||||
Changelog
|
||||
2011/11/27 - creation (jcrussell)
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _ZMUTEX_H
|
||||
#define _ZMUTEX_H
|
||||
|
||||
#include <ZUtil/ZUtilBuild.hpp>
|
||||
|
||||
#include <SST/SST_Mutex.h>
|
||||
|
||||
/*
|
||||
ZMutex class. Used to allocate and deallocate a mutex within the scope of a class.
|
||||
Cannot be copied or assigned, which prevents it from being used in stl-like containers.
|
||||
*/
|
||||
class ZMutex
|
||||
{
|
||||
private:
|
||||
DISABLE_COPY_AND_ASSIGN(ZMutex);
|
||||
|
||||
//libsst Mutex
|
||||
SST_Mutex Mutex;
|
||||
|
||||
public:
|
||||
/*
|
||||
Constructor. Creates a mutex from libsst-concurrency.
|
||||
*/
|
||||
ZMutex();
|
||||
|
||||
/*
|
||||
Destructor. Frees our mutex from libsst-concurrency.
|
||||
*/
|
||||
~ZMutex();
|
||||
|
||||
/*
|
||||
public ZLock::Acquire
|
||||
|
||||
Acquires this lock, which locks the contained mutex.
|
||||
|
||||
@return (void)
|
||||
@context (all)
|
||||
*/
|
||||
void Acquire();
|
||||
|
||||
/*
|
||||
public ZLock::Release
|
||||
|
||||
Releases this lock, which unlocks the contained mutex.
|
||||
|
||||
@return (void)
|
||||
@context (all)
|
||||
*/
|
||||
void Release();
|
||||
};
|
||||
|
||||
/*
|
||||
Scoped lock. Acquires the provided lock so long as it remains in scope. Releases the lock when
|
||||
it goes out of scope.
|
||||
*/
|
||||
class ZLock
|
||||
{
|
||||
private:
|
||||
DISABLE_COPY_AND_ASSIGN(ZLock);
|
||||
|
||||
//The Mutex
|
||||
ZMutex& Mutex;
|
||||
|
||||
public:
|
||||
/*
|
||||
Constructor. Acquires the mutex during construction.
|
||||
|
||||
@param _mutex - the mutex we are to acquire
|
||||
*/
|
||||
ZLock(ZMutex& _lock);
|
||||
|
||||
/*
|
||||
Destructor. Releases the mutex when the object is destructed (goes out of scope).
|
||||
*/
|
||||
~ZLock();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
172
Include/ZUtil/ZName.hpp
Normal file
172
Include/ZUtil/ZName.hpp
Normal file
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
ZName.hpp
|
||||
Author: James Russell <jcrussell@762studios.com>
|
||||
Created: 4/6/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
'Name' implementation, which is a bit like a ZBasicString but remains constant after
|
||||
construction. This allows for fast comparison and copy.
|
||||
|
||||
In addition this allows the name to be compared to a hash of the name and determine equality.
|
||||
|
||||
License:
|
||||
|
||||
TODO
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _ZNAME_H
|
||||
#define _ZNAME_H
|
||||
|
||||
#include <ZSTL/ZString.hpp>
|
||||
|
||||
#include <ZUtil/ZUtilBuild.hpp>
|
||||
|
||||
//This is the maximum allowed length of a name
|
||||
#ifndef ZNAME_MAX_LENGTH
|
||||
#define ZNAME_MAX_LENGTH (128)
|
||||
#endif
|
||||
|
||||
/*
|
||||
ZName Implementation.
|
||||
*/
|
||||
class ZName
|
||||
{
|
||||
private:
|
||||
//The string
|
||||
char String[ZNAME_MAX_LENGTH + 1];
|
||||
|
||||
//Length of the string
|
||||
size_t Length;
|
||||
|
||||
//Hash of the string
|
||||
uint64_t Hash;
|
||||
|
||||
public:
|
||||
/*
|
||||
Constructor.
|
||||
*/
|
||||
ZName();
|
||||
|
||||
/*
|
||||
Parameterized constructor.
|
||||
|
||||
@param _string - the string name (null terminated)
|
||||
*/
|
||||
ZName(const char *_string);
|
||||
|
||||
/*
|
||||
Parameterized constructor.
|
||||
|
||||
@param _string - the string name
|
||||
*/
|
||||
explicit ZName(const ZString& _string);
|
||||
|
||||
/*
|
||||
Parameterized constructor that takes the pre-computed hash value
|
||||
for the name. When a ZName is constructed in this fashion, the
|
||||
ToString() function will return '<precomputed>'.
|
||||
|
||||
@param _hash - the precomputed hash value for this string
|
||||
*/
|
||||
ZName(uint64_t _hash);
|
||||
|
||||
/*
|
||||
Copy Constructor.
|
||||
|
||||
@param _other - the other name
|
||||
*/
|
||||
ZName(const ZName& _other);
|
||||
|
||||
/*
|
||||
Destructor.
|
||||
*/
|
||||
~ZName();
|
||||
|
||||
/*
|
||||
= operator overload, that assigns this name to be another.
|
||||
|
||||
@param _other - the name to assign this to
|
||||
@return - this name
|
||||
*/
|
||||
ZName& operator = (const ZName& _other);
|
||||
|
||||
/*
|
||||
= operator overload, that assigns this name to be a string.
|
||||
|
||||
@param _string - the string to create this name from
|
||||
@return - this name
|
||||
*/
|
||||
ZName& operator = (const ZString& _string);
|
||||
|
||||
/*
|
||||
= operator overload, that assigns this name to be equal to a C-style string.
|
||||
|
||||
@param _string - the string to create this name from
|
||||
@return - this name
|
||||
*/
|
||||
ZName& operator = (const char* _string);
|
||||
|
||||
/*
|
||||
== operator. Because names are constant, this is a fast comparison.
|
||||
|
||||
@param _other - the name to compare this to
|
||||
@return - true if equal, false otherwise
|
||||
*/
|
||||
bool operator == (const ZName& _other) const;
|
||||
|
||||
/*
|
||||
== operator for comparison with strings. Less fast.
|
||||
|
||||
@param _other - the string to compare this to
|
||||
@return - true if equal, false otherwise
|
||||
*/
|
||||
bool operator == (const ZString& _other) const;
|
||||
|
||||
/*
|
||||
== operator. Compares a name against hash value only.
|
||||
|
||||
@param hash - the hash value to compare
|
||||
@return - true if equivalent hashes, false otherwise
|
||||
*/
|
||||
bool operator == (const ZHashValue hash) const;
|
||||
|
||||
/*
|
||||
!= operator. Because names are constant, this is a fast comparison.
|
||||
|
||||
@param _other - the name to compare this to
|
||||
@return (bool) - true if not equal, false otherwise
|
||||
*/
|
||||
bool operator != (const ZName& _other) const;
|
||||
|
||||
/*
|
||||
Hash code override. Returns the (pre-computed) hash code.
|
||||
|
||||
@return - hash code for this name
|
||||
*/
|
||||
operator ZHashValue () const;
|
||||
|
||||
/*
|
||||
Returns this name as a string.
|
||||
|
||||
@return (ZString) - this name as a ZString
|
||||
*/
|
||||
operator ZString () const;
|
||||
|
||||
/*
|
||||
Gets this name as a string.
|
||||
|
||||
@return (ZString) - this name as a ZString
|
||||
*/
|
||||
ZString ToString() const;
|
||||
|
||||
/*
|
||||
Returns the string data for this name.
|
||||
|
||||
@return (char*) - string data
|
||||
*/
|
||||
const char* Data() const;
|
||||
};
|
||||
|
||||
#endif
|
||||
79
Include/ZUtil/ZNoise.hpp
Normal file
79
Include/ZUtil/ZNoise.hpp
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
ZNoise.hpp
|
||||
Author : Chris Ertel
|
||||
|
||||
Purpose : Interface class to call noise generation functions.
|
||||
|
||||
Changelog
|
||||
2/13/11 - Creation (crertel)
|
||||
*/
|
||||
|
||||
#ifndef _ZNOISE_H
|
||||
#define _ZNOISE_H
|
||||
|
||||
#include <ZUtil/ZUtilBuild.hpp>
|
||||
|
||||
class ZNoise
|
||||
{
|
||||
public:
|
||||
virtual ~ZNoise() {}
|
||||
|
||||
/*
|
||||
virtual public ZNoise::reseed
|
||||
|
||||
Function to set seed for the noise generator.
|
||||
|
||||
@param _seed - int to seed the noise with.
|
||||
@return (void)
|
||||
*/
|
||||
virtual void reseed (const int _seed) = 0;
|
||||
|
||||
/*
|
||||
virtual public ZNoise::noise1
|
||||
|
||||
Function for getting 1D noise.
|
||||
|
||||
@param _x - float x coord
|
||||
@return (float) - value of noise at x
|
||||
*/
|
||||
virtual float noise1(const float _x) = 0;
|
||||
|
||||
/*
|
||||
virtual public ZNoise::noise2
|
||||
|
||||
Function for getting 2D noise.
|
||||
|
||||
@param _x - float x coord
|
||||
@param _y - float y coord
|
||||
@return (float) - value of noise at (x,y)
|
||||
*/
|
||||
virtual float noise2(const float _x, const float _y) = 0;
|
||||
|
||||
/*
|
||||
virtual public ZNoise::noise3
|
||||
|
||||
Function for getting 3D noise.
|
||||
|
||||
@param _x - float x coord
|
||||
@param _y - float y coord
|
||||
@param _z - float z coord
|
||||
@return (float) - value of noise at (x,y,z)
|
||||
*/
|
||||
virtual float noise3(const float _x, const float _y, const float _z) = 0;
|
||||
|
||||
/*
|
||||
virtual public ZNoise::noise4
|
||||
|
||||
Function for getting 4D noise.
|
||||
|
||||
@param _x - float x coord
|
||||
@param _y - float y coord
|
||||
@param _z - float z coord
|
||||
@param _w - float w coord
|
||||
@return (float) - value of noise at (x,y,z,w)
|
||||
*/
|
||||
virtual float noise4(const float _x, const float _y, const float _z, const float _w) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
185
Include/ZUtil/ZNoiseMap.hpp
Normal file
185
Include/ZUtil/ZNoiseMap.hpp
Normal file
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
ZNoiseMap.hpp
|
||||
Author : Chris Ertel
|
||||
|
||||
Purpose : Interface to create a map for noise values.
|
||||
|
||||
Changelog
|
||||
2/13/11 - Creation (crertel)
|
||||
2/20/11 - Changed interface to be useful. (crertel)
|
||||
*/
|
||||
|
||||
#ifndef _ZNOISEMAP_H
|
||||
#define _ZNOISEMAP_H
|
||||
|
||||
#include <ZUtil/ZSimplexNoise.hpp>
|
||||
|
||||
class ZNoiseMap
|
||||
{
|
||||
public:
|
||||
virtual ~ZNoiseMap() {}
|
||||
|
||||
/*
|
||||
virtual public ZNoiseMap::GetDimensionality
|
||||
|
||||
Gets dimension of noise map (1,2,etc.).
|
||||
|
||||
@return (int) - dimension of noise map
|
||||
*/
|
||||
virtual int GetDimensionality() = 0;
|
||||
|
||||
/*
|
||||
virtual public ZNoiseMap::GetLacunarity
|
||||
|
||||
Get lacunarity (scaling of successive frequencies in noise series).
|
||||
|
||||
@return (float) - lacunarity of noise map
|
||||
*/
|
||||
virtual float GetLacunarity() = 0; // scaling of successive frequencies in noise octaves
|
||||
|
||||
/*
|
||||
virtual public ZNoiseMap::GetPersistence
|
||||
|
||||
Get persistence (scaling of successive amplitudes in noise series).
|
||||
|
||||
@return (float)
|
||||
*/
|
||||
virtual float GetPersistence() = 0; // scaling of successive amplitudes in noise octaves
|
||||
|
||||
|
||||
/*
|
||||
virtual public ZNoiseMap::GetNumberOfOctaves
|
||||
|
||||
Get number of octaves in noise series.
|
||||
|
||||
@return (int) - number of terms in noise series.
|
||||
*/
|
||||
virtual int GetNumberOfOctaves() = 0;
|
||||
|
||||
/*
|
||||
virtual public ZNoiseMap::GetNumberSamplesInX
|
||||
|
||||
Get number of samples in X dimensions of noise map.
|
||||
|
||||
@return (int) - number of samples in X.
|
||||
*/
|
||||
virtual int GetNumberSamplesInX() = 0;
|
||||
|
||||
/*
|
||||
virtual public ZNoiseMap::GetNumberSamplesInY
|
||||
|
||||
Get number of samples in Y dimensions of noise map.
|
||||
|
||||
@return (int) - number of samples in Y.
|
||||
*/
|
||||
virtual int GetNumberSamplesInY() = 0;
|
||||
|
||||
/*
|
||||
virtual public ZNoiseMap::GetNumberSamplesInZ
|
||||
|
||||
Get number of samples in Z dimensions of noise map.
|
||||
|
||||
@return (int) - number of samples in Z.
|
||||
*/
|
||||
virtual int GetNumberSamplesInZ() = 0;
|
||||
|
||||
/*
|
||||
virtual public ZNoiseMap::GetNumberSamplesInW
|
||||
|
||||
Get number of samples in Z dimensions of noise map.
|
||||
|
||||
@return (int) - number of samples in W.
|
||||
*/
|
||||
virtual int GetNumberSamplesInW() = 0;
|
||||
|
||||
/*
|
||||
virtual public ZNoiseMap::SetLacunarity
|
||||
|
||||
Sets the lacunarity (scaling of successive frequencies in noise series).
|
||||
|
||||
@param _lac - lacunarity to use.
|
||||
@return (void)
|
||||
*/
|
||||
virtual void SetLacunarity(float _lac) = 0; // scaling of successive frequencies in noise octaves
|
||||
|
||||
/*
|
||||
virtual public ZNoiseMap::SetPersistence
|
||||
|
||||
Sets the persistence (scaling of successive amplitudes in noise series).
|
||||
|
||||
@param _per - persistence to set noise map to.
|
||||
@return (void)
|
||||
*/
|
||||
virtual void SetPersistence(float _per) = 0; // scaling of successive amplitudes in noise octaves
|
||||
|
||||
/*
|
||||
virtual public ZNoiseMap::SetNumberOfOctaves
|
||||
|
||||
Set number of octave in noise series.
|
||||
|
||||
@param _numOctaves - number of octaves to use.
|
||||
@return (void)
|
||||
*/
|
||||
virtual void SetNumberOfOctaves(int _numOctaves ) = 0;
|
||||
|
||||
/*
|
||||
virtual public ZNoiseMap::SetNumberSamplesInX
|
||||
|
||||
Sets number of samples in X direction.
|
||||
|
||||
@param _numSamples - number of samples in X direction.
|
||||
@return (void)
|
||||
*/
|
||||
virtual void SetNumberSamplesInX(int _numSamples) = 0;
|
||||
|
||||
/*
|
||||
virtual public ZNoiseMap::SetNumberSamplesInY
|
||||
|
||||
Sets number of samples in Y direction.
|
||||
|
||||
@param _numSamples - number of samples in Y direction.
|
||||
@return (void)
|
||||
*/
|
||||
virtual void SetNumberSamplesInY(int _numSamples) = 0;
|
||||
|
||||
/*
|
||||
virtual public ZNoiseMap::SetNumberSamplesInZ
|
||||
|
||||
Sets number of samples in Z direction.
|
||||
|
||||
@param _numSamples - number of samples in Z direction.
|
||||
@return (void)
|
||||
*/
|
||||
virtual void SetNumberSamplesInZ(int _numSamples) = 0;
|
||||
|
||||
/*
|
||||
virtual public ZNoiseMap::SetNumberSamplesInW
|
||||
|
||||
Sets number of samples in W direction.
|
||||
|
||||
@param _numSamples - number of samples in W direction.
|
||||
@return (void)
|
||||
*/
|
||||
virtual void SetNumberSamplesInW(int _numSamples) = 0;
|
||||
|
||||
/*
|
||||
virtual public ZNoiseMap::Generate
|
||||
|
||||
Generates noise map values.
|
||||
|
||||
@return (bool) - True if successful, false otherwise.
|
||||
*/
|
||||
virtual bool Generate(int _seed) = 0;
|
||||
|
||||
/*
|
||||
virtual public ZNoiseMap::Cleanup
|
||||
|
||||
Cleans up resources for noise map.
|
||||
|
||||
@return (void)
|
||||
*/
|
||||
virtual void Cleanup() = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
245
Include/ZUtil/ZRandomGenerator.hpp
Normal file
245
Include/ZUtil/ZRandomGenerator.hpp
Normal file
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
ZRandomGeneratorBase.hpp
|
||||
Author: James Russell <jcrussell@762studios.com>
|
||||
|
||||
Purpose:
|
||||
|
||||
This is an RAII wrapper class for the libsst-random pseudo-random number generators that
|
||||
also introduces some extra functionality.
|
||||
|
||||
License:
|
||||
|
||||
TODO
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _ZRANDOMGENERATOR_H
|
||||
#define _ZRANDOMGENERATOR_H
|
||||
|
||||
#include <ZUtil/ZUtilBuild.hpp>
|
||||
|
||||
#include <SST/SST_PRNG.h>
|
||||
|
||||
class ZRandomGenerator
|
||||
{
|
||||
private:
|
||||
DISABLE_COPY_AND_ASSIGN(ZRandomGenerator);
|
||||
|
||||
protected:
|
||||
//Our random generator type
|
||||
const SST_PRNG_TYPE Type;
|
||||
|
||||
//Random Seed
|
||||
uint32_t Seed;
|
||||
|
||||
//Random Sequence
|
||||
uint64_t Sequence;
|
||||
|
||||
//Our SST RNG Instance
|
||||
SST_PRNG RNG;
|
||||
|
||||
public:
|
||||
/*
|
||||
Default Constructor.
|
||||
|
||||
This constructor will create a random generator that uses type SST_PRNG_SMALLPRNG,
|
||||
that is seeded with the current time, and starts at sequence 0.
|
||||
*/
|
||||
ZRandomGenerator();
|
||||
|
||||
/*
|
||||
Parameterized Constructor.
|
||||
|
||||
@param _type - the type of random number generator to create
|
||||
@param _seed - the seed to create the generator with
|
||||
@param _sequence - the sequence number to start at
|
||||
*/
|
||||
ZRandomGenerator(SST_PRNG_TYPE _type, uint32_t _seed, uint64_t _sequence = 0);
|
||||
|
||||
/*
|
||||
Destructor.
|
||||
*/
|
||||
~ZRandomGenerator();
|
||||
|
||||
/*
|
||||
public ZRandomGenerator::GetFloat
|
||||
|
||||
Gets next float from random generator in the range [0, 1).
|
||||
|
||||
@return (float) - next float from the PRNG
|
||||
*/
|
||||
float GetFloat();
|
||||
|
||||
/*
|
||||
public ZRandomGenerator::GetFloatArray
|
||||
|
||||
Gets an array of floats from the random generator in the range [0, 1).
|
||||
|
||||
@param _array - array to store floats into
|
||||
@param _count - number of elements in array
|
||||
@return (void)
|
||||
*/
|
||||
void GetFloatArray(float *_array, size_t _count);
|
||||
|
||||
/*
|
||||
public ZRandomGenerator::GetFloatInRange
|
||||
|
||||
Gets a float in the range [_min, _max)
|
||||
|
||||
@param _min - inclusive lower bound of range.
|
||||
@param _max - exclusive upper bound of range.
|
||||
@return (float) - next float in range.
|
||||
*/
|
||||
float GetFloatInRange(float _min, float _max);
|
||||
|
||||
/*
|
||||
public ZRandomGenerator::GetFloatArrayInRange
|
||||
|
||||
Gets an array of floats in range [_min, _max).
|
||||
|
||||
@param _array - array to store floats into
|
||||
@param _count - number of elements in array
|
||||
@param _min - inclusive lower bound of range
|
||||
@param _max - exclusive upper bound of range
|
||||
@return (void)
|
||||
*/
|
||||
void GetFloatArrayInRange(float *_array, size_t _count, float _min, float _max);
|
||||
|
||||
/*
|
||||
public ZRandomGeneratorGenerator::GetInt
|
||||
|
||||
Gets an int in the range [STDINT_MIN, STDINT_MAX).
|
||||
|
||||
@return (int) - next int from generator
|
||||
*/
|
||||
int GetInt();
|
||||
|
||||
/*
|
||||
public ZRandomGenerator::GetIntArray
|
||||
|
||||
Gets an array of ints in the range [STDINT_MIN, STDINT_MAX).
|
||||
|
||||
@param _array - array to store ints into
|
||||
@param _count - number of elements in
|
||||
@return (void)
|
||||
*/
|
||||
void GetIntArray(int *_array, size_t _count);
|
||||
|
||||
/*
|
||||
public ZRandomGenerator::GetIntInRange
|
||||
|
||||
Gets an int in the range [_min, _max).
|
||||
|
||||
@param _min - inclusive lower bound of range
|
||||
@param _max - exclusive upper bound of range
|
||||
@return (int) - next int from range
|
||||
*/
|
||||
int GetIntInRange(int _min, int _max);
|
||||
|
||||
/*
|
||||
public ZRandomGenerator::GetIntArrayInRange
|
||||
|
||||
Gets an array of ints in the range [_min, _max).
|
||||
|
||||
@param _array - array to store floats into
|
||||
@param _count - number of elements in array
|
||||
@param _min - inclusive lower bound of range
|
||||
@param _max - exclusive upper bound of range
|
||||
@return (void)
|
||||
*/
|
||||
void GetIntArrayInRange( int *_array, size_t _count, int _min, int _max);
|
||||
|
||||
/*
|
||||
public ZRandomGenerator::GetGaussianFloat
|
||||
|
||||
Gets a gaussian-distributed float in the range [_min, _max). This is expected to generate
|
||||
two random numbers to get the gaussian distributed number, which will increase sequence by two.
|
||||
|
||||
@param _min - inclusive lower bound of range
|
||||
@param _max - exclusive upper bound of range
|
||||
@return (float) - floating point number in range
|
||||
*/
|
||||
float GetGaussianFloat(float _min, float _max);
|
||||
|
||||
/*
|
||||
public ZRandomGenerator::GetGaussianFloatArray
|
||||
|
||||
Gets an array of guassian-distributed floats in the range [_min, _max). This is expected to generate
|
||||
two random numbers to get the gaussian distributed number, which will increase sequence by two.
|
||||
|
||||
@param _array - array to store floats into
|
||||
@param _count - number of elements in array
|
||||
@param _min - inclusive lower bound of range
|
||||
@param _max - exclusive upper bound of range
|
||||
@return (void)
|
||||
*/
|
||||
void GetGaussianFloatArray(float *_array, size_t _count, float _min, float _max);
|
||||
|
||||
/*
|
||||
public ZRandomGenerator::GetGaussianInt
|
||||
|
||||
Gets a gaussian-distributed int in the range [_min, _max). This is expected to generate
|
||||
two random numbers to get the gaussian distributed number, which will increase sequence by two.
|
||||
|
||||
@param _min - inclusive lower bound of range
|
||||
@param _max - exclusive upper bound of range
|
||||
@return (int)
|
||||
*/
|
||||
int GetGaussianInt(int _min, int _max);
|
||||
|
||||
/*
|
||||
public ZRandomGenerator::GetGaussianIntArray
|
||||
|
||||
Gets an array of gaussian-distributed int in the range [_min, _max). This is expected to generate
|
||||
two random numbers to get the gaussian distributed number, which will increase sequence by two.
|
||||
|
||||
@param _array - array to store ints into
|
||||
@param _count - number of elements in array
|
||||
@param _min - inclusive lower bound of range
|
||||
@param _max - exclusive upper bound of range
|
||||
@return (void)
|
||||
*/
|
||||
void GetGaussianIntArray(int *_array, size_t _count, int _min, int _max);
|
||||
|
||||
/*
|
||||
public ZRandomGenerator::GetSeed
|
||||
|
||||
Gets the seed of this random generator.
|
||||
|
||||
@return (uint32_t) - PRNG seed
|
||||
*/
|
||||
uint32_t GetSeed();
|
||||
|
||||
/*
|
||||
public ZRandomGenerator::GetSequence
|
||||
|
||||
Gets the sequence of this random number generator, which is the number of random
|
||||
numbers that have currently been generated.
|
||||
|
||||
@return (uint64_t) - sequence of this random generator
|
||||
*/
|
||||
uint64_t GetSequence();
|
||||
|
||||
/*
|
||||
public ZRandomGenerator::SetSequence
|
||||
|
||||
Sets the sequence (amount of numbers generated) for this PRNG.
|
||||
|
||||
@param _seq - sequence to set this generator to.
|
||||
@return (void)
|
||||
*/
|
||||
void SetSequence(uint64_t _seq);
|
||||
|
||||
/*
|
||||
public ZRandomGenerator::SetSeed
|
||||
|
||||
Sets the seed on this PRNG.
|
||||
|
||||
@param _seed - 32 bit unsigned integer seed to use
|
||||
@return (void)
|
||||
*/
|
||||
void SetSeed(uint32_t _seed);
|
||||
};
|
||||
|
||||
#endif
|
||||
84
Include/ZUtil/ZReadWriteLock.hpp
Normal file
84
Include/ZUtil/ZReadWriteLock.hpp
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
ZReadWriteLock.hpp
|
||||
Author: James Russell <jcrussell@762studios.com>
|
||||
Created: 5/17/2012
|
||||
|
||||
Purpose:
|
||||
|
||||
RAII wrapper for SST_ReadWriteLock from libsst-concurrency.
|
||||
|
||||
License:
|
||||
|
||||
TODO
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _ZREADWRITELOCK_HPP
|
||||
#define _ZREADWRITELOCK_HPP
|
||||
|
||||
#include <SST/SST_ReadWriteLock.h>
|
||||
|
||||
#include <ZUtil/ZUtilBuild.hpp>
|
||||
|
||||
class ZReadWriteLock
|
||||
{
|
||||
private:
|
||||
DISABLE_COPY_AND_ASSIGN(ZReadWriteLock);
|
||||
|
||||
//The SST_ReadWriteLock
|
||||
SST_ReadWriteLock Lock;
|
||||
|
||||
public:
|
||||
/*
|
||||
Default Constructor.
|
||||
*/
|
||||
ZReadWriteLock();
|
||||
|
||||
/*
|
||||
Destructor.
|
||||
*/
|
||||
~ZReadWriteLock();
|
||||
|
||||
/*
|
||||
public LockForReading
|
||||
|
||||
Locks this read write lock for reading. Blocks until the lock is obtained.
|
||||
|
||||
@param ticks - the maximum amount of time to block
|
||||
@return (bool) - true if the lock was obtained, false otherwise
|
||||
*/
|
||||
bool LockForReading(uint32_t ticks) const;
|
||||
|
||||
/*
|
||||
public LockForWriting
|
||||
|
||||
Locks this read write lock for writing. Blocks until the lock is obtained.
|
||||
|
||||
@param ticks - the maximum amount of time to block
|
||||
@return (bool) - true if the lock was obtained, false otherwise
|
||||
*/
|
||||
bool LockForWriting(uint32_t ticks);
|
||||
|
||||
/*
|
||||
public EndReading
|
||||
|
||||
Signals that a read operation has completed.
|
||||
|
||||
@return (void)
|
||||
*/
|
||||
void EndReading() const;
|
||||
|
||||
/*
|
||||
public EndWriting
|
||||
|
||||
Signals that a write operation has completed.
|
||||
|
||||
@return (void)
|
||||
*/
|
||||
void EndWriting();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
399
Include/ZUtil/ZReferenceBuffer.hpp
Normal file
399
Include/ZUtil/ZReferenceBuffer.hpp
Normal file
@@ -0,0 +1,399 @@
|
||||
/*
|
||||
ZReferenceBuffer.hpp
|
||||
Author: James Russell
|
||||
|
||||
Purpose : Acts as a means of storing arbitrary types of values in an array which gives back index-based references to
|
||||
pointers of those types of values. Handles, internally, the Buffer overflowing and looping back around
|
||||
the end of the storage array.
|
||||
|
||||
Changelog :
|
||||
2/11/10 - Creation (jcr2)
|
||||
2/13/10 - Should be working as advertised (jcr)
|
||||
3/04/10 - NOW working as advertised (jcr)
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _ZREFERENCEBUFFER_H
|
||||
#define _ZREFERENCEBUFFER_H
|
||||
|
||||
#include <ZUtil/ZAlloc.hpp>
|
||||
#include <ZUtil/ZAssert.hpp>
|
||||
#include <ZSTL/ZArray.hpp>
|
||||
#include <ZSTL/ZList.hpp>
|
||||
|
||||
#define ZRB_DEFAULT_BUFFER_SIZE (10)
|
||||
#define ZRB_INVALID_HANDLE (-1)
|
||||
|
||||
typedef int ZReferenceBufferHandle;
|
||||
|
||||
template <typename T>
|
||||
class ZReferenceBuffer
|
||||
{
|
||||
protected:
|
||||
//The Current Index Value (next value to be assigned)
|
||||
int CurrentIndex;
|
||||
|
||||
//The Current Size of the Buffer (Storage Capacity)
|
||||
int BufferSize;
|
||||
|
||||
//The Current Number of Items contained in the Buffer
|
||||
int ItemCount;
|
||||
|
||||
//Indicator array used to indicate which indices of the Buffer are valid
|
||||
ZArray<int> Indicator;
|
||||
|
||||
//Buffer of T* Values
|
||||
ZArray<T*> Buffer;
|
||||
|
||||
//Checks if a given reference is valid
|
||||
inline bool IsValid(int index);
|
||||
|
||||
//Checks if a given reference is invalid
|
||||
inline bool IsInvalid(int index);
|
||||
|
||||
//Sets the Indicator of an index to valid
|
||||
inline void SetValid(int index);
|
||||
|
||||
//Sets the Indicator of an index to invalid
|
||||
inline void SetInvalid(int index);
|
||||
|
||||
public:
|
||||
|
||||
/*
|
||||
Default constructor.
|
||||
*/
|
||||
ZReferenceBuffer();
|
||||
|
||||
/*
|
||||
Constructor.
|
||||
|
||||
@param _size - The starting size of the reference buffer.
|
||||
*/
|
||||
ZReferenceBuffer(int _size);
|
||||
|
||||
/*
|
||||
Constructor.
|
||||
|
||||
@param _allocator - the allocator to use for allocations / deallocations in the reference buffer
|
||||
*/
|
||||
ZReferenceBuffer(ZArrayAllocator<T> *_allocator);
|
||||
|
||||
/*
|
||||
Constructor.
|
||||
|
||||
@param _size - The starting size of the reference buffer.
|
||||
@param _allocator - the allocator to use for allocations / deallocations in the reference buffer
|
||||
*/
|
||||
ZReferenceBuffer( int _size, ZArrayAllocator<T> *_allocator);
|
||||
|
||||
/*
|
||||
Destructor.
|
||||
*/
|
||||
~ZReferenceBuffer();
|
||||
|
||||
/*
|
||||
public ZReferenceBuffer::AddItem
|
||||
|
||||
Adds the item to the reference Buffer, returning a handle. Resizes the Buffer automatically to
|
||||
increase the size of the buffer if full.
|
||||
|
||||
@param _item - the item to add to the buffer
|
||||
|
||||
@return (ZReferenceBufferHandle) - a ZReferenceBufferHandle which can be used to reference item, Will never return NULL.
|
||||
*/
|
||||
ZReferenceBufferHandle AddItem(T _item);
|
||||
|
||||
/*
|
||||
public ZReferenceBuffer::GetItem
|
||||
|
||||
Gets an item in the Buffer given a reference handle.
|
||||
|
||||
@param _ref - the reference handle to the item you wish to get
|
||||
|
||||
@return (T&) - the item the handle refers to
|
||||
*/
|
||||
T& GetItem(ZReferenceBufferHandle _ref);
|
||||
|
||||
/*
|
||||
public ZReferenceBuffer::SetItem
|
||||
|
||||
Attempts to set the reference to map to the provided item. Used for updating references.
|
||||
|
||||
@param _ref - a valid reference handle to update. If NULL, will set the null handle, allowing a NULL reference to be valid.
|
||||
@param _item - the item to update the reference to
|
||||
|
||||
@return (T) - the overwritten value that ref pointed to
|
||||
*/
|
||||
T SetItem(ZReferenceBufferHandle _ref, T _item);
|
||||
|
||||
/*
|
||||
public ZReferenceBuffer::RemoveItem
|
||||
|
||||
Removes an item from the Buffer given a reference handle and invalidates the handle (until reassigned).
|
||||
|
||||
@param _ref - the reference handle to the item you wish to remove
|
||||
|
||||
@return (T) - the item removed
|
||||
*/
|
||||
T RemoveItem(ZReferenceBufferHandle _ref);
|
||||
|
||||
/*
|
||||
public ZReferenceBuffer::Remove
|
||||
|
||||
Removes all occurrences of an item from the Buffer given a pointer to the item.
|
||||
|
||||
@param _item - the item you wish to remove
|
||||
|
||||
@return (void)
|
||||
*/
|
||||
void Remove(T _item);
|
||||
|
||||
/*
|
||||
public ZReferenceBuffer::Size
|
||||
|
||||
Gets the current size of the buffer.
|
||||
|
||||
@return (int) - the size (capacity) of the buffer
|
||||
*/
|
||||
int Size();
|
||||
|
||||
/*
|
||||
public ZReferenceBuffer::Count
|
||||
|
||||
Returns the number of elements currently stored in the Buffer
|
||||
|
||||
@return (int) - the count (number of items) in the buffer
|
||||
*/
|
||||
int Count();
|
||||
|
||||
/*
|
||||
public ZReferenceBuffer::Items
|
||||
|
||||
Returns a ZList containing the elements of the reference Buffer.
|
||||
|
||||
@return (ZList<T>) - a list containing all the values currently in the buffer
|
||||
*/
|
||||
ZList<T> Items();
|
||||
|
||||
/*
|
||||
inline public ZReferenceBuffer::IsFull
|
||||
|
||||
Returns true if the Buffer is full, false otherwise.
|
||||
|
||||
@return (bool) - boolean indicating the buffer is full
|
||||
*/
|
||||
inline bool IsFull();
|
||||
|
||||
/*
|
||||
public ZReferenceBuffer::Resize
|
||||
|
||||
Resizes the Buffer to store _newSize number of elements. Already existing references remain valid. Returns true
|
||||
on success, false otherwise. Newsize must be greater than the current size of the reference Buffer.
|
||||
|
||||
@param _newSize - the ZNew capacity of the buffer
|
||||
|
||||
@return (bool) - boolean indicating success or failure
|
||||
*/
|
||||
bool Resize( int _newSize);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
ZReferenceBuffer<T>::ZReferenceBuffer( int _size, ZArrayAllocator<T>* _allocator)
|
||||
: CurrentIndex(1), BufferSize(_size+1), ItemCount(0), Allocator(_allocator)
|
||||
{
|
||||
this->Buffer.Resize(BufferSize);
|
||||
this->Indicator.Resize(this->BufferSize, false);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
ZReferenceBuffer<T>::ZReferenceBuffer( int _size)
|
||||
: CurrentIndex(1), BufferSize(_size+1), ItemCount(0)
|
||||
{
|
||||
this->Buffer.Resize(BufferSize);
|
||||
this->Indicator.Resize(this->BufferSize, false);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
ZReferenceBuffer<T>::ZReferenceBuffer(ZArrayAllocator<T>* _allocator)
|
||||
: CurrentIndex(1), BufferSize(ZRB_DEFAULT_BUFFER_SIZE+1), ItemCount(0), Allocator(_allocator)
|
||||
{
|
||||
this->Buffer.Resize(BufferSize);
|
||||
this->Indicator.Resize(this->BufferSize, false);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
ZReferenceBuffer<T>::ZReferenceBuffer()
|
||||
: CurrentIndex(1), BufferSize(ZRB_DEFAULT_BUFFER_SIZE+1), ItemCount(0)
|
||||
{
|
||||
this->Buffer.Resize(BufferSize);
|
||||
this->Indicator.Resize(this->BufferSize, false);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
ZReferenceBuffer<T>::~ZReferenceBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool ZReferenceBuffer<T>::IsValid(int _index)
|
||||
{
|
||||
if (_index >= 0)
|
||||
return this->Indicator[_index] != 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool ZReferenceBuffer<T>::IsInvalid(int _index)
|
||||
{
|
||||
return !IsValid(_index);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ZReferenceBuffer<T>::SetValid( int _index)
|
||||
{
|
||||
this->Indicator[_index] = 1;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ZReferenceBuffer<T>::SetInvalid( int _index)
|
||||
{
|
||||
this->Indicator[_index] = 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
ZReferenceBufferHandle ZReferenceBuffer<T>::AddItem(T _item)
|
||||
{
|
||||
int startIndex;
|
||||
int ref;
|
||||
|
||||
//CurrentIndex should only be zero if Buffer is full
|
||||
if (this->CurrentIndex == 0)
|
||||
return this->CurrentIndex;
|
||||
|
||||
ref = startIndex = this->CurrentIndex;
|
||||
|
||||
while (this->IsValid(this->CurrentIndex))
|
||||
{
|
||||
this->CurrentIndex++;
|
||||
ref = this->CurrentIndex;
|
||||
|
||||
if (this->CurrentIndex == startIndex)
|
||||
this->Resize(this->BufferSize * 2);
|
||||
|
||||
if (this->CurrentIndex >= this->BufferSize)
|
||||
ref = this->CurrentIndex = 1;
|
||||
}
|
||||
|
||||
if (ref != -1)
|
||||
{
|
||||
this->Buffer[ref] = _item;
|
||||
this->SetValid(ref);
|
||||
|
||||
this->ItemCount++;
|
||||
}
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T& ZReferenceBuffer<T>::GetItem(ZReferenceBufferHandle _ref)
|
||||
{
|
||||
ZASSERT(this->IsValid(_ref), "ERROR: ZReferenceBuffer::GetItemRef passed invalid reference!");
|
||||
|
||||
return this->Buffer[_ref];
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T ZReferenceBuffer<T>::RemoveItem(ZReferenceBufferHandle _ref)
|
||||
{
|
||||
T item;
|
||||
|
||||
ZASSERT( this->IsValid(_ref) , "ERROR: ZReferenceBuffer::RemoveItem passed invalid reference!" );
|
||||
|
||||
this->ItemCount--;
|
||||
this->SetInvalid(_ref);
|
||||
item = this->Buffer[_ref];
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ZReferenceBuffer<T>::Remove(T _item)
|
||||
{
|
||||
for ( int i = 0; i < this->BufferSize; i++)
|
||||
if (this->Buffer[i] == _item)
|
||||
this->RemoveItem(i);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T ZReferenceBuffer<T>::SetItem(int _ref, T _item)
|
||||
{
|
||||
T ret;
|
||||
|
||||
ret = this->Buffer[_ref];
|
||||
this->Buffer[_ref] = _item;
|
||||
|
||||
this->SetValid(_ref);
|
||||
|
||||
this->ItemCount++;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int ZReferenceBuffer<T>::Size()
|
||||
{
|
||||
return this->BufferSize;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int ZReferenceBuffer<T>::Count()
|
||||
{
|
||||
return this->ItemCount;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool ZReferenceBuffer<T>::IsFull()
|
||||
{
|
||||
return (!this->CurrentIndex);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool ZReferenceBuffer<T>::Resize( int _newSize)
|
||||
{
|
||||
if (_newSize < this->BufferSize)
|
||||
return false;
|
||||
|
||||
this->BufferSize = _newSize + 1;
|
||||
|
||||
ZArray<T*> newBuffer;
|
||||
newBuffer.Resize(this->BufferSize);
|
||||
|
||||
for ( int i = 0; i < this->BufferSize; i++)
|
||||
newBuffer[i] = this->Buffer[i];
|
||||
|
||||
this->Indicator.Resize(this->BufferSize, false);
|
||||
|
||||
this->Buffer = newBuffer;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
ZList<T> ZReferenceBuffer<T>::Items()
|
||||
{
|
||||
int i;
|
||||
ZList<T> items;
|
||||
|
||||
for (i = 1; i < this->BufferSize; i++)
|
||||
{
|
||||
if (this->IsValid(i))
|
||||
items.PushBack(this->Buffer[i]);
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
243
Include/ZUtil/ZReferenceCounter.hpp
Normal file
243
Include/ZUtil/ZReferenceCounter.hpp
Normal file
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
ZReferenceCounter.hpp
|
||||
Author: James Russell <jcrussell@762studios.com>
|
||||
Created: 3/22/2012
|
||||
|
||||
Purpose:
|
||||
|
||||
Defines a structure that is usually allocated on the heap and will maintain a strong
|
||||
reference count, a weak reference count, and an integer flag used to signal state. This
|
||||
reference counter is designed to be thread safe by using atomic operations.
|
||||
|
||||
License:
|
||||
|
||||
TODO
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _ZREFERENCECOUNTER_HPP
|
||||
#define _ZREFERENCECOUNTER_HPP
|
||||
|
||||
#include <SST/SST_Atomic.h>
|
||||
|
||||
#include <ZUtil/ZUtilBuild.hpp>
|
||||
#include <ZUtil/ZAssert.hpp>
|
||||
#include <ZUtil/ZAlloc.hpp>
|
||||
|
||||
//The leading (negative) bit is used to indicate deallocation on the State int
|
||||
#define ZREFCOUNTER_DEALLOC_BIT (0x80000000)
|
||||
|
||||
/*
|
||||
ZReferenceCounter::CombinedCount is a 32-bit integer value containing
|
||||
2x16-bit integer values -- the strong and weak reference counts. They
|
||||
are stored as 0xWWWWSSSS, i.e. upper 16 bits are the weak reference
|
||||
count, and the lower 16 bits are the strong reference count.
|
||||
|
||||
Do realize that this limits us to 65565 strong and 65565 weak references
|
||||
without error conditions. We find this to be an acceptable limit.
|
||||
*/
|
||||
|
||||
//These define how much to shift by to affect the strong/weak counters
|
||||
#define ZREFCOUNTER_STRONG_SHIFT (0)
|
||||
#define ZREFCOUNTER_WEAK_SHIFT (16)
|
||||
|
||||
//These masks are what we will use to mask the upper half (weak) and lower half (strong) parts
|
||||
//of the integer reference count
|
||||
#define ZREFCOUNTER_STRONG_MASK (0xFFFF << ZREFCOUNTER_STRONG_SHIFT)
|
||||
#define ZREFCOUNTER_WEAK_MASK (0xFFFF << ZREFCOUNTER_WEAK_SHIFT)
|
||||
|
||||
//These values are used to add a single weak reference or a single strong reference to the
|
||||
//reference count
|
||||
#define ZREFCOUNTER_STRONG_REF (1 << ZREFCOUNTER_STRONG_SHIFT)
|
||||
#define ZREFCOUNTER_WEAK_REF (1 << ZREFCOUNTER_WEAK_SHIFT)
|
||||
|
||||
//These macros extract the strong/weak reference counts respectively from the combined counts
|
||||
#define ZREFCOUNTER_EXTRACT_STRONG_REF(x) (((x) >> ZREFCOUNTER_STRONG_SHIFT) & 0xFFFF)
|
||||
#define ZREFCOUNTER_EXTRACT_WEAK_REF(x) (((x) >> ZREFCOUNTER_WEAK_SHIFT) & 0xFFFF)
|
||||
|
||||
/*
|
||||
Reference counting struct. Keeps a reference count to an
|
||||
object (both strong and weak), and a state signaling integer.
|
||||
*/
|
||||
struct ZReferenceCounter
|
||||
{
|
||||
/*
|
||||
Integer we use for keeping track of strong and weak references within the
|
||||
space of a single native integer. The upper half is used to determine
|
||||
weak count. The lower half is used to determine strong count. This allows
|
||||
us to use atomic operations on both the strong reference count and weak
|
||||
reference count on architectures that do not have a DoubleCAS operation.
|
||||
|
||||
Must be unsigned so >> doesn't do arthimetic shift.
|
||||
*/
|
||||
volatile uint32_t CombinedCount;
|
||||
|
||||
/*
|
||||
Flag used for signaling object usage state
|
||||
|
||||
> 0 - in use (number of users)
|
||||
0 - not in use
|
||||
< 0 - ready for deallocation (discounting deallocation bit gives number of users)
|
||||
*/
|
||||
volatile int State;
|
||||
|
||||
/*
|
||||
Default constructor.
|
||||
*/
|
||||
ZReferenceCounter()
|
||||
: CombinedCount(0), State(0) { }
|
||||
|
||||
/*
|
||||
Destructor.
|
||||
*/
|
||||
~ZReferenceCounter()
|
||||
{ }
|
||||
|
||||
/*
|
||||
Using atomic operations, will increment the strong reference count.
|
||||
*/
|
||||
inline void GainStrongRef()
|
||||
{
|
||||
SST_Atomic_Add((volatile int*)&CombinedCount, ZREFCOUNTER_STRONG_REF);
|
||||
}
|
||||
|
||||
/*
|
||||
Using atomic operations, will increment the weak reference count.
|
||||
*/
|
||||
inline void GainWeakRef()
|
||||
{
|
||||
SST_Atomic_Add((volatile int*)&CombinedCount, ZREFCOUNTER_WEAK_REF);
|
||||
}
|
||||
|
||||
/*
|
||||
Gets the current strong reference count.
|
||||
*/
|
||||
inline uint32_t GetStrongRefCount()
|
||||
{
|
||||
return ZREFCOUNTER_EXTRACT_STRONG_REF(CombinedCount);
|
||||
}
|
||||
|
||||
/*
|
||||
Gets the current weak reference count.
|
||||
*/
|
||||
inline uint32_t GetWeakRefCount()
|
||||
{
|
||||
return ZREFCOUNTER_EXTRACT_WEAK_REF(CombinedCount);
|
||||
}
|
||||
|
||||
/*
|
||||
Using atomic operations, will decrement the strong reference count and
|
||||
return the number of remaining references, both strong and weak, as part
|
||||
of the same value.
|
||||
|
||||
To get the strong reference count, use ZREFCOUNTER_EXTRACT_STRONG_REF() on the return value.
|
||||
|
||||
To get the weak reference count, use ZREFCOUNTER_EXTRACT_WEAK_REF() on the return value.
|
||||
*/
|
||||
inline uint32_t LoseStrongRef()
|
||||
{
|
||||
return SST_Atomic_AddReturn((volatile int*)&CombinedCount, -ZREFCOUNTER_STRONG_REF);
|
||||
}
|
||||
|
||||
/*
|
||||
Using atomic operations, will decrement the weak reference count and
|
||||
return the number of remaining references, both strong and weak, as part
|
||||
of the same value.
|
||||
|
||||
To get the strong reference count, use ZREFCOUNTER_EXTRACT_STRONG_REF() on the return value.
|
||||
|
||||
To get the weak reference count, use ZREFCOUNTER_EXTRACT_WEAK_REF() on the return value.
|
||||
*/
|
||||
inline uint32_t LoseWeakRef()
|
||||
{
|
||||
return SST_Atomic_AddReturn((volatile int*)&CombinedCount, -ZREFCOUNTER_WEAK_REF);
|
||||
}
|
||||
|
||||
/*
|
||||
Using atomic operations, will set the state flag as 'deallocated' as soon as possible,
|
||||
which will ensure anyone using 'SignalInUse' will get a 'false' return value.
|
||||
*/
|
||||
inline void SignalDeallocateObject()
|
||||
{
|
||||
//Check deallocated
|
||||
if (State & ZREFCOUNTER_DEALLOC_BIT)
|
||||
return;
|
||||
|
||||
//Set high bit
|
||||
SST_Atomic_Or(&State, ZREFCOUNTER_DEALLOC_BIT);
|
||||
|
||||
//Wait logic
|
||||
while ((State & ~ZREFCOUNTER_DEALLOC_BIT) != 0)
|
||||
continue;
|
||||
|
||||
//State is guaranteed here to be == ZREFCOUNTER_DEALLOC_BIT
|
||||
}
|
||||
|
||||
/*
|
||||
Using atomic operations, will set the state flag as 'in use'. If unable to set
|
||||
state flag as 'in use' because the object is deallocated, will return false.
|
||||
|
||||
This is important to weak reference holders to signal to strong reference holders that
|
||||
the object should not be deallocated until the object is no longer in use.
|
||||
*/
|
||||
inline bool SignalInUse()
|
||||
{
|
||||
//Check deallocated
|
||||
if (State & ZREFCOUNTER_DEALLOC_BIT)
|
||||
return false;
|
||||
|
||||
int val = SST_Atomic_IncReturn(&State);
|
||||
|
||||
if (val & ZREFCOUNTER_DEALLOC_BIT)
|
||||
{
|
||||
SST_Atomic_Dec(&State); //Atomic decrement to ensure we don't starve the waiting deallocation thread
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
Using atomic operations, will set the state flag as 'no longer in use'.
|
||||
*/
|
||||
inline void SignalUnused()
|
||||
{
|
||||
SST_Atomic_Dec(&State);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Allocator class for ZReferenceCounter. Responsible for heap allocation and deletion of
|
||||
ZReferenceCounter instances.
|
||||
*/
|
||||
class ZReferenceCounterAllocator
|
||||
{
|
||||
public:
|
||||
/*
|
||||
public ZSmartPointerAllocator::AllocateCounter
|
||||
|
||||
Allocation method that allocates a reference counter for use by the smart pointer.
|
||||
|
||||
@return (ZSmartPointerRefCounter*)
|
||||
*/
|
||||
ZReferenceCounter* AllocateCounter()
|
||||
{
|
||||
return znew ZReferenceCounter();
|
||||
}
|
||||
|
||||
/*
|
||||
public ZSmartPointerAllocator::DeallocateCounter
|
||||
|
||||
Deallocates a reference counter that was provided by AllocateCounter.
|
||||
|
||||
@param _counter - the counter to deallocate
|
||||
*/
|
||||
void DeallocateCounter(ZReferenceCounter* _counter)
|
||||
{
|
||||
zdelete _counter;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
145
Include/ZUtil/ZRegistry.hpp
Normal file
145
Include/ZUtil/ZRegistry.hpp
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
ZRegistry.hpp
|
||||
Author: James Russell <jcrussell@762studios.com>
|
||||
Created: 2/18/2013
|
||||
|
||||
Purpose:
|
||||
|
||||
ZRegistry defines a use case for ZKVTree as a concurrent data store. A ZRegistry
|
||||
maps keys to values using path strings, just as ZKVTree does, but the path string
|
||||
must be unique as subscripts are not supported and siblings with the same name
|
||||
are not supported.
|
||||
|
||||
ZRegistry is thread-safe on all operations.
|
||||
|
||||
ZRegistry (currently) supports only string value types, but the return value struct
|
||||
from 'Get' can be converted to integer and double types with the Convert() function.
|
||||
|
||||
License:
|
||||
|
||||
TODO
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _ZREGISTRY_HPP
|
||||
#define _ZREGISTRY_HPP
|
||||
|
||||
#include <ZUtil/ZConcurrency.hpp>
|
||||
#include <ZUtil/ZKVTree.hpp>
|
||||
|
||||
class ZRegistry
|
||||
{
|
||||
public:
|
||||
/*
|
||||
Default Constructor.
|
||||
*/
|
||||
ZRegistry();
|
||||
|
||||
/*
|
||||
Constructs this registry from a KVTree.
|
||||
*/
|
||||
ZRegistry(const ZKVTree& _tree);
|
||||
|
||||
/*
|
||||
Destructor.
|
||||
*/
|
||||
~ZRegistry();
|
||||
|
||||
/*
|
||||
ZRegistry value type, which will evaluate to true if the value was found
|
||||
and false otherwise.
|
||||
*/
|
||||
class Value
|
||||
{
|
||||
friend class ZRegistry;
|
||||
public:
|
||||
/*
|
||||
Operator overload used to get the value.
|
||||
*/
|
||||
operator ZString () const
|
||||
{ return Val; }
|
||||
|
||||
/*
|
||||
Function used to verify validity of the returned value.
|
||||
*/
|
||||
bool Valid() const
|
||||
{ return bValid; }
|
||||
|
||||
/*
|
||||
Function used to get the string value.
|
||||
*/
|
||||
const ZString& GetString() const
|
||||
{ return Val; }
|
||||
|
||||
int GetInt() const
|
||||
{ return ZStringAlgo::NumericInt(Val); }
|
||||
|
||||
double GetDouble() const
|
||||
{ return ZStringAlgo::NumericDouble(Val); }
|
||||
|
||||
private:
|
||||
/*
|
||||
Constructor, which initializes the reference and the flag indicating
|
||||
whether or not this is a valid value.
|
||||
*/
|
||||
Value(const ZString& _val, bool _valid)
|
||||
: Val(_val), bValid(_valid) { }
|
||||
|
||||
ZString Val; //Value copy (cannot maintain reference into data structure)
|
||||
bool bValid; //Validity flag
|
||||
};
|
||||
|
||||
/*
|
||||
public ZRegistry::operator []
|
||||
|
||||
[] operator overload, equivalent to Get(_key).
|
||||
|
||||
@param _key - the key to look up
|
||||
@return (const ZString&) - the value looked up
|
||||
*/
|
||||
const Value operator [] (const ZString& _key) const
|
||||
{ return Get(_key); }
|
||||
|
||||
/*
|
||||
public ZRegistry::Erase
|
||||
|
||||
Erases a key/value pair (and all child key/value pairs) from the registry.
|
||||
|
||||
@param _key - the key to erase
|
||||
@return (void)
|
||||
*/
|
||||
void Erase(const ZString& _key);
|
||||
|
||||
/*
|
||||
public ZRegistry::Get
|
||||
|
||||
Returns the value instance bound to the given key.
|
||||
|
||||
@param _key - the key to evaluate
|
||||
@return (Value) - value instance for this key
|
||||
*/
|
||||
const Value Get(const ZString& _key) const;
|
||||
|
||||
/*
|
||||
public ZRegistry::Put
|
||||
|
||||
Places a key / value pair into the registry. Will create any necessary nodes
|
||||
to place the key and value pair.
|
||||
|
||||
@param _key - the key to map
|
||||
@param _value - the value to map to the key
|
||||
@return (bool) - true if able to map the key/value, false otherwise
|
||||
*/
|
||||
bool Put(const ZString& _key, const ZString& _value);
|
||||
|
||||
private:
|
||||
DISABLE_COPY_AND_ASSIGN(ZRegistry);
|
||||
|
||||
ZReadWriteLock Lock; //The concurrency read write lock
|
||||
ZKVTree Tree; //The tree we store out data in
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
89
Include/ZUtil/ZSemaphore.hpp
Normal file
89
Include/ZUtil/ZSemaphore.hpp
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
ZSema.hpp
|
||||
Author: James Russell <jcrussell@762studios.com>
|
||||
|
||||
Purpose: RAII wrapper for libsst-concurrency SST_Semaphore.
|
||||
|
||||
Changelog
|
||||
2011/11/27 - creation (jcrussell)
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _ZSEMAPHORE_H
|
||||
#define _ZSEMAPHORE_H
|
||||
|
||||
#include <ZUtil/ZUtilBuild.hpp>
|
||||
|
||||
#include <SST/SST_Semaphore.h>
|
||||
|
||||
/*
|
||||
ZSemaphore class. Used to allocate and deallocate a semaphore within the scope of a class.
|
||||
Cannot be copied or assigned, which prevents it from being used in stl-like containers.
|
||||
*/
|
||||
class ZSemaphore
|
||||
{
|
||||
private:
|
||||
DISABLE_COPY_AND_ASSIGN(ZSemaphore);
|
||||
|
||||
//libsst Semaphore
|
||||
SST_Semaphore Semaphore;
|
||||
|
||||
public:
|
||||
/*
|
||||
Constructor.
|
||||
|
||||
@param _initialCount - initial count of the semaphore
|
||||
*/
|
||||
ZSemaphore(int _initialCount);
|
||||
|
||||
/*
|
||||
Destructor.
|
||||
*/
|
||||
~ZSemaphore();
|
||||
|
||||
/*
|
||||
public ZSema::Post
|
||||
|
||||
TODO
|
||||
|
||||
@return (void)
|
||||
@context (all)
|
||||
*/
|
||||
void Post();
|
||||
|
||||
/*
|
||||
public ZSema::Post
|
||||
|
||||
TODO
|
||||
|
||||
@param _count -
|
||||
@return (void)
|
||||
@context (all)
|
||||
*/
|
||||
void Post(uint32_t _count);
|
||||
|
||||
/*
|
||||
public ZSema::Wait
|
||||
|
||||
TODO
|
||||
|
||||
@return (bool)
|
||||
@context (all)
|
||||
*/
|
||||
bool Wait();
|
||||
|
||||
/*
|
||||
public ZSema::Wait
|
||||
|
||||
TODO
|
||||
|
||||
@param _ms -
|
||||
@return (bool)
|
||||
@context (all)
|
||||
*/
|
||||
bool Wait(uint32_t _ms);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
41
Include/ZUtil/ZSimplexNoise.hpp
Normal file
41
Include/ZUtil/ZSimplexNoise.hpp
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
ZSimplexNoise.hpp
|
||||
Author : Chris Ertel
|
||||
|
||||
Purpose : Math namespace for the ZEngine which will contain functions for mathematical operations on primitives
|
||||
and arrays of primitives.
|
||||
|
||||
Changelog
|
||||
2/13/11 - Creation (crertel)
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _ZSIMPLEXNOISE_H
|
||||
#define _ZSIMPLEXNOISE_H
|
||||
|
||||
#include <ZUtil/ZNoise.hpp>
|
||||
#include <SST/SST_SimplexNoise.h>
|
||||
|
||||
class ZSimplexNoise : public ZNoise
|
||||
{
|
||||
protected:
|
||||
SST_SimplexNoise simplexGenerator;
|
||||
|
||||
public:
|
||||
ZSimplexNoise();
|
||||
virtual ~ZSimplexNoise() {}
|
||||
|
||||
//Subclass implementation
|
||||
void reseed(const int _seed);
|
||||
//Subclass implementation
|
||||
float noise1(const float _x);
|
||||
//Subclass implementation
|
||||
float noise2(const float _x, const float _y);
|
||||
//Subclass implementation
|
||||
float noise3(const float _x, const float _y, const float _z);
|
||||
//Subclass implementation
|
||||
float noise4(const float _x, const float _y, const float _z, const float _w);
|
||||
};
|
||||
|
||||
#endif
|
||||
261
Include/ZUtil/ZSimplexNoiseMap.hpp
Normal file
261
Include/ZUtil/ZSimplexNoiseMap.hpp
Normal file
@@ -0,0 +1,261 @@
|
||||
/*
|
||||
ZSimplexNoiseMap.hpp
|
||||
Author : Chris Ertel
|
||||
|
||||
Purpose : Interface to create a map for simplex noise values.
|
||||
|
||||
Changelog
|
||||
2/20/11 - Creation (crertel)
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _ZSIMPLEXNOISEMAP_H
|
||||
#define _ZSIMPLEXNOISEMAP_H
|
||||
|
||||
#include <ZUtil/ZSimplexNoise.hpp>
|
||||
#include <ZUtil/ZNoiseMap.hpp>
|
||||
#include <ZUtil/ZUtil.hpp>
|
||||
|
||||
class ZSimplexNoiseMap : public ZNoiseMap
|
||||
{
|
||||
protected:
|
||||
ZSimplexNoise noiseGen;
|
||||
float lacunarity;
|
||||
float persistence;
|
||||
int numberofoctaves;
|
||||
float* values;
|
||||
|
||||
public:
|
||||
|
||||
ZSimplexNoiseMap()
|
||||
: lacunarity(.5), persistence(.5), numberofoctaves(8), values(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~ZSimplexNoiseMap()
|
||||
{
|
||||
}
|
||||
|
||||
virtual int GetDimensionality() = 0;
|
||||
|
||||
//Subclass implementation
|
||||
float GetLacunarity() { return this->lacunarity; }
|
||||
|
||||
//Subclass implementation
|
||||
float GetPersistence() { return this->persistence; }
|
||||
|
||||
//Subclass implementation
|
||||
int GetNumberOfOctaves() { return this->numberofoctaves; }
|
||||
|
||||
//Not implemented
|
||||
virtual int GetNumberSamplesInX() = 0;
|
||||
//Not implemented
|
||||
virtual int GetNumberSamplesInY() = 0;
|
||||
//Not implemented
|
||||
virtual int GetNumberSamplesInZ() = 0;
|
||||
//Not implemented
|
||||
virtual int GetNumberSamplesInW() = 0;
|
||||
|
||||
/*
|
||||
public ZSimplexNoiseMap::GetSamples
|
||||
|
||||
Function to get array of values for noise map.
|
||||
|
||||
@return (float*) - array of values
|
||||
*/
|
||||
float* GetSamples() { return this->values; }
|
||||
|
||||
//Subclass implementation
|
||||
void SetLacunarity(float _lac) { this->lacunarity = _lac; } // scaling of successive frequencies in noise octaves
|
||||
//Subclass implementation
|
||||
void SetPersistence(float _per) { this->persistence = _per; } // scaling of successive amplitudes in noise octaves
|
||||
//Subclass implementation
|
||||
void SetNumberOfOctaves(int _numOctaves ) { this->numberofoctaves = _numOctaves; }
|
||||
|
||||
//Not implemented
|
||||
virtual void SetNumberSamplesInX(int _numSamples) = 0;
|
||||
//Not implemented
|
||||
virtual void SetNumberSamplesInY(int _numSamples) = 0;
|
||||
//Not implemented
|
||||
virtual void SetNumberSamplesInZ(int _numSamples) = 0;
|
||||
//Not implemented
|
||||
virtual void SetNumberSamplesInW(int _numSamples) = 0;
|
||||
|
||||
//Not implemented
|
||||
virtual bool Generate(int _seed) = 0;
|
||||
//Not implemented
|
||||
virtual void Cleanup() = 0;
|
||||
};
|
||||
|
||||
class ZSimplexNoiseMap2D : public ZSimplexNoiseMap
|
||||
{
|
||||
protected:
|
||||
int numberSamplesInX;
|
||||
int numberSamplesInY;
|
||||
|
||||
public:
|
||||
ZSimplexNoiseMap2D()
|
||||
: ZSimplexNoiseMap(), numberSamplesInX(0), numberSamplesInY(0)
|
||||
{
|
||||
}
|
||||
|
||||
~ZSimplexNoiseMap2D()
|
||||
{
|
||||
this->Cleanup();
|
||||
}
|
||||
|
||||
//Subclass implementation
|
||||
int GetDimensionality() { return 2; }
|
||||
//Subclass implementation
|
||||
int GetNumberSamplesInX() { return this->numberSamplesInX; }
|
||||
//Subclass implementation
|
||||
int GetNumberSamplesInY() { return this->numberSamplesInY; }
|
||||
//Subclass implementation
|
||||
int GetNumberSamplesInZ() { return 0; }
|
||||
//Subclass implementation
|
||||
int GetNumberSamplesInW() { return 0; }
|
||||
|
||||
//Subclass implementation
|
||||
void SetNumberSamplesInX(int _numSamples) { this->numberSamplesInX = _numSamples; }
|
||||
//Subclass implementation
|
||||
void SetNumberSamplesInY(int _numSamples) { this->numberSamplesInY = _numSamples; }
|
||||
//Subclass implementation
|
||||
void SetNumberSamplesInZ(int _numSamples) { URFP ( _numSamples) ; }
|
||||
//Subclass implementation
|
||||
void SetNumberSamplesInW(int _numSamples) { URFP ( _numSamples) ; }
|
||||
|
||||
/*
|
||||
public ZSimplexNoiseMap2D::getValue
|
||||
|
||||
Gets value at a particular point on the noise map.
|
||||
|
||||
@param _x - x-coordinate to sample
|
||||
@param _y - y-coordinate to sample
|
||||
@return (double) - value at point (x,y)
|
||||
*/
|
||||
float getValue(int _x, int _y);
|
||||
|
||||
//Subclass implementation
|
||||
bool Generate(int _seed = 0);
|
||||
//Subclass implementation
|
||||
void Cleanup();
|
||||
};
|
||||
|
||||
class ZSimplexNoiseMap3D : public ZSimplexNoiseMap
|
||||
{
|
||||
protected:
|
||||
int numberSamplesInX;
|
||||
int numberSamplesInY;
|
||||
int numberSamplesInZ;
|
||||
|
||||
public:
|
||||
ZSimplexNoiseMap3D()
|
||||
: ZSimplexNoiseMap(), numberSamplesInX(0), numberSamplesInY(0), numberSamplesInZ(0)
|
||||
{
|
||||
}
|
||||
|
||||
~ZSimplexNoiseMap3D()
|
||||
{
|
||||
this->Cleanup();
|
||||
}
|
||||
|
||||
//Subclass implementation
|
||||
int GetDimensionality() { return 3; }
|
||||
//Subclass implementation
|
||||
int GetNumberSamplesInX() { return this->numberSamplesInX; }
|
||||
//Subclass implementation
|
||||
int GetNumberSamplesInY() { return this->numberSamplesInY; }
|
||||
//Subclass implementation
|
||||
int GetNumberSamplesInZ() { return this->numberSamplesInZ; }
|
||||
//Subclass implementation
|
||||
int GetNumberSamplesInW() { return 0; }
|
||||
|
||||
//Subclass implementation
|
||||
void SetNumberSamplesInX(int _numSamples) { this->numberSamplesInX = _numSamples; }
|
||||
//Subclass implementation
|
||||
void SetNumberSamplesInY(int _numSamples) { this->numberSamplesInY = _numSamples; }
|
||||
//Subclass implementation
|
||||
void SetNumberSamplesInZ(int _numSamples) { this->numberSamplesInZ = _numSamples; }
|
||||
//Subclass implementation
|
||||
void SetNumberSamplesInW(int _numSamples) { URFP ( _numSamples) ; }
|
||||
|
||||
/*
|
||||
public ZSimplexNoiseMap3D::getValue
|
||||
|
||||
Gets value at a particular point on the noise map.
|
||||
|
||||
@param _x - x-coordinate to sample
|
||||
@param _y - y-coordinate to sample
|
||||
@param _z - z-coordinate to sample
|
||||
@return (float) - value at point in noise map.
|
||||
*/
|
||||
float getValue(int _x, int _y, int _z);
|
||||
|
||||
//Subclass implementation
|
||||
bool Generate(int _seed = 0);
|
||||
//Subclass implementation
|
||||
void Cleanup();
|
||||
};
|
||||
|
||||
class ZSimplexNoiseMap4D : public ZSimplexNoiseMap
|
||||
{
|
||||
protected:
|
||||
int numberSamplesInX;
|
||||
int numberSamplesInY;
|
||||
int numberSamplesInZ;
|
||||
int numberSamplesInW;
|
||||
|
||||
public:
|
||||
ZSimplexNoiseMap4D()
|
||||
: ZSimplexNoiseMap(), numberSamplesInX(0), numberSamplesInY(0), numberSamplesInZ(0),
|
||||
numberSamplesInW(0)
|
||||
{
|
||||
}
|
||||
|
||||
~ZSimplexNoiseMap4D()
|
||||
{
|
||||
this->Cleanup();
|
||||
}
|
||||
|
||||
//Subclass implementation
|
||||
int GetDimensionality() { return 4; }
|
||||
//Subclass implementation
|
||||
int GetNumberSamplesInX() { return this->numberSamplesInX; }
|
||||
//Subclass implementation
|
||||
int GetNumberSamplesInY() { return this->numberSamplesInY; }
|
||||
//Subclass implementation
|
||||
int GetNumberSamplesInZ() { return this->numberSamplesInZ; }
|
||||
//Subclass implementation
|
||||
int GetNumberSamplesInW() { return this->numberSamplesInW; }
|
||||
|
||||
//Subclass implementation
|
||||
void SetNumberSamplesInX(int _numSamples) { this->numberSamplesInX = _numSamples; }
|
||||
//Subclass implementation
|
||||
void SetNumberSamplesInY(int _numSamples) { this->numberSamplesInY = _numSamples; }
|
||||
//Subclass implementation
|
||||
void SetNumberSamplesInZ(int _numSamples) { this->numberSamplesInZ = _numSamples; }
|
||||
//Subclass implementation
|
||||
void SetNumberSamplesInW(int _numSamples) { this->numberSamplesInW = _numSamples; }
|
||||
|
||||
/*
|
||||
public ZSimplexNoiseMap4D::getValue
|
||||
|
||||
Gets value at a particular point on the noise map.
|
||||
|
||||
@param _x - x-coordinate to sample
|
||||
@param _y - y-coordinate to sample
|
||||
@param _z - z-coordinate to sample
|
||||
@param _w - w-coordinate to sample
|
||||
@return (float) - value at point in noise map.
|
||||
*/
|
||||
float getValue(int _x, int _y, int _z, int _w);
|
||||
|
||||
//Subclass implementation
|
||||
bool Generate(int _seed = 0);
|
||||
//Subclass implementation
|
||||
void Cleanup();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
237
Include/ZUtil/ZSlabAllocator.hpp
Normal file
237
Include/ZUtil/ZSlabAllocator.hpp
Normal file
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
ZSlabAllocator.hpp
|
||||
Author: James Russell <jcrussell@762studios.com>
|
||||
Created: 9/12/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
Used to pre-allocate a large pool of objects whose size is fixed. These objects can
|
||||
then be allocated and deallocated as needed, which will return a pointer to an already
|
||||
allocated member.
|
||||
|
||||
Will correctly handle allocation of more objects than is allocated at compile time, but
|
||||
performance will be impacted as another slab of equivalent size to the original is
|
||||
allocated.
|
||||
|
||||
This is not a multithreaded access allocator. The user of this is required to provide
|
||||
their own thread safety mechanisms.
|
||||
|
||||
License:
|
||||
|
||||
TODO
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _ZSLABALLOCATOR_H
|
||||
#define _ZSLABALLOCATOR_H
|
||||
|
||||
#include <ZUtil/ZUtilBuild.hpp>
|
||||
#include <ZUtil/ZAlloc.hpp>
|
||||
#include <ZUtil/ZAssert.hpp>
|
||||
#include <ZUtil/ZLog.hpp>
|
||||
|
||||
/*
|
||||
Slab Allocator, which holds a contiguous array of objects and leases them out for use.
|
||||
|
||||
The template parameter T is the type of object to hold.
|
||||
|
||||
The template parameter N is the size of the slab (how many objects to allocate statically).
|
||||
*/
|
||||
template <typename T, size_t N>
|
||||
class ZSlabAllocator
|
||||
{
|
||||
private:
|
||||
DISABLE_COPY_AND_ASSIGN(ZSlabAllocator);
|
||||
|
||||
protected:
|
||||
|
||||
/*
|
||||
Allocated slab of objects, that links to the next
|
||||
slab of objects.
|
||||
*/
|
||||
class Slab
|
||||
{
|
||||
private:
|
||||
T Pool[N]; //The object pool
|
||||
T* Handles[N]; //Handles to objects in the object pool
|
||||
size_t HandleIndex; //Handle index to the next available handle
|
||||
Slab* NextPool; //Next pool
|
||||
|
||||
public:
|
||||
Slab() :
|
||||
HandleIndex(0), NextPool(NULL)
|
||||
{
|
||||
//Populate our handles pool
|
||||
for (size_t i = 0; i < N; i++)
|
||||
Handles[i] = &(Pool[i]);
|
||||
}
|
||||
|
||||
//Used to verify that a handle belongs to the pool of objects
|
||||
bool IsPoolMember(T* _handle)
|
||||
{
|
||||
uintptr_t handle = (uintptr_t) _handle;
|
||||
uintptr_t poolLower = (uintptr_t) &Pool[0];
|
||||
uintptr_t poolUpper = (uintptr_t) &Pool[N - 1];
|
||||
|
||||
if ((handle >= poolLower) && (handle <= poolUpper)) //Checks to see if handle is within the range of the pool
|
||||
if (((handle - poolLower) % sizeof(T)) == 0) //Checks to see if handle is aligned on an object in the pool
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
T* Allocate()
|
||||
{
|
||||
T* object = NULL;
|
||||
|
||||
if (HandleIndex < N)
|
||||
{
|
||||
//Grab an object from the object pool
|
||||
object = Handles[HandleIndex++];
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
void Deallocate(T* object)
|
||||
{
|
||||
Handles[--HandleIndex] = object;
|
||||
}
|
||||
|
||||
Slab* GetNextPool() { return NextPool; }
|
||||
void SetNextPool(Slab* p) { NextPool = p; }
|
||||
|
||||
};
|
||||
|
||||
//ZSlabAllocator members
|
||||
Slab FirstPool;
|
||||
size_t NrAllocated;
|
||||
size_t NrSlabs;
|
||||
|
||||
public:
|
||||
/*
|
||||
Default Constructor.
|
||||
*/
|
||||
ZSlabAllocator() :
|
||||
NrAllocated(0), NrSlabs(1)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
Destructor.
|
||||
*/
|
||||
~ZSlabAllocator()
|
||||
{
|
||||
Slab* slab = FirstPool.GetNextPool();
|
||||
|
||||
while(slab)
|
||||
{
|
||||
Slab* next = slab->GetNextPool();
|
||||
|
||||
zdelete slab;
|
||||
slab = next;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
public ZSlabAllocator<T,N>::Allocate
|
||||
|
||||
Gets a valid object of type T and returns a pointer.
|
||||
|
||||
@return (T*) - a valid object pointer of type T
|
||||
*/
|
||||
T* Allocate()
|
||||
{
|
||||
T* object = NULL;
|
||||
|
||||
Slab* slab = &FirstPool; //Begin with first pool
|
||||
|
||||
while(object == NULL)
|
||||
{
|
||||
//Any objects left in this pool?
|
||||
object = slab->Allocate();
|
||||
if(object == NULL)
|
||||
{
|
||||
//Doh, try next pool
|
||||
Slab* next = slab->GetNextPool();
|
||||
|
||||
//Unless there is no next pool...
|
||||
if(next == NULL)
|
||||
{
|
||||
//Try to allocate another one
|
||||
Slab* newPool = znew Slab;
|
||||
if(newPool == NULL)
|
||||
return NULL; //Doh, out of memory. :(
|
||||
else
|
||||
NrSlabs++;
|
||||
|
||||
//Save this pool
|
||||
slab->SetNextPool(newPool);
|
||||
next = newPool;
|
||||
}
|
||||
|
||||
//Try next pool
|
||||
slab = next;
|
||||
}
|
||||
else
|
||||
NrAllocated++;
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
/*
|
||||
public ZSlabAllocator<T,N>::Capacity
|
||||
|
||||
Gets the size of the object pool. Returns the total capacity of the pool.
|
||||
|
||||
@return (size_t) - the capacity of the object pool
|
||||
*/
|
||||
size_t Capacity() const
|
||||
{
|
||||
return NrSlabs * N;
|
||||
}
|
||||
|
||||
/*
|
||||
public ZSlabAllocator<T,N>::Count
|
||||
|
||||
Gets the number of objects contained by the object pool.
|
||||
|
||||
@return (size_t) - the number of objects contained by this pool
|
||||
*/
|
||||
size_t Available() const
|
||||
{
|
||||
return NrSlabs * N - NrAllocated;
|
||||
}
|
||||
|
||||
size_t Allocated() const
|
||||
{
|
||||
return NrAllocated;
|
||||
}
|
||||
|
||||
/*
|
||||
public ZSlabAllocator<T,N>::Deallocate
|
||||
|
||||
Allocates an object from the slab.
|
||||
|
||||
@param _object - a valid object pointer of type T gained through 'Allocate'
|
||||
@return (void)
|
||||
*/
|
||||
void Deallocate(T *_object)
|
||||
{
|
||||
for(Slab* slab = &FirstPool; slab != NULL; slab = slab->GetNextPool())
|
||||
{
|
||||
if(slab->IsPoolMember(_object))
|
||||
{
|
||||
NrAllocated--;
|
||||
slab->Deallocate(_object);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ZASSERT_RUNTIME_FAIL("ZSlabAllocator: Object deallocated that was not allocated here!");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
944
Include/ZUtil/ZSmartPointer.hpp
Normal file
944
Include/ZUtil/ZSmartPointer.hpp
Normal file
@@ -0,0 +1,944 @@
|
||||
/*
|
||||
ZSmartPointer.hpp
|
||||
Author: James Russell
|
||||
Created: 08/12/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
Smart pointer implementation for the ZEngine. Frees up the programmer from having to
|
||||
worry too hard about the minutiae of memory management for allocated objects. Not to
|
||||
use on arrays; use ZArray for dynamic array management.
|
||||
|
||||
Uses atomic operations to enable the smart pointer to work across threads.
|
||||
|
||||
Don't pass these things around by pointer or reference unless you really know what you
|
||||
are doing. You won't like the results.
|
||||
|
||||
License:
|
||||
|
||||
TODO
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _ZSMARTPOINTER_H
|
||||
#define _ZSMARTPOINTER_H
|
||||
|
||||
#include <SST/SST_Atomic.h>
|
||||
#include <SST/SST_Concurrency.h>
|
||||
|
||||
#include <ZUtil/ZUtilBuild.hpp>
|
||||
#include <ZUtil/ZAlloc.hpp>
|
||||
#include <ZUtil/ZAssert.hpp>
|
||||
#include <ZUtil/ZReferenceCounter.hpp>
|
||||
|
||||
#include <ZSTL/ZArray.hpp>
|
||||
#include <ZSTL/ZList.hpp>
|
||||
#include <ZSTL/ZRingBuffer.hpp>
|
||||
|
||||
//Shorthand used for ZSmartPointer
|
||||
#define ZPtr ZSmartPointer
|
||||
|
||||
/*
|
||||
Default deallocator functor for ZSmartPointer, which is responsible for deallocating
|
||||
the managed object. This default version uses 'zdelete'.
|
||||
|
||||
The template parameter T is the type of object pointed to by the smart pointer.
|
||||
|
||||
The unary functor takes a single argument of type T*, which is the object to be deallocated.
|
||||
*/
|
||||
template <typename T>
|
||||
struct ZSmartPointerDeallocator {
|
||||
void operator () (T* _object) {
|
||||
zdelete _object;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
NULL deallocator functor for ZSmartPointer, which doesn't actually deallocate anything.
|
||||
|
||||
The template parameter T is the type of object pointed to by the smart pointer.
|
||||
|
||||
The unary functor takes a single argument of type T*, which is destroyed.
|
||||
*/
|
||||
template <typename T>
|
||||
struct ZSmartPointerNullDeallocator {
|
||||
void operator() (T* _object) {
|
||||
URFP(_object);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Smart pointer class, used to share a references to an allocated object. This smart pointer
|
||||
uses atomic operations to ensure that the reference count is maintained properly even when
|
||||
the object is shared among threads.
|
||||
|
||||
The template parameter T is the type of the object pointed to.
|
||||
|
||||
The template parameter DF is the type of object deallocator functor to use.
|
||||
|
||||
The template parameter R is the type of reference counter allocator to use.
|
||||
*/
|
||||
template <typename T, typename DF = ZSmartPointerDeallocator<T>, typename R = ZReferenceCounterAllocator >
|
||||
class ZSmartPointer
|
||||
{
|
||||
protected:
|
||||
//The pointed to object
|
||||
T* Object;
|
||||
|
||||
//Object Deallocator
|
||||
DF ObjDeallocator;
|
||||
|
||||
//Reference Counter Allocator
|
||||
R RefAllocator;
|
||||
|
||||
//Reference Counter for the pointer (also contains the pointer)
|
||||
ZReferenceCounter* Ref;
|
||||
|
||||
//Checks to see if we need a reference counter, allocates if so, and increments the strong
|
||||
//reference count
|
||||
inline void ReferenceGained()
|
||||
{
|
||||
if (Object == NULL)
|
||||
return;
|
||||
|
||||
if (Ref == NULL)
|
||||
{
|
||||
Ref = RefAllocator.AllocateCounter();
|
||||
|
||||
ZASSERT_RUNTIME(Ref != NULL, "ZSmartPointer: Reference counter allocator returned NULL!");
|
||||
}
|
||||
|
||||
Ref->GainStrongRef();
|
||||
}
|
||||
|
||||
//Checks to see if we can delete the reference and lowers the count
|
||||
inline void ReferenceLost()
|
||||
{
|
||||
if (Ref == NULL)
|
||||
{
|
||||
ZASSERT_UTIL(Object == NULL, "ZSmartPointer: Reference lost with no reference counter, but object is still present!");
|
||||
return;
|
||||
}
|
||||
|
||||
ZASSERT_UTIL(Ref->GetStrongRefCount() > 0 && Object != NULL, "ZSmartPointer: Reference lost but object is already deallocated!");
|
||||
|
||||
uint32_t combinedCount = Ref->LoseStrongRef(); //Decrement our strong count and get the combined count
|
||||
|
||||
//Check if we lost the last strong ref
|
||||
if ((combinedCount & ZREFCOUNTER_STRONG_MASK) == 0) //Note we don't use the EXTRACT_STRONG_REF() since 0 bitshifted is still 0
|
||||
{
|
||||
Ref->SignalDeallocateObject(); //Signal object deallocation
|
||||
|
||||
ObjDeallocator(Object); //Deallocate the object
|
||||
|
||||
//Check if we lost the last weak reference
|
||||
if ((combinedCount & ZREFCOUNTER_WEAK_MASK) == 0) //Note we don't use the EXTRACT_WEAK_REF() since 0 bitshifted is still 0
|
||||
{
|
||||
RefAllocator.DeallocateCounter(Ref); //Deallocate the counter
|
||||
}
|
||||
}
|
||||
|
||||
//We lost our reference, so we don't need these
|
||||
Object = NULL;
|
||||
Ref = NULL;
|
||||
}
|
||||
|
||||
public:
|
||||
/*
|
||||
Default constructor. Sets the reference to NULL and does not allocate a reference
|
||||
counter.
|
||||
*/
|
||||
ZSmartPointer()
|
||||
: Object(NULL), Ref(NULL)
|
||||
{ }
|
||||
|
||||
/*
|
||||
Constructor. Explicit to ensure we don't accidentally take ownership of
|
||||
a pointer. Allocates a reference counter from the reference counter allocator.
|
||||
|
||||
@param _ptr - pointer to be managed
|
||||
*/
|
||||
explicit ZSmartPointer(T* _ptr)
|
||||
: Object(_ptr), Ref(NULL)
|
||||
{
|
||||
ReferenceGained();
|
||||
}
|
||||
|
||||
/*
|
||||
Copy constructor.
|
||||
|
||||
@param _other - the other smart pointer
|
||||
*/
|
||||
ZSmartPointer(const ZSmartPointer<T, DF, R>& _other)
|
||||
: Object(_other.Pointer()), Ref(_other.Counter())
|
||||
{
|
||||
ZASSERT_UTIL(!(Object != NULL && Ref == NULL), "ZSmartPointer: Copy constructor called from smart pointer with invalid reference counter!");
|
||||
|
||||
ReferenceGained();
|
||||
}
|
||||
|
||||
/*
|
||||
Conversion constructor. Used to auto up-cast derived classes or other
|
||||
classes that can be converted.
|
||||
|
||||
@param D - the typename of the derived class
|
||||
@param EF - the deallocator functor type of the other class
|
||||
@param S - the reference counter allocator type of the other class
|
||||
@param _other - the other smart pointer
|
||||
*/
|
||||
template <typename D, typename EF, typename S>
|
||||
ZSmartPointer(const ZSmartPointer<D, EF, S>& _other)
|
||||
: Object(static_cast<T*>(_other.Pointer())), Ref(_other.Counter())
|
||||
{
|
||||
ZASSERT_UTIL(!(Object != NULL && Ref == NULL), "ZSmartPointer: Copy constructor called from smart pointer with invalid reference counter!");
|
||||
|
||||
ReferenceGained();
|
||||
}
|
||||
|
||||
/*
|
||||
Destructor. Causes a strong reference to be lost.
|
||||
*/
|
||||
~ZSmartPointer()
|
||||
{
|
||||
ReferenceLost();
|
||||
}
|
||||
|
||||
/*
|
||||
= operator overload. Sets this smart pointer to be the owner of the provided pointer,
|
||||
which may require allocation of a reference counter.
|
||||
|
||||
@param _ptr - the pointer to the object to own
|
||||
@return (ZSmartPointer<T, DF, R>&) - this smart pointer
|
||||
*/
|
||||
ZSmartPointer<T, DF, R>& operator = (T* _ptr)
|
||||
{
|
||||
if (Object == _ptr)
|
||||
return *this;
|
||||
|
||||
if (_ptr == NULL)
|
||||
{
|
||||
ReferenceLost(); //Ditch our reference
|
||||
|
||||
Object = NULL; //Nullify our object pointer
|
||||
Ref = NULL; //Nullify our counter
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Object != NULL)
|
||||
ReferenceLost(); //Lose our reference to the valid object
|
||||
|
||||
Object = _ptr; //Own it
|
||||
Ref = NULL; //Make sure Ref is set to NULL
|
||||
|
||||
ReferenceGained(); //Create a new reference counter
|
||||
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*
|
||||
= operator overload. Sets this smart pointer to provide a strong reference to the same object
|
||||
managed by the other smart pointer.
|
||||
|
||||
@param _other - the other smart pointer
|
||||
@return (ZSmartPointer<T, DF, R>&) - this smart pointer
|
||||
*/
|
||||
ZSmartPointer<T, DF, R>& operator = (const ZSmartPointer<T, DF, R>& _other)
|
||||
{
|
||||
if (*this == _other || Ref == _other.Counter())
|
||||
return *this;
|
||||
|
||||
ReferenceLost(); //Lose a reference to our current object
|
||||
|
||||
Object = _other.Pointer(); //Own the new one
|
||||
Ref = _other.Counter(); //Get our new reference counter
|
||||
|
||||
ReferenceGained(); //Increment the reference
|
||||
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*
|
||||
= operator overload. Used to assign to derived classes and classes that can
|
||||
be converted to T.
|
||||
|
||||
@param D - the type held by the other smart pointer
|
||||
@param EF - the deallocator type of the other smart pointer
|
||||
@param S - the reference counter allocator type of the other smart pointer
|
||||
@param _other - the other smart pointer
|
||||
@return (ZSmartPointer<T, DF, R>&) - this smart pointer
|
||||
*/
|
||||
template <typename D, typename EF, typename S>
|
||||
ZSmartPointer<T, DF, R>& operator = (const ZSmartPointer<D, EF, S>& _other)
|
||||
{
|
||||
T* testCast = static_cast<T*>(_other.Pointer()); ((void)testCast); //This will fail to compile if T* cannot static cast to D*
|
||||
|
||||
return *this = static_cast< ZSmartPointer<T, DF, R> >(_other);
|
||||
}
|
||||
|
||||
/*
|
||||
== operator overload. Checks to see if this smart pointer owns the provided raw pointer.
|
||||
|
||||
@param _ptr - the pointer to check
|
||||
@return (bool) - true if the pointer is managed by this smart pointer, false otherwise
|
||||
*/
|
||||
bool operator == (const T* _ptr) const
|
||||
{
|
||||
return Object == _ptr;
|
||||
}
|
||||
|
||||
/*
|
||||
== operator overload. Checks to see if these pointers reference the same object.
|
||||
|
||||
@param _other - the other smart pointer
|
||||
@return (bool) - true if equal, false otherwise
|
||||
*/
|
||||
bool operator == (const ZSmartPointer<T, DF, R>& _other) const
|
||||
{
|
||||
return Object == _other.Object;
|
||||
}
|
||||
|
||||
/*
|
||||
== operator overload. Used to compare with smart pointers referencing derived
|
||||
classes or a class that can be converted to T.
|
||||
|
||||
@param _other - the other smart pointer
|
||||
@return (bool) - true if equal, false otherwise
|
||||
*/
|
||||
template <typename D, typename EF, typename S>
|
||||
bool operator == (const ZSmartPointer<D, EF, S>& _other) const
|
||||
{
|
||||
return Object == static_cast<T*>( _other.Pointer());
|
||||
}
|
||||
|
||||
/*
|
||||
!= operator overload. Checks to see if this smart pointer does not
|
||||
own the provided raw pointer.
|
||||
|
||||
@param _ptr - the pointer to check
|
||||
@return (bool) - true if this smart pointer does not reference the provided, false otherwise
|
||||
*/
|
||||
bool operator != (const T* _ptr) const
|
||||
{
|
||||
return !(*this == _ptr);
|
||||
}
|
||||
|
||||
/*
|
||||
!= operator overload. Checks to see if the smart pointers reference different objects.
|
||||
|
||||
@param _other - the other smart pointer
|
||||
@return (bool) - true if this smart pointer and the other do not reference the same object, false otherwise
|
||||
*/
|
||||
bool operator != (const ZSmartPointer<T, DF, R>& _other) const
|
||||
{
|
||||
return !(*this == _other);
|
||||
}
|
||||
|
||||
/*
|
||||
!= operator overload. Checks to see if these pointers reference different objects. Used
|
||||
to compare with derived classes.
|
||||
|
||||
@param D - the type contained by the other smart pointer
|
||||
@param EF - the allocator used by the other smart pointer
|
||||
@param S - the reference counter allocator type used by the other smart pointer
|
||||
@param _other - the other smart pointer
|
||||
@return (bool) - true if this smart pointer and the other do not reference the same object, false otherwise
|
||||
*/
|
||||
template <typename D, typename EF, typename S>
|
||||
bool operator != (const ZSmartPointer<D, EF, S>& _other) const
|
||||
{
|
||||
return !(*this == _other);
|
||||
}
|
||||
|
||||
/*
|
||||
-> operator overload. Allows this to be accessed as a T* would be.
|
||||
|
||||
@return (T*) - raw pointer to the object
|
||||
@assert - if the pointer is NULL
|
||||
*/
|
||||
T* operator -> () const
|
||||
{
|
||||
ZASSERT_RUNTIME(Object != NULL, "ZSmartPointer: Null Pointer Dereferenced!");
|
||||
|
||||
return Object;
|
||||
}
|
||||
|
||||
/*
|
||||
'*' operator overload. Allows this to be dereferenced as a T* would be.
|
||||
|
||||
@return (T&) - reference to the object
|
||||
@assert - if the object is NULL
|
||||
*/
|
||||
T& operator * () const
|
||||
{
|
||||
ZASSERT_RUNTIME(Object != NULL, "ZSmartPointer: Null Pointer Dereferenced!");
|
||||
|
||||
return *Object;
|
||||
}
|
||||
|
||||
/*
|
||||
public ZSmartPointer<T, DF, R>::CounterAllocator
|
||||
|
||||
Gets the reference counter allocator for this smart pointer.
|
||||
|
||||
@return (R&) - the reference counter allocator
|
||||
*/
|
||||
R& CounterAllocator() const
|
||||
{
|
||||
return RefAllocator;
|
||||
}
|
||||
|
||||
/*
|
||||
public ZSmartPointer<T, DF, R>::Cast
|
||||
|
||||
Used to cast this smart pointer into another type. This will construct an
|
||||
additional smart pointer that also references the object. The owned
|
||||
object must be convertible to type C* via static_cast.
|
||||
|
||||
@param C - the type contained by the other type
|
||||
@return (ZSmartPointer<C, DF, R>) - this smart pointer as another type
|
||||
*/
|
||||
template <typename C>
|
||||
ZSmartPointer<C, DF, R> Cast()
|
||||
{
|
||||
return static_cast< ZSmartPointer<C, DF, R> >(*this);
|
||||
}
|
||||
|
||||
/*
|
||||
public ZSmartPointer<T, DF, R>::Counter
|
||||
|
||||
Gets the ZRefrenceCounter instance used by this smart pointer.
|
||||
|
||||
@return (ZReferenceCounter*)- ZRefCounter instance
|
||||
*/
|
||||
ZReferenceCounter* Counter() const
|
||||
{
|
||||
return Ref;
|
||||
}
|
||||
|
||||
/*
|
||||
public ZSmartPointer<T, DF, R>::Deallocator
|
||||
|
||||
Gets the object deallocator for this smart pointer.
|
||||
|
||||
@return (DF&) - reference to the object deallocator
|
||||
*/
|
||||
DF& Deallocator() const
|
||||
{
|
||||
return ObjDeallocator;
|
||||
}
|
||||
|
||||
/*
|
||||
public ZSmartPointer<T, DF, R>::Detach
|
||||
|
||||
Detaches the pointer from memory management by the smart pointer. Should only be
|
||||
called if there is a single strong reference to the object, otherwise it will return
|
||||
NULL. Weak references will be nullified as if the object has been deallocated.
|
||||
|
||||
@return (T*) - raw pointer detached from this smart pointer, or NULL if more
|
||||
than one reference and unable to detach
|
||||
*/
|
||||
T* Detach()
|
||||
{
|
||||
if (Object == NULL || Ref == NULL || Ref->GetStrongRefCount() != 1)
|
||||
return NULL;
|
||||
else
|
||||
{
|
||||
uint32_t combinedCount = Ref->LoseStrongRef(); //Notify everyone we are losing this strong reference
|
||||
|
||||
Ref->SignalDeallocateObject(); //Signal that we are deallocating the object
|
||||
|
||||
if ((combinedCount & ZREFCOUNTER_WEAK_MASK) == 0)
|
||||
RefAllocator.DeallocateCounter(Ref); //Deallocate our reference counter
|
||||
|
||||
T* ptr;
|
||||
|
||||
ptr = Object; //Detach the pointer
|
||||
|
||||
Object = NULL; //Nullify our object reference
|
||||
Ref = NULL; //Nullify our reference counter
|
||||
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
public ZSmartPointer<T, DF, R>::Pointer
|
||||
|
||||
Gets the smart pointer as a raw pointer. Buyer beware.
|
||||
|
||||
@return (T*) - raw pointer that this smart pointer manages
|
||||
*/
|
||||
T* Pointer() const
|
||||
{
|
||||
return Object;
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////
|
||||
/* ZArray Containment Specializations */
|
||||
////////////////////////////////////////
|
||||
|
||||
//Helper function used to nullify references in a range
|
||||
template <typename T, typename DF, typename R>
|
||||
void ZSmartPointerArrayNullify(ZSmartPointer<T, DF, R>* _array, size_t _start, size_t _end)
|
||||
{
|
||||
for (size_t i = _start; i < _end; i++)
|
||||
_array[i] = NULL;
|
||||
}
|
||||
|
||||
//Specialization for ZArray_ClearImpl containing ZSmartPointer
|
||||
template <typename T, typename A, typename DF, typename R>
|
||||
struct ZArray_ClearImpl< ZSmartPointer<T, DF, R>, A> {
|
||||
|
||||
inline static void Call(ZArray<ZSmartPointer<T, DF, R>, A>& _self)
|
||||
{
|
||||
//Nullify references
|
||||
ZSmartPointerArrayNullify(_self.Array, 0, _self.ArraySize);
|
||||
|
||||
//Reset size and check integrity
|
||||
_self.ArraySize = 0;
|
||||
_self.CheckIntegrity();
|
||||
}
|
||||
|
||||
inline static void Call(ZArray<ZSmartPointer<T, DF, R>, A>& _self, size_t _newCapacity)
|
||||
{
|
||||
//Nullify references
|
||||
ZSmartPointerArrayNullify(_self.Array, 0, _self.ArraySize);
|
||||
|
||||
#if !ZSTL_DISABLE_RUNTIME_CHECKS
|
||||
ZSTL_ASSERT(_newCapacity > 0, "ZArray: Cannot set capacity to zero!");
|
||||
#endif
|
||||
|
||||
//Reallocate if needed, drop our size to zero, and check integrity
|
||||
if (_newCapacity > _self.ArrayCapacity)
|
||||
{
|
||||
_self.Deallocate(_self.Array, _self.ArrayCapacity);
|
||||
_self.ArrayCapacity = _newCapacity;
|
||||
_self.Allocate(_self.ArrayCapacity);
|
||||
}
|
||||
|
||||
_self.ArraySize = 0;
|
||||
_self.CheckIntegrity();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//Specialization for ZArray_EraseImpl containing ZSmartPointer
|
||||
template <typename T, typename A, typename DF, typename R>
|
||||
struct ZArray_EraseImpl< ZSmartPointer<T, DF, R>, A> {
|
||||
|
||||
inline static ZSmartPointer<T, DF, R> Call(ZArray<ZSmartPointer<T, DF, R>, A>& _self, size_t _index)
|
||||
{
|
||||
size_t index = _self.BoundsCheck(_index, _self.ArraySize);
|
||||
|
||||
//Grab the currently held element, shift the array down, reduce size, and check integrity
|
||||
ZSmartPointer<T, DF, R> element = _self.Array[index];
|
||||
|
||||
for (size_t i = index; i + 1 < _self.ArraySize; i++)
|
||||
_self.Array[i] = _self.Array[i + 1];
|
||||
|
||||
_self.ArraySize--;
|
||||
_self.CheckIntegrity();
|
||||
|
||||
//Nullify reference
|
||||
ZSmartPointerArrayNullify(_self.Array, _self.ArraySize, _self.ArraySize + 1);
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
inline static void Call(ZArray<ZSmartPointer<T, DF, R>, A>& _self, const size_t _start, const size_t _end)
|
||||
{
|
||||
size_t start = _self.BoundsCheck(_start, _self.ArraySize);
|
||||
size_t end = _self.BoundsCheck(_end, _self.ArraySize + 1);
|
||||
|
||||
#if !ZSTL_DISABLE_RUNTIME_CHECKS
|
||||
ZSTL_ASSERT(start <= end, "ZArray: cannot erase with start < end!");
|
||||
#endif
|
||||
|
||||
//Copy the elements down, compute new size, and check integrity
|
||||
for (size_t idx = start; idx + (end - start) < _self.ArraySize; idx++)
|
||||
_self.Array[idx] = _self.Array[idx + (end - start)];
|
||||
|
||||
_self.ArraySize = _self.ArraySize - (end - start);
|
||||
_self.CheckIntegrity();
|
||||
|
||||
//Nullify references (where we moved from)
|
||||
ZSmartPointerArrayNullify(_self.Array, _self.ArraySize, _self.ArraySize + (end - start));
|
||||
}
|
||||
};
|
||||
|
||||
//Specialization for ZArray_PopBackImpl containing ZSmartPointer
|
||||
template <typename T, typename A, typename DF, typename R>
|
||||
struct ZArray_PopBackImpl< ZSmartPointer<T, DF, R>, A> {
|
||||
|
||||
inline static ZSmartPointer<T, DF, R> Call(ZArray<ZSmartPointer<T, DF, R>, A>& _self)
|
||||
{
|
||||
#if !ZSTL_DISABLE_RUNTIME_CHECKS
|
||||
ZSTL_ASSERT(_self.ArraySize > 0, "ZArray: Cannot pop from array with no elements!");
|
||||
#endif
|
||||
|
||||
ZSmartPointer<T, DF, R> ptr = _self.Array[--(_self.ArraySize)];
|
||||
|
||||
//Nullify reference
|
||||
ZSmartPointerArrayNullify(_self.Array, _self.ArraySize, _self.ArraySize + 1);
|
||||
|
||||
//Grab the last element in the array and decrease our array size
|
||||
return ptr;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//Specialization for ZArray_PopFrontImpl containing ZSmartPointer
|
||||
template <typename T, typename A, typename DF, typename R>
|
||||
struct ZArray_PopFrontImpl< ZSmartPointer<T, DF, R>, A> {
|
||||
|
||||
inline static ZSmartPointer<T, DF, R> Call(ZArray<ZSmartPointer<T, DF, R>, A>& _self)
|
||||
{
|
||||
#if !ZSTL_DISABLE_RUNTIME_CHECKS
|
||||
ZSTL_ASSERT(_self.ArraySize > 0, "ZArray: Cannot pop from array with no elements!");
|
||||
#endif
|
||||
|
||||
//This will nullify the reference
|
||||
return _self.Erase(0);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//Specialization for ZArray_ResizeImpl containing ZSmartPointer
|
||||
template <typename T, typename A, typename DF, typename R>
|
||||
struct ZArray_ResizeImpl< ZSmartPointer<T, DF, R>, A> {
|
||||
|
||||
inline static void Call(ZArray<ZSmartPointer<T, DF, R>, A>& _self, const size_t _size)
|
||||
{
|
||||
//Nullify references if needed
|
||||
if (_size < _self.ArraySize)
|
||||
ZSmartPointerArrayNullify(_self.Array, _size, _self.ArraySize);
|
||||
|
||||
//Check to see if we need more space, change our size, and check integrity
|
||||
if (_size > _self.ArrayCapacity)
|
||||
_self.Reserve(_size);
|
||||
|
||||
_self.ArraySize = _size;
|
||||
_self.CheckIntegrity();
|
||||
}
|
||||
|
||||
inline static void Call(ZArray<ZSmartPointer<T, DF, R>, A>& _self, const size_t _size, const ZSmartPointer<T, DF, R>& _value)
|
||||
{
|
||||
//Nullify references if needed
|
||||
if (_size < _self.ArraySize)
|
||||
ZSmartPointerArrayNullify(_self.Array, _size, _self.ArraySize);
|
||||
|
||||
//See if we need more space, copy in the new value, change our size, and check integrity
|
||||
if (_size > _self.ArrayCapacity)
|
||||
_self.Reserve(_size);
|
||||
|
||||
for (size_t i = _self.ArraySize; i < _size; i++)
|
||||
_self.Array[i] = _value;
|
||||
|
||||
_self.ArraySize = _size;
|
||||
_self.CheckIntegrity();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
///////////////////////////////////////
|
||||
/* ZList Containment Specializations */
|
||||
///////////////////////////////////////
|
||||
|
||||
//Specialization for ZList_ClearImpl containing ZSmartPointer
|
||||
template <typename T, typename A, typename DF, typename R>
|
||||
struct ZList_ClearImpl < ZSmartPointer<T, DF, R>, A> {
|
||||
|
||||
inline static void Call(ZList<ZSmartPointer<T, DF, R>, A>& _self, ZListIterator< ZSmartPointer<T, DF, R> >& _itr) {
|
||||
|
||||
ZListNode<ZSmartPointer<T, DF, R> >* next;
|
||||
ZListNode<ZSmartPointer<T, DF, R> >* current = _itr.GetNode();
|
||||
|
||||
_self.CheckIntegrity();
|
||||
|
||||
//Early out
|
||||
if (_self.Empty())
|
||||
return;
|
||||
|
||||
//If we are the starting node, be sure to reset the EmptyNode.Next pointer
|
||||
if (current == _self.EmptyNode.Next)
|
||||
_self.EmptyNode.Next = &_self.EmptyNode;
|
||||
|
||||
//This is always true
|
||||
_self.EmptyNode.Previous = current->Previous;
|
||||
current->Previous->Next = &_self.EmptyNode;
|
||||
|
||||
//Iterate and deallocate the nodes
|
||||
while (current != &_self.EmptyNode)
|
||||
{
|
||||
next = current->Next;
|
||||
current->Element = NULL; //This is the specialization
|
||||
_self.DeallocateNode(current);
|
||||
current = next;
|
||||
}
|
||||
|
||||
//Set the node on the iterator equal to the end node
|
||||
_itr.SetNode(&_self.EmptyNode);
|
||||
|
||||
_self.CheckIntegrity();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//Specialization for ZList_EraseImpl containing ZSmartPointer
|
||||
template <typename T, typename A, typename DF, typename R>
|
||||
struct ZList_EraseImpl < ZSmartPointer<T, DF, R>, A> {
|
||||
|
||||
inline static ZSmartPointer<T, DF, R> Call(ZList<ZSmartPointer<T, DF, R>, A>& _self, ZListIterator< ZSmartPointer<T, DF, R> >& _itr)
|
||||
{
|
||||
ZSmartPointer<T, DF, R> elem;
|
||||
ZListNode< ZSmartPointer<T, DF, R> > *node = _itr.GetNode();
|
||||
|
||||
#if !ZSTL_DISABLE_RUNTIME_CHECKS
|
||||
ZSTL_ASSERT(node != NULL, "ZList: Iterator is invalid!");
|
||||
ZSTL_ASSERT(node != &_self.EmptyNode, "ZList: Cannot erase end node!");
|
||||
#endif
|
||||
|
||||
//Increment the iterator to the next list node to keep the iterator valid
|
||||
++_itr;
|
||||
|
||||
//Rearrange the pointers
|
||||
node->Previous->Next = node->Next;
|
||||
node->Next->Previous = node->Previous;
|
||||
|
||||
elem = node->Element;
|
||||
node->Element = NULL; //This is the specialization
|
||||
|
||||
_self.DeallocateNode(node);
|
||||
|
||||
_self.CheckIntegrity();
|
||||
|
||||
return elem;
|
||||
}
|
||||
|
||||
inline static void Call(ZList<ZSmartPointer<T, DF, R>, A>& _self, ZListIterator< ZSmartPointer<T, DF, R> >& _start, const ZListIterator< ZSmartPointer<T, DF, R> >& _end)
|
||||
{
|
||||
|
||||
ZListNode< ZSmartPointer<T, DF, R> > *nodeStart = _start.GetNode();
|
||||
ZListNode< ZSmartPointer<T, DF, R> > *nodeEnd = _end.GetNode();
|
||||
|
||||
ZListNode< ZSmartPointer<T, DF, R> > *curNode;
|
||||
ZListNode< ZSmartPointer<T, DF, R> > *prevNode;
|
||||
|
||||
#if !ZSTL_DISABLE_RUNTIME_CHECKS
|
||||
ZSTL_ASSERT(nodeStart != NULL && nodeEnd != NULL, "ZList: Cannot erase with invalid iterator!");
|
||||
ZSTL_ASSERT(nodeStart != &_self.EmptyNode, "ZList: Cannot erase end node!");
|
||||
#endif
|
||||
|
||||
//Rearrange the pointers
|
||||
nodeStart->Previous->Next = nodeEnd;
|
||||
nodeEnd->Previous = nodeStart->Previous;
|
||||
|
||||
//Erase each element between from and to
|
||||
curNode = nodeStart;
|
||||
prevNode = NULL;
|
||||
|
||||
while (curNode != nodeEnd)
|
||||
{
|
||||
#if !ZSTL_DISABLE_RUNTIME_CHECKS
|
||||
ZSTL_ASSERT(curNode != &_self.EmptyNode, "ZList: Cannot erase end node!");
|
||||
#endif
|
||||
|
||||
prevNode = curNode;
|
||||
curNode = curNode->Next;
|
||||
|
||||
prevNode->Element = NULL; //This is the specialization
|
||||
_self.DeallocateNode(prevNode);
|
||||
}
|
||||
|
||||
_start = _end;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//Specialization for ZList_PopBackImpl containing ZSmartPointer
|
||||
template <typename T, typename A, typename DF, typename R>
|
||||
struct ZList_PopBackImpl < ZSmartPointer<T, DF, R>, A> {
|
||||
inline static ZSmartPointer<T, DF, R> Call(ZList<ZSmartPointer<T, DF, R>, A>& _self) {
|
||||
|
||||
ZSmartPointer<T, DF, R> elem;
|
||||
ZListNode< ZSmartPointer<T, DF, R> > *node;
|
||||
|
||||
#if !ZSTL_DISABLE_RUNTIME_CHECKS
|
||||
ZSTL_ASSERT(!_self.Empty(), "ZList: Cannot pop from back of empty list!");
|
||||
#endif
|
||||
|
||||
//Grab the element at the back of the list
|
||||
node = _self.EmptyNode.Previous;
|
||||
|
||||
//Remove the node from the list
|
||||
node->Previous->Next = &_self.EmptyNode;
|
||||
_self.EmptyNode.Previous = node->Previous;
|
||||
|
||||
//Get the element value and lose our reference
|
||||
elem = node->Element;
|
||||
node->Element = NULL;
|
||||
|
||||
//Deallocate and then return
|
||||
_self.DeallocateNode(node);
|
||||
|
||||
_self.CheckIntegrity();
|
||||
|
||||
return elem;
|
||||
}
|
||||
};
|
||||
|
||||
//Specialization for ZList_PopFrontImpl containing ZSmartPointer
|
||||
template <typename T, typename A, typename DF, typename R>
|
||||
struct ZList_PopFrontImpl < ZSmartPointer<T, DF, R>, A> {
|
||||
inline static ZSmartPointer<T, DF, R> Call(ZList<ZSmartPointer<T, DF, R>, A>& _self) {
|
||||
|
||||
ZSmartPointer<T, DF, R> elem;
|
||||
ZListNode< ZSmartPointer<T, DF, R> > *node;
|
||||
|
||||
#if !ZSTL_DISABLE_RUNTIME_CHECKS
|
||||
ZSTL_ASSERT(!_self.Empty(), "ZList: Cannot pop from front of empty list!");
|
||||
#endif
|
||||
|
||||
//Grab the element at the front of the list
|
||||
node = _self.EmptyNode.Next;
|
||||
|
||||
//Remove the node from the list
|
||||
node->Next->Previous = node->Previous;
|
||||
node->Previous->Next = node->Next;
|
||||
|
||||
//Get the element value and lose our reference
|
||||
elem = node->Element;
|
||||
node->Element = NULL;
|
||||
|
||||
//Deallocate and then return
|
||||
_self.DeallocateNode(node);
|
||||
|
||||
_self.CheckIntegrity();
|
||||
|
||||
return elem;
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////
|
||||
/* ZRingBuffer Containment Specializations */
|
||||
/////////////////////////////////////////////
|
||||
|
||||
//Specialization for ZRingBuffer_ClearImpl containing ZSmartPointer
|
||||
template <typename T, typename P, typename A, typename DF, typename R>
|
||||
struct ZRingBuffer_ClearImpl < ZSmartPointer<T, DF, R>, P, A> {
|
||||
inline static void Call( ZRingBuffer< ZSmartPointer<T, DF, R>, P, A>& _self )
|
||||
{
|
||||
// set to null to remove references
|
||||
for (size_t i = 0; i < _self.BufferSize; i++)
|
||||
_self.At(i) = ZSmartPointer<T,DF,R>(NULL);
|
||||
|
||||
_self.BufferSize = 0;
|
||||
_self.FrontIndex = 0;
|
||||
_self.BackIndex = 0;
|
||||
}
|
||||
inline static void Call( ZRingBuffer< ZSmartPointer<T, DF, R>, P, A>& _self, size_t _newCapacity )
|
||||
{
|
||||
// set to null to remove references
|
||||
for (size_t i = 0; i < _self.BufferSize; i++)
|
||||
_self.At(i) = ZSmartPointer<T,DF,R>(NULL);
|
||||
|
||||
_self.Buffer.Resize(_newCapacity);
|
||||
|
||||
_self.BufferSize = 0;
|
||||
_self.FrontIndex = 0;
|
||||
_self.BackIndex = 0;
|
||||
}
|
||||
};
|
||||
|
||||
//Specialization for ZRingBuffer_EraseImpl containing ZSmartPointer
|
||||
template <typename T, typename P, typename A, typename DF, typename R>
|
||||
struct ZRingBuffer_EraseImpl < ZSmartPointer<T, DF, R>, P, A> {
|
||||
inline static T Call( ZRingBuffer< ZSmartPointer<T, DF, R>, P, A>& _self, size_t _index)
|
||||
{
|
||||
//We are going to do this in a very naive fashion, as this container is not intended for these
|
||||
//kinds of operations anyhow. Anyone who wishes to optimize this at a later date is welcome.
|
||||
|
||||
_self.AlignBuffer();
|
||||
|
||||
_self.BufferSize--;
|
||||
_self.BackIndex--;
|
||||
|
||||
// set to null to remove references
|
||||
ZSmartPointer<T, DF, R> ret = _self.Buffer.At(_index);
|
||||
_self.Buffer.At(_index) = ZSmartPointer<T, DF, R>(NULL);
|
||||
return ret;
|
||||
|
||||
}
|
||||
inline static void Call( ZRingBuffer< ZSmartPointer<T, DF, R>, P, A>& _self, size_t _i, size_t _j )
|
||||
{
|
||||
//We are going to do this in a very naive fashion, as this container is not intended for these
|
||||
//kinds of operations anyhow. Anyone who wishes to optimize this at a later date is welcome.
|
||||
|
||||
size_t count;
|
||||
|
||||
_self.AlignBuffer();
|
||||
|
||||
count = (size_t)(_j - _i);
|
||||
|
||||
_self.BufferSize = _self.BufferSize - count;
|
||||
_self.BackIndex = _self.BackIndex - count;
|
||||
|
||||
// set to null to remove references
|
||||
for( size_t i = _i; i < _j; i++)
|
||||
_self.Buffer.At(i) = ZSmartPointer<T, DF, R>(NULL);
|
||||
|
||||
_self.Buffer.Erase(_i, _j);
|
||||
}
|
||||
};
|
||||
|
||||
//Specialization for ZRingBuffer_PopBackImpl containing ZSmartPointer
|
||||
template <typename T, typename P, typename A, typename DF, typename R>
|
||||
struct ZRingBuffer_PopBackImpl < ZSmartPointer<T, DF, R>, P, A> {
|
||||
inline static T Call( ZRingBuffer< ZSmartPointer<T, DF, R>, P, A>& _self )
|
||||
{
|
||||
#if !ZSTL_DISABLE_RUNTIME_CHECKS
|
||||
ZSTL_ASSERT( _self.BufferSize > 0, "ZRingBuffer::PopBack() caused underflow!");
|
||||
#endif
|
||||
|
||||
size_t index = _self.BackIndex;
|
||||
|
||||
_self.DecrementBack();
|
||||
|
||||
_self.CheckIntegrity();
|
||||
|
||||
// set to NULL to fix ref count issues
|
||||
ZSmartPointer< T, DF, R > ret = _self.Buffer.At(index);
|
||||
_self.Buffer.At(index) = ZSmartPointer< T, DF, R>(NULL);
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
//Specialization for ZRingBuffer_PopFrontImpl containing ZSmartPointer
|
||||
template <typename T, typename P, typename A, typename DF, typename R>
|
||||
struct ZRingBuffer_PopFrontImpl < ZSmartPointer<T, DF, R>, P, A> {
|
||||
inline static T Call( ZRingBuffer< ZSmartPointer<T, DF, R>, P, A>& _self )
|
||||
{
|
||||
#if !ZSTL_DISABLE_RUNTIME_CHECKS
|
||||
ZSTL_ASSERT( _self.BufferSize > 0, "ZRingBuffer::PopFront() caused underflow!");
|
||||
#endif
|
||||
|
||||
size_t index = _self.FrontIndex;
|
||||
|
||||
_self.IncrementFront();
|
||||
|
||||
_self.CheckIntegrity();
|
||||
|
||||
// set to NULL to fix ref count issues
|
||||
ZSmartPointer< T, DF, R > ret = _self.Buffer.At(index);
|
||||
_self.Buffer.At(index) = ZSmartPointer< T, DF, R>(NULL);
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
404
Include/ZUtil/ZTaskStream.hpp
Normal file
404
Include/ZUtil/ZTaskStream.hpp
Normal file
@@ -0,0 +1,404 @@
|
||||
/*
|
||||
ZTaskStream.hpp
|
||||
Author: James Russell <jcrussell@762studios.com>
|
||||
|
||||
Purpose: Manages the execution of 'Tasks' by a number of threads determined at runtime. Attempts to parallelize
|
||||
execution as well as possible with the provided information.
|
||||
|
||||
Changelog
|
||||
2011/04/10 - creation (jcrussell)
|
||||
*/
|
||||
|
||||
#ifndef _ZTASKSTREAM_H
|
||||
#define _ZTASKSTREAM_H
|
||||
|
||||
#include <ZUtil/ZThread.hpp>
|
||||
#include <stdlib.h> //size_t
|
||||
|
||||
//Forward Declarations
|
||||
class ZTaskStream;
|
||||
|
||||
typedef size_t ZTaskPriority; //Task Priority
|
||||
typedef size_t ZTaskThreadId; //Task Thread Id
|
||||
|
||||
//Definition for immediate task execution priority
|
||||
#define ZTASK_PRIORITY_IMMEDIATE (0)
|
||||
|
||||
//Default allocator buffer size for the task thread
|
||||
#define ZTT_DEFAULT_BUFFER_SIZE 256
|
||||
|
||||
//Default allocator buffer size for the task stream
|
||||
#define ZTS_DEFAULT_BUFFER_SIZE 1024
|
||||
|
||||
/*
|
||||
ZTask execute return values.
|
||||
*/
|
||||
enum ZTaskReturnStatus
|
||||
{
|
||||
ZTRS_SUCCESS, // Task has succeeded
|
||||
ZTRS_FAILURE, // Task has failed
|
||||
|
||||
ZTRS_ENUM_SIZE
|
||||
};
|
||||
|
||||
/*
|
||||
ZTask thread Status enumeration.
|
||||
*/
|
||||
enum ZTaskThreadStatus
|
||||
{
|
||||
ZTTS_UNINITIALIZED, // Task thread is uninitialized
|
||||
ZTTS_WAITING, // Task thread is awaiting tasks
|
||||
ZTTS_EXECUTING, // Task thread is executing tasks
|
||||
|
||||
ZTTS_ENUM_SIZE
|
||||
};
|
||||
|
||||
/*
|
||||
Tasks are the basic unit of execution for a ZTaskStream. They are added to the ZTaskStream and
|
||||
assigned to a thread for execution. They are then executed as TaskThreads
|
||||
become available.
|
||||
*/
|
||||
class ZTask
|
||||
{
|
||||
friend class ZTaskThread;
|
||||
friend class ZTaskStream;
|
||||
public:
|
||||
ZTaskStream* TaskStream; // The task stream that is executing this task
|
||||
ZTaskPriority Priority; // Priority, assigned at construction, decreased each time it is delayed to zero, which is immediate priority
|
||||
bool bCancelTask; // Cancel Boolean, if set to true, will prevent the task from being executed
|
||||
|
||||
/*
|
||||
Parameterized c'tor (with default arguments).
|
||||
|
||||
@param _priority - The amount of time (in ms) the task can be delayed is priority. This means the closer to zero
|
||||
the priority is set, the faster it will be executed.
|
||||
*/
|
||||
ZTask(ZTaskPriority _priority = ZTASK_PRIORITY_IMMEDIATE)
|
||||
: TaskStream(NULL), Priority(_priority), bCancelTask(false), Func(NULL), TaskArgument(NULL) { }
|
||||
|
||||
/*
|
||||
Parameterized c'tor.
|
||||
|
||||
@param _func - function to execute
|
||||
@param _taskArg - argument to the task
|
||||
@param _priority - The amount of time (in ms) the task can be delayed is priority. This means the closer to zero
|
||||
the priority is set, the faster it will be executed.
|
||||
*/
|
||||
ZTask(ZTaskReturnStatus (*_func)(ZTaskStream*, ZTask*, void*), void *_taskArg, ZTaskPriority _priority = ZTASK_PRIORITY_IMMEDIATE)
|
||||
: TaskStream(NULL), Priority(_priority), bCancelTask(false), Func(_func),TaskArgument(_taskArg) { }
|
||||
|
||||
/*
|
||||
Destructor.
|
||||
*/
|
||||
virtual ~ZTask() { }
|
||||
|
||||
/*
|
||||
virtual public ZTask::Execute
|
||||
|
||||
Execute method. Defined by the task implementation.
|
||||
|
||||
@param _arg - argument to the task (NULL by default)
|
||||
@return (ZTaskReturnStatus) - task return value
|
||||
*/
|
||||
virtual ZTaskReturnStatus Execute(void *_arg)
|
||||
{ URFP(_arg); if (Func != NULL) return Func(TaskStream, this, TaskArgument); else return ZTRS_FAILURE; }
|
||||
|
||||
/*
|
||||
virtual public ZTask::OnTaskFailed
|
||||
|
||||
Handler function for task failure. No-op by default.
|
||||
|
||||
@return (void)
|
||||
*/
|
||||
virtual void OnTaskFailed(void *_taskArgument)
|
||||
{ URFP(_taskArgument); }
|
||||
|
||||
protected:
|
||||
ZTaskReturnStatus (*Func)(ZTaskStream*, ZTask*, void*); // function for the ZTask to execute if not implemented as a subtask
|
||||
void* TaskArgument; // Argument passed to this task
|
||||
};
|
||||
|
||||
/*
|
||||
Future. Used to asynchronously execute a function that will return a value when completed.
|
||||
*/
|
||||
template <typename R, typename A>
|
||||
class ZFuture
|
||||
{
|
||||
friend class ZTaskStream;
|
||||
protected:
|
||||
// Future Task
|
||||
class ZFutureTask : public ZTask
|
||||
{
|
||||
public:
|
||||
R (*Func)(A); // The Function
|
||||
A Arg; // The argument
|
||||
R Ret; // The return value
|
||||
bool Completed; // Completed flag
|
||||
ZEvent CompletedEvent; // Completed Event
|
||||
|
||||
// c'tor
|
||||
ZFutureTask(R (*_func)(A), A _arg)
|
||||
: ZTask(), Func(_func), Arg(_arg), Ret(), Completed(false), CompletedEvent() { }
|
||||
|
||||
// d'tor
|
||||
~ZFutureTask() { }
|
||||
|
||||
// subclass override
|
||||
virtual ZTaskReturnStatus Execute(void *_arg)
|
||||
{
|
||||
URFP(_arg);
|
||||
|
||||
CompletedEvent.Reset();
|
||||
Ret = Func(Arg);
|
||||
Completed = true;
|
||||
CompletedEvent.Notify();
|
||||
|
||||
return ZTRS_SUCCESS;
|
||||
}
|
||||
};
|
||||
|
||||
ZPtr<ZFutureTask> FutureTask; // The function execute task
|
||||
|
||||
public:
|
||||
/*
|
||||
Parameterized c'tor.
|
||||
|
||||
@param _func - the function to execute, must return a value of type R
|
||||
@param _arg - argument to the function
|
||||
*/
|
||||
ZFuture(R (_func)(A), A _arg) : FutureTask(znew ZFutureTask(_func, _arg)) { }
|
||||
|
||||
/*
|
||||
public ZFuture<R, A>::IsComplete
|
||||
|
||||
Returns whether or not the future has completed.
|
||||
|
||||
@return (bool) - true if the task has completed
|
||||
*/
|
||||
bool IsComplete() { return FutureTask->Completed; }
|
||||
|
||||
/*
|
||||
public ZFuture<R, A>::GetValue
|
||||
|
||||
Gets the return value from the future.
|
||||
|
||||
@return (R) - return from the task
|
||||
*/
|
||||
R GetValue() { if (!FutureTask->Completed) FutureTask->CompletedEvent.Wait(); return FutureTask->Ret; }
|
||||
|
||||
/*
|
||||
public ZFuture<R, A>::GetValueRef
|
||||
|
||||
Gets the return value from the future as a reference.
|
||||
|
||||
@return (R&) - reference to return from the task
|
||||
*/
|
||||
R& GetValueRef() { if (!FutureTask->Completed) FutureTask->CompletedEvent.Wait(); return FutureTask->Ret; }
|
||||
};
|
||||
|
||||
/*
|
||||
Threads which execute tasks in the ZTaskStream. The number of operating Task Threads is
|
||||
assigned at construction of a ZTaskStream and can be changed.
|
||||
*/
|
||||
class ZTaskThread : public ZThread
|
||||
{
|
||||
friend class ZTaskStream;
|
||||
public:
|
||||
/*
|
||||
Parameterized c'tor.
|
||||
|
||||
@param _stream - the stream giving us tasks
|
||||
@param _id - the id of this task
|
||||
*/
|
||||
ZTaskThread(ZTaskStream *_stream, ZTaskThreadId _id);
|
||||
|
||||
// d'tor
|
||||
virtual ~ZTaskThread();
|
||||
|
||||
/*
|
||||
public ZTaskThread::PushTask()
|
||||
|
||||
Adds a task to the task thread.
|
||||
|
||||
@param _task - the task to add to this task thread (argument already set)
|
||||
@return (void)
|
||||
*/
|
||||
void PushTask(ZPtr<ZTask> _task);
|
||||
|
||||
protected:
|
||||
// Subclass implementation of thread run, which executes tasks
|
||||
ZThreadReturn run(uint64_t _dt);
|
||||
|
||||
private:
|
||||
ZMutex TaskLock; // Concurrency lock
|
||||
ZSemaphore TaskSema; // Event that is set when new tasks are available
|
||||
ZTaskStream* Stream; // The task stream providing us with tasks
|
||||
ZTaskThreadId Id; // Task thread ID, used to identify this task thread
|
||||
ZTaskThreadStatus ThrStatus; // Status of this task thread
|
||||
|
||||
ZTaskPriority CurrentTaskPriority; //The priority of the currently executing task
|
||||
ZArray< ZPtr<ZTask> > Tasks; //Set of tasks to execute
|
||||
};
|
||||
|
||||
/*
|
||||
The task stream. Assigns tasks to task threads that execute when desired. Can also
|
||||
handle 'background' tasks.
|
||||
*/
|
||||
class ZTaskStream
|
||||
{
|
||||
public:
|
||||
/*
|
||||
Default c'tor.
|
||||
|
||||
Creates a single task thread. The amount of task threads running concurrently can be changed
|
||||
using SetTaskThreadCount.
|
||||
*/
|
||||
ZTaskStream();
|
||||
|
||||
// d'tor
|
||||
~ZTaskStream();
|
||||
|
||||
/*
|
||||
public ZTaskStream::ExecuteTasks
|
||||
|
||||
Begins execution on the currently loaded set of tasks and any further tasks generated
|
||||
during the execution of those tasks. Returns after all tasks that will be executed this
|
||||
frame are done executing.
|
||||
|
||||
Tasks that were not completed have had their priority values reduced, meaning that if
|
||||
they are again added to the ZTaskStream for execution repeatedly until executed, they
|
||||
are guaranteed to eventually execute within their priority time frame.
|
||||
|
||||
@param _frameTime - (given in ms) is the desired amount of time that execution of all tasks
|
||||
should take; if any time is remaining after execution of ALL priority zero
|
||||
tasks, a number of extra priority > 0 tasks are executed as can be fit into
|
||||
the extra time. Because of this definition, frameTime is an estimate and
|
||||
not a guarantee - execution of priority 0 tasks can take more than frameTime.
|
||||
@return (void)
|
||||
*/
|
||||
void ExecuteTasks(int _frameTime);
|
||||
|
||||
/*
|
||||
public ZTaskStream::GetTaskThreadCount
|
||||
|
||||
Gets the current number of worker threads.
|
||||
|
||||
@return (size_t) - number of task stream worker threads
|
||||
*/
|
||||
size_t GetTaskThreadCount();
|
||||
|
||||
/*
|
||||
public ZTaskStream::HaltFrame
|
||||
|
||||
Notifies the ZTaskStream to stop assigning tasks tasks and return from the ExecuteTasks
|
||||
call that started the process. This does not stop the execution of tasks that have already
|
||||
been assigned.
|
||||
|
||||
@return (void)
|
||||
*/
|
||||
void HaltFrame();
|
||||
|
||||
/*
|
||||
public ZTaskStream::Pause
|
||||
|
||||
Notifies the ZTaskStream to pause task execution for all tasks.
|
||||
|
||||
@param _pause - true to pause the stream, false to unpause
|
||||
@return (void)
|
||||
*/
|
||||
void PauseFrame(bool _pause);
|
||||
|
||||
/*
|
||||
public ZTaskStream::PushFuture
|
||||
|
||||
Adds a ZFuture to the task stream, which will execute the future at the soonest available
|
||||
opportunity.
|
||||
|
||||
The ZSmartPointer version will hold a reference to the future until after execution. If
|
||||
the raw pointer version is used, the user is required to keep the pointer valid until after
|
||||
execution.
|
||||
|
||||
@param _future - the future to execute
|
||||
@return (void)
|
||||
*/
|
||||
template <typename R, typename A>
|
||||
void PushFuture(ZPtr< ZFuture<R, A> > _future) {
|
||||
TaskThreads[AssignTask(_future->FutureTask.Pointer())]->PushTask(_future->FutureTask);
|
||||
}
|
||||
|
||||
template <typename R, typename A>
|
||||
void PushFuture(ZFuture<R, A>* _future) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
/*
|
||||
public ZTaskStream::PushTask
|
||||
|
||||
Adds a task to the task list. The task is added to the task queue in the currently executing
|
||||
frame phase, or if a phase is not yet executing, it will be added to the next frame phase to
|
||||
execute.
|
||||
|
||||
The ZSmartPointer version will hold a reference to the task until after execution. If the
|
||||
raw pointer version is used, the user is required to keep the pointer valid until after
|
||||
execution.
|
||||
|
||||
@param _task - the task to add
|
||||
@return (void) - the id of the task
|
||||
*/
|
||||
void PushTask(ZPtr<ZTask> _task);
|
||||
void PushTask(ZTask* _task);
|
||||
|
||||
/*
|
||||
public ZTaskStream::PushTasks
|
||||
|
||||
Adds a list of tasks. Identical to PushTask() but with less locking overhead. The list of
|
||||
tasks is not emptied (i.e _tasks.Clear() is not called).
|
||||
|
||||
The ZSmartPointer version will hold a reference to the tasks until after execution. If the
|
||||
raw pointer version is used, the user is required to keep the pointer valid until after
|
||||
execution.
|
||||
|
||||
@param _tasks - the tasks to add
|
||||
@param _count - the number of tasks
|
||||
@return (void)
|
||||
*/
|
||||
void PushTasks(ZArray< ZPtr<ZTask> >& _tasks);
|
||||
void PushTasks(ZTask* _tasks, size_t _count);
|
||||
|
||||
/*
|
||||
public ZTaskStream::SetTaskThreadCount
|
||||
|
||||
Sets the number of task threads that will be running. Should be greater than zero, or the
|
||||
call has no effect.
|
||||
|
||||
@param _count - the number of task threads to run simultaneously
|
||||
|
||||
@return (void)
|
||||
*/
|
||||
void SetTaskThreadCount(size_t _count);
|
||||
|
||||
protected:
|
||||
ZMutex TaskStreamLock; // Lock for controlling access to the ZTaskStream objects
|
||||
ZSemaphore TaskStreamSema; // Semaphore for signaling events
|
||||
ZEvent FrameCompletedEvent; // Event for notifying the execute caller thread that a frame is completed
|
||||
ZEvent PausedEvent; // Event for pausing the Task Stream
|
||||
ZArray<ZTaskThread*> TaskThreads; // Task threads that run the set of tasks
|
||||
ZArray< ZPtr<ZTask> > Tasks; // The task list
|
||||
|
||||
// Pause flag, which indicates that task execution should be paused
|
||||
// This is only used for debugging purposes, 'PausedEvent' has the same state
|
||||
// wrapped into an OS object.
|
||||
bool bPaused;
|
||||
|
||||
//Halt flag, which indicates that task execution should halt
|
||||
bool bShouldHalt;
|
||||
|
||||
//Assigns a task to one of the task threads
|
||||
ZTaskThreadId AssignTask( ZTask *_task);
|
||||
|
||||
//Kills a given task thread
|
||||
void KillTaskThread(size_t _idx);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
368
Include/ZUtil/ZThread.hpp
Normal file
368
Include/ZUtil/ZThread.hpp
Normal file
@@ -0,0 +1,368 @@
|
||||
/*
|
||||
ZThread.hpp
|
||||
Author : James Russell <jcrussell@762studios.com>
|
||||
Created: 07/04/09
|
||||
|
||||
Purpose :
|
||||
|
||||
Wrapper class to allow easy thread creation. By making a class that is
|
||||
a subclass of ZThread and defining the run() method, a thread 'object' can
|
||||
be created that allows for greater consistency and when dealing with thread
|
||||
resources.
|
||||
|
||||
License:
|
||||
|
||||
TODO
|
||||
*/
|
||||
|
||||
#ifndef _ZTHREAD_H
|
||||
#define _ZTHREAD_H
|
||||
|
||||
#include <ZSTL/ZList.hpp>
|
||||
#include <ZSTL/ZString.hpp>
|
||||
|
||||
#include <ZUtil/ZConcurrency.hpp>
|
||||
#include <ZUtil/ZSmartPointer.hpp>
|
||||
|
||||
class ZThread;
|
||||
typedef void (*ZThreadCallbackFunc)(ZThread* executor, void* arg);
|
||||
|
||||
/*
|
||||
Macro that creates an anonymous request object for marshalling code into a thread request.
|
||||
|
||||
Example:
|
||||
|
||||
TODO
|
||||
|
||||
@param zthread - the zthread object that should execute the request
|
||||
@param argument - the void* argument to pass in (accessible as Arg)
|
||||
@param wait - a boolean indicating if we should wait or not
|
||||
@param code - the actual code that should be executed as part of the request (wrap in parenthesis)
|
||||
*/
|
||||
#define ZTHREAD_EXECUTE(zthread, argument, wait, code) \
|
||||
{ \
|
||||
class Z##__FUNCTION__##__LINE__##ThreadRequest : public ZThreadRequest \
|
||||
{ \
|
||||
protected: \
|
||||
void *Arg; \
|
||||
public: \
|
||||
Z##__FUNCTION__##__LINE__##ThreadRequest() : ZThreadRequest(), Arg(argument) { } \
|
||||
\
|
||||
virtual void Execute(ZThread *_threadObj) \
|
||||
{ \
|
||||
code \
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
zthread->AddThreadRequest(ZPtr<ZThreadRequest>(znew Z##__FUNCTION__##__LINE__##ThreadRequest), wait); \
|
||||
}
|
||||
|
||||
//Forward declaration of ZThread
|
||||
class ZThread;
|
||||
|
||||
//Possible return values from ZThread run
|
||||
typedef enum ZThreadReturn
|
||||
{
|
||||
ZTR_TERMINATE, //Indicates the thread should terminate after returning from run
|
||||
ZTR_LOOP, //Indicates the thread should loop after returning from run
|
||||
ZTR_PAUSE, //Indicates the thread should pause after returning from run
|
||||
ZTR_SIZE
|
||||
} ZThreadReturn;
|
||||
|
||||
/*
|
||||
A ZThread 'Request' object. Used for thread marshaling.
|
||||
*/
|
||||
class ZThreadRequest
|
||||
{
|
||||
friend class ZThread;
|
||||
private:
|
||||
//Completion Event
|
||||
ZEvent CompletedEvent;
|
||||
|
||||
//Indicates this 'ThreadRequest' should persist until removed
|
||||
bool Persist;
|
||||
|
||||
//Indicates to the ZThread that this request should stop running immediately
|
||||
//This value is checked before execution
|
||||
bool Stop;
|
||||
|
||||
public:
|
||||
/*
|
||||
Default Constructor.
|
||||
|
||||
@param _persist - boolean indicating this thread request should execute continuously until
|
||||
the ZThread object is deleted
|
||||
*/
|
||||
ZThreadRequest(bool _persist = false)
|
||||
: CompletedEvent(), Persist(_persist), Stop(false) { }
|
||||
|
||||
/*
|
||||
Destructor.
|
||||
|
||||
Destroys the concurrency event.
|
||||
*/
|
||||
virtual ~ZThreadRequest() { }
|
||||
|
||||
/*
|
||||
virtual public ZThreadRequest::Execute
|
||||
|
||||
Virtual method, which defines the thread request to be executed. The function will be executed
|
||||
from within the ZThread object's thread context. If this method is not overridden and Func is not
|
||||
NULL, Func is called with the provided argument.
|
||||
|
||||
@param _threadObj - the ZThread object executing this request
|
||||
|
||||
@return (void)
|
||||
*/
|
||||
virtual void Execute(ZThread *_threadObj) = 0;
|
||||
|
||||
/*
|
||||
public ZThreadRequest::StopExecution
|
||||
|
||||
Stops execution of the thread request, provided it has not executed yet.
|
||||
|
||||
@return (void)
|
||||
*/
|
||||
void StopExecution() { this->Stop = true; }
|
||||
|
||||
/*
|
||||
public ZThreadRequest::Wait
|
||||
|
||||
Blocks until after the thread request has been executed.
|
||||
|
||||
@return (void)
|
||||
*/
|
||||
void Wait() { CompletedEvent.Wait(); }
|
||||
};
|
||||
|
||||
/*
|
||||
ZThread object class. Should be subclassed to make a threadable 'object'.
|
||||
*/
|
||||
class ZThread
|
||||
{
|
||||
private:
|
||||
DISABLE_COPY_AND_ASSIGN(ZThread);
|
||||
|
||||
public:
|
||||
/*
|
||||
Default Constructor.
|
||||
|
||||
@param _threadName - the name of this thread
|
||||
*/
|
||||
ZThread(ZString _threadName = "");
|
||||
|
||||
/*
|
||||
Destructor for the ZThread Object. When the ZThread object is deleted, the destructor will wait on
|
||||
the thread to terminate and return resources to the system.
|
||||
*/
|
||||
virtual ~ZThread();
|
||||
|
||||
/*
|
||||
public ZThread::AddThreadRequest()
|
||||
|
||||
Adds a callback that will be executed when the thread loops.
|
||||
|
||||
@param _request - the thread request to add to the thread's context
|
||||
|
||||
@return (void)
|
||||
*/
|
||||
void AddThreadRequest(ZPtr<ZThreadRequest> _request, bool _wait = false);
|
||||
|
||||
/*
|
||||
public ZThread::AddCallbackRequest()
|
||||
|
||||
Adds a callback to be executed by the thread. It can be executed synchronously or asynchronously.
|
||||
|
||||
@param function - The function to execute
|
||||
@param arg - The argument
|
||||
@param async - If true, this returns immediately, otherwise it waits for the function to execute.
|
||||
|
||||
@return (void)
|
||||
*/
|
||||
void AddCallbackRequest(ZThreadCallbackFunc function, void* arg, bool async);
|
||||
|
||||
/*
|
||||
public ZThread::GetThreadID
|
||||
|
||||
Gets the thread ID of the thread object.
|
||||
|
||||
@return (uint32_t) - int that is the thread id of the thread object
|
||||
*/
|
||||
uint32_t GetThreadId();
|
||||
|
||||
/*
|
||||
public ZThread::GetThreadName
|
||||
|
||||
Gets the thread name of the ZThread object. The name of a thread is either a
|
||||
string value of the thread id or a name that was set by the ZThread object.
|
||||
|
||||
@return (ZString) - string representing the 'name' of this thread
|
||||
*/
|
||||
ZString GetThreadName();
|
||||
|
||||
/*
|
||||
public ZThread::PauseThread
|
||||
|
||||
Tells the user thread to pause.
|
||||
|
||||
@return (void)
|
||||
*/
|
||||
void PauseThread();
|
||||
|
||||
/*
|
||||
public ZThread::RestartThread
|
||||
|
||||
Restarts a paused thread.
|
||||
|
||||
@return (void)
|
||||
*/
|
||||
void RestartThread();
|
||||
|
||||
/*
|
||||
public ZThread::ThreadRunning
|
||||
|
||||
Indicates if a ZThread object is executing it's run method or is paused.
|
||||
|
||||
@return (bool) - boolean indicating thread is running or is paused
|
||||
*/
|
||||
bool ThreadRunning();
|
||||
|
||||
/*
|
||||
public ZThread::ThreadInitialized
|
||||
|
||||
Returns true if the ZThread object has called it's initThread() method and returned.
|
||||
|
||||
@return (bool) - boolean indicating the thread is initialized
|
||||
*/
|
||||
bool ThreadInitialized();
|
||||
|
||||
/*
|
||||
public ZThread::ShutdownThread
|
||||
|
||||
Tells the user thread to shutdown. Blocks until it happens.
|
||||
|
||||
@return (void)
|
||||
*/
|
||||
void ShutdownThread();
|
||||
|
||||
/*
|
||||
public ZThread::StartThread
|
||||
|
||||
When StartThread is called on a class that extends ZThread, a thread will be created
|
||||
that will call the run() function implemented by the subclass.
|
||||
|
||||
@return (bool) - boolean indicating the thread has started successfully
|
||||
*/
|
||||
bool StartThread();
|
||||
|
||||
/*
|
||||
public ZThread::WaitInitialized
|
||||
|
||||
Caller waits until the ZThread has initialized.
|
||||
|
||||
@return (void)
|
||||
@context (all)
|
||||
*/
|
||||
void WaitInitialized();
|
||||
|
||||
/*
|
||||
public ZThread::WaitShutdown
|
||||
|
||||
Caller waits until the ZThread has shutdown.
|
||||
|
||||
@return (void)
|
||||
@context (all)
|
||||
*/
|
||||
void WaitShutdown();
|
||||
|
||||
protected:
|
||||
//Thread 'name' of this thread
|
||||
ZString ThreadName;
|
||||
|
||||
//Boolean field which, when set to true, indicates the thread should terminate.
|
||||
bool bShouldShutdown;
|
||||
|
||||
//Boolean field which, when set to true, indicates the thread should pause.
|
||||
bool bShouldPause;
|
||||
|
||||
/*
|
||||
This is a wrapper around the user run() method, which calls that method in a loop, executing
|
||||
thread requests and setting the condition variables appropriately.
|
||||
*/
|
||||
void Run();
|
||||
|
||||
/*
|
||||
Executes the thread requests that may be pending at the time it is called by the subclass.
|
||||
*/
|
||||
void ExecuteThreadRequests();
|
||||
|
||||
/*
|
||||
Initialization method which is called when the thread starts. Does not have to be overridden, but any
|
||||
thread specific initialization that must be done in the thread context of the ZThread object needs
|
||||
to be defined here.
|
||||
*/
|
||||
virtual void initThread() { }
|
||||
|
||||
/*
|
||||
Shutdown method which is called when the thread terminates. Does not have to be overridden, but any
|
||||
thread specific shutdown requirements that must be done in the thread context of the ZThread object
|
||||
needs to be defined here.
|
||||
*/
|
||||
virtual void shutdownThread() { }
|
||||
|
||||
/*
|
||||
This method must be implemented by the ZThread subclass. This is the 'main' function of execution for
|
||||
the newly created thread.
|
||||
|
||||
@param _dt - the time (in ms) since last time run was called
|
||||
@return - a ZTHREAD_RETURN value indicating whether the thread should run once (ZTR_TERMINATE),
|
||||
loop (ZTR_RETURN), or pause (ZTR_PAUSE).
|
||||
*/
|
||||
virtual ZThreadReturn run(uint64_t _dt) = 0;
|
||||
|
||||
bool IsCallerTheThread();
|
||||
private:
|
||||
struct ZThreadCallbackRequest {
|
||||
ZThreadCallbackFunc callback;
|
||||
void* arg;
|
||||
SST_Event doneEvent;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//Thread context of this thread
|
||||
ZThreadContext ThreadContext;
|
||||
|
||||
//The mutex for use by this thread object for handling thread marshaling.
|
||||
ZMutex ThreadLock;
|
||||
|
||||
//The event signaled when the thread has finished initializing
|
||||
ZEvent InitEvent;
|
||||
|
||||
//Previous tick count for this thread object
|
||||
uint64_t PreviousTickCount;
|
||||
|
||||
//Current tick count for this thread object
|
||||
uint64_t CurrentTickCount;
|
||||
|
||||
//Boolean field which, when set to true, indicates the thread is initialized and running.
|
||||
bool bIsRunning;
|
||||
|
||||
//Boolean field which, when set to true, indicates the thread has called and returned from initThread()
|
||||
bool bIsInitialized;
|
||||
|
||||
//List of callbacks that will occur when the ZThread object runs.
|
||||
ZList< ZPtr<ZThreadRequest> > ZTRCallbacks; // ZTR callbacks
|
||||
ZList< ZThreadCallbackRequest > Callbacks; // Simple (non-object) callbacks
|
||||
|
||||
/*
|
||||
Proxy method called by StartThread() which will call initThread and Run on the ZThread Object.
|
||||
|
||||
@param _runnable - a pointer to the ZThread object to run
|
||||
@return - integer condition (not used)
|
||||
*/
|
||||
static int InitThread(void *_runnable);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
49
Include/ZUtil/ZUtil.hpp
Normal file
49
Include/ZUtil/ZUtil.hpp
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
ZUtil.hpp
|
||||
Author: James Russell <jcrussell@762studios.com>
|
||||
Created: 12/26/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
Header for the ZUtil project that includes all other ZUtil headers
|
||||
in the proper order.
|
||||
|
||||
License:
|
||||
|
||||
TODO
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _ZUTIL_HPP
|
||||
#define _ZUTIL_HPP
|
||||
|
||||
/* ZUtil Project Build File */
|
||||
#include <ZUtil/ZUtilBuild.hpp>
|
||||
|
||||
/* External Includes */
|
||||
#include <ZSTL/ZSTL.hpp>
|
||||
|
||||
/* Standard Util Includes */
|
||||
#include <ZUtil/ZAssert.hpp>
|
||||
#include <ZUtil/ZAlloc.hpp>
|
||||
#include <ZUtil/ZConcurrency.hpp>
|
||||
#include <ZUtil/ZLog.hpp>
|
||||
#include <ZUtil/ZThread.hpp>
|
||||
|
||||
#include <ZUtil/ZTaskStream.hpp>
|
||||
|
||||
#include <ZUtil/ZName.hpp>
|
||||
#include <ZUtil/ZBitmap.hpp>
|
||||
|
||||
#include <ZUtil/ZSmartPointer.hpp>
|
||||
#include <ZUtil/ZWeakPointer.hpp>
|
||||
#include <ZUtil/ZSlabAllocator.hpp>
|
||||
|
||||
#include <ZUtil/ZBinaryBufferReader.hpp>
|
||||
#include <ZUtil/ZBinaryBufferWriter.hpp>
|
||||
|
||||
#include <ZUtil/ZKVTree.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
121
Include/ZUtil/ZUtilBuild.hpp
Normal file
121
Include/ZUtil/ZUtilBuild.hpp
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
ZUtilBuild.hpp
|
||||
Author: James Russell <jcrussell@762studios.com>
|
||||
Created: 11/7/2010
|
||||
|
||||
Purpose:
|
||||
|
||||
Used to generate definitions for the preprocessor using only compiler-set
|
||||
preprocessor variables, mostly to force a semblance of cross-system compatibility.
|
||||
|
||||
License:
|
||||
|
||||
TODO
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _ZUTILBUILD_HPP
|
||||
#define _ZUTILBUILD_HPP
|
||||
|
||||
//This gives us our standard int types
|
||||
#include <pstdint.h>
|
||||
|
||||
#include "ZBuild.hpp"
|
||||
|
||||
//Version number constants for ZUtil
|
||||
#define ZUTIL_VERSION_MAJOR 0x01
|
||||
#define ZUTIL_VERSION_MINOR 0x00
|
||||
#define ZUTIL_VERSION_PATCH 0x0000
|
||||
#define ZUTIL_VERSION (ZUTIL_VERSION_MAJOR << 24) | (ZUTIL_VERSION_MINOR << 16) | (ZUTIL_VERSION_PATCH)
|
||||
|
||||
#define ZUTIL_VERSION_STRING "1.0.0"
|
||||
|
||||
//Make sure we get proper C-style TRUE, FALSE, and NULL
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
//Get our numeric limits
|
||||
#include <limits>
|
||||
#undef min
|
||||
#undef max
|
||||
#define STDINT_MAX std::numeric_limits<int>::max()
|
||||
#define STDINT_MIN std::numeric_limits<int>::min()
|
||||
#define STDFLT_MAX std::numeric_limits<float>::max()
|
||||
#define STDFLT_MIN std::numeric_limits<float>::min()
|
||||
#define STDDBL_MAX std::numeric_limits<double>::max()
|
||||
#define STDDBL_MIN std::numeric_limits<double>::min()
|
||||
|
||||
//Used to get rid of the (/W4 or -Wall) warning 'Unreferenced Formal Parameter'
|
||||
#if !defined(URFP)
|
||||
#define URFP(x) ((void)x)
|
||||
#endif
|
||||
|
||||
//Use this to disable copy construction and assignment on a class
|
||||
#define DISABLE_COPY_AND_ASSIGN(ClassName) \
|
||||
ClassName(const ClassName&); \
|
||||
void operator = (const ClassName&)
|
||||
|
||||
//Directory separators and line terminators for the various platforms
|
||||
#define DIRECTORY_SEPARATOR_WIN32 "\\"
|
||||
#define LINE_TERMINATOR_WIN32 "\r\n"
|
||||
|
||||
#define DIRECTORY_SEPARATOR_UNIX "/"
|
||||
#define LINE_TERMINATOR_UNIX "\n"
|
||||
|
||||
#define DIRECTORY_SEPARATOR_OSX ":"
|
||||
#define LINE_TERMINATOR_OSX "\n"
|
||||
|
||||
//Windows specialized defines
|
||||
#ifdef _WIN32
|
||||
#define WINDOWS 1
|
||||
#define UNIX 0
|
||||
#define OSX 0
|
||||
|
||||
#define DIRECTORY_SEPARATOR DIRECTORY_SEPARATOR_WIN32
|
||||
#define LINE_TERMINATOR LINE_TERMINATOR_WIN32
|
||||
|
||||
#define _SCL_SECURE_NO_WARNINGS
|
||||
|
||||
#endif
|
||||
|
||||
//UNIX specialized defines
|
||||
#ifdef _UNIX
|
||||
#define WINDOWS 0
|
||||
#define UNIX 1
|
||||
#define OSX 0
|
||||
|
||||
#define DIRECTORY_SEPARATOR DIRECTORY_SEPARATOR_UNIX
|
||||
#define LINE_TERMINATOR LINE_TERMINATOR_UNIX
|
||||
|
||||
//Macros to get around gcc's lack of *_s and _* functions and vc9's insistence on using them
|
||||
#define _stricmp(a, b) strcasecmp(a, b)
|
||||
#define sprintf_s(a, b, c, d...) snprintf(a, b, c, ## d)
|
||||
#define vsnprintf_s(a, b, c, d, e...) vsnprintf(a, b, d, ## e)
|
||||
#endif
|
||||
|
||||
//Mac specialized defines
|
||||
#ifdef _MACOS
|
||||
#define WINDOWS 0
|
||||
#define UNIX 0
|
||||
#define OSX 1
|
||||
|
||||
#define DIRECTORY_SEPARATOR DIRECTORY_SEPARATOR_OSX
|
||||
#define LINE_TERMINATOR LINE_TERMINATOR_OSX
|
||||
|
||||
#define _stricmp(a, b) strcasecmp(a, b)
|
||||
#define sprintf_s(a, b, c, d...) snprintf(a, b, c, ## d)
|
||||
#define vsnprintf_s(a, b, c, d, e...) vsnprintf(a, b, d, ## e)
|
||||
#endif
|
||||
|
||||
#endif //_ZUTILBUILD_HPP
|
||||
1024
Include/ZUtil/ZWeakPointer.hpp
Normal file
1024
Include/ZUtil/ZWeakPointer.hpp
Normal file
File diff suppressed because it is too large
Load Diff
160
Include/ZUtil/ZXMLReader.hpp
Normal file
160
Include/ZUtil/ZXMLReader.hpp
Normal file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
ZXMLReader.hpp
|
||||
Author: James Russell <jcrussell@762studios.com>
|
||||
Created: 5/11/2012
|
||||
|
||||
Purpose:
|
||||
|
||||
Reads in data from the given XML input and parses the data into a ZKVTree instance
|
||||
that can be used for path-based lookup and iteration of values. For example, the following
|
||||
XML data:
|
||||
|
||||
<node type="emitter">
|
||||
<position x="100" y="100" z="1" />
|
||||
<facing x="0" y="0" z="1" />
|
||||
|
||||
This is a particle emitter node.
|
||||
</node>
|
||||
<node type="time" value="2200" />
|
||||
|
||||
Is given the following ZKVTree layout (node values in parenthesis):
|
||||
|
||||
Root
|
||||
|
|
||||
+-> node (This is a particle emitter node.)
|
||||
| |
|
||||
| +-> type (emitter)
|
||||
| |
|
||||
| +-> position ()
|
||||
| | |
|
||||
| | +-> x (100)
|
||||
| | +-> y (100)
|
||||
| | +-> z (1)
|
||||
| |
|
||||
| +-> facing ()
|
||||
| | |
|
||||
| +-> x (0)
|
||||
| +-> y (0)
|
||||
| +-> z (1)
|
||||
|
|
||||
+-> node
|
||||
|
|
||||
+-> type (time)
|
||||
+-> value (2200)
|
||||
|
||||
Note that all XML elements will have the body assigned to the value of the node. Attributes
|
||||
will have their attribute value assigned to the node value, but will never have child nodes.
|
||||
|
||||
This does mean that an XML element with a body value but no attributes will be functionally
|
||||
identical in the KVTree representation to an attribute of the parent element. For example, the
|
||||
following two XML snippets will have an identical layout in the KVTree:
|
||||
|
||||
<node type="emitter">
|
||||
<flags>1</flags>
|
||||
</node>
|
||||
|
||||
<node type="emitter" flags="1" />
|
||||
|
||||
The parsed layout in ZKVTree form is as follows:
|
||||
|
||||
Root
|
||||
|
|
||||
+-> node ()
|
||||
|
|
||||
+-> type (emitter)
|
||||
|
|
||||
+-> flags (1)
|
||||
|
||||
Note that the current implementation uses rapidxml, and will technically parse a superset of W3C
|
||||
compliant XML as valid. In particular, closing tags are not checked for matching, meaning that
|
||||
any closing tag will close any node. There are other non-W3C compliance issues with rapidxml
|
||||
as well, although it will never refuse to parse valid XML.
|
||||
|
||||
More information about rapidxml can be found here: http://rapidxml.sourceforge.net/manual.html
|
||||
|
||||
License:
|
||||
|
||||
TODO
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _ZXMLREADER_HPP
|
||||
#define _ZXMLREADER_HPP
|
||||
|
||||
#include <ZUtil/ZKVTree.hpp>
|
||||
#include <ZUtil/ZSmartPointer.hpp>
|
||||
|
||||
/*
|
||||
ZXMLReader class, which converts XML data into a ZKVtree that can be used to access / iterate
|
||||
the data.
|
||||
*/
|
||||
class ZXMLReader
|
||||
{
|
||||
public:
|
||||
/*
|
||||
Default Constructor.
|
||||
*/
|
||||
ZXMLReader()
|
||||
: ErrorMessage() { }
|
||||
|
||||
/*
|
||||
Destructor.
|
||||
*/
|
||||
~ZXMLReader()
|
||||
{ Tree.Clear(); }
|
||||
|
||||
|
||||
/*
|
||||
public ZXMLReader::Read
|
||||
|
||||
Reads in XML data stored as a ZString and parses it into an internal format.
|
||||
|
||||
@param _xml - Pointer to XML data
|
||||
@return (bool) - true if successful, false if failure (use GetErrorString() to get the message)
|
||||
*/
|
||||
bool Read(const ZString& _xml)
|
||||
{ return Read(_xml.Data(), _xml.Length()); }
|
||||
|
||||
/*
|
||||
public ZXMLReader::Read
|
||||
|
||||
Reads in XML data stored as a memory block and parses it into an internal format.
|
||||
|
||||
@param _data - Pointer to XML data
|
||||
@param _length - Length of XML data
|
||||
@return (bool) - true if successful, false if failure (use GetErrorString() to get the message)
|
||||
*/
|
||||
bool Read(const char* _data, size_t _length);
|
||||
|
||||
/*
|
||||
public ZXMLReader::GetErrorString
|
||||
|
||||
Gets the error message generated while loading the data if loading failed. If loading
|
||||
the data was successful, this returns an empty string.
|
||||
|
||||
@return (const ZString&) - error message string
|
||||
*/
|
||||
const ZString& GetErrorString();
|
||||
|
||||
/*
|
||||
public ZXMLReader::GetKVTree
|
||||
|
||||
Gets the data from the parsed XML as a key-value tree. If the loading failed,
|
||||
the tree is returned empty.
|
||||
|
||||
|
||||
|
||||
@param _kvtree - the tree to fill with parsed xml data
|
||||
*/
|
||||
void GetKVTree(ZKVTree& _kvtree);
|
||||
|
||||
private:
|
||||
DISABLE_COPY_AND_ASSIGN(ZXMLReader);
|
||||
|
||||
ZString ErrorMessage; // error message (if there has been an error)
|
||||
ZKVTree Tree; // tree to store the xml in
|
||||
};
|
||||
|
||||
#endif
|
||||
110
Include/ZUtil/ZXMLWriter.hpp
Normal file
110
Include/ZUtil/ZXMLWriter.hpp
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
ZXMLWriter.hpp
|
||||
Author: James Russell <jcrussell@762studios.com>
|
||||
Created: 5/13/2012
|
||||
|
||||
Purpose:
|
||||
|
||||
Interprets a ZKVTree as XML, writing the node structure and values into XML elements. Acts as
|
||||
an inverse of ZXMLReader (see header for details on format).
|
||||
|
||||
Note that the same ambiguity is present for elements with no attributes and body data - they will
|
||||
be written out as attributes. For example, consider the following ZKVTree structure:
|
||||
|
||||
Root
|
||||
|
|
||||
+-> node (This is a particle emitter node.)
|
||||
| |
|
||||
| +-> type (emitter)
|
||||
| |
|
||||
| +-> position ()
|
||||
| | |
|
||||
| | +-> x (100)
|
||||
| | +-> y (100)
|
||||
| | +-> z (1)
|
||||
| |
|
||||
| +-> facing ()
|
||||
| | |
|
||||
| | +-> x (0)
|
||||
| | +-> y (0)
|
||||
| | +-> z (1)
|
||||
| |
|
||||
| +-> flags (1)
|
||||
|
|
||||
+-> node
|
||||
|
|
||||
+-> type (time)
|
||||
+-> value (2200)
|
||||
|
||||
The above will be written out as follows:
|
||||
|
||||
<node type="emitter" flags="1">
|
||||
<position x="100" y="100" z="1" />
|
||||
<facing x="0" y="0" z="1" />
|
||||
This is a particle emitter node.
|
||||
</node>
|
||||
<node type="time" value="2200" />
|
||||
|
||||
Notice that the ambiguous case described in ZXMLReader.hpp for an attribute of an XML
|
||||
element and the body of an attribute-free element will always be written out as an
|
||||
attribute.
|
||||
|
||||
The body of 'node' is not ambiguous because the 'node' element has attributes and child
|
||||
elements.
|
||||
|
||||
License:
|
||||
|
||||
TODO
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _ZXMLWRITER_HPP
|
||||
#define _ZXMLWRITER_HPP
|
||||
|
||||
#include <ZUtil/ZKVTree.hpp>
|
||||
|
||||
class ZXMLWriter
|
||||
{
|
||||
private:
|
||||
DISABLE_COPY_AND_ASSIGN(ZXMLWriter);
|
||||
|
||||
//Error message (if an error has happened)
|
||||
ZString ErrorMessage;
|
||||
|
||||
// recursive functions for writing XML
|
||||
bool writeAttributes(ZString& _output, const ZKVTree::Iterator& _itr);
|
||||
bool writeElements(ZString& _output, bool _useNewlines, const ZKVTree::Iterator& _itr);
|
||||
|
||||
public:
|
||||
/*
|
||||
Default Constructor.
|
||||
*/
|
||||
ZXMLWriter() { }
|
||||
|
||||
/*
|
||||
public ZXMLWriter::GetErrorString
|
||||
|
||||
Gets the error message generated while writing the data if writing failed. If writing
|
||||
the data was successful, this returns an empty string.
|
||||
|
||||
@return (const ZString&)
|
||||
*/
|
||||
const ZString& GetErrorString();
|
||||
|
||||
/*
|
||||
public ZXMLWriter::Write
|
||||
|
||||
Writes the data from the registry into the provided output string in XML format.
|
||||
|
||||
@param _input - the KVTree we wish to represent as XML
|
||||
@param _output - the string to write the data into (the data is appended)
|
||||
@param _useNewlines - indicates whether or not we should use newlines in the output
|
||||
@return (bool) - true if successful, false otherwise
|
||||
*/
|
||||
bool Write(const ZKVTree& _input, ZString& _output, bool _useNewlines);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user