513 lines
18 KiB
C++
513 lines
18 KiB
C++
#pragma once
|
|
|
|
#include "dtcore/inc/dtdefinitions.h"
|
|
#include "dtcore/inc/dtvector.h"
|
|
#include "dtcore/inc/dtmap.h"
|
|
#include "dtcore/inc/dtset.h"
|
|
#include "dtcore/inc/dtstrongtype.h"
|
|
#include "dtcore/inc/dtchrono.h"
|
|
|
|
#pragma warning(push)
|
|
#include <stdarg.h>
|
|
#pragma warning(pop)
|
|
|
|
namespace dt
|
|
{
|
|
class WString;
|
|
|
|
enum class EndOfLineStandards
|
|
{
|
|
Dos,
|
|
Unix
|
|
};
|
|
|
|
class String
|
|
{
|
|
public:
|
|
DT_CORE_DLL_ENTRY String();
|
|
DT_CORE_DLL_ENTRY String(char ch);
|
|
DT_CORE_DLL_ENTRY String(const String& str);
|
|
DT_CORE_DLL_ENTRY String(String&& str);
|
|
DT_CORE_DLL_ENTRY String(const char* str);
|
|
DT_CORE_DLL_ENTRY String(const char* str, SizeT n);
|
|
DT_CORE_DLL_ENTRY String(const WString& str);
|
|
DT_CORE_DLL_ENTRY ~String();
|
|
|
|
// Move assignment operator.
|
|
DT_CORE_DLL_ENTRY String& operator=(String&& other);
|
|
DT_CORE_DLL_ENTRY String& operator=(const String& str);
|
|
DT_CORE_DLL_ENTRY String& operator+=(const String& str);
|
|
DT_CORE_DLL_ENTRY String& operator+=(const WString& str);
|
|
DT_CORE_DLL_ENTRY String& operator+=(const char* str);
|
|
DT_CORE_DLL_ENTRY String& operator+=(const Wchar* str);
|
|
DT_CORE_DLL_ENTRY String& operator+=(char c);
|
|
DT_CORE_DLL_ENTRY String operator+(const String& str) const;
|
|
DT_CORE_DLL_ENTRY const char& operator[](SizeT idx) const;
|
|
DT_CORE_DLL_ENTRY char& operator[](SizeT idx);
|
|
|
|
DT_CORE_DLL_ENTRY bool operator<(const String& str) const { return Compare(str) < 0; }
|
|
DT_CORE_DLL_ENTRY bool operator==(const String& str) const;
|
|
DT_CORE_DLL_ENTRY bool operator!=(const String& str) const;
|
|
|
|
DT_CORE_DLL_ENTRY int Compare(const String& str, bool caseSensitive = true) const;
|
|
|
|
DT_CORE_DLL_ENTRY SizeT Find(const String& str, SizeT start=0, bool caseSensitive = true) const;
|
|
|
|
DT_CORE_DLL_ENTRY bool Contains(const String& str, SizeT start=0) const;
|
|
|
|
DT_CORE_DLL_ENTRY bool Matches(const String& expr, bool caseSensitive) const;
|
|
|
|
DT_CORE_DLL_ENTRY void Split(const String& separator, Vector<String>& out) const;
|
|
|
|
DT_CORE_DLL_ENTRY SizeT ReverseFind(const String& str, SizeT start = 0, bool caseSensitive = true) const;
|
|
|
|
DT_CORE_DLL_ENTRY bool StartsWith(const String& str, bool caseSensitive = true) const;
|
|
|
|
DT_CORE_DLL_ENTRY bool EndsWith(const String& str, bool caseSensitive = true) const;
|
|
|
|
DT_CORE_DLL_ENTRY void Upper();
|
|
DT_CORE_DLL_ENTRY String GetUppered() const;
|
|
|
|
DT_CORE_DLL_ENTRY void Lower();
|
|
DT_CORE_DLL_ENTRY String GetLowered() const;
|
|
|
|
DT_CORE_DLL_ENTRY String SubStr(SizeT start, SizeT n = -1) const;
|
|
|
|
DT_CORE_DLL_ENTRY void Trim();
|
|
DT_CORE_DLL_ENTRY String GetTrimmed() const;
|
|
|
|
DT_CORE_DLL_ENTRY void TrimLeft();
|
|
DT_CORE_DLL_ENTRY String GetTrimmedLeft() const;
|
|
|
|
DT_CORE_DLL_ENTRY void PadRight(char c, SizeT n);
|
|
|
|
DT_CORE_DLL_ENTRY void Repeat(char c, SizeT n);
|
|
|
|
DT_CORE_DLL_ENTRY static String FromBin(SizeT size, const void* data, int cols = 30);
|
|
|
|
DT_CORE_DLL_ENTRY void HtmlEscape();
|
|
|
|
DT_CORE_DLL_ENTRY String GetAsAscii() const;
|
|
|
|
DT_CORE_DLL_ENTRY bool Replace(const String& str, const String& by, SizeT start = 0);
|
|
DT_CORE_DLL_ENTRY String GetReplaced(const String& str, const String& by, SizeT start = 0) const;
|
|
|
|
DT_CORE_DLL_ENTRY bool ReplaceAll(const String& str, const String& by, SizeT start = 0);
|
|
DT_CORE_DLL_ENTRY String GetReplacedAll(const String& str, const String& by, SizeT start = 0) const;
|
|
|
|
DT_CORE_DLL_ENTRY void Clear();
|
|
|
|
DT_CORE_DLL_ENTRY void Reserve(SizeT size);
|
|
|
|
DT_CORE_DLL_ENTRY void Resize(SizeT size);
|
|
|
|
DT_CORE_DLL_ENTRY SizeT Capacity() const;
|
|
|
|
DT_CORE_DLL_ENTRY SizeT Size() const;
|
|
|
|
DT_CORE_DLL_ENTRY void Swap(String& str);
|
|
|
|
DT_CORE_DLL_ENTRY static SizeT StringLength(const char* str);
|
|
DT_CORE_DLL_ENTRY static SizeT StringLengthFromUTF8(const char* str);
|
|
|
|
DT_CORE_DLL_ENTRY static SizeT StringCompare(const char* str1, const char* str2);
|
|
|
|
DT_CORE_DLL_ENTRY bool Empty() const;
|
|
|
|
DT_CORE_DLL_ENTRY bool IsWhiteSpaceOrEmpty() const;
|
|
|
|
DT_CORE_DLL_ENTRY void StandardizeEndOfLine(EndOfLineStandards standard);
|
|
DT_CORE_DLL_ENTRY String GetStandardizedEndOfLine(EndOfLineStandards standard) const;
|
|
|
|
DT_CORE_DLL_ENTRY const char* CStr() const;
|
|
|
|
DT_CORE_DLL_ENTRY static const SizeT NPOS;
|
|
|
|
DT_CORE_DLL_ENTRY static const String& Blank();
|
|
|
|
private:
|
|
enum { FIXED_BUFFER_SIZE=64 };
|
|
char m_FixedBuffer[FIXED_BUFFER_SIZE];
|
|
char* m_Buffer;
|
|
SizeT m_Size;
|
|
SizeT m_Capacity;
|
|
};
|
|
|
|
class WString
|
|
{
|
|
public:
|
|
DT_CORE_DLL_ENTRY WString();
|
|
DT_CORE_DLL_ENTRY WString(Wchar ch);
|
|
DT_CORE_DLL_ENTRY WString(const WString& str);
|
|
DT_CORE_DLL_ENTRY WString(const String& str);
|
|
DT_CORE_DLL_ENTRY WString(WString&& str);
|
|
DT_CORE_DLL_ENTRY WString(const Wchar* str);
|
|
DT_CORE_DLL_ENTRY WString(const Wchar* str, SizeT n);
|
|
DT_CORE_DLL_ENTRY ~WString();
|
|
|
|
// Move assignment operator.
|
|
DT_CORE_DLL_ENTRY WString& operator=(WString&& other);
|
|
DT_CORE_DLL_ENTRY WString& operator=(const WString& str);
|
|
DT_CORE_DLL_ENTRY WString& operator+=(const WString& str);
|
|
DT_CORE_DLL_ENTRY WString& operator+=(const String& str);
|
|
DT_CORE_DLL_ENTRY WString& operator+=(const char* str);
|
|
DT_CORE_DLL_ENTRY WString& operator+=(const Wchar* str);
|
|
DT_CORE_DLL_ENTRY WString& operator+=(Wchar c);
|
|
DT_CORE_DLL_ENTRY WString operator+(const WString& str) const;
|
|
DT_CORE_DLL_ENTRY const Wchar& operator[](SizeT idx) const;
|
|
DT_CORE_DLL_ENTRY Wchar& operator[](SizeT idx);
|
|
|
|
DT_CORE_DLL_ENTRY bool operator<(const String& str) const { return Compare(str) < 0; }
|
|
DT_CORE_DLL_ENTRY bool operator==(const WString& str) const;
|
|
DT_CORE_DLL_ENTRY bool operator!=(const WString& str) const;
|
|
|
|
DT_CORE_DLL_ENTRY int Compare(const WString& str) const;
|
|
|
|
DT_CORE_DLL_ENTRY void Clear();
|
|
|
|
DT_CORE_DLL_ENTRY void Reserve(SizeT size);
|
|
|
|
DT_CORE_DLL_ENTRY void Resize(SizeT size);
|
|
|
|
DT_CORE_DLL_ENTRY SizeT Capacity() const;
|
|
|
|
DT_CORE_DLL_ENTRY SizeT Size() const;
|
|
|
|
DT_CORE_DLL_ENTRY void Swap(WString& str);
|
|
|
|
DT_CORE_DLL_ENTRY bool Empty() const;
|
|
|
|
DT_CORE_DLL_ENTRY bool IsWhiteSpaceOrEmpty() const;
|
|
|
|
DT_CORE_DLL_ENTRY const Wchar* CStr() const;
|
|
|
|
DT_CORE_DLL_ENTRY static const WString& Blank();
|
|
|
|
DT_CORE_DLL_ENTRY static SizeT StringLength(const Wchar* str);
|
|
DT_CORE_DLL_ENTRY static SizeT StringLengthToUTF8(const Wchar* str);
|
|
|
|
private:
|
|
enum { FIXED_BUFFER_SIZE = 32 };
|
|
Wchar m_FixedBuffer[FIXED_BUFFER_SIZE];
|
|
Wchar* m_Buffer;
|
|
SizeT m_Size;
|
|
SizeT m_Capacity;
|
|
};
|
|
|
|
class IntU8
|
|
{
|
|
public:
|
|
DT_CORE_DLL_ENTRY static String ToString(U8 value, int width = 1);
|
|
DT_CORE_DLL_ENTRY static U8 Parse(const String& value);
|
|
DT_CORE_DLL_ENTRY static bool IsValid(const String& value);
|
|
};
|
|
|
|
class IntS8
|
|
{
|
|
public:
|
|
DT_CORE_DLL_ENTRY static String ToString(S8 value, int width = 1);
|
|
DT_CORE_DLL_ENTRY static S8 Parse(const String& value);
|
|
DT_CORE_DLL_ENTRY static bool IsValid(const String& value);
|
|
};
|
|
|
|
class IntU16
|
|
{
|
|
public:
|
|
DT_CORE_DLL_ENTRY static String ToString(U16 value, int width = 1);
|
|
DT_CORE_DLL_ENTRY static U16 Parse(const String& value);
|
|
DT_CORE_DLL_ENTRY static bool IsValid(const String& value);
|
|
};
|
|
|
|
class IntS16
|
|
{
|
|
public:
|
|
DT_CORE_DLL_ENTRY static String ToString(S16 value, int width = 1);
|
|
DT_CORE_DLL_ENTRY static S16 Parse(const String& value);
|
|
DT_CORE_DLL_ENTRY static bool IsValid(const String& value);
|
|
};
|
|
|
|
class IntU32
|
|
{
|
|
public:
|
|
DT_CORE_DLL_ENTRY static String ToString(U32 value, int width = 1);
|
|
DT_CORE_DLL_ENTRY static U32 Parse(const String& value);
|
|
DT_CORE_DLL_ENTRY static bool IsValid(const String& value);
|
|
};
|
|
|
|
class IntS32
|
|
{
|
|
public:
|
|
DT_CORE_DLL_ENTRY static String ToString(S32 value, int width = 1);
|
|
DT_CORE_DLL_ENTRY static String ToHexString(S32 value);
|
|
DT_CORE_DLL_ENTRY static S32 Parse(const String& value);
|
|
DT_CORE_DLL_ENTRY static bool IsValid(const String& value);
|
|
};
|
|
using Int = IntS32; // compatibility
|
|
|
|
class IntU64
|
|
{
|
|
public:
|
|
DT_CORE_DLL_ENTRY static String ToString(U64 value, int width = 1);
|
|
DT_CORE_DLL_ENTRY static String ToHexString(U64 value);
|
|
DT_CORE_DLL_ENTRY static U64 Parse(const String& value);
|
|
DT_CORE_DLL_ENTRY static bool IsValid(const String& value);
|
|
};
|
|
|
|
class IntS64
|
|
{
|
|
public:
|
|
DT_CORE_DLL_ENTRY static String ToString(S64 value, int width = 1);
|
|
DT_CORE_DLL_ENTRY static String ToHexString(S64 value);
|
|
DT_CORE_DLL_ENTRY static S64 Parse(const String& value);
|
|
DT_CORE_DLL_ENTRY static bool IsValid(const String& value);
|
|
};
|
|
|
|
class Float
|
|
{
|
|
public:
|
|
DT_CORE_DLL_ENTRY static String ToString(float value, int decimals = 3);
|
|
DT_CORE_DLL_ENTRY static float Parse(const String& value);
|
|
DT_CORE_DLL_ENTRY static bool IsValid(const String& value);
|
|
};
|
|
|
|
class Double
|
|
{
|
|
public:
|
|
DT_CORE_DLL_ENTRY static String ToString(double value, int decimals = 3);
|
|
DT_CORE_DLL_ENTRY static double Parse(const String& value);
|
|
DT_CORE_DLL_ENTRY static bool IsValid(const String& value);
|
|
};
|
|
|
|
class Boolean
|
|
{
|
|
public:
|
|
DT_CORE_DLL_ENTRY static String ToString(bool value);
|
|
DT_CORE_DLL_ENTRY static bool Parse(const String& value);
|
|
DT_CORE_DLL_ENTRY static bool IsValid(const String& value);
|
|
};
|
|
|
|
typedef Vector<String> Strings;
|
|
|
|
DT_CORE_DLL_ENTRY String PadString(char c, SizeT count, const String& in = String::Blank());
|
|
|
|
DT_CORE_DLL_ENTRY void CreateTuple(const String& inLeft, const String& inRight, String* out);
|
|
DT_CORE_DLL_ENTRY bool ParseTuple(const String& in, String* outLeft, String* outRight);
|
|
|
|
DT_CORE_DLL_ENTRY String PeriodInMicroSecToString(S64 usecs);
|
|
template <class Rep, class Period> String Humanize(std::chrono::duration<Rep, Period> value)
|
|
{
|
|
return PeriodInMicroSecToString(std::chrono::duration_cast<MicroSeconds>(value).count());
|
|
}
|
|
|
|
DT_CORE_DLL_ENTRY String NumBytesToString(SizeT numBytes);
|
|
|
|
DT_CORE_DLL_ENTRY void SplitInLines(const String& value,
|
|
SizeT firstLineLength,
|
|
SizeT remainLength,
|
|
Strings& outLines);
|
|
|
|
struct StringCaseInsensitiveLess
|
|
{
|
|
bool operator() (const String& lhs, const String& rhs) const
|
|
{
|
|
return lhs.Compare(rhs, false) < 0;
|
|
}
|
|
};
|
|
|
|
struct ConstCharPtrLess
|
|
{
|
|
bool operator() (const char* lhs, const char* rhs) const
|
|
{
|
|
return String::StringCompare(lhs, rhs) < 0;
|
|
}
|
|
};
|
|
|
|
#if !defined(EAL_USE_STDINT_INT_TYPES)
|
|
DT_CORE_DLL_ENTRY extern String& operator<<(String& buffer, int value);
|
|
DT_CORE_DLL_ENTRY extern int& operator>>(const String& buffer, int& value);
|
|
#endif // EAL_USE_STDINT_INT_TYPES
|
|
|
|
DT_CORE_DLL_ENTRY extern bool operator==(const char* lhs, const String& rhs);
|
|
DT_CORE_DLL_ENTRY extern bool operator==(const Wchar* lhs, const WString& rhs);
|
|
|
|
DT_CORE_DLL_ENTRY extern String& operator<<(String& buffer, S8 value);
|
|
DT_CORE_DLL_ENTRY extern String& operator<<(String& buffer, S16 value);
|
|
DT_CORE_DLL_ENTRY extern String& operator<<(String& buffer, S32 value);
|
|
DT_CORE_DLL_ENTRY extern String& operator<<(String& buffer, S64 value);
|
|
DT_CORE_DLL_ENTRY extern String& operator<<(String& buffer, U8 value);
|
|
DT_CORE_DLL_ENTRY extern String& operator<<(String& buffer, U16 value);
|
|
DT_CORE_DLL_ENTRY extern String& operator<<(String& buffer, U32 value);
|
|
DT_CORE_DLL_ENTRY extern String& operator<<(String& buffer, U64 value);
|
|
DT_CORE_DLL_ENTRY extern String& operator<<(String& buffer, float value);
|
|
DT_CORE_DLL_ENTRY extern String& operator<<(String& buffer, double value);
|
|
DT_CORE_DLL_ENTRY extern String& operator<<(String& buffer, const String& value);
|
|
DT_CORE_DLL_ENTRY extern String& operator<<(String& buffer, const WString& value);
|
|
DT_CORE_DLL_ENTRY extern String& operator<<(String& buffer, const char* value);
|
|
DT_CORE_DLL_ENTRY extern String& operator<<(String& buffer, const Wchar* value);
|
|
DT_CORE_DLL_ENTRY extern String& operator<<(String& buffer, char value);
|
|
DT_CORE_DLL_ENTRY extern String& operator<<(String& buffer, Wchar value);
|
|
DT_CORE_DLL_ENTRY extern String& operator<<(String& buffer, bool value);
|
|
|
|
DT_CORE_DLL_ENTRY extern WString& operator<<(WString& buffer, const WString& value);
|
|
DT_CORE_DLL_ENTRY extern WString& operator<<(WString& buffer, const String& value);
|
|
DT_CORE_DLL_ENTRY extern WString& operator<<(WString& buffer, const char* value);
|
|
|
|
DT_CORE_DLL_ENTRY extern S8& operator>>(const String& buffer, S8& value);
|
|
DT_CORE_DLL_ENTRY extern S16& operator>>(const String& buffer, S16& value);
|
|
DT_CORE_DLL_ENTRY extern S32& operator>>(const String& buffer, S32& value);
|
|
DT_CORE_DLL_ENTRY extern S64& operator>>(const String& buffer, S64& value);
|
|
DT_CORE_DLL_ENTRY extern U8& operator>>(const String& buffer, U8& value);
|
|
DT_CORE_DLL_ENTRY extern U16& operator>>(const String& buffer, U16& value);
|
|
DT_CORE_DLL_ENTRY extern U32& operator>>(const String& buffer, U32& value);
|
|
DT_CORE_DLL_ENTRY extern U64& operator>>(const String& buffer, U64& value);
|
|
DT_CORE_DLL_ENTRY extern float& operator>>(const String& buffer, float& value);
|
|
DT_CORE_DLL_ENTRY extern double& operator>>(const String& buffer, double& value);
|
|
DT_CORE_DLL_ENTRY extern String& operator>>(const String& buffer, String& value);
|
|
DT_CORE_DLL_ENTRY extern char& operator>>(const String& buffer, char& value);
|
|
DT_CORE_DLL_ENTRY extern bool& operator>>(const String& buffer, bool& value);
|
|
|
|
template <typename T> inline String& operator<<(String& buffer, const T* value)
|
|
{
|
|
return buffer << IntU64::ToHexString(reinterpret_cast<U64>(value));
|
|
}
|
|
|
|
template <typename T> inline String& operator<<(String& buffer, const Vector<T>& values)
|
|
{
|
|
bool first = true;
|
|
for (auto i = values.Begin(); i != values.End(); ++i)
|
|
{
|
|
if (!first)
|
|
{
|
|
buffer << ", ";
|
|
}
|
|
buffer << *i;
|
|
first = false;
|
|
}
|
|
return buffer;
|
|
}
|
|
|
|
template <typename T> inline const String& operator>>(const String& buffer, Vector<T>& values)
|
|
{
|
|
Strings parts;
|
|
buffer.Split(",", parts);
|
|
if (parts.Size() != 1 || !parts.Empty())
|
|
{
|
|
values.Reserve(parts.Size());
|
|
for (String& part : parts)
|
|
{
|
|
part.Trim();
|
|
T v;
|
|
part >> v;
|
|
values.PushBack(v);
|
|
}
|
|
}
|
|
return buffer;
|
|
}
|
|
|
|
template <typename T, typename U> inline String& operator<<(String& buffer, Map<T, U> values)
|
|
{
|
|
bool first = true;
|
|
for (auto i = values.Begin(); i != values.End(); ++i)
|
|
{
|
|
if (!first)
|
|
{
|
|
buffer << ", ";
|
|
}
|
|
buffer << i->first << ':' << i->second;
|
|
first = false;
|
|
}
|
|
return buffer;
|
|
}
|
|
|
|
template <typename T> inline String& operator<<(String& buffer, Set<T> values)
|
|
{
|
|
bool first = true;
|
|
for (auto i = values.Begin(); i != values.End(); ++i)
|
|
{
|
|
if (!first)
|
|
{
|
|
buffer << ", ";
|
|
}
|
|
buffer << *i;
|
|
first = false;
|
|
}
|
|
return buffer;
|
|
}
|
|
|
|
template <typename T> inline const String& operator>>(const String& buffer, Set<T>& values)
|
|
{
|
|
Strings parts;
|
|
buffer.Split(",", parts);
|
|
if (parts.Size() != 1 || !parts.Empty())
|
|
{
|
|
values.Reserve(parts.Size());
|
|
for (String& part : parts)
|
|
{
|
|
part.Trim();
|
|
T v;
|
|
part >> v;
|
|
values.Insert(v);
|
|
}
|
|
}
|
|
return buffer;
|
|
}
|
|
|
|
template <typename T, typename Param> String& operator<<(String& buffer, StrongType<T, Param> value)
|
|
{
|
|
buffer << value.UnboxValue();
|
|
return buffer;
|
|
}
|
|
|
|
template <typename T, typename Param> StrongType<T, Param>& operator>>(const String& buffer, StrongType<T, Param>& value)
|
|
{
|
|
buffer >> value.UnboxValue();
|
|
return value;
|
|
}
|
|
|
|
template <typename Rep, typename Period> inline
|
|
String& operator<<(String& buffer, std::chrono::duration<Rep, Period> value)
|
|
{
|
|
buffer << value.count();
|
|
return buffer;
|
|
}
|
|
|
|
template <typename Rep, typename Period> inline
|
|
std::chrono::duration<Rep, Period>& operator>>(const String& buffer, std::chrono::duration<Rep, Period>& value)
|
|
{
|
|
Rep v;
|
|
buffer >> v;
|
|
value = std::chrono::duration<Rep, Period>(v);
|
|
return value;
|
|
}
|
|
|
|
template <typename String> inline const String& Humanize(const String& value)
|
|
{
|
|
return value;
|
|
}
|
|
|
|
template <typename T> inline String Humanize(const Vector<T>& values)
|
|
{
|
|
String buffer;
|
|
SizeT counter = 0;
|
|
SizeT last = values.Size() - 1;
|
|
for (auto i = values.Begin(); i != values.End(); ++i)
|
|
{
|
|
if (counter != 0)
|
|
{
|
|
if (counter == last)
|
|
{
|
|
buffer << " and ";
|
|
}
|
|
else
|
|
{
|
|
buffer << ", ";
|
|
}
|
|
}
|
|
buffer << dt::Humanize(*i);
|
|
counter++;
|
|
}
|
|
return buffer;
|
|
}
|
|
|
|
}
|
|
|