소스 검색

2009-03-05 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

	Added Util::pathJoin()
	* src/Util.h
	* test/UtilTest.cc
Tatsuhiro Tsujikawa 16 년 전
부모
커밋
70a8403575
3개의 변경된 파일70개의 추가작업 그리고 0개의 파일을 삭제
  1. 6 0
      ChangeLog
  2. 27 0
      src/Util.h
  3. 37 0
      test/UtilTest.cc

+ 6 - 0
ChangeLog

@@ -1,3 +1,9 @@
+2009-03-05  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
+
+	Added Util::pathJoin()
+	* src/Util.h
+	* test/UtilTest.cc
+
 2009-03-04  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
 
 	Applied basename function to remove directory element in

+ 27 - 0
src/Util.h

@@ -43,11 +43,13 @@
 #include <utility>
 #include <deque>
 #include <iosfwd>
+#include <numeric>
 
 #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<typename InputIterator>
+  static std::string joinPath(InputIterator first, InputIterator last)
+  {
+    std::deque<std::string> 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

+ 37 - 0
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