mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 16:15:43 +00:00
Make sure gdt values are escaped
This commit is contained in:
parent
ea7b1eadae
commit
603994ce61
@ -63,9 +63,36 @@ bool GdtReader::ReadStringContent(std::string& str)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto c = m_stream.get();
|
auto c = m_stream.get();
|
||||||
while (c != '"' && c != '\n' && c != EOF)
|
auto escaped = false;
|
||||||
|
while ((escaped || c != '"' && c != '\n') && c != EOF)
|
||||||
|
{
|
||||||
|
if (escaped)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case '\n':
|
||||||
|
case 'n':
|
||||||
|
ss << '\n';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'r':
|
||||||
|
ss << '\r';
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ss << static_cast<char>(c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
escaped = false;
|
||||||
|
}
|
||||||
|
else if(c == '\\')
|
||||||
|
{
|
||||||
|
escaped = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
ss << static_cast<char>(c);
|
ss << static_cast<char>(c);
|
||||||
|
}
|
||||||
c = m_stream.get();
|
c = m_stream.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,6 +294,55 @@ void GdtOutputStream::WriteVersion(const GdtVersion& gdtVersion)
|
|||||||
WriteEntry(versionEntry);
|
WriteEntry(versionEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GdtOutputStream::WriteEscaped(const std::string& str) const
|
||||||
|
{
|
||||||
|
auto wroteBefore = false;
|
||||||
|
for(auto i = 0u; i < str.size(); i++)
|
||||||
|
{
|
||||||
|
auto needsEscape = false;
|
||||||
|
auto c = str[i];
|
||||||
|
switch(c)
|
||||||
|
{
|
||||||
|
case '\r':
|
||||||
|
needsEscape = true;
|
||||||
|
c = 'r';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '\n':
|
||||||
|
needsEscape = true;
|
||||||
|
c = 'n';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '\\':
|
||||||
|
needsEscape = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(needsEscape)
|
||||||
|
{
|
||||||
|
if(!wroteBefore)
|
||||||
|
{
|
||||||
|
wroteBefore = true;
|
||||||
|
m_stream << std::string(str, 0, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_stream << '\\' << c;
|
||||||
|
}
|
||||||
|
else if(wroteBefore)
|
||||||
|
{
|
||||||
|
m_stream << c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!wroteBefore)
|
||||||
|
{
|
||||||
|
m_stream << str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GdtOutputStream::WriteEntry(const GdtEntry& entry)
|
void GdtOutputStream::WriteEntry(const GdtEntry& entry)
|
||||||
{
|
{
|
||||||
DoIntendation();
|
DoIntendation();
|
||||||
@ -283,7 +359,9 @@ void GdtOutputStream::WriteEntry(const GdtEntry& entry)
|
|||||||
for (const auto& [propertyKey, propertyValue] : entry.m_properties)
|
for (const auto& [propertyKey, propertyValue] : entry.m_properties)
|
||||||
{
|
{
|
||||||
DoIntendation();
|
DoIntendation();
|
||||||
m_stream << "\"" << propertyKey << "\" \"" << propertyValue << "\"\n";
|
m_stream << "\"" << propertyKey << "\" \"";
|
||||||
|
WriteEscaped(propertyValue);
|
||||||
|
m_stream << "\"\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
m_intendation_level--;
|
m_intendation_level--;
|
||||||
|
@ -36,6 +36,7 @@ public:
|
|||||||
|
|
||||||
void BeginStream();
|
void BeginStream();
|
||||||
void WriteVersion(const GdtVersion& gdtVersion);
|
void WriteVersion(const GdtVersion& gdtVersion);
|
||||||
|
void WriteEscaped(const std::string& str) const;
|
||||||
void WriteEntry(const GdtEntry& entry);
|
void WriteEntry(const GdtEntry& entry);
|
||||||
void EndStream();
|
void EndStream();
|
||||||
|
|
||||||
|
@ -4,8 +4,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "Obj/Gdt/GdtEntry.h"
|
||||||
#include "Obj/GDT/GdtEntry.h"
|
|
||||||
#include "Zone/ZoneTypes.h"
|
#include "Zone/ZoneTypes.h"
|
||||||
|
|
||||||
class InfoString
|
class InfoString
|
||||||
|
@ -300,4 +300,41 @@ namespace obj::gdt
|
|||||||
REQUIRE(entry.m_properties.at("idk") == "whattotypeanymore");
|
REQUIRE(entry.m_properties.at("idk") == "whattotypeanymore");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Gdt: Ensure can write gdt with escape values and parse it again", "[gdt]")
|
||||||
|
{
|
||||||
|
Gdt gdt;
|
||||||
|
gdt.m_version.m_game = "whatagame";
|
||||||
|
gdt.m_version.m_version = 6969;
|
||||||
|
|
||||||
|
{
|
||||||
|
auto entry = std::make_unique<GdtEntry>("sickentry", "verycool.gdf");
|
||||||
|
entry->m_properties["hello"] = "very\nkewl\\stuff";
|
||||||
|
gdt.m_entries.emplace_back(std::move(entry));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
|
GdtOutputStream::WriteGdt(gdt, ss);
|
||||||
|
|
||||||
|
std::cout << ss.str();
|
||||||
|
|
||||||
|
Gdt gdt2;
|
||||||
|
GdtReader reader(ss);
|
||||||
|
REQUIRE(reader.Read(gdt2));
|
||||||
|
|
||||||
|
REQUIRE(gdt2.m_version.m_game == "whatagame");
|
||||||
|
REQUIRE(gdt2.m_version.m_version == 6969);
|
||||||
|
|
||||||
|
REQUIRE(gdt2.m_entries.size() == 1);
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto& entry = *gdt2.m_entries[0];
|
||||||
|
REQUIRE(entry.m_name == "sickentry");
|
||||||
|
REQUIRE(entry.m_gdf_name == "verycool.gdf");
|
||||||
|
REQUIRE(entry.m_parent == nullptr);
|
||||||
|
REQUIRE(entry.m_properties.size() == 1);
|
||||||
|
|
||||||
|
REQUIRE(entry.m_properties.at("hello") == "very\nkewl\\stuff");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user