mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-07-07 07:21:18 +12:00
252 lines
4.4 KiB
C++
252 lines
4.4 KiB
C++
#pragma once
|
|
|
|
class StringTokenParser
|
|
{
|
|
public:
|
|
StringTokenParser() : m_str(nullptr), m_len(0) {};
|
|
|
|
StringTokenParser(const char* input, sint32 inputLen) : m_str(input), m_len(inputLen) {};
|
|
StringTokenParser(std::string_view str) : m_str(str.data()), m_len((sint32)str.size()) {};
|
|
|
|
// skip whitespaces at current ptr position
|
|
void skipWhitespaces()
|
|
{
|
|
m_str = _skipWhitespaces(m_str, m_len);
|
|
}
|
|
|
|
// decrease string length as long as there is a whitespace at the end
|
|
void trimWhitespaces()
|
|
{
|
|
while (m_len > 0)
|
|
{
|
|
const char c = m_str[m_len - 1];
|
|
if (c != ' ' && c != '\t')
|
|
break;
|
|
m_len--;
|
|
}
|
|
}
|
|
|
|
bool isEndOfString()
|
|
{
|
|
return m_len <= 0;
|
|
}
|
|
|
|
sint32 skipToCharacter(const char c)
|
|
{
|
|
auto str = m_str;
|
|
auto len = m_len;
|
|
sint32 idx = 0;
|
|
while (len > 0)
|
|
{
|
|
if (*str == c)
|
|
{
|
|
m_str = str;
|
|
m_len = len;
|
|
return idx;
|
|
}
|
|
len--;
|
|
str++;
|
|
idx++;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
bool matchWordI(const char* word)
|
|
{
|
|
auto str = m_str;
|
|
auto length = m_len;
|
|
str = _skipWhitespaces(str, length);
|
|
for (sint32 i = 0; i <= length; i++)
|
|
{
|
|
if (word[i] == '\0')
|
|
{
|
|
m_str = str + i;
|
|
m_len = length - i;
|
|
return true;
|
|
}
|
|
if (i == length)
|
|
return false;
|
|
|
|
char c1 = str[i];
|
|
char c2 = word[i];
|
|
c1 = _toUpperCase(c1);
|
|
c2 = _toUpperCase(c2);
|
|
if (c1 != c2)
|
|
return false;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool compareCharacter(sint32 relativeIndex, const char c)
|
|
{
|
|
if (relativeIndex >= m_len)
|
|
return false;
|
|
return m_str[relativeIndex] == c;
|
|
}
|
|
|
|
bool compareCharacterI(sint32 relativeIndex, const char c)
|
|
{
|
|
if (relativeIndex >= m_len)
|
|
return false;
|
|
return _toUpperCase(m_str[relativeIndex]) == _toUpperCase(c);
|
|
}
|
|
|
|
void skipCharacters(sint32 count)
|
|
{
|
|
if (count > m_len)
|
|
count = m_len;
|
|
m_str += count;
|
|
m_len -= count;
|
|
}
|
|
|
|
bool parseU32(uint32& val)
|
|
{
|
|
auto str = m_str;
|
|
auto length = m_len;
|
|
str = _skipWhitespaces(str, length);
|
|
uint32 value = 0;
|
|
sint32 index = 0;
|
|
bool isHex = false;
|
|
if (length <= 0)
|
|
return false;
|
|
if (length >= 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
|
|
{
|
|
isHex = true;
|
|
index += 2;
|
|
}
|
|
else if (str[index] == '0')
|
|
{
|
|
isHex = true;
|
|
index++;
|
|
}
|
|
if (length <= index)
|
|
return false;
|
|
if (isHex)
|
|
{
|
|
sint32 firstDigitIndex = index;
|
|
for (; index < length; index++)
|
|
{
|
|
const char c = str[index];
|
|
if (c >= '0' && c <= '9')
|
|
{
|
|
value *= 0x10;
|
|
value += (c - '0');
|
|
}
|
|
else if (c >= 'a' && c <= 'f')
|
|
{
|
|
value *= 0x10;
|
|
value += (c - 'a' + 10);
|
|
}
|
|
else if (c >= 'A' && c <= 'F')
|
|
{
|
|
value *= 0x10;
|
|
value += (c - 'A' + 10);
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
if (index == firstDigitIndex)
|
|
return false;
|
|
m_str = str + index;
|
|
m_len = length - index;
|
|
}
|
|
else
|
|
{
|
|
sint32 firstDigitIndex = index;
|
|
for (; index < length; index++)
|
|
{
|
|
const char c = str[index];
|
|
if (c >= '0' && c <= '9')
|
|
{
|
|
value *= 10;
|
|
value += (c - '0');
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
if (index == firstDigitIndex)
|
|
return false;
|
|
m_str = str + index;
|
|
m_len = length - index;
|
|
}
|
|
val = value;
|
|
return true;
|
|
}
|
|
|
|
bool parseSymbolName(const char*& symbolStr, sint32& symbolLength)
|
|
{
|
|
auto str = m_str;
|
|
auto length = m_len;
|
|
str = _skipWhitespaces(str, length);
|
|
// symbols must start with a letter or _
|
|
if (length <= 0)
|
|
return false;
|
|
if (!(str[0] >= 'a' && str[0] <= 'z') &&
|
|
!(str[0] >= 'A' && str[0] <= 'Z') &&
|
|
!(str[0] == '_'))
|
|
return false;
|
|
sint32 idx = 1;
|
|
while (idx < length)
|
|
{
|
|
const char c = str[idx];
|
|
if (!(c >= 'a' && c <= 'z') &&
|
|
!(c >= 'A' && c <= 'Z') &&
|
|
!(c >= '0' && c <= '9') &&
|
|
!(c == '_') && !(c == '.'))
|
|
break;
|
|
idx++;
|
|
}
|
|
symbolStr = str;
|
|
symbolLength = idx;
|
|
m_str = str + idx;
|
|
m_len = length - idx;
|
|
return true;
|
|
}
|
|
|
|
const char* getCurrentPtr()
|
|
{
|
|
return m_str;
|
|
}
|
|
|
|
sint32 getCurrentLen()
|
|
{
|
|
return m_len;
|
|
}
|
|
|
|
void storeParserState(StringTokenParser* bak)
|
|
{
|
|
bak->m_str = m_str;
|
|
bak->m_len = m_len;
|
|
}
|
|
|
|
void restoreParserState(const StringTokenParser* bak)
|
|
{
|
|
m_str = bak->m_str;
|
|
m_len = bak->m_len;
|
|
}
|
|
|
|
private:
|
|
const char* _skipWhitespaces(const char* str, sint32& length)
|
|
{
|
|
while (length > 0)
|
|
{
|
|
if (*str != ' ' && *str != '\t')
|
|
break;
|
|
str++;
|
|
length--;
|
|
}
|
|
return str;
|
|
}
|
|
|
|
char _toUpperCase(const char c)
|
|
{
|
|
if (c >= 'a' && c <= 'z')
|
|
return c + ('A' - 'a');
|
|
return c;
|
|
}
|
|
|
|
private:
|
|
const char* m_str;
|
|
sint32 m_len;
|
|
};
|
|
|