Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

760 lines
32KB

  1. /*
  2. ==============================================================================
  3. This file is part of the Water library.
  4. Copyright (c) 2016 ROLI Ltd.
  5. Copyright (C) 2017-2024 Filipe Coelho <falktx@falktx.com>
  6. Permission is granted to use this software under the terms of the ISC license
  7. http://www.isc.org/downloads/software-support-policy/isc-license/
  8. Permission to use, copy, modify, and/or distribute this software for any
  9. purpose with or without fee is hereby granted, provided that the above
  10. copyright notice and this permission notice appear in all copies.
  11. THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD
  12. TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  13. FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
  14. OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
  15. USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  16. TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  17. OF THIS SOFTWARE.
  18. ==============================================================================
  19. */
  20. #ifndef WATER_FILE_H_INCLUDED
  21. #define WATER_FILE_H_INCLUDED
  22. #include "../misc/Result.h"
  23. #include "../text/String.h"
  24. #include <vector>
  25. namespace water {
  26. //==============================================================================
  27. /**
  28. Represents a local file or directory.
  29. This class encapsulates the absolute pathname of a file or directory, and
  30. has methods for finding out about the file and changing its properties.
  31. To read or write to the file, there are methods for returning an input or
  32. output stream.
  33. @see FileInputStream, FileOutputStream
  34. */
  35. class File
  36. {
  37. public:
  38. //==============================================================================
  39. /** Creates an (invalid) file object.
  40. The file is initially set to an empty path, so getFullPathName() will return
  41. an empty string.
  42. You can use its operator= method to point it at a proper file.
  43. */
  44. File() noexcept;
  45. /** Creates a file from an absolute path.
  46. If the path supplied is a relative path, it is taken to be relative
  47. to the current working directory (see File::getCurrentWorkingDirectory()),
  48. but this isn't a recommended way of creating a file, because you
  49. never know what the CWD is going to be.
  50. On the Mac/Linux, the path can include "~" notation for referring to
  51. user home directories.
  52. */
  53. File (const char* absolutePath);
  54. /** Creates a copy of another file object. */
  55. File (const File&);
  56. /** Destructor. */
  57. ~File() noexcept {}
  58. /** Sets the file based on an absolute pathname.
  59. If the path supplied is a relative path, it is taken to be relative
  60. to the current working directory (see File::getCurrentWorkingDirectory()),
  61. but this isn't a recommended way of creating a file, because you
  62. never know what the CWD is going to be.
  63. On the Mac/Linux, the path can include "~" notation for referring to
  64. user home directories.
  65. */
  66. File& operator= (const char* newAbsolutePath);
  67. /** Copies from another file object. */
  68. File& operator= (const File& otherFile);
  69. //==============================================================================
  70. /** Checks whether the file actually exists.
  71. @returns true if the file exists, either as a file or a directory.
  72. @see existsAsFile, isDirectory
  73. */
  74. bool exists() const;
  75. /** Checks whether the file exists and is a file rather than a directory.
  76. @returns true only if this is a real file, false if it's a directory
  77. or doesn't exist
  78. @see exists, isDirectory
  79. */
  80. bool existsAsFile() const;
  81. /** Checks whether the file is a directory that exists.
  82. @returns true only if the file is a directory which actually exists, so
  83. false if it's a file or doesn't exist at all
  84. @see exists, existsAsFile
  85. */
  86. bool isDirectory() const;
  87. /** Checks whether the file is invalid (empty path).
  88. */
  89. bool isNull() const;
  90. /** Checks whether the file is valid (non-empty path).
  91. */
  92. bool isNotNull() const;
  93. /** Returns the size of the file in bytes.
  94. @returns the number of bytes in the file, or 0 if it doesn't exist.
  95. */
  96. int64 getSize() const;
  97. //==============================================================================
  98. /** Returns the complete, absolute path of this file.
  99. This includes the filename and all its parent folders. On Windows it'll
  100. also include the drive letter prefix; on Mac or Linux it'll be a complete
  101. path starting from the root folder.
  102. If you just want the file's name, you should use getFileName() or
  103. getFileNameWithoutExtension().
  104. @see getFileName, getRelativePathFrom
  105. */
  106. const String& getFullPathName() const noexcept { return fullPath; }
  107. /** Returns the last section of the pathname.
  108. Returns just the final part of the path - e.g. if the whole path
  109. is "/moose/fish/foo.txt" this will return "foo.txt".
  110. For a directory, it returns the final part of the path - e.g. for the
  111. directory "/moose/fish" it'll return "fish".
  112. If the filename begins with a dot, it'll return the whole filename, e.g. for
  113. "/moose/.fish", it'll return ".fish"
  114. @see getFullPathName, getFileNameWithoutExtension
  115. */
  116. String getFileName() const;
  117. /** Creates a relative path that refers to a file relatively to a given directory.
  118. e.g. File ("/moose/foo.txt").getRelativePathFrom (File ("/moose/fish/haddock"))
  119. would return "../../foo.txt".
  120. If it's not possible to navigate from one file to the other, an absolute
  121. path is returned. If the paths are invalid, an empty string may also be
  122. returned.
  123. @param directoryToBeRelativeTo the directory which the resultant string will
  124. be relative to. If this is actually a file rather than
  125. a directory, its parent directory will be used instead.
  126. If it doesn't exist, it's assumed to be a directory.
  127. @see getChildFile, isAbsolutePath
  128. */
  129. String getRelativePathFrom (const File& directoryToBeRelativeTo) const;
  130. //==============================================================================
  131. /** Returns the file's extension.
  132. Returns the file extension of this file, also including the dot.
  133. e.g. "/moose/fish/foo.txt" would return ".txt"
  134. @see hasFileExtension, withFileExtension, getFileNameWithoutExtension
  135. */
  136. String getFileExtension() const;
  137. /** Checks whether the file has a given extension.
  138. @param extensionToTest the extension to look for - it doesn't matter whether or
  139. not this string has a dot at the start, so ".wav" and "wav"
  140. will have the same effect. To compare with multiple extensions, this
  141. parameter can contain multiple strings, separated by semi-colons -
  142. so, for example: hasFileExtension (".jpeg;png;gif") would return
  143. true if the file has any of those three extensions.
  144. @see getFileExtension, withFileExtension, getFileNameWithoutExtension
  145. */
  146. bool hasFileExtension (const char* extensionToTest) const;
  147. /** Returns a version of this file with a different file extension.
  148. e.g. File ("/moose/fish/foo.txt").withFileExtension ("html") returns "/moose/fish/foo.html"
  149. @param newExtension the new extension, either with or without a dot at the start (this
  150. doesn't make any difference). To get remove a file's extension altogether,
  151. pass an empty string into this function.
  152. @see getFileName, getFileExtension, hasFileExtension, getFileNameWithoutExtension
  153. */
  154. File withFileExtension (const char* newExtension) const;
  155. /** Returns the last part of the filename, without its file extension.
  156. e.g. for "/moose/fish/foo.txt" this will return "foo".
  157. @see getFileName, getFileExtension, hasFileExtension, withFileExtension
  158. */
  159. String getFileNameWithoutExtension() const;
  160. //==============================================================================
  161. /** Returns a file that represents a relative (or absolute) sub-path of the current one.
  162. This will find a child file or directory of the current object.
  163. e.g.
  164. File ("/moose/fish").getChildFile ("foo.txt") will produce "/moose/fish/foo.txt".
  165. File ("/moose/fish").getChildFile ("haddock/foo.txt") will produce "/moose/fish/haddock/foo.txt".
  166. File ("/moose/fish").getChildFile ("../foo.txt") will produce "/moose/foo.txt".
  167. If the string is actually an absolute path, it will be treated as such, e.g.
  168. File ("/moose/fish").getChildFile ("/foo.txt") will produce "/foo.txt"
  169. @see getSiblingFile, getParentDirectory, getRelativePathFrom, isAChildOf
  170. */
  171. File getChildFile (const char* relativeOrAbsolutePath) const;
  172. /** Returns a file which is in the same directory as this one.
  173. This is equivalent to getParentDirectory().getChildFile (name).
  174. @see getChildFile, getParentDirectory
  175. */
  176. File getSiblingFile (const char* siblingFileName) const;
  177. //==============================================================================
  178. /** Returns the directory that contains this file or directory.
  179. e.g. for "/moose/fish/foo.txt" this will return "/moose/fish".
  180. */
  181. File getParentDirectory() const;
  182. /** Checks whether a file is somewhere inside a directory.
  183. Returns true if this file is somewhere inside a subdirectory of the directory
  184. that is passed in. Neither file actually has to exist, because the function
  185. just checks the paths for similarities.
  186. e.g. File ("/moose/fish/foo.txt").isAChildOf ("/moose") is true.
  187. File ("/moose/fish/foo.txt").isAChildOf ("/moose/fish") is also true.
  188. */
  189. bool isAChildOf (const File& potentialParentDirectory) const;
  190. //==============================================================================
  191. /** Chooses a filename relative to this one that doesn't already exist.
  192. If this file is a directory, this will return a child file of this
  193. directory that doesn't exist, by adding numbers to a prefix and suffix until
  194. it finds one that isn't already there.
  195. If the prefix + the suffix doesn't exist, it won't bother adding a number.
  196. e.g. File ("/moose/fish").getNonexistentChildFile ("foo", ".txt", true) might
  197. return "/moose/fish/foo(2).txt" if there's already a file called "foo.txt".
  198. @param prefix the string to use for the filename before the number
  199. @param suffix the string to add to the filename after the number
  200. @param putNumbersInBrackets if true, this will create filenames in the
  201. format "prefix(number)suffix", if false, it will leave the
  202. brackets out.
  203. */
  204. File getNonexistentChildFile (const String& prefix,
  205. const String& suffix,
  206. bool putNumbersInBrackets = true) const;
  207. /** Chooses a filename for a sibling file to this one that doesn't already exist.
  208. If this file doesn't exist, this will just return itself, otherwise it
  209. will return an appropriate sibling that doesn't exist, e.g. if a file
  210. "/moose/fish/foo.txt" exists, this might return "/moose/fish/foo(2).txt".
  211. @param putNumbersInBrackets whether to add brackets around the numbers that
  212. get appended to the new filename.
  213. */
  214. File getNonexistentSibling (bool putNumbersInBrackets = true) const;
  215. //==============================================================================
  216. /** Compares the pathnames for two files. */
  217. bool operator== (const File&) const;
  218. /** Compares the pathnames for two files. */
  219. bool operator!= (const File&) const;
  220. /** Compares the pathnames for two files. */
  221. bool operator< (const File&) const;
  222. /** Compares the pathnames for two files. */
  223. bool operator> (const File&) const;
  224. //==============================================================================
  225. /** Checks whether a file can be created or written to.
  226. @returns true if it's possible to create and write to this file. If the file
  227. doesn't already exist, this will check its parent directory to
  228. see if writing is allowed.
  229. @see setReadOnly
  230. */
  231. bool hasWriteAccess() const;
  232. /** Returns true if this file is a hidden or system file.
  233. The criteria for deciding whether a file is hidden are platform-dependent.
  234. */
  235. bool isHidden() const;
  236. //==============================================================================
  237. /** Returns the last modification time of this file.
  238. @returns the time, or an invalid time if the file doesn't exist.
  239. @see getLastAccessTime, getCreationTime
  240. */
  241. int64 getLastModificationTime() const;
  242. /** Returns the last time this file was accessed.
  243. @returns the time, or an invalid time if the file doesn't exist.
  244. @see getLastModificationTime, getCreationTime
  245. */
  246. int64 getLastAccessTime() const;
  247. /** Returns the time that this file was created.
  248. @returns the time, or an invalid time if the file doesn't exist.
  249. @see getLastModificationTime, getLastAccessTime
  250. */
  251. int64 getCreationTime() const;
  252. //==============================================================================
  253. /** Creates an empty file if it doesn't already exist.
  254. If the file that this object refers to doesn't exist, this will create a file
  255. of zero size.
  256. If it already exists or is a directory, this method will do nothing.
  257. If the parent directories of the File do not exist then this method will
  258. recursively create the parent directories.
  259. @returns a result to indicate whether the file was created successfully,
  260. or an error message if it failed.
  261. @see createDirectory
  262. */
  263. Result create() const;
  264. /** Creates a new directory for this filename.
  265. This will try to create the file as a directory, and will also create
  266. any parent directories it needs in order to complete the operation.
  267. @returns a result to indicate whether the directory was created successfully, or
  268. an error message if it failed.
  269. @see create
  270. */
  271. Result createDirectory() const;
  272. /** Deletes a file.
  273. If this file is actually a directory, it may not be deleted correctly if it
  274. contains files. See deleteRecursively() as a better way of deleting directories.
  275. @returns true if the file has been successfully deleted (or if it didn't exist to
  276. begin with).
  277. @see deleteRecursively
  278. */
  279. bool deleteFile() const;
  280. /** Deletes a file or directory and all its subdirectories.
  281. If this file is a directory, this will try to delete it and all its subfolders. If
  282. it's just a file, it will just try to delete the file.
  283. @returns true if the file and all its subfolders have been successfully deleted
  284. (or if it didn't exist to begin with).
  285. @see deleteFile
  286. */
  287. bool deleteRecursively() const;
  288. /** Moves or renames a file.
  289. Tries to move a file to a different location.
  290. If the target file already exists, this will attempt to delete it first, and
  291. will fail if this can't be done.
  292. Note that the destination file isn't the directory to put it in, it's the actual
  293. filename that you want the new file to have.
  294. Also note that on some OSes (e.g. Windows), moving files between different
  295. volumes may not be possible.
  296. @returns true if the operation succeeds
  297. */
  298. bool moveFileTo (const File& targetLocation) const;
  299. /** Copies a file.
  300. Tries to copy a file to a different location.
  301. If the target file already exists, this will attempt to delete it first, and
  302. will fail if this can't be done.
  303. @returns true if the operation succeeds
  304. */
  305. bool copyFileTo (const File& targetLocation) const;
  306. /** Replaces a file.
  307. Replace the file in the given location, assuming the replaced files identity.
  308. Depending on the file system this will preserve file attributes such as
  309. creation date, short file name, etc.
  310. If replacement succeeds the original file is deleted.
  311. @returns true if the operation succeeds
  312. */
  313. bool replaceFileIn (const File& targetLocation) const;
  314. /** Copies a directory.
  315. Tries to copy an entire directory, recursively.
  316. If this file isn't a directory or if any target files can't be created, this
  317. will return false.
  318. @param newDirectory the directory that this one should be copied to. Note that this
  319. is the name of the actual directory to create, not the directory
  320. into which the new one should be placed, so there must be enough
  321. write privileges to create it if it doesn't exist. Any files inside
  322. it will be overwritten by similarly named ones that are copied.
  323. */
  324. bool copyDirectoryTo (const File& newDirectory) const;
  325. //==============================================================================
  326. /** Used in file searching, to specify whether to return files, directories, or both.
  327. */
  328. enum TypesOfFileToFind
  329. {
  330. findDirectories = 1, /**< Use this flag to indicate that you want to find directories. */
  331. findFiles = 2, /**< Use this flag to indicate that you want to find files. */
  332. findFilesAndDirectories = 3, /**< Use this flag to indicate that you want to find both files and directories. */
  333. ignoreHiddenFiles = 4 /**< Add this flag to avoid returning any hidden files in the results. */
  334. };
  335. /** Searches inside a directory for files matching a wildcard pattern.
  336. Assuming that this file is a directory, this method will search it
  337. for either files or subdirectories whose names match a filename pattern.
  338. @param results an vector to which File objects will be added for the
  339. files that the search comes up with
  340. @param whatToLookFor a value from the TypesOfFileToFind enum, specifying whether to
  341. return files, directories, or both. If the ignoreHiddenFiles flag
  342. is also added to this value, hidden files won't be returned
  343. @param searchRecursively if true, all subdirectories will be recursed into to do
  344. an exhaustive search
  345. @param wildCardPattern the filename pattern to search for, e.g. "*.txt"
  346. @returns the number of results that have been found
  347. @see getNumberOfChildFiles, DirectoryIterator
  348. */
  349. uint findChildFiles (std::vector<File>& results,
  350. int whatToLookFor,
  351. bool searchRecursively,
  352. const char* wildCardPattern = "*") const;
  353. /** Searches inside a directory and counts how many files match a wildcard pattern.
  354. Assuming that this file is a directory, this method will search it
  355. for either files or subdirectories whose names match a filename pattern,
  356. and will return the number of matches found.
  357. This isn't a recursive call, and will only search this directory, not
  358. its children.
  359. @param whatToLookFor a value from the TypesOfFileToFind enum, specifying whether to
  360. count files, directories, or both. If the ignoreHiddenFiles flag
  361. is also added to this value, hidden files won't be counted
  362. @param wildCardPattern the filename pattern to search for, e.g. "*.txt"
  363. @returns the number of matches found
  364. @see findChildFiles, DirectoryIterator
  365. */
  366. uint getNumberOfChildFiles (int whatToLookFor,
  367. const char* wildCardPattern = "*") const;
  368. /** Returns true if this file is a directory that contains one or more subdirectories.
  369. @see isDirectory, findChildFiles
  370. */
  371. bool containsSubDirectories() const;
  372. //==============================================================================
  373. /** Creates a stream to read from this file.
  374. @returns a stream that will read from this file (initially positioned at the
  375. start of the file), or nullptr if the file can't be opened for some reason
  376. @see createOutputStream, loadFileAsData
  377. */
  378. FileInputStream* createInputStream() const;
  379. /** Creates a stream to write to this file.
  380. If the file exists, the stream that is returned will be positioned ready for
  381. writing at the end of the file, so you might want to use deleteFile() first
  382. to write to an empty file.
  383. @returns a stream that will write to this file (initially positioned at the
  384. end of the file), or nullptr if the file can't be opened for some reason
  385. @see createInputStream, appendData, appendText
  386. */
  387. FileOutputStream* createOutputStream (size_t bufferSize = 0x8000) const;
  388. //==============================================================================
  389. /** Loads a file's contents into memory as a block of binary data.
  390. Of course, trying to load a very large file into memory will blow up, so
  391. it's better to check first.
  392. @param result the data block to which the file's contents should be appended - note
  393. that if the memory block might already contain some data, you
  394. might want to clear it first
  395. @returns true if the file could all be read into memory
  396. */
  397. bool loadFileAsData (MemoryBlock& result) const;
  398. /** Reads a file into memory as a string.
  399. Attempts to load the entire file as a zero-terminated string.
  400. This makes use of InputStream::readEntireStreamAsString, which can
  401. read either UTF-16 or UTF-8 file formats.
  402. */
  403. String loadFileAsString() const;
  404. //==============================================================================
  405. /** Appends a block of binary data to the end of the file.
  406. This will try to write the given buffer to the end of the file.
  407. @returns false if it can't write to the file for some reason
  408. */
  409. bool appendData (const void* dataToAppend,
  410. size_t numberOfBytes) const;
  411. /** Replaces this file's contents with a given block of data.
  412. This will delete the file and replace it with the given data.
  413. A nice feature of this method is that it's safe - instead of deleting
  414. the file first and then re-writing it, it creates a new temporary file,
  415. writes the data to that, and then moves the new file to replace the existing
  416. file. This means that if the power gets pulled out or something crashes,
  417. you're a lot less likely to end up with a corrupted or unfinished file..
  418. Returns true if the operation succeeds, or false if it fails.
  419. @see appendText
  420. */
  421. bool replaceWithData (const void* dataToWrite,
  422. size_t numberOfBytes) const;
  423. /** Appends a string to the end of the file.
  424. This will try to append a text string to the file, as either 16-bit unicode
  425. or 8-bit characters in the default system encoding.
  426. It can also write the 'ff fe' unicode header bytes before the text to indicate
  427. the endianness of the file.
  428. Any single \\n characters in the string are replaced with \\r\\n before it is written.
  429. @see replaceWithText
  430. */
  431. bool appendText (const String& textToAppend,
  432. bool asUnicode = false,
  433. bool writeUnicodeHeaderBytes = false) const;
  434. /** Replaces this file's contents with a given text string.
  435. This will delete the file and replace it with the given text.
  436. A nice feature of this method is that it's safe - instead of deleting
  437. the file first and then re-writing it, it creates a new temporary file,
  438. writes the text to that, and then moves the new file to replace the existing
  439. file. This means that if the power gets pulled out or something crashes,
  440. you're a lot less likely to end up with an empty file..
  441. For an explanation of the parameters here, see the appendText() method.
  442. Returns true if the operation succeeds, or false if it fails.
  443. @see appendText
  444. */
  445. bool replaceWithText (const String& textToWrite,
  446. bool asUnicode = false,
  447. bool writeUnicodeHeaderBytes = false) const;
  448. /** Attempts to scan the contents of this file and compare it to another file, returning
  449. true if this is possible and they match byte-for-byte.
  450. */
  451. bool hasIdenticalContentTo (const File& other) const;
  452. //==============================================================================
  453. /** A set of types of location that can be passed to the getSpecialLocation() method.
  454. */
  455. enum SpecialLocationType
  456. {
  457. /** The user's home folder. This is the same as using File ("~"). */
  458. userHomeDirectory,
  459. /** The folder that should be used for temporary files.
  460. Always delete them when you're finished, to keep the user's computer tidy!
  461. */
  462. tempDirectory,
  463. /** Returns this application's executable file.
  464. If running as a plug-in or DLL, this will (where possible) be the DLL rather than the
  465. host app.
  466. On the mac this will return the unix binary, not the package folder.
  467. */
  468. currentExecutableFile,
  469. /** In a plugin, this will return the path of the host executable. */
  470. hostApplicationPath,
  471. /** Windows specific paths */
  472. winAppData, winProgramFiles, winCommonProgramFiles, winMyDocuments
  473. };
  474. /** Finds the location of a special type of file or directory, such as a home folder or
  475. documents folder.
  476. @see SpecialLocationType
  477. */
  478. static File getSpecialLocation (const SpecialLocationType type);
  479. //==============================================================================
  480. /** Returns a temporary file in the system's temp directory.
  481. This will try to return the name of a non-existent temp file.
  482. To get the temp folder, you can use getSpecialLocation (File::tempDirectory).
  483. */
  484. static File createTempFile (const char* fileNameEnding);
  485. //==============================================================================
  486. /** Returns the current working directory.
  487. @see setAsCurrentWorkingDirectory
  488. */
  489. static File getCurrentWorkingDirectory();
  490. /** Sets the current working directory to be this file.
  491. For this to work the file must point to a valid directory.
  492. @returns true if the current directory has been changed.
  493. @see getCurrentWorkingDirectory
  494. */
  495. bool setAsCurrentWorkingDirectory() const;
  496. //==============================================================================
  497. /** Returns a version of a filename with any illegal characters removed.
  498. This will return a copy of the given string after removing characters
  499. that are not allowed in a legal filename, and possibly shortening the
  500. string if it's too long.
  501. Because this will remove slashes, don't use it on an absolute pathname - use
  502. createLegalPathName() for that.
  503. @see createLegalPathName
  504. */
  505. static String createLegalFileName (const String& fileNameToFix);
  506. /** Returns a version of a path with any illegal characters removed.
  507. Similar to createLegalFileName(), but this won't remove slashes, so can
  508. be used on a complete pathname.
  509. @see createLegalFileName
  510. */
  511. static String createLegalPathName (const String& pathNameToFix);
  512. /** Indicates whether filenames are case-sensitive on the current operating system. */
  513. static bool areFileNamesCaseSensitive();
  514. /** Returns true if the string seems to be a fully-specified absolute path. */
  515. static bool isAbsolutePath (const char* path);
  516. /** Creates a file that simply contains this string, without doing the sanity-checking
  517. that the normal constructors do.
  518. Best to avoid this unless you really know what you're doing.
  519. */
  520. static File createFileWithoutCheckingPath (const String& absolutePath) noexcept;
  521. /** Adds a separator character to the end of a path if it doesn't already have one. */
  522. static String addTrailingSeparator (const String& path);
  523. //==============================================================================
  524. /** Tries to create a symbolic link and returns a boolean to indicate success */
  525. bool createSymbolicLink (const File& linkFileToCreate, bool overwriteExisting) const;
  526. /** Returns true if this file is a link or alias that can be followed using getLinkedTarget(). */
  527. bool isSymbolicLink() const;
  528. /** If this file is a link or alias, this returns the file that it points to.
  529. If the file isn't actually link, it'll just return itself.
  530. */
  531. File getLinkedTarget() const;
  532. //==============================================================================
  533. struct NaturalFileComparator
  534. {
  535. NaturalFileComparator (bool shouldPutFoldersFirst) noexcept : foldersFirst (shouldPutFoldersFirst) {}
  536. int compareElements (const File& firstFile, const File& secondFile) const
  537. {
  538. if (foldersFirst && (firstFile.isDirectory() != secondFile.isDirectory()))
  539. return firstFile.isDirectory() ? -1 : 1;
  540. return firstFile.getFullPathName().compareNatural (secondFile.getFullPathName(), File::areFileNamesCaseSensitive());
  541. }
  542. bool foldersFirst;
  543. };
  544. private:
  545. //==============================================================================
  546. String fullPath;
  547. static String parseAbsolutePath (const String&);
  548. String getPathUpToLastSlash() const;
  549. Result createDirectoryInternal (const String&) const;
  550. bool copyInternal (const File&) const;
  551. bool moveInternal (const File&) const;
  552. bool replaceInternal (const File&) const;
  553. void getFileTimesInternal (int64& m, int64& a, int64& c) const;
  554. bool setFileReadOnlyInternal (bool) const;
  555. bool setFileExecutableInternal (bool) const;
  556. };
  557. }
  558. #endif // WATER_FILE_H_INCLUDED