summaryrefslogtreecommitdiff
path: root/Source/modules/asura-base
diff options
context:
space:
mode:
Diffstat (limited to 'Source/modules/asura-base')
-rw-r--r--Source/modules/asura-base/Classes.h11
-rw-r--r--Source/modules/asura-base/Math/Matrix44.h8
-rw-r--r--Source/modules/asura-base/Math/Quaternion.h4
-rw-r--r--Source/modules/asura-base/Math/Random.h4
-rw-r--r--Source/modules/asura-base/Math/Rect.hpp8
-rw-r--r--Source/modules/asura-base/Math/Transform.h6
-rw-r--r--Source/modules/asura-base/Math/Vector2.hpp6
-rw-r--r--Source/modules/asura-base/Math/Vector3.hpp8
-rw-r--r--Source/modules/asura-base/Math/Vector4.h8
-rw-r--r--Source/modules/asura-base/Misc/GUID.cpp (renamed from Source/modules/asura-base/Utilities/LinkedList.cpp)0
-rw-r--r--Source/modules/asura-base/Misc/GUID.h0
-rw-r--r--Source/modules/asura-base/Misc/UTF8.cpp395
-rw-r--r--Source/modules/asura-base/Misc/UTF8.h20
-rw-r--r--Source/modules/asura-base/Utilities/LinkedList.h388
-rw-r--r--Source/modules/asura-base/Utilities/dynamic_array.h337
15 files changed, 1172 insertions, 31 deletions
diff --git a/Source/modules/asura-base/Classes.h b/Source/modules/asura-base/Classes.h
index b2700f0..515762b 100644
--- a/Source/modules/asura-base/Classes.h
+++ b/Source/modules/asura-base/Classes.h
@@ -1,7 +1,16 @@
#ifndef _ASURAENGINE_CLASSES_H_
#define _ASURAENGINE_CLASSES_H_
-#define GET_SET(TYPE,PROP_NAME,VAR_NAME) void Set##PROP_NAME (TYPE val) { VAR_NAME = val; } TYPE Get##PROP_NAME () {return VAR_NAME; }
+#define GET_SET(TYPE,PROP_NAME,VAR_NAME) \
+inline void Set##PROP_NAME (TYPE val) { VAR_NAME = val; } \
+inline TYPE Get##PROP_NAME () {return VAR_NAME; }
+
+#define PROPERTY(TYPE,PROP_NAME,VAR_NAME) \
+private: \
+ TYPE VAR_NAME; \
+public: \
+ inline void Set##PROP_NAME (TYPE val) { VAR_NAME = val; } \
+ inline TYPE Get##PROP_NAME () {return VAR_NAME; }
#define namespace_begin(NAMESPACE) namespace NAMESPACE {
#define namespace_end }
diff --git a/Source/modules/asura-base/Math/Matrix44.h b/Source/modules/asura-base/Math/Matrix44.h
index e987dd4..6babde1 100644
--- a/Source/modules/asura-base/Math/Matrix44.h
+++ b/Source/modules/asura-base/Math/Matrix44.h
@@ -6,7 +6,7 @@
#include "../Scripting/Scripting.h"
namespace_begin(AsuraEngine)
-namespace_begin(Math)
+//namespace_begin(Math)
/// ҪתõOpenGLglm::mat4
/// https://blog.csdn.net/candycat1992/article/details/8830894
@@ -71,9 +71,7 @@ public:
/////
//void transform(Graphics::Vertex* dst, const Graphics::Vertex * src, int size) const;
- ///
/// ʽ
- ///
float Calculate();
private:
@@ -88,9 +86,7 @@ private:
};
+//namespace_end
namespace_end
-namespace_end
-
-namespace AEMath = AsuraEngine::Math;
#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/Math/Quaternion.h b/Source/modules/asura-base/Math/Quaternion.h
index c1e19be..53b63c9 100644
--- a/Source/modules/asura-base/Math/Quaternion.h
+++ b/Source/modules/asura-base/Math/Quaternion.h
@@ -4,7 +4,7 @@
#include <asura-base/Classes.h>
namespace_begin(AsruaEngine)
-namespace_begin(Math)
+//namespace_begin(Math)
class Quaternion
{
@@ -12,7 +12,7 @@ class Quaternion
};
-namespace_end
+//namespace_end
namespace_end
#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/Math/Random.h b/Source/modules/asura-base/Math/Random.h
index 7d3b976..914a607 100644
--- a/Source/modules/asura-base/Math/Random.h
+++ b/Source/modules/asura-base/Math/Random.h
@@ -5,7 +5,7 @@
#include "../Classes.h"
namespace_begin(AsuraEngine)
-namespace_begin(Math)
+//namespace_begin(Math)
/*
Some random generator timings:
@@ -82,7 +82,7 @@ private:
uint32 x, y, z, w;
};
-namespace_end
+//namespace_end
namespace_end
#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/Math/Rect.hpp b/Source/modules/asura-base/Math/Rect.hpp
index af4fa78..3b9039b 100644
--- a/Source/modules/asura-base/Math/Rect.hpp
+++ b/Source/modules/asura-base/Math/Rect.hpp
@@ -3,8 +3,8 @@
namespace AsuraEngine
{
-namespace Math
-{
+//namespace Math
+//{
template<typename T>
struct Rect
@@ -42,9 +42,7 @@ typedef Rect<unsigned int> Rectu;
typedef Rect<float> Rectf;
typedef Rect<long> Reftl;
+//}
}
-}
-
-namespace AEMath = AsuraEngine::Math;
#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/Math/Transform.h b/Source/modules/asura-base/Math/Transform.h
index 5dcfdcf..02f3c1c 100644
--- a/Source/modules/asura-base/Math/Transform.h
+++ b/Source/modules/asura-base/Math/Transform.h
@@ -5,8 +5,8 @@
namespace AsuraEngine
{
- namespace Math
- {
+ //namespace Math
+ //{
class Transform
{
@@ -24,7 +24,7 @@ namespace AsuraEngine
};
- }
+// }
}
#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/Math/Vector2.hpp b/Source/modules/asura-base/Math/Vector2.hpp
index e141017..09fd299 100644
--- a/Source/modules/asura-base/Math/Vector2.hpp
+++ b/Source/modules/asura-base/Math/Vector2.hpp
@@ -4,7 +4,7 @@
#include <asura-base/Classes.h>
namespace_begin(AsuraEngine)
-namespace_begin(Math)
+//namespace_begin(Math)
template <typename T>
class Vector2
@@ -64,9 +64,7 @@ typedef Vector2<int> Vector2i;
typedef Vector2<unsigned int> Vector2u;
typedef Vector2<float> Vector2f;
+//namespace_end
namespace_end
-namespace_end
-
-namespace AEMath = AsuraEngine::Math;
#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/Math/Vector3.hpp b/Source/modules/asura-base/Math/Vector3.hpp
index c526ace..b50c363 100644
--- a/Source/modules/asura-base/Math/Vector3.hpp
+++ b/Source/modules/asura-base/Math/Vector3.hpp
@@ -3,8 +3,8 @@
namespace AsuraEngine
{
- namespace Math
- {
+ //namespace Math
+ //{
template <typename T>
class Vector3
{
@@ -227,9 +227,7 @@ namespace AsuraEngine
typedef Vector3<int> Vector3i;
typedef Vector3<float> Vector3f;
- }
+// }
}
-namespace AEMath = AsuraEngine::Math;
-
#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/Math/Vector4.h b/Source/modules/asura-base/Math/Vector4.h
index a5bf549..c39d9a6 100644
--- a/Source/modules/asura-base/Math/Vector4.h
+++ b/Source/modules/asura-base/Math/Vector4.h
@@ -3,8 +3,8 @@
namespace AsuraEngine
{
- namespace Math
- {
+ //namespace Math
+ //{
template <typename T>
class Vector4
{
@@ -228,7 +228,9 @@ namespace AsuraEngine
typedef Vector4<int> Vector4i;
typedef Vector4<float> Vector4f;
- }
+// }
}
+
+
#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/Utilities/LinkedList.cpp b/Source/modules/asura-base/Misc/GUID.cpp
index e69de29..e69de29 100644
--- a/Source/modules/asura-base/Utilities/LinkedList.cpp
+++ b/Source/modules/asura-base/Misc/GUID.cpp
diff --git a/Source/modules/asura-base/Misc/GUID.h b/Source/modules/asura-base/Misc/GUID.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-base/Misc/GUID.h
diff --git a/Source/modules/asura-base/Misc/UTF8.cpp b/Source/modules/asura-base/Misc/UTF8.cpp
new file mode 100644
index 0000000..8cfb3ab
--- /dev/null
+++ b/Source/modules/asura-base/Misc/UTF8.cpp
@@ -0,0 +1,395 @@
+#include "UTF8.h"
+
+namespace_begin(AsuraEngine)
+
+typedef unsigned long UTF32; /* at least 32 bits */
+typedef unsigned short UTF16; /* at least 16 bits */
+typedef unsigned char UTF8; /* typically 8 bits */
+typedef unsigned char Boolean; /* 0 or 1 */
+
+typedef enum {
+ strictConversion = 0,
+ lenientConversion
+} ConversionFlags;
+
+typedef enum {
+ conversionOK, /* conversion successful */
+ sourceExhausted, /* partial character in source, but hit end */
+ targetExhausted, /* insuff. room in target for conversion */
+ sourceIllegal /* source sequence is illegal/malformed */
+} ConversionResult;
+
+/* Some fundamental constants */
+#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD
+#define UNI_MAX_BMP (UTF32)0x0000FFFF
+#define UNI_MAX_UTF16 (UTF32)0x0010FFFF
+#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF
+#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF
+
+ConversionResult ConvertUTF8toUTF16(
+ const UTF8** sourceStart, const UTF8* sourceEnd,
+ UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
+
+
+/*
+* Copyright 2001-2004 Unicode, Inc.
+*
+* Disclaimer
+*
+* This source code is provided as is by Unicode, Inc. No claims are
+* made as to fitness for any particular purpose. No warranties of any
+* kind are expressed or implied. The recipient agrees to determine
+* applicability of information provided. If this file has been
+* purchased on magnetic or optical media from Unicode, Inc., the
+* sole remedy for any claim will be exchange of defective media
+* within 90 days of receipt.
+*
+* Limitations on Rights to Redistribute This Code
+*
+* Unicode, Inc. hereby grants the right to freely use the information
+* supplied in this file in the creation of products supporting the
+* Unicode Standard, and to make copies of this file in any form
+* for internal or external distribution as long as this notice
+* remains attached.
+*/
+
+/* ---------------------------------------------------------------------
+
+Conversions between UTF32, UTF-16, and UTF-8. Source code file.
+Author: Mark E. Davis, 1994.
+Rev History: Rick McGowan, fixes & updates May 2001.
+Sept 2001: fixed const & error conditions per
+mods suggested by S. Parent & A. Lillich.
+June 2002: Tim Dodd added detection and handling of incomplete
+source sequences, enhanced error detection, added casts
+to eliminate compiler warnings.
+July 2003: slight mods to back out aggressive FFFE detection.
+Jan 2004: updated switches in from-UTF8 conversions.
+Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions.
+
+See the header file "ConvertUTF.h" for complete documentation.
+
+------------------------------------------------------------------------ */
+
+
+#include "UTF8.h"
+#ifdef CVTUTF_DEBUG
+#include <stdio.h>
+#endif
+
+static const int halfShift = 10; /* used for shifting by 10 bits */
+
+static const UTF32 halfBase = 0x0010000UL;
+static const UTF32 halfMask = 0x3FFUL;
+
+#define UNI_SUR_HIGH_START (UTF32)0xD800
+#define UNI_SUR_HIGH_END (UTF32)0xDBFF
+#define UNI_SUR_LOW_START (UTF32)0xDC00
+#define UNI_SUR_LOW_END (UTF32)0xDFFF
+
+
+/* --------------------------------------------------------------------- */
+
+/*
+* Index into the table below with the first byte of a UTF-8 sequence to
+* get the number of trailing bytes that are supposed to follow it.
+* Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is
+* left as-is for anyone who may want to do such conversion, which was
+* allowed in earlier algorithms.
+*/
+static const char trailingBytesForUTF8[256] = {
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
+};
+
+/*
+* Magic values subtracted from a buffer value during UTF8 conversion.
+* This table contains as many values as there might be trailing bytes
+* in a UTF-8 sequence.
+*/
+static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,
+0x03C82080UL, 0xFA082080UL, 0x82082080UL };
+
+/*
+* Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
+* into the first byte, depending on how many bytes follow. There are
+* as many entries in this table as there are UTF-8 sequence types.
+* (I.e., one byte sequence, two byte... etc.). Remember that sequencs
+* for *legal* UTF-8 will be 4 or fewer bytes total.
+*/
+static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
+
+
+/* --------------------------------------------------------------------- */
+
+/*
+* Utility routine to tell whether a sequence of bytes is legal UTF-8.
+* This must be called with the length pre-determined by the first byte.
+* If not calling this from ConvertUTF8to*, then the length can be set by:
+* length = trailingBytesForUTF8[*source]+1;
+* and the sequence is illegal right away if there aren't that many bytes
+* available.
+* If presented with a length > 4, this returns false. The Unicode
+* definition of UTF-8 goes up to 4-byte sequences.
+*/
+
+static Boolean isLegalUTF8(const UTF8 *source, int length) {
+ UTF8 a;
+ const UTF8 *srcptr = source + length;
+ switch (length) {
+ default: return false;
+ /* Everything else falls through when "true"... */
+ case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
+ case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
+ case 2: if ((a = (*--srcptr)) > 0xBF) return false;
+
+ switch (*source) {
+ /* no fall-through in this inner switch */
+ case 0xE0: if (a < 0xA0) return false; break;
+ case 0xED: if (a > 0x9F) return false; break;
+ case 0xF0: if (a < 0x90) return false; break;
+ case 0xF4: if (a > 0x8F) return false; break;
+ default: if (a < 0x80) return false;
+ }
+
+ case 1: if (*source >= 0x80 && *source < 0xC2) return false;
+ }
+ if (*source > 0xF4) return false;
+ return true;
+}
+
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF8toUTF16(
+ const UTF8** sourceStart, const UTF8* sourceEnd,
+ UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
+ ConversionResult result = conversionOK;
+ const UTF8* source = *sourceStart;
+ UTF16* target = *targetStart;
+ while (source < sourceEnd) {
+ UTF32 ch = 0;
+ unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
+ if (source + extraBytesToRead >= sourceEnd) {
+ result = sourceExhausted; break;
+ }
+ /* Do this check whether lenient or strict */
+ if (!isLegalUTF8(source, extraBytesToRead + 1)) {
+ result = sourceIllegal;
+ break;
+ }
+ /*
+ * The cases all fall through. See "Note A" below.
+ */
+ switch (extraBytesToRead) {
+ case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
+ case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
+ case 3: ch += *source++; ch <<= 6;
+ case 2: ch += *source++; ch <<= 6;
+ case 1: ch += *source++; ch <<= 6;
+ case 0: ch += *source++;
+ }
+ ch -= offsetsFromUTF8[extraBytesToRead];
+
+ //DebugAssertIf(target >= targetEnd);
+
+ if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
+ if (flags == strictConversion) {
+ source -= (extraBytesToRead + 1); /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ else {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ }
+ else {
+ *target++ = (UTF16)ch; /* normal case */
+ }
+ }
+ else if (ch > UNI_MAX_UTF16) {
+ if (flags == strictConversion) {
+ result = sourceIllegal;
+ source -= (extraBytesToRead + 1); /* return to the start */
+ break; /* Bail out; shouldn't continue */
+ }
+ else {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ }
+ else {
+ /* target is a character in range 0xFFFF - 0x10FFFF. */
+ if (target + 1 >= targetEnd) {
+ source -= (extraBytesToRead + 1); /* Back up source pointer! */
+ result = targetExhausted; break;
+ }
+ ch -= halfBase;
+ *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
+ *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
+ }
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+
+/* ---------------------------------------------------------------------
+
+Note A.
+The fall-through switches in UTF-8 reading code save a
+temp variable, some decrements & conditionals. The switches
+are equivalent to the following loop:
+{
+int tmpBytesToRead = extraBytesToRead+1;
+do {
+ch += *source++;
+--tmpBytesToRead;
+if (tmpBytesToRead) ch <<= 6;
+} while (tmpBytesToRead > 0);
+}
+In UTF-8 writing code, the switches on "bytesToWrite" are
+similarly unrolled loops.
+
+--------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF16toUTF8(
+ const UTF16** sourceStart, const UTF16* sourceEnd,
+ UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
+ ConversionResult result = conversionOK;
+ const UTF16* source = *sourceStart;
+ UTF8* target = *targetStart;
+ while (source < sourceEnd) {
+ UTF32 ch;
+ unsigned short bytesToWrite = 0;
+ const UTF32 byteMask = 0xBF;
+ const UTF32 byteMark = 0x80;
+ const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
+ ch = *source++;
+ /* If we have a surrogate pair, convert to UTF32 first. */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END && source < sourceEnd) {
+ UTF32 ch2 = *source;
+ if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
+ ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
+ + (ch2 - UNI_SUR_LOW_START) + halfBase;
+ ++source;
+ }
+ else if (flags == strictConversion) { /* it's an unpaired high surrogate */
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ }
+ else if ((flags == strictConversion) && (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END)) {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ /* Figure out how many bytes the result will require */
+ if (ch < (UTF32)0x80) {
+ bytesToWrite = 1;
+ }
+ else if (ch < (UTF32)0x800) {
+ bytesToWrite = 2;
+ }
+ else if (ch < (UTF32)0x10000) {
+ bytesToWrite = 3;
+ }
+ else if (ch < (UTF32)0x200000) {
+ bytesToWrite = 4;
+ }
+ else {
+ bytesToWrite = 2;
+ ch = UNI_REPLACEMENT_CHAR;
+ }
+
+ target += bytesToWrite;
+ if (target > targetEnd) {
+ source = oldSource; /* Back up source pointer! */
+ target -= bytesToWrite; result = targetExhausted; break;
+ }
+ switch (bytesToWrite) { /* note: everything falls through. */
+ case 4: *--target = (ch | byteMark) & byteMask; ch >>= 6;
+ case 3: *--target = (ch | byteMark) & byteMask; ch >>= 6;
+ case 2: *--target = (ch | byteMark) & byteMask; ch >>= 6;
+ case 1: *--target = ch | firstByteMark[bytesToWrite];
+ }
+ target += bytesToWrite;
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+
+
+bool ConvertUTF8toUTF16(const char* source, int srcLength, uint16* output, int& outlength)
+{
+ uint16* newoutput = output;
+ const UTF8* src = (UTF8*)source;
+ if (ConvertUTF8toUTF16(&src, src + srcLength, &newoutput, newoutput + srcLength, lenientConversion) != sourceIllegal)
+ {
+ outlength = newoutput - output;
+ return true;
+ }
+ else
+ {
+ outlength = 0;
+ return false;
+ }
+}
+
+bool ConvertUTF8toUTF16(const std::string& source, dynamic_array<uint16>& utf16)
+{
+ utf16.resize_uninitialized(source.size());
+ int length = 0;
+ bool success = ConvertUTF8toUTF16(source.data(), (int)source.size(), utf16.begin(), length);
+ utf16.resize_uninitialized(length);
+ return success;
+}
+
+bool ConvertUTF16toUTF8(const uint16* source, int srcLength, char* output, int& outlength)
+{
+ UTF8* newoutput = (UTF8*)output;
+ const UTF16* src = (UTF16*)source;
+ if (ConvertUTF16toUTF8(&src, src + srcLength, &newoutput, newoutput + (srcLength * 4), lenientConversion) != sourceIllegal)
+ {
+ outlength = newoutput - (UTF8*)output;
+ return true;
+ }
+ else
+ {
+ outlength = 0;
+ return false;
+ }
+}
+
+
+bool ConvertUTF16toUTF8(const dynamic_array<UnicodeChar>& source, std::string& utf8)
+{
+ utf8.resize(source.size() * 4);
+ int length = 0;
+ bool success = ConvertUTF16toUTF8(source.data(), (int)source.size(), &utf8[0], length);
+ utf8.resize(length);
+ return success;
+}
+
+bool ConvertUTF16toUTF8(const uint16 utf16character, std::string& utf8)
+{
+ int len;
+ char character[5];
+ if (!ConvertUTF16toUTF8(&utf16character, 1, character, len))
+ return false;
+ character[len] = 0;
+ utf8 = std::string(character);
+ return true;
+}
+
+
+namespace_end \ No newline at end of file
diff --git a/Source/modules/asura-base/Misc/UTF8.h b/Source/modules/asura-base/Misc/UTF8.h
new file mode 100644
index 0000000..269ad36
--- /dev/null
+++ b/Source/modules/asura-base/Misc/UTF8.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <string>
+
+#include "../Type.h"
+#include "../Classes.h"
+#include "../Utilities/dynamic_array.h"
+
+namespace_begin(AsuraEngine)
+
+typedef uint16 UnicodeChar;
+
+bool ConvertUTF8toUTF16(const char* source, int srcLength, UnicodeChar* output, int& outlength);
+bool ConvertUTF8toUTF16(const std::string& source, dynamic_array<UnicodeChar>& utf16);
+bool ConvertUTF16toUTF8(const uint16* source, int srcLength, char* output, int& outlength);
+bool ConvertUTF16toUTF8(const dynamic_array<UnicodeChar>& source, std::string& utf8);
+bool ConvertUTF16toUTF8(const uint16* source, int srcLength, char* output, int& outlength);
+bool ConvertUTF16toUTF8(const uint16 utf16character, std::string& utf8);
+
+namespace_end \ No newline at end of file
diff --git a/Source/modules/asura-base/Utilities/LinkedList.h b/Source/modules/asura-base/Utilities/LinkedList.h
index e69de29..5a7dc74 100644
--- a/Source/modules/asura-base/Utilities/LinkedList.h
+++ b/Source/modules/asura-base/Utilities/LinkedList.h
@@ -0,0 +1,388 @@
+#ifndef _ASURA_LINKED_LIST_H_
+#define _ASURA_LINKED_LIST_H_
+
+#include "../Type.h"
+#include <string.h>
+
+#if !ASURA_RELEASE
+#define LINKED_LIST_ASSERT(x) Assert(x)
+#else
+#define LINKED_LIST_ASSERT(x)
+#endif
+
+class ListElement
+{
+public:
+ inline ListElement();
+ inline ~ListElement() { RemoveFromList(); }
+
+ inline bool IsInList() const;
+ inline bool RemoveFromList();
+ inline void InsertInList(ListElement* pos);
+
+ // Check against List::end(), not NULL
+ ListElement* GetPrev() const { return m_Prev; }
+ ListElement* GetNext() const { return m_Next; }
+
+private:
+ // Non copyable
+ ListElement(const ListElement&);
+ ListElement& operator=(const ListElement&);
+
+ ListElement* m_Prev;
+ ListElement* m_Next;
+
+ template <class T> friend class List;
+ inline void ValidateLinks() const;
+
+#if !ASURA_RELEASE
+ // Iterator debugging only
+ template <class T> friend class ListIterator;
+ template <class T> friend class ListConstIterator;
+ void SetList(void* l) { m_List = l; }
+ void* m_List;
+#else
+ void SetList(void*) {}
+#endif
+};
+
+template <class T>
+class ListNode : public ListElement
+{
+public:
+ ListNode(T* data = NULL) : m_Data(data) {}
+ T& operator*() const { return *m_Data; }
+ T* operator->() const { return m_Data; }
+ T* GetData() const { return m_Data; }
+ void SetData(T* data) { m_Data = data; }
+
+ // We know the type of prev and next element
+ ListNode* GetPrev() const { return static_cast<ListNode*>(ListElement::GetPrev()); }
+ ListNode* GetNext() const { return static_cast<ListNode*>(ListElement::GetNext()); }
+
+private:
+ T * m_Data;
+};
+
+template <class T>
+class ListIterator
+{
+public:
+ ListIterator(T* node = NULL) : m_Node(node) {}
+
+ // Pre- and post-increment operator
+ ListIterator& operator++() { m_Node = m_Node->GetNext(); return *this; }
+ ListIterator operator++(int) { ListIterator ret(*this); ++(*this); return ret; }
+
+ // Pre- and post-decrement operator
+ ListIterator& operator--() { m_Node = m_Node->GetPrev(); return *this; }
+ ListIterator operator--(int) { ListIterator ret(*this); --(*this); return ret; }
+
+ T& operator*() const { return static_cast<T&>(*m_Node); }
+ T* operator->() const { return static_cast<T*>(m_Node); }
+
+ friend bool operator !=(const ListIterator& x, const ListIterator& y) { return x.m_Node != y.m_Node; }
+ friend bool operator ==(const ListIterator& x, const ListIterator& y) { return x.m_Node == y.m_Node; }
+
+private:
+ template <class S> friend class List;
+ ListIterator(ListElement* node) : m_Node(node) {}
+ ListElement* m_Node;
+};
+
+
+template <class T>
+class ListConstIterator
+{
+public:
+ ListConstIterator(const T* node = NULL) : m_Node(node) {}
+
+ // Pre- and post-increment operator
+ ListConstIterator& operator++() { m_Node = m_Node->GetNext(); return *this; }
+ ListConstIterator operator++(int) { ListConstIterator ret(*this); ++(*this); return ret; }
+
+ // Pre- and post-decrement operator
+ ListConstIterator& operator--() { m_Node = m_Node->GetPrev(); return *this; }
+ ListConstIterator operator--(int) { ListConstIterator ret(*this); --(*this); return ret; }
+
+ const T& operator*() const { return static_cast<const T&>(*m_Node); }
+ const T* operator->() const { return static_cast<const T*>(m_Node); }
+
+ friend bool operator !=(const ListConstIterator& x, const ListConstIterator& y) { return x.m_Node != y.m_Node; }
+ friend bool operator ==(const ListConstIterator& x, const ListConstIterator& y) { return x.m_Node == y.m_Node; }
+
+private:
+ template <class S> friend class List;
+ ListConstIterator(const ListElement* node) : m_Node(node) {}
+ const ListElement* m_Node;
+};
+
+template <class T>
+class List
+{
+public:
+ typedef ListConstIterator<T> const_iterator;
+ typedef ListIterator<T> iterator;
+ typedef T value_type;
+
+ inline List();
+ inline ~List();
+
+ void push_back(T& node) { node.InsertInList(&m_Root); }
+ void push_front(T& node) { node.InsertInList(m_Root.m_Next); }
+ void insert(iterator pos, T& node) { node.InsertInList(&(*pos)); }
+ void erase(iterator pos) { pos->RemoveFromList(); }
+
+ void pop_back() { if (m_Root.m_Prev != &m_Root) m_Root.m_Prev->RemoveFromList(); }
+ void pop_front() { if (m_Root.m_Next != &m_Root) m_Root.m_Next->RemoveFromList(); }
+
+ iterator begin() { return iterator(m_Root.m_Next); }
+ iterator end() { return iterator(&m_Root); }
+
+ const_iterator begin() const { return const_iterator(m_Root.m_Next); }
+ const_iterator end() const { return const_iterator(&m_Root); }
+
+ T& front() { LINKED_LIST_ASSERT(!empty()); return static_cast<T&>(*m_Root.m_Next); }
+ T& back() { LINKED_LIST_ASSERT(!empty()); return static_cast<T&>(*m_Root.m_Prev); }
+
+ const T& front() const { LINKED_LIST_ASSERT(!empty()); return static_cast<const T&>(*m_Root.m_Next); }
+ const T& back() const { LINKED_LIST_ASSERT(!empty()); return static_cast<const T&>(*m_Root.m_Prev); }
+
+ bool empty() const { return begin() == end(); }
+
+ size_t size_slow() const;
+ inline void clear();
+ inline void swap(List& other);
+
+ // Insert list into list (removes elements from source)
+ inline void insert(iterator pos, List& src);
+ inline void append(List& src);
+
+private:
+ ListElement m_Root;
+};
+
+
+template <class T>
+List<T>::List()
+{
+ m_Root.m_Prev = &m_Root;
+ m_Root.m_Next = &m_Root;
+ m_Root.SetList(this);
+}
+
+template <class T>
+List<T>::~List()
+{
+ clear();
+}
+
+template <class T>
+size_t List<T>::size_slow() const
+{
+ size_t size = 0;
+ ListElement* node = m_Root.m_Next;
+ while (node != &m_Root)
+ {
+ node = node->m_Next;
+ size++;
+ }
+ return size;
+}
+
+template <class T>
+void List<T>::clear()
+{
+ ListElement* node = m_Root.m_Next;
+ while (node != &m_Root)
+ {
+ ListElement* next = node->m_Next;
+ node->m_Prev = NULL;
+ node->m_Next = NULL;
+ node->SetList(NULL);
+ node = next;
+ }
+ m_Root.m_Next = &m_Root;
+ m_Root.m_Prev = &m_Root;
+}
+
+template <class T>
+void List<T>::swap(List<T>& other)
+{
+ LINKED_LIST_ASSERT(this != &other);
+
+ std::swap(other.m_Root.m_Prev, m_Root.m_Prev);
+ std::swap(other.m_Root.m_Next, m_Root.m_Next);
+
+ if (other.m_Root.m_Prev == &m_Root)
+ other.m_Root.m_Prev = &other.m_Root;
+ if (m_Root.m_Prev == &other.m_Root)
+ m_Root.m_Prev = &m_Root;
+ if (other.m_Root.m_Next == &m_Root)
+ other.m_Root.m_Next = &other.m_Root;
+ if (m_Root.m_Next == &other.m_Root)
+ m_Root.m_Next = &m_Root;
+
+ other.m_Root.m_Prev->m_Next = &other.m_Root;
+ other.m_Root.m_Next->m_Prev = &other.m_Root;
+
+ m_Root.m_Prev->m_Next = &m_Root;
+ m_Root.m_Next->m_Prev = &m_Root;
+
+#if !ASURA_RELEASE
+ iterator my_it, my_end = end();
+ for (my_it = begin(); my_it != my_end; ++my_it)
+ my_it->m_List = this;
+ iterator other_it, other_end = other.end();
+ for (other_it = other.begin(); other_it != other_end; ++other_it)
+ other_it->m_List = &other;
+#endif
+}
+
+template <class T>
+void List<T>::insert(iterator pos, List<T>& src)
+{
+ LINKED_LIST_ASSERT(this != &src);
+ if (src.empty())
+ return;
+
+#if !ASURA_RELEASE
+ iterator src_it, src_end = src.end();
+ for (src_it = src.begin(); src_it != src_end; ++src_it)
+ src_it->m_List = this;
+#endif
+ // Insert source before pos
+ ListElement* a = pos.m_Node->m_Prev;
+ ListElement* b = pos.m_Node;
+ a->m_Next = src.m_Root.m_Next;
+ b->m_Prev = src.m_Root.m_Prev;
+ a->m_Next->m_Prev = a;
+ b->m_Prev->m_Next = b;
+ // Clear source list
+ src.m_Root.m_Next = &src.m_Root;
+ src.m_Root.m_Prev = &src.m_Root;
+}
+
+template <class T>
+void List<T>::append(List& src)
+{
+ insert(end(), src);
+}
+
+ListElement::ListElement()
+{
+ m_Prev = NULL;
+ m_Next = NULL;
+ SetList(NULL);
+}
+
+bool ListElement::IsInList() const
+{
+ return m_Prev != NULL;
+}
+
+bool ListElement::RemoveFromList()
+{
+ if (!IsInList())
+ return false;
+
+#if !ASURA_RELEASE
+ ValidateLinks();
+#endif
+ m_Prev->m_Next = m_Next;
+ m_Next->m_Prev = m_Prev;
+ m_Prev = NULL;
+ m_Next = NULL;
+ return true;
+}
+
+void ListElement::InsertInList(ListElement* pos)
+{
+ if (this == pos)
+ return;
+
+ if (IsInList())
+ RemoveFromList();
+
+#if !ASURA_RELEASE
+ m_List = pos->m_List;
+ pos->m_Prev->ValidateLinks();
+ pos->ValidateLinks();
+#endif
+ m_Prev = pos->m_Prev;
+ m_Next = pos;
+ m_Prev->m_Next = this;
+ m_Next->m_Prev = this;
+#if !ASURA_RELEASE
+ ValidateLinks();
+#endif
+ return;
+}
+
+void ListElement::ValidateLinks() const
+{
+#if !ASURA_RELEASE
+ LINKED_LIST_ASSERT(m_Prev != NULL && m_Next != NULL);
+ LINKED_LIST_ASSERT(m_Prev->m_Next == this && m_Next->m_Prev == this);
+ LINKED_LIST_ASSERT(m_Prev->m_List == m_List && m_Next->m_List == m_List);
+#endif
+}
+
+/// Allows for iterating a linked list, even if you add / remove any node during traversal.
+template<class T>
+class SafeIterator
+{
+public:
+ SafeIterator(T& list)
+ : m_SourceList(list)
+ {
+ m_CurrentNode = NULL;
+ m_ExecuteList.swap(m_SourceList);
+ }
+
+ ~SafeIterator()
+ {
+ // Call Complete if you abort the iteration!
+ LINKED_LIST_ASSERT(m_ExecuteList.empty());
+ }
+
+ // You must call complete if you are in some way aborting list iteration.
+ // If you dont call Complete, the source list will lose nodes that have not yet been iterated permanently.
+ //
+ /// SafeIterator<Behaviour*> i(myList);
+ /// i =0;
+ /// while(i.GetNext() && ++i != 3)
+ /// (**i).Update();
+ /// i.Complete();
+ void Complete()
+ {
+ m_SourceList.append(m_ExecuteList);
+ }
+
+ typename T::value_type* Next()
+ {
+ if (!m_ExecuteList.empty())
+ {
+ typename T::iterator it = m_ExecuteList.begin();
+ m_CurrentNode = &*it;
+ m_ExecuteList.erase(it);
+ m_SourceList.push_back(*m_CurrentNode);
+ }
+ else
+ {
+ m_CurrentNode = NULL;
+ }
+ return m_CurrentNode;
+ }
+
+ typename T::value_type& operator *() const { return *m_CurrentNode; }
+ typename T::value_type* operator ->() const { return m_CurrentNode; }
+
+private:
+ T m_ExecuteList;
+ T& m_SourceList;
+ typename T::value_type* m_CurrentNode;
+};
+
+
+#endif
diff --git a/Source/modules/asura-base/Utilities/dynamic_array.h b/Source/modules/asura-base/Utilities/dynamic_array.h
new file mode 100644
index 0000000..36885f0
--- /dev/null
+++ b/Source/modules/asura-base/Utilities/dynamic_array.h
@@ -0,0 +1,337 @@
+#pragma once
+
+#include <memory> // std::uninitialized_fill
+
+// dynamic_array - simplified version of std::vector<T>
+//
+// features:
+// . always uses memcpy for copying elements. Your data structures must be simple and can't have internal pointers / rely on copy constructor.
+// . EASTL like push_back(void) implementation
+// Existing std STL implementations implement insertion operations by copying from an element.
+// For example, resize(size() + 1) creates a throw-away temporary object.
+// There is no way in existing std STL implementations to add an element to a container without implicitly or
+// explicitly providing one to copy from (aside from some existing POD optimizations).
+// For expensive-to-construct objects this creates a potentially serious performance problem.
+// . grows X2 on reallocation
+// . small code footprint
+// . clear actually deallocates memory
+// . resize does NOT initialize members!
+//
+// Changelog:
+// Added pop_back()
+// Added assign()
+// Added clear() - frees the data, use resize(0) to clear w/o freeing
+// zero allocation for empty array
+//
+//
+template<typename T>
+struct AlignOfType
+{
+ enum { align = ALIGN_OF(T) };
+};
+
+
+template <typename T, size_t align = AlignOfType<T>::align, MemLabelIdentifier defaultLabel = kMemDynamicArrayId>
+struct dynamic_array
+{
+public:
+ typedef T* iterator;
+ typedef const T* const_iterator;
+ typedef T value_type;
+ typedef size_t size_type;
+ typedef size_t difference_type;
+ typedef T& reference;
+ typedef const T& const_reference;
+
+public:
+
+ dynamic_array() : m_data(NULL), m_label(defaultLabel, NULL), m_size(0), m_capacity(0)
+ {
+ m_label = MemLabelId(defaultLabel, GET_CURRENT_ALLOC_ROOT_HEADER());
+ }
+
+ dynamic_array(MemLabelRef label) : m_data(NULL), m_label(label), m_size(0), m_capacity(0)
+ {
+ }
+
+ explicit dynamic_array(size_t size, MemLabelRef label)
+ : m_label(label), m_size(size), m_capacity(size)
+ {
+ m_data = allocate(size);
+ }
+
+ dynamic_array(size_t size, T const& init_value, MemLabelRef label)
+ : m_label(label), m_size(size), m_capacity(size)
+ {
+ m_data = allocate(size);
+ std::uninitialized_fill(m_data, m_data + size, init_value);
+ }
+
+ ~dynamic_array()
+ {
+ if (owns_data())
+ m_data = deallocate(m_data);
+ }
+
+ dynamic_array(const dynamic_array& other) : m_capacity(0), m_size(0), m_label(other.m_label)
+ {
+ //m_label.SetRootHeader(GET_CURRENT_ALLOC_ROOT_HEADER());
+ m_data = NULL;
+ assign(other.begin(), other.end());
+ }
+
+ dynamic_array& operator=(const dynamic_array& other)
+ {
+ // should not allocate memory unless we have to
+ assign(other.begin(), other.end());
+ return *this;
+ }
+
+ void clear()
+ {
+ if (owns_data())
+ m_data = deallocate(m_data);
+ m_size = 0;
+ m_capacity = 0;
+ }
+
+ void assign(const_iterator begin, const_iterator end)
+ {
+ Assert(begin <= end);
+
+ resize_uninitialized(end - begin);
+ memcpy(m_data, begin, m_size * sizeof(T));
+ }
+
+ void erase(iterator input_begin, iterator input_end)
+ {
+ Assert(input_begin <= input_end);
+ Assert(input_begin >= begin());
+ Assert(input_end <= end());
+
+ size_t leftOverSize = end() - input_end;
+ memmove(input_begin, input_end, leftOverSize * sizeof(T));
+ m_size -= input_end - input_begin;
+ }
+
+ iterator erase(iterator position)
+ {
+ Assert(position >= begin());
+ Assert(position < end());
+
+ size_t leftOverSize = end() - position - 1;
+ memmove(position, position + 1, leftOverSize * sizeof(T));
+ m_size -= 1;
+
+ return position;
+ }
+
+ iterator insert(iterator insert_before, const_iterator input_begin, const_iterator input_end)
+ {
+ Assert(input_begin <= input_end);
+ Assert(insert_before >= begin());
+ Assert(insert_before <= end());
+
+ // resize (make sure that insertBefore does not get invalid in the meantime because of a reallocation)
+ size_t insert_before_index = insert_before - begin();
+ size_t elements_to_be_moved = size() - insert_before_index;
+ resize_uninitialized((input_end - input_begin) + size());
+ insert_before = begin() + insert_before_index;
+
+ size_t insertsize = input_end - input_begin;
+ // move to the end of where the inserted data will be
+ memmove(insert_before + insertsize, insert_before, elements_to_be_moved * sizeof(T));
+ // inject input data in the hole we just created
+ memcpy(insert_before, input_begin, insertsize * sizeof(T));
+
+ return insert_before;
+ }
+
+ iterator insert(iterator insertBefore, const T& t) { return insert(insertBefore, &t, &t + 1); }
+
+ void swap(dynamic_array& other) throw()
+ {
+ if (m_data) UNITY_TRANSFER_OWNERSHIP_TO_HEADER(m_data, m_label, other.m_label.GetRootHeader());
+ if (other.m_data) UNITY_TRANSFER_OWNERSHIP_TO_HEADER(other.m_data, other.m_label, m_label.GetRootHeader());
+ std::swap(m_data, other.m_data);
+ std::swap(m_size, other.m_size);
+ std::swap(m_capacity, other.m_capacity);
+ std::swap(m_label, other.m_label);
+ }
+
+ T& push_back()
+ {
+ if (++m_size > capacity())
+ reserve(std::max<size_t>(capacity() * 2, 1));
+ return back();
+ }
+
+ void push_back(const T& t)
+ {
+ push_back() = t;
+ }
+
+ void pop_back()
+ {
+ Assert(m_size >= 1);
+ m_size--;
+ }
+
+ void resize_uninitialized(size_t size, bool double_on_resize = false)
+ {
+ m_size = size;
+ if (m_size <= capacity())
+ return;
+
+ if (double_on_resize && size < capacity() * 2)
+ size = capacity() * 2;
+ reserve(size);
+ }
+
+ void resize_initialized(size_t size, const T& t = T(), bool double_on_resize = false)
+ {
+ if (size > capacity())
+ {
+ size_t requested_size = size;
+ if (double_on_resize && size < capacity() * 2)
+ requested_size = capacity() * 2;
+ reserve(requested_size);
+ }
+
+ if (size > m_size)
+ std::uninitialized_fill(m_data + m_size, m_data + size, t);
+ m_size = size;
+ }
+
+ void reserve(size_t inCapacity)
+ {
+ if (capacity() >= inCapacity)
+ return;
+
+ if (owns_data())
+ {
+ m_capacity = inCapacity;
+ m_data = reallocate(m_data, inCapacity);
+ }
+ else
+ {
+ T* newData = allocate(inCapacity);
+ memcpy(newData, m_data, m_size * sizeof(T));
+
+ // Invalidate old non-owned data, since using the data from two places is most likely a really really bad idea.
+#if DEBUGMODE
+ memset(m_data, 0xCD, capacity() * sizeof(T));
+#endif
+
+ m_capacity = inCapacity; // and clear reference bit
+ m_data = newData;
+ }
+ }
+
+ void assign_external(T* begin, T* end)
+ {
+ if (owns_data())
+ m_data = deallocate(m_data);
+ m_size = m_capacity = reinterpret_cast<value_type*> (end) - reinterpret_cast<value_type*> (begin);
+ Assert(m_size < k_reference_bit);
+ m_capacity |= k_reference_bit;
+ m_data = begin;
+ }
+
+ void set_owns_data(bool ownsData)
+ {
+ if (ownsData)
+ m_capacity &= ~k_reference_bit;
+ else
+ m_capacity |= k_reference_bit;
+ }
+
+ void shrink_to_fit()
+ {
+ if (owns_data())
+ {
+ m_capacity = m_size;
+ m_data = reallocate(m_data, m_size);
+ }
+ }
+
+ const T& back() const { Assert(m_size != 0); return m_data[m_size - 1]; }
+ const T& front() const { Assert(m_size != 0); return m_data[0]; }
+
+ T& back() { Assert(m_size != 0); return m_data[m_size - 1]; }
+ T& front() { Assert(m_size != 0); return m_data[0]; }
+
+ T* data() { return m_data; }
+ T const* data() const { return m_data; }
+
+ bool empty() const { return m_size == 0; }
+ size_t size() const { return m_size; }
+ size_t capacity() const { return m_capacity & ~k_reference_bit; }
+
+ T const& operator[] (size_t index) const { DebugAssert(index < m_size); return m_data[index]; }
+ T& operator[] (size_t index) { DebugAssert(index < m_size); return m_data[index]; }
+
+ T const* begin() const { return m_data; }
+ T* begin() { return m_data; }
+
+ T const* end() const { return m_data + m_size; }
+ T* end() { return m_data + m_size; }
+
+ bool owns_data() { return (m_capacity & k_reference_bit) == 0; }
+
+ bool equals(const dynamic_array& other)
+ {
+ if (m_size != other.m_size)
+ return false;
+
+ for (int i = 0; i < m_size; i++)
+ {
+ if (m_data[i] != other.m_data[i])
+ return false;
+ }
+
+ return true;
+ }
+
+ void set_memory_label(MemLabelRef label)
+ {
+ Assert(m_data == NULL);
+ m_label = label;
+ }
+
+private:
+
+ static const size_t k_reference_bit = (size_t)1 << (sizeof(size_t) * 8 - 1);
+
+ T* allocate(size_t size)
+ {
+ // If you are getting this error then you are trying to allocate memory for an incomplete type
+ CompileTimeAssert(sizeof(T) != 0, "incomplete type");
+ CompileTimeAssert(align != 0, "incomplete type");
+
+ return static_cast<T*> (UNITY_MALLOC_ALIGNED(m_label, size * sizeof(T), align));
+ }
+
+ T* deallocate(T* data)
+ {
+ Assert(owns_data());
+ UNITY_FREE(m_label, data);
+ return NULL;
+ }
+
+ T* reallocate(T* data, size_t size)
+ {
+ // If you are getting this error then you are trying to allocate memory for an incomplete type
+ CompileTimeAssert(sizeof(T) != 0, "incomplete type");
+ CompileTimeAssert(align != 0, "incomplete type");
+
+ Assert(owns_data());
+ int alignof = static_cast<int>(align);
+ return static_cast<T*> (UNITY_REALLOC_ALIGNED(m_label, data, size * sizeof(T), alignof));
+ }
+
+ T* m_data;
+ MemLabelId m_label;
+ size_t m_size;
+ size_t m_capacity;
+};