summaryrefslogtreecommitdiff
path: root/Source/Asura.Engine/text
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Asura.Engine/text')
-rw-r--r--Source/Asura.Engine/text/glyph.cpp0
-rw-r--r--Source/Asura.Engine/text/glyph.h0
-rw-r--r--Source/Asura.Engine/text/string.cpp376
-rw-r--r--Source/Asura.Engine/text/string.hpp594
-rw-r--r--Source/Asura.Engine/text/string.inl29
-rw-r--r--Source/Asura.Engine/text/ttf.cpp0
-rw-r--r--Source/Asura.Engine/text/ttf.h17
-rw-r--r--Source/Asura.Engine/text/utf.hpp720
-rw-r--r--Source/Asura.Engine/text/utf.inl752
9 files changed, 2488 insertions, 0 deletions
diff --git a/Source/Asura.Engine/text/glyph.cpp b/Source/Asura.Engine/text/glyph.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/Asura.Engine/text/glyph.cpp
diff --git a/Source/Asura.Engine/text/glyph.h b/Source/Asura.Engine/text/glyph.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/Asura.Engine/text/glyph.h
diff --git a/Source/Asura.Engine/text/string.cpp b/Source/Asura.Engine/text/string.cpp
new file mode 100644
index 0000000..8c9c55a
--- /dev/null
+++ b/Source/Asura.Engine/text/string.cpp
@@ -0,0 +1,376 @@
+#include "String.hpp"
+#include "Utf.hpp"
+
+namespace AsuraEngine
+{
+ namespace Text
+ {
+
+
+ ////////////////////////////////////////////////////////////
+ const std::size_t String::InvalidPos = std::basic_string<uint32>::npos;
+
+
+ ////////////////////////////////////////////////////////////
+ String::String()
+ {
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ String::String(char ansiChar, const std::locale& locale)
+ {
+ mString += Utf32::DecodeAnsi(ansiChar, locale);
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ String::String(wchar_t wideChar)
+ {
+ mString += Utf32::DecodeWide(wideChar);
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ String::String(uint32 utf32Char)
+ {
+ mString += utf32Char;
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ String::String(const char* ansiString, const std::locale& locale)
+ {
+ if (ansiString)
+ {
+ std::size_t length = strlen(ansiString);
+ if (length > 0)
+ {
+ mString.reserve(length + 1);
+ Utf32::FromAnsi(ansiString, ansiString + length, std::back_inserter(mString), locale);
+ }
+ }
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ String::String(const std::string& ansiString, const std::locale& locale)
+ {
+ mString.reserve(ansiString.length() + 1);
+ Utf32::FromAnsi(ansiString.begin(), ansiString.end(), std::back_inserter(mString), locale);
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ String::String(const wchar_t* wideString)
+ {
+ if (wideString)
+ {
+ std::size_t length = std::wcslen(wideString);
+ if (length > 0)
+ {
+ mString.reserve(length + 1);
+ Utf32::FromWide(wideString, wideString + length, std::back_inserter(mString));
+ }
+ }
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ String::String(const std::wstring& wideString)
+ {
+ mString.reserve(wideString.length() + 1);
+ Utf32::FromWide(wideString.begin(), wideString.end(), std::back_inserter(mString));
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ String::String(const uint32* utf32String)
+ {
+ if (utf32String)
+ mString = utf32String;
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ String::String(const std::basic_string<uint32>& utf32String) :
+ mString(utf32String)
+ {
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ String::String(const String& copy) :
+ mString(copy.mString)
+ {
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ String::operator std::string() const
+ {
+ return ToAnsiString();
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ String::operator std::wstring() const
+ {
+ return ToWideString();
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ std::string String::ToAnsiString(const std::locale& locale) const
+ {
+ // Prepare the output string
+ std::string output;
+ output.reserve(mString.length() + 1);
+
+ // Convert
+ Utf32::ToAnsi(mString.begin(), mString.end(), std::back_inserter(output), 0, locale);
+
+ return output;
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ std::wstring String::ToWideString() const
+ {
+ // Prepare the output string
+ std::wstring output;
+ output.reserve(mString.length() + 1);
+
+ // Convert
+ Utf32::ToWide(mString.begin(), mString.end(), std::back_inserter(output), 0);
+
+ return output;
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ std::basic_string<uint8> String::ToUtf8() const
+ {
+ // Prepare the output string
+ std::basic_string<uint8> output;
+ output.reserve(mString.length());
+
+ // Convert
+ Utf32::ToUtf8(mString.begin(), mString.end(), std::back_inserter(output));
+
+ return output;
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ std::basic_string<uint16> String::ToUtf16() const
+ {
+ // Prepare the output string
+ std::basic_string<uint16> output;
+ output.reserve(mString.length());
+
+ // Convert
+ Utf32::ToUtf16(mString.begin(), mString.end(), std::back_inserter(output));
+
+ return output;
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ std::basic_string<uint32> String::ToUtf32() const
+ {
+ return mString;
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ String& String::operator =(const String& right)
+ {
+ mString = right.mString;
+ return *this;
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ String& String::operator +=(const String& right)
+ {
+ mString += right.mString;
+ return *this;
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ uint32 String::operator [](std::size_t index) const
+ {
+ return mString[index];
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ uint32& String::operator [](std::size_t index)
+ {
+ return mString[index];
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ void String::Clear()
+ {
+ mString.clear();
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ std::size_t String::GetSize() const
+ {
+ return mString.size();
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ bool String::IsEmpty() const
+ {
+ return mString.empty();
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ void String::Erase(std::size_t position, std::size_t count)
+ {
+ mString.erase(position, count);
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ void String::Insert(std::size_t position, const String& str)
+ {
+ mString.insert(position, str.mString);
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ std::size_t String::Find(const String& str, std::size_t start) const
+ {
+ return mString.find(str.mString, start);
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ void String::Replace(std::size_t position, std::size_t length, const String& replaceWith)
+ {
+ mString.replace(position, length, replaceWith.mString);
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ void String::Replace(const String& searchFor, const String& replaceWith)
+ {
+ std::size_t step = replaceWith.GetSize();
+ std::size_t len = searchFor.GetSize();
+ std::size_t pos = Find(searchFor);
+
+ // Replace each occurrence of search
+ while (pos != InvalidPos)
+ {
+ Replace(pos, len, replaceWith);
+ pos = Find(searchFor, pos + step);
+ }
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ String String::Substring(std::size_t position, std::size_t length) const
+ {
+ return mString.substr(position, length);
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ const uint32* String::GetData() const
+ {
+ return mString.c_str();
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ String::Iterator String::Begin()
+ {
+ return mString.begin();
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ String::ConstIterator String::Begin() const
+ {
+ return mString.begin();
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ String::Iterator String::End()
+ {
+ return mString.end();
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ String::ConstIterator String::End() const
+ {
+ return mString.end();
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ bool operator ==(const String& left, const String& right)
+ {
+ return left.mString == right.mString;
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ bool operator !=(const String& left, const String& right)
+ {
+ return !(left == right);
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ bool operator <(const String& left, const String& right)
+ {
+ return left.mString < right.mString;
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ bool operator >(const String& left, const String& right)
+ {
+ return right < left;
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ bool operator <=(const String& left, const String& right)
+ {
+ return !(right < left);
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ bool operator >=(const String& left, const String& right)
+ {
+ return !(left < right);
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ String operator +(const String& left, const String& right)
+ {
+ String string = left;
+ string += right;
+
+ return string;
+ }
+
+
+ }
+}
diff --git a/Source/Asura.Engine/text/string.hpp b/Source/Asura.Engine/text/string.hpp
new file mode 100644
index 0000000..226735b
--- /dev/null
+++ b/Source/Asura.Engine/text/string.hpp
@@ -0,0 +1,594 @@
+#ifndef __ASURA_ENGINE_STRING_H__
+#define __ASURA_ENGINE_STRING_H__
+
+#include "Config.h"
+#include <iterator>
+#include <locale>
+#include <string>
+
+namespace AsuraEngine
+{
+ namespace Text
+ {
+
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Utility string class that automatically handles
+ /// conversions between types and encodings
+ ///
+ ////////////////////////////////////////////////////////////
+ class String
+ {
+ public:
+
+ ////////////////////////////////////////////////////////////
+ // Types
+ ////////////////////////////////////////////////////////////
+ typedef std::basic_string<uint32>::iterator Iterator; ///< Iterator type
+ typedef std::basic_string<uint32>::const_iterator ConstIterator; ///< Read-only iterator type
+
+ ////////////////////////////////////////////////////////////
+ // Static member data
+ ////////////////////////////////////////////////////////////
+ static const std::size_t InvalidPos; ///< Represents an invalid position in the string
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Default constructor
+ ///
+ /// This constructor creates an empty string.
+ ///
+ ////////////////////////////////////////////////////////////
+ String();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Construct from a single ANSI character and a locale
+ ///
+ /// The source character is converted to UTF-32 according
+ /// to the given locale.
+ ///
+ /// \param ansiChar ANSI character to convert
+ /// \param locale Locale to use for conversion
+ ///
+ ////////////////////////////////////////////////////////////
+ String(char ansiChar, const std::locale& locale = std::locale());
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Construct from single wide character
+ ///
+ /// \param wideChar Wide character to convert
+ ///
+ ////////////////////////////////////////////////////////////
+ String(wchar_t wideChar);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Construct from single UTF-32 character
+ ///
+ /// \param utf32Char UTF-32 character to convert
+ ///
+ ////////////////////////////////////////////////////////////
+ String(uint utf32Char);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Construct from a null-terminated C-style ANSI string and a locale
+ ///
+ /// The source string is converted to UTF-32 according
+ /// to the given locale.
+ ///
+ /// \param ansiString ANSI string to convert
+ /// \param locale Locale to use for conversion
+ ///
+ ////////////////////////////////////////////////////////////
+ String(const char* ansiString, const std::locale& locale = std::locale());
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Construct from an ANSI string and a locale
+ ///
+ /// The source string is converted to UTF-32 according
+ /// to the given locale.
+ ///
+ /// \param ansiString ANSI string to convert
+ /// \param locale Locale to use for conversion
+ ///
+ ////////////////////////////////////////////////////////////
+ String(const std::string& ansiString, const std::locale& locale = std::locale());
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Construct from null-terminated C-style wide string
+ ///
+ /// \param wideString Wide string to convert
+ ///
+ ////////////////////////////////////////////////////////////
+ String(const wchar_t* wideString);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Construct from a wide string
+ ///
+ /// \param wideString Wide string to convert
+ ///
+ ////////////////////////////////////////////////////////////
+ String(const std::wstring& wideString);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Construct from a null-terminated C-style UTF-32 string
+ ///
+ /// \param utf32String UTF-32 string to assign
+ ///
+ ////////////////////////////////////////////////////////////
+ String(const uint* utf32String);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Construct from an UTF-32 string
+ ///
+ /// \param utf32String UTF-32 string to assign
+ ///
+ ////////////////////////////////////////////////////////////
+ String(const std::basic_string<uint>& utf32String);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Copy constructor
+ ///
+ /// \param copy Instance to copy
+ ///
+ ////////////////////////////////////////////////////////////
+ String(const String& copy);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Create a new sf::String from a UTF-8 encoded string
+ ///
+ /// \param begin Forward iterator to the beginning of the UTF-8 sequence
+ /// \param end Forward iterator to the end of the UTF-8 sequence
+ ///
+ /// \return A sf::String containing the source string
+ ///
+ /// \see fromUtf16, fromUtf32
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename T>
+ static String FromUtf8(T begin, T end);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Create a new sf::String from a UTF-16 encoded string
+ ///
+ /// \param begin Forward iterator to the beginning of the UTF-16 sequence
+ /// \param end Forward iterator to the end of the UTF-16 sequence
+ ///
+ /// \return A sf::String containing the source string
+ ///
+ /// \see fromUtf8, fromUtf32
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename T>
+ static String FromUtf16(T begin, T end);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Create a new sf::String from a UTF-32 encoded string
+ ///
+ /// This function is provided for consistency, it is equivalent to
+ /// using the constructors that takes a const sf::uint* or
+ /// a std::basic_string<sf::uint>.
+ ///
+ /// \param begin Forward iterator to the beginning of the UTF-32 sequence
+ /// \param end Forward iterator to the end of the UTF-32 sequence
+ ///
+ /// \return A sf::String containing the source string
+ ///
+ /// \see fromUtf8, fromUtf16
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename T>
+ static String FromUtf32(T begin, T end);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Implicit conversion operator to std::string (ANSI string)
+ ///
+ /// The current global locale is used for conversion. If you
+ /// want to explicitly specify a locale, see toAnsiString.
+ /// Characters that do not fit in the target encoding are
+ /// discarded from the returned string.
+ /// This operator is defined for convenience, and is equivalent
+ /// to calling toAnsiString().
+ ///
+ /// \return Converted ANSI string
+ ///
+ /// \see toAnsiString, operator std::wstring
+ ///
+ ////////////////////////////////////////////////////////////
+ operator std::string() const;
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Implicit conversion operator to std::wstring (wide string)
+ ///
+ /// Characters that do not fit in the target encoding are
+ /// discarded from the returned string.
+ /// This operator is defined for convenience, and is equivalent
+ /// to calling toWideString().
+ ///
+ /// \return Converted wide string
+ ///
+ /// \see toWideString, operator std::string
+ ///
+ ////////////////////////////////////////////////////////////
+ operator std::wstring() const;
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert the Unicode string to an ANSI string
+ ///
+ /// The UTF-32 string is converted to an ANSI string in
+ /// the encoding defined by \a locale.
+ /// Characters that do not fit in the target encoding are
+ /// discarded from the returned string.
+ ///
+ /// \param locale Locale to use for conversion
+ ///
+ /// \return Converted ANSI string
+ ///
+ /// \see toWideString, operator std::string
+ ///
+ ////////////////////////////////////////////////////////////
+ std::string ToAnsiString(const std::locale& locale = std::locale()) const;
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert the Unicode string to a wide string
+ ///
+ /// Characters that do not fit in the target encoding are
+ /// discarded from the returned string.
+ ///
+ /// \return Converted wide string
+ ///
+ /// \see toAnsiString, operator std::wstring
+ ///
+ ////////////////////////////////////////////////////////////
+ std::wstring ToWideString() const;
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert the Unicode string to a UTF-8 string
+ ///
+ /// \return Converted UTF-8 string
+ ///
+ /// \see toUtf16, toUtf32
+ ///
+ ////////////////////////////////////////////////////////////
+ std::basic_string<uint8> ToUtf8() const;
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert the Unicode string to a UTF-16 string
+ ///
+ /// \return Converted UTF-16 string
+ ///
+ /// \see toUtf8, toUtf32
+ ///
+ ////////////////////////////////////////////////////////////
+ std::basic_string<uint16> ToUtf16() const;
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert the Unicode string to a UTF-32 string
+ ///
+ /// This function doesn't perform any conversion, since the
+ /// string is already stored as UTF-32 internally.
+ ///
+ /// \return Converted UTF-32 string
+ ///
+ /// \see toUtf8, toUtf16
+ ///
+ ////////////////////////////////////////////////////////////
+ std::basic_string<uint> ToUtf32() const;
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Overload of assignment operator
+ ///
+ /// \param right Instance to assign
+ ///
+ /// \return Reference to self
+ ///
+ ////////////////////////////////////////////////////////////
+ String& operator =(const String& right);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Overload of += operator to append an UTF-32 string
+ ///
+ /// \param right String to append
+ ///
+ /// \return Reference to self
+ ///
+ ////////////////////////////////////////////////////////////
+ String& operator +=(const String& right);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Overload of [] operator to access a character by its position
+ ///
+ /// This function provides read-only access to characters.
+ /// Note: the behavior is undefined if \a index is out of range.
+ ///
+ /// \param index Index of the character to get
+ ///
+ /// \return Character at position \a index
+ ///
+ ////////////////////////////////////////////////////////////
+ uint operator [](std::size_t index) const;
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Overload of [] operator to access a character by its position
+ ///
+ /// This function provides read and write access to characters.
+ /// Note: the behavior is undefined if \a index is out of range.
+ ///
+ /// \param index Index of the character to get
+ ///
+ /// \return Reference to the character at position \a index
+ ///
+ ////////////////////////////////////////////////////////////
+ uint& operator [](std::size_t index);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Clear the string
+ ///
+ /// This function removes all the characters from the string.
+ ///
+ /// \see isEmpty, erase
+ ///
+ ////////////////////////////////////////////////////////////
+ void Clear();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Get the size of the string
+ ///
+ /// \return Number of characters in the string
+ ///
+ /// \see isEmpty
+ ///
+ ////////////////////////////////////////////////////////////
+ std::size_t GetSize() const;
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Check whether the string is empty or not
+ ///
+ /// \return True if the string is empty (i.e. contains no character)
+ ///
+ /// \see clear, getSize
+ ///
+ ////////////////////////////////////////////////////////////
+ bool IsEmpty() const;
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Erase one or more characters from the string
+ ///
+ /// This function removes a sequence of \a count characters
+ /// starting from \a position.
+ ///
+ /// \param position Position of the first character to erase
+ /// \param count Number of characters to erase
+ ///
+ ////////////////////////////////////////////////////////////
+ void Erase(std::size_t position, std::size_t count = 1);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Insert one or more characters into the string
+ ///
+ /// This function inserts the characters of \a str
+ /// into the string, starting from \a position.
+ ///
+ /// \param position Position of insertion
+ /// \param str Characters to insert
+ ///
+ ////////////////////////////////////////////////////////////
+ void Insert(std::size_t position, const String& str);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Find a sequence of one or more characters in the string
+ ///
+ /// This function searches for the characters of \a str
+ /// in the string, starting from \a start.
+ ///
+ /// \param str Characters to find
+ /// \param start Where to begin searching
+ ///
+ /// \return Position of \a str in the string, or String::InvalidPos if not found
+ ///
+ ////////////////////////////////////////////////////////////
+ std::size_t Find(const String& str, std::size_t start = 0) const;
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Replace a substring with another string
+ ///
+ /// This function replaces the substring that starts at index \a position
+ /// and spans \a length characters with the string \a replaceWith.
+ ///
+ /// \param position Index of the first character to be replaced
+ /// \param length Number of characters to replace. You can pass InvalidPos to
+ /// replace all characters until the end of the string.
+ /// \param replaceWith String that replaces the given substring.
+ ///
+ ////////////////////////////////////////////////////////////
+ void Replace(std::size_t position, std::size_t length, const String& replaceWith);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Replace all occurrences of a substring with a replacement string
+ ///
+ /// This function replaces all occurrences of \a searchFor in this string
+ /// with the string \a replaceWith.
+ ///
+ /// \param searchFor The value being searched for
+ /// \param replaceWith The value that replaces found \a searchFor values
+ ///
+ ////////////////////////////////////////////////////////////
+ void Replace(const String& searchFor, const String& replaceWith);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Return a part of the string
+ ///
+ /// This function returns the substring that starts at index \a position
+ /// and spans \a length characters.
+ ///
+ /// \param position Index of the first character
+ /// \param length Number of characters to include in the substring (if
+ /// the string is shorter, as many characters as possible
+ /// are included). \ref InvalidPos can be used to include all
+ /// characters until the end of the string.
+ ///
+ /// \return String object containing a substring of this object
+ ///
+ ////////////////////////////////////////////////////////////
+ String Substring(std::size_t position, std::size_t length = InvalidPos) const;
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Get a pointer to the C-style array of characters
+ ///
+ /// This functions provides a read-only access to a
+ /// null-terminated C-style representation of the string.
+ /// The returned pointer is temporary and is meant only for
+ /// immediate use, thus it is not recommended to store it.
+ ///
+ /// \return Read-only pointer to the array of characters
+ ///
+ ////////////////////////////////////////////////////////////
+ const uint* GetData() const;
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Return an iterator to the beginning of the string
+ ///
+ /// \return Read-write iterator to the beginning of the string characters
+ ///
+ /// \see end
+ ///
+ ////////////////////////////////////////////////////////////
+ Iterator Begin();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Return an iterator to the beginning of the string
+ ///
+ /// \return Read-only iterator to the beginning of the string characters
+ ///
+ /// \see end
+ ///
+ ////////////////////////////////////////////////////////////
+ ConstIterator Begin() const;
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Return an iterator to the end of the string
+ ///
+ /// The end iterator refers to 1 position past the last character;
+ /// thus it represents an invalid character and should never be
+ /// accessed.
+ ///
+ /// \return Read-write iterator to the end of the string characters
+ ///
+ /// \see begin
+ ///
+ ////////////////////////////////////////////////////////////
+ Iterator End();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Return an iterator to the end of the string
+ ///
+ /// The end iterator refers to 1 position past the last character;
+ /// thus it represents an invalid character and should never be
+ /// accessed.
+ ///
+ /// \return Read-only iterator to the end of the string characters
+ ///
+ /// \see begin
+ ///
+ ////////////////////////////////////////////////////////////
+ ConstIterator End() const;
+
+ private:
+
+ friend bool operator ==(const String& left, const String& right);
+ friend bool operator <(const String& left, const String& right);
+
+ ////////////////////////////////////////////////////////////
+ // Member data
+ ////////////////////////////////////////////////////////////
+ std::basic_string<uint> mString; ///< Internal string of UTF-32 characters
+ };
+
+ ////////////////////////////////////////////////////////////
+ /// \relates String
+ /// \brief Overload of == operator to compare two UTF-32 strings
+ ///
+ /// \param left Left operand (a string)
+ /// \param right Right operand (a string)
+ ///
+ /// \return True if both strings are equal
+ ///
+ ////////////////////////////////////////////////////////////
+ bool operator ==(const String& left, const String& right);
+
+ ////////////////////////////////////////////////////////////
+ /// \relates String
+ /// \brief Overload of != operator to compare two UTF-32 strings
+ ///
+ /// \param left Left operand (a string)
+ /// \param right Right operand (a string)
+ ///
+ /// \return True if both strings are different
+ ///
+ ////////////////////////////////////////////////////////////
+ bool operator !=(const String& left, const String& right);
+
+ ////////////////////////////////////////////////////////////
+ /// \relates String
+ /// \brief Overload of < operator to compare two UTF-32 strings
+ ///
+ /// \param left Left operand (a string)
+ /// \param right Right operand (a string)
+ ///
+ /// \return True if \a left is lexicographically before \a right
+ ///
+ ////////////////////////////////////////////////////////////
+ bool operator <(const String& left, const String& right);
+
+ ////////////////////////////////////////////////////////////
+ /// \relates String
+ /// \brief Overload of > operator to compare two UTF-32 strings
+ ///
+ /// \param left Left operand (a string)
+ /// \param right Right operand (a string)
+ ///
+ /// \return True if \a left is lexicographically after \a right
+ ///
+ ////////////////////////////////////////////////////////////
+ bool operator >(const String& left, const String& right);
+
+ ////////////////////////////////////////////////////////////
+ /// \relates String
+ /// \brief Overload of <= operator to compare two UTF-32 strings
+ ///
+ /// \param left Left operand (a string)
+ /// \param right Right operand (a string)
+ ///
+ /// \return True if \a left is lexicographically before or equivalent to \a right
+ ///
+ ////////////////////////////////////////////////////////////
+ bool operator <=(const String& left, const String& right);
+
+ ////////////////////////////////////////////////////////////
+ /// \relates String
+ /// \brief Overload of >= operator to compare two UTF-32 strings
+ ///
+ /// \param left Left operand (a string)
+ /// \param right Right operand (a string)
+ ///
+ /// \return True if \a left is lexicographically after or equivalent to \a right
+ ///
+ ////////////////////////////////////////////////////////////
+ bool operator >=(const String& left, const String& right);
+
+ ////////////////////////////////////////////////////////////
+ /// \relates String
+ /// \brief Overload of binary + operator to concatenate two strings
+ ///
+ /// \param left Left operand (a string)
+ /// \param right Right operand (a string)
+ ///
+ /// \return Concatenated string
+ ///
+ ////////////////////////////////////////////////////////////
+ String operator +(const String& left, const String& right);
+
+ #include "String.inl"
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/Source/Asura.Engine/text/string.inl b/Source/Asura.Engine/text/string.inl
new file mode 100644
index 0000000..ef18228
--- /dev/null
+++ b/Source/Asura.Engine/text/string.inl
@@ -0,0 +1,29 @@
+
+////////////////////////////////////////////////////////////
+template <typename T>
+String String::fromUtf8(T begin, T end)
+{
+ String string;
+ Utf8::toUtf32(begin, end, std::back_inserter(string.m_string));
+ return string;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename T>
+String String::fromUtf16(T begin, T end)
+{
+ String string;
+ Utf16::toUtf32(begin, end, std::back_inserter(string.m_string));
+ return string;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename T>
+String String::fromUtf32(T begin, T end)
+{
+ String string;
+ string.m_string.assign(begin, end);
+ return string;
+}
diff --git a/Source/Asura.Engine/text/ttf.cpp b/Source/Asura.Engine/text/ttf.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/Asura.Engine/text/ttf.cpp
diff --git a/Source/Asura.Engine/text/ttf.h b/Source/Asura.Engine/text/ttf.h
new file mode 100644
index 0000000..840b63e
--- /dev/null
+++ b/Source/Asura.Engine/text/ttf.h
@@ -0,0 +1,17 @@
+#ifndef __ASURA_TTF_H__
+#define __ASURA_TTF_H__
+
+namespace AsuraEngine
+{
+ namespace Text
+ {
+
+ class TTF
+ {
+
+ };
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/Source/Asura.Engine/text/utf.hpp b/Source/Asura.Engine/text/utf.hpp
new file mode 100644
index 0000000..2e04ee4
--- /dev/null
+++ b/Source/Asura.Engine/text/utf.hpp
@@ -0,0 +1,720 @@
+#ifndef __ASURA_UTF_HPP__
+#define __ASURA_UTF_HPP__
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <algorithm>
+#include <locale>
+#include <string>
+#include <cstdlib>
+
+namespace AsuraEngine
+{
+ namespace Text
+ {
+
+ template <unsigned int N>
+ class Utf;
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Specialization of the Utf template for UTF-8
+ ///
+ ////////////////////////////////////////////////////////////
+ template <>
+ class Utf<8>
+ {
+ public:
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Decode a single UTF-8 character
+ ///
+ /// Decoding a character means finding its unique 32-bits
+ /// code (called the codepoint) in the Unicode standard.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Codepoint of the decoded UTF-8 character
+ /// \param replacement Replacement character to use in case the UTF-8 sequence is invalid
+ ///
+ /// \return Iterator pointing to one past the last read element of the input sequence
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In>
+ static In Decode(In begin, In end, Uint32& output, Uint32 replacement = 0);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Encode a single UTF-8 character
+ ///
+ /// Encoding a character means converting a unique 32-bits
+ /// code (called the codepoint) in the target encoding, UTF-8.
+ ///
+ /// \param input Codepoint to encode as UTF-8
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to UTF-8 (use 0 to skip them)
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename Out>
+ static Out Encode(Uint32 input, Out output, Uint8 replacement = 0);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Advance to the next UTF-8 character
+ ///
+ /// This function is necessary for multi-elements encodings, as
+ /// a single character may use more than 1 storage element.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ ///
+ /// \return Iterator pointing to one past the last read element of the input sequence
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In>
+ static In Next(In begin, In end);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Count the number of characters of a UTF-8 sequence
+ ///
+ /// This function is necessary for multi-elements encodings, as
+ /// a single character may use more than 1 storage element, thus the
+ /// total size can be different from (begin - end).
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ ///
+ /// \return Iterator pointing to one past the last read element of the input sequence
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In>
+ static std::size_t Count(In begin, In end);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an ANSI characters range to UTF-8
+ ///
+ /// The current global locale will be used by default, unless you
+ /// pass a custom one in the \a locale parameter.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param locale Locale to use for conversion
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out FromAnsi(In begin, In end, Out output, const std::locale& locale = std::locale());
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a wide characters range to UTF-8
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out FromWide(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-8
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out FromLatin1(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an UTF-8 characters range to ANSI characters
+ ///
+ /// The current global locale will be used by default, unless you
+ /// pass a custom one in the \a locale parameter.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them)
+ /// \param locale Locale to use for conversion
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToAnsi(In begin, In end, Out output, char replacement = 0, const std::locale& locale = std::locale());
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an UTF-8 characters range to wide characters
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToWide(In begin, In end, Out output, wchar_t replacement = 0);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an UTF-8 characters range to latin-1 (ISO-5589-1) characters
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToLatin1(In begin, In end, Out output, char replacement = 0);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a UTF-8 characters range to UTF-8
+ ///
+ /// This functions does nothing more than a direct copy;
+ /// it is defined only to provide the same interface as other
+ /// specializations of the sf::Utf<> template, and allow
+ /// generic code to be written on top of it.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToUtf8(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a UTF-8 characters range to UTF-16
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToUtf16(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a UTF-8 characters range to UTF-32
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToUtf32(In begin, In end, Out output);
+ };
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Specialization of the Utf template for UTF-16
+ ///
+ ////////////////////////////////////////////////////////////
+ template <>
+ class Utf<16>
+ {
+ public:
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Decode a single UTF-16 character
+ ///
+ /// Decoding a character means finding its unique 32-bits
+ /// code (called the codepoint) in the Unicode standard.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Codepoint of the decoded UTF-16 character
+ /// \param replacement Replacement character to use in case the UTF-8 sequence is invalid
+ ///
+ /// \return Iterator pointing to one past the last read element of the input sequence
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In>
+ static In Decode(In begin, In end, Uint32& output, Uint32 replacement = 0);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Encode a single UTF-16 character
+ ///
+ /// Encoding a character means converting a unique 32-bits
+ /// code (called the codepoint) in the target encoding, UTF-16.
+ ///
+ /// \param input Codepoint to encode as UTF-16
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to UTF-16 (use 0 to skip them)
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename Out>
+ static Out Encode(Uint32 input, Out output, Uint16 replacement = 0);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Advance to the next UTF-16 character
+ ///
+ /// This function is necessary for multi-elements encodings, as
+ /// a single character may use more than 1 storage element.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ ///
+ /// \return Iterator pointing to one past the last read element of the input sequence
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In>
+ static In Next(In begin, In end);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Count the number of characters of a UTF-16 sequence
+ ///
+ /// This function is necessary for multi-elements encodings, as
+ /// a single character may use more than 1 storage element, thus the
+ /// total size can be different from (begin - end).
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ ///
+ /// \return Iterator pointing to one past the last read element of the input sequence
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In>
+ static std::size_t Count(In begin, In end);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an ANSI characters range to UTF-16
+ ///
+ /// The current global locale will be used by default, unless you
+ /// pass a custom one in the \a locale parameter.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param locale Locale to use for conversion
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out FromAnsi(In begin, In end, Out output, const std::locale& locale = std::locale());
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a wide characters range to UTF-16
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out FromWide(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-16
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out FromLatin1(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an UTF-16 characters range to ANSI characters
+ ///
+ /// The current global locale will be used by default, unless you
+ /// pass a custom one in the \a locale parameter.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them)
+ /// \param locale Locale to use for conversion
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToAnsi(In begin, In end, Out output, char replacement = 0, const std::locale& locale = std::locale());
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an UTF-16 characters range to wide characters
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToWide(In begin, In end, Out output, wchar_t replacement = 0);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an UTF-16 characters range to latin-1 (ISO-5589-1) characters
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToLatin1(In begin, In end, Out output, char replacement = 0);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a UTF-16 characters range to UTF-8
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToUtf8(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a UTF-16 characters range to UTF-16
+ ///
+ /// This functions does nothing more than a direct copy;
+ /// it is defined only to provide the same interface as other
+ /// specializations of the sf::Utf<> template, and allow
+ /// generic code to be written on top of it.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToUtf16(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a UTF-16 characters range to UTF-32
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToUtf32(In begin, In end, Out output);
+ };
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Specialization of the Utf template for UTF-32
+ ///
+ ////////////////////////////////////////////////////////////
+ template <>
+ class Utf<32>
+ {
+ public:
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Decode a single UTF-32 character
+ ///
+ /// Decoding a character means finding its unique 32-bits
+ /// code (called the codepoint) in the Unicode standard.
+ /// For UTF-32, the character value is the same as the codepoint.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Codepoint of the decoded UTF-32 character
+ /// \param replacement Replacement character to use in case the UTF-8 sequence is invalid
+ ///
+ /// \return Iterator pointing to one past the last read element of the input sequence
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In>
+ static In Decode(In begin, In end, Uint32& output, Uint32 replacement = 0);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Encode a single UTF-32 character
+ ///
+ /// Encoding a character means converting a unique 32-bits
+ /// code (called the codepoint) in the target encoding, UTF-32.
+ /// For UTF-32, the codepoint is the same as the character value.
+ ///
+ /// \param input Codepoint to encode as UTF-32
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to UTF-32 (use 0 to skip them)
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename Out>
+ static Out Encode(Uint32 input, Out output, Uint32 replacement = 0);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Advance to the next UTF-32 character
+ ///
+ /// This function is trivial for UTF-32, which can store
+ /// every character in a single storage element.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ ///
+ /// \return Iterator pointing to one past the last read element of the input sequence
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In>
+ static In Next(In begin, In end);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Count the number of characters of a UTF-32 sequence
+ ///
+ /// This function is trivial for UTF-32, which can store
+ /// every character in a single storage element.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ ///
+ /// \return Iterator pointing to one past the last read element of the input sequence
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In>
+ static std::size_t Count(In begin, In end);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an ANSI characters range to UTF-32
+ ///
+ /// The current global locale will be used by default, unless you
+ /// pass a custom one in the \a locale parameter.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param locale Locale to use for conversion
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out FromAnsi(In begin, In end, Out output, const std::locale& locale = std::locale());
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a wide characters range to UTF-32
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out FromWide(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-32
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out FromLatin1(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an UTF-32 characters range to ANSI characters
+ ///
+ /// The current global locale will be used by default, unless you
+ /// pass a custom one in the \a locale parameter.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them)
+ /// \param locale Locale to use for conversion
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToAnsi(In begin, In end, Out output, char replacement = 0, const std::locale& locale = std::locale());
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an UTF-32 characters range to wide characters
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToWide(In begin, In end, Out output, wchar_t replacement = 0);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an UTF-16 characters range to latin-1 (ISO-5589-1) characters
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToLatin1(In begin, In end, Out output, char replacement = 0);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a UTF-32 characters range to UTF-8
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToUtf8(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a UTF-32 characters range to UTF-16
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToUtf16(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a UTF-32 characters range to UTF-32
+ ///
+ /// This functions does nothing more than a direct copy;
+ /// it is defined only to provide the same interface as other
+ /// specializations of the sf::Utf<> template, and allow
+ /// generic code to be written on top of it.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToUtf32(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Decode a single ANSI character to UTF-32
+ ///
+ /// This function does not exist in other specializations
+ /// of sf::Utf<>, it is defined for convenience (it is used by
+ /// several other conversion functions).
+ ///
+ /// \param input Input ANSI character
+ /// \param locale Locale to use for conversion
+ ///
+ /// \return Converted character
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In>
+ static Uint32 DecodeAnsi(In input, const std::locale& locale = std::locale());
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Decode a single wide character to UTF-32
+ ///
+ /// This function does not exist in other specializations
+ /// of sf::Utf<>, it is defined for convenience (it is used by
+ /// several other conversion functions).
+ ///
+ /// \param input Input wide character
+ ///
+ /// \return Converted character
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In>
+ static Uint32 DecodeWide(In input);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Encode a single UTF-32 character to ANSI
+ ///
+ /// This function does not exist in other specializations
+ /// of sf::Utf<>, it is defined for convenience (it is used by
+ /// several other conversion functions).
+ ///
+ /// \param codepoint Iterator pointing to the beginning of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement if the input character is not convertible to ANSI (use 0 to skip it)
+ /// \param locale Locale to use for conversion
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename Out>
+ static Out EncodeAnsi(Uint32 codepoint, Out output, char replacement = 0, const std::locale& locale = std::locale());
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Encode a single UTF-32 character to wide
+ ///
+ /// This function does not exist in other specializations
+ /// of sf::Utf<>, it is defined for convenience (it is used by
+ /// several other conversion functions).
+ ///
+ /// \param codepoint Iterator pointing to the beginning of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement if the input character is not convertible to wide (use 0 to skip it)
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename Out>
+ static Out EncodeWide(Uint32 codepoint, Out output, wchar_t replacement = 0);
+ };
+
+#include "Utf.inl"
+
+ // Make typedefs to get rid of the template syntax
+ typedef Utf<8> Utf8;
+ typedef Utf<16> Utf16;
+ typedef Utf<32> Utf32;
+
+ } // namespace sf
+
+}
+
+
+#endif // SFML_UTF_HPP
diff --git a/Source/Asura.Engine/text/utf.inl b/Source/Asura.Engine/text/utf.inl
new file mode 100644
index 0000000..69a523b
--- /dev/null
+++ b/Source/Asura.Engine/text/utf.inl
@@ -0,0 +1,752 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2019 Laurent Gomila (laurent@sfml-dev.org)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented;
+// you must not claim that you wrote the original software.
+// If you use this software in a product, an acknowledgment
+// in the product documentation would be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such,
+// and must not be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////
+// References:
+//
+// https://www.unicode.org/
+// https://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.c
+// https://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.h
+// https://people.w3.org/rishida/scripts/uniview/conversion
+//
+////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////
+template <typename In>
+In Utf<8>::Decode(In begin, In end, Uint32& output, Uint32 replacement)
+{
+ // Some useful precomputed data
+ static const int trailing[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
+ };
+ static const Uint32 offsets[6] =
+ {
+ 0x00000000, 0x00003080, 0x000E2080, 0x03C82080, 0xFA082080, 0x82082080
+ };
+
+ // decode the character
+ int trailingBytes = trailing[static_cast<Uint8>(*begin)];
+ if (begin + trailingBytes < end)
+ {
+ output = 0;
+ switch (trailingBytes)
+ {
+ case 5: output += static_cast<Uint8>(*begin++); output <<= 6;
+ case 4: output += static_cast<Uint8>(*begin++); output <<= 6;
+ case 3: output += static_cast<Uint8>(*begin++); output <<= 6;
+ case 2: output += static_cast<Uint8>(*begin++); output <<= 6;
+ case 1: output += static_cast<Uint8>(*begin++); output <<= 6;
+ case 0: output += static_cast<Uint8>(*begin++);
+ }
+ output -= offsets[trailingBytes];
+ }
+ else
+ {
+ // Incomplete character
+ begin = end;
+ output = replacement;
+ }
+
+ return begin;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename Out>
+Out Utf<8>::Encode(Uint32 input, Out output, Uint8 replacement)
+{
+ // Some useful precomputed data
+ static const Uint8 firstBytes[7] =
+ {
+ 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC
+ };
+
+ // encode the character
+ if ((input > 0x0010FFFF) || ((input >= 0xD800) && (input <= 0xDBFF)))
+ {
+ // Invalid character
+ if (replacement)
+ *output++ = replacement;
+ }
+ else
+ {
+ // Valid character
+
+ // Get the number of bytes to write
+ std::size_t bytestoWrite = 1;
+ if (input < 0x80) bytestoWrite = 1;
+ else if (input < 0x800) bytestoWrite = 2;
+ else if (input < 0x10000) bytestoWrite = 3;
+ else if (input <= 0x0010FFFF) bytestoWrite = 4;
+
+ // Extract the bytes to write
+ Uint8 bytes[4];
+ switch (bytestoWrite)
+ {
+ case 4: bytes[3] = static_cast<Uint8>((input | 0x80) & 0xBF); input >>= 6;
+ case 3: bytes[2] = static_cast<Uint8>((input | 0x80) & 0xBF); input >>= 6;
+ case 2: bytes[1] = static_cast<Uint8>((input | 0x80) & 0xBF); input >>= 6;
+ case 1: bytes[0] = static_cast<Uint8> (input | firstBytes[bytestoWrite]);
+ }
+
+ // Add them to the output
+ output = std::copy(bytes, bytes + bytestoWrite, output);
+ }
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In>
+In Utf<8>::Next(In begin, In end)
+{
+ Uint32 codepoint;
+ return Decode(begin, end, codepoint);
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In>
+std::size_t Utf<8>::Count(In begin, In end)
+{
+ std::size_t length = 0;
+ while (begin < end)
+ {
+ begin = Next(begin, end);
+ ++length;
+ }
+
+ return length;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<8>::FromAnsi(In begin, In end, Out output, const std::locale& locale)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint = Utf<32>::DecodeAnsi(*begin++, locale);
+ output = Encode(codepoint, output);
+ }
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<8>::FromWide(In begin, In end, Out output)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint = Utf<32>::DecodeWide(*begin++);
+ output = Encode(codepoint, output);
+ }
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<8>::FromLatin1(In begin, In end, Out output)
+{
+ // Latin-1 is directly compatible with Unicode encodings,
+ // and can thus be treated as (a sub-range of) UTF-32
+ while (begin < end)
+ output = Encode(*begin++, output);
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<8>::ToAnsi(In begin, In end, Out output, char replacement, const std::locale& locale)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint;
+ begin = Decode(begin, end, codepoint);
+ output = Utf<32>::EncodeAnsi(codepoint, output, replacement, locale);
+ }
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<8>::ToWide(In begin, In end, Out output, wchar_t replacement)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint;
+ begin = Decode(begin, end, codepoint);
+ output = Utf<32>::EncodeWide(codepoint, output, replacement);
+ }
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<8>::ToLatin1(In begin, In end, Out output, char replacement)
+{
+ // Latin-1 is directly compatible with Unicode encodings,
+ // and can thus be treated as (a sub-range of) UTF-32
+ while (begin < end)
+ {
+ Uint32 codepoint;
+ begin = Decode(begin, end, codepoint);
+ *output++ = codepoint < 256 ? static_cast<char>(codepoint) : replacement;
+ }
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<8>::ToUtf8(In begin, In end, Out output)
+{
+ return std::copy(begin, end, output);
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<8>::ToUtf16(In begin, In end, Out output)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint;
+ begin = Decode(begin, end, codepoint);
+ output = Utf<16>::Encode(codepoint, output);
+ }
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<8>::ToUtf32(In begin, In end, Out output)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint;
+ begin = Decode(begin, end, codepoint);
+ *output++ = codepoint;
+ }
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In>
+In Utf<16>::Decode(In begin, In end, Uint32& output, Uint32 replacement)
+{
+ Uint16 first = *begin++;
+
+ // If it's a surrogate pair, first convert to a single UTF-32 character
+ if ((first >= 0xD800) && (first <= 0xDBFF))
+ {
+ if (begin < end)
+ {
+ Uint32 second = *begin++;
+ if ((second >= 0xDC00) && (second <= 0xDFFF))
+ {
+ // The second element is valid: convert the two elements to a UTF-32 character
+ output = ((first - 0xD800) << 10) + (second - 0xDC00) + 0x0010000;
+ }
+ else
+ {
+ // Invalid character
+ output = replacement;
+ }
+ }
+ else
+ {
+ // Invalid character
+ begin = end;
+ output = replacement;
+ }
+ }
+ else
+ {
+ // We can make a direct copy
+ output = first;
+ }
+
+ return begin;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename Out>
+Out Utf<16>::Encode(Uint32 input, Out output, Uint16 replacement)
+{
+ if (input <= 0xFFFF)
+ {
+ // The character can be copied directly, we just need to check if it's in the valid range
+ if ((input >= 0xD800) && (input <= 0xDFFF))
+ {
+ // Invalid character (this range is reserved)
+ if (replacement)
+ *output++ = replacement;
+ }
+ else
+ {
+ // Valid character directly convertible to a single UTF-16 character
+ *output++ = static_cast<Uint16>(input);
+ }
+ }
+ else if (input > 0x0010FFFF)
+ {
+ // Invalid character (greater than the maximum Unicode value)
+ if (replacement)
+ *output++ = replacement;
+ }
+ else
+ {
+ // The input character will be converted to two UTF-16 elements
+ input -= 0x0010000;
+ *output++ = static_cast<Uint16>((input >> 10) + 0xD800);
+ *output++ = static_cast<Uint16>((input & 0x3FFUL) + 0xDC00);
+ }
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In>
+In Utf<16>::Next(In begin, In end)
+{
+ Uint32 codepoint;
+ return Decode(begin, end, codepoint);
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In>
+std::size_t Utf<16>::Count(In begin, In end)
+{
+ std::size_t length = 0;
+ while (begin < end)
+ {
+ begin = Next(begin, end);
+ ++length;
+ }
+
+ return length;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<16>::FromAnsi(In begin, In end, Out output, const std::locale& locale)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint = Utf<32>::DecodeAnsi(*begin++, locale);
+ output = Encode(codepoint, output);
+ }
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<16>::FromWide(In begin, In end, Out output)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint = Utf<32>::DecodeWide(*begin++);
+ output = Encode(codepoint, output);
+ }
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<16>::FromLatin1(In begin, In end, Out output)
+{
+ // Latin-1 is directly compatible with Unicode encodings,
+ // and can thus be treated as (a sub-range of) UTF-32
+ return std::copy(begin, end, output);
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<16>::ToAnsi(In begin, In end, Out output, char replacement, const std::locale& locale)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint;
+ begin = Decode(begin, end, codepoint);
+ output = Utf<32>::EncodeAnsi(codepoint, output, replacement, locale);
+ }
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<16>::ToWide(In begin, In end, Out output, wchar_t replacement)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint;
+ begin = Decode(begin, end, codepoint);
+ output = Utf<32>::EncodeWide(codepoint, output, replacement);
+ }
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<16>::ToLatin1(In begin, In end, Out output, char replacement)
+{
+ // Latin-1 is directly compatible with Unicode encodings,
+ // and can thus be treated as (a sub-range of) UTF-32
+ while (begin < end)
+ {
+ *output++ = *begin < 256 ? static_cast<char>(*begin) : replacement;
+ begin++;
+ }
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<16>::ToUtf8(In begin, In end, Out output)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint;
+ begin = Decode(begin, end, codepoint);
+ output = Utf<8>::Encode(codepoint, output);
+ }
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<16>::ToUtf16(In begin, In end, Out output)
+{
+ return std::copy(begin, end, output);
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<16>::ToUtf32(In begin, In end, Out output)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint;
+ begin = Decode(begin, end, codepoint);
+ *output++ = codepoint;
+ }
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In>
+In Utf<32>::Decode(In begin, In /*end*/, Uint32& output, Uint32 /*replacement*/)
+{
+ output = *begin++;
+ return begin;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename Out>
+Out Utf<32>::Encode(Uint32 input, Out output, Uint32 /*replacement*/)
+{
+ *output++ = input;
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In>
+In Utf<32>::Next(In begin, In /*end*/)
+{
+ return ++begin;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In>
+std::size_t Utf<32>::Count(In begin, In end)
+{
+ return begin - end;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<32>::FromAnsi(In begin, In end, Out output, const std::locale& locale)
+{
+ while (begin < end)
+ *output++ = DecodeAnsi(*begin++, locale);
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<32>::FromWide(In begin, In end, Out output)
+{
+ while (begin < end)
+ *output++ = DecodeWide(*begin++);
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<32>::FromLatin1(In begin, In end, Out output)
+{
+ // Latin-1 is directly compatible with Unicode encodings,
+ // and can thus be treated as (a sub-range of) UTF-32
+ return std::copy(begin, end, output);
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<32>::ToAnsi(In begin, In end, Out output, char replacement, const std::locale& locale)
+{
+ while (begin < end)
+ output = EncodeAnsi(*begin++, output, replacement, locale);
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<32>::ToWide(In begin, In end, Out output, wchar_t replacement)
+{
+ while (begin < end)
+ output = EncodeWide(*begin++, output, replacement);
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<32>::ToLatin1(In begin, In end, Out output, char replacement)
+{
+ // Latin-1 is directly compatible with Unicode encodings,
+ // and can thus be treated as (a sub-range of) UTF-32
+ while (begin < end)
+ {
+ *output++ = *begin < 256 ? static_cast<char>(*begin) : replacement;
+ begin++;
+ }
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<32>::ToUtf8(In begin, In end, Out output)
+{
+ while (begin < end)
+ output = Utf<8>::Encode(*begin++, output);
+
+ return output;
+}
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<32>::ToUtf16(In begin, In end, Out output)
+{
+ while (begin < end)
+ output = Utf<16>::Encode(*begin++, output);
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<32>::ToUtf32(In begin, In end, Out output)
+{
+ return std::copy(begin, end, output);
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In>
+Uint32 Utf<32>::DecodeAnsi(In input, const std::locale& locale)
+{
+ // On Windows, GCC's standard library (glibc++) has almost
+ // no support for Unicode stuff. As a consequence, in this
+ // context we can only use the default locale and ignore
+ // the one passed as parameter.
+
+ #if defined(SFML_SYSTEM_WINDOWS) && /* if Windows ... */ \
+ (defined(__GLIBCPP__) || defined (__GLIBCXX__)) && /* ... and standard library is glibc++ ... */ \
+ !(defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) /* ... and STLPort is not used on top of it */
+
+ (void)locale; // to avoid warnings
+
+ wchar_t character = 0;
+ mbtowc(&character, &input, 1);
+ return static_cast<Uint32>(character);
+
+ #else
+
+ // Get the facet of the locale which deals with character conversion
+ const std::ctype<wchar_t>& facet = std::use_facet< std::ctype<wchar_t> >(locale);
+
+ // Use the facet to convert each character of the input string
+ return static_cast<Uint32>(facet.widen(input));
+
+ #endif
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In>
+Uint32 Utf<32>::DecodeWide(In input)
+{
+ // The encoding of wide characters is not well defined and is left to the system;
+ // however we can safely assume that it is UCS-2 on Windows and
+ // UCS-4 on Unix systems.
+ // In both cases, a simple copy is enough (UCS-2 is a subset of UCS-4,
+ // and UCS-4 *is* UTF-32).
+
+ return input;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename Out>
+Out Utf<32>::EncodeAnsi(Uint32 codepoint, Out output, char replacement, const std::locale& locale)
+{
+ // On Windows, gcc's standard library (glibc++) has almost
+ // no support for Unicode stuff. As a consequence, in this
+ // context we can only use the default locale and ignore
+ // the one passed as parameter.
+
+ #if defined(SFML_SYSTEM_WINDOWS) && /* if Windows ... */ \
+ (defined(__GLIBCPP__) || defined (__GLIBCXX__)) && /* ... and standard library is glibc++ ... */ \
+ !(defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) /* ... and STLPort is not used on top of it */
+
+ (void)locale; // to avoid warnings
+
+ char character = 0;
+ if (wctomb(&character, static_cast<wchar_t>(codepoint)) >= 0)
+ *output++ = character;
+ else if (replacement)
+ *output++ = replacement;
+
+ return output;
+
+ #else
+
+ // Get the facet of the locale which deals with character conversion
+ const std::ctype<wchar_t>& facet = std::use_facet< std::ctype<wchar_t> >(locale);
+
+ // Use the facet to convert each character of the input string
+ *output++ = facet.narrow(static_cast<wchar_t>(codepoint), replacement);
+
+ return output;
+
+ #endif
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename Out>
+Out Utf<32>::EncodeWide(Uint32 codepoint, Out output, wchar_t replacement)
+{
+ // The encoding of wide characters is not well defined and is left to the system;
+ // however we can safely assume that it is UCS-2 on Windows and
+ // UCS-4 on Unix systems.
+ // For UCS-2 we need to check if the source characters fits in (UCS-2 is a subset of UCS-4).
+ // For UCS-4 we can do a direct copy (UCS-4 *is* UTF-32).
+
+ switch (sizeof(wchar_t))
+ {
+ case 4:
+ {
+ *output++ = static_cast<wchar_t>(codepoint);
+ break;
+ }
+
+ default:
+ {
+ if ((codepoint <= 0xFFFF) && ((codepoint < 0xD800) || (codepoint > 0xDFFF)))
+ {
+ *output++ = static_cast<wchar_t>(codepoint);
+ }
+ else if (replacement)
+ {
+ *output++ = replacement;
+ }
+ break;
+ }
+ }
+
+ return output;
+}