diff options
author | chai <chaifix@163.com> | 2019-08-16 08:54:08 +0800 |
---|---|---|
committer | chai <chaifix@163.com> | 2019-08-16 08:54:08 +0800 |
commit | a077eb38b01292611f4f6031b75e3e2c1c20f06e (patch) | |
tree | 8f760483d7b0290952bbdb5bcd8f3943102aeb3a /Source/modules/asura-base | |
parent | 6a065c913e9308cc72e1ad0723b6167048f439b6 (diff) |
Diffstat (limited to 'Source/modules/asura-base')
-rw-r--r-- | Source/modules/asura-base/Classes.h | 11 | ||||
-rw-r--r-- | Source/modules/asura-base/Math/Matrix44.h | 8 | ||||
-rw-r--r-- | Source/modules/asura-base/Math/Quaternion.h | 4 | ||||
-rw-r--r-- | Source/modules/asura-base/Math/Random.h | 4 | ||||
-rw-r--r-- | Source/modules/asura-base/Math/Rect.hpp | 8 | ||||
-rw-r--r-- | Source/modules/asura-base/Math/Transform.h | 6 | ||||
-rw-r--r-- | Source/modules/asura-base/Math/Vector2.hpp | 6 | ||||
-rw-r--r-- | Source/modules/asura-base/Math/Vector3.hpp | 8 | ||||
-rw-r--r-- | Source/modules/asura-base/Math/Vector4.h | 8 | ||||
-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.h | 0 | ||||
-rw-r--r-- | Source/modules/asura-base/Misc/UTF8.cpp | 395 | ||||
-rw-r--r-- | Source/modules/asura-base/Misc/UTF8.h | 20 | ||||
-rw-r--r-- | Source/modules/asura-base/Utilities/LinkedList.h | 388 | ||||
-rw-r--r-- | Source/modules/asura-base/Utilities/dynamic_array.h | 337 |
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; +}; |