Browse Source

More functions to the file API.

David Piuva 3 years ago
parent
commit
3093e49289
2 changed files with 63 additions and 17 deletions
  1. 32 13
      Source/DFPSR/api/fileAPI.cpp
  2. 31 4
      Source/DFPSR/api/fileAPI.h

+ 32 - 13
Source/DFPSR/api/fileAPI.cpp

@@ -149,15 +149,15 @@ const char32_t* file_separator() {
 	return getPathSeparator(LOCAL_PATH_SYNTAX);
 	return getPathSeparator(LOCAL_PATH_SYNTAX);
 }
 }
 
 
-inline bool isSeparator(DsrChar c) {
+bool file_isSeparator(DsrChar c) {
 	return c == U'\\' || c == U'/';
 	return c == U'\\' || c == U'/';
 }
 }
 
 
 // Returns the index of the first / or \ in path, or defaultIndex if none existed.
 // Returns the index of the first / or \ in path, or defaultIndex if none existed.
-static int64_t getFirstSeparator(const ReadableString &path, int64_t defaultIndex) {
-	for (int64_t i = 0; i < string_length(path); i++) {
+int64_t file_findFirstSeparator(const ReadableString &path, int64_t defaultIndex, int64_t startIndex) {
+	for (int64_t i = startIndex; i < string_length(path); i++) {
 		DsrChar c = path[i];
 		DsrChar c = path[i];
-		if (isSeparator(c)) {
+		if (file_isSeparator(c)) {
 			return i;
 			return i;
 		}
 		}
 	}
 	}
@@ -165,10 +165,10 @@ static int64_t getFirstSeparator(const ReadableString &path, int64_t defaultInde
 }
 }
 
 
 // Returns the index of the last / or \ in path, or defaultIndex if none existed.
 // Returns the index of the last / or \ in path, or defaultIndex if none existed.
-static int64_t getLastSeparator(const ReadableString &path, int64_t defaultIndex) {
+int64_t file_findLastSeparator(const ReadableString &path, int64_t defaultIndex) {
 	for (int64_t i = string_length(path) - 1; i >= 0; i--) {
 	for (int64_t i = string_length(path) - 1; i >= 0; i--) {
 		DsrChar c = path[i];
 		DsrChar c = path[i];
-		if (isSeparator(c)) {
+		if (file_isSeparator(c)) {
 			return i;
 			return i;
 		}
 		}
 	}
 	}
@@ -186,7 +186,7 @@ String file_optimizePath(const ReadableString &path, PathSyntax pathSyntax) {
 	//   The null terminator is not actually stored, but reading out of bound gives a null terminator.
 	//   The null terminator is not actually stored, but reading out of bound gives a null terminator.
 	for (int64_t i = 0; i <= inputLength; i++) {
 	for (int64_t i = 0; i <= inputLength; i++) {
 		DsrChar c = path[i];
 		DsrChar c = path[i];
-		bool separator = isSeparator(c);
+		bool separator = file_isSeparator(c);
 		if (separator || i == inputLength) {
 		if (separator || i == inputLength) {
 			bool appendEntry = true;
 			bool appendEntry = true;
 			bool appendSeparator = separator;
 			bool appendSeparator = separator;
@@ -228,7 +228,7 @@ String file_optimizePath(const ReadableString &path, PathSyntax pathSyntax) {
 	if (hadSeparator && hadContent) {
 	if (hadSeparator && hadContent) {
 		int64_t lastNonSeparator = -1;
 		int64_t lastNonSeparator = -1;
 		for (int64_t i = string_length(result) - 1; i >= 0; i--) {
 		for (int64_t i = string_length(result) - 1; i >= 0; i--) {
-			if (!isSeparator(result[i])) {
+			if (!file_isSeparator(result[i])) {
 				lastNonSeparator = i;
 				lastNonSeparator = i;
 				break;
 				break;
 			}
 			}
@@ -239,12 +239,12 @@ String file_optimizePath(const ReadableString &path, PathSyntax pathSyntax) {
 }
 }
 
 
 ReadableString file_getPathlessName(const ReadableString &path) {
 ReadableString file_getPathlessName(const ReadableString &path) {
-	return string_after(path, getLastSeparator(path, -1));
+	return string_after(path, file_findLastSeparator(path));
 }
 }
 
 
 ReadableString file_getExtension(const String& filename) {
 ReadableString file_getExtension(const String& filename) {
 	int64_t lastDotIndex = string_findLast(filename, U'.');
 	int64_t lastDotIndex = string_findLast(filename, U'.');
-	int64_t lastSeparatorIndex = getLastSeparator(filename, -1);
+	int64_t lastSeparatorIndex = file_findLastSeparator(filename);
 	// Only use the last dot if there is no folder separator after it.
 	// Only use the last dot if there is no folder separator after it.
 	if (lastDotIndex != -1 && lastSeparatorIndex < lastDotIndex) {
 	if (lastDotIndex != -1 && lastSeparatorIndex < lastDotIndex) {
 		return string_removeOuterWhiteSpace(string_after(filename, lastDotIndex));
 		return string_removeOuterWhiteSpace(string_after(filename, lastDotIndex));
@@ -272,7 +272,7 @@ String file_getRelativeParentFolder(const ReadableString &path, PathSyntax pathS
 		return file_combinePaths(optimizedPath, U"..", pathSyntax);
 		return file_combinePaths(optimizedPath, U"..", pathSyntax);
 	} else {
 	} else {
 		// Inside of something.
 		// Inside of something.
-		int64_t lastSeparator = getLastSeparator(optimizedPath, 0);
+		int64_t lastSeparator = file_findLastSeparator(optimizedPath, 0);
 		if (pathSyntax == PathSyntax::Windows) {
 		if (pathSyntax == PathSyntax::Windows) {
 			// Return everything before the last separator.
 			// Return everything before the last separator.
 			return string_before(optimizedPath, lastSeparator);
 			return string_before(optimizedPath, lastSeparator);
@@ -326,7 +326,7 @@ bool file_isRoot(const ReadableString &path, bool treatHomeFolderAsRoot, PathSyn
 }
 }
 
 
 bool file_hasRoot(const ReadableString &path, bool treatHomeFolderAsRoot, PathSyntax pathSyntax) {
 bool file_hasRoot(const ReadableString &path, bool treatHomeFolderAsRoot, PathSyntax pathSyntax) {
-	int64_t firstSeparator = getFirstSeparator(path, -1);
+	int64_t firstSeparator = file_findFirstSeparator(path);
 	if (firstSeparator == -1) {
 	if (firstSeparator == -1) {
 		// If there is no separator, path has a root if it is a root.
 		// If there is no separator, path has a root if it is a root.
 		return file_isRoot(path, treatHomeFolderAsRoot, pathSyntax);
 		return file_isRoot(path, treatHomeFolderAsRoot, pathSyntax);
@@ -417,7 +417,7 @@ String file_combinePaths(const ReadableString &a, const ReadableString &b, PathS
 		// Ignoring initial relative path, so that relative paths are not suddenly moved to the root by a new separator.
 		// Ignoring initial relative path, so that relative paths are not suddenly moved to the root by a new separator.
 		return cleanA;
 		return cleanA;
 	} else {
 	} else {
-		if (isSeparator(a[lengthA - 1])) {
+		if (file_isSeparator(a[lengthA - 1])) {
 			// Already ending with a separator.
 			// Already ending with a separator.
 			return string_combine(cleanA, cleanB);
 			return string_combine(cleanA, cleanB);
 		} else {
 		} else {
@@ -589,4 +589,23 @@ bool file_getFolderContent(const ReadableString& folderPath, std::function<void(
 	return true;
 	return true;
 }
 }
 
 
+void file_getPathEntries(const ReadableString& path, std::function<void(ReadableString, int64_t, int64_t)> action) {
+	int64_t sectionStart = 0;
+	int64_t length = string_length(path);
+	for (int64_t i = 0; i < string_length(path); i++) {
+		DsrChar c = path[i];
+		if (file_isSeparator(c)) {
+			int64_t sectionEnd = i - 1; // Inclusive end
+			ReadableString content = string_inclusiveRange(path, sectionStart, sectionEnd);
+			if (string_length(content)) { action(content, sectionStart, sectionEnd); }
+			sectionStart = i + 1;
+		}
+	}
+	if (length > sectionStart) {
+		int64_t sectionEnd = length - 1; // Inclusive end
+		ReadableString content = string_inclusiveRange(path, sectionStart, sectionEnd);
+		if (string_length(content)) { action(content, sectionStart, sectionEnd); }
+	}
+}
+
 }
 }

+ 31 - 4
Source/DFPSR/api/fileAPI.h

@@ -90,6 +90,34 @@ namespace dsr {
 	//   Can be used to construct a file path that works for both forward and backward slash separators.
 	//   Can be used to construct a file path that works for both forward and backward slash separators.
 	const char32_t* file_separator();
 	const char32_t* file_separator();
 
 
+	// Path-syntax: This operation can handle separators given from any supported platform.
+	//   because separators will be corrected by file_optimizePath when used to access files.
+	// Post-condition: Returns true iff the character C is a folder separator, currently / and \ are accepted as folder separators.
+	bool file_isSeparator(DsrChar c);
+
+	// Path-syntax: This operation can handle separators given from any supported platform.
+	// Post-condition: Returns the base-zero index of the first path separator (as defined by file_isSeparator) starting from startIndex, or defaultIndex if not found.
+	//                 If the result is not equal to defaultIndex, it is guaranteed to be equal to or greater than startIndex.
+	// Similar to string_findFirst, but with the character to find repalced with a replacable default index.
+	int64_t file_findFirstSeparator(const ReadableString &path, int64_t defaultIndex = -1, int64_t startIndex = 0);
+
+	// Path-syntax: This operation can handle separators given from any supported platform.
+	// Post-condition: Returns the base-zero index of the last path separator (as defined by file_isSeparator), or defaultIndex if not found.
+	// Similar to string_findLast, but with the character to find repalced with a replacable default index.
+	int64_t file_findLastSeparator(const ReadableString &path, int64_t defaultIndex = -1);
+
+	// Returns callbacks for non-empty entries between separator characters.
+	//   This includes folder names, filenames, symbolic links, drive letter.
+	//   This excludes blank space before the first or after the last separator, so the implicit Windows drive \ and Posix system root / will not be included.
+	// Path-syntax: This operation can handle separators given from any supported platform.
+	//              It should handle both / and \, with and without spaces in filenames.
+	// Side-effect: Returns a callback for each selectable non-empty entry in the path, from left to right.
+	//              The first argument in the callback is the entry name, and the integers are an inclusive base-zero index range from first to last characters in path.
+	// The first entry must be something selectable to be included. Otherwise it is ignored.
+	//   C: would be returned as an entry, because other drives can be selected.
+	//   The implicit Windows drive \ and Posix system root / will not be returned, because they are implicit and can't be replaced in the path.
+	void file_getPathEntries(const ReadableString& path, std::function<void(ReadableString, int64_t, int64_t)> action);
+
 	// Path-syntax: Depends on pathSyntax argument.
 	// Path-syntax: Depends on pathSyntax argument.
 	// Turns / and \ into the path convention specified by pathSyntax, which is the local system's by default.
 	// Turns / and \ into the path convention specified by pathSyntax, which is the local system's by default.
 	// Removes redundant . and .. to reduce the risk of running out of buffer space when calling the system.
 	// Removes redundant . and .. to reduce the risk of running out of buffer space when calling the system.
@@ -102,7 +130,7 @@ namespace dsr {
 	String file_combinePaths(const ReadableString &a, const ReadableString &b, PathSyntax pathSyntax IMPLICIT_PATH_SYNTAX);
 	String file_combinePaths(const ReadableString &a, const ReadableString &b, PathSyntax pathSyntax IMPLICIT_PATH_SYNTAX);
 
 
 	// Path-syntax: Depends on pathSyntax argument.
 	// Path-syntax: Depends on pathSyntax argument.
-	// Post-condition: Returns true for relative paths true iff path contains a root, according to the path syntax.
+	// Post-condition: Returns true iff path starts from a root, according to the path syntax.
 	//                 Implicit drives on Windows using \ are treated as roots because we know that there is nothing above them.
 	//                 Implicit drives on Windows using \ are treated as roots because we know that there is nothing above them.
 	// If treatHomeFolderAsRoot is true, starting from the /home/username folder using the Posix ~ alias will be allowed as a root as well, because we can't append it behind another path.
 	// If treatHomeFolderAsRoot is true, starting from the /home/username folder using the Posix ~ alias will be allowed as a root as well, because we can't append it behind another path.
 	bool file_hasRoot(const ReadableString &path, bool treatHomeFolderAsRoot, PathSyntax pathSyntax IMPLICIT_PATH_SYNTAX);
 	bool file_hasRoot(const ReadableString &path, bool treatHomeFolderAsRoot, PathSyntax pathSyntax IMPLICIT_PATH_SYNTAX);
@@ -146,9 +174,8 @@ namespace dsr {
 	bool file_setCurrentPath(const ReadableString &path);
 	bool file_setCurrentPath(const ReadableString &path);
 
 
 	// Path-syntax: According to the local computer.
 	// Path-syntax: According to the local computer.
-	// Post-condition: Returns  the application's folder path, from where the application is stored.
-	// If not implemented and allowFallback is true,
-	//   the current path is returned instead as a qualified guess instead of raising an exception.
+	// Post-condition: Returns the application's folder path, from where the application is stored.
+	// If not implemented and allowFallback is true, the current path is returned instead as a qualified guess instead of raising an exception.
 	String file_getApplicationFolder(bool allowFallback = true);
 	String file_getApplicationFolder(bool allowFallback = true);
 
 
 	// Path-syntax: This trivial operation should work the same independent of operating system.
 	// Path-syntax: This trivial operation should work the same independent of operating system.