This is an automated email from the ASF dual-hosted git repository. bennoe pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mesos.git
commit ddf59b8b99b95fe3dc0e862f36dfeed2c0fd287a Author: Benjamin Bannier <[email protected]> AuthorDate: Tue Jan 7 13:19:04 2020 +0100 Added iteration support to stout's Path. Review: https://reviews.apache.org/r/71878/ --- 3rdparty/stout/include/stout/path.hpp | 85 +++++++++++++++++++++++++++++++++++ 3rdparty/stout/tests/path_tests.cpp | 44 ++++++++++++++++++ 2 files changed, 129 insertions(+) diff --git a/3rdparty/stout/include/stout/path.hpp b/3rdparty/stout/include/stout/path.hpp index ba1f665..0aa3b01 100644 --- a/3rdparty/stout/include/stout/path.hpp +++ b/3rdparty/stout/include/stout/path.hpp @@ -17,6 +17,8 @@ #include <utility> #include <vector> +#include <glog/logging.h> + #include <stout/stringify.hpp> #include <stout/strings.hpp> @@ -379,6 +381,89 @@ public: return value; } + // An iterator over path components. Paths are expected to be normalized. + // + // The effect of using this iterator is to split the path at its + // separator and iterate over the different splits. This means in + // particular that this class performs no path normalization. + class const_iterator + { + public: + using iterator_category = std::forward_iterator_tag; + using value_type = std::string; + using difference_type = std::string::const_iterator::difference_type; + using pointer = std::string::const_iterator::pointer; + + // We cannot return a reference type (or `const char*` for that + // matter) as we neither own string values nor deal with setting up + // proper null-terminated output buffers. + // + // TODO(bbannier): Consider introducing a `string_view`-like class + // to wrap path components and use it as a reference type here and as + // `value_type`, and as return value for most `Path` member functions above. + using reference = std::string; + + explicit const_iterator( + const Path* path_, + std::string::const_iterator offset_) + : path(path_), offset(offset_) {} + + // Disallow construction from temporary as we hold a reference to `path`. + explicit const_iterator(Path&& path) = delete; + + const_iterator& operator++() + { + offset = std::find(offset, path->string().end(), path->separator); + + // If after incrementing we have reached the end return immediately. + if (offset == path->string().end()) { + return *this; + } else { + // If we are not at the end we have a separator to skip. + ++offset; + } + + return *this; + } + + const_iterator operator++(int) + { + const_iterator it = *this; + ++(*this); + return it; + } + + bool operator==(const const_iterator& other) const + { + CHECK_EQ(path, other.path) + << "Iterators into different paths cannot be compared"; + + return (!path && !other.path) || offset == other.offset; + } + + bool operator!=(const const_iterator& other) const + { + return !(*this == other); + } + + reference operator*() const + { + auto end = std::find(offset, path->string().end(), path->separator); + return reference(offset, end); + } + + private: + const Path* path = nullptr; + std::string::const_iterator offset; + }; + + const_iterator begin() const + { + return const_iterator(this, string().begin()); + } + + const_iterator end() const { return const_iterator(this, string().end()); } + private: std::string value; char separator; diff --git a/3rdparty/stout/tests/path_tests.cpp b/3rdparty/stout/tests/path_tests.cpp index 19dd910..41c5f6c 100644 --- a/3rdparty/stout/tests/path_tests.cpp +++ b/3rdparty/stout/tests/path_tests.cpp @@ -398,6 +398,50 @@ TEST(PathTest, FromURI) } +TEST(PathTest, PathIteration) +{ + { + // An empty path should contain no elements and have its begin and + // end iterators compare equal. + Path path; + EXPECT_EQ(0u, std::distance(path.begin(), path.end())); + EXPECT_EQ(path.begin(), path.end()); + } + + { + // Checks for behavior of relative paths. + const vector<string> components{"1", "2", "3", "4", "5", "file.ext"}; + const Path relative_path( + strings::join(string(1, os::PATH_SEPARATOR), components)); + + EXPECT_NE(relative_path.begin(), relative_path.end()); + EXPECT_EQ( + components.size(), + std::distance(relative_path.begin(), relative_path.end())); + + EXPECT_EQ( + components, vector<string>(relative_path.begin(), relative_path.end())); + } + + { + // Checks for behavior of absolute paths. + const vector<string> components{"", "1", "2", "3", "4", "5", "file.ext"}; + const Path absolute_path( + strings::join(string(1, os::PATH_SEPARATOR), components)); + + ASSERT_TRUE(absolute_path.absolute()); + + EXPECT_NE(absolute_path.begin(), absolute_path.end()); + EXPECT_EQ( + components.size(), + std::distance(absolute_path.begin(), absolute_path.end())); + + EXPECT_EQ( + components, vector<string>(absolute_path.begin(), absolute_path.end())); + } +} + + class PathFileTest : public TemporaryDirectoryTest {};
