Badminton-Scoreboard/Libraries/libil2cpp/include/utils/StringView.h
2023-10-08 10:24:48 +08:00

203 lines
5.0 KiB
C++

#pragma once
#include "il2cpp-config.h"
#include <limits.h>
#if IL2CPP_TARGET_WINDOWS
#include <malloc.h>
#else
#include <alloca.h>
#endif
#if IL2CPP_TARGET_LINUX
#define GCC_VERSION (__GNUC__ * 10000 \
+ __GNUC_MINOR__ * 100 \
+ __GNU_PATCHLEVEL__)
#endif
namespace il2cpp
{
namespace utils
{
template<typename CharType>
class StringView
{
private:
const CharType* m_String;
size_t m_Length;
// Intended to only be used by Empty()
inline StringView() :
m_String(NULL),
m_Length(0)
{
}
public:
template<size_t Length>
inline StringView(const CharType(&str)[Length]) :
m_String(str), m_Length(Length - 1)
{
}
inline StringView(const CharType* str, size_t length) :
m_String(str), m_Length(length)
{
IL2CPP_ASSERT(str != NULL);
}
inline StringView(const CharType* str, size_t startIndex, size_t length) :
m_String(str + startIndex), m_Length(length)
{
IL2CPP_ASSERT(str != NULL);
}
inline StringView(const StringView<CharType>& str, size_t startIndex, size_t length) :
m_String(str.Str() + startIndex),
m_Length(length)
{
IL2CPP_ASSERT(startIndex + length <= str.Length());
}
// This is to work around a bug in gcc (24666) where arrays decay to pointers too fast
// This is known to be fixed by at least 7.3.0
#if IL2CPP_TARGET_LINUX && GCC_VERSION < 70300
inline StringView(const char* str) :
m_String(str), m_Length(strlen(str))
{
}
#endif
inline const CharType* Str() const
{
return m_String;
}
inline size_t Length() const
{
return m_Length;
}
inline CharType operator[](size_t index) const
{
return m_String[index];
}
inline bool IsNullTerminated() const
{
return m_String[m_Length] == 0;
}
inline bool IsEmpty() const
{
return Length() == 0;
}
static inline StringView<CharType> Empty()
{
return StringView<CharType>();
}
inline size_t Find(CharType c, size_t startIndex = 0) const
{
const CharType* end = m_String + m_Length;
for (const CharType* ptr = m_String + startIndex; ptr < end; ptr++)
{
if (*ptr == c)
return ptr - m_String;
}
return NPos();
}
inline size_t RFind(CharType c) const
{
for (const CharType* ptr = m_String + m_Length; ptr-- > m_String;)
{
if (*ptr == c)
return ptr - m_String;
}
return NPos();
}
inline StringView<CharType> SubStr(size_t startIndex, size_t length)
{
return StringView<CharType>(*this, startIndex, length);
}
inline StringView<CharType> SubStr(size_t startIndex)
{
return StringView<CharType>(*this, startIndex, Length() - startIndex);
}
inline static size_t NPos()
{
return static_cast<size_t>(-1);
}
inline bool TryParseAsInt(int& outResult)
{
if (Length() == 0)
return false;
int result = 0;
bool isNegative = false;
const CharType* ptr = m_String;
const CharType* end = m_String + m_Length;
if (ptr[0] == '-')
{
isNegative = true;
ptr++;
}
for (; ptr < end; ptr++)
{
CharType digit = *ptr;
if (digit < '0' || digit > '9')
return false;
int digitNumeric = digit - '0';
if (result > INT_MAX / 10)
return false;
result = result * 10;
if (result > INT_MAX - digitNumeric)
return false;
result += digitNumeric;
}
if (isNegative)
{
outResult = -result;
}
else
{
outResult = result;
}
return true;
}
};
#define StringViewAsNullTerminatedStringOf(CharType, stringView, variableName) \
const CharType* variableName; \
do \
{ \
if (!stringView.IsEmpty() && stringView.IsNullTerminated()) \
{ \
variableName = stringView.Str(); \
} \
else \
{ \
CharType* buffer = static_cast<CharType*>(alloca((stringView.Length() + 1) * sizeof(CharType))); \
memcpy(buffer, stringView.Str(), stringView.Length() * sizeof(CharType)); \
buffer[stringView.Length()] = 0; \
variableName = buffer; \
} \
} \
while (false)
}
}