diff options
author | Andreas Stöckel <astoecke@techfak.uni-bielefeld.de> | 2014-12-11 22:30:50 +0100 |
---|---|---|
committer | Andreas Stöckel <astoecke@techfak.uni-bielefeld.de> | 2014-12-11 22:30:50 +0100 |
commit | be370445362aff67b70f80567b8cf6099c72ddd8 (patch) | |
tree | 28339e19fc9566c7bc83e38a25f2fdf2f039f514 | |
parent | d43b75cb459136e1d0c9df5447151069094f341d (diff) | |
parent | 3d1e59ff0b3116255b70f6247137009903cd530b (diff) |
Merge branch 'master' of somweyr.de:ousia
-rw-r--r-- | CMakeLists.txt | 23 | ||||
-rw-r--r-- | src/core/ResourceLocator.hpp | 4 | ||||
-rw-r--r-- | src/plugins/boost/FileLocator.cpp | 77 | ||||
-rw-r--r-- | src/plugins/boost/FileLocator.hpp | 22 | ||||
-rw-r--r-- | test/core/RegistryTest.cpp | 4 | ||||
-rw-r--r-- | test/core/ResourceLocatorTest.cpp | 6 | ||||
-rw-r--r-- | test/plugins/boost/FileLocatorTest.cpp | 146 |
7 files changed, 270 insertions, 12 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 3cfa185..39d04e1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,10 +32,11 @@ OPTION(BUILD_DOCUMENTATION "Create and install the HTML based API documentation # Enable C++11 and all warnings SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic-errors -std=c++11") -# Include expat and mozjs-24 via PkgConfig +# Include boost (filesystem) expat and mozjs-24 via PkgConfig FIND_PACKAGE(PkgConfig REQUIRED) PKG_CHECK_MODULES(MOZJS REQUIRED mozjs-24) PKG_CHECK_MODULES(EXPAT REQUIRED expat) +FIND_PACKAGE(Boost COMPONENTS system filesystem REQUIRED) ################################################################################ # Inclusion of doxygen # @@ -85,6 +86,7 @@ INCLUDE_DIRECTORIES( src/ ${MOZJS_INCLUDE_DIRS} ${EXPAT_INCLUDE_DIRS} + ${Boost_INCLUDE_DIR} ) # Link directories @@ -120,6 +122,15 @@ ADD_LIBRARY(ousia_core # src/core/script/Variant ) +ADD_LIBRARY(ousia_boost + src/plugins/boost/FileLocator +) + +TARGET_LINK_LIBRARIES(ousia_boost + ousia_core + ${Boost_LIBRARIES} +) + ADD_LIBRARY(ousia_css src/plugins/css/CSSParser ) @@ -179,6 +190,16 @@ IF(TEST) ousia_core ) + ADD_EXECUTABLE(ousia_test_boost + test/plugins/boost/FileLocatorTest + ) + + TARGET_LINK_LIBRARIES(ousia_test_boost + ${GTEST_LIBRARIES} + ousia_core + ousia_boost + ) + ADD_EXECUTABLE(ousia_test_css test/plugins/css/CSSParserTest ) diff --git a/src/core/ResourceLocator.hpp b/src/core/ResourceLocator.hpp index 36930e9..926b312 100644 --- a/src/core/ResourceLocator.hpp +++ b/src/core/ResourceLocator.hpp @@ -39,11 +39,11 @@ public: */ enum class Type { // A Domain description - DOMAIN, + DOMAIN_DESC, // An ECMA/JavaScript SCRIPT, // A Type System - TYPESYSTEM, + TYPESYS, // TODO: Aren't documents and attribute descriptors missing? // TODO: What is the purpose of these two? GENERIC_MODULE, diff --git a/src/plugins/boost/FileLocator.cpp b/src/plugins/boost/FileLocator.cpp new file mode 100644 index 0000000..ed9d0c9 --- /dev/null +++ b/src/plugins/boost/FileLocator.cpp @@ -0,0 +1,77 @@ +/* + Ousía + Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "FileLocator.hpp" + +#include <fstream> + +namespace ousia { + +void FileLocator::addSearchPath(const boost::filesystem::path &path, + std::set<ResourceLocator::Type> types) +{ + for (auto &type : types) { + // retrieve the path vector for the given type. + auto it = searchPaths.find(type); + if (it != searchPaths.end()) { + it->second.push_back(path); + } else { + std::vector<boost::filesystem::path> v{path}; + searchPaths.insert({type, v}); + } + } +} + +ResourceLocator::Location FileLocator::locate(const std::string &path, + const std::string &relativeTo, + const Type type) const +{ + boost::filesystem::path base(relativeTo); + // use the / operator to append the path. + base /= path; + // if we already found a fitting resource there, use that. + if (boost::filesystem::exists(base)) { + std::string location = + boost::filesystem::canonical(base).generic_string(); + return ResourceLocator::Location(true, *this, type, location); + } + // otherwise look in the search paths. + auto it = searchPaths.find(type); + if (it != searchPaths.end()) { + for (boost::filesystem::path p : it->second) { + p /= path; + if (boost::filesystem::exists(p)) { + std::string location = + boost::filesystem::canonical(p).generic_string(); + return ResourceLocator::Location(true, *this, type, location); + } + } + } + // if we find the resource in none of the search paths we return a location. + // with the found flag set to false. + ResourceLocator::Location l(false, *this, type, ""); + return l; +} + +std::unique_ptr<std::istream> FileLocator::stream( + const std::string &location) const +{ + std::unique_ptr<std::istream> ifs{new std::ifstream(location)}; + return std::move(ifs); +} +} diff --git a/src/plugins/boost/FileLocator.hpp b/src/plugins/boost/FileLocator.hpp index 50a77db..9cb705c 100644 --- a/src/plugins/boost/FileLocator.hpp +++ b/src/plugins/boost/FileLocator.hpp @@ -19,10 +19,14 @@ #ifndef _OUSIA_FILE_LOCATOR_HPP_ #define _OUSIA_FILE_LOCATOR_HPP_ +#include <core/ResourceLocator.hpp> + #include <map> #include <set> +#include <vector> + +#include <boost/filesystem.hpp> -#include <core/ResourceLocator.hpp> namespace ousia { @@ -36,10 +40,10 @@ namespace ousia { */ class FileLocator : public ResourceLocator { private: - map<ResourceLocator::Type, std::vector<std::string>> searchPaths; + std::map<ResourceLocator::Type, std::vector<boost::filesystem::path>> searchPaths; public: - FileLocator() searchpaths() {} + FileLocator() : searchPaths() {} /** * Adds a search paths for the given types. @@ -49,9 +53,19 @@ public: * resources of the specified types at the given path in the * future. */ - void addSearchPath(const std::string &path, + void addSearchPath(const boost::filesystem::path &path, std::set<ResourceLocator::Type> types); + /** + * Returns the backing map containing all search paths for a given type. + * This is read-only. + */ + const std::map<ResourceLocator::Type, std::vector<boost::filesystem::path>> & + getSearchPaths() const + { + return searchPaths; + } + Location locate(const std::string &path, const std::string &relativeTo, const Type type) const override; diff --git a/test/core/RegistryTest.cpp b/test/core/RegistryTest.cpp index 22365f2..8280188 100644 --- a/test/core/RegistryTest.cpp +++ b/test/core/RegistryTest.cpp @@ -54,9 +54,9 @@ TEST(Registry, locateResource) instance.registerResourceLocator(&locator); ResourceLocator::Location location = - instance.locateResource("path", "", ResourceLocator::Type::DOMAIN); + instance.locateResource("path", "", ResourceLocator::Type::DOMAIN_DESC); ASSERT_TRUE(location.found); - ASSERT_EQ(ResourceLocator::Type::DOMAIN, location.type); + ASSERT_EQ(ResourceLocator::Type::DOMAIN_DESC, location.type); ASSERT_EQ("path", location.location); } diff --git a/test/core/ResourceLocatorTest.cpp b/test/core/ResourceLocatorTest.cpp index 38cfc3e..ebb164d 100644 --- a/test/core/ResourceLocatorTest.cpp +++ b/test/core/ResourceLocatorTest.cpp @@ -48,9 +48,9 @@ TEST(ResourceLocator, locate) { TestResourceLocator instance; ResourceLocator::Location location = - instance.locate("path", "", ResourceLocator::Type::DOMAIN); + instance.locate("path", "", ResourceLocator::Type::DOMAIN_DESC); ASSERT_TRUE(location.found); - ASSERT_EQ(ResourceLocator::Type::DOMAIN, location.type); + ASSERT_EQ(ResourceLocator::Type::DOMAIN_DESC, location.type); ASSERT_EQ("path", location.location); } @@ -58,7 +58,7 @@ TEST(ResourceLocator, stream) { TestResourceLocator instance; ResourceLocator::Location location = - instance.locate("path", "", ResourceLocator::Type::DOMAIN); + instance.locate("path", "", ResourceLocator::Type::DOMAIN_DESC); std::unique_ptr<std::istream> is = location.stream(); std::string str; diff --git a/test/plugins/boost/FileLocatorTest.cpp b/test/plugins/boost/FileLocatorTest.cpp new file mode 100644 index 0000000..2057a9f --- /dev/null +++ b/test/plugins/boost/FileLocatorTest.cpp @@ -0,0 +1,146 @@ +/* + Ousía + Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <gtest/gtest.h> + +#include <plugins/boost/FileLocator.hpp> + +namespace ousia { +TEST(FileLocator, testAddSearchPath) +{ + FileLocator instance; + ASSERT_EQ(0, instance.getSearchPaths().size()); + + // Add one path for three types. + instance.addSearchPath( + ".", {ResourceLocator::Type::DOMAIN_DESC, ResourceLocator::Type::SCRIPT, + ResourceLocator::Type::TYPESYS}); + + ASSERT_EQ(3, instance.getSearchPaths().size()); + + auto it = + instance.getSearchPaths().find(ResourceLocator::Type::DOMAIN_DESC); + + ASSERT_EQ(1, it->second.size()); + ASSERT_EQ(".", it->second[0].generic_string()); + + it = instance.getSearchPaths().find(ResourceLocator::Type::SCRIPT); + + ASSERT_EQ(1, it->second.size()); + ASSERT_EQ(".", it->second[0].generic_string()); + + it = instance.getSearchPaths().find(ResourceLocator::Type::TYPESYS); + + ASSERT_EQ(1, it->second.size()); + ASSERT_EQ(".", it->second[0].generic_string()); + + // Add another path for only one of those types. + + instance.addSearchPath("..", {ResourceLocator::Type::DOMAIN_DESC}); + + ASSERT_EQ(3, instance.getSearchPaths().size()); + + it = instance.getSearchPaths().find(ResourceLocator::Type::DOMAIN_DESC); + + ASSERT_EQ(2, it->second.size()); + ASSERT_EQ(".", it->second[0].generic_string()); + ASSERT_EQ("..", it->second[1].generic_string()); +} + +void assert_located( + const FileLocator &instance, const std::string &path, + const std::string &relativeTo, + ResourceLocator::Type type = ResourceLocator::Type::DOMAIN_DESC) +{ + ResourceLocator::Location loc = instance.locate(path, relativeTo, type); + ASSERT_TRUE(loc.found); + boost::filesystem::path p(loc.location); + ASSERT_TRUE(boost::filesystem::exists(p)); + ASSERT_EQ(path, p.filename()); +} + +void assert_not_located( + const FileLocator &instance, const std::string &path, + const std::string &relativeTo, + ResourceLocator::Type type = ResourceLocator::Type::DOMAIN_DESC) +{ + ResourceLocator::Location loc = instance.locate(path, relativeTo, type); + ASSERT_FALSE(loc.found); +} + +TEST(FileLocator, testLocate) +{ + // Initialization + boost::filesystem::path start("."); + start = boost::filesystem::canonical(start); + std::string relativeTo; + + if (start.filename() == "build") { + relativeTo = ".."; + start = start.parent_path(); + } else if (start.filename() == "application") { + relativeTo = "."; + } else { + ASSERT_TRUE(false); + } + FileLocator instance; + + // We should be able to find the CMakeLists file in the main directory. + assert_located(instance, "CMakeLists.txt", relativeTo); + // But not the FileLocator.hpp + assert_not_located(instance, "FileLocator.hpp", relativeTo); + + // Add the respective search path. + instance.addSearchPath(start / "src/plugins/boost", + {ResourceLocator::Type::DOMAIN_DESC}); + // Now we should be able to find both. + assert_located(instance, "CMakeLists.txt", relativeTo); + assert_located(instance, "FileLocator.hpp", relativeTo); + // but only with the correct type. + assert_not_located(instance, "FileLocator.hpp", relativeTo, + ResourceLocator::Type::SCRIPT); +} + +TEST(FileLocator, testStream) +{ + // Initialization + boost::filesystem::path start("."); + start = boost::filesystem::canonical(start); + std::string relativeTo; + + if (start.filename() == "build") { + relativeTo = ".."; + start = start.parent_path(); + } else if (start.filename() == "application") { + relativeTo = "."; + } else { + ASSERT_TRUE(false); + } + FileLocator instance; + // Locate the CMakeLists.txt + ResourceLocator::Location loc = instance.locate( + "CMakeLists.txt", relativeTo, ResourceLocator::Type::DOMAIN_DESC); + // Stream the content. + auto is_ptr = loc.stream(); + // get the beginning. + char buf[256]; + is_ptr->getline(buf, 256); + std::string first_line(buf); + ASSERT_EQ("# Ousía", first_line); +} +} |