summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorljfa-ag <ljfa-ag@web.de>2015-08-09 19:33:39 +0200
committerljfa-ag <ljfa-ag@web.de>2015-08-09 19:33:39 +0200
commit12374391af5b876094b802408e9b0e92429ae3c1 (patch)
treed42489e01384a77a5e6815244e2da43c05c0f6d0
parentb992d074054dc03b548e6b8a169cff5e1788ea73 (diff)
downloadProject-Tick-12374391af5b876094b802408e9b0e92429ae3c1.tar.gz
Project-Tick-12374391af5b876094b802408e9b0e92429ae3c1.zip
Implement Visitor design pattern for tag
-rw-r--r--include/crtp_tag.h9
-rw-r--r--include/tag.h9
-rw-r--r--include/tag_visitor.h55
-rw-r--r--test/nbttest.cpp46
4 files changed, 118 insertions, 1 deletions
diff --git a/include/crtp_tag.h b/include/crtp_tag.h
index 25f87bf6e8..86f070e147 100644
--- a/include/crtp_tag.h
+++ b/include/crtp_tag.h
@@ -21,6 +21,7 @@
#define CRTP_TAG_H_INCLUDED
#include "tag.h"
+#include "tag_visitor.h"
#include "make_unique.h"
namespace nbt
@@ -43,6 +44,8 @@ namespace detail
tag& assign(tag&& rhs) override final;
+ void accept(tag_visitor& visitor);
+
private:
bool equals(const tag& rhs) const override final;
};
@@ -75,6 +78,12 @@ namespace detail
}
template<class Sub>
+ void crtp_tag<Sub>::accept(tag_visitor& visitor)
+ {
+ visitor.visit(static_cast<Sub&>(*this));
+ }
+
+ template<class Sub>
bool crtp_tag<Sub>::equals(const tag& rhs) const
{
return static_cast<const Sub&>(*this) == static_cast<const Sub&>(rhs);
diff --git a/include/tag.h b/include/tag.h
index 569da446d6..f3e9696a53 100644
--- a/include/tag.h
+++ b/include/tag.h
@@ -51,7 +51,8 @@ enum class tag_type : int8_t
*/
bool is_valid_type(int type, bool allow_end = false);
-//Forward declaration
+//Forward declarations
+class tag_visitor;
namespace io
{ class stream_reader; }
@@ -86,6 +87,12 @@ public:
virtual tag& assign(tag&& rhs) = 0;
/**
+ * @brief Calls the appropriate overload of @c visit() on the visitor with
+ * @c *this as argument
+ */
+ virtual void accept(tag_visitor& visitor) = 0;
+
+ /**
* @brief Reads the tag's payload from the stream
* @throw io::stream_reader::input_error on failure
*/
diff --git a/include/tag_visitor.h b/include/tag_visitor.h
new file mode 100644
index 0000000000..bc5113918c
--- /dev/null
+++ b/include/tag_visitor.h
@@ -0,0 +1,55 @@
+/*
+ * libnbt++ - A library for the Minecraft Named Binary Tag format.
+ * Copyright (C) 2013, 2015 ljfa-ag
+ *
+ * This file is part of libnbt++.
+ *
+ * libnbt++ is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * libnbt++ is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libnbt++. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef TAG_VISITOR_H_INCLUDED
+#define TAG_VISITOR_H_INCLUDED
+
+#include "tagfwd.h"
+
+namespace nbt
+{
+
+/**
+ * @brief Base class for visitors of tags
+ *
+ * Implementing the Visitor pattern
+ */
+class tag_visitor
+{
+public:
+ virtual ~tag_visitor() noexcept = 0; //Abstract class
+
+ virtual void visit(tag_byte& tag) {}
+ virtual void visit(tag_short& tag) {}
+ virtual void visit(tag_int& tag) {}
+ virtual void visit(tag_long& tag) {}
+ virtual void visit(tag_float& tag) {}
+ virtual void visit(tag_double& tag) {}
+ virtual void visit(tag_byte_array& tag) {}
+ virtual void visit(tag_string& tag) {}
+ virtual void visit(tag_list& tag) {}
+ virtual void visit(tag_compound& tag) {}
+ virtual void visit(tag_int_array& tag) {}
+};
+
+inline tag_visitor::~tag_visitor() noexcept {}
+
+}
+
+#endif // TAG_VISITOR_H_INCLUDED
diff --git a/test/nbttest.cpp b/test/nbttest.cpp
index b041d44aa8..4c46668f0b 100644
--- a/test/nbttest.cpp
+++ b/test/nbttest.cpp
@@ -19,6 +19,7 @@
*/
#include "microtest.h"
#include "nbt_tags.h"
+#include "tag_visitor.h"
#include <algorithm>
#include <stdexcept>
@@ -425,6 +426,50 @@ void test_tag_int_array()
std::clog << "test_tag_int_array passed" << std::endl;
}
+void test_visitor()
+{
+ struct : public tag_visitor
+ {
+ tag_type visited = tag_type::Null;
+
+ void visit(tag_byte& tag) override { visited = tag_type::Byte; }
+ void visit(tag_short& tag) override { visited = tag_type::Short; }
+ void visit(tag_int& tag) override { visited = tag_type::Int; }
+ void visit(tag_long& tag) override { visited = tag_type::Long; }
+ void visit(tag_float& tag) override { visited = tag_type::Float; }
+ void visit(tag_double& tag) override { visited = tag_type::Double; }
+ void visit(tag_byte_array& tag) override { visited = tag_type::Byte_Array; }
+ void visit(tag_string& tag) override { visited = tag_type::String; }
+ void visit(tag_list& tag) override { visited = tag_type::List; }
+ void visit(tag_compound& tag) override { visited = tag_type::Compound; }
+ void visit(tag_int_array& tag) override { visited = tag_type::Int_Array; }
+ } v;
+
+ tag_byte().accept(v);
+ ASSERT(v.visited == tag_type::Byte);
+ tag_short().accept(v);
+ ASSERT(v.visited == tag_type::Short);
+ tag_int().accept(v);
+ ASSERT(v.visited == tag_type::Int);
+ tag_long().accept(v);
+ ASSERT(v.visited == tag_type::Long);
+ tag_float().accept(v);
+ ASSERT(v.visited == tag_type::Float);
+ tag_double().accept(v);
+ ASSERT(v.visited == tag_type::Double);
+ tag_byte_array().accept(v);
+ ASSERT(v.visited == tag_type::Byte_Array);
+ tag_string().accept(v);
+ ASSERT(v.visited == tag_type::String);
+ tag_list().accept(v);
+ ASSERT(v.visited == tag_type::List);
+ tag_compound().accept(v);
+ ASSERT(v.visited == tag_type::Compound);
+ tag_int_array().accept(v);
+ ASSERT(v.visited == tag_type::Int_Array);
+ std::clog << "test_visitor passed" << std::endl;
+}
+
int main()
{
test_tag();
@@ -436,4 +481,5 @@ int main()
test_tag_list();
test_tag_byte_array();
test_tag_int_array();
+ test_visitor();
}