mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-06-06 08:27:43 +00:00
Extract Gdt reading and writing classes to GdtStream file
This commit is contained in:
parent
defc388210
commit
aa972614e5
@ -1,323 +1,9 @@
|
|||||||
#include "Gdt.h"
|
#include "Gdt.h"
|
||||||
|
|
||||||
#include <sstream>
|
Gdt::Gdt()
|
||||||
|
= default;
|
||||||
|
|
||||||
class GdtConst
|
Gdt::Gdt(GdtVersion version)
|
||||||
{
|
: m_version(std::move(version))
|
||||||
public:
|
|
||||||
static constexpr const char* VERSION_ENTRY_NAME = "version";
|
|
||||||
static constexpr const char* VERSION_ENTRY_GDF = "version.gdf";
|
|
||||||
static constexpr const char* VERSION_KEY_GAME = "game";
|
|
||||||
static constexpr const char* VERSION_KEY_VERSION = "version";
|
|
||||||
};
|
|
||||||
|
|
||||||
class GdtReader
|
|
||||||
{
|
|
||||||
std::istream& m_stream;
|
|
||||||
char m_char;
|
|
||||||
bool m_peeked;
|
|
||||||
int m_line;
|
|
||||||
|
|
||||||
void PrintError(const std::string& message) const
|
|
||||||
{
|
|
||||||
std::cout << "GDT Error at line " << m_line << ": " << message << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
int PeekChar()
|
|
||||||
{
|
|
||||||
if (m_peeked)
|
|
||||||
return m_char;
|
|
||||||
|
|
||||||
int c;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
c = m_stream.get();
|
|
||||||
}
|
|
||||||
while (isspace(c));
|
|
||||||
|
|
||||||
m_peeked = true;
|
|
||||||
m_char = c;
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
int NextChar()
|
|
||||||
{
|
|
||||||
if (m_peeked)
|
|
||||||
{
|
|
||||||
m_peeked = false;
|
|
||||||
return m_char;
|
|
||||||
}
|
|
||||||
|
|
||||||
int c;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
c = m_stream.get();
|
|
||||||
}
|
|
||||||
while (isspace(c));
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ReadStringContent(std::string& str)
|
|
||||||
{
|
|
||||||
std::ostringstream ss;
|
|
||||||
|
|
||||||
if (NextChar() != '"')
|
|
||||||
{
|
|
||||||
PrintError("Expected string opening tag");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto c = m_stream.get();
|
|
||||||
while (c != '"' && c != '\n' && c != EOF)
|
|
||||||
{
|
|
||||||
ss << static_cast<char>(c);
|
|
||||||
c = m_stream.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c == '"')
|
|
||||||
{
|
|
||||||
str = ss.str();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GdtEntry* GetEntryByName(const Gdt& gdt, const std::string& name)
|
|
||||||
{
|
|
||||||
for (const auto& entry : gdt.m_entries)
|
|
||||||
{
|
|
||||||
if (entry->m_name == name)
|
|
||||||
return entry.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ReadProperties(GdtEntry& entry)
|
|
||||||
{
|
|
||||||
while (PeekChar() == '"')
|
|
||||||
{
|
|
||||||
std::string propertyKey;
|
|
||||||
std::string propertyValue;
|
|
||||||
|
|
||||||
if (!ReadStringContent(propertyKey))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (PeekChar() != '"')
|
|
||||||
{
|
|
||||||
PrintError("Expected value string");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ReadStringContent(propertyValue))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
entry.m_properties.emplace(std::move(propertyKey), std::move(propertyValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (NextChar() != '}')
|
|
||||||
{
|
|
||||||
PrintError("Expected closing tags");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AddEntry(Gdt& gdt, GdtEntry& entry) const
|
|
||||||
{
|
|
||||||
if(entry.m_name == GdtConst::VERSION_ENTRY_NAME
|
|
||||||
&& entry.m_gdf_name == GdtConst::VERSION_ENTRY_GDF)
|
|
||||||
{
|
|
||||||
auto foundEntry = entry.m_properties.find(GdtConst::VERSION_KEY_GAME);
|
|
||||||
if(foundEntry == entry.m_properties.end())
|
|
||||||
{
|
|
||||||
PrintError("Version does not feature game property");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
gdt.m_version.m_game = foundEntry->second;
|
|
||||||
|
|
||||||
foundEntry = entry.m_properties.find(GdtConst::VERSION_KEY_VERSION);
|
|
||||||
if (foundEntry == entry.m_properties.end())
|
|
||||||
{
|
|
||||||
PrintError("Version does not feature version property");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
gdt.m_version.m_version = strtol(foundEntry->second.c_str(), nullptr, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
gdt.m_entries.emplace_back(std::make_unique<GdtEntry>(std::move(entry)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit GdtReader(std::istream& stream)
|
|
||||||
: m_stream(stream),
|
|
||||||
m_char(0),
|
|
||||||
m_peeked(false),
|
|
||||||
m_line(0)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Read(Gdt& gdt)
|
|
||||||
{
|
|
||||||
if (NextChar() != '{')
|
|
||||||
{
|
|
||||||
PrintError("Expected opening tag");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (PeekChar() == '"')
|
|
||||||
{
|
|
||||||
GdtEntry entry;
|
|
||||||
|
|
||||||
if (!ReadStringContent(entry.m_name))
|
|
||||||
{
|
|
||||||
PrintError("Failed to read string");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PeekChar() == '(')
|
|
||||||
{
|
|
||||||
NextChar();
|
|
||||||
if (!ReadStringContent(entry.m_gdf_name))
|
|
||||||
return false;
|
|
||||||
if (NextChar() != ')')
|
|
||||||
{
|
|
||||||
PrintError("Expected closing parenthesis");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (PeekChar() == '[')
|
|
||||||
{
|
|
||||||
NextChar();
|
|
||||||
std::string parentName;
|
|
||||||
if (!ReadStringContent(parentName))
|
|
||||||
return false;
|
|
||||||
if (NextChar() != ']')
|
|
||||||
{
|
|
||||||
PrintError("Expected closing square brackets");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
entry.m_parent = GetEntryByName(gdt, parentName);
|
|
||||||
if (entry.m_parent == nullptr)
|
|
||||||
{
|
|
||||||
PrintError("Could not find parent with name");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NextChar() != '{')
|
|
||||||
{
|
|
||||||
PrintError("Expected opening tag for entries");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ReadProperties(entry))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!AddEntry(gdt, entry))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (NextChar() != '}')
|
|
||||||
{
|
|
||||||
PrintError("Expected closing tags");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class GdtWriter
|
|
||||||
{
|
|
||||||
std::ostream& m_stream;
|
|
||||||
unsigned m_intendation_level;
|
|
||||||
|
|
||||||
void DoIntendation() const
|
|
||||||
{
|
|
||||||
for (auto i = 0u; i < m_intendation_level; i++)
|
|
||||||
m_stream << "\t";
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteVersion(const GdtVersion& gdtVersion)
|
|
||||||
{
|
|
||||||
GdtEntry versionEntry;
|
|
||||||
versionEntry.m_name = GdtConst::VERSION_ENTRY_NAME;
|
|
||||||
versionEntry.m_gdf_name = GdtConst::VERSION_ENTRY_GDF;
|
|
||||||
versionEntry.m_properties[GdtConst::VERSION_KEY_GAME] = gdtVersion.m_game;
|
|
||||||
versionEntry.m_properties[GdtConst::VERSION_KEY_VERSION] = std::to_string(gdtVersion.m_version);
|
|
||||||
|
|
||||||
WriteEntry(versionEntry);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteEntry(const GdtEntry& entry)
|
|
||||||
{
|
|
||||||
DoIntendation();
|
|
||||||
m_stream << "\"" << entry.m_name << "\" ";
|
|
||||||
if (entry.m_parent)
|
|
||||||
m_stream << "[ \"" << entry.m_parent->m_name << "\" ]\n";
|
|
||||||
else
|
|
||||||
m_stream << "( \"" << entry.m_gdf_name << "\" )\n";
|
|
||||||
DoIntendation();
|
|
||||||
m_stream << "{\n";
|
|
||||||
|
|
||||||
m_intendation_level++;
|
|
||||||
|
|
||||||
for (const auto& [propertyKey, propertyValue] : entry.m_properties)
|
|
||||||
{
|
|
||||||
DoIntendation();
|
|
||||||
m_stream << "\"" << propertyKey << "\" \"" << propertyValue << "\"\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
m_intendation_level--;
|
|
||||||
DoIntendation();
|
|
||||||
m_stream << "}\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit GdtWriter(std::ostream& stream)
|
|
||||||
: m_stream(stream),
|
|
||||||
m_intendation_level(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void Write(const Gdt& gdt)
|
|
||||||
{
|
|
||||||
m_stream << "{\n";
|
|
||||||
m_intendation_level++;
|
|
||||||
|
|
||||||
WriteVersion(gdt.m_version);
|
|
||||||
for (const auto& entry : gdt.m_entries)
|
|
||||||
{
|
|
||||||
WriteEntry(*entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_intendation_level--;
|
|
||||||
m_stream << "}";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
bool Gdt::ReadFromStream(std::istream& stream)
|
|
||||||
{
|
|
||||||
GdtReader reader(stream);
|
|
||||||
return reader.Read(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Gdt::WriteToStream(std::ostream& stream) const
|
|
||||||
{
|
|
||||||
GdtWriter writer(stream);
|
|
||||||
writer.Write(*this);
|
|
||||||
}
|
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include "GdtEntry.h"
|
#include "GdtEntry.h"
|
||||||
#include "GdtVersion.h"
|
#include "GdtVersion.h"
|
||||||
@ -13,6 +12,6 @@ public:
|
|||||||
GdtVersion m_version;
|
GdtVersion m_version;
|
||||||
std::vector<std::unique_ptr<GdtEntry>> m_entries;
|
std::vector<std::unique_ptr<GdtEntry>> m_entries;
|
||||||
|
|
||||||
bool ReadFromStream(std::istream& stream);
|
Gdt();
|
||||||
void WriteToStream(std::ostream& stream) const;
|
explicit Gdt(GdtVersion version);
|
||||||
};
|
};
|
||||||
|
314
src/ObjCommon/Obj/Gdt/GdtStream.cpp
Normal file
314
src/ObjCommon/Obj/Gdt/GdtStream.cpp
Normal file
@ -0,0 +1,314 @@
|
|||||||
|
#include "GdtStream.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
class GdtConst
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static constexpr const char* VERSION_ENTRY_NAME = "version";
|
||||||
|
static constexpr const char* VERSION_ENTRY_GDF = "version.gdf";
|
||||||
|
static constexpr const char* VERSION_KEY_GAME = "game";
|
||||||
|
static constexpr const char* VERSION_KEY_VERSION = "version";
|
||||||
|
};
|
||||||
|
|
||||||
|
void GdtReader::PrintError(const std::string& message) const
|
||||||
|
{
|
||||||
|
std::cout << "GDT Error at line " << m_line << ": " << message << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
int GdtReader::PeekChar()
|
||||||
|
{
|
||||||
|
if (m_peeked)
|
||||||
|
return m_char;
|
||||||
|
|
||||||
|
int c;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
c = m_stream.get();
|
||||||
|
}
|
||||||
|
while (isspace(c));
|
||||||
|
|
||||||
|
m_peeked = true;
|
||||||
|
m_char = c;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GdtReader::NextChar()
|
||||||
|
{
|
||||||
|
if (m_peeked)
|
||||||
|
{
|
||||||
|
m_peeked = false;
|
||||||
|
return m_char;
|
||||||
|
}
|
||||||
|
|
||||||
|
int c;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
c = m_stream.get();
|
||||||
|
}
|
||||||
|
while (isspace(c));
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GdtReader::ReadStringContent(std::string& str)
|
||||||
|
{
|
||||||
|
std::ostringstream ss;
|
||||||
|
|
||||||
|
if (NextChar() != '"')
|
||||||
|
{
|
||||||
|
PrintError("Expected string opening tag");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto c = m_stream.get();
|
||||||
|
while (c != '"' && c != '\n' && c != EOF)
|
||||||
|
{
|
||||||
|
ss << static_cast<char>(c);
|
||||||
|
c = m_stream.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == '"')
|
||||||
|
{
|
||||||
|
str = ss.str();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
GdtEntry* GdtReader::GetEntryByName(const Gdt& gdt, const std::string& name)
|
||||||
|
{
|
||||||
|
for (const auto& entry : gdt.m_entries)
|
||||||
|
{
|
||||||
|
if (entry->m_name == name)
|
||||||
|
return entry.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GdtReader::ReadProperties(GdtEntry& entry)
|
||||||
|
{
|
||||||
|
while (PeekChar() == '"')
|
||||||
|
{
|
||||||
|
std::string propertyKey;
|
||||||
|
std::string propertyValue;
|
||||||
|
|
||||||
|
if (!ReadStringContent(propertyKey))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (PeekChar() != '"')
|
||||||
|
{
|
||||||
|
PrintError("Expected value string");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ReadStringContent(propertyValue))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
entry.m_properties.emplace(std::move(propertyKey), std::move(propertyValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (NextChar() != '}')
|
||||||
|
{
|
||||||
|
PrintError("Expected closing tags");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GdtReader::AddEntry(Gdt& gdt, GdtEntry& entry) const
|
||||||
|
{
|
||||||
|
if (entry.m_name == GdtConst::VERSION_ENTRY_NAME
|
||||||
|
&& entry.m_gdf_name == GdtConst::VERSION_ENTRY_GDF)
|
||||||
|
{
|
||||||
|
auto foundEntry = entry.m_properties.find(GdtConst::VERSION_KEY_GAME);
|
||||||
|
if (foundEntry == entry.m_properties.end())
|
||||||
|
{
|
||||||
|
PrintError("Version does not feature game property");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
gdt.m_version.m_game = foundEntry->second;
|
||||||
|
|
||||||
|
foundEntry = entry.m_properties.find(GdtConst::VERSION_KEY_VERSION);
|
||||||
|
if (foundEntry == entry.m_properties.end())
|
||||||
|
{
|
||||||
|
PrintError("Version does not feature version property");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
gdt.m_version.m_version = strtol(foundEntry->second.c_str(), nullptr, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gdt.m_entries.emplace_back(std::make_unique<GdtEntry>(std::move(entry)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
GdtReader::GdtReader(std::istream& stream)
|
||||||
|
: m_stream(stream),
|
||||||
|
m_char(0),
|
||||||
|
m_peeked(false),
|
||||||
|
m_line(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GdtReader::Read(Gdt& gdt)
|
||||||
|
{
|
||||||
|
if (NextChar() != '{')
|
||||||
|
{
|
||||||
|
PrintError("Expected opening tag");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (PeekChar() == '"')
|
||||||
|
{
|
||||||
|
GdtEntry entry;
|
||||||
|
|
||||||
|
if (!ReadStringContent(entry.m_name))
|
||||||
|
{
|
||||||
|
PrintError("Failed to read string");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PeekChar() == '(')
|
||||||
|
{
|
||||||
|
NextChar();
|
||||||
|
if (!ReadStringContent(entry.m_gdf_name))
|
||||||
|
return false;
|
||||||
|
if (NextChar() != ')')
|
||||||
|
{
|
||||||
|
PrintError("Expected closing parenthesis");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (PeekChar() == '[')
|
||||||
|
{
|
||||||
|
NextChar();
|
||||||
|
std::string parentName;
|
||||||
|
if (!ReadStringContent(parentName))
|
||||||
|
return false;
|
||||||
|
if (NextChar() != ']')
|
||||||
|
{
|
||||||
|
PrintError("Expected closing square brackets");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
entry.m_parent = GetEntryByName(gdt, parentName);
|
||||||
|
if (entry.m_parent == nullptr)
|
||||||
|
{
|
||||||
|
PrintError("Could not find parent with name");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NextChar() != '{')
|
||||||
|
{
|
||||||
|
PrintError("Expected opening tag for entries");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ReadProperties(entry))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!AddEntry(gdt, entry))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (NextChar() != '}')
|
||||||
|
{
|
||||||
|
PrintError("Expected closing tags");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
GdtOutputStream::GdtOutputStream(std::ostream& stream)
|
||||||
|
: m_stream(stream),
|
||||||
|
m_open(false),
|
||||||
|
m_intendation_level(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void GdtOutputStream::BeginStream()
|
||||||
|
{
|
||||||
|
if (!m_open)
|
||||||
|
{
|
||||||
|
m_stream << "{\n";
|
||||||
|
m_intendation_level++;
|
||||||
|
m_open = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GdtOutputStream::DoIntendation() const
|
||||||
|
{
|
||||||
|
for (auto i = 0u; i < m_intendation_level; i++)
|
||||||
|
m_stream << "\t";
|
||||||
|
}
|
||||||
|
|
||||||
|
void GdtOutputStream::WriteVersion(const GdtVersion& gdtVersion)
|
||||||
|
{
|
||||||
|
GdtEntry versionEntry;
|
||||||
|
versionEntry.m_name = GdtConst::VERSION_ENTRY_NAME;
|
||||||
|
versionEntry.m_gdf_name = GdtConst::VERSION_ENTRY_GDF;
|
||||||
|
versionEntry.m_properties[GdtConst::VERSION_KEY_GAME] = gdtVersion.m_game;
|
||||||
|
versionEntry.m_properties[GdtConst::VERSION_KEY_VERSION] = std::to_string(gdtVersion.m_version);
|
||||||
|
|
||||||
|
WriteEntry(versionEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GdtOutputStream::WriteEntry(const GdtEntry& entry)
|
||||||
|
{
|
||||||
|
DoIntendation();
|
||||||
|
m_stream << "\"" << entry.m_name << "\" ";
|
||||||
|
if (entry.m_parent)
|
||||||
|
m_stream << "[ \"" << entry.m_parent->m_name << "\" ]\n";
|
||||||
|
else
|
||||||
|
m_stream << "( \"" << entry.m_gdf_name << "\" )\n";
|
||||||
|
DoIntendation();
|
||||||
|
m_stream << "{\n";
|
||||||
|
|
||||||
|
m_intendation_level++;
|
||||||
|
|
||||||
|
for (const auto& [propertyKey, propertyValue] : entry.m_properties)
|
||||||
|
{
|
||||||
|
DoIntendation();
|
||||||
|
m_stream << "\"" << propertyKey << "\" \"" << propertyValue << "\"\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
m_intendation_level--;
|
||||||
|
DoIntendation();
|
||||||
|
m_stream << "}\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void GdtOutputStream::EndStream()
|
||||||
|
{
|
||||||
|
if (m_open)
|
||||||
|
{
|
||||||
|
m_intendation_level--;
|
||||||
|
m_stream << "}";
|
||||||
|
m_open = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GdtOutputStream::WriteGdt(const Gdt& gdt, std::ostream& stream)
|
||||||
|
{
|
||||||
|
GdtOutputStream out(stream);
|
||||||
|
out.BeginStream();
|
||||||
|
out.WriteVersion(gdt.m_version);
|
||||||
|
|
||||||
|
for (const auto& entry : gdt.m_entries)
|
||||||
|
out.WriteEntry(*entry);
|
||||||
|
|
||||||
|
out.EndStream();
|
||||||
|
}
|
43
src/ObjCommon/Obj/Gdt/GdtStream.h
Normal file
43
src/ObjCommon/Obj/Gdt/GdtStream.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "Gdt.h"
|
||||||
|
|
||||||
|
class GdtReader
|
||||||
|
{
|
||||||
|
std::istream& m_stream;
|
||||||
|
char m_char;
|
||||||
|
bool m_peeked;
|
||||||
|
int m_line;
|
||||||
|
|
||||||
|
static GdtEntry* GetEntryByName(const Gdt& gdt, const std::string& name);
|
||||||
|
void PrintError(const std::string& message) const;
|
||||||
|
int PeekChar();
|
||||||
|
int NextChar();
|
||||||
|
bool ReadStringContent(std::string& str);
|
||||||
|
bool ReadProperties(GdtEntry& entry);
|
||||||
|
bool AddEntry(Gdt& gdt, GdtEntry& entry) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit GdtReader(std::istream& stream);
|
||||||
|
bool Read(Gdt& gdt);
|
||||||
|
};
|
||||||
|
|
||||||
|
class GdtOutputStream
|
||||||
|
{
|
||||||
|
std::ostream& m_stream;
|
||||||
|
bool m_open;
|
||||||
|
unsigned m_intendation_level;
|
||||||
|
|
||||||
|
void DoIntendation() const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit GdtOutputStream(std::ostream& stream);
|
||||||
|
|
||||||
|
void BeginStream();
|
||||||
|
void WriteVersion(const GdtVersion& gdtVersion);
|
||||||
|
void WriteEntry(const GdtEntry& entry);
|
||||||
|
void EndStream();
|
||||||
|
|
||||||
|
static void WriteGdt(const Gdt& gdt, std::ostream& stream);
|
||||||
|
};
|
@ -3,6 +3,7 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
#include "Obj/Gdt/Gdt.h"
|
#include "Obj/Gdt/Gdt.h"
|
||||||
|
#include "Obj/Gdt/GdtStream.h"
|
||||||
|
|
||||||
namespace obj::gdt
|
namespace obj::gdt
|
||||||
{
|
{
|
||||||
@ -18,7 +19,8 @@ namespace obj::gdt
|
|||||||
std::istringstream ss(gdtString);
|
std::istringstream ss(gdtString);
|
||||||
|
|
||||||
Gdt gdt;
|
Gdt gdt;
|
||||||
REQUIRE(gdt.ReadFromStream(ss));
|
GdtReader reader(ss);
|
||||||
|
REQUIRE(reader.Read(gdt));
|
||||||
|
|
||||||
REQUIRE(gdt.m_entries.size() == 1);
|
REQUIRE(gdt.m_entries.size() == 1);
|
||||||
|
|
||||||
@ -46,7 +48,8 @@ namespace obj::gdt
|
|||||||
std::istringstream ss(gdtString);
|
std::istringstream ss(gdtString);
|
||||||
|
|
||||||
Gdt gdt;
|
Gdt gdt;
|
||||||
REQUIRE(gdt.ReadFromStream(ss));
|
GdtReader reader(ss);
|
||||||
|
REQUIRE(reader.Read(gdt));
|
||||||
|
|
||||||
REQUIRE(gdt.m_entries.size() == 1);
|
REQUIRE(gdt.m_entries.size() == 1);
|
||||||
|
|
||||||
@ -74,7 +77,8 @@ namespace obj::gdt
|
|||||||
std::istringstream ss(gdtString);
|
std::istringstream ss(gdtString);
|
||||||
|
|
||||||
Gdt gdt;
|
Gdt gdt;
|
||||||
REQUIRE(gdt.ReadFromStream(ss));
|
GdtReader reader(ss);
|
||||||
|
REQUIRE(reader.Read(gdt));
|
||||||
|
|
||||||
REQUIRE(gdt.m_entries.empty());
|
REQUIRE(gdt.m_entries.empty());
|
||||||
REQUIRE(gdt.m_version.m_game == "t6");
|
REQUIRE(gdt.m_version.m_game == "t6");
|
||||||
@ -98,7 +102,8 @@ namespace obj::gdt
|
|||||||
std::istringstream ss(gdtString);
|
std::istringstream ss(gdtString);
|
||||||
|
|
||||||
Gdt gdt;
|
Gdt gdt;
|
||||||
REQUIRE(gdt.ReadFromStream(ss));
|
GdtReader reader(ss);
|
||||||
|
REQUIRE(reader.Read(gdt));
|
||||||
|
|
||||||
REQUIRE(gdt.m_version.m_game == "t6");
|
REQUIRE(gdt.m_version.m_game == "t6");
|
||||||
REQUIRE(gdt.m_version.m_version == 1337);
|
REQUIRE(gdt.m_version.m_version == 1337);
|
||||||
@ -144,7 +149,8 @@ namespace obj::gdt
|
|||||||
std::istringstream ss(gdtString);
|
std::istringstream ss(gdtString);
|
||||||
|
|
||||||
Gdt gdt;
|
Gdt gdt;
|
||||||
REQUIRE(gdt.ReadFromStream(ss));
|
GdtReader reader(ss);
|
||||||
|
REQUIRE(reader.Read(gdt));
|
||||||
|
|
||||||
REQUIRE(gdt.m_version.m_game == "t6");
|
REQUIRE(gdt.m_version.m_game == "t6");
|
||||||
REQUIRE(gdt.m_version.m_version == 1337);
|
REQUIRE(gdt.m_version.m_version == 1337);
|
||||||
@ -208,7 +214,8 @@ namespace obj::gdt
|
|||||||
std::istringstream ss(gdtString);
|
std::istringstream ss(gdtString);
|
||||||
|
|
||||||
Gdt gdt;
|
Gdt gdt;
|
||||||
REQUIRE(gdt.ReadFromStream(ss));
|
GdtReader reader(ss);
|
||||||
|
REQUIRE(reader.Read(gdt));
|
||||||
|
|
||||||
REQUIRE(gdt.m_version.m_game == "t6");
|
REQUIRE(gdt.m_version.m_game == "t6");
|
||||||
REQUIRE(gdt.m_version.m_version == 1337);
|
REQUIRE(gdt.m_version.m_version == 1337);
|
||||||
@ -259,12 +266,13 @@ namespace obj::gdt
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
gdt.WriteToStream(ss);
|
GdtOutputStream::WriteGdt(gdt, ss);
|
||||||
|
|
||||||
std::cout << ss.str();
|
std::cout << ss.str();
|
||||||
|
|
||||||
Gdt gdt2;
|
Gdt gdt2;
|
||||||
REQUIRE(gdt2.ReadFromStream(ss));
|
GdtReader reader(ss);
|
||||||
|
REQUIRE(reader.Read(gdt2));
|
||||||
|
|
||||||
REQUIRE(gdt2.m_version.m_game == "whatagame");
|
REQUIRE(gdt2.m_version.m_game == "whatagame");
|
||||||
REQUIRE(gdt2.m_version.m_version == 6969);
|
REQUIRE(gdt2.m_version.m_version == 6969);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user