27 : fullPath (parseAbsolutePath (fullPathName))
39 : fullPath (other.fullPath)
45 fullPath = parseAbsolutePath (newPath);
51 fullPath = other.fullPath;
56 : fullPath (std::move (other.fullPath))
62 fullPath = std::move (other.fullPath);
66JUCE_DECLARE_DEPRECATED_STATIC (
const File File::nonexistent{};)
69static String removeEllipsis (
const String& path)
74 if (path.contains (
".\\"))
76 if (path.contains (
"./"))
81 bool anythingChanged =
false;
83 for (
int i = 1; i < toks.size(); ++i)
87 if (t ==
".." && toks[i - 1] !=
"..")
89 anythingChanged =
true;
90 toks.removeRange (i - 1, 2);
95 anythingChanged =
true;
107static String normaliseSeparators (
const String& path)
109 auto normalisedPath = path;
112 String doubleSeparator (separator + separator);
114 auto uncPath = normalisedPath.startsWith (doubleSeparator)
115 && ! normalisedPath.fromFirstOccurrenceOf (doubleSeparator,
false,
false).startsWith (separator);
118 normalisedPath = normalisedPath.fromFirstOccurrenceOf (doubleSeparator,
false,
false);
120 while (normalisedPath.contains (doubleSeparator))
121 normalisedPath = normalisedPath.replace (doubleSeparator, separator);
123 return uncPath ? doubleSeparator + normalisedPath
139 auto path = normaliseSeparators (removeEllipsis (p.
replaceCharacter (
'/',
'\\')));
157 else if (! path.containsChar (
':'))
178 auto path = normaliseSeparators (removeEllipsis (p));
180 if (path.startsWithChar (
'~'))
193 if (
auto* pw = getpwnam (userName.toUTF8()))
199 #if JUCE_DEBUG || JUCE_LOG_ASSERTIONS
200 if (! (path.startsWith (
"./") || path.startsWith (
"../")))
211 #if JUCE_LOG_ASSERTIONS
235 #define NAMES_ARE_CASE_SENSITIVE 1
240 #if NAMES_ARE_CASE_SENSITIVE
247static int compareFilenames (
const String& name1,
const String& name2)
noexcept
249 #if NAMES_ARE_CASE_SENSITIVE
250 return name1.compare (name2);
252 return name1.compareIgnoreCase (name2);
263 const bool applyRecursively)
const
269 worked = f.setReadOnly (shouldBeReadOnly,
true) && worked;
271 return setFileReadOnlyInternal (shouldBeReadOnly) && worked;
276 return setFileExecutableInternal (shouldBeExecutable);
285 worked = f.deleteRecursively (followSymlinks) && worked;
292 if (newFile.fullPath == fullPath)
298 #if ! NAMES_ARE_CASE_SENSITIVE
299 if (*
this != newFile)
304 return moveInternal (newFile);
309 return (*
this == newFile)
315 if (newFile.fullPath == fullPath)
321 if (! replaceInternal (newFile))
333 if (! f.copyFileTo (newDirectory.
getChildFile (f.getFileName())))
337 if (! f.copyDirectoryTo (newDirectory.
getChildFile (f.getFileName())))
347String File::getPathUpToLastSlash()
const
352 return fullPath.
substring (0, lastSlash);
376 if (lastDot > lastSlash)
377 return fullPath.
substring (lastSlash, lastDot);
384 if (potentialParent.fullPath.
isEmpty())
387 auto ourPath = getPathUpToLastSlash();
389 if (compareFilenames (potentialParent.fullPath, ourPath) == 0)
392 if (potentialParent.fullPath.
length() >= ourPath.length())
404 auto firstChar = *(path.
text);
408 || (firstChar != 0 && path.
text[1] ==
':');
416 auto r = relativePath.
text;
422 if (r.indexOf ((juce_wchar)
'/') >= 0)
426 auto path = fullPath;
432 auto secondChar = *++r;
434 if (secondChar ==
'.')
436 auto thirdChar = *++r;
438 if (thirdChar == separatorChar || thirdChar == 0)
440 auto lastSlash = path.lastIndexOfChar (separatorChar);
443 path = path.substring (0, lastSlash);
445 while (*r == separatorChar)
454 else if (secondChar == separatorChar || secondChar == 0)
456 while (*r == separatorChar)
467 path.appendCharPointer (r);
482 if (bytes == 1) { suffix =
" byte"; }
483 else if (bytes < 1024) { suffix =
" bytes"; }
484 else if (bytes < 1024 * 1024) { suffix =
" KB"; divisor = 1024.0; }
485 else if (bytes < 1024 * 1024 * 1024) { suffix =
" MB"; divisor = 1024.0 * 1024.0; }
486 else { suffix =
" GB"; divisor = 1024.0 * 1024.0 * 1024.0; }
488 return (divisor > 0 ?
String (bytes / divisor, 1) :
String (bytes)) + suffix;
499 if (parentDir == *
this)
502 auto r = parentDir.createDirectory();
520 if (parentDir == *
this)
523 auto r = parentDir.createDirectory();
569 findChildFiles (results, whatToLookFor, searchRecursively, wildcard);
579 results.
add (di.getFile());
608 bool putNumbersInBrackets)
const
615 auto prefix = suggestedPrefix;
618 if (prefix.trim().endsWithChar (
')'))
620 putNumbersInBrackets =
true;
623 auto closeBracks = prefix.lastIndexOfChar (
')');
626 && closeBracks > openBracks
627 && prefix.substring (openBracks + 1, closeBracks).containsOnly (
"0123456789"))
629 number = prefix.substring (openBracks + 1, closeBracks).getIntValue();
630 prefix = prefix.substring (0, openBracks);
636 auto newName = prefix;
638 if (putNumbersInBrackets)
640 newName <<
'(' << ++number <<
')';
652 }
while (f.exists());
665 putNumbersInBrackets);
684 auto semicolon = possibleSuffix.
text.indexOf ((juce_wchar)
';');
692 if (possibleSuffix.
text[0] ==
'.')
695 auto dotPos = fullPath.
length() - possibleSuffix.
length() - 1;
698 return fullPath[dotPos] ==
'.';
711 auto lastDot = filePart.lastIndexOfChar (
'.');
714 filePart = filePart.substring (0, lastDot);
734 return fin.release();
741 std::unique_ptr<FileOutputStream> out (
new FileOutputStream (*
this, bufferSize));
743 return out->failedToOpen() ? nullptr
749 const size_t numberOfBytes)
const
751 jassert (((ssize_t) numberOfBytes) >= 0);
753 if (numberOfBytes == 0)
757 return out.
openedOk() && out.
write (dataToAppend, numberOfBytes);
761 const size_t numberOfBytes)
const
763 if (numberOfBytes == 0)
778 return out.
writeText (text, asUnicode, writeHeaderBytes, lineFeed);
784 tempFile.
getFile().
appendText (textToWrite, asUnicode, writeHeaderBytes, lineFeed);
797 if (in1.openedOk() && in2.
openedOk())
799 const int bufferSize = 4096;
804 auto num1 = in1.read (buffer1, bufferSize);
805 auto num2 = in2.
read (buffer2, bufferSize);
813 if (memcmp (buffer1, buffer2, (
size_t) num1) != 0)
828 if (s.isNotEmpty() && s[1] ==
':')
842 const int maxLength = 128;
847 auto lastDot = s.lastIndexOfChar (
'.');
849 if (lastDot > jmax (0, len - 12))
851 s = s.substring (0, maxLength - (len - lastDot))
852 + s.substring (lastDot);
856 s = s.substring (0, maxLength);
864static int countNumberOfSeparators (String::CharPointerType s)
870 auto c = s.getAndAdvance();
887 auto thisPath = fullPath;
895 int commonBitLength = 0;
896 auto thisPathAfterCommon = thisPath.getCharPointer();
897 auto dirPathAfterCommon = dirPath.getCharPointer();
900 auto thisPathIter = thisPath.getCharPointer();
901 auto dirPathIter = dirPath.getCharPointer();
905 auto c1 = thisPathIter.getAndAdvance();
906 auto c2 = dirPathIter.getAndAdvance();
908 #if NAMES_ARE_CASE_SENSITIVE
920 thisPathAfterCommon = thisPathIter;
921 dirPathAfterCommon = dirPathIter;
928 if (commonBitLength == 0 || (commonBitLength == 1 && thisPath[1] ==
getSeparatorChar()))
931 auto numUpDirectoriesNeeded = countNumberOfSeparators (dirPathAfterCommon);
933 if (numUpDirectoriesNeeded == 0)
934 return thisPathAfterCommon;
941 s.appendCharPointer (thisPathAfterCommon);
952 if (tempFile.exists())
959 const String& nativePathOfTarget,
960 bool overwriteExisting)
962 if (linkFileToCreate.
exists())
972 if (overwriteExisting)
976 #if JUCE_MAC || JUCE_LINUX
990 targetFile.
isDirectory() ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0) != FALSE;
992 ignoreUnused (nativePathOfTarget);
1015 : range (0, file.getSize())
1017 openInternal (file, mode, exclusive);
1021 : range (fileRange.getIntersectionWith (
Range<int64> (0, file.getSize())))
1023 openInternal (file, mode, exclusive);
1035 :
UnitTest (
"Files", UnitTestCategories::files)
1038 void runTest()
override
1040 beginTest (
"Reading");
1042 const File home (File::getSpecialLocation (File::userHomeDirectory));
1043 const File temp (File::getSpecialLocation (File::tempDirectory));
1045 expect (! File().exists());
1046 expect (! File().existsAsFile());
1047 expect (! File().isDirectory());
1049 expect (File(
"/").isDirectory());
1051 expect (home.isDirectory());
1052 expect (home.exists());
1053 expect (! home.existsAsFile());
1054 expect (File::getSpecialLocation (File::userApplicationDataDirectory).isDirectory());
1055 expect (File::getSpecialLocation (File::currentExecutableFile).exists());
1056 expect (File::getSpecialLocation (File::currentApplicationFile).exists());
1057 expect (File::getSpecialLocation (File::invokedExecutableFile).exists());
1058 expect (home.getVolumeTotalSize() > 1024 * 1024);
1059 expect (home.getBytesFreeOnVolume() > 0);
1060 expect (! home.isHidden());
1061 expect (home.isOnHardDisk());
1062 expect (! home.isOnCDRomDrive());
1063 expect (File::getCurrentWorkingDirectory().exists());
1064 expect (home.setAsCurrentWorkingDirectory());
1065 expect (File::getCurrentWorkingDirectory() == home);
1069 File::findFileSystemRoots (roots);
1070 expect (roots.size() > 0);
1072 int numRootsExisting = 0;
1073 for (
int i = 0; i < roots.size(); ++i)
1074 if (roots[i].exists())
1078 expect (numRootsExisting > 0);
1081 beginTest (
"Writing");
1083 File demoFolder (temp.getChildFile (
"JUCE UnitTests Temp Folder.folder"));
1084 expect (demoFolder.deleteRecursively());
1085 expect (demoFolder.createDirectory());
1086 expect (demoFolder.isDirectory());
1087 expect (demoFolder.getParentDirectory() == temp);
1088 expect (temp.isDirectory());
1089 expect (temp.findChildFiles (File::findFilesAndDirectories,
false,
"*").contains (demoFolder));
1090 expect (temp.findChildFiles (File::findDirectories,
true,
"*.folder").contains (demoFolder));
1092 File tempFile (demoFolder.getNonexistentChildFile (
"test",
".txt",
false));
1094 expect (tempFile.getFileExtension() ==
".txt");
1095 expect (tempFile.hasFileExtension (
".txt"));
1096 expect (tempFile.hasFileExtension (
"txt"));
1097 expect (tempFile.withFileExtension (
"xyz").hasFileExtension (
".xyz"));
1098 expect (tempFile.withFileExtension (
"xyz").hasFileExtension (
"abc;xyz;foo"));
1099 expect (tempFile.withFileExtension (
"xyz").hasFileExtension (
"xyz;foo"));
1100 expect (! tempFile.withFileExtension (
"h").hasFileExtension (
"bar;foo;xx"));
1101 expect (tempFile.getSiblingFile (
"foo").isAChildOf (temp));
1102 expect (tempFile.hasWriteAccess());
1104 expect (home.getChildFile (
".") == home);
1105 expect (home.getChildFile (
"..") == home.getParentDirectory());
1106 expect (home.getChildFile (
".xyz").getFileName() ==
".xyz");
1107 expect (home.getChildFile (
"..xyz").getFileName() ==
"..xyz");
1108 expect (home.getChildFile (
"...xyz").getFileName() ==
"...xyz");
1109 expect (home.getChildFile (
"./xyz") == home.getChildFile (
"xyz"));
1110 expect (home.getChildFile (
"././xyz") == home.getChildFile (
"xyz"));
1111 expect (home.getChildFile (
"../xyz") == home.getParentDirectory().getChildFile (
"xyz"));
1112 expect (home.getChildFile (
".././xyz") == home.getParentDirectory().getChildFile (
"xyz"));
1113 expect (home.getChildFile (
".././xyz/./abc") == home.getParentDirectory().getChildFile (
"xyz/abc"));
1114 expect (home.getChildFile (
"./../xyz") == home.getParentDirectory().getChildFile (
"xyz"));
1115 expect (home.getChildFile (
"a1/a2/a3/./../../a4") == home.getChildFile (
"a1/a4"));
1118 FileOutputStream fo (tempFile);
1119 fo.write (
"0123456789", 10);
1122 expect (tempFile.exists());
1123 expect (tempFile.getSize() == 10);
1124 expect (std::abs ((
int) (tempFile.getLastModificationTime().toMilliseconds() - Time::getCurrentTime().toMilliseconds())) < 3000);
1125 expectEquals (tempFile.loadFileAsString(), String (
"0123456789"));
1126 expect (! demoFolder.containsSubDirectories());
1128 expectEquals (tempFile.getRelativePathFrom (demoFolder.getParentDirectory()), demoFolder.getFileName() + File::getSeparatorString() + tempFile.getFileName());
1129 expectEquals (demoFolder.getParentDirectory().getRelativePathFrom (tempFile),
".." + File::getSeparatorString() +
".." + File::getSeparatorString() + demoFolder.getParentDirectory().getFileName());
1131 expect (demoFolder.getNumberOfChildFiles (File::findFiles) == 1);
1132 expect (demoFolder.getNumberOfChildFiles (File::findFilesAndDirectories) == 1);
1133 expect (demoFolder.getNumberOfChildFiles (File::findDirectories) == 0);
1134 demoFolder.getNonexistentChildFile (
"tempFolder",
"",
false).createDirectory();
1135 expect (demoFolder.getNumberOfChildFiles (File::findDirectories) == 1);
1136 expect (demoFolder.getNumberOfChildFiles (File::findFilesAndDirectories) == 2);
1137 expect (demoFolder.containsSubDirectories());
1139 expect (tempFile.hasWriteAccess());
1140 tempFile.setReadOnly (
true);
1141 expect (! tempFile.hasWriteAccess());
1142 tempFile.setReadOnly (
false);
1143 expect (tempFile.hasWriteAccess());
1145 Time t (Time::getCurrentTime());
1146 tempFile.setLastModificationTime (t);
1147 Time t2 = tempFile.getLastModificationTime();
1148 expect (std::abs ((
int) (t2.toMilliseconds() - t.toMilliseconds())) <= 1000);
1152 tempFile.loadFileAsData (mb);
1153 expect (mb.getSize() == 10);
1154 expect (mb[0] ==
'0');
1158 expect (tempFile.getSize() == 10);
1159 FileOutputStream fo (tempFile);
1160 expect (fo.openedOk());
1162 expect (fo.setPosition (7));
1163 expect (fo.truncate().wasOk());
1164 expect (tempFile.getSize() == 7);
1165 fo.write (
"789", 3);
1167 expect (tempFile.getSize() == 10);
1170 beginTest (
"Memory-mapped files");
1173 MemoryMappedFile mmf (tempFile, MemoryMappedFile::readOnly);
1174 expect (mmf.getSize() == 10);
1175 expect (mmf.getData() !=
nullptr);
1176 expect (memcmp (mmf.getData(),
"0123456789", 10) == 0);
1180 const File tempFile2 (tempFile.getNonexistentSibling (
false));
1181 expect (tempFile2.create());
1182 expect (tempFile2.appendData (
"xxxxxxxxxx", 10));
1185 MemoryMappedFile mmf (tempFile2, MemoryMappedFile::readWrite);
1186 expect (mmf.getSize() == 10);
1187 expect (mmf.getData() !=
nullptr);
1188 memcpy (mmf.getData(),
"abcdefghij", 10);
1192 MemoryMappedFile mmf (tempFile2, MemoryMappedFile::readWrite);
1193 expect (mmf.getSize() == 10);
1194 expect (mmf.getData() !=
nullptr);
1195 expect (memcmp (mmf.getData(),
"abcdefghij", 10) == 0);
1198 expect (tempFile2.deleteFile());
1201 beginTest (
"More writing");
1203 expect (tempFile.appendData (
"abcdefghij", 10));
1204 expect (tempFile.getSize() == 20);
1205 expect (tempFile.replaceWithData (
"abcdefghij", 10));
1206 expect (tempFile.getSize() == 10);
1208 File tempFile2 (tempFile.getNonexistentSibling (
false));
1209 expect (tempFile.copyFileTo (tempFile2));
1210 expect (tempFile2.exists());
1211 expect (tempFile2.hasIdenticalContentTo (tempFile));
1212 expect (tempFile.deleteFile());
1213 expect (! tempFile.exists());
1214 expect (tempFile2.moveFileTo (tempFile));
1215 expect (tempFile.exists());
1216 expect (! tempFile2.exists());
1218 expect (demoFolder.deleteRecursively());
1219 expect (! demoFolder.exists());
1222 URL url (
"https://audio.dev/foo/bar/");
1223 expectEquals (url.toString (
false), String (
"https://audio.dev/foo/bar/"));
1224 expectEquals (url.getChildURL (
"x").toString (
false), String (
"https://audio.dev/foo/bar/x"));
1225 expectEquals (url.getParentURL().toString (
false), String (
"https://audio.dev/foo"));
1226 expectEquals (url.getParentURL().getParentURL().toString (
false), String (
"https://audio.dev/"));
1227 expectEquals (url.getParentURL().getParentURL().getParentURL().toString (
false), String (
"https://audio.dev/"));
1228 expectEquals (url.getParentURL().getChildURL (
"x").toString (
false), String (
"https://audio.dev/foo/x"));
1229 expectEquals (url.getParentURL().getParentURL().getParentURL().getChildURL (
"x").toString (
false), String (
"https://audio.dev/x"));
1233 URL url (
"https://audio.dev/foo/bar");
1234 expectEquals (url.toString (
false), String (
"https://audio.dev/foo/bar"));
1235 expectEquals (url.getChildURL (
"x").toString (
false), String (
"https://audio.dev/foo/bar/x"));
1236 expectEquals (url.getParentURL().toString (
false), String (
"https://audio.dev/foo"));
1237 expectEquals (url.getParentURL().getParentURL().toString (
false), String (
"https://audio.dev/"));
1238 expectEquals (url.getParentURL().getParentURL().getParentURL().toString (
false), String (
"https://audio.dev/"));
1239 expectEquals (url.getParentURL().getChildURL (
"x").toString (
false), String (
"https://audio.dev/foo/x"));
1240 expectEquals (url.getParentURL().getParentURL().getParentURL().getChildURL (
"x").toString (
false), String (
"https://audio.dev/x"));
1245static FileTests fileUnitTests;
void add(const ElementType &newElement)
static juce_wchar toLowerCase(juce_wchar character) noexcept
static bool isDigit(char character) noexcept
const Result & getStatus() const noexcept
bool write(const void *, size_t) override
bool failedToOpen() const noexcept
bool openedOk() const noexcept
bool replaceWithText(const String &textToWrite, bool asUnicode=false, bool writeUnicodeHeaderBytes=false, const char *lineEndings="\r\n") const
bool isSymbolicLink() const
int getNumberOfChildFiles(int whatToLookFor, const String &wildCardPattern="*") const
bool moveFileTo(const File &targetLocation) const
bool operator==(const File &) const
bool containsSubDirectories() const
bool hasIdenticalContentTo(const File &other) const
FileOutputStream * createOutputStream(size_t bufferSize=0x8000) const
static String createLegalPathName(const String &pathNameToFix)
static String addTrailingSeparator(const String &path)
String getFileExtension() const
Time getLastModificationTime() const
bool existsAsFile() const
bool copyFileTo(const File &targetLocation) const
bool deleteRecursively(bool followSymlinks=false) const
static File JUCE_CALLTYPE getSpecialLocation(const SpecialLocationType type)
const String & getFullPathName() const noexcept
String getFileName() const
bool replaceWithData(const void *dataToWrite, size_t numberOfBytes) const
bool setLastAccessTime(Time newTime) const
File getChildFile(StringRef relativeOrAbsolutePath) const
void readLines(StringArray &destLines) const
static bool isAbsolutePath(StringRef path)
File getSiblingFile(StringRef siblingFileName) const
bool createSymbolicLink(const File &linkFileToCreate, bool overwriteExisting) const
String getFileNameWithoutExtension() const
Array< File > findChildFiles(int whatToLookFor, bool searchRecursively, const String &wildCardPattern="*") const
File getNonexistentSibling(bool putNumbersInBrackets=true) const
String getRelativePathFrom(const File &directoryToBeRelativeTo) const
bool appendText(const String &textToAppend, bool asUnicode=false, bool writeUnicodeHeaderBytes=false, const char *lineEndings="\r\n") const
@ findFilesAndDirectories
File getNonexistentChildFile(const String &prefix, const String &suffix, bool putNumbersInBrackets=true) const
bool operator!=(const File &) const
bool setCreationTime(Time newTime) const
static String descriptionOfSizeInBytes(int64 bytes)
bool setReadOnly(bool shouldBeReadOnly, bool applyRecursively=false) const
static File createTempFile(StringRef fileNameEnding)
static juce_wchar getSeparatorChar()
static bool areFileNamesCaseSensitive()
String loadFileAsString() const
FileInputStream * createInputStream() const
bool operator>(const File &) const
File getLinkedTarget() const
File getParentDirectory() const
bool appendData(const void *dataToAppend, size_t numberOfBytes) const
bool operator<(const File &) const
Time getCreationTime() const
bool setExecutePermission(bool shouldBeExecutable) const
File withFileExtension(StringRef newExtension) const
static String createLegalFileName(const String &fileNameToFix)
bool replaceFileIn(const File &targetLocation) const
bool isAChildOf(const File &potentialParentDirectory) const
static File createFileWithoutCheckingPath(const String &absolutePath) noexcept
bool startAsProcess(const String ¶meters=String()) const
String getNativeLinkedTarget() const
bool hasFileExtension(StringRef extensionToTest) const
bool copyDirectoryTo(const File &newDirectory) const
bool loadFileAsData(MemoryBlock &result) const
bool setLastModificationTime(Time newTime) const
Time getLastAccessTime() const
Result createDirectory() const
static File getCurrentWorkingDirectory()
static StringRef getSeparatorString()
File & operator=(const String &newAbsolutePath)
static void JUCE_CALLTYPE writeToLog(const String &message)
MemoryMappedFile(const File &file, AccessMode mode, bool exclusive=false)
virtual bool writeText(const String &text, bool asUTF16, bool writeUTF16ByteOrderMark, const char *lineEndings)
static bool JUCE_CALLTYPE openDocument(const String &documentURL, const String ¶meters)
static Random & getSystemRandom() noexcept
static Result fail(const String &errorMessage) noexcept
static Result ok() noexcept
int addLines(StringRef stringToBreakUp)
bool isNotEmpty() const noexcept
int length() const noexcept
String::CharPointerType text
bool isEmpty() const noexcept
static String repeatedString(StringRef stringToRepeat, int numberOfTimesToRepeat)
int indexOfChar(juce_wchar characterToLookFor) const noexcept
String upToFirstOccurrenceOf(StringRef substringToEndWith, bool includeSubStringInResult, bool ignoreCase) const
int length() const noexcept
bool endsWithChar(juce_wchar character) const noexcept
bool isEmpty() const noexcept
const char * toRawUTF8() const
int64 hashCode64() const noexcept
bool containsChar(juce_wchar character) const noexcept
String removeCharacters(StringRef charactersToRemove) const
bool endsWithIgnoreCase(StringRef text) const noexcept
String dropLastCharacters(int numberToDrop) const
static String toHexString(IntegerType number)
int lastIndexOfChar(juce_wchar character) const noexcept
const wchar_t * toWideCharPointer() const
String trimCharactersAtEnd(StringRef charactersToTrim) const
String replaceCharacter(juce_wchar characterToReplace, juce_wchar characterToInsertInstead) const
String substring(int startIndex, int endIndex) const
int hashCode() const noexcept
bool isNotEmpty() const noexcept
String fromFirstOccurrenceOf(StringRef substringToStartFrom, bool includeSubStringInResult, bool ignoreCase) const
bool overwriteTargetFileWithTemporary() const
const File & getFile() const noexcept
int64 toMilliseconds() const noexcept