lib: implement write functions for RIFF classes

This commit is contained in:
itsmattkc 2022-07-11 14:18:56 -07:00
parent 6f8d3d500c
commit 4d05dc8ac8
5 changed files with 97 additions and 9 deletions

View file

@ -8,9 +8,10 @@
namespace si {
Chunk::Chunk()
Chunk::Chunk(uint32_t id) :
id_(id),
offset_(0)
{
id_ = 0;
}
Chunk::~Chunk()
@ -89,6 +90,40 @@ bool Chunk::Read(std::ifstream &f, uint32_t &version, uint32_t &alignment)
return true;
}
bool Chunk::Write(std::ofstream &f, const uint32_t &version) const
{
// Write 4-byte ID
f.write((const char *) &id_, sizeof(id_));
// Write placeholder for size and store position so we can come back later
uint32_t chunk_size = 0;
std::ios::pos_type size_pos = f.tellp();
f.write((const char *) &chunk_size, sizeof(chunk_size));
if (RIFF *writer = GetReaderFromType(type())) {
writer->Write(f, data_, version);
delete writer;
}
for (Children::const_iterator it=GetChildren().begin(); it!=GetChildren().end(); it++) {
static_cast<Chunk*>(*it)->Write(f, version);
}
// Backtrack and write chunk size
chunk_size = uint32_t(f.tellp()) - (uint32_t(size_pos) + sizeof(uint32_t));
f.seekp(size_pos);
f.write((const char *) &chunk_size, sizeof(chunk_size));
f.seekp(0, std::ios::end);
// Byte align to 2
if (chunk_size%2 == 1) {
const char nothing = 0;
f.write(&nothing, 1);
}
return true;
}
RIFF *Chunk::GetReaderFromType(Type type)
{
switch (type) {
@ -108,6 +143,8 @@ RIFF *Chunk::GetReaderFromType(Type type)
return new pad_();
case TYPE_MxOb:
return new MxOb();
case TYPE_MxDa:
break;
}
return NULL;
@ -122,6 +159,23 @@ void Chunk::Clear()
DeleteChildren();
}
bool Chunk::Write(const std::string &f)
{
return Write(f.c_str());
}
bool Chunk::Write(const char *f)
{
std::ofstream file(f, std::ios::out | std::ios::binary);
if (!file.is_open() || !file.good()) {
return false;
}
uint32_t version = 0;
return Write(file, version);
}
const char *Chunk::GetTypeDescription(Type type)
{
switch (type) {
@ -141,6 +195,8 @@ const char *Chunk::GetTypeDescription(Type type)
return "Padding";
case TYPE_MxOb:
return "Streamable Object";
case TYPE_MxDa:
return "Data";
}
return "Unknown";

View file

@ -24,16 +24,20 @@ public:
TYPE_MxCh = 0x6843784d,
TYPE_MxOf = 0x664f784d,
TYPE_MxOb = 0x624f784d,
TYPE_MxDa = 0x6144784d,
TYPE_pad_ = 0x20646170
};
LIBWEAVER_EXPORT Chunk();
LIBWEAVER_EXPORT Chunk(uint32_t id = 0);
virtual LIBWEAVER_EXPORT ~Chunk();
LIBWEAVER_EXPORT bool Read(const std::string &f);
LIBWEAVER_EXPORT bool Read(const char *f);
LIBWEAVER_EXPORT void Clear();
LIBWEAVER_EXPORT bool Write(const std::string &f);
LIBWEAVER_EXPORT bool Write(const char *f);
LIBWEAVER_EXPORT Type type() const { return static_cast<Type>(id_); }
LIBWEAVER_EXPORT const uint32_t &id() const { return id_; }
LIBWEAVER_EXPORT const uint32_t &offset() const { return offset_; }
@ -52,6 +56,7 @@ public:
private:
bool Read(std::ifstream &f, uint32_t &version, uint32_t &alignment);
bool Write(std::ofstream &f, const uint32_t &version) const;
static RIFF *GetReaderFromType(Type type);

View file

@ -78,6 +78,7 @@ void WriteString(std::ofstream &os, const std::string &d)
const char *s = &d[0];
while ((*s) != 0) {
os.write(s, 1);
s++;
}
}
@ -186,15 +187,19 @@ void MxOf::Write(std::ofstream &os, const DataMap &data, uint32_t version)
void pad_::Read(std::ifstream &is, DataMap &data, uint32_t version, uint32_t size)
{
data["Size"] = size;
is.seekg(size, std::ios::cur);
}
void pad_::WritePadding(std::ofstream &os, size_t size)
void pad_::Write(std::ofstream &os, const DataMap &data, uint32_t version)
{
bytearray b;
b.resize(size);
b.fill(0xCD);
WriteBytes(os, b);
uint32_t sz = data.at("Size").toU32();
if (sz > 0) {
bytearray b;
b.resize(sz);
b.fill(0xCD);
WriteBytes(os, b);
}
}
const char *MxOb::GetTypeName(Type type)

View file

@ -18,6 +18,10 @@ namespace si {
class RIFF
{
public:
enum {
OMNI = 0x494e4d4f
};
virtual ~RIFF(){}
virtual void Read(std::ifstream &is, DataMap &data, uint32_t version, uint32_t size);
@ -81,6 +85,13 @@ public:
class MxCh : public RIFF
{
public:
enum Flag {
FLAG_SPLIT = 0x16,
FLAG_END = 0x2
};
static const uint32_t HEADER_SIZE = 14;
virtual void Read(std::ifstream &is, DataMap &data, uint32_t version, uint32_t size);
virtual void Write(std::ofstream &os, const DataMap &data, uint32_t version);
};
@ -110,7 +121,7 @@ class pad_ : public RIFF
{
public:
virtual void Read(std::ifstream &is, DataMap &data, uint32_t version, uint32_t size);
void WritePadding(std::ofstream &os, size_t size);
virtual void Write(std::ofstream &os, const DataMap &data, uint32_t version);
};
/**
@ -146,6 +157,10 @@ class MxOb : public RIFF
public:
enum Type
{
/// Not an MxOb type, this is our identifier for an object that is in the TOC but doesn't
/// actually exist
Null = -1,
/// Video
Video = 0x03,
@ -202,6 +217,9 @@ public:
/// Bitmap image
STL = 0x4C545320,
/// FLIC animation
FLC = 0x434c4620,
};
// FIXME: sitypes.h probably won't be part of the public API, so this should

View file

@ -26,6 +26,10 @@ class bytearray : public std::vector<char>
{
public:
bytearray(){}
bytearray(size_t size)
{
resize(size);
}
template <typename T>
T *cast() { return reinterpret_cast<T*>(data()); }