mirror of https://github.com/oxen-io/oxen-core.git
180 lines
4.8 KiB
C++
180 lines
4.8 KiB
C++
#include "epee/storages/parserse_base_utils.h"
|
|
#undef OXEN_DEFAULT_LOG_CATEGORY
|
|
#define OXEN_DEFAULT_LOG_CATEGORY "serialization"
|
|
|
|
|
|
#include <algorithm>
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <oxenc/hex.h>
|
|
#include "epee/misc_log_ex.h"
|
|
|
|
namespace epee::misc_utils::parse {
|
|
|
|
/*
|
|
|
|
\b Backspace (ascii code 08)
|
|
\f Form feed (ascii code 0C)
|
|
\n New line
|
|
\r Carriage return
|
|
\t Tab
|
|
\v Vertical tab
|
|
\' Apostrophe or single quote
|
|
\" Double quote
|
|
\\ Backslash character
|
|
|
|
*/
|
|
void match_string2(const char*& star_end_string, const char* buf_end, std::string& val)
|
|
{
|
|
bool escape_mode = false;
|
|
auto it = star_end_string;
|
|
++it;
|
|
auto fi = it;
|
|
while (fi != buf_end && ((detail::lut[(uint8_t)*fi] & 32)) == 0)
|
|
++fi;
|
|
val.assign(it, fi);
|
|
val.reserve(std::distance(star_end_string, buf_end));
|
|
it = fi;
|
|
for(;it != buf_end;it++)
|
|
{
|
|
if(escape_mode/*prev_ch == '\\'*/)
|
|
{
|
|
switch(*it)
|
|
{
|
|
case 'b': //Backspace (ascii code 08)
|
|
val.push_back(0x08);break;
|
|
case 'f': //Form feed (ascii code 0C)
|
|
val.push_back(0x0C);break;
|
|
case 'n': //New line
|
|
val.push_back('\n');break;
|
|
case 'r': //Carriage return
|
|
val.push_back('\r');break;
|
|
case 't': //Tab
|
|
val.push_back('\t');break;
|
|
case 'v': //Vertical tab
|
|
val.push_back('\v');break;
|
|
case '\'': //Apostrophe or single quote
|
|
val.push_back('\'');break;
|
|
case '"': //Double quote
|
|
val.push_back('"');break;
|
|
case '\\': //Backslash character
|
|
val.push_back('\\');break;
|
|
case '/': //Slash character
|
|
val.push_back('/');break;
|
|
case 'u': //Unicode code point
|
|
if (buf_end - it < 4)
|
|
{
|
|
ASSERT_MES_AND_THROW("Invalid Unicode escape sequence");
|
|
}
|
|
else
|
|
{
|
|
uint32_t dst = 0;
|
|
for (int i = 0; i < 4; ++i)
|
|
{
|
|
const auto c = *++it;
|
|
CHECK_AND_ASSERT_THROW_MES(oxenc::is_hex_digit(c), "Bad Unicode encoding: " + std::to_string(c));
|
|
dst = dst << 4 | oxenc::from_hex_digit(c);
|
|
}
|
|
// encode as UTF-8
|
|
if (dst <= 0x7f)
|
|
{
|
|
val.push_back(dst);
|
|
}
|
|
else if (dst <= 0x7ff)
|
|
{
|
|
val.push_back(0xc0 | (dst >> 6));
|
|
val.push_back(0x80 | (dst & 0x3f));
|
|
}
|
|
else if (dst <= 0xffff)
|
|
{
|
|
val.push_back(0xe0 | (dst >> 12));
|
|
val.push_back(0x80 | ((dst >> 6) & 0x3f));
|
|
val.push_back(0x80 | (dst & 0x3f));
|
|
}
|
|
else
|
|
{
|
|
ASSERT_MES_AND_THROW("Unicode code point is out or range");
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
val.push_back(*it);
|
|
LOG_PRINT_L0("Unknown escape sequence :\"\\" << *it << "\"");
|
|
}
|
|
escape_mode = false;
|
|
}else if(*it == '"')
|
|
{
|
|
star_end_string = it;
|
|
return;
|
|
}else if(*it == '\\')
|
|
{
|
|
escape_mode = true;
|
|
}
|
|
else
|
|
{
|
|
val.push_back(*it);
|
|
}
|
|
}
|
|
ASSERT_MES_AND_THROW("Failed to match string in json entry: " << std::string(star_end_string, buf_end));
|
|
}
|
|
// The only conclusive thing that can be said about this function is that it does indeed
|
|
// closely match a "number 2". 💩
|
|
void match_number2(const char*& star_end_string, const char* buf_end, std::string_view& val, bool& is_float_val, bool& is_negative_val)
|
|
{
|
|
val = {};
|
|
uint8_t float_flag = 0;
|
|
is_negative_val = false;
|
|
is_float_val = false;
|
|
size_t chars = 0;
|
|
auto it = star_end_string;
|
|
if (it != buf_end && *it == '-')
|
|
{
|
|
is_negative_val = true;
|
|
++chars;
|
|
++it;
|
|
}
|
|
for(;it != buf_end;it++)
|
|
{
|
|
const uint8_t flags = detail::lut[(uint8_t)*it];
|
|
if (flags & 16)
|
|
{
|
|
float_flag |= flags;
|
|
++chars;
|
|
}
|
|
else
|
|
{
|
|
val = std::string_view(&*star_end_string, chars);
|
|
if(val.size())
|
|
{
|
|
star_end_string = --it;
|
|
is_float_val = !!(float_flag & 2);
|
|
return;
|
|
}
|
|
else
|
|
ASSERT_MES_AND_THROW("wrong number in json entry: " << std::string(star_end_string, buf_end));
|
|
}
|
|
}
|
|
ASSERT_MES_AND_THROW("wrong number in json entry: " << std::string(star_end_string, buf_end));
|
|
}
|
|
void match_word2(const char*& star_end_string, const char* buf_end, std::string_view& val)
|
|
{
|
|
val = {};
|
|
|
|
for(auto it = star_end_string;it != buf_end;it++)
|
|
{
|
|
if (!(detail::lut[(uint8_t)*it] & 4))
|
|
{
|
|
val = std::string_view(&*star_end_string, std::distance(star_end_string, it));
|
|
if(val.size())
|
|
{
|
|
star_end_string = --it;
|
|
return;
|
|
}else
|
|
ASSERT_MES_AND_THROW("failed to match word number in json entry: " << std::string(star_end_string, buf_end));
|
|
}
|
|
}
|
|
ASSERT_MES_AND_THROW("failed to match word number in json entry: " << std::string(star_end_string, buf_end));
|
|
}
|
|
|
|
} // namespace epee::misc_utils::parse
|