2020-09-13 21:32:55 -04:00
|
|
|
#pragma once
|
|
|
|
|
2020-11-21 12:52:38 -05:00
|
|
|
/*!
|
|
|
|
* @file BinaryWriter.h
|
|
|
|
* Write raw data like a stream.
|
|
|
|
*/
|
2020-09-06 12:45:31 -04:00
|
|
|
|
|
|
|
#include <cstdint>
|
|
|
|
#include <cstring>
|
2022-06-22 23:37:46 -04:00
|
|
|
#include <stdexcept>
|
|
|
|
#include <vector>
|
|
|
|
|
2022-02-08 19:02:47 -05:00
|
|
|
#include "common/util/Assert.h"
|
2022-07-05 20:38:13 -04:00
|
|
|
#include "common/util/FileUtil.h"
|
2020-09-06 12:45:31 -04:00
|
|
|
|
|
|
|
struct BinaryWriterRef {
|
|
|
|
size_t offset;
|
|
|
|
size_t write_size;
|
|
|
|
};
|
|
|
|
|
|
|
|
class BinaryWriter {
|
|
|
|
public:
|
|
|
|
BinaryWriter() = default;
|
|
|
|
|
2020-09-06 16:58:25 -04:00
|
|
|
template <typename T>
|
2020-09-06 12:45:31 -04:00
|
|
|
BinaryWriterRef add(const T& obj) {
|
|
|
|
auto orig_size = data.size();
|
|
|
|
data.resize(orig_size + sizeof(T));
|
|
|
|
memcpy(data.data() + orig_size, &obj, sizeof(T));
|
|
|
|
return {orig_size, sizeof(T)};
|
|
|
|
}
|
|
|
|
|
2020-09-06 16:58:25 -04:00
|
|
|
template <typename T>
|
2020-09-06 12:45:31 -04:00
|
|
|
void add_at_ref(const T& obj, const BinaryWriterRef& ref) {
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(ref.write_size == sizeof(T));
|
|
|
|
ASSERT(ref.offset + ref.write_size < get_size());
|
2020-09-06 12:45:31 -04:00
|
|
|
memcpy(data.data() + ref.offset, &obj, sizeof(T));
|
|
|
|
}
|
|
|
|
|
2020-09-06 16:58:25 -04:00
|
|
|
void add_str_len(const std::string& str, size_t len) { add_cstr_len(str.c_str(), len); }
|
2020-09-06 12:45:31 -04:00
|
|
|
|
|
|
|
void add_cstr_len(const char* str, size_t len) {
|
|
|
|
size_t i = 0;
|
2020-09-06 16:58:25 -04:00
|
|
|
while (*str) {
|
2020-09-06 12:45:31 -04:00
|
|
|
data.push_back(*str);
|
|
|
|
str++;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
2020-09-06 16:58:25 -04:00
|
|
|
while (i < len) {
|
2020-09-06 12:45:31 -04:00
|
|
|
data.push_back(0);
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BinaryWriterRef add_data(void* d, size_t len) {
|
|
|
|
auto orig_size = data.size();
|
|
|
|
data.resize(orig_size + len);
|
|
|
|
memcpy(data.data() + orig_size, d, len);
|
|
|
|
return {orig_size, len};
|
|
|
|
}
|
|
|
|
|
2020-09-06 16:58:25 -04:00
|
|
|
size_t get_size() { return data.size(); }
|
2020-09-06 12:45:31 -04:00
|
|
|
|
2020-09-06 16:58:25 -04:00
|
|
|
void* get_data() { return data.data(); }
|
2020-09-06 12:45:31 -04:00
|
|
|
|
2022-07-05 20:38:13 -04:00
|
|
|
void write_to_file(const fs::path& filename) {
|
|
|
|
auto fp = file_util::open_file(filename.string().c_str(), "wb");
|
2020-09-06 16:58:25 -04:00
|
|
|
if (!fp)
|
2022-06-29 23:32:46 -04:00
|
|
|
throw std::runtime_error("failed to open " + filename.string());
|
2020-09-06 16:58:25 -04:00
|
|
|
if (fwrite(get_data(), get_size(), 1, fp) != 1)
|
2022-06-29 23:32:46 -04:00
|
|
|
throw std::runtime_error("failed to write " + filename.string());
|
2020-09-06 12:45:31 -04:00
|
|
|
fclose(fp);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
std::vector<uint8_t> data;
|
|
|
|
};
|