mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-11-03 23:56:43 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			212 lines
		
	
	
	
		
			4.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			212 lines
		
	
	
	
		
			4.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#include "esmwriter.hpp"
 | 
						|
#include <fstream>
 | 
						|
#include <cstring>
 | 
						|
 | 
						|
bool count = true;
 | 
						|
 | 
						|
namespace ESM
 | 
						|
{
 | 
						|
 | 
						|
int ESMWriter::getVersion()
 | 
						|
{
 | 
						|
    return m_header.version;
 | 
						|
}
 | 
						|
 | 
						|
void ESMWriter::setVersion(int ver)
 | 
						|
{
 | 
						|
    m_header.version = ver;
 | 
						|
}
 | 
						|
 | 
						|
int ESMWriter::getType()
 | 
						|
{
 | 
						|
    return m_header.type;
 | 
						|
}
 | 
						|
 | 
						|
void ESMWriter::setType(int type)
 | 
						|
{
 | 
						|
    m_header.type = type;
 | 
						|
}
 | 
						|
 | 
						|
void ESMWriter::setAuthor(const std::string& auth)
 | 
						|
{
 | 
						|
    strncpy((char*)&m_header.author, auth.c_str(), 32);
 | 
						|
}
 | 
						|
 | 
						|
void ESMWriter::setDescription(const std::string& desc)
 | 
						|
{
 | 
						|
    strncpy((char*)&m_header.desc, desc.c_str(), 256);
 | 
						|
}
 | 
						|
 | 
						|
void ESMWriter::addMaster(const std::string& name, uint64_t size)
 | 
						|
{
 | 
						|
    MasterData d;
 | 
						|
    d.name = name;
 | 
						|
    d.size = size;
 | 
						|
    m_masters.push_back(d);
 | 
						|
}
 | 
						|
 | 
						|
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::save(std::ostream& file)
 | 
						|
{
 | 
						|
    m_recordCount = 0;
 | 
						|
    m_stream = &file;
 | 
						|
 | 
						|
    startRecord("TES3", 0);
 | 
						|
 | 
						|
    m_header.records = 0;
 | 
						|
    writeHNT("HEDR", m_header, 300);
 | 
						|
    m_headerPos = m_stream->tellp() - (std::streampos)4;
 | 
						|
 | 
						|
    for (std::list<MasterData>::iterator it = m_masters.begin(); it != m_masters.end(); ++it)
 | 
						|
    {
 | 
						|
        writeHNCString("MAST", it->name);
 | 
						|
        writeHNT("DATA", it->size);
 | 
						|
    }
 | 
						|
 | 
						|
    endRecord("TES3");
 | 
						|
}
 | 
						|
 | 
						|
void ESMWriter::close()
 | 
						|
{
 | 
						|
    std::cout << "Writing amount of saved records (" << m_recordCount - 1 << ")" << std::endl;
 | 
						|
    m_stream->seekp(m_headerPos);
 | 
						|
    writeT<int>(m_recordCount-1);
 | 
						|
    m_stream->seekp(0, std::ios::end);
 | 
						|
    m_stream->flush();
 | 
						|
 | 
						|
    if (!m_records.empty())
 | 
						|
        throw "Unclosed record remaining";
 | 
						|
}
 | 
						|
 | 
						|
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);
 | 
						|
}
 | 
						|
 | 
						|
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::endRecord(const std::string& name)
 | 
						|
{
 | 
						|
    RecordData rec = m_records.back();
 | 
						|
    assert(rec.name == name);
 | 
						|
    m_records.pop_back();
 | 
						|
    
 | 
						|
    m_stream->seekp(rec.position);
 | 
						|
 | 
						|
    count = false;
 | 
						|
    write((char*)&rec.size, sizeof(int));
 | 
						|
    count = true;
 | 
						|
 | 
						|
    m_stream->seekp(0, std::ios::end);
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
void ESMWriter::writeHNString(const std::string& name, const std::string& data)
 | 
						|
{
 | 
						|
    startSubRecord(name);
 | 
						|
    writeHString(data);
 | 
						|
    endRecord(name);
 | 
						|
}
 | 
						|
 | 
						|
void ESMWriter::writeHNString(const std::string& name, const std::string& data, int size)
 | 
						|
{
 | 
						|
    assert(static_cast<int> (data.size()) <= size);
 | 
						|
    startSubRecord(name);
 | 
						|
    writeHString(data);
 | 
						|
 | 
						|
    if (static_cast<int> (data.size()) < size)
 | 
						|
    {
 | 
						|
        for (int i = data.size(); i < size; ++i)
 | 
						|
            write("\0",1);
 | 
						|
    }
 | 
						|
 | 
						|
    endRecord(name);
 | 
						|
}
 | 
						|
 | 
						|
void ESMWriter::writeHString(const std::string& data)
 | 
						|
{
 | 
						|
    if (data.size() == 0)
 | 
						|
        write("\0", 1);
 | 
						|
    else
 | 
						|
    {
 | 
						|
        char *ptr = ToUTF8::getBuffer(data.size()+1);
 | 
						|
        strncpy(ptr, &data[0], data.size());
 | 
						|
        ptr[data.size()] = '\0';
 | 
						|
 | 
						|
        // Convert to UTF8 and return
 | 
						|
        std::string ascii = ToUTF8::getLegacyEnc(m_encoding);
 | 
						|
 | 
						|
        write(ascii.c_str(), ascii.size());
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void ESMWriter::writeHCString(const std::string& data)
 | 
						|
{
 | 
						|
    writeHString(data);
 | 
						|
    if (data.size() > 0 && data[data.size()-1] != '\0')
 | 
						|
        write("\0", 1);
 | 
						|
}
 | 
						|
 | 
						|
void ESMWriter::writeName(const std::string& name)
 | 
						|
{
 | 
						|
    assert((name.size() == 4 && name[3] != '\0'));
 | 
						|
    write(name.c_str(), name.size());
 | 
						|
}
 | 
						|
 | 
						|
void ESMWriter::write(const char* data, int size)
 | 
						|
{
 | 
						|
    if (count && !m_records.empty())
 | 
						|
    {
 | 
						|
        for (std::list<RecordData>::iterator it = m_records.begin(); it != m_records.end(); ++it)
 | 
						|
            it->size += size;
 | 
						|
    }
 | 
						|
 | 
						|
    m_stream->write(data, size);
 | 
						|
}
 | 
						|
 | 
						|
void ESMWriter::setEncoding(const std::string& encoding)
 | 
						|
{
 | 
						|
    if (encoding == "win1250")
 | 
						|
    {
 | 
						|
        m_encoding = ToUTF8::WINDOWS_1250;
 | 
						|
    }
 | 
						|
    else if (encoding == "win1251")
 | 
						|
    {
 | 
						|
        m_encoding = ToUTF8::WINDOWS_1251;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        // Default Latin encoding
 | 
						|
        m_encoding = ToUTF8::WINDOWS_1252;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
}
 |