Jelajahi Sumber

Add path::reduce()

Daniele Bartolini 9 tahun lalu
induk
melakukan
e6c07aa6b1
3 mengubah file dengan 54 tambahan dan 0 penghapusan
  1. 27 0
      src/core/filesystem/path.cpp
  2. 3 0
      src/core/filesystem/path.h
  3. 24 0
      src/core/unit_tests.cpp

+ 27 - 0
src/core/filesystem/path.cpp

@@ -81,5 +81,32 @@ namespace path
 		CE_ENSURE(NULL != path);
 		return path[strlen32(path) - 1] == PATH_SEPARATOR;
 	}
+
+	inline bool any_separator(char c)
+	{
+		return c == '/' || c == '\\';
+	}
+
+	void reduce(DynamicString& clean, const char* path)
+	{
+		if (path == NULL)
+			return;
+
+		char cc = any_separator(*path) ? PATH_SEPARATOR : *path;
+		clean += cc;
+		++path;
+
+		for (; *path; ++path)
+		{
+			if (cc == PATH_SEPARATOR && (any_separator(*path) || *path == '.'))
+				continue;
+
+			cc = any_separator(*path) ? PATH_SEPARATOR : *path;
+			clean += cc;
+		}
+
+		if (has_trailing_separator(clean.c_str()))
+			array::pop_back(clean._data);
+	}
 } // namespace path
 } // namespace crown

+ 3 - 0
src/core/filesystem/path.h

@@ -42,6 +42,9 @@ namespace path
 
 	/// Returns whether the @a path has a trailing separator.
 	bool has_trailing_separator(const char* path);
+
+	/// Removes unnecessary dots and separators from @a path.
+	void reduce(DynamicString& clean, const char* path);
 } // namespace path
 
 } // namespace crown

+ 24 - 0
src/core/unit_tests.cpp

@@ -1166,6 +1166,18 @@ static void test_path()
 		ENSURE(path::has_trailing_separator("/home/foo/"));
 		ENSURE(!path::has_trailing_separator("/home/foo"));
 	}
+	{
+		TempAllocator128 ta;
+		DynamicString clean(ta);
+		path::reduce(clean, "/home/./foo/");
+		ENSURE(clean == "/home/foo");
+	}
+	{
+		TempAllocator128 ta;
+		DynamicString clean(ta);
+		path::reduce(clean, "\\home\\.\\foo\\");
+		ENSURE(clean == "/home/foo");
+	}
 #else
 	{
 		const bool a = path::is_absolute("C:\\Users\\foo");
@@ -1195,6 +1207,18 @@ static void test_path()
 		ENSURE(path::has_trailing_separator("C:\\Users\\foo\\"));
 		ENSURE(!path::has_trailing_separator("C:\\Users\\foo"));
 	}
+	{
+		TempAllocator128 ta;
+		DynamicString clean(ta);
+		path::reduce(clean, "C:\\Users\\.\\foo\\");
+		ENSURE(clean == "C:\\Users\\foo");
+	}
+	{
+		TempAllocator128 ta;
+		DynamicString clean(ta);
+		path::reduce(clean, "C:/Users/./foo/");
+		ENSURE(clean == "C:\\Users\\foo");
+	}
 #endif // CROWN_PLATFORM_POSIX
 	{
 		const char* p = path::basename("");