OpenShot Audio Library | OpenShotAudio: juce_File.cpp Source File

OpenShot Audio Library | OpenShotAudio 0.4.0

Loading...
Searching...
No Matches
juce_File.cpp
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21*/
22
23namespace juce
24{
25
26 File::File (const String& fullPathName)
27 : fullPath (parseAbsolutePath (fullPathName))
28{
29}
30
31 File File::createFileWithoutCheckingPath (const String& path) noexcept
32{
33 File f;
34 f.fullPath = path;
35 return f;
36}
37
38 File::File (const File& other)
39 : fullPath (other.fullPath)
40{
41}
42
43 File& File::operator= (const String& newPath)
44{
45 fullPath = parseAbsolutePath (newPath);
46 return *this;
47}
48
49 File& File::operator= (const File& other)
50{
51 fullPath = other.fullPath;
52 return *this;
53}
54
55 File::File (File&& other) noexcept
56 : fullPath (std::move (other.fullPath))
57{
58}
59
60 File& File::operator= (File&& other) noexcept
61{
62 fullPath = std::move (other.fullPath);
63 return *this;
64}
65
66//==============================================================================
67static String removeEllipsis (const String& path)
68{
69 // This will quickly find both /../ and /./ at the expense of a minor
70 // false-positive performance hit when path elements end in a dot.
71 #if JUCE_WINDOWS
72 if (path.contains (".\\"))
73 #else
74 if (path.contains ("./"))
75 #endif
76 {
77 StringArray toks;
78 toks.addTokens (path, File::getSeparatorString(), {});
79 bool anythingChanged = false;
80
81 for (int i = 1; i < toks.size(); ++i)
82 {
83 auto& t = toks[i];
84
85 if (t == ".." && toks[i - 1] != "..")
86 {
87 anythingChanged = true;
88 toks.removeRange (i - 1, 2);
89 i = jmax (0, i - 2);
90 }
91 else if (t == ".")
92 {
93 anythingChanged = true;
94 toks.remove (i--);
95 }
96 }
97
98 if (anythingChanged)
99 return toks.joinIntoString (File::getSeparatorString());
100 }
101
102 return path;
103}
104
105static String normaliseSeparators (const String& path)
106{
107 auto normalisedPath = path;
108
109 String separator (File::getSeparatorString());
110 String doubleSeparator (separator + separator);
111
112 auto uncPath = normalisedPath.startsWith (doubleSeparator)
113 && ! normalisedPath.fromFirstOccurrenceOf (doubleSeparator, false, false).startsWith (separator);
114
115 if (uncPath)
116 normalisedPath = normalisedPath.fromFirstOccurrenceOf (doubleSeparator, false, false);
117
118 while (normalisedPath.contains (doubleSeparator))
119 normalisedPath = normalisedPath.replace (doubleSeparator, separator);
120
121 return uncPath ? doubleSeparator + normalisedPath
122 : normalisedPath;
123}
124
125 bool File::isRoot() const
126{
127 return fullPath.isNotEmpty() && *this == getParentDirectory();
128}
129
130 String File::parseAbsolutePath (const String& p)
131{
132 if (p.isEmpty())
133 return {};
134
135 #if JUCE_WINDOWS
136 // Windows..
137 auto path = normaliseSeparators (removeEllipsis (p.replaceCharacter ('/', '\\')));
138
139 if (path.startsWithChar (getSeparatorChar()))
140 {
141 if (path[1] != getSeparatorChar())
142 {
143 /* When you supply a raw string to the File object constructor, it must be an absolute path.
144 If you're trying to parse a string that may be either a relative path or an absolute path,
145 you MUST provide a context against which the partial path can be evaluated - you can do
146 this by simply using File::getChildFile() instead of the File constructor. E.g. saying
147 "File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
148 path if that's what was supplied, or would evaluate a partial path relative to the CWD.
149 */
150 jassertfalse;
151
152 path = File::getCurrentWorkingDirectory().getFullPathName().substring (0, 2) + path;
153 }
154 }
155 else if (! path.containsChar (':'))
156 {
157 /* When you supply a raw string to the File object constructor, it must be an absolute path.
158 If you're trying to parse a string that may be either a relative path or an absolute path,
159 you MUST provide a context against which the partial path can be evaluated - you can do
160 this by simply using File::getChildFile() instead of the File constructor. E.g. saying
161 "File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
162 path if that's what was supplied, or would evaluate a partial path relative to the CWD.
163 */
164 jassertfalse;
165
166 return File::getCurrentWorkingDirectory().getChildFile (path).getFullPathName();
167 }
168 #else
169 // Mac or Linux..
170
171 // Yes, I know it's legal for a unix pathname to contain a backslash, but this assertion is here
172 // to catch anyone who's trying to run code that was written on Windows with hard-coded path names.
173 // If that's why you've ended up here, use File::getChildFile() to build your paths instead.
174 jassert ((! p.containsChar ('\\')) || (p.indexOfChar ('/') >= 0 && p.indexOfChar ('/') < p.indexOfChar ('\\')));
175
176 auto path = normaliseSeparators (removeEllipsis (p));
177
178 if (path.startsWithChar ('~'))
179 {
180 if (path[1] == getSeparatorChar() || path[1] == 0)
181 {
182 // expand a name of the form "~/abc"
183 path = File::getSpecialLocation (File::userHomeDirectory).getFullPathName()
184 + path.substring (1);
185 }
186 else
187 {
188 // expand a name of type "~dave/abc"
189 auto userName = path.substring (1).upToFirstOccurrenceOf ("/", false, false);
190
191 if (auto* pw = getpwnam (userName.toUTF8()))
192 path = addTrailingSeparator (pw->pw_dir) + path.fromFirstOccurrenceOf ("/", false, false);
193 }
194 }
195 else if (! path.startsWithChar (getSeparatorChar()))
196 {
197 #if JUCE_DEBUG || JUCE_LOG_ASSERTIONS
198 if (! (path.startsWith ("./") || path.startsWith ("../")))
199 {
200 /* When you supply a raw string to the File object constructor, it must be an absolute path.
201 If you're trying to parse a string that may be either a relative path or an absolute path,
202 you MUST provide a context against which the partial path can be evaluated - you can do
203 this by simply using File::getChildFile() instead of the File constructor. E.g. saying
204 "File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
205 path if that's what was supplied, or would evaluate a partial path relative to the CWD.
206 */
207 jassertfalse;
208
209 #if JUCE_LOG_ASSERTIONS
210 Logger::writeToLog ("Illegal absolute path: " + path);
211 #endif
212 }
213 #endif
214
215 return File::getCurrentWorkingDirectory().getChildFile (path).getFullPathName();
216 }
217 #endif
218
219 while (path.endsWithChar (getSeparatorChar()) && path != getSeparatorString()) // careful not to turn a single "/" into an empty string.
220 path = path.dropLastCharacters (1);
221
222 return path;
223}
224
225 String File::addTrailingSeparator (const String& path)
226{
227 return path.endsWithChar (getSeparatorChar()) ? path
228 : path + getSeparatorChar();
229}
230
231//==============================================================================
232#if JUCE_LINUX || JUCE_BSD
233 #define NAMES_ARE_CASE_SENSITIVE 1
234#endif
235
236 bool File::areFileNamesCaseSensitive()
237{
238 #if NAMES_ARE_CASE_SENSITIVE
239 return true;
240 #else
241 return false;
242 #endif
243}
244
245static int compareFilenames (const String& name1, const String& name2) noexcept
246{
247 #if NAMES_ARE_CASE_SENSITIVE
248 return name1.compare (name2);
249 #else
250 return name1.compareIgnoreCase (name2);
251 #endif
252}
253
254 bool File::operator== (const File& other) const { return compareFilenames (fullPath, other.fullPath) == 0; }
255 bool File::operator!= (const File& other) const { return compareFilenames (fullPath, other.fullPath) != 0; }
256 bool File::operator< (const File& other) const { return compareFilenames (fullPath, other.fullPath) < 0; }
257 bool File::operator> (const File& other) const { return compareFilenames (fullPath, other.fullPath) > 0; }
258
259//==============================================================================
260 bool File::setReadOnly (const bool shouldBeReadOnly,
261 const bool applyRecursively) const
262{
263 bool worked = true;
264
265 if (applyRecursively && isDirectory())
266 for (auto& f : findChildFiles (File::findFilesAndDirectories, false))
267 worked = f.setReadOnly (shouldBeReadOnly, true) && worked;
268
269 return setFileReadOnlyInternal (shouldBeReadOnly) && worked;
270}
271
272 bool File::setExecutePermission (bool shouldBeExecutable) const
273{
274 return setFileExecutableInternal (shouldBeExecutable);
275}
276
277 bool File::deleteRecursively (bool followSymlinks) const
278{
279 bool worked = true;
280
281 if (isDirectory() && (followSymlinks || ! isSymbolicLink()))
282 for (auto& f : findChildFiles (File::findFilesAndDirectories, false))
283 worked = f.deleteRecursively (followSymlinks) && worked;
284
285 return deleteFile() && worked;
286}
287
288 bool File::moveFileTo (const File& newFile) const
289{
290 if (newFile.fullPath == fullPath)
291 return true;
292
293 if (! exists())
294 return false;
295
296 #if ! NAMES_ARE_CASE_SENSITIVE
297 if (*this != newFile)
298 #endif
299 if (! newFile.deleteFile())
300 return false;
301
302 return moveInternal (newFile);
303}
304
305 bool File::copyFileTo (const File& newFile) const
306{
307 return (*this == newFile)
308 || (exists() && newFile.deleteFile() && copyInternal (newFile));
309}
310
311 bool File::replaceFileIn (const File& newFile) const
312{
313 if (newFile.fullPath == fullPath)
314 return true;
315
316 if (! newFile.exists())
317 return moveFileTo (newFile);
318
319 if (! replaceInternal (newFile))
320 return false;
321
322 deleteFile();
323 return true;
324}
325
326 bool File::copyDirectoryTo (const File& newDirectory) const
327{
328 if (isDirectory() && newDirectory.createDirectory())
329 {
330 for (auto& f : findChildFiles (File::findFiles, false))
331 if (! f.copyFileTo (newDirectory.getChildFile (f.getFileName())))
332 return false;
333
334 for (auto& f : findChildFiles (File::findDirectories, false))
335 if (! f.copyDirectoryTo (newDirectory.getChildFile (f.getFileName())))
336 return false;
337
338 return true;
339 }
340
341 return false;
342}
343
344//==============================================================================
345 String File::getPathUpToLastSlash() const
346{
347 auto lastSlash = fullPath.lastIndexOfChar (getSeparatorChar());
348
349 if (lastSlash > 0)
350 return fullPath.substring (0, lastSlash);
351
352 if (lastSlash == 0)
353 return getSeparatorString();
354
355 return fullPath;
356}
357
358 File File::getParentDirectory() const
359{
360 return createFileWithoutCheckingPath (getPathUpToLastSlash());
361}
362
363bool File::isNonEmptyDirectory() const
364{
365 if (! isDirectory())
366 return false;
367
368 return RangedDirectoryIterator (*this, false, "*", findFilesAndDirectories) != RangedDirectoryIterator();
369}
370
371//==============================================================================
372 String File::getFileName() const
373{
374 return fullPath.substring (fullPath.lastIndexOfChar (getSeparatorChar()) + 1);
375}
376
377 String File::getFileNameWithoutExtension() const
378{
379 auto lastSlash = fullPath.lastIndexOfChar (getSeparatorChar()) + 1;
380 auto lastDot = fullPath.lastIndexOfChar ('.');
381
382 if (lastDot > lastSlash)
383 return fullPath.substring (lastSlash, lastDot);
384
385 return fullPath.substring (lastSlash);
386}
387
388 bool File::isAChildOf (const File& potentialParent) const
389{
390 if (potentialParent.fullPath.isEmpty())
391 return false;
392
393 auto ourPath = getPathUpToLastSlash();
394
395 if (compareFilenames (potentialParent.fullPath, ourPath) == 0)
396 return true;
397
398 if (potentialParent.fullPath.length() >= ourPath.length())
399 return false;
400
401 return getParentDirectory().isAChildOf (potentialParent);
402}
403
404 int File::hashCode() const { return fullPath.hashCode(); }
405int64 File::hashCode64() const { return fullPath.hashCode64(); }
406
407//==============================================================================
408 bool File::isAbsolutePath (StringRef path)
409{
410 auto firstChar = *(path.text);
411
412 return firstChar == getSeparatorChar()
413 #if JUCE_WINDOWS
414 || (firstChar != 0 && path.text[1] == ':');
415 #else
416 || firstChar == '~';
417 #endif
418}
419
420 File File::getChildFile (StringRef relativePath) const
421{
422 auto r = relativePath.text;
423
424 if (isAbsolutePath (r))
425 return File (String (r));
426
427 #if JUCE_WINDOWS
428 if (r.indexOf ((juce_wchar) '/') >= 0)
429 return getChildFile (String (r).replaceCharacter ('/', '\\'));
430 #endif
431
432 auto path = fullPath;
433 auto separatorChar = getSeparatorChar();
434
435 while (*r == '.')
436 {
437 auto lastPos = r;
438 auto secondChar = *++r;
439
440 if (secondChar == '.') // remove "../"
441 {
442 auto thirdChar = *++r;
443
444 if (thirdChar == separatorChar || thirdChar == 0)
445 {
446 auto lastSlash = path.lastIndexOfChar (separatorChar);
447
448 if (lastSlash >= 0)
449 path = path.substring (0, lastSlash);
450
451 while (*r == separatorChar) // ignore duplicate slashes
452 ++r;
453 }
454 else
455 {
456 r = lastPos;
457 break;
458 }
459 }
460 else if (secondChar == separatorChar || secondChar == 0) // remove "./"
461 {
462 while (*r == separatorChar) // ignore duplicate slashes
463 ++r;
464 }
465 else
466 {
467 r = lastPos;
468 break;
469 }
470 }
471
472 path = addTrailingSeparator (path);
473 path.appendCharPointer (r);
474 return File (path);
475}
476
477 File File::getSiblingFile (StringRef fileName) const
478{
479 return getParentDirectory().getChildFile (fileName);
480}
481
482//==============================================================================
483 String File::descriptionOfSizeInBytes (const int64 bytes)
484{
485 const char* suffix;
486 double divisor = 0;
487
488 if (bytes == 1) { suffix = " byte"; }
489 else if (bytes < 1024) { suffix = " bytes"; }
490 else if (bytes < 1024 * 1024) { suffix = " KB"; divisor = 1024.0; }
491 else if (bytes < 1024 * 1024 * 1024) { suffix = " MB"; divisor = 1024.0 * 1024.0; }
492 else { suffix = " GB"; divisor = 1024.0 * 1024.0 * 1024.0; }
493
494 return (divisor > 0 ? String ((double) bytes / divisor, 1) : String (bytes)) + suffix;
495}
496
497//==============================================================================
498 Result File::create() const
499{
500 if (exists())
501 return Result::ok();
502
503 auto parentDir = getParentDirectory();
504
505 if (parentDir == *this)
506 return Result::fail ("Cannot create parent directory");
507
508 auto r = parentDir.createDirectory();
509
510 if (r.wasOk())
511 {
512 FileOutputStream fo (*this, 8);
513 r = fo.getStatus();
514 }
515
516 return r;
517}
518
519 Result File::createDirectory() const
520{
521 if (isDirectory())
522 return Result::ok();
523
524 auto parentDir = getParentDirectory();
525
526 if (parentDir == *this)
527 return Result::fail ("Cannot create parent directory");
528
529 auto r = parentDir.createDirectory();
530
531 if (r.wasOk())
532 r = createDirectoryInternal (fullPath.trimCharactersAtEnd (getSeparatorString()));
533
534 return r;
535}
536
537//==============================================================================
538 Time File::getLastModificationTime() const { int64 m, a, c; getFileTimesInternal (m, a, c); return Time (m); }
539 Time File::getLastAccessTime() const { int64 m, a, c; getFileTimesInternal (m, a, c); return Time (a); }
540 Time File::getCreationTime() const { int64 m, a, c; getFileTimesInternal (m, a, c); return Time (c); }
541
542 bool File::setLastModificationTime (Time t) const { return setFileTimesInternal (t.toMilliseconds(), 0, 0); }
543 bool File::setLastAccessTime (Time t) const { return setFileTimesInternal (0, t.toMilliseconds(), 0); }
544 bool File::setCreationTime (Time t) const { return setFileTimesInternal (0, 0, t.toMilliseconds()); }
545
546//==============================================================================
547 bool File::loadFileAsData (MemoryBlock& destBlock) const
548{
549 if (! existsAsFile())
550 return false;
551
552 FileInputStream in (*this);
553 return in.openedOk() && getSize() == (int64) in.readIntoMemoryBlock (destBlock);
554}
555
556 String File::loadFileAsString() const
557{
558 if (! existsAsFile())
559 return {};
560
561 FileInputStream in (*this);
562 return in.openedOk() ? in.readEntireStreamAsString()
563 : String();
564}
565
566 void File::readLines (StringArray& destLines) const
567{
568 destLines.addLines (loadFileAsString());
569}
570
571//==============================================================================
572 Array<File> File::findChildFiles (int whatToLookFor, bool searchRecursively, const String& wildcard, FollowSymlinks followSymlinks) const
573{
574 Array<File> results;
575 findChildFiles (results, whatToLookFor, searchRecursively, wildcard, followSymlinks);
576 return results;
577}
578
579 int File::findChildFiles (Array<File>& results, int whatToLookFor, bool searchRecursively, const String& wildcard, FollowSymlinks followSymlinks) const
580{
581 int total = 0;
582
583 for (const auto& di : RangedDirectoryIterator (*this, searchRecursively, wildcard, whatToLookFor, followSymlinks))
584 {
585 results.add (di.getFile());
586 ++total;
587 }
588
589 return total;
590}
591
592 int File::getNumberOfChildFiles (const int whatToLookFor, const String& wildCardPattern) const
593{
594 return std::accumulate (RangedDirectoryIterator (*this, false, wildCardPattern, whatToLookFor),
595 RangedDirectoryIterator(),
596 0,
597 [] (int acc, const DirectoryEntry&) { return acc + 1; });
598}
599
600 bool File::containsSubDirectories() const
601{
602 if (! isDirectory())
603 return false;
604
605 return RangedDirectoryIterator (*this, false, "*", findDirectories) != RangedDirectoryIterator();
606}
607
608//==============================================================================
609 File File::getNonexistentChildFile (const String& suggestedPrefix,
610 const String& suffix,
611 bool putNumbersInBrackets) const
612{
613 auto f = getChildFile (suggestedPrefix + suffix);
614
615 if (f.exists())
616 {
617 int number = 1;
618 auto prefix = suggestedPrefix;
619
620 // remove any bracketed numbers that may already be on the end..
621 if (prefix.trim().endsWithChar (')'))
622 {
623 putNumbersInBrackets = true;
624
625 auto openBracks = prefix.lastIndexOfChar ('(');
626 auto closeBracks = prefix.lastIndexOfChar (')');
627
628 if (openBracks > 0
629 && closeBracks > openBracks
630 && prefix.substring (openBracks + 1, closeBracks).containsOnly ("0123456789"))
631 {
632 number = prefix.substring (openBracks + 1, closeBracks).getIntValue();
633 prefix = prefix.substring (0, openBracks);
634 }
635 }
636
637 do
638 {
639 auto newName = prefix;
640
641 if (putNumbersInBrackets)
642 {
643 newName << '(' << ++number << ')';
644 }
645 else
646 {
647 if (CharacterFunctions::isDigit (prefix.getLastCharacter()))
648 newName << '_'; // pad with an underscore if the name already ends in a digit
649
650 newName << ++number;
651 }
652
653 f = getChildFile (newName + suffix);
654
655 } while (f.exists());
656 }
657
658 return f;
659}
660
661 File File::getNonexistentSibling (const bool putNumbersInBrackets) const
662{
663 if (! exists())
664 return *this;
665
666 return getParentDirectory().getNonexistentChildFile (getFileNameWithoutExtension(),
667 getFileExtension(),
668 putNumbersInBrackets);
669}
670
671//==============================================================================
672 String File::getFileExtension() const
673{
674 auto indexOfDot = fullPath.lastIndexOfChar ('.');
675
676 if (indexOfDot > fullPath.lastIndexOfChar (getSeparatorChar()))
677 return fullPath.substring (indexOfDot);
678
679 return {};
680}
681
682 bool File::hasFileExtension (StringRef possibleSuffix) const
683{
684 if (possibleSuffix.isEmpty())
685 return fullPath.lastIndexOfChar ('.') <= fullPath.lastIndexOfChar (getSeparatorChar());
686
687 auto semicolon = possibleSuffix.text.indexOf ((juce_wchar) ';');
688
689 if (semicolon >= 0)
690 return hasFileExtension (String (possibleSuffix.text).substring (0, semicolon).trimEnd())
691 || hasFileExtension ((possibleSuffix.text + (semicolon + 1)).findEndOfWhitespace());
692
693 if (fullPath.endsWithIgnoreCase (possibleSuffix))
694 {
695 if (possibleSuffix.text[0] == '.')
696 return true;
697
698 auto dotPos = fullPath.length() - possibleSuffix.length() - 1;
699
700 if (dotPos >= 0)
701 return fullPath[dotPos] == '.';
702 }
703
704 return false;
705}
706
707 File File::withFileExtension (StringRef newExtension) const
708{
709 if (fullPath.isEmpty())
710 return {};
711
712 auto filePart = getFileName();
713
714 auto lastDot = filePart.lastIndexOfChar ('.');
715
716 if (lastDot >= 0)
717 filePart = filePart.substring (0, lastDot);
718
719 if (newExtension.isNotEmpty() && newExtension.text[0] != '.')
720 filePart << '.';
721
722 return getSiblingFile (filePart + newExtension);
723}
724
725//==============================================================================
726 bool File::startAsProcess (const String& parameters) const
727{
728 return exists() && Process::openDocument (fullPath, parameters);
729}
730
731//==============================================================================
732std::unique_ptr<FileInputStream> File::createInputStream() const
733{
734 auto fin = std::make_unique<FileInputStream> (*this);
735
736 if (fin->openedOk())
737 return fin;
738
739 return nullptr;
740}
741
742std::unique_ptr<FileOutputStream> File::createOutputStream (size_t bufferSize) const
743{
744 auto fout = std::make_unique<FileOutputStream> (*this, bufferSize);
745
746 if (fout->openedOk())
747 return fout;
748
749 return nullptr;
750}
751
752//==============================================================================
753 bool File::appendData (const void* const dataToAppend,
754 const size_t numberOfBytes) const
755{
756 jassert (((ssize_t) numberOfBytes) >= 0);
757
758 if (numberOfBytes == 0)
759 return true;
760
761 FileOutputStream fout (*this, 8192);
762 return fout.openedOk() && fout.write (dataToAppend, numberOfBytes);
763}
764
765 bool File::replaceWithData (const void* const dataToWrite,
766 const size_t numberOfBytes) const
767{
768 if (numberOfBytes == 0)
769 return deleteFile();
770
771 TemporaryFile tempFile (*this, TemporaryFile::useHiddenFile);
772 tempFile.getFile().appendData (dataToWrite, numberOfBytes);
773 return tempFile.overwriteTargetFileWithTemporary();
774}
775
776 bool File::appendText (const String& text, bool asUnicode, bool writeHeaderBytes, const char* lineFeed) const
777{
778 FileOutputStream fout (*this);
779
780 if (fout.failedToOpen())
781 return false;
782
783 return fout.writeText (text, asUnicode, writeHeaderBytes, lineFeed);
784}
785
786 bool File::replaceWithText (const String& textToWrite, bool asUnicode, bool writeHeaderBytes, const char* lineFeed) const
787{
788 TemporaryFile tempFile (*this, TemporaryFile::useHiddenFile);
789 tempFile.getFile().appendText (textToWrite, asUnicode, writeHeaderBytes, lineFeed);
790 return tempFile.overwriteTargetFileWithTemporary();
791}
792
793 bool File::hasIdenticalContentTo (const File& other) const
794{
795 if (other == *this)
796 return true;
797
798 if (getSize() == other.getSize() && existsAsFile() && other.existsAsFile())
799 {
800 FileInputStream in1 (*this), in2 (other);
801
802 if (in1.openedOk() && in2.openedOk())
803 {
804 const int bufferSize = 4096;
805 HeapBlock<char> buffer1 (bufferSize), buffer2 (bufferSize);
806
807 for (;;)
808 {
809 auto num1 = in1.read (buffer1, bufferSize);
810 auto num2 = in2.read (buffer2, bufferSize);
811
812 if (num1 != num2)
813 break;
814
815 if (num1 <= 0)
816 return true;
817
818 if (memcmp (buffer1, buffer2, (size_t) num1) != 0)
819 break;
820 }
821 }
822 }
823
824 return false;
825}
826
827//==============================================================================
828 String File::createLegalPathName (const String& original)
829{
830 auto s = original;
831 String start;
832
833 if (s.isNotEmpty() && s[1] == ':')
834 {
835 start = s.substring (0, 2);
836 s = s.substring (2);
837 }
838
839 return start + s.removeCharacters ("\"#@,;:<>*^|?")
840 .substring (0, 1024);
841}
842
843 String File::createLegalFileName (const String& original)
844{
845 auto s = original.removeCharacters ("\"#@,;:<>*^|?\\/");
846
847 const int maxLength = 128; // only the length of the filename, not the whole path
848 auto len = s.length();
849
850 if (len > maxLength)
851 {
852 auto lastDot = s.lastIndexOfChar ('.');
853
854 if (lastDot > jmax (0, len - 12))
855 {
856 s = s.substring (0, maxLength - (len - lastDot))
857 + s.substring (lastDot);
858 }
859 else
860 {
861 s = s.substring (0, maxLength);
862 }
863 }
864
865 return s;
866}
867
868//==============================================================================
869static int countNumberOfSeparators (String::CharPointerType s)
870{
871 int num = 0;
872
873 for (;;)
874 {
875 auto c = s.getAndAdvance();
876
877 if (c == 0)
878 break;
879
880 if (c == File::getSeparatorChar())
881 ++num;
882 }
883
884 return num;
885}
886
887 String File::getRelativePathFrom (const File& dir) const
888{
889 if (dir == *this)
890 return ".";
891
892 auto thisPath = fullPath;
893
894 while (thisPath.endsWithChar (getSeparatorChar()))
895 thisPath = thisPath.dropLastCharacters (1);
896
897 auto dirPath = addTrailingSeparator (dir.existsAsFile() ? dir.getParentDirectory().getFullPathName()
898 : dir.fullPath);
899
900 int commonBitLength = 0;
901 auto thisPathAfterCommon = thisPath.getCharPointer();
902 auto dirPathAfterCommon = dirPath.getCharPointer();
903
904 {
905 auto thisPathIter = thisPath.getCharPointer();
906 auto dirPathIter = dirPath.getCharPointer();
907
908 for (int i = 0;;)
909 {
910 auto c1 = thisPathIter.getAndAdvance();
911 auto c2 = dirPathIter.getAndAdvance();
912
913 #if NAMES_ARE_CASE_SENSITIVE
914 if (c1 != c2
915 #else
916 if ((c1 != c2 && CharacterFunctions::toLowerCase (c1) != CharacterFunctions::toLowerCase (c2))
917 #endif
918 || c1 == 0)
919 break;
920
921 ++i;
922
923 if (c1 == getSeparatorChar())
924 {
925 thisPathAfterCommon = thisPathIter;
926 dirPathAfterCommon = dirPathIter;
927 commonBitLength = i;
928 }
929 }
930 }
931
932 // if the only common bit is the root, then just return the full path..
933 if (commonBitLength == 0 || (commonBitLength == 1 && thisPath[1] == getSeparatorChar()))
934 return fullPath;
935
936 auto numUpDirectoriesNeeded = countNumberOfSeparators (dirPathAfterCommon);
937
938 if (numUpDirectoriesNeeded == 0)
939 return thisPathAfterCommon;
940
941 #if JUCE_WINDOWS
942 auto s = String::repeatedString ("..\\", numUpDirectoriesNeeded);
943 #else
944 auto s = String::repeatedString ("../", numUpDirectoriesNeeded);
945 #endif
946 s.appendCharPointer (thisPathAfterCommon);
947 return s;
948}
949
950//==============================================================================
951 File File::createTempFile (StringRef fileNameEnding)
952{
953 auto tempFile = getSpecialLocation (tempDirectory)
954 .getChildFile ("temp_" + String::toHexString (Random::getSystemRandom().nextInt()))
955 .withFileExtension (fileNameEnding);
956
957 if (tempFile.exists())
958 return createTempFile (fileNameEnding);
959
960 return tempFile;
961}
962
963 bool File::createSymbolicLink (const File& linkFileToCreate,
964 [[maybe_unused]] const String& nativePathOfTarget,
965 bool overwriteExisting)
966{
967 if (linkFileToCreate.exists())
968 {
969 if (! linkFileToCreate.isSymbolicLink())
970 {
971 // user has specified an existing file / directory as the link
972 // this is bad! the user could end up unintentionally destroying data
973 jassertfalse;
974 return false;
975 }
976
977 if (overwriteExisting)
978 linkFileToCreate.deleteFile();
979 }
980
981 #if JUCE_MAC || JUCE_LINUX || JUCE_BSD
982 // one common reason for getting an error here is that the file already exists
983 if (symlink (nativePathOfTarget.toRawUTF8(), linkFileToCreate.getFullPathName().toRawUTF8()) == -1)
984 {
985 jassertfalse;
986 return false;
987 }
988
989 return true;
990 #elif JUCE_MSVC
991 File targetFile (linkFileToCreate.getSiblingFile (nativePathOfTarget));
992
993 return CreateSymbolicLink (linkFileToCreate.getFullPathName().toWideCharPointer(),
994 nativePathOfTarget.toWideCharPointer(),
995 targetFile.isDirectory() ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0) != FALSE;
996 #else
997 jassertfalse; // symbolic links not supported on this platform!
998 return false;
999 #endif
1000}
1001
1002 bool File::createSymbolicLink (const File& linkFileToCreate, bool overwriteExisting) const
1003{
1004 return createSymbolicLink (linkFileToCreate, getFullPathName(), overwriteExisting);
1005}
1006
1007#if ! JUCE_WINDOWS
1008 File File::getLinkedTarget() const
1009{
1010 if (isSymbolicLink())
1011 return getSiblingFile (getNativeLinkedTarget());
1012
1013 return *this;
1014}
1015#endif
1016
1017//==============================================================================
1018#if JUCE_ALLOW_STATIC_NULL_VARIABLES
1019
1020JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-declarations")
1021JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4996)
1022
1023const File File::nonexistent{};
1024
1025JUCE_END_IGNORE_WARNINGS_GCC_LIKE
1026JUCE_END_IGNORE_WARNINGS_MSVC
1027
1028#endif
1029
1030//==============================================================================
1031MemoryMappedFile::MemoryMappedFile (const File& file, MemoryMappedFile::AccessMode mode, bool exclusive)
1032 : range (0, file.getSize())
1033{
1034 openInternal (file, mode, exclusive);
1035}
1036
1037 MemoryMappedFile::MemoryMappedFile (const File& file, const Range<int64>& fileRange, AccessMode mode, bool exclusive)
1038 : range (fileRange.getIntersectionWith (Range<int64> (0, file.getSize())))
1039{
1040 openInternal (file, mode, exclusive);
1041}
1042
1043
1044//==============================================================================
1045//==============================================================================
1046#if JUCE_UNIT_TESTS
1047
1048class FileTests final : public UnitTest
1049{
1050public:
1051 FileTests()
1052 : UnitTest ("Files", UnitTestCategories::files)
1053 {}
1054
1055 void runTest() override
1056 {
1057 beginTest ("Reading");
1058
1059 const File home (File::getSpecialLocation (File::userHomeDirectory));
1060 const File temp (File::getSpecialLocation (File::tempDirectory));
1061
1062 expect (! File().exists());
1063 expect (! File().existsAsFile());
1064 expect (! File().isDirectory());
1065 #if ! JUCE_WINDOWS
1066 expect (File ("/").isDirectory());
1067 #endif
1068 expect (home.isDirectory());
1069 expect (home.exists());
1070 expect (! home.existsAsFile());
1071 expect (File::getSpecialLocation (File::userApplicationDataDirectory).isDirectory());
1072 expect (File::getSpecialLocation (File::currentExecutableFile).exists());
1073 expect (File::getSpecialLocation (File::currentApplicationFile).exists());
1074 expect (File::getSpecialLocation (File::invokedExecutableFile).exists());
1075 expect (home.getVolumeTotalSize() > 1024 * 1024);
1076 expect (home.getBytesFreeOnVolume() > 0);
1077 expect (! home.isHidden());
1078 expect (home.isOnHardDisk());
1079 expect (! home.isOnCDRomDrive());
1080 expect (File::getCurrentWorkingDirectory().exists());
1081 expect (home.setAsCurrentWorkingDirectory());
1082
1083 {
1084 auto homeParent = home;
1085 bool noSymlinks = true;
1086
1087 while (! homeParent.isRoot())
1088 {
1089 if (homeParent.isSymbolicLink())
1090 {
1091 noSymlinks = false;
1092 break;
1093 }
1094
1095 homeParent = homeParent.getParentDirectory();
1096 }
1097
1098 if (noSymlinks)
1099 expect (File::getCurrentWorkingDirectory() == home);
1100 }
1101
1102 {
1103 Array<File> roots;
1104 File::findFileSystemRoots (roots);
1105 expect (roots.size() > 0);
1106
1107 int numRootsExisting = 0;
1108 for (int i = 0; i < roots.size(); ++i)
1109 if (roots[i].exists())
1110 ++numRootsExisting;
1111
1112 // (on windows, some of the drives may not contain media, so as long as at least one is ok..)
1113 expect (numRootsExisting > 0);
1114 }
1115
1116 beginTest ("Writing");
1117
1118 auto random = getRandom();
1119 const auto tempFolderName = "JUCE UnitTests Temp Folder "
1120 + String::toHexString (random.nextInt())
1121 + ".folder";
1122 File demoFolder (temp.getChildFile (tempFolderName));
1123 expect (demoFolder.deleteRecursively());
1124 expect (demoFolder.createDirectory());
1125 expect (demoFolder.isDirectory());
1126 expect (demoFolder.getParentDirectory() == temp);
1127 expect (temp.isDirectory());
1128 expect (temp.findChildFiles (File::findFilesAndDirectories, false, "*").contains (demoFolder));
1129 expect (temp.findChildFiles (File::findDirectories, true, "*.folder").contains (demoFolder));
1130
1131 File tempFile (demoFolder.getNonexistentChildFile ("test", ".txt", false));
1132
1133 expect (tempFile.getFileExtension() == ".txt");
1134 expect (tempFile.hasFileExtension (".txt"));
1135 expect (tempFile.hasFileExtension ("txt"));
1136 expect (tempFile.withFileExtension ("xyz").hasFileExtension (".xyz"));
1137 expect (tempFile.withFileExtension ("xyz").hasFileExtension ("abc;xyz;foo"));
1138 expect (tempFile.withFileExtension ("xyz").hasFileExtension ("xyz;foo"));
1139 expect (! tempFile.withFileExtension ("h").hasFileExtension ("bar;foo;xx"));
1140 expect (tempFile.getSiblingFile ("foo").isAChildOf (temp));
1141 expect (tempFile.hasWriteAccess());
1142
1143 expect (home.getChildFile (".") == home);
1144 expect (home.getChildFile ("..") == home.getParentDirectory());
1145 expect (home.getChildFile (".xyz").getFileName() == ".xyz");
1146 expect (home.getChildFile ("..xyz").getFileName() == "..xyz");
1147 expect (home.getChildFile ("...xyz").getFileName() == "...xyz");
1148 expect (home.getChildFile ("./xyz") == home.getChildFile ("xyz"));
1149 expect (home.getChildFile ("././xyz") == home.getChildFile ("xyz"));
1150 expect (home.getChildFile ("../xyz") == home.getParentDirectory().getChildFile ("xyz"));
1151 expect (home.getChildFile (".././xyz") == home.getParentDirectory().getChildFile ("xyz"));
1152 expect (home.getChildFile (".././xyz/./abc") == home.getParentDirectory().getChildFile ("xyz/abc"));
1153 expect (home.getChildFile ("./../xyz") == home.getParentDirectory().getChildFile ("xyz"));
1154 expect (home.getChildFile ("a1/a2/a3/./../../a4") == home.getChildFile ("a1/a4"));
1155
1156 expect (! File().hasReadAccess());
1157 expect (! File().hasWriteAccess());
1158
1159 expect (! tempFile.hasReadAccess());
1160
1161 {
1162 FileOutputStream fo (tempFile);
1163 fo.write ("0123456789", 10);
1164 }
1165
1166 expect (tempFile.hasReadAccess());
1167
1168 expect (tempFile.exists());
1169 expect (tempFile.getSize() == 10);
1170 expect (std::abs ((int) (tempFile.getLastModificationTime().toMilliseconds() - Time::getCurrentTime().toMilliseconds())) < 3000);
1171 expectEquals (tempFile.loadFileAsString(), String ("0123456789"));
1172 expect (! demoFolder.containsSubDirectories());
1173
1174 expectEquals (tempFile.getRelativePathFrom (demoFolder.getParentDirectory()), demoFolder.getFileName() + File::getSeparatorString() + tempFile.getFileName());
1175 expectEquals (demoFolder.getParentDirectory().getRelativePathFrom (tempFile), ".." + File::getSeparatorString() + ".." + File::getSeparatorString() + demoFolder.getParentDirectory().getFileName());
1176
1177 expect (demoFolder.getNumberOfChildFiles (File::findFiles) == 1);
1178 expect (demoFolder.getNumberOfChildFiles (File::findFilesAndDirectories) == 1);
1179 expect (demoFolder.getNumberOfChildFiles (File::findDirectories) == 0);
1180 demoFolder.getNonexistentChildFile ("tempFolder", "", false).createDirectory();
1181 expect (demoFolder.getNumberOfChildFiles (File::findDirectories) == 1);
1182 expect (demoFolder.getNumberOfChildFiles (File::findFilesAndDirectories) == 2);
1183 expect (demoFolder.containsSubDirectories());
1184
1185 expect (tempFile.hasWriteAccess());
1186 tempFile.setReadOnly (true);
1187 expect (! tempFile.hasWriteAccess());
1188 tempFile.setReadOnly (false);
1189 expect (tempFile.hasWriteAccess());
1190
1191 Time t (Time::getCurrentTime());
1192 tempFile.setLastModificationTime (t);
1193 Time t2 = tempFile.getLastModificationTime();
1194 expect (std::abs ((int) (t2.toMilliseconds() - t.toMilliseconds())) <= 1000);
1195
1196 {
1197 MemoryBlock mb;
1198 tempFile.loadFileAsData (mb);
1199 expect (mb.getSize() == 10);
1200 expect (mb[0] == '0');
1201 }
1202
1203 {
1204 expect (tempFile.getSize() == 10);
1205 FileOutputStream fo (tempFile);
1206 expect (fo.openedOk());
1207
1208 expect (fo.setPosition (7));
1209 expect (fo.truncate().wasOk());
1210 expect (tempFile.getSize() == 7);
1211 fo.write ("789", 3);
1212 fo.flush();
1213 expect (tempFile.getSize() == 10);
1214 }
1215
1216 beginTest ("Memory-mapped files");
1217
1218 {
1219 MemoryMappedFile mmf (tempFile, MemoryMappedFile::readOnly);
1220 expect (mmf.getSize() == 10);
1221 expect (mmf.getData() != nullptr);
1222 expect (memcmp (mmf.getData(), "0123456789", 10) == 0);
1223 }
1224
1225 {
1226 const File tempFile2 (tempFile.getNonexistentSibling (false));
1227 expect (tempFile2.create());
1228 expect (tempFile2.appendData ("xxxxxxxxxx", 10));
1229
1230 {
1231 MemoryMappedFile mmf (tempFile2, MemoryMappedFile::readWrite);
1232 expect (mmf.getSize() == 10);
1233 expect (mmf.getData() != nullptr);
1234 memcpy (mmf.getData(), "abcdefghij", 10);
1235 }
1236
1237 {
1238 MemoryMappedFile mmf (tempFile2, MemoryMappedFile::readWrite);
1239 expect (mmf.getSize() == 10);
1240 expect (mmf.getData() != nullptr);
1241 expect (memcmp (mmf.getData(), "abcdefghij", 10) == 0);
1242 }
1243
1244 expect (tempFile2.deleteFile());
1245 }
1246
1247 beginTest ("More writing");
1248
1249 expect (tempFile.appendData ("abcdefghij", 10));
1250 expect (tempFile.getSize() == 20);
1251 expect (tempFile.replaceWithData ("abcdefghij", 10));
1252 expect (tempFile.getSize() == 10);
1253
1254 File tempFile2 (tempFile.getNonexistentSibling (false));
1255 expect (tempFile.copyFileTo (tempFile2));
1256 expect (tempFile2.exists());
1257 expect (tempFile2.hasIdenticalContentTo (tempFile));
1258 expect (tempFile.deleteFile());
1259 expect (! tempFile.exists());
1260 expect (tempFile2.moveFileTo (tempFile));
1261 expect (tempFile.exists());
1262 expect (! tempFile2.exists());
1263
1264 expect (demoFolder.deleteRecursively());
1265 expect (! demoFolder.exists());
1266
1267 {
1268 URL url ("https://audio.dev/foo/bar/");
1269 expectEquals (url.toString (false), String ("https://audio.dev/foo/bar/"));
1270 expectEquals (url.getChildURL ("x").toString (false), String ("https://audio.dev/foo/bar/x"));
1271 expectEquals (url.getParentURL().toString (false), String ("https://audio.dev/foo"));
1272 expectEquals (url.getParentURL().getParentURL().toString (false), String ("https://audio.dev/"));
1273 expectEquals (url.getParentURL().getParentURL().getParentURL().toString (false), String ("https://audio.dev/"));
1274 expectEquals (url.getParentURL().getChildURL ("x").toString (false), String ("https://audio.dev/foo/x"));
1275 expectEquals (url.getParentURL().getParentURL().getParentURL().getChildURL ("x").toString (false), String ("https://audio.dev/x"));
1276 }
1277
1278 {
1279 URL url ("https://audio.dev/foo/bar");
1280 expectEquals (url.toString (false), String ("https://audio.dev/foo/bar"));
1281 expectEquals (url.getChildURL ("x").toString (false), String ("https://audio.dev/foo/bar/x"));
1282 expectEquals (url.getParentURL().toString (false), String ("https://audio.dev/foo"));
1283 expectEquals (url.getParentURL().getParentURL().toString (false), String ("https://audio.dev/"));
1284 expectEquals (url.getParentURL().getParentURL().getParentURL().toString (false), String ("https://audio.dev/"));
1285 expectEquals (url.getParentURL().getChildURL ("x").toString (false), String ("https://audio.dev/foo/x"));
1286 expectEquals (url.getParentURL().getParentURL().getParentURL().getChildURL ("x").toString (false), String ("https://audio.dev/x"));
1287 }
1288 }
1289};
1290
1291static FileTests fileUnitTests;
1292
1293#endif
1294
1295} // namespace juce
juce::Array
Definition juce_Array.h:56
juce::Array::add
void add(const ElementType &newElement)
Definition juce_Array.h:418
juce::CharacterFunctions::toLowerCase
static juce_wchar toLowerCase(juce_wchar character) noexcept
Definition juce_CharacterFunctions.cpp:33
juce::CharacterFunctions::isDigit
static bool isDigit(char character) noexcept
Definition juce_CharacterFunctions.cpp:69
juce::DirectoryEntry
Definition juce_RangedDirectoryIterator.h:36
juce::FileInputStream
Definition juce_FileInputStream.h:35
juce::FileInputStream::read
int read(void *, int) override
Definition juce_FileInputStream.cpp:43
juce::FileInputStream::openedOk
bool openedOk() const noexcept
Definition juce_FileInputStream.h:67
juce::FileOutputStream
Definition juce_FileOutputStream.h:35
juce::FileOutputStream::getStatus
const Result & getStatus() const noexcept
Definition juce_FileOutputStream.h:81
juce::FileOutputStream::write
bool write(const void *, size_t) override
Definition juce_FileOutputStream.cpp:76
juce::FileOutputStream::failedToOpen
bool failedToOpen() const noexcept
Definition juce_FileOutputStream.h:86
juce::FileOutputStream::openedOk
bool openedOk() const noexcept
Definition juce_FileOutputStream.h:91
juce::File
Definition juce_File.h:45
juce::File::createOutputStream
std::unique_ptr< FileOutputStream > createOutputStream(size_t bufferSize=0x8000) const
Definition juce_File.cpp:742
juce::File::replaceWithText
bool replaceWithText(const String &textToWrite, bool asUnicode=false, bool writeUnicodeHeaderBytes=false, const char *lineEndings="\r\n") const
Definition juce_File.cpp:786
juce::File::isSymbolicLink
bool isSymbolicLink() const
juce::File::getNumberOfChildFiles
int getNumberOfChildFiles(int whatToLookFor, const String &wildCardPattern="*") const
Definition juce_File.cpp:592
juce::File::moveFileTo
bool moveFileTo(const File &targetLocation) const
Definition juce_File.cpp:288
juce::File::operator==
bool operator==(const File &) const
Definition juce_File.cpp:254
juce::File::hashCode64
int64 hashCode64() const
Definition juce_File.cpp:405
juce::File::containsSubDirectories
bool containsSubDirectories() const
Definition juce_File.cpp:600
juce::File::isDirectory
bool isDirectory() const
juce::File::findChildFiles
Array< File > findChildFiles(int whatToLookFor, bool searchRecursively, const String &wildCardPattern="*", FollowSymlinks followSymlinks=FollowSymlinks::yes) const
Definition juce_File.cpp:572
juce::File::hasIdenticalContentTo
bool hasIdenticalContentTo(const File &other) const
Definition juce_File.cpp:793
juce::File::createLegalPathName
static String createLegalPathName(const String &pathNameToFix)
Definition juce_File.cpp:828
juce::File::addTrailingSeparator
static String addTrailingSeparator(const String &path)
Definition juce_File.cpp:225
juce::File::getFileExtension
String getFileExtension() const
Definition juce_File.cpp:672
juce::File::getLastModificationTime
Time getLastModificationTime() const
Definition juce_File.cpp:538
juce::File::existsAsFile
bool existsAsFile() const
juce::File::copyFileTo
bool copyFileTo(const File &targetLocation) const
Definition juce_File.cpp:305
juce::File::getSize
int64 getSize() const
juce::File::deleteRecursively
bool deleteRecursively(bool followSymlinks=false) const
Definition juce_File.cpp:277
juce::File::getSpecialLocation
static File JUCE_CALLTYPE getSpecialLocation(const SpecialLocationType type)
juce::File::getFullPathName
const String & getFullPathName() const noexcept
Definition juce_File.h:153
juce::File::getFileName
String getFileName() const
Definition juce_File.cpp:372
juce::File::replaceWithData
bool replaceWithData(const void *dataToWrite, size_t numberOfBytes) const
Definition juce_File.cpp:765
juce::File::setLastAccessTime
bool setLastAccessTime(Time newTime) const
Definition juce_File.cpp:543
juce::File::getChildFile
File getChildFile(StringRef relativeOrAbsolutePath) const
Definition juce_File.cpp:420
juce::File::readLines
void readLines(StringArray &destLines) const
Definition juce_File.cpp:566
juce::File::isAbsolutePath
static bool isAbsolutePath(StringRef path)
Definition juce_File.cpp:408
juce::File::getSiblingFile
File getSiblingFile(StringRef siblingFileName) const
Definition juce_File.cpp:477
juce::File::createSymbolicLink
bool createSymbolicLink(const File &linkFileToCreate, bool overwriteExisting) const
Definition juce_File.cpp:1002
juce::File::getFileNameWithoutExtension
String getFileNameWithoutExtension() const
Definition juce_File.cpp:377
juce::File::getNonexistentSibling
File getNonexistentSibling(bool putNumbersInBrackets=true) const
Definition juce_File.cpp:661
juce::File::tempDirectory
@ tempDirectory
Definition juce_File.h:919
juce::File::userHomeDirectory
@ userHomeDirectory
Definition juce_File.h:869
juce::File::getRelativePathFrom
String getRelativePathFrom(const File &directoryToBeRelativeTo) const
Definition juce_File.cpp:887
juce::File::appendText
bool appendText(const String &textToAppend, bool asUnicode=false, bool writeUnicodeHeaderBytes=false, const char *lineEndings="\r\n") const
Definition juce_File.cpp:776
juce::File::hashCode
int hashCode() const
Definition juce_File.cpp:404
juce::File::create
Result create() const
Definition juce_File.cpp:498
juce::File::findDirectories
@ findDirectories
Definition juce_File.h:565
juce::File::findFilesAndDirectories
@ findFilesAndDirectories
Definition juce_File.h:567
juce::File::findFiles
@ findFiles
Definition juce_File.h:566
juce::File::getNonexistentChildFile
File getNonexistentChildFile(const String &prefix, const String &suffix, bool putNumbersInBrackets=true) const
Definition juce_File.cpp:609
juce::File::operator!=
bool operator!=(const File &) const
Definition juce_File.cpp:255
juce::File::setCreationTime
bool setCreationTime(Time newTime) const
Definition juce_File.cpp:544
juce::File::descriptionOfSizeInBytes
static String descriptionOfSizeInBytes(int64 bytes)
Definition juce_File.cpp:483
juce::File::setReadOnly
bool setReadOnly(bool shouldBeReadOnly, bool applyRecursively=false) const
Definition juce_File.cpp:260
juce::File::createTempFile
static File createTempFile(StringRef fileNameEnding)
Definition juce_File.cpp:951
juce::File::getSeparatorChar
static juce_wchar getSeparatorChar()
juce::File::areFileNamesCaseSensitive
static bool areFileNamesCaseSensitive()
Definition juce_File.cpp:236
juce::File::FollowSymlinks
FollowSymlinks
Definition juce_File.h:572
juce::File::isRoot
bool isRoot() const
Definition juce_File.cpp:125
juce::File::loadFileAsString
String loadFileAsString() const
Definition juce_File.cpp:556
juce::File::operator>
bool operator>(const File &) const
Definition juce_File.cpp:257
juce::File::getLinkedTarget
File getLinkedTarget() const
Definition juce_File.cpp:1008
juce::File::getParentDirectory
File getParentDirectory() const
Definition juce_File.cpp:358
juce::File::appendData
bool appendData(const void *dataToAppend, size_t numberOfBytes) const
Definition juce_File.cpp:753
juce::File::createInputStream
std::unique_ptr< FileInputStream > createInputStream() const
Definition juce_File.cpp:732
juce::File::operator<
bool operator<(const File &) const
Definition juce_File.cpp:256
juce::File::getCreationTime
Time getCreationTime() const
Definition juce_File.cpp:540
juce::File::setExecutePermission
bool setExecutePermission(bool shouldBeExecutable) const
Definition juce_File.cpp:272
juce::File::withFileExtension
File withFileExtension(StringRef newExtension) const
Definition juce_File.cpp:707
juce::File::createLegalFileName
static String createLegalFileName(const String &fileNameToFix)
Definition juce_File.cpp:843
juce::File::File
File()=default
juce::File::deleteFile
bool deleteFile() const
juce::File::replaceFileIn
bool replaceFileIn(const File &targetLocation) const
Definition juce_File.cpp:311
juce::File::isAChildOf
bool isAChildOf(const File &potentialParentDirectory) const
Definition juce_File.cpp:388
juce::File::createFileWithoutCheckingPath
static File createFileWithoutCheckingPath(const String &absolutePath) noexcept
Definition juce_File.cpp:31
juce::File::startAsProcess
bool startAsProcess(const String &parameters=String()) const
Definition juce_File.cpp:726
juce::File::getNativeLinkedTarget
String getNativeLinkedTarget() const
juce::File::hasFileExtension
bool hasFileExtension(StringRef extensionToTest) const
Definition juce_File.cpp:682
juce::File::exists
bool exists() const
juce::File::copyDirectoryTo
bool copyDirectoryTo(const File &newDirectory) const
Definition juce_File.cpp:326
juce::File::loadFileAsData
bool loadFileAsData(MemoryBlock &result) const
Definition juce_File.cpp:547
juce::File::setLastModificationTime
bool setLastModificationTime(Time newTime) const
Definition juce_File.cpp:542
juce::File::getLastAccessTime
Time getLastAccessTime() const
Definition juce_File.cpp:539
juce::File::createDirectory
Result createDirectory() const
Definition juce_File.cpp:519
juce::File::getCurrentWorkingDirectory
static File getCurrentWorkingDirectory()
juce::File::getSeparatorString
static StringRef getSeparatorString()
juce::File::operator=
File & operator=(const String &newAbsolutePath)
Definition juce_File.cpp:43
juce::HeapBlock
Definition juce_HeapBlock.h:87
juce::InputStream::readIntoMemoryBlock
virtual size_t readIntoMemoryBlock(MemoryBlock &destBlock, ssize_t maxNumBytesToRead=-1)
Definition juce_InputStream.cpp:223
juce::InputStream::readEntireStreamAsString
virtual String readEntireStreamAsString()
Definition juce_InputStream.cpp:229
juce::Logger::writeToLog
static void JUCE_CALLTYPE writeToLog(const String &message)
Definition juce_Logger.cpp:40
juce::MemoryBlock
Definition juce_MemoryBlock.h:33
juce::MemoryMappedFile::MemoryMappedFile
MemoryMappedFile(const File &file, AccessMode mode, bool exclusive=false)
Definition juce_File.cpp:1031
juce::MemoryMappedFile::AccessMode
AccessMode
Definition juce_MemoryMappedFile.h:37
juce::OutputStream::writeText
virtual bool writeText(const String &text, bool asUTF16, bool writeUTF16ByteOrderMark, const char *lineEndings)
Definition juce_OutputStream.cpp:198
juce::Process::openDocument
static bool JUCE_CALLTYPE openDocument(const String &documentURL, const String &parameters)
juce::Random::getSystemRandom
static Random & getSystemRandom() noexcept
Definition juce_Random.cpp:67
juce::Range
Definition juce_Range.h:40
juce::RangedDirectoryIterator
Definition juce_RangedDirectoryIterator.h:100
juce::Result
Definition juce_Result.h:57
juce::Result::fail
static Result fail(const String &errorMessage) noexcept
Definition juce_Result.cpp:65
juce::Result::ok
static Result ok() noexcept
Definition juce_Result.h:61
juce::StringArray
Definition juce_StringArray.h:35
juce::StringArray::joinIntoString
String joinIntoString(StringRef separatorString, int startIndex=0, int numberOfElements=-1) const
Definition juce_StringArray.cpp:289
juce::StringArray::size
int size() const noexcept
Definition juce_StringArray.h:136
juce::StringArray::addLines
int addLines(StringRef stringToBreakUp)
Definition juce_StringArray.cpp:358
juce::StringArray::removeRange
void removeRange(int startIndex, int numberToRemove)
Definition juce_StringArray.cpp:244
juce::StringArray::remove
void remove(int index)
Definition juce_StringArray.cpp:223
juce::StringArray::addTokens
int addTokens(StringRef stringToTokenise, bool preserveQuotedStrings)
Definition juce_StringArray.cpp:329
juce::StringRef
Definition juce_StringRef.h:62
juce::StringRef::isNotEmpty
bool isNotEmpty() const noexcept
Definition juce_StringRef.h:103
juce::StringRef::length
int length() const noexcept
Definition juce_StringRef.h:105
juce::StringRef::text
String::CharPointerType text
Definition juce_StringRef.h:130
juce::StringRef::isEmpty
bool isEmpty() const noexcept
Definition juce_StringRef.h:101
juce::String
Definition juce_String.h:53
juce::String::repeatedString
static String repeatedString(StringRef stringToRepeat, int numberOfTimesToRepeat)
Definition juce_String.cpp:1147
juce::String::indexOfChar
int indexOfChar(juce_wchar characterToLookFor) const noexcept
Definition juce_String.cpp:874
juce::String::length
int length() const noexcept
Definition juce_String.cpp:511
juce::String::endsWithChar
bool endsWithChar(juce_wchar character) const noexcept
Definition juce_String.cpp:1410
juce::String::isEmpty
bool isEmpty() const noexcept
Definition juce_String.h:310
juce::String::toRawUTF8
const char * toRawUTF8() const
Definition juce_String.cpp:2074
juce::String::hashCode64
int64 hashCode64() const noexcept
Definition juce_String.cpp:550
juce::String::containsChar
bool containsChar(juce_wchar character) const noexcept
Definition juce_String.cpp:1040
juce::String::removeCharacters
String removeCharacters(StringRef charactersToRemove) const
Definition juce_String.cpp:1757
juce::String::endsWithIgnoreCase
bool endsWithIgnoreCase(StringRef text) const noexcept
Definition juce_String.cpp:1438
juce::String::dropLastCharacters
String dropLastCharacters(int numberToDrop) const
Definition juce_String.cpp:1555
juce::String::contains
bool contains(StringRef text) const noexcept
Definition juce_String.cpp:1035
juce::String::trimEnd
String trimEnd() const
Definition juce_String.cpp:1687
juce::String::toHexString
static String toHexString(IntegerType number)
Definition juce_String.h:1097
juce::String::lastIndexOfChar
int lastIndexOfChar(juce_wchar character) const noexcept
Definition juce_String.cpp:899
juce::String::toWideCharPointer
const wchar_t * toWideCharPointer() const
Definition juce_String.cpp:2079
juce::String::trimCharactersAtEnd
String trimCharactersAtEnd(StringRef charactersToTrim) const
Definition juce_String.cpp:1711
juce::String::replaceCharacter
String replaceCharacter(juce_wchar characterToReplace, juce_wchar characterToInsertInstead) const
Definition juce_String.cpp:1344
juce::String::substring
String substring(int startIndex, int endIndex) const
Definition juce_String.cpp:1498
juce::String::hashCode
int hashCode() const noexcept
Definition juce_String.cpp:549
juce::String::isNotEmpty
bool isNotEmpty() const noexcept
Definition juce_String.h:316
juce::String::fromFirstOccurrenceOf
String fromFirstOccurrenceOf(StringRef substringToStartFrom, bool includeSubStringInResult, bool ignoreCase) const
Definition juce_String.cpp:1565
juce::TemporaryFile
Definition juce_TemporaryFile.h:65
juce::TemporaryFile::useHiddenFile
@ useHiddenFile
Definition juce_TemporaryFile.h:70
juce::TemporaryFile::overwriteTargetFileWithTemporary
bool overwriteTargetFileWithTemporary() const
Definition juce_TemporaryFile.cpp:93
juce::TemporaryFile::getFile
const File & getFile() const noexcept
Definition juce_TemporaryFile.h:126
juce::Time
Definition juce_Time.h:37
juce::Time::toMilliseconds
int64 toMilliseconds() const noexcept
Definition juce_Time.h:98
juce::UnitTest
Definition juce_UnitTest.h:70