1
0
mirror of https://github.com/ScrelliCopter/tmx2gba.git synced 2025-02-21 03:29:25 +11:00

replace rapidxml uses with pugixml

This commit is contained in:
2024-04-10 06:31:43 +10:00
parent c2e9f5c974
commit e6bb098e15
14 changed files with 116 additions and 3499 deletions

View File

@@ -27,9 +27,7 @@ target_compile_options(tmx2gba PRIVATE
$<$<CXX_COMPILER_ID:GNU,Clang,AppleClang>:-Wall -Wextra -pedantic>
$<$<CXX_COMPILER_ID:Clang,AppleClang>:-Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-padded>)
target_link_libraries(tmx2gba External::rapidxml)
#pugixml)
target_link_libraries(tmx2gba base64::base64 Zstd::Zstd
target_link_libraries(tmx2gba pugixml base64::base64 Zstd::Zstd
$<$<TARGET_EXISTS:ZLIB::ZLIB>:ZLIB::ZLIB>
$<$<TARGET_EXISTS:miniz::miniz>:miniz::miniz>)

View File

@@ -25,7 +25,7 @@ public:
TmxLayer(int width, int height, const std::string_view name, std::vector<uint32_t>&& tileDat) noexcept
: mName(name), mWidth(width), mHeight(height), mTileDat(std::move(tileDat)) {}
[[nodiscard]] constexpr const std::string_view Name() const noexcept { return mName; }
[[nodiscard]] const std::string_view Name() const noexcept { return mName; }
[[nodiscard]] constexpr std::pair<int, int> TileCount() const noexcept { return { mWidth, mHeight }; }
[[nodiscard]] constexpr const std::span<const uint32_t> Tiles() const noexcept { return mTileDat; }
};

View File

@@ -2,14 +2,70 @@
// SPDX-FileCopyrightText: (c) 2015-2024 a dinosaur
#include "tmxmap.hpp"
#include "base64.h"
#include <pugixml.hpp>
#include <base64.h>
#ifdef USE_ZLIB
# include <zlib.h>
#else
# include "gzip.hpp"
#endif
#include <sstream>
#include <fstream>
#include <limits>
#include <cerrno>
#include <optional>
template <typename T>
[[nodiscard]] static std::optional<T> IntFromStr(const char* str, int base = 0) noexcept
{
using std::numeric_limits;
errno = 0;
char* end = nullptr;
long res = std::strtol(str, &end, base);
if (errno == ERANGE) { return std::nullopt; }
if (str == end) { return std::nullopt; }
if constexpr (sizeof(long) > sizeof(T))
{
if (res > numeric_limits<T>::max() || res < numeric_limits<T>::min())
return std::nullopt;
}
return static_cast<T>(res);
}
template <typename T>
[[nodiscard]] static std::optional<T> UintFromStr(const char* str, int base = 0) noexcept
{
using std::numeric_limits;
char* end = nullptr;
errno = 0;
unsigned long res = std::strtoul(str, &end, base);
if (errno == ERANGE) { return std::nullopt; }
if (str == end) { return std::nullopt; }
if constexpr (numeric_limits<unsigned long>::max() > numeric_limits<T>::max())
{
if (res > numeric_limits<T>::max()) { return std::nullopt; }
}
return static_cast<T>(res);
}
template <typename T>
[[nodiscard]] static std::optional<T> FloatFromStr(const char* str) noexcept
{
char* end = nullptr;
T res;
errno = 0;
if constexpr (std::is_same_v<T, float>)
res = std::strtof(str, &end);
else
res = static_cast<T>(std::strtod(str, &end));
if (errno == ERANGE) { return std::nullopt; }
if (str == end) { return std::nullopt; }
return res;
}
bool TmxMap::Decode(std::span<uint32_t> out, const std::string_view base64)
@@ -37,132 +93,78 @@ bool TmxMap::Decode(std::span<uint32_t> out, const std::string_view base64)
return res >= 0;
}
void TmxMap::ReadTileset(rapidxml::xml_node<>* aXNode)
void TmxMap::ReadTileset(const pugi::xml_node& xNode)
{
std::string_view name, source;
uint32_t firstGid = 0, lastGid = 0;
std::string_view name = xNode.attribute("name").value();
std::string_view source = xNode.attribute("source").value();
// Read name
auto xAttrib = aXNode->first_attribute("name");
if (xAttrib != nullptr)
name = xAttrib->value();
// Read source
xAttrib = aXNode->first_attribute("source");
if (xAttrib != nullptr)
source = xAttrib->value();
// Read first global ID
xAttrib = aXNode->first_attribute("firstgid");
if (xAttrib != nullptr)
firstGid = static_cast<uint32_t>(std::stoul(xAttrib->value()));
// Read last global ID
xAttrib = aXNode->first_attribute("lastgid");
if (xAttrib)
lastGid = static_cast<uint32_t>(std::stoul(xAttrib->value()));
auto firstGid = UintFromStr<uint32_t>(xNode.attribute("firstgid").value()).value_or(0);
auto lastGid = UintFromStr<uint32_t>(xNode.attribute("lastgid").value()).value_or(0);
mTilesets.emplace_back(TmxTileset(name, source, firstGid, lastGid));
}
void TmxMap::ReadLayer(rapidxml::xml_node<>* aXNode)
void TmxMap::ReadLayer(const pugi::xml_node& xNode)
{
std::string_view name;
int width = 0, height = 0;
std::string_view name = xNode.attribute("name").value();
// Read name
auto xAttrib = aXNode->first_attribute("name");
if (xAttrib != nullptr)
name = xAttrib->value();
// Read width
xAttrib = aXNode->first_attribute("width");
if (xAttrib != nullptr)
width = std::stoi(xAttrib->value());
// Read height
xAttrib = aXNode->first_attribute("height");
if (xAttrib != nullptr)
height = std::stoi(xAttrib->value());
// Read tile data
auto xData = aXNode->first_node("data");
if (xData == nullptr)
// Read layer size
int width = IntFromStr<int>(xNode.attribute("width").value()).value_or(0);
int height = IntFromStr<int>(xNode.attribute("height").value()).value_or(0);
if (width <= 0 || height <= 0)
return;
// Read tile data
auto xData = xNode.child("data");
if (xData.empty() || xData.first_child().empty())
return;
// TODO: don't assume base64
std::vector<uint32_t> tileDat(width * height);
if (!Decode(tileDat, xData->value()))
if (!Decode(tileDat, xData.child_value()))
return;
mLayers.emplace_back(TmxLayer(width, height, name, std::move(tileDat)));
}
void TmxMap::ReadObjects(rapidxml::xml_node<>* aXNode)
void TmxMap::ReadObjects(const pugi::xml_node& xNode)
{
for (auto xNode = aXNode->first_node(); xNode != nullptr; xNode = xNode->next_sibling())
for (const auto it : xNode.children("object"))
{
if (strcmp(xNode->name(), "object") != 0)
continue;
std::string_view name = it.attribute("name").value();
std::string_view name;
float x = 0.0f, y = 0.0f;
// Read name
auto xAttrib = xNode->first_attribute("name");
if (xAttrib != nullptr)
name = xAttrib->value();
// Read X pos
xAttrib = xNode->first_attribute("x");
if (xAttrib != nullptr)
x = std::stof(xAttrib->value());
// Read Y pos
xAttrib = xNode->first_attribute("y");
if (xAttrib != nullptr)
y = std::stof(xAttrib->value());
// Read position
auto x = FloatFromStr<float>(it.attribute("x").value()).value_or(0.0f);
auto y = FloatFromStr<float>(it.attribute("y").value()).value_or(0.0f);
mObjects.emplace_back(TmxObject(name, x, y));
}
}
bool TmxMap::Load(const std::string_view inPath)
bool TmxMap::Load(const std::string& inPath)
{
// Read file into a buffer
auto inFile = std::ifstream(inPath);
std::stringstream buf;
buf << inFile.rdbuf();
std::string strXml = buf.str();
buf.clear();
// Parse document
rapidxml::xml_document<> xDoc;
xDoc.parse<0>(const_cast<char*>(strXml.c_str()));
// Get map node
auto xMap = xDoc.first_node("map");
if (xMap == nullptr)
pugi::xml_document xDoc;
auto res = xDoc.load_file(inPath.c_str());
if (res.status != pugi::xml_parse_status::status_ok)
return false;
// Get map node
auto xMap = xDoc.child("map");
//if (xMap == nullptr)
// return false;
// Read map attribs
rapidxml::xml_attribute<>* xAttrib = nullptr;
if ((xAttrib = xMap->first_attribute("width")) != nullptr)
mWidth = std::stoi(xAttrib->value());
if ((xAttrib = xMap->first_attribute("height")) != nullptr)
mHeight = std::stoi(xAttrib->value());
mWidth = IntFromStr<int>(xMap.attribute("width").value()).value_or(0);
mHeight = IntFromStr<int>(xMap.attribute("height").value()).value_or(0);
// Read nodes
for (auto xNode = xMap->first_node(); xNode != nullptr; xNode = xNode->next_sibling())
//for (auto it = xMap.begin(); it != xMap.end(); ++it)
for (auto it : xMap.children())
{
// Read layer nodes
const auto xName = xNode->name();
if (std::strcmp(xName, "layer") == 0)
ReadLayer(xNode);
else if (std::strcmp(xName, "tileset") == 0)
ReadTileset(xNode);
else if (std::strcmp(xName, "objectgroup") == 0)
ReadObjects(xNode);
std::string_view name(it.name());
if (!name.compare("layer")) { ReadLayer(it); }
else if (!name.compare("tileset")) { ReadTileset(it); }
else if (!name.compare("objectgroup")) { ReadObjects(it); }
}
return true;

View File

@@ -7,11 +7,13 @@
#include "tmxtileset.hpp"
#include "tmxobject.hpp"
#include "tmxlayer.hpp"
#include <rapidxml/rapidxml.hpp>
#include <vector>
#include <span>
#include <string>
#include <string_view>
namespace pugi { class xml_node; }
class TmxMap
{
int mWidth = 0, mHeight = 0;
@@ -21,12 +23,12 @@ class TmxMap
std::vector<TmxObject> mObjects;
[[nodiscard]] bool Decode(std::span<uint32_t> out, const std::string_view base64);
void ReadTileset(rapidxml::xml_node<>* aXNode);
void ReadLayer(rapidxml::xml_node<>* aXNode);
void ReadObjects(rapidxml::xml_node<>* aXNode);
void ReadTileset(const pugi::xml_node& xNode);
void ReadLayer(const pugi::xml_node& xNode);
void ReadObjects(const pugi::xml_node& xNode);
public:
[[nodiscard]] bool Load(const std::string_view inPath);
[[nodiscard]] bool Load(const std::string& inPath);
constexpr std::pair<int, int> TileCount() const noexcept { return { mWidth, mHeight }; }
constexpr const std::vector<TmxTileset>& Tilesets() const noexcept { return mTilesets; }

View File

@@ -14,7 +14,7 @@ public:
template <typename T>
struct Position { T x, y; };
constexpr const std::string_view Name() const noexcept { return mName; }
const std::string_view Name() const noexcept { return mName; }
constexpr Position<float> Pos() const noexcept { return mPos; }
private:

View File

@@ -88,46 +88,31 @@ TmxReader::Error TmxReader::Open(const std::string& inPath,
mGidTable.emplace_back(set.GidRange());
// Read objects
/*
if (!objMapping.empty())
{
std::vector<Object> v;
for (const auto& tmxObj : objGroups.value().get())
{
auto it = objMapping.find(std::string(tmxObj.Name()));
if (it == objMapping.end())
continue;
const auto& pos = tmxObj.Pos();
Object obj;
obj.id = it->second;
obj.x = pos.x;
obj.y = pos.y;
v.emplace_back(obj);
}
/*
for (const auto& group : objGroups)
{
const auto& tmxObjects = group.get().Objects();
v.reserve(v.size() + tmxObjects.size());
for (const auto& tmxObj : tmxObjects)
{
auto it = objMapping.find(tmxObj.getName());
auto it = objMapping.find(std::string(tmxObj.Name()));
if (it == objMapping.end())
continue;
const auto& aabb = tmxObj.getAABB();
const auto& pos = tmxObj.Pos();
Object obj;
obj.id = it->second;
obj.x = aabb.left;
obj.y = aabb.top;
obj.x = pos.x;
obj.y = pos.y;
v.emplace_back(obj);
}
}
*/
mObjects.emplace(v);
}
*/
return Error::OK;
}

View File

@@ -16,8 +16,8 @@ public:
TmxTileset(const std::string_view name, const std::string_view source, uint32_t firstGid, uint32_t lastGid)
: mName(name), mSource(source), mFirstGid(firstGid), mLastGid(lastGid) {}
[[nodiscard]] constexpr const std::string_view Name() const noexcept { return mName; }
[[nodiscard]] constexpr const std::string_view Source() const noexcept { return mSource; }
[[nodiscard]] const std::string_view Name() const noexcept { return mName; }
[[nodiscard]] const std::string_view Source() const noexcept { return mSource; }
[[nodiscard]] constexpr const std::pair<uint32_t, uint32_t> GidRange() const noexcept { return { mFirstGid, mLastGid }; }
};