Files
Juliet/Juliet/include/Core/Common/String.h

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