From 70a8403575cb8ea66d01b9abd32e98d33300527b Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Wed, 4 Mar 2009 15:53:56 +0000 Subject: [PATCH] 2009-03-05 Tatsuhiro Tsujikawa Added Util::pathJoin() * src/Util.h * test/UtilTest.cc --- ChangeLog | 6 ++++++ src/Util.h | 27 +++++++++++++++++++++++++++ test/UtilTest.cc | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+) diff --git a/ChangeLog b/ChangeLog index 4bc93e9e..ca2fa79f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2009-03-05 Tatsuhiro Tsujikawa + + Added Util::pathJoin() + * src/Util.h + * test/UtilTest.cc + 2009-03-04 Tatsuhiro Tsujikawa Applied basename function to remove directory element in diff --git a/src/Util.h b/src/Util.h index de51f699..f171ac13 100644 --- a/src/Util.h +++ b/src/Util.h @@ -43,11 +43,13 @@ #include #include #include +#include #include "SharedHandle.h" #include "IntSequence.h" #include "a2time.h" #include "a2netcompat.h" +#include "a2functional.h" namespace aria2 { @@ -279,6 +281,31 @@ public: getNumericNameInfo(const struct sockaddr* sockaddr, socklen_t len); static std::string htmlEscape(const std::string& src); + + // Joins path element specified in [first, last). If ".." is found, + // it eats the previous element if it exists. If "." is found, it + // is just ignored and it is not appeared in the result. + template + static std::string joinPath(InputIterator first, InputIterator last) + { + std::deque elements; + for(;first != last; ++first) { + if(*first == "..") { + if(!elements.empty()) { + elements.pop_back(); + } + } else if(*first == ".") { + // do nothing + } else { + elements.push_back(*first); + } + } + if(elements.empty()) { + return ""; + } + return std::accumulate(elements.begin()+1, elements.end(), elements[0], + Concat("/")); + } }; } // namespace aria2 diff --git a/test/UtilTest.cc b/test/UtilTest.cc index 808f1db6..cc3a38b7 100644 --- a/test/UtilTest.cc +++ b/test/UtilTest.cc @@ -11,6 +11,7 @@ #include "ByteArrayDiskWriter.h" #include "FileEntry.h" #include "File.h" +#include "array_fun.h" namespace aria2 { @@ -52,6 +53,7 @@ class UtilTest:public CppUnit::TestFixture { CPPUNIT_TEST(testNtoh64); CPPUNIT_TEST(testUrlencode); CPPUNIT_TEST(testHtmlEscape); + CPPUNIT_TEST(testJoinPath); CPPUNIT_TEST_SUITE_END(); private: @@ -94,6 +96,7 @@ public: void testNtoh64(); void testUrlencode(); void testHtmlEscape(); + void testJoinPath(); }; @@ -741,4 +744,38 @@ void UtilTest::testHtmlEscape() Util::htmlEscape("aria2<>\"'util")); } +void UtilTest::testJoinPath() +{ + const std::string dir1dir2file[] = { "dir1", "dir2", "file" }; + CPPUNIT_ASSERT_EQUAL + (std::string("dir1/dir2/file"), + Util::joinPath(&dir1dir2file[0], + &dir1dir2file[arrayLength(dir1dir2file)])); + + const std::string dirparentfile[] = { "dir", "..", "file" }; + CPPUNIT_ASSERT_EQUAL + (std::string("file"), + Util::joinPath(&dirparentfile[0], + &dirparentfile[arrayLength(dirparentfile)])); + + const std::string dirparentparentfile[] = { "dir", "..", "..", "file" }; + CPPUNIT_ASSERT_EQUAL + (std::string("file"), + Util::joinPath(&dirparentparentfile[0], + &dirparentparentfile[arrayLength(dirparentparentfile)])); + + const std::string dirdotfile[] = { "dir", ".", "file" }; + CPPUNIT_ASSERT_EQUAL(std::string("dir/file"), + Util::joinPath(&dirdotfile[0], + &dirdotfile[arrayLength(dirdotfile)])); + + const std::string empty[] = {}; + CPPUNIT_ASSERT_EQUAL(std::string(""), Util::joinPath(&empty[0], &empty[0])); + + const std::string parentdot[] = { "..", "." }; + CPPUNIT_ASSERT_EQUAL(std::string(""), + Util::joinPath(&parentdot[0], + &parentdot[arrayLength(parentdot)])); +} + } // namespace aria2