CCash/fbe/user_model/fbe.cpp
EntireTwix 0130f3c971 🎉 FBE
2021-07-14 22:56:10 -07:00

401 lines
10 KiB
C++

// Automatically generated by the Fast Binary Encoding compiler, do not modify!
// https://github.com/chronoxor/FastBinaryEncoding
// Source: FBE
// Version: 1.7.0.0
#include "fbe.h"
namespace FBE {
std::string buffer_t::base64encode() const
{
const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
std::string result;
int val = 0;
int valb = -6;
for (auto c : _data)
{
val = (val << 8) + c;
valb += 8;
while (valb >= 0)
{
result.push_back(base64[(val >> valb) & 0x3F]);
valb -= 6;
}
}
if (valb > -6)
result.push_back(base64[((val << 8) >> (valb + 8)) & 0x3F]);
while (result.size() % 4)
result.push_back('=');
return result;
}
buffer_t buffer_t::base64decode(const std::string& str)
{
const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
buffer_t result;
std::vector<int> pattern(256, -1);
for (int i = 0; i < 64; ++i)
pattern[base64[i]] = i;
int val = 0;
int valb = -8;
for (auto c : str)
{
if (pattern[c] == -1)
break;
val = (val << 6) + pattern[c];
valb += 6;
if (valb >= 0)
{
result.push_back((uint8_t)((val >> valb) & 0xFF));
valb -= 8;
}
}
return result;
}
uint64_t utc()
{
#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
struct timespec timestamp;
if (clock_gettime(CLOCK_REALTIME, &timestamp) != 0)
throw std::runtime_error("Cannot get value of CLOCK_REALTIME timer!");
return (timestamp.tv_sec * 1000000000) + timestamp.tv_nsec;
#elif defined(_WIN32) || defined(_WIN64)
FILETIME ft;
GetSystemTimePreciseAsFileTime(&ft);
ULARGE_INTEGER result;
result.LowPart = ft.dwLowDateTime;
result.HighPart = ft.dwHighDateTime;
return (result.QuadPart - 116444736000000000ull) * 100;
#endif
}
uint8_t unhex(char ch)
{
if ((ch >= '0') && (ch <= '9'))
return ch - '0';
else if ((ch >= 'a') && (ch <= 'f'))
return 10 + ch - 'a';
else if ((ch >= 'A') && (ch <= 'F'))
return 10 + ch - 'A';
else
return 255;
}
uuid_t::uuid_t(const std::string& uuid)
{
char v1 = 0;
char v2 = 0;
bool pack = false;
size_t index = 0;
// Parse UUID string
for (auto ch : uuid)
{
if ((ch == '-') || (ch == '{') || (ch == '}'))
continue;
if (pack)
{
v2 = ch;
pack = false;
uint8_t ui1 = unhex(v1);
uint8_t ui2 = unhex(v2);
if ((ui1 > 15) || (ui2 > 15))
throw std::invalid_argument("Invalid UUID string: " + uuid);
_data[index++] = ui1 * 16 + ui2;
if (index >= 16)
break;
}
else
{
v1 = ch;
pack = true;
}
}
// Fill remaining data with zeros
for (; index < 16; ++index)
_data[index++] = 0;
}
std::string uuid_t::string() const
{
const char* digits = "0123456789abcdef";
std::string result(36, '0');
int index = 0;
for (auto value : _data)
{
result[index++] = digits[(value >> 4) & 0x0F];
result[index++] = digits[(value >> 0) & 0x0F];
if ((index == 8) || (index == 13) || (index == 18) || (index == 23))
result[index++] = '-';
}
return result;
}
uuid_t uuid_t::sequential()
{
uuid_t result;
#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
::uuid_t uuid;
uuid_generate_time(uuid);
result._data[0] = uuid[0];
result._data[1] = uuid[1];
result._data[2] = uuid[2];
result._data[3] = uuid[3];
result._data[4] = uuid[4];
result._data[5] = uuid[5];
result._data[6] = uuid[6];
result._data[7] = uuid[7];
result._data[8] = uuid[8];
result._data[9] = uuid[9];
result._data[10] = uuid[10];
result._data[11] = uuid[11];
result._data[12] = uuid[12];
result._data[13] = uuid[13];
result._data[14] = uuid[14];
result._data[15] = uuid[15];
#elif defined(_WIN32) || defined(_WIN64)
::UUID uuid;
if (UuidCreateSequential(&uuid) != RPC_S_OK)
throw std::runtime_error("Cannot generate sequential UUID!");
result._data[0] = (uuid.Data1 >> 24) & 0xFF;
result._data[1] = (uuid.Data1 >> 16) & 0xFF;
result._data[2] = (uuid.Data1 >> 8) & 0xFF;
result._data[3] = (uuid.Data1 >> 0) & 0xFF;
result._data[4] = (uuid.Data2 >> 8) & 0xFF;
result._data[5] = (uuid.Data2 >> 0) & 0xFF;
result._data[6] = (uuid.Data3 >> 8) & 0xFF;
result._data[7] = (uuid.Data3 >> 0) & 0xFF;
result._data[8] = uuid.Data4[0];
result._data[9] = uuid.Data4[1];
result._data[10] = uuid.Data4[2];
result._data[11] = uuid.Data4[3];
result._data[12] = uuid.Data4[4];
result._data[13] = uuid.Data4[5];
result._data[14] = uuid.Data4[6];
result._data[15] = uuid.Data4[7];
#endif
return result;
}
uuid_t uuid_t::random()
{
uuid_t result;
#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
::uuid_t uuid;
uuid_generate_random(uuid);
result._data[0] = uuid[0];
result._data[1] = uuid[1];
result._data[2] = uuid[2];
result._data[3] = uuid[3];
result._data[4] = uuid[4];
result._data[5] = uuid[5];
result._data[6] = uuid[6];
result._data[7] = uuid[7];
result._data[8] = uuid[8];
result._data[9] = uuid[9];
result._data[10] = uuid[10];
result._data[11] = uuid[11];
result._data[12] = uuid[12];
result._data[13] = uuid[13];
result._data[14] = uuid[14];
result._data[15] = uuid[15];
#elif defined(_WIN32) || defined(_WIN64)
::UUID uuid;
if (UuidCreate(&uuid) != RPC_S_OK)
throw std::runtime_error("Cannot generate random UUID!");
result._data[0] = (uuid.Data1 >> 24) & 0xFF;
result._data[1] = (uuid.Data1 >> 16) & 0xFF;
result._data[2] = (uuid.Data1 >> 8) & 0xFF;
result._data[3] = (uuid.Data1 >> 0) & 0xFF;
result._data[4] = (uuid.Data2 >> 8) & 0xFF;
result._data[5] = (uuid.Data2 >> 0) & 0xFF;
result._data[6] = (uuid.Data3 >> 8) & 0xFF;
result._data[7] = (uuid.Data3 >> 0) & 0xFF;
result._data[8] = uuid.Data4[0];
result._data[9] = uuid.Data4[1];
result._data[10] = uuid.Data4[2];
result._data[11] = uuid.Data4[3];
result._data[12] = uuid.Data4[4];
result._data[13] = uuid.Data4[5];
result._data[14] = uuid.Data4[6];
result._data[15] = uuid.Data4[7];
#endif
return result;
}
#if defined(LOGGING_PROTOCOL)
CppLogging::Record& operator<<(CppLogging::Record& record, const uuid_t& uuid)
{
const char* digits = "0123456789abcdef";
std::array<char, 36> result;
int index = 0;
for (auto value : uuid.data())
{
result[index++] = digits[(value >> 4) & 0x0F];
result[index++] = digits[(value >> 0) & 0x0F];
if ((index == 8) || (index == 13) || (index == 18) || (index == 23))
result[index++] = '-';
}
return record.StoreCustom(std::string_view(result.data(), result.size()));
}
#endif
void FBEBuffer::attach(const void* data, size_t size, size_t offset)
{
assert((data != nullptr) && "Invalid buffer!");
if (data == nullptr)
throw std::invalid_argument("Invalid buffer!");
assert((size > 0) && "Invalid size!");
if (size == 0)
throw std::invalid_argument("Invalid size!");
assert((offset <= size) && "Invalid offset!");
if (offset > size)
throw std::invalid_argument("Invalid offset!");
_data = (uint8_t*)data;
_capacity = 0;
_size = size;
_offset = offset;
}
void FBEBuffer::attach(const std::vector<uint8_t>& buffer, size_t offset)
{
assert((buffer.data() != nullptr) && "Invalid buffer!");
if (buffer.data() == nullptr)
throw std::invalid_argument("Invalid buffer!");
assert((buffer.size() > 0) && "Invalid size!");
if (buffer.size() == 0)
throw std::invalid_argument("Invalid size!");
assert((offset <= buffer.size()) && "Invalid offset!");
if (offset > buffer.size())
throw std::invalid_argument("Invalid offset!");
_data = (uint8_t*)buffer.data();
_capacity = 0;
_size = buffer.size();
_offset = offset;
}
void FBEBuffer::clone(const void* data, size_t size, size_t offset)
{
assert((offset <= size) && "Invalid offset!");
if (offset > size)
throw std::invalid_argument("Invalid offset!");
reserve(size);
std::memcpy(_data, data, size);
_capacity = size;
_size = size;
_offset = offset;
}
void FBEBuffer::clone(const std::vector<uint8_t>& buffer, size_t offset)
{
assert((offset <= buffer.size()) && "Invalid offset!");
if (offset > buffer.size())
throw std::invalid_argument("Invalid offset!");
size_t size = buffer.size();
reserve(size);
std::memcpy(_data, buffer.data(), size);
_capacity = size;
_size = size;
_offset = offset;
}
size_t FBEBuffer::allocate(size_t size)
{
size_t offset = _size;
// Calculate a new buffer size
size_t total = _size + size;
if (total <= _capacity)
{
_size = total;
return offset;
}
_capacity = std::max(total, 2 * _capacity);
uint8_t* data = (uint8_t*)std::malloc(_capacity);
std::memcpy(data, _data, _size);
std::free(_data);
_data = data;
_size = total;
return offset;
}
void FBEBuffer::remove(size_t offset, size_t size)
{
assert(((offset + size) <= _size) && "Invalid offset & size!");
if ((offset + size) > _size)
throw std::invalid_argument("Invalid offset & size!");
std::memcpy(_data + offset, _data + offset + size, _size - size - offset);
_size -= size;
if (_offset >= (offset + size))
_offset -= size;
else if (_offset >= offset)
{
_offset -= _offset - offset;
if (_offset > _size)
_offset = _size;
}
}
void FBEBuffer::reserve(size_t capacity)
{
if (capacity > _capacity)
{
_capacity = std::max(capacity, 2 * _capacity);
uint8_t* data = (uint8_t*)std::malloc(_capacity);
std::memcpy(data, _data, _size);
std::free(_data);
_data = data;
}
}
void FBEBuffer::resize(size_t size)
{
reserve(size);
_size = size;
if (_offset > _size)
_offset = _size;
}
void FBEBuffer::reset()
{
_size = 0;
_offset = 0;
}
} // namespace FBE