#pragma once
#include "ioBase.hpp"
#include "fwd.hpp"
NAMESPACE_SOUP
{
class Writer : public ioBase<false>
{
public:
using ioBase::ioBase;
bool skip(size_t len) noexcept
{
uint8_t v = 0;
while (len--)
{
u8(v);
}
return true;
}
bool u64_dyn(const uint64_t& v) noexcept;
bool i64_dyn(const int64_t& v) noexcept;
bool u64_dyn_v2(const uint64_t& v) noexcept;
bool i64_dyn_v2(const int64_t& v) noexcept;
template <typename Int>
bool om(const Int& v) noexcept
{
bool ret = true;
auto chunks = 0;
{
Int val = v;
while (true)
{
val >>= 7;
if (!val)
{
break;
}
++chunks;
}
}
do
{
uint8_t byte = ((v >> (chunks * 7)) & 0x7F);
if (chunks != 0)
{
byte |= 0x80;
}
ret &= u8(byte);
} while (chunks--);
return ret;
}
template <typename Int>
bool oml(const Int& v) noexcept
{
bool ret = true;
Int in = v;
while (true)
{
uint8_t byte = (in & 0x7F);
in >>= 7;
if (in == 0)
{
ret &= u8(byte);
break;
}
byte |= 0x80;
ret &= u8(byte);
}
return ret;
}
template <typename Int>
bool soml(const Int& v) noexcept
{
bool ret = true;
Int in = v;
while (true)
{
uint8_t byte = (in & 0x7F);
in >>= 7;
if ((byte & 0x40) ? (in == -1) : (in == 0))
{
ret &= u8(byte);
break;
}
byte |= 0x80;
ret &= u8(byte);
}
return ret;
}
bool mysql_lenenc(const uint64_t& v) noexcept;
bool str_nt(const std::string& v) noexcept
{
bool ret = raw(const_cast<char*>(v.data()), v.size());
uint8_t term = 0;
ret &= u8(term);
return ret;
}
template <typename T>
bool str_lp(const std::string& v, const T max_len = -1) noexcept
{
size_t len = v.size();
SOUP_IF_LIKELY (len <= max_len)
{
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4267)
#endif
auto tl = static_cast<T>(len);
#ifdef _MSC_VER
#pragma warning(pop)
#endif
bool ret = ser<T>(tl);
ret &= raw(const_cast<char*>(v.data()), v.size());
return ret;
}
return false;
}
bool str_lp_u64_dyn(const std::string& v) noexcept
{
bool ret = u64_dyn(v.size());
ret &= raw(const_cast<char*>(v.data()), v.size());
return ret;
}
bool str_lp_mysql(const std::string& v) noexcept
{
bool ret = mysql_lenenc(v.size());
ret &= raw(const_cast<char*>(v.data()), v.size());
return ret;
}
bool str(size_t len, const std::string& v) noexcept
{
size_t pad = (len - v.size());
bool ret = raw(const_cast<char*>(v.data()), v.size());
ret &= skip(pad);
return ret;
}
bool str(size_t len, const char* v) noexcept
{
return raw(const_cast<char*>(v), len);
}
bool vec_u8_u8(std::vector<uint8_t>& v) noexcept
{
SOUP_IF_UNLIKELY (v.size() > 0xFF)
{
return false;
}
bool ret = true;
auto len = (uint8_t)v.size();
ret &= u8(len);
for (auto& entry : v)
{
ret &= u8(entry);
}
return ret;
}
bool vec_u16be_bl_u16be(std::vector<uint16_t>& v) noexcept
{
size_t bl = (v.size() * sizeof(uint16_t));
SOUP_IF_UNLIKELY (bl > 0xFFFF)
{
return false;
}
bool ret = true;
auto bl_u16 = (uint16_t)bl;
ret &= ioBase::u16be(bl_u16);
for (auto& entry : v)
{
ret &= ioBase::u16be(entry);
}
return ret;
}
bool vec_str_nt_u64_dyn(std::vector<std::string>& v) noexcept
{
bool ret = true;
uint64_t len = v.size();
ret &= u64_dyn(len);
for (auto& entry : v)
{
ret &= str_nt(entry);
}
return ret;
}
bool vec_str_lp_u24be_bl_u24be(std::vector<std::string>& v) noexcept
{
size_t bl = (v.size() * 3);
for (const auto& entry : v)
{
bl += entry.size();
}
SOUP_IF_UNLIKELY (bl > 0xFFFFFF)
{
return false;
}
bool ret = true;
auto bl_u32 = (uint32_t)bl;
ret &= ioBase::u24be(bl_u32);
for (auto& entry : v)
{
ret &= str_lp<u24be_t>(entry);
}
return ret;
}
};
}