various ESMWriter fixes

actorid
Marc Zinnschlag 11 years ago
parent 8326ac9b6f
commit bcd36bd378

@ -2,185 +2,182 @@
#include <cassert>
#include <fstream>
#include <iostream>
bool count = true;
#include <stdexcept>
namespace ESM
{
ESMWriter::ESMWriter() : mRecordCount (0), mCounting (false) {}
int ESMWriter::getVersion()
{
return mHeader.mData.version;
}
void ESMWriter::setVersion(int ver)
{
mHeader.mData.version = ver;
}
void ESMWriter::setAuthor(const std::string& auth)
{
mHeader.mData.author.assign (auth);
}
void ESMWriter::setDescription(const std::string& desc)
{
mHeader.mData.desc.assign (desc);
}
unsigned int ESMWriter::getVersion() const
{
return mHeader.mData.version;
}
void ESMWriter::setRecordCount (int count)
{
mHeader.mData.records = count;
}
void ESMWriter::setVersion(unsigned int ver)
{
mHeader.mData.version = ver;
}
void ESMWriter::setFormat (int format)
{
mHeader.mFormat = format;
}
void ESMWriter::setAuthor(const std::string& auth)
{
mHeader.mData.author.assign (auth);
}
void ESMWriter::addMaster(const std::string& name, uint64_t size)
{
Header::MasterData d;
d.name = name;
d.size = size;
mHeader.mMaster.push_back(d);
}
void ESMWriter::setDescription(const std::string& desc)
{
mHeader.mData.desc.assign (desc);
}
void ESMWriter::save(const std::string& file)
{
std::ofstream fs(file.c_str(), std::ios_base::out | std::ios_base::trunc);
save(fs);
}
void ESMWriter::setRecordCount (int count)
{
mHeader.mData.records = count;
}
void ESMWriter::save(std::ostream& file)
{
m_recordCount = 0;
m_stream = &file;
void ESMWriter::setFormat (int format)
{
mHeader.mFormat = format;
}
startRecord("TES3", 0);
void ESMWriter::addMaster(const std::string& name, uint64_t size)
{
Header::MasterData d;
d.name = name;
d.size = size;
mHeader.mMaster.push_back(d);
}
mHeader.save (*this);
void ESMWriter::save(const std::string& file)
{
std::ofstream fs(file.c_str(), std::ios_base::out | std::ios_base::trunc);
save(fs);
}
endRecord("TES3");
}
void ESMWriter::save(std::ostream& file)
{
mRecordCount = 0;
mRecords.clear();
mStream = &file;
void ESMWriter::close()
{
m_stream->flush();
startRecord("TES3", 0);
if (!m_records.empty())
throw "Unclosed record remaining";
}
mHeader.save (*this);
void ESMWriter::startRecord(const std::string& name, uint32_t flags)
{
m_recordCount++;
writeName(name);
RecordData rec;
rec.name = name;
rec.position = m_stream->tellp();
rec.size = 0;
writeT<int>(0); // Size goes here
writeT<int>(0); // Unused header?
writeT(flags);
m_records.push_back(rec);
assert(m_records.back().size == 0);
}
endRecord("TES3");
}
void ESMWriter::startSubRecord(const std::string& name)
{
writeName(name);
RecordData rec;
rec.name = name;
rec.position = m_stream->tellp();
rec.size = 0;
writeT<int>(0); // Size goes here
m_records.push_back(rec);
assert(m_records.back().size == 0);
}
void ESMWriter::close()
{
if (!mRecords.empty())
throw std::runtime_error ("Unclosed record remaining");
}
void ESMWriter::endRecord(const std::string& name)
{
RecordData rec = m_records.back();
assert(rec.name == name);
m_records.pop_back();
void ESMWriter::startRecord(const std::string& name, uint32_t flags)
{
mRecordCount++;
writeName(name);
RecordData rec;
rec.name = name;
rec.position = mStream->tellp();
rec.size = 0;
writeT<int>(0); // Size goes here
writeT<int>(0); // Unused header?
writeT(flags);
mRecords.push_back(rec);
assert(mRecords.back().size == 0);
}
m_stream->seekp(rec.position);
void ESMWriter::startSubRecord(const std::string& name)
{
writeName(name);
RecordData rec;
rec.name = name;
rec.position = mStream->tellp();
rec.size = 0;
writeT<int>(0); // Size goes here
mRecords.push_back(rec);
assert(mRecords.back().size == 0);
}
count = false;
write((char*)&rec.size, sizeof(int));
count = true;
void ESMWriter::endRecord(const std::string& name)
{
RecordData rec = mRecords.back();
assert(rec.name == name);
mRecords.pop_back();
m_stream->seekp(0, std::ios::end);
mStream->seekp(rec.position);
}
mCounting = false;
write (reinterpret_cast<const char*> (&rec.size), sizeof(int));
mCounting = true;
void ESMWriter::writeHNString(const std::string& name, const std::string& data)
{
startSubRecord(name);
writeHString(data);
endRecord(name);
}
mStream->seekp(0, std::ios::end);
void ESMWriter::writeHNString(const std::string& name, const std::string& data, size_t size)
{
assert(data.size() <= size);
startSubRecord(name);
writeHString(data);
}
if (data.size() < size)
void ESMWriter::writeHNString(const std::string& name, const std::string& data)
{
for (size_t i = data.size(); i < size; ++i)
write("\0",1);
startSubRecord(name);
writeHString(data);
endRecord(name);
}
endRecord(name);
}
void ESMWriter::writeHString(const std::string& data)
{
if (data.size() == 0)
write("\0", 1);
else
void ESMWriter::writeHNString(const std::string& name, const std::string& data, size_t size)
{
// Convert to UTF8 and return
std::string ascii = m_encoder->getLegacyEnc(data);
assert(data.size() <= size);
startSubRecord(name);
writeHString(data);
if (data.size() < size)
{
for (size_t i = data.size(); i < size; ++i)
write("\0",1);
}
write(ascii.c_str(), ascii.size());
endRecord(name);
}
}
void ESMWriter::writeHCString(const std::string& data)
{
writeHString(data);
if (data.size() > 0 && data[data.size()-1] != '\0')
write("\0", 1);
}
void ESMWriter::writeHString(const std::string& data)
{
if (data.size() == 0)
write("\0", 1);
else
{
// Convert to UTF8 and return
std::string ascii = mEncoder->getLegacyEnc(data);
write(ascii.c_str(), ascii.size());
}
}
void ESMWriter::writeName(const std::string& name)
{
assert((name.size() == 4 && name[3] != '\0'));
write(name.c_str(), name.size());
}
void ESMWriter::writeHCString(const std::string& data)
{
writeHString(data);
if (data.size() > 0 && data[data.size()-1] != '\0')
write("\0", 1);
}
void ESMWriter::write(const char* data, size_t size)
{
if (count && !m_records.empty())
void ESMWriter::writeName(const std::string& name)
{
for (std::list<RecordData>::iterator it = m_records.begin(); it != m_records.end(); ++it)
it->size += size;
assert((name.size() == 4 && name[3] != '\0'));
write(name.c_str(), name.size());
}
m_stream->write(data, size);
}
void ESMWriter::write(const char* data, size_t size)
{
if (mCounting && !mRecords.empty())
{
for (std::list<RecordData>::iterator it = mRecords.begin(); it != mRecords.end(); ++it)
it->size += size;
}
void ESMWriter::setEncoder(ToUTF8::Utf8Encoder* encoder)
{
m_encoder = encoder;
}
mStream->write(data, size);
}
void ESMWriter::setEncoder(ToUTF8::Utf8Encoder* encoder)
{
mEncoder = encoder;
}
}

@ -13,92 +13,101 @@ namespace ESM {
class ESMWriter
{
struct RecordData
{
std::string name;
std::streampos position;
size_t size;
struct RecordData
{
std::string name;
std::streampos position;
size_t size;
};
public:
ESMWriter();
unsigned int getVersion() const;
void setVersion(unsigned int ver = 0x3fa66666);
void setEncoder(ToUTF8::Utf8Encoder *encoding);
void setAuthor(const std::string& author);
void setDescription(const std::string& desc);
void setRecordCount (int count);
void setFormat (int format);
void addMaster(const std::string& name, uint64_t size);
void save(const std::string& file);
///< Start saving a file by writing the TES3 header.
void save(std::ostream& file);
///< Start saving a file by writing the TES3 header.
void close();
///< \note Does not close the stream.
void writeHNString(const std::string& name, const std::string& data);
void writeHNString(const std::string& name, const std::string& data, size_t size);
void writeHNCString(const std::string& name, const std::string& data)
{
startSubRecord(name);
writeHCString(data);
endRecord(name);
}
void writeHNOString(const std::string& name, const std::string& data)
{
if (!data.empty())
writeHNString(name, data);
}
void writeHNOCString(const std::string& name, const std::string& data)
{
if (!data.empty())
writeHNCString(name, data);
}
template<typename T>
void writeHNT(const std::string& name, const T& data)
{
startSubRecord(name);
writeT(data);
endRecord(name);
}
template<typename T>
void writeHNT(const std::string& name, const T& data, int size)
{
startSubRecord(name);
writeT(data, size);
endRecord(name);
}
template<typename T>
void writeT(const T& data)
{
write((char*)&data, sizeof(T));
}
template<typename T>
void writeT(const T& data, size_t size)
{
write((char*)&data, size);
}
void startRecord(const std::string& name, uint32_t flags);
void startSubRecord(const std::string& name);
void endRecord(const std::string& name);
void writeHString(const std::string& data);
void writeHCString(const std::string& data);
void writeName(const std::string& data);
void write(const char* data, size_t size);
private:
std::list<RecordData> mRecords;
std::ostream* mStream;
std::streampos mHeaderPos;
ToUTF8::Utf8Encoder* mEncoder;
int mRecordCount;
bool mCounting;
Header mHeader;
};
public:
int getVersion();
void setVersion(int ver);
void setEncoder(ToUTF8::Utf8Encoder *encoding); // Write strings as UTF-8?
void setAuthor(const std::string& author);
void setDescription(const std::string& desc);
void setRecordCount (int count);
void setFormat (int format);
void addMaster(const std::string& name, uint64_t size);
void save(const std::string& file);
void save(std::ostream& file);
void close();
void writeHNString(const std::string& name, const std::string& data);
void writeHNString(const std::string& name, const std::string& data, size_t size);
void writeHNCString(const std::string& name, const std::string& data)
{
startSubRecord(name);
writeHCString(data);
endRecord(name);
}
void writeHNOString(const std::string& name, const std::string& data)
{
if (!data.empty())
writeHNString(name, data);
}
void writeHNOCString(const std::string& name, const std::string& data)
{
if (!data.empty())
writeHNCString(name, data);
}
template<typename T>
void writeHNT(const std::string& name, const T& data)
{
startSubRecord(name);
writeT(data);
endRecord(name);
}
template<typename T>
void writeHNT(const std::string& name, const T& data, int size)
{
startSubRecord(name);
writeT(data, size);
endRecord(name);
}
template<typename T>
void writeT(const T& data)
{
write((char*)&data, sizeof(T));
}
template<typename T>
void writeT(const T& data, size_t size)
{
write((char*)&data, size);
}
void startRecord(const std::string& name, uint32_t flags);
void startSubRecord(const std::string& name);
void endRecord(const std::string& name);
void writeHString(const std::string& data);
void writeHCString(const std::string& data);
void writeName(const std::string& data);
void write(const char* data, size_t size);
private:
std::list<RecordData> m_records;
std::ostream* m_stream;
std::streampos m_headerPos;
ToUTF8::Utf8Encoder* m_encoder;
int m_recordCount;
Header mHeader;
};
}
#endif

@ -24,7 +24,7 @@ namespace ESM
versions are 1.2 and 1.3. These correspond to:
1.2 = 0x3f99999a and 1.3 = 0x3fa66666
*/
int version;
unsigned int version;
int type; // 0=esp, 1=esm, 32=ess (unused)
NAME32 author; // Author's name
NAME256 desc; // File description

Loading…
Cancel
Save