OpenShot Audio Library | OpenShotAudio: juce_File.cpp Source File

OpenShot Audio Library | OpenShotAudio 0.3.0

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