commit 6e5a7ebb5e158b50a36d5c8f8a1e33987a5242eb
parent 85bc759a8730d4de1d897c729e7bd05206b7bcb5
Author: cfillion <cfillion@users.noreply.github.com>
Date: Wed, 25 Nov 2015 20:24:00 -0500
implement another part of the xml database parser
Diffstat:
11 files changed, 254 insertions(+), 14 deletions(-)
diff --git a/src/database.cpp b/src/database.cpp
@@ -2,8 +2,6 @@
#include <WDL/tinyxml/tinyxml.h>
-#include <cstdio>
-
DatabasePtr Database::load(const char *file, const char **error)
{
TiXmlDocument doc(file);
@@ -38,12 +36,34 @@ DatabasePtr Database::load(const char *file, const char **error)
}
}
-Database::Database()
+void Database::addCategory(CategoryPtr cat)
+{
+ m_categories.push_back(cat);
+}
+
+Category::Category(const std::string &name)
+ : m_name(name)
+{
+}
+
+void Category::addPackage(PackagePtr pack)
+{
+ pack->setCategory(this);
+ m_packages.push_back(pack);
+}
+
+Package::Type Package::convertType(const char *type)
{
- printf("constructed\n");
+ if(!type)
+ return UnknownType;
+
+ if(!strcmp(type, "script"))
+ return ScriptType;
+
+ return UnknownType;
}
-Database::~Database()
+Package::Package()
+ : m_category(0)
{
- printf("destructed\n");
}
diff --git a/src/database.hpp b/src/database.hpp
@@ -2,21 +2,73 @@
#define REAPACK_DATABASE_HPP
#include <memory>
+#include <string>
+#include <vector>
class TiXmlElement;
class Database;
typedef std::shared_ptr<Database> DatabasePtr;
+class Category;
+typedef std::shared_ptr<Category> CategoryPtr;
+
+class Package;
+typedef std::shared_ptr<Package> PackagePtr;
+
class Database {
public:
static DatabasePtr load(const char *, const char **error);
- Database();
- ~Database();
+ void addCategory(CategoryPtr cat);
+ const std::vector<CategoryPtr> &categories() const { return m_categories; }
+ CategoryPtr category(const int i) const { return m_categories[i]; }
private:
+ friend Category;
static DatabasePtr loadV1(TiXmlElement *, const char **);
+
+ std::vector<CategoryPtr> m_categories;
+};
+
+class Category {
+public:
+ Category(const std::string &name);
+
+ const std::string &name() const { return m_name; }
+
+ void addPackage(PackagePtr pack);
+ const std::vector<PackagePtr> &packages() const { return m_packages; }
+ PackagePtr package(const int i) const { return m_packages[i]; }
+
+private:
+ friend Package;
+ friend DatabasePtr Database::loadV1(TiXmlElement *, const char **);
+ static CategoryPtr loadV1(TiXmlElement *, const char **);
+
+ std::string m_name;
+ std::vector<PackagePtr> m_packages;
+};
+
+class Package {
+public:
+ enum Type {
+ UnknownType,
+ ScriptType,
+ };
+
+ static Type convertType(const char *);
+
+ Package();
+
+ void setCategory(Category *cat) { m_category = cat; }
+ Category *category() const { return m_category; }
+
+private:
+ friend CategoryPtr Category::loadV1(TiXmlElement *, const char **);
+ static PackagePtr loadV1(TiXmlElement *, const char **);
+
+ Category *m_category;
};
#endif
diff --git a/src/database_v1.cpp b/src/database_v1.cpp
@@ -2,23 +2,88 @@
#include <WDL/tinyxml/tinyxml.h>
+using namespace std;
+
DatabasePtr Database::loadV1(TiXmlElement *root, const char **error)
{
- DatabasePtr db = std::make_shared<Database>();
+ DatabasePtr db = make_shared<Database>();
// read categories
- TiXmlElement *catNode = root->FirstChildElement("category");
+ TiXmlElement *catNode = root->FirstChildElement();
while(catNode) {
- const char *name = catNode->Attribute("name");
+ CategoryPtr cat = Category::loadV1(catNode, error);
- if(!name) {
- *error = "missing category name";
+ if(!cat.get())
return 0;
- }
+
+ db->addCategory(cat);
catNode = catNode->NextSiblingElement();
}
return db;
}
+
+CategoryPtr Category::loadV1(TiXmlElement *catNode, const char **error)
+{
+ if(strcmp(catNode->Value(), "category")) {
+ *error = "not a category";
+ return 0;
+ }
+
+ const char *name = catNode->Attribute("name");
+
+ if(!name || !strlen(name)) {
+ *error = "missing category name";
+ return 0;
+ }
+
+ CategoryPtr cat = make_shared<Category>(name);
+
+ TiXmlElement *packNode = catNode->FirstChildElement();
+
+ while(packNode) {
+ PackagePtr pack = Package::loadV1(packNode, error);
+
+ if(!pack.get())
+ return 0;
+
+ cat->addPackage(pack);
+
+ packNode = packNode->NextSiblingElement();
+ }
+ return cat;
+}
+
+PackagePtr Package::loadV1(TiXmlElement *packNode, const char **error)
+{
+ if(strcmp(packNode->Value(), "reapack")) {
+ *error = "not a package";
+ return 0;
+ }
+
+ const char *name = packNode->Attribute("name");
+
+ if(!name || !strlen(name)) {
+ *error = "missing package name";
+ return 0;
+ }
+
+ const char *typeStr = packNode->Attribute("type");
+ const Package::Type type = Package::convertType(typeStr);
+
+ if(type == Package::UnknownType) {
+ *error = "unsupported package type";
+ return 0;
+ }
+
+ const char *author = packNode->Attribute("author");
+
+ if(!author || !strlen(author)) {
+ *error = "package is anonymous";
+ return 0;
+ }
+
+ return 0;
+}
diff --git a/test/database.cpp b/test/database.cpp
@@ -48,3 +48,39 @@ TEST_CASE("future version", M) {
CHECK(db.get() == 0);
REQUIRE(string(error) == "unsupported version");
}
+
+TEST_CASE("add category to database", M) {
+ Database db;
+ CHECK(db.categories().size() == 0);
+
+ db.addCategory(make_shared<Category>("a"));
+
+ REQUIRE(db.categories().size() == 1);
+}
+
+TEST_CASE("add package to category", M) {
+ PackagePtr pack = make_shared<Package>();
+
+ Category cat("a");
+ CHECK(cat.packages().size() == 0);
+ CHECK_FALSE(pack->category());
+
+ cat.addPackage(pack);
+
+ REQUIRE(cat.packages().size() == 1);
+ REQUIRE(pack->category() == &cat);
+}
+
+TEST_CASE("package type from string", M) {
+ SECTION("null") {
+ REQUIRE(Package::convertType(0) == Package::UnknownType);
+ }
+
+ SECTION("unknown") {
+ REQUIRE(Package::convertType("yoyo") == Package::UnknownType);
+ }
+
+ SECTION("script") {
+ REQUIRE(Package::convertType("script") == Package::ScriptType);
+ }
+}
diff --git a/test/database_v1.cpp b/test/database_v1.cpp
@@ -17,3 +17,45 @@ TEST_CASE("unnamed category", M) {
CHECK(db.get() == 0);
REQUIRE(string(error) == "missing category name");
}
+
+TEST_CASE("empty category", M) {
+ const char *error = 0;
+ DatabasePtr db = Database::load(DBPATH "empty_category.xml", &error);
+
+ REQUIRE(error == 0);
+ REQUIRE(db->categories().size() == 1);
+ REQUIRE(db->category(0)->name() == "Hello World");
+ REQUIRE(db->category(0)->packages().empty());
+}
+
+TEST_CASE("invalid category tag", M) {
+ const char *error = "";
+ DatabasePtr db = Database::load(DBPATH "wrong_category_tag.xml", &error);
+
+ CHECK(db.get() == 0);
+ REQUIRE(string(error) == "not a category");
+}
+
+TEST_CASE("unnamed package", M) {
+ const char *error = "";
+ DatabasePtr db = Database::load(DBPATH "unnamed_package.xml", &error);
+
+ CHECK(db.get() == 0);
+ REQUIRE(string(error) == "missing package name");
+}
+
+TEST_CASE("invalid package type", M) {
+ const char *error = "";
+ DatabasePtr db = Database::load(DBPATH "invalid_type.xml", &error);
+
+ CHECK(db.get() == 0);
+ REQUIRE(string(error) == "unsupported package type");
+}
+
+TEST_CASE("anonymous package", M) {
+ const char *error = "";
+ DatabasePtr db = Database::load(DBPATH "anonymous_package.xml", &error);
+
+ CHECK(db.get() == 0);
+ REQUIRE(string(error) == "package is anonymous");
+}
diff --git a/test/db/v1/anonymous_package.xml b/test/db/v1/anonymous_package.xml
@@ -0,0 +1,6 @@
+<index version="1">
+ <category name="test">
+ <reapack name="abc" type="script" />
+ <reapack name="abc" type="script" author="" />
+ </category>
+</index>
diff --git a/test/db/v1/empty_category.xml b/test/db/v1/empty_category.xml
@@ -0,0 +1,3 @@
+<index version="1">
+ <category name="Hello World"/>
+</index>
diff --git a/test/db/v1/invalid_type.xml b/test/db/v1/invalid_type.xml
@@ -0,0 +1,6 @@
+<index version="1">
+ <category name="test">
+ <reapack name="a" />
+ <reapack name="c" type="yoyo" />
+ </category>
+</index>
diff --git a/test/db/v1/unnamed_category.xml b/test/db/v1/unnamed_category.xml
@@ -1,3 +1,4 @@
<index version="1">
<category />
+ <category name="" />
</index>
diff --git a/test/db/v1/unnamed_package.xml b/test/db/v1/unnamed_package.xml
@@ -0,0 +1,6 @@
+<index version="1">
+ <category name="test">
+ <reapack />
+ <reapack name="" />
+ </category>
+</index>
diff --git a/test/db/v1/wrong_category_tag.xml b/test/db/v1/wrong_category_tag.xml
@@ -0,0 +1,3 @@
+<index version="1">
+ <hello_world />
+</index>