Browse Source

Implemented file_hasExtension and file_getExtensionless.

David Piuva 3 years ago
parent
commit
155a735e20

+ 21 - 0
Source/DFPSR/api/fileAPI.cpp

@@ -242,6 +242,16 @@ ReadableString file_getPathlessName(const ReadableString &path) {
 	return string_after(path, file_findLastSeparator(path));
 }
 
+bool file_hasExtension(const String& path) {
+	int64_t lastDotIndex = string_findLast(path, U'.');
+	int64_t lastSeparatorIndex = file_findLastSeparator(path);
+	if (lastDotIndex != -1 && lastSeparatorIndex < lastDotIndex) {
+		return true;
+	} else {
+		return false;
+	}
+}
+
 ReadableString file_getExtension(const String& filename) {
 	int64_t lastDotIndex = string_findLast(filename, U'.');
 	int64_t lastSeparatorIndex = file_findLastSeparator(filename);
@@ -253,6 +263,17 @@ ReadableString file_getExtension(const String& filename) {
 	}
 }
 
+ReadableString file_getExtensionless(const String& filename) {
+	int64_t lastDotIndex = string_findLast(filename, U'.');
+	int64_t lastSeparatorIndex = file_findLastSeparator(filename);
+	// Only use the last dot if there is no folder separator after it.
+	if (lastDotIndex != -1 && lastSeparatorIndex < lastDotIndex) {
+		return string_removeOuterWhiteSpace(string_before(filename, lastDotIndex));
+	} else {
+		return string_removeOuterWhiteSpace(filename);
+	}
+}
+
 String file_getRelativeParentFolder(const ReadableString &path, PathSyntax pathSyntax) {
 	String optimizedPath = file_optimizePath(path, pathSyntax);
 	if (string_length(optimizedPath) == 0) {

+ 10 - 0
Source/DFPSR/api/fileAPI.h

@@ -186,6 +186,16 @@ namespace dsr {
 	//   Use file_getEntryType instead if you want to know if it's a file or folder.
 	ReadableString file_getExtension(const String& filename);
 
+	// Path-syntax: This trivial operation should work the same independent of operating system.
+	// Post-condition: Returns filename without any extension, which is the original input if there is no extension.
+	//   Use to remove a file's type before appending a new extension.
+	ReadableString file_getExtensionless(const String& filename);
+
+	// Path-syntax: This trivial operation should work the same independent of operating system.
+	// Post-condition: Returns true iff path has an extension, even if it's just an empty dot at the end that file_getExtension would not detect.
+	//   Useful to check if you need to add an extension or if it already exists in a full filename.
+	bool file_hasExtension(const String& path);
+
 	// Quickly gets the relative parent folder by removing the last entry from the string or appending .. at the end.
 	// Path-syntax: Depends on pathSyntax argument.
 	// This pure syntax function getting the parent folder does not access the system in any way.

+ 44 - 0
Source/test/tests/FileTest.cpp

@@ -57,4 +57,48 @@ START_TEST(File)
 		ASSERT_MATCH(file_getRelativeParentFolder(U"mediaFolder\\..\\myFile.txt", PathSyntax::Windows), U"");
 		ASSERT_MATCH(file_getTheoreticalAbsoluteParentFolder(U"mediaFolder\\..\\myFile.txt", U"C:\\folder\\anotherFolder", PathSyntax::Windows), U"C:\\folder\\anotherFolder");
 	}
+	{ // Path removal
+		ASSERT_MATCH(file_getPathlessName(U"C:\\..\\folder\\file.txt"), U"file.txt");
+		ASSERT_MATCH(file_getPathlessName(U"C:\\..\\folder\\"), U"");
+		ASSERT_MATCH(file_getPathlessName(U"C:\\..\\folder"), U"folder");
+		ASSERT_MATCH(file_getPathlessName(U"C:\\..\\"), U"");
+		ASSERT_MATCH(file_getPathlessName(U"C:\\.."), U"..");
+		ASSERT_MATCH(file_getPathlessName(U"C:\\"), U"");
+		ASSERT_MATCH(file_getPathlessName(U"C:"), U"C:");
+		ASSERT_MATCH(file_getPathlessName(U"/folder/file.h"), U"file.h");
+		ASSERT_MATCH(file_getPathlessName(U"/folder/"), U"");
+		ASSERT_MATCH(file_getPathlessName(U"/folder"), U"folder");
+		ASSERT_MATCH(file_getPathlessName(U"/"), U"");
+	}
+	{ // Extension removal
+		ASSERT_MATCH(file_getExtensionless(U"C:\\..\\folder\\file.txt"), U"C:\\..\\folder\\file");
+		ASSERT_MATCH(file_getExtensionless(U"C:\\folder\\file.h"), U"C:\\folder\\file");
+		ASSERT_MATCH(file_getExtensionless(U"C:\\file."), U"C:\\file");
+		ASSERT_MATCH(file_getExtensionless(U"\\file."), U"\\file");
+		ASSERT_MATCH(file_getExtensionless(U"file"), U"file");
+		ASSERT_MATCH(file_getExtensionless(U""), U"");
+		ASSERT_MATCH(file_getExtensionless(U"/folder/./file.txt"), U"/folder/./file");
+		ASSERT_MATCH(file_getExtensionless(U"/folder/file.h"), U"/folder/file");
+		ASSERT_MATCH(file_getExtensionless(U"/folder/../file.h"), U"/folder/../file");
+		ASSERT_MATCH(file_getExtensionless(U"/file."), U"/file");
+		ASSERT_MATCH(file_getExtensionless(U"file"), U"file");
+		ASSERT_MATCH(file_getExtension(U"C:\\..\\folder\\file.txt"), U"txt");
+		ASSERT_MATCH(file_getExtension(U"C:\\..\\folder\\file.foo.txt"), U"txt");
+		ASSERT_MATCH(file_getExtension(U"C:\\..\\folder\\file.foo_bar.txt"), U"txt");
+		ASSERT_MATCH(file_getExtension(U"C:\\..\\folder\\file.foo.bar_txt"), U"bar_txt");
+		ASSERT_MATCH(file_getExtension(U"C:\\folder\\file.h"), U"h");
+		ASSERT_MATCH(file_getExtension(U"C:\\file."), U"");
+		ASSERT_MATCH(file_getExtension(U"\\file."), U"");
+		ASSERT_MATCH(file_getExtension(U"file"), U"");
+		ASSERT_MATCH(file_getExtension(U""), U"");
+		ASSERT_MATCH(file_getExtension(U"/folder/./file.txt"), U"txt");
+		ASSERT_MATCH(file_getExtension(U"/folder/file.h"), U"h");
+		ASSERT_MATCH(file_getExtension(U"/folder/../file.h"), U"h");
+		ASSERT_MATCH(file_getExtension(U"/file."), U"");
+		ASSERT_MATCH(file_getExtension(U"file"), U"");
+		ASSERT_EQUAL(file_hasExtension(U"/folder/./file.txt"), true);
+		ASSERT_EQUAL(file_hasExtension(U"/../folder/file.h"), true);
+		ASSERT_EQUAL(file_hasExtension(U"/folder/file."), true); // Not a named extension, but ending with a dot is not a pure extensionless path either.
+		ASSERT_EQUAL(file_hasExtension(U"/folder/file"), false);
+	}
 END_TEST

+ 2 - 3
Source/tools/builder/generator.cpp

@@ -70,9 +70,8 @@ void resolveDependencies(ProjectContext &context) {
 }
 
 static String findSourceFile(const ReadableString& headerPath, bool acceptC, bool acceptCpp) {
-	int lastDotIndex = string_findLast(headerPath, U'.');
-	if (lastDotIndex != -1) {
-		ReadableString extensionlessPath = string_removeOuterWhiteSpace(string_before(headerPath, lastDotIndex));
+	if (file_hasExtension(headerPath)) {
+		ReadableString extensionlessPath = file_getExtensionless(headerPath);
 		String cPath = extensionlessPath + U".c";
 		String cppPath = extensionlessPath + U".cpp";
 		if (acceptC && file_getEntryType(cPath) == EntryType::File) {