#pragma once
#include "System/ArgumentException.h"
#include "System/ArgumentOutOfRangeException.h"
#include "System/NotImplementedException.h"
#include "System/OverflowException.h"
#include "System/FormatException.h"
#include "Utils.h"
// Forward declaration moved
#include "System/Utils/StringConvert.h"
#include <initializer_list>
#include <ctype.h>
#include <wctype.h>
#include <cstring>
namespace DotNetDupe {
namespace System {
template<typename T> class Array;
enum class StringSplitOptions {
None,
RemoveEmptyEntries,
TrimEntries
};
// Helper for portable case-insensitive comparison
struct CaseInsensitiveCompare {
static bool Equals(char c1, char c2) {
return tolower(static_cast<unsigned char>(c1)) == tolower(static_cast<unsigned char>(c2));
}
};
struct CaseInsensitiveCompareWChar {
static bool Equals(wchar_t c1, wchar_t c2) {
return towlower(c1) == towlower(c2);
}
};
class DateTimeOffset;
struct BoolRepresentation {
static constexpr const char* True = "True";
static constexpr const char* False = "False";
};
struct BoolRepresentationWChar {
static constexpr const wchar_t* True = L"True";
static constexpr const wchar_t* False = L"False";
};
struct FormatExceptionMessage {
static constexpr const char* Message = "Input string was not in a correct format.";
};
struct FormatExceptionMessageWChar {
static constexpr const wchar_t* Message = L"Input string was not in a correct format.";
};
class String {
public:
DOTNETDUPE_API String();
DOTNETDUPE_API String(const char* pStr);
DOTNETDUPE_API String(const String& sStr);
DOTNETDUPE_API String& operator=(const String& sStr);
DOTNETDUPE_API String(String&& sStr) noexcept;
DOTNETDUPE_API String& operator=(String&& sStr) noexcept;
DOTNETDUPE_API String& operator=(const char* pStr);
DOTNETDUPE_API ~String();
// Converting constructor & assignment for opposite character pointer type
DOTNETDUPE_API String(const wchar_t* pStr);
DOTNETDUPE_API String& operator=(const wchar_t* pStr);
// std::nullptr_t & int (0/NULL) constructors & assignments to throw ArgumentException
DOTNETDUPE_API String(std::nullptr_t) { throw ArgumentException("Invalid input pointer"); }
DOTNETDUPE_API String& operator=(std::nullptr_t) { throw ArgumentException("Invalid input pointer"); }
DOTNETDUPE_API String(int nNull) {
if (nNull == 0) throw ArgumentException("Invalid input pointer");
throw ArgumentException("Invalid input integer");
}
DOTNETDUPE_API const char* GetRawString() const;
operator const char* () const { return GetRawString(); }
DOTNETDUPE_API int GetHashCode() const;
DOTNETDUPE_API int GetLength() const;
DOTNETDUPE_API String Clone() const;
DOTNETDUPE_API bool operator<(const String& sStr) const {
const char* p1 = GetRawString();
const char* p2 = sStr.GetRawString();
if (!p1 && !p2) return false;
if (!p1) return true;
if (!p2) return false;
return strcmp(p1, p2) < 0;
}
friend bool operator==(const String& sStr1, const String& sStr2) {
const char* p1 = sStr1.GetRawString();
const char* p2 = sStr2.GetRawString();
if (p1 == p2) return true;
if (!p1 || !p2) return false;
return strcmp(p1, p2) == 0;
}
friend bool operator==(const String& sStr1, const char* pStr2) {
const char* p1 = sStr1.GetRawString();
if (p1 == pStr2) return true;
if (!p1 || !pStr2) return false;
return strcmp(p1, pStr2) == 0;
}
friend bool operator==(const char* pStr1, const String& sStr2) {
return sStr2 == pStr1;
}
friend bool operator!=(const String& sStr1, const String& sStr2) {
return !(sStr1 == sStr2);
}
friend bool operator!=(const String& sStr1, const char* pStr2) {
return !(sStr1 == pStr2);
}
friend bool operator!=(const char* pStr1, const String& sStr2) {
return !(pStr1 == sStr2);
}
DOTNETDUPE_API char operator[](int iIndex) const;
DOTNETDUPE_API static int Compare(const String& sStr1, int iIndex1,
const String& sStr2, int iIndex2, int iLength,
bool bIgnoreCase);
DOTNETDUPE_API int CompareTo(const String& sStr) const;
DOTNETDUPE_API String operator+(const String& sStr) const;
DOTNETDUPE_API String operator+(const char* pStr) const;
DOTNETDUPE_API String operator+(char ch) const;
DOTNETDUPE_API String& operator+=(const String& sStr);
DOTNETDUPE_API String& operator+=(const char* pStr);
DOTNETDUPE_API String& operator+=(char ch);
DOTNETDUPE_API friend String operator+(const char* pStr, const String& sStr);
DOTNETDUPE_API friend String operator+(char ch, const String& sStr);
DOTNETDUPE_API String Concat(
const std::initializer_list<String> sStrs) const;
DOTNETDUPE_API bool Contains(char ch) const;
DOTNETDUPE_API bool Contains(const String& sStr) const;
DOTNETDUPE_API void CopyTo(int iSourceIndex, char* pDestination, int iDestinationIndex,
int iDestArraySize, int iCount) const;
DOTNETDUPE_API bool EndsWith(char ch, bool bIgnoreCase) const;
DOTNETDUPE_API bool EndsWith(const String& sSuffix, bool bIgnoreCase) const;
DOTNETDUPE_API static bool Equals(const String& sStr1,
const String& sStr2);
DOTNETDUPE_API bool Equals(const String& sStr) const;
DOTNETDUPE_API int IndexOf(const String& sSubstring) const;
DOTNETDUPE_API int IndexOf(const String& sSubstring, bool bIgnoreCase) const;
DOTNETDUPE_API int IndexOf(const String& sSubstring, int iStartIndex,
bool bIgnoreCase) const;
DOTNETDUPE_API int IndexOfAny(int iStartIndex, std::initializer_list<char> chChars);
DOTNETDUPE_API String& Append(const char ch);
DOTNETDUPE_API String& Append(const String& sStr);
DOTNETDUPE_API String& Insert(int iIndex, const String& sStr);
DOTNETDUPE_API bool IsEmpty() const;
DOTNETDUPE_API static String Join(
char chSeparator, std::initializer_list<String> sStrings);
DOTNETDUPE_API static String Join(
char chSeparator, std::initializer_list<String> sStrings,
int iStartIndex, int iCount);
DOTNETDUPE_API static String Join(
const String& sSeparator,
std::initializer_list<String> sStrings);
DOTNETDUPE_API static String Join(
const String& sSeparator,
std::initializer_list<String> sStrings, int iStartIndex,
int iCount);
static String FormatArgHelper(bool b) { return b ? "True" : "False"; }
static String FormatArgHelper(std::nullptr_t) { return ""; }
static String FormatArgHelper(const String& s) { return s; }
static String FormatArgHelper(const char* s) { return String(s); }
static String FormatArgHelper(char c) { char arr[2] = {c, 0}; return String(arr); }
static String FormatArgHelper(short i) { return String::FromInt(i); }
static String FormatArgHelper(unsigned short i) { return String::FromInt(i); }
static String FormatArgHelper(int i) { return String::FromInt(i); }
static String FormatArgHelper(unsigned int u) { return String::ValueOf((long long)u); }
static String FormatArgHelper(long l) { return String::ValueOf((long long)l); }
static String FormatArgHelper(unsigned long ul) { return String::ValueOf((long long)ul); }
static String FormatArgHelper(long long ll) { return String::ValueOf(ll); }
static String FormatArgHelper(unsigned long long ull) { return String::ValueOf((long long)ull); }
static String FormatArgHelper(float f) { return String::ValueOf((double)f); }
static String FormatArgHelper(double d) { return String::ValueOf(d); }
template<typename T>
static String FormatArgHelper(const T& arg) { return arg.ToString(); }
DOTNETDUPE_API static String InternalFormat(const char* pFormat, const String* pArgs, int iArgCount);
template <typename Arg1, typename... Args>
static String Format(const char* pFormat, const Arg1& arg1, const Args&... args) {
String arrArgs[] = { FormatArgHelper(arg1), FormatArgHelper(args)... };
return InternalFormat(pFormat, arrArgs, 1 + sizeof...(Args));
}
static String Format(const char* pFormat) {
return InternalFormat(pFormat, nullptr, 0);
}
static String Format(const String& sFormat) {
return Format(sFormat.GetRawString() ? sFormat.GetRawString() : "");
}
template <typename Arg1, typename... Args>
static String Format(const String& sFormat, const Arg1& arg1, const Args&... args) {
return Format(sFormat.GetRawString() ? sFormat.GetRawString() : "", arg1, args...);
}
DOTNETDUPE_API int LastIndexOf(const String& sStr, bool bIgnoreCase);
DOTNETDUPE_API int LastIndexOfAny(int iStartIndex, std::initializer_list<char> chChars,
bool bIgnoreCase);
DOTNETDUPE_API String PadLeft(int iTotalWidth);
DOTNETDUPE_API String PadLeft(int iTotalWidth, char ch);
DOTNETDUPE_API String PadRight(int iTotalWidth);
DOTNETDUPE_API String PadRight(int iTotalWidth, char ch);
DOTNETDUPE_API String Remove(int iStartIndex) const;
DOTNETDUPE_API String Remove(int iStartIndex, int iCount) const;
DOTNETDUPE_API String Replace(char chOriginalChar, char chReplaceChar) const;
DOTNETDUPE_API String Replace(const String& sOriginalStr,
const String& sReplaceStr) const;
DOTNETDUPE_API Array<String> Split(char chSeparator) const;
DOTNETDUPE_API Array<String> Split(const Array<String>& arrSeparators,
StringSplitOptions eOptions = StringSplitOptions::None) const;
DOTNETDUPE_API Array<String> Split(const String* pSeparator, int iCount,
StringSplitOptions eOptions) const;
DOTNETDUPE_API bool StartsWith(const String& sPrefix) const;
DOTNETDUPE_API bool StartsWith(const String& sPrefix, bool bIgnoreCase) const;
DOTNETDUPE_API String Substring(int iStartIndex) const;
DOTNETDUPE_API String Substring(int iStartIndex, int iLength) const;
DOTNETDUPE_API static String FromInt(int iValue);
DOTNETDUPE_API static String ValueOf(int iValue);
DOTNETDUPE_API static String ValueOf(long long llValue);
DOTNETDUPE_API static String ValueOf(double dValue);
DOTNETDUPE_API static String ToString(int iValue);
DOTNETDUPE_API static String ToString(long long llValue);
DOTNETDUPE_API static String ToString(double dValue);
DOTNETDUPE_API static String ToString(bool bValue);
DOTNETDUPE_API String ToLower() const;
DOTNETDUPE_API String ToUpper() const;
DOTNETDUPE_API String Trim() const;
DOTNETDUPE_API String TrimStart() const;
DOTNETDUPE_API String TrimEnd() const;
DOTNETDUPE_API void* operator new(size_t size);
DOTNETDUPE_API void operator delete(void* p);
DOTNETDUPE_API void* operator new[](size_t size);
DOTNETDUPE_API void operator delete[](void* p);
private:
struct StringImpl;
StringImpl* m_pImpl;
};
}
}