#pragma once
#include <cstring>
#include <ostream>
#include <stdexcept>
#include <string>
#include <vector>
#include <whiteout/common_types.h>
#include "concepts.h"
namespace whiteout {
namespace common {
class BinaryWriter {
public:
BinaryWriter(std::ostream& outputStream) : file(outputStream) {
}
~BinaryWriter() {
}
template <BinaryBlob T>
void write(const T& value) {
file.write(reinterpret_cast<const char*>(std::addressof(value)), sizeof(T));
}
template <TrivialContiguousRange C>
void write(const C& c) {
using T = std::remove_cv_t<std::remove_pointer_t<decltype(std::data(c))>>;
file.write(reinterpret_cast<const char*>(std::data(c)), std::size(c) * sizeof(T));
}
void writeBytes(const char* buffer, u32 count) {
file.write(buffer, count);
}
void writeString(const std::string& str, u32 size) {
std::vector<char> buffer(size, '\0');
size_t copySize = std::min(static_cast<size_t>(size), str.size());
std::memcpy(buffer.data(), str.c_str(), copySize);
file.write(buffer.data(), size);
}
void writeString(const std::string& str) {
file.write(str.c_str(), str.size());
}
void writeZString(const std::string& str) {
file.write(str.c_str(), str.size());
write<u8>(0); }
u32 getPosition() {
return static_cast<u32>(file.tellp());
}
void setPosition(u32 pos) {
file.seekp(pos, std::ios::beg);
}
void writePadding(u32 count, u8 fillByte = 0) {
for (u32 i = 0; i < count; i++) {
write<u8>(fillByte);
}
}
void AlignTo(u32 alignment, u8 fillByte = 0) {
u32 currentPos = getPosition();
u32 padding = (alignment - (currentPos % alignment)) % alignment;
writePadding(padding, fillByte);
}
bool isValid() const {
return file.good();
}
private:
std::ostream& file;
};
} }