[+] AuParse::[Stringify/Parse][U/S]Int[16] class of parse APIs

[*] Optimize UNIX IPC ABI: Handle String encodes an array of U16s to optimize space. Could still be better.
This commit is contained in:
Reece Wilson 2022-08-04 13:53:59 +01:00
parent e4e0af2f1d
commit 21902a5d5b
5 changed files with 401 additions and 25 deletions

View File

@ -218,6 +218,68 @@ namespace Aurora::Parse
AUKN_SYM void SerializeToken(ParsableTag type, const ParseValue &value, AuString &str);
AUKN_SYM void Serialize(const ParsedObject &structure, AuString &ret);
AUKN_SYM AuString StringifyUInt16(AuUInt64 in, bool bZeroX = true);
AUKN_SYM AuString StringifySInt16(AuInt64 in, bool bZeroX = true);
/**
* @brief Parse Base10 null string
*/
AUKN_SYM AuResult<AuSInt> ParseSInt(const char *begin, const char *&end);
/**
* @brief Parse Base10 null string
*/
AUKN_SYM AuResult<AuUInt> ParseUInt(const char *begin, const char *&end);
/**
* @brief Parse Base64 string with optional 0x suffix and 'h' ending
*/
AUKN_SYM AuResult<AuSInt> ParseSInt16(const char *begin, const char *&end);
/**
* @brief Parse Base64 string with optional 0x suffix and 'h' ending
*/
AUKN_SYM AuResult<AuUInt> ParseUInt16(const char *begin, const char *&end);
/**
* @brief Parse Base64 null terminated string with optional 0x suffix and 'h' ending
*/
AUKN_SYM AuResult<AuSInt> ParseSInt16(const char *begin);
/**
* @brief Parse Base64 abi terminated string with optional 0x suffix and 'h' ending
*/
AUKN_SYM AuResult<AuSInt> ParseSInt16(const AuString &str);
/**
* @brief Parse Base64 null terminated string with optional 0x suffix and 'h' ending
*/
AUKN_SYM AuResult<AuUInt> ParseUInt16(const char *begin);
/**
* @brief Parse Base64 abi terminated string with optional 0x suffix and 'h' ending
*/
AUKN_SYM AuResult<AuUInt> ParseUInt16(const AuString &str);
/**
* @brief Parse abi null terminated string
*/
AUKN_SYM AuResult<AuSInt> ParseSInt(const AuString &str);
/**
* @brief Parse Base10 null terminated string
*/
AUKN_SYM AuResult<AuSInt> ParseSInt(const char *begin);
/**
* @brief Parse Base10 abi terminated string
*/
AUKN_SYM AuResult<AuUInt> ParseUInt(const AuString &str);
/**
* @brief Parse Base10 null terminated string
*/
AUKN_SYM AuResult<AuUInt> ParseUInt(const char *begin);
}

View File

@ -27,7 +27,7 @@ namespace Aurora::IO::FS
bool directIO;
};
struct LinuxAsyncFileStream : public IAsyncFileStream
struct LinuxAsyncFileStream : IAsyncFileStream
{
AuSPtr<IAsyncTransaction> NewTransaction() override;
bool BlockingTruncate(AuUInt64 length) override;

View File

@ -0,0 +1,2 @@
// TODO: Kevent can be backed by POSIX AIO
// :D

View File

@ -147,7 +147,7 @@ namespace Aurora::IO::IPC
const char *endPtr = &in[stringOffset]; \
const char *startPtr = &in[startOffset]; \
stringOffset++; \
auto nextIntOpt = AuParse::ParseUInt(startPtr, endPtr); \
auto nextIntOpt = AuParse::ParseUInt16(startPtr, endPtr); \
if (!nextIntOpt.has_value()) \
{ \
return false; \
@ -157,7 +157,6 @@ namespace Aurora::IO::IPC
int stringOffset {};
int count {};
IPCHeader headerZero;
while (in.size() > (stringOffset + 2))
{
int index = count++;
@ -173,11 +172,6 @@ namespace Aurora::IO::IPC
this->pid = nextInt;
}
if (index == 0)
{
headerZero = header;
}
auto readIPC = [&](IPCHeader header, IPCValue &value)
{
value.subtype = (EIPCHandleType)header.bmType;
@ -275,13 +269,13 @@ namespace Aurora::IO::IPC
if (header.bmHasPid)
{
ret += AuToString(this->pid);
ret += AuParse::StringifyUInt16(this->pid, false);
ret += ':';
}
if (header.bmHasWord)
{
ret += AuToString(ipcValue.token.word);
ret += AuParse::StringifyUInt16(ipcValue.token.word, false);
ret += ':';
}
@ -292,7 +286,7 @@ namespace Aurora::IO::IPC
}
else
{
ret += AuToString(ipcValue.token.cookie);
ret += AuParse::StringifyUInt16(ipcValue.token.cookie, false);
ret += ':';
}

View File

@ -262,28 +262,102 @@ namespace Aurora::Parse
return true;
}
AUKN_SYM AuResult<AuUInt> ParseUInt(const char *begin, const char *&end)
template <typename T, typename Iterator>
bool ParseInt16(Iterator begin, Iterator &end, T &out)
{
AuUInt temp{};
T res = 0;
T sign = 1;
out = 0;
if (!ParseInt<AuUInt>(begin, end, temp))
auto itr = begin;
if constexpr (AuIsSame_v<T, AuSInt>)
{
return {};
if (itr != end)
{
if (*itr == '-')
{
itr++;
sign = -1;
}
}
}
return temp;
}
AUKN_SYM AuResult<AuSInt> ParseSInt(const char *begin, const char *&end)
{
AuSInt temp{};
if (!ParseInt<AuSInt>(begin, end, temp))
if (itr != end)
{
return {};
if ((*itr == '0') && (itr[1] == 'x')) // TODO (Reece): EVIL... but it's only a byte
{
itr++;
itr++;
}
}
return temp;
if (begin != end)
{
auto endChar = *(end - 1);
if (endChar == 'h' || endChar == 'H')
{
end--;
}
}
int perf {};
for (;
(itr != end) &&
(*itr != '\0');
itr++)
{
auto c = *itr;
int delta {};
if ((c >= 'A') && (c <= 'F'))
{
delta = 10 + (c - 'A');
}
else if ((c >= 'a') && (c <= 'f'))
{
delta = 10 + (c - 'a');
}
else if ((c >= '0') && (c <= '9'))
{
delta = c - '0';
}
else
{
return false;
}
auto old = res;
res *= T(16);
res += T(delta);
if ((perf++) >= 5)
{
if constexpr (AuIsSame_v<T, AuUInt>)
{
if (old > res)
{
SysPushErrorSyntaxError("Unsigned integer overflow: {}", AuString(begin, end));
end = itr;
return false;
}
}
else if constexpr (AuIsSame_v<T, AuSInt>)
{
if (SignBit(old) != SignBit(res))
{
SysPushErrorSyntaxError("Signed integer overflow: {}", AuString(begin, end));
end = itr;
return false;
}
}
}
}
end = itr;
out = res * sign;
return true;
}
static bool ConsumeTokenPrimitiveish(ParseState &state, ParsableTag type, ParseValue &out)
@ -657,4 +731,248 @@ namespace Aurora::Parse
}
}
}
AUKN_SYM AuResult<AuUInt> ParseUInt(const char *begin, const char *&end)
{
AuUInt temp{};
if (!ParseInt<AuUInt>(begin, end, temp))
{
return {};
}
return temp;
}
AUKN_SYM AuResult<AuSInt> ParseSInt(const char *begin, const char *&end)
{
AuSInt temp{};
if (!ParseInt<AuSInt>(begin, end, temp))
{
return {};
}
return temp;
}
AUKN_SYM AuResult<AuUInt> ParseUInt16(const char *begin, const char *&end)
{
AuUInt temp{};
if (!ParseInt16<AuUInt>(begin, end, temp))
{
return {};
}
return temp;
}
AUKN_SYM AuResult<AuSInt> ParseSInt16(const char *begin, const char *&end)
{
AuSInt temp{};
if (!ParseInt16<AuSInt>(begin, end, temp))
{
return {};
}
return temp;
}
AUKN_SYM AuString StringifySInt16(AuInt64 in, bool bZeroX)
{
if (bZeroX)
{
auto str = fmt::format("{0:#X}", in);
if (str.size() > 2)
{
if (str[1] == 'X')
{
str[1] = 'x';
}
else if (str.size() > 3 && str[2] == 'X')
{
str[2] = 'x';
}
}
return str;
}
else
{
return fmt::format("{:X}", in);
}
}
AUKN_SYM AuString StringifyUInt16(AuUInt64 in, bool bZeroX)
{
if (bZeroX)
{
auto str = fmt::format("{0:#X}", in);
if (str.size() > 2)
{
if (str[1] == 'X')
{
str[1] = 'x';
}
else if (str.size() > 3 && str[2] == 'X')
{
str[2] = 'x';
}
}
return str;
}
else
{
return fmt::format("{:X}", in);
}
}
AUKN_SYM AuResult<AuSInt> ParseSInt16(const char *begin)
{
const auto end = begin + ::strlen(begin);
const char *didntFuckingAskTYVM {end };
auto res = ParseSInt16(begin, didntFuckingAskTYVM);
if (!res.has_value())
{
return {};
}
if (didntFuckingAskTYVM != end)
{
return {};
}
return res;
}
AUKN_SYM AuResult<AuSInt> ParseSInt16(const AuString &str)
{
const char *didntFuckingAskTYVM { &str[str.size()] };
auto res = ParseSInt16(str.c_str(), didntFuckingAskTYVM);
if (!res.has_value())
{
return {};
}
if (didntFuckingAskTYVM != &str[str.size()])
{
return {};
}
return res;
}
AUKN_SYM AuResult<AuUInt> ParseUInt16(const char *begin)
{
const auto end = begin + ::strlen(begin);
const char *didntFuckingAskTYVM { end };
auto res = ParseUInt16(begin, didntFuckingAskTYVM);
if (!res.has_value())
{
return {};
}
if (didntFuckingAskTYVM != end)
{
return {};
}
return res;
}
AUKN_SYM AuResult<AuUInt> ParseUInt16(const AuString &str)
{
const char *didntFuckingAskTYVM { &str[str.size()] };
auto res = ParseUInt16(str.c_str(), didntFuckingAskTYVM);
if (!res.has_value())
{
return {};
}
if (didntFuckingAskTYVM != &str[str.size()])
{
return {};
}
return res;
}
AUKN_SYM AuResult<AuSInt> ParseSInt(const AuString &str)
{
const char *didntFuckingAskTYVM { &str[str.size()] };
auto res = ParseSInt(str.c_str(), didntFuckingAskTYVM);
if (!res.has_value())
{
return {};
}
if (didntFuckingAskTYVM != &str[str.size()])
{
return {};
}
return res;
}
AUKN_SYM AuResult<AuSInt> ParseSInt(const char *begin)
{
const auto end = begin + ::strlen(begin);
const char *didntFuckingAskTYVM { end };
auto res = ParseSInt(begin, didntFuckingAskTYVM);
if (!res.has_value())
{
return {};
}
if (didntFuckingAskTYVM != end)
{
return {};
}
return res;
}
AUKN_SYM AuResult<AuUInt> ParseUInt(const AuString &str)
{
const char *didntFuckingAskTYVM { &str[str.size()] };
auto res = ParseUInt(str.c_str(), didntFuckingAskTYVM);
if (!res.has_value())
{
return {};
}
if (didntFuckingAskTYVM != &str[str.size()])
{
return {};
}
return res;
}
AUKN_SYM AuResult<AuUInt> ParseUInt(const char *begin)
{
const auto end = begin + ::strlen(begin);
const char *didntFuckingAskTYVM { end };
auto res = ParseUInt(begin, didntFuckingAskTYVM);
if (!res.has_value())
{
return {};
}
if (didntFuckingAskTYVM != end)
{
return {};
}
return res;
}
}