163 lines
4.3 KiB
C++
163 lines
4.3 KiB
C++
#pragma once
|
|
|
|
#include <Core/Math/MathUtils.h>
|
|
#include <Core/Memory/Utils.h>
|
|
|
|
namespace Juliet
|
|
{
|
|
#define ConstString(str) { const_cast<char*>((str)), sizeof(str) - 1 }
|
|
#define CStr(str) ((str).Data)
|
|
#define InplaceString(name, size) \
|
|
char name##_[size]; \
|
|
MemSet(name##_, 0, sizeof(uint32)); \
|
|
String name = { name##_, 0 }
|
|
|
|
// Everything is Little Endian
|
|
enum class StringEncoding : uint8
|
|
{
|
|
Unknown = 0,
|
|
ASCII,
|
|
LATIN1,
|
|
UTF8,
|
|
UTF16,
|
|
UTF32,
|
|
UCS2,
|
|
UCS4,
|
|
};
|
|
|
|
// Represents a UTF-8 String.
|
|
// Not null terminated.
|
|
struct String
|
|
{
|
|
char* Data;
|
|
size_t Size;
|
|
};
|
|
|
|
struct StringBuffer : String
|
|
{
|
|
size_t Capacity;
|
|
};
|
|
|
|
constexpr uint32 kInvalidUTF8 = 0xFFFD;
|
|
|
|
inline size_t StringLength(String str)
|
|
{
|
|
return str.Size;
|
|
}
|
|
|
|
inline size_t StringLength(const char* str)
|
|
{
|
|
size_t length = 0;
|
|
if (str)
|
|
{
|
|
while (char ch = *str)
|
|
{
|
|
if ((ch & 0xC0) != 0x80)
|
|
{
|
|
++length;
|
|
}
|
|
++str;
|
|
}
|
|
}
|
|
|
|
return length;
|
|
}
|
|
|
|
inline bool IsValid(String str)
|
|
{
|
|
return str.Size > 0 && str.Data != nullptr && *str.Data;
|
|
}
|
|
|
|
inline String WrapString(const char* str)
|
|
{
|
|
String result = {};
|
|
result.Data = const_cast<char*>(str);
|
|
result.Size = StringLength(str);
|
|
return result;
|
|
}
|
|
|
|
inline String FindChar(String str, char c)
|
|
{
|
|
String result = str;
|
|
while (result.Size)
|
|
{
|
|
if (*result.Data != c)
|
|
{
|
|
++result.Data;
|
|
--result.Size;
|
|
}
|
|
else
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
return {};
|
|
}
|
|
|
|
inline bool ContainsChar(String str, char c)
|
|
{
|
|
return IsValid(FindChar(str, c));
|
|
}
|
|
|
|
// Return:
|
|
// - < 0 if str1 < str2
|
|
// - = 0 : Both strings are equals
|
|
// - > 0 if str1 > str2
|
|
inline int32 StringCompare(String str1, String str2)
|
|
{
|
|
size_t len1 = StringLength(str1);
|
|
size_t len2 = StringLength(str2);
|
|
size_t minLen = Min(len1, len2);
|
|
int32 result = MemCompare(CStr(str1), CStr(str2), minLen);
|
|
if (result == 0)
|
|
{
|
|
if (len1 > len2)
|
|
{
|
|
return 1;
|
|
}
|
|
if (len1 < len2)
|
|
{
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
JULIET_API uint32 StepUTF8(String& inStr);
|
|
JULIET_API String FindString(String strLeft, String strRight);
|
|
|
|
// Case insensitive compare. Supports ASCII only
|
|
// TODO: Support UNICODE
|
|
extern JULIET_API int8 StringCompareCaseInsensitive(String str1, String str2);
|
|
|
|
// Do not allocate anything, you must allocate your out buffer yourself
|
|
// TODO: Version taking arena that can allocate
|
|
// Do not take String type because we dont know the string encoding we are going from/to
|
|
// src and dst will be casted based on the encoding.
|
|
// size will correspond to the number of characters
|
|
// Will convert \0 character if present.
|
|
extern JULIET_API bool ConvertString(StringEncoding from, StringEncoding to, String src, StringBuffer& dst, bool nullTerminate);
|
|
extern JULIET_API bool ConvertString(String from, String to, String src, StringBuffer& dst, bool nullTerminate);
|
|
|
|
} // namespace Juliet
|
|
|
|
#ifdef UNIT_TEST
|
|
namespace Juliet::UnitTest
|
|
{
|
|
inline void TestFindChar()
|
|
{
|
|
String s1 = ConstString("");
|
|
String s2 = ConstString("abcdefabcdef");
|
|
String s3 = ConstString("11111111111111111111");
|
|
|
|
Assert(FindChar(s1, 'x').Data == nullptr);
|
|
Assert(FindChar(s2, 'y').Data == nullptr);
|
|
Assert(FindChar(s2, 'a').Data - s2.Data == 0);
|
|
Assert(FindChar(s2, 'd').Data - s2.Data == 3);
|
|
Assert(FindChar(s2, 'f').Data - s2.Data == 5);
|
|
Assert(FindChar(s3, '1').Data - s3.Data == 0);
|
|
}
|
|
} // namespace Juliet::UnitTest
|
|
#endif
|