2023-05-11 16:50:11 -04:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
namespace demonware
|
|
|
|
{
|
|
|
|
class byte_buffer final
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
byte_buffer() = default;
|
|
|
|
|
|
|
|
explicit byte_buffer(std::string buffer) : buffer_(std::move(buffer))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool read_bool(bool* output);
|
|
|
|
bool read_byte(char* output);
|
|
|
|
bool read_ubyte(unsigned char* output);
|
|
|
|
bool read_int16(short* output);
|
|
|
|
bool read_uint16(unsigned short* output);
|
|
|
|
bool read_int32(int* output);
|
|
|
|
bool read_uint32(unsigned int* output);
|
|
|
|
bool read_int64(__int64* output);
|
|
|
|
bool read_uint64(unsigned __int64* output);
|
|
|
|
bool read_float(float* output);
|
|
|
|
bool read_string(char** output);
|
|
|
|
bool read_string(char* output, int length);
|
|
|
|
bool read_string(std::string* output);
|
|
|
|
bool read_blob(char** output, int* length);
|
|
|
|
bool read_blob(std::string* output);
|
|
|
|
bool read_struct(char** output, int* length);
|
|
|
|
bool read_struct(std::string* output);
|
|
|
|
bool read_data_type(char expected);
|
|
|
|
|
2023-11-10 16:52:20 -05:00
|
|
|
bool read_array_header(const unsigned char expected
|
|
|
|
, unsigned int* element_count, unsigned int* element_size);
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
bool read_array(const unsigned char expected, std::vector<T>* vec)
|
|
|
|
{
|
|
|
|
const auto using_types = this->is_using_data_types();
|
|
|
|
this->set_use_data_types(false);
|
|
|
|
|
|
|
|
uint32_t ItemCount, itemSize;
|
|
|
|
|
|
|
|
if (!this->read_array_header(expected, &ItemCount, &itemSize)) return false;
|
|
|
|
if (itemSize != sizeof(T)) return false;
|
|
|
|
|
|
|
|
for (size_t i = 0; i < ItemCount; i++)
|
|
|
|
{
|
|
|
|
T item{};
|
|
|
|
|
|
|
|
if (!this->read(sizeof(T), &item)) return false;
|
|
|
|
|
|
|
|
vec->push_back(item);
|
|
|
|
}
|
|
|
|
|
|
|
|
this->set_use_data_types(using_types);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
bool read_array(const unsigned char expected, std::map<T, T>* map)
|
|
|
|
{
|
|
|
|
const auto using_types = this->is_using_data_types();
|
|
|
|
this->set_use_data_types(false);
|
|
|
|
|
|
|
|
uint32_t ItemCount, itemSize;
|
|
|
|
|
|
|
|
if (!this->read_array_header(expected, &ItemCount, &itemSize)) return false;
|
|
|
|
if (itemSize != sizeof(T)) return false;
|
|
|
|
|
|
|
|
for (size_t i = 0; i < ItemCount / 2; i++)
|
|
|
|
{
|
|
|
|
T key{}, value{};
|
|
|
|
|
|
|
|
if (!this->read(sizeof(T), &key)
|
|
|
|
|| !this->read(sizeof(T), &value)
|
|
|
|
) return false;
|
|
|
|
|
|
|
|
map->insert({ key, value });
|
|
|
|
}
|
|
|
|
|
|
|
|
this->set_use_data_types(using_types);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-05-11 16:50:11 -04:00
|
|
|
|
|
|
|
bool write_bool(bool data);
|
|
|
|
bool write_byte(char data);
|
|
|
|
bool write_ubyte(unsigned char data);
|
|
|
|
bool write_int16(short data);
|
|
|
|
bool write_uint16(unsigned short data);
|
|
|
|
bool write_int32(int data);
|
|
|
|
bool write_uint32(unsigned int data);
|
|
|
|
bool write_int64(__int64 data);
|
|
|
|
bool write_uint64(unsigned __int64 data);
|
|
|
|
bool write_data_type(char data);
|
|
|
|
bool write_float(float data);
|
|
|
|
bool write_string(const char* data);
|
|
|
|
bool write_string(const std::string& data);
|
|
|
|
bool write_blob(const char* data, int length);
|
|
|
|
bool write_blob(const std::string& data);
|
|
|
|
bool write_struct(const char* data, int length);
|
|
|
|
bool write_struct(const std::string& data);
|
|
|
|
|
2023-11-10 16:52:20 -05:00
|
|
|
bool write_array_header(const unsigned char type,
|
|
|
|
const unsigned int element_count, const unsigned int element_size);
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
bool write_array(const unsigned char type, const std::vector<T>& vec)
|
|
|
|
{
|
|
|
|
const auto using_types = this->is_using_data_types();
|
|
|
|
this->set_use_data_types(false);
|
|
|
|
|
|
|
|
auto result = write_array_header(type, vec.size(), sizeof(T));
|
|
|
|
|
|
|
|
for (size_t i = 0; i < vec.size(); i++)
|
|
|
|
{
|
|
|
|
result &= this->write(sizeof(T), &vec[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
this->set_use_data_types(using_types);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
bool write_array(const unsigned char type, const std::map<T, T>& map)
|
|
|
|
{
|
|
|
|
const auto using_types = this->is_using_data_types();
|
|
|
|
this->set_use_data_types(false);
|
|
|
|
|
|
|
|
auto result = write_array_header(type, map.size() * 2, sizeof(T));
|
|
|
|
|
|
|
|
for (const auto& item : map)
|
|
|
|
{
|
|
|
|
result &= this->write(sizeof(T), &item.first);
|
|
|
|
result &= this->write(sizeof(T), &item.second);
|
|
|
|
}
|
|
|
|
|
|
|
|
this->set_use_data_types(using_types);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2023-05-11 16:50:11 -04:00
|
|
|
|
|
|
|
bool read(int bytes, void* output);
|
|
|
|
bool write(int bytes, const void* data);
|
|
|
|
bool write(const std::string& data);
|
|
|
|
|
|
|
|
void set_use_data_types(bool use_data_types);
|
|
|
|
size_t size() const;
|
|
|
|
|
|
|
|
bool is_using_data_types() const;
|
|
|
|
|
|
|
|
std::string& get_buffer();
|
|
|
|
std::string get_remaining();
|
|
|
|
|
|
|
|
bool has_more_data() const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
std::string buffer_;
|
|
|
|
size_t current_byte_ = 0;
|
|
|
|
bool use_data_types_ = true;
|
|
|
|
};
|
|
|
|
}
|