Index: ps/trunk/source/ps/CStr.cpp
===================================================================
--- ps/trunk/source/ps/CStr.cpp (revision 25899)
+++ ps/trunk/source/ps/CStr.cpp (revision 25900)
@@ -1,536 +1,572 @@
/* Copyright (C) 2021 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see .
*/
-/**
- * Description : Controls compilation of CStr class and
- * : includes some function implementations.
- **/
#include "precompiled.h"
#ifndef CStr_CPP_FIRST
#define CStr_CPP_FIRST
#include "lib/fnv_hash.h"
#include "lib/utf8.h"
#include "lib/byte_order.h"
#include "network/Serialization.h"
#include
+#include
#include
#include
+#include
+
+namespace
+{
+ // Use a knowingly false expression, as we can't use
+ // static_assert(false, ...) directly, because it's an ill-formed program
+ // with a value (false) which doesn't depend on any input parameter.
+ // We don't use constexpr bool AlwaysFalse = false, because some compilers
+ // complain about an unused constant.
+ template
+ struct AlwaysFalse : std::false_type
+ {};
+
+ template
+ using tstringstream = std::basic_stringstream;
+
+ template
+ bool istspace(const Char chr)
+ {
+ if constexpr (std::is_same_v)
+ return static_cast(std::isspace(chr));
+ else
+ return static_cast(std::iswspace(chr));
+ }
+
+ template
+ Char totlower(const Char chr)
+ {
+ if constexpr (std::is_same_v)
+ return std::tolower(chr);
+ else
+ return std::towlower(chr);
+ }
+
+ template
+ Char totupper(const Char chr)
+ {
+ if constexpr (std::is_same_v)
+ return std::toupper(chr);
+ else
+ return std::towupper(chr);
+ }
+
+ template
+ u8* SerializeImpl(const StrBase& str, u8* buffer)
+ {
+ using Char = typename StrBase::value_type;
+ ENSURE(buffer);
+ if constexpr (std::is_same_v)
+ {
+ // CStr8 is always serialized to / from ASCII(or whatever 8 - bit codepage stored
+ // in the CStr).
+ size_t len = str.length();
+ Serialize_int_4(buffer, (u32)len);
+ size_t i = 0;
+ for (i = 0; i < len; i++)
+ buffer[i] = str[i];
+ return buffer + len;
+ }
+ else if constexpr (std::is_same_v)
+ {
+ // CStrW is always serialized to / from UTF - 16.
+ size_t len = str.length();
+ size_t i = 0;
+ for (i = 0; i < len; i++)
+ {
+ const u16 bigEndian = to_be16(str[i]);
+ *(u16 *)(buffer + i * 2) = bigEndian;
+ }
+ *(u16 *)(buffer + i * 2) = 0;
+ return buffer + len * 2 + 2;
+ }
+ else
+ static_assert(AlwaysFalse::value, "Not implemented.");
+ }
+
+ template
+ const u8* DeserializeImpl(const u8* buffer, const u8* bufferend, StrBase& str)
+ {
+ using Char = typename StrBase::value_type;
+ ENSURE(buffer);
+ ENSURE(bufferend);
+ if constexpr (std::is_same_v)
+ {
+ u32 len;
+ Deserialize_int_4(buffer, len);
+ if (buffer + len > bufferend)
+ return NULL;
+ str = StrBase(buffer, buffer + len);
+ return buffer + len;
+ }
+ else if constexpr (std::is_same_v)
+ {
+ const u16 *strend = (const u16 *)buffer;
+ while ((const u8 *)strend < bufferend && *strend)
+ strend++;
+ if ((const u8 *)strend >= bufferend)
+ return nullptr;
+
+ str.resize(strend - (const u16 *)buffer);
+ const u16 *ptr = (const u16 *)buffer;
+
+ typename StrBase::iterator it = str.begin();
+ while (ptr < strend)
+ {
+ const u16 native = to_be16(*(ptr++)); // we want from_be16, but that's the same
+ *(it++) = (Char)native;
+ }
+
+ return (const u8 *)(strend + 1);
+ }
+ else
+ static_assert(AlwaysFalse::value, "Not implemented.");
+ }
+
+ template
+ size_t GetSerializedLengthImpl(const StrBase& str)
+ {
+ using Char = typename StrBase::value_type;
+ if constexpr (std::is_same_v)
+ return str.length() + 4;
+ else if constexpr (std::is_same_v)
+ return str.length() * 2 + 2;
+ else
+ static_assert(AlwaysFalse::value, "Not implemented.");
+ }
+
+} // anonymous namespace
#define UNIDOUBLER_HEADER "CStr.cpp"
#include "UniDoubler.h"
// Only include these function definitions in the first instance of CStr.cpp:
/**
* Convert CStr to UTF-8
*
* @return CStr8 converted string
**/
CStr8 CStrW::ToUTF8() const
{
Status err;
return utf8_from_wstring(*this, &err);
}
/**
* Convert UTF-8 to CStr
*
* @return CStrW converted string
**/
CStrW CStr8::FromUTF8() const
{
Status err;
return wstring_from_utf8(*this, &err);
}
#else
// The following code is compiled twice, as CStrW then as CStr8:
#include "CStr.h"
-#include
-
-#ifdef _UNICODE
- #define _istspace iswspace
- #define _totlower towlower
- #define _totupper towupper
-#else
- #define _istspace isspace
- #define _totlower tolower
- #define _totupper toupper
-#endif
-
-namespace
-{
-
-template
-using tstringstream = std::basic_stringstream;
-
-} // anonymous namespace
-
CStr CStr::Repeat(const CStr& str, size_t reps)
{
CStr ret;
ret.reserve(str.length() * reps);
while (reps--) ret += str;
return ret;
}
// Construction from numbers:
CStr CStr::FromInt(int n)
{
tstringstream ss;
ss << n;
return ss.str();
}
CStr CStr::FromUInt(unsigned int n)
{
tstringstream ss;
ss << n;
return ss.str();
}
CStr CStr::FromInt64(i64 n)
{
tstringstream ss;
ss << n;
return ss.str();
}
CStr CStr::FromDouble(double n)
{
tstringstream ss;
ss << n;
return ss.str();
}
// Conversion to numbers:
int CStr::ToInt() const
{
int ret = 0;
tstringstream str(*this);
str >> ret;
return ret;
}
unsigned int CStr::ToUInt() const
{
unsigned int ret = 0;
tstringstream str(*this);
str >> ret;
return ret;
}
long CStr::ToLong() const
{
long ret = 0;
tstringstream str(*this);
str >> ret;
return ret;
}
unsigned long CStr::ToULong() const
{
unsigned long ret = 0;
tstringstream str(*this);
str >> ret;
return ret;
}
/**
* libc++ and libstd++ differ on how they handle string-to-number parsing for floating-points numbers.
* See https://trac.wildfiregames.com/ticket/2780#comment:4 for details.
* To prevent this, only consider [0-9.-+], replace the others in-place with a neutral character.
*/
CStr ParseableAsNumber(CStr cleaned_copy)
{
- for (tchar& c : cleaned_copy)
+ for (CStr::Char& c : cleaned_copy)
if (!std::isdigit(c) && c != '.' && c != '-' && c != '+')
c = ' ';
return cleaned_copy;
}
float CStr::ToFloat() const
{
float ret = 0;
tstringstream str(ParseableAsNumber(*this));
str >> ret;
return ret;
}
double CStr::ToDouble() const
{
double ret = 0;
tstringstream str(ParseableAsNumber(*this));
str >> ret;
return ret;
}
// Search the string for another string
long CStr::Find(const CStr& str) const
{
size_t pos = find(str, 0);
if (pos != npos)
return static_cast(pos);
return -1;
}
// Search the string for another string
-long CStr::Find(const tchar chr) const
+long CStr::Find(const Char chr) const
{
size_t pos = find(chr, 0);
if (pos != npos)
return static_cast(pos);
return -1;
}
// Search the string for another string
-long CStr::Find(const int start, const tchar chr) const
+long CStr::Find(const int start, const Char chr) const
{
size_t pos = find(chr, start);
if (pos != npos)
return static_cast(pos);
return -1;
}
-long CStr::FindInsensitive(const int start, const tchar chr) const { return LowerCase().Find(start, _totlower(chr)); }
-long CStr::FindInsensitive(const tchar chr) const { return LowerCase().Find(_totlower(chr)); }
+long CStr::FindInsensitive(const int start, const Char chr) const { return LowerCase().Find(start, totlower(chr)); }
+long CStr::FindInsensitive(const Char chr) const { return LowerCase().Find(totlower(chr)); }
long CStr::FindInsensitive(const CStr& str) const { return LowerCase().Find(str.LowerCase()); }
long CStr::ReverseFind(const CStr& str) const
{
size_t pos = rfind(str, length() );
if (pos != npos)
return static_cast(pos);
return -1;
}
// Lowercase and uppercase
CStr CStr::LowerCase() const
{
StrBase newStr = *this;
for (size_t i = 0; i < length(); i++)
- newStr[i] = (tchar)_totlower((*this)[i]);
+ newStr[i] = (Char)totlower((*this)[i]);
return newStr;
}
CStr CStr::UpperCase() const
{
StrBase newStr = *this;
for (size_t i = 0; i < length(); i++)
- newStr[i] = (tchar)_totupper((*this)[i]);
+ newStr[i] = (Char)totupper((*this)[i]);
return newStr;
}
// Retrieve the substring of the first n characters
CStr CStr::Left(size_t len) const
{
ENSURE(len <= length());
return substr(0, len);
}
// Retrieve the substring of the last n characters
CStr CStr::Right(size_t len) const
{
ENSURE(len <= length());
return substr(length()-len, len);
}
// Retrieve the substring following the last occurrence of Str
// (or the whole string if it doesn't contain Str)
CStr CStr::AfterLast(const CStr& str, size_t startPos) const
{
size_t pos = rfind(str, startPos);
if (pos == npos)
return *this;
else
return substr(pos + str.length());
}
// Retrieve the substring preceding the last occurrence of Str
// (or the whole string if it doesn't contain Str)
CStr CStr::BeforeLast(const CStr& str, size_t startPos) const
{
size_t pos = rfind(str, startPos);
if (pos == npos)
return *this;
else
return substr(0, pos);
}
// Retrieve the substring following the first occurrence of Str
// (or the whole string if it doesn't contain Str)
CStr CStr::AfterFirst(const CStr& str, size_t startPos) const
{
size_t pos = find(str, startPos);
if (pos == npos)
return *this;
else
return substr(pos + str.length());
}
// Retrieve the substring preceding the first occurrence of Str
// (or the whole string if it doesn't contain Str)
CStr CStr::BeforeFirst(const CStr& str, size_t startPos) const
{
size_t pos = find(str, startPos);
if (pos == npos)
return *this;
else
return substr(0, pos);
}
// Remove all occurrences of some character or substring
void CStr::Remove(const CStr& str)
{
size_t foundAt = 0;
while (foundAt != npos)
{
foundAt = find(str, 0);
if (foundAt != npos)
erase(foundAt, str.length());
}
}
// Replace all occurrences of some substring by another
void CStr::Replace(const CStr& toReplace, const CStr& replaceWith)
{
size_t pos = 0;
while (pos != npos)
{
pos = find(toReplace, pos);
if (pos != npos)
{
erase(pos, toReplace.length());
insert(pos, replaceWith);
pos += replaceWith.length();
}
}
}
std::string CStr::EscapeToPrintableASCII() const
{
std::string newStr;
for (size_t i = 0; i < length(); i++)
{
- tchar ch = (*this)[i];
+ Char ch = (*this)[i];
if (ch == '"') newStr += "\\\"";
else if (ch == '\\') newStr += "\\\\";
else if (ch == '\b') newStr += "\\b";
else if (ch == '\f') newStr += "\\f";
else if (ch == '\n') newStr += "\\n";
else if (ch == '\r') newStr += "\\r";
else if (ch == '\t') newStr += "\\t";
else if (ch >= 32 && ch <= 126)
newStr += ch;
else
{
std::stringstream ss;
ss << "\\u" << std::hex << std::setfill('0') << std::setw(4) << (int)(unsigned char)ch;
newStr += ss.str();
}
}
return newStr;
}
// Returns a trimmed string, removes whitespace from the left/right/both
CStr CStr::Trim(PS_TRIM_MODE mode) const
{
size_t left = 0, right = 0;
switch (mode)
{
case PS_TRIM_LEFT:
{
for (left = 0; left < length(); left++)
- if (_istspace((*this)[left]) == false)
+ if (istspace((*this)[left]) == false)
break; // end found, trim 0 to Left-1 inclusive
} break;
case PS_TRIM_RIGHT:
{
right = length();
while (right--)
- if (_istspace((*this)[right]) == false)
+ if (istspace((*this)[right]) == false)
break; // end found, trim len-1 to Right+1 inclusive
} break;
case PS_TRIM_BOTH:
{
for (left = 0; left < length(); left++)
- if (_istspace((*this)[left]) == false)
+ if (istspace((*this)[left]) == false)
break; // end found, trim 0 to Left-1 inclusive
right = length();
while (right--)
- if (_istspace((*this)[right]) == false)
+ if (istspace((*this)[right]) == false)
break; // end found, trim len-1 to Right+1 inclusive
} break;
default:
debug_warn(L"CStr::Trim: invalid Mode");
}
return substr(left, right - left + 1);
}
CStr CStr::Pad(PS_TRIM_MODE mode, size_t len) const
{
size_t left = 0, right = 0;
if (len <= length())
return *this;
// From here: Length-length() >= 1
switch (mode)
{
case PS_TRIM_LEFT:
left = len - length();
break;
case PS_TRIM_RIGHT:
right = len - length();
break;
case PS_TRIM_BOTH:
left = (len - length() + 1) / 2;
right = (len - length() - 1) / 2; // cannot be negative
break;
default:
debug_warn(L"CStr::Trim: invalid Mode");
}
- return StrBase(left, _T(' ')) + *this + StrBase(right, _T(' '));
+ return StrBase(left, ' ') + *this + StrBase(right, ' ');
}
size_t CStr::GetHashCode() const
{
return (size_t)fnv_hash(data(), length()*sizeof(value_type));
// janwas 2005-03-18: now use 32-bit version; 64 is slower and
// the result was truncated down to 32 anyway.
}
-#ifdef _UNICODE
-/*
- CStrW is always serialized to/from UTF-16
-*/
-
-u8* CStrW::Serialize(u8* buffer) const
+u8* CStr::Serialize(u8* buffer) const
{
- size_t len = length();
- size_t i = 0;
- for (i = 0; i < len; i++)
- {
- const u16 bigEndian = to_be16((*this)[i]);
- *(u16 *)(buffer + i*2) = bigEndian;
- }
- *(u16 *)(buffer + i*2) = 0;
- return buffer + len*2 + 2;
+ return SerializeImpl(*this, buffer);
}
-const u8* CStrW::Deserialize(const u8* buffer, const u8* bufferend)
+const u8* CStr::Deserialize(const u8* buffer, const u8* bufferend)
{
- ENSURE(buffer);
- ENSURE(bufferend);
- const u16 *strend = (const u16 *)buffer;
- while ((const u8 *)strend < bufferend && *strend) strend++;
- if ((const u8 *)strend >= bufferend) return NULL;
-
- resize(strend - (const u16 *)buffer);
- const u16 *ptr = (const u16 *)buffer;
-
- std::wstring::iterator str = begin();
- while (ptr < strend)
- {
- const u16 native = to_be16(*(ptr++)); // we want from_be16, but that's the same
- *(str++) = (tchar)native;
- }
-
- return (const u8 *)(strend+1);
+ return DeserializeImpl(buffer, bufferend, *this);
}
size_t CStr::GetSerializedLength() const
{
- return size_t(length()*2 + 2);
+ return GetSerializedLengthImpl(*this);
}
-#else
-/*
- CStr8 is always serialized to/from ASCII (or whatever 8-bit codepage stored
- in the CStr)
-*/
-
-u8* CStr8::Serialize(u8* buffer) const
-{
- size_t len = length();
- Serialize_int_4(buffer, (u32)len);
- size_t i = 0;
- for (i = 0; i < len; i++)
- buffer[i] = (*this)[i];
- return buffer + len;
-}
-
-const u8* CStr8::Deserialize(const u8* buffer, const u8* bufferend)
-{
- ENSURE(buffer);
- ENSURE(bufferend);
- u32 len;
- Deserialize_int_4(buffer, len);
- if (buffer + len > bufferend)
- return NULL;
- *this = std::string(buffer, buffer + len);
- return buffer + len;
-}
-
-size_t CStr::GetSerializedLength() const
-{
- return length() + 4;
-}
-
-#endif // _UNICODE
-
-// Clean up, to keep the second pass through unidoubler happy
-#undef _istspace
-#undef _totlower
-#undef _totupper
-
#endif // CStr_CPP_FIRST
Index: ps/trunk/source/ps/CStr.h
===================================================================
--- ps/trunk/source/ps/CStr.h (revision 25899)
+++ ps/trunk/source/ps/CStr.h (revision 25900)
@@ -1,353 +1,354 @@
/* Copyright (C) 2021 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see .
*/
/**
* Description : Contains CStr class which is a versatile class for making string use easy.
* : The class implements a series of string manipulation/formatting functions.
**/
#ifndef INCLUDED_CSTR
#define INCLUDED_CSTR
/**
* Whitespace trim identifier for Trim and Pad functions
**/
enum PS_TRIM_MODE
{
PS_TRIM_LEFT, /// Trim all white space from the beginning of the string
PS_TRIM_RIGHT, /// Trim all white space from the end of the string
PS_TRIM_BOTH /// Trim all white space from the beginning and end of the string
};
#ifndef IN_UNIDOUBLER
#define UNIDOUBLER_HEADER "CStr.h"
#include "UniDoubler.h"
#endif
#endif
// Include this section when in unidoubler mode, and when this unicode/ascii
// version has not already been included.
#if defined(IN_UNIDOUBLER) && ( (defined(_UNICODE) && !defined(CSTR_H_U)) || (!defined(_UNICODE) && !defined(CSTR_H_A)) )
#ifdef _UNICODE
#define CSTR_H_U
#else
#define CSTR_H_A
#endif
#include
#include "ps/utf16string.h"
class CStr8;
class CStrW;
/**
* The base class of all strings
**/
class CStr : public std::tstring
{
public:
using StrBase = std::tstring;
+ using Char = typename std::tstring::value_type;
CStr() {}
- CStr(const tchar* str) : StrBase(str) {}
- CStr(const tchar* str, size_t len) : StrBase(str, len) {}
+ CStr(const Char* str) : StrBase(str) {}
+ CStr(const Char* str, size_t len) : StrBase(str, len) {}
CStr(const StrBase& str) : StrBase(str) {}
template
CStr (InputIterator first, InputIterator last) : StrBase(first, last) {}
/**
* Repeat: Named constructor, to avoid overload overload.
*
* @param const CStr & str reference to another CStr object to be repeated for initialization
* @param size_t Reps number of times to repeat the initialization
* @return CStr new CStr object
**/
static CStr Repeat(const CStr& str, size_t reps);
/**
* Construction from utf16strings.
*
* @param utf16string String utf16string to be used for initialization.
**/
explicit CStr(const utf16string& str) : StrBase(str.begin(), str.end()) {}
// Conversion to/from UTF-8, encoded in a CStr8.
// Invalid bytes/characters (e.g. broken UTF-8, and Unicode characters
// above U+FFFF) are silently replaced with U+FFFD.
#ifdef _UNICODE
CStr8 ToUTF8() const;
#else
CStrW FromUTF8() const;
#endif
// Conversions:
static CStr FromInt(int n);
static CStr FromUInt(unsigned int n);
static CStr FromInt64(i64 n);
static CStr FromDouble(double n);
/**
* Return CStr as Integer.
* Conversion is from the beginning of CStr.
*
* @return int CStr represented as an integer.
**/
int ToInt() const;
/**
* Return CStr as Unsigned Integer.
* Conversion is from the beginning of CStr.
*
* @return unsigned int CStr represented as an unsigned integer.
**/
unsigned int ToUInt() const;
/**
* Return CStr as Long.
* Conversion is from the beginning of CStr.
*
* @return long CStr represented as a long.
**/
long ToLong() const;
/**
* Return CStr as Unsigned Long.
* Conversion is from the beginning of CStr.
*
* @return unsigned long CStr represented as an unsigned long.
**/
unsigned long ToULong() const;
/**
* Return CStr as Float.
* Conversion is from the beginning of CStr.
*
* @return float CStr represented as a float.
**/
float ToFloat() const;
/**
* Return CStr as Double.
* Conversion is from the beginning of CStr.
*
* @return double CStr represented as a double.
**/
double ToDouble() const;
/**
* Search the CStr for another string.
* The search is case-sensitive.
*
* @param const CStr & str reference to the search string
* @return long offset into the CStr of the first occurrence of the search string
* -1 if the search string is not found
**/
long Find(const CStr& str) const;
/**
* Search the CStr for another string.
* The search is case-sensitive.
*
* @param const {t|w}char_t & chr reference to the search string
* @return long offset into the CStr of the first occurrence of the search string
* -1 if the search string is not found
**/
- long Find(const tchar chr) const;
+ long Find(const Char chr) const;
/**
* Search the CStr for another string with starting offset.
* The search is case-sensitive.
*
* @param const int & start character offset into CStr to begin search
* @param const {t|w}char_t & chr reference to the search string
* @return long offset into the CStr of the first occurrence of the search string
* -1 if the search string is not found
**/
- long Find(const int start, const tchar chr) const;
+ long Find(const int start, const Char chr) const;
/**
* Search the CStr for another string.
* The search is case-insensitive.
*
* @param const CStr & str reference to the search string
* @return long offset into the CStr of the first occurrence of the search string
* -1 if the search string is not found
**/
long FindInsensitive(const CStr& str) const;
/**
* Search the CStr for another string.
* The search is case-insensitive.
*
* @param const {t|w}char_t & chr reference to the search string
* @return long offset into the CStr of the first occurrence of the search string
* -1 if the search string is not found
**/
- long FindInsensitive(const tchar chr) const;
+ long FindInsensitive(const Char chr) const;
/**
* Search the CStr for another string with starting offset.
* The search is case-insensitive.
*
* @param const int & start character offset into CStr to begin search
* @param const {t|w}char_t & chr reference to the search string
* @return long offset into the CStr of the first occurrence of the search string
* -1 if the search string is not found
**/
- long FindInsensitive(const int start, const tchar chr) const;
+ long FindInsensitive(const int start, const Char chr) const;
/**
* Search the CStr for another string.
* The search is case-sensitive.
*
* @param const CStr & str reference to the search string
* @return long offset into the CStr of the last occurrence of the search string
* -1 if the search string is not found
**/
long ReverseFind(const CStr& str) const;
/**
* Make a copy of the CStr in lower-case.
*
* @return CStr converted copy of CStr.
**/
CStr LowerCase() const;
/**
* Make a copy of the CStr in upper-case.
*
* @return CStr converted copy of CStr.
**/
CStr UpperCase() const;
/**
* Retrieve first n characters of the CStr.
*
* @param size_t len the number of characters to retrieve.
* @return CStr retrieved substring.
**/
CStr Left(size_t len) const;
/**
* Retrieve last n characters of the CStr.
*
* @param size_t len the number of characters to retrieve.
* @return CStr retrieved substring.
**/
CStr Right(size_t len) const;
/**
* Retrieve substring of the CStr after last occurrence of a string.
* Return substring of the CStr after the last occurrence of the search string.
*
* @param const CStr & str reference to search string
* @param size_t startPos character position to start searching from
* @return CStr substring remaining after match
* the CStr if no match is found
**/
CStr AfterLast(const CStr& str, size_t startPos = npos) const;
/**
* Retrieve substring of the CStr preceding last occurrence of a string.
* Return substring of the CStr preceding the last occurrence of the search string.
*
* @param const CStr & str reference to search string
* @param size_t startPos character position to start searching from
* @return CStr substring preceding before match
* the CStr if no match is found
**/
CStr BeforeLast(const CStr& str, size_t startPos = npos) const;
/**
* Retrieve substring of the CStr after first occurrence of a string.
* Return substring of the CStr after the first occurrence of the search string.
*
* @param const CStr & str reference to search string
* @param size_t startPos character position to start searching from
* @return CStr substring remaining after match
* the CStr if no match is found
**/
CStr AfterFirst(const CStr& str, size_t startPos = 0) const;
/**
* Retrieve substring of the CStr preceding first occurrence of a string.
* Return substring of the CStr preceding the first occurrence of the search string.
*
* @param const CStr & str reference to search string
* @param size_t startPos character position to start searching from
* @return CStr substring preceding before match
* the CStr if no match is found
**/
CStr BeforeFirst(const CStr& str, size_t startPos = 0) const;
/**
* Remove all occurrences of a string from the CStr.
*
* @param const CStr & str reference to search string to remove.
**/
void Remove(const CStr& str);
/**
* Replace all occurrences of one string by another string in the CStr.
*
* @param const CStr & strToReplace reference to search string.
* @param const CStr & replaceWith reference to replace string.
**/
void Replace(const CStr& toReplace, const CStr& replaceWith);
/**
* Convert strings to printable ASCII characters with JSON-style escapes.
*/
std::string EscapeToPrintableASCII() const;
/**
* Return a trimmed copy of the CStr.
*
* @param PS_TRIM_MODE Mode value from trim mode enumeration.
* @return CStr copy of trimmed CStr.
**/
CStr Trim(PS_TRIM_MODE mode) const;
/**
* Return a space padded copy of the CStr.
*
* @param PS_TRIM_MODE Mode value from trim mode enumeration.
* @param size_t Length number of pad spaces to add
* @return CStr copy of padded CStr.
**/
CStr Pad(PS_TRIM_MODE mode, size_t len) const;
// Conversion to utf16string
utf16string utf16() const { return utf16string(begin(), end()); }
// Calculates a hash of the string's contents
size_t GetHashCode() const;
// Serialization functions
// (These are not virtual or inherited from ISerializable, to avoid
// adding a vtable and making the strings larger than std::string)
size_t GetSerializedLength() const;
u8* Serialize(u8* buffer) const;
const u8* Deserialize(const u8* buffer, const u8* bufferend);
};
namespace std
{
template <>
struct hash
{
std::size_t operator()(const CStr& str) const
{
return str.GetHashCode();
}
};
}
#endif
Index: ps/trunk/source/ps/UniDoubler.h
===================================================================
--- ps/trunk/source/ps/UniDoubler.h (revision 25899)
+++ ps/trunk/source/ps/UniDoubler.h (revision 25900)
@@ -1,70 +1,60 @@
-/* Copyright (C) 2017 Wildfire Games.
+/* Copyright (C) 2021 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see .
*/
// Make sure we have the argument (UNIDOUBLER_HEADER), and that we're not
// called from within another unidoubler execution (now that's just asking for
// trouble)
#if defined(UNIDOUBLER_HEADER) && !defined(IN_UNIDOUBLER)
#define IN_UNIDOUBLER
// When compiling CStr.cpp with PCH, the unidoubler stuff gets rather
// confusing because of all the nested inclusions, but this makes it work:
#undef CStr
// First, set up the environment for the Unicode version
#ifndef _UNICODE
#define _UNICODE
#endif
#define CStr CStrW
#define tstring wstring
-#define tchar wchar_t
-#define _T(t) L ## t
// Include the unidoubled file
#include UNIDOUBLER_HEADER
// Clean up all the macros
#undef _UNICODE
#undef CStr
#undef tstring
-#undef tchar
-#undef _T
-
// Now include the 8-bit version under the name CStr8
#define CStr CStr8
#define tstring string
-#define tchar char
-#define _T(t) t
#include UNIDOUBLER_HEADER
// Clean up the macros again, to minimise namespace pollution
#undef CStr
#undef tstring
-#undef tchar
-#undef _T
-
// To please the file that originally include CStr.h, make CStr an alias for CStr8:
#define CStr CStr8
#undef IN_UNIDOUBLER
#undef UNIDOUBLER_HEADER
#endif