LMMS
Loading...
Searching...
No Matches
File.cpp
Go to the documentation of this file.
1/*
2 ==============================================================================
3
4 This file is part of the Water library.
5 Copyright (c) 2016 ROLI Ltd.
6 Copyright (C) 2017-2023 Filipe Coelho <falktx@falktx.com>
7
8 Permission is granted to use this software under the terms of the ISC license
9 http://www.isc.org/downloads/software-support-policy/isc-license/
10
11 Permission to use, copy, modify, and/or distribute this software for any
12 purpose with or without fee is hereby granted, provided that the above
13 copyright notice and this permission notice appear in all copies.
14
15 THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD
16 TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
18 OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
19 USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
21 OF THIS SOFTWARE.
22
23 ==============================================================================
24*/
25
26#include "File.h"
27#include "DirectoryIterator.h"
28#include "FileInputStream.h"
29#include "FileOutputStream.h"
30#include "TemporaryFile.h"
31#include "../maths/Random.h"
32#include "../misc/Time.h"
33#include "../text/StringArray.h"
34
35#ifdef CARLA_OS_WIN
36# include <shlobj.h>
37#else
38# include <dlfcn.h>
39# include <fcntl.h>
40# include <fnmatch.h>
41# include <pwd.h>
42# include <sys/stat.h>
43# ifdef CARLA_OS_MAC
44# include <mach-o/dyld.h>
45# import <Foundation/NSFileManager.h>
46# import <Foundation/NSPathUtilities.h>
47# import <Foundation/NSString.h>
48# else
49# include <dirent.h>
50# endif
51#endif
52
53namespace water {
54
56 : fullPath ()
57{
58}
59
60File::File (const String& fullPathName)
61 : fullPath (parseAbsolutePath (fullPathName))
62{
63}
64
66{
67 File f;
68 f.fullPath = path;
69 return f;
70}
71
72File::File (const File& other)
73 : fullPath (other.fullPath)
74{
75}
76
78{
79 fullPath = parseAbsolutePath (newPath);
80 return *this;
81}
82
84{
85 fullPath = other.fullPath;
86 return *this;
87}
88
89bool File::isNull() const
90{
91 return fullPath.isEmpty();
92}
93
94bool File::isNotNull() const
95{
96 return fullPath.isNotEmpty();
97}
98
99//==============================================================================
100static String removeEllipsis (const String& path)
101{
102 // This will quickly find both /../ and /./ at the expense of a minor
103 // false-positive performance hit when path elements end in a dot.
104 #ifdef CARLA_OS_WIN
105 if (path.contains (".\\"))
106 #else
107 if (path.contains ("./"))
108 #endif
109 {
110 StringArray toks;
112 bool anythingChanged = false;
113
114 for (int i = 1; i < toks.size(); ++i)
115 {
116 const String& t = toks[i];
117
118 if (t == ".." && toks[i - 1] != "..")
119 {
120 anythingChanged = true;
121 toks.removeRange (i - 1, 2);
122 i = jmax (0, i - 2);
123 }
124 else if (t == ".")
125 {
126 anythingChanged = true;
127 toks.remove (i--);
128 }
129 }
130
131 if (anythingChanged)
133 }
134
135 return path;
136}
137
139{
140 if (p.isEmpty())
141 return String();
142
143#ifdef CARLA_OS_WIN
144 // Windows..
145 String path (removeEllipsis (p.replaceCharacter ('/', '\\')));
146
147 if (path.startsWithChar (separator))
148 {
149 if (path[1] != separator)
150 {
151 // Check if path is valid under Wine
152 String testpath ("Z:" + path);
153
154 if (File(testpath).exists())
155 {
156 path = testpath;
157 }
158 else
159 {
160 /* When you supply a raw string to the File object constructor, it must be an absolute path.
161 If you're trying to parse a string that may be either a relative path or an absolute path,
162 you MUST provide a context against which the partial path can be evaluated - you can do
163 this by simply using File::getChildFile() instead of the File constructor. E.g. saying
164 "File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
165 path if that's what was supplied, or would evaluate a partial path relative to the CWD.
166 */
167 carla_safe_assert(testpath.toRawUTF8(), __FILE__, __LINE__);
168
170 }
171 }
172 }
173 else if (! path.containsChar (':'))
174 {
175 /* When you supply a raw string to the File object constructor, it must be an absolute path.
176 If you're trying to parse a string that may be either a relative path or an absolute path,
177 you MUST provide a context against which the partial path can be evaluated - you can do
178 this by simply using File::getChildFile() instead of the File constructor. E.g. saying
179 "File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
180 path if that's what was supplied, or would evaluate a partial path relative to the CWD.
181 */
182 carla_safe_assert(path.toRawUTF8(), __FILE__, __LINE__);
183
185 }
186#else
187 // Mac or Linux..
188
189 // Yes, I know it's legal for a unix pathname to contain a backslash, but this assertion is here
190 // to catch anyone who's trying to run code that was written on Windows with hard-coded path names.
191 // If that's why you've ended up here, use File::getChildFile() to build your paths instead.
192 wassert ((! p.containsChar ('\\')) || (p.indexOfChar ('/') >= 0 && p.indexOfChar ('/') < p.indexOfChar ('\\')));
193
194 String path (removeEllipsis (p));
195
196 if (path.startsWithChar ('~'))
197 {
198 if (path[1] == separator || path[1] == 0)
199 {
200 // expand a name of the form "~/abc"
202 + path.substring (1);
203 }
204 else
205 {
206 // expand a name of type "~dave/abc"
207 const String userName (path.substring (1).upToFirstOccurrenceOf ("/", false, false));
208
209 if (struct passwd* const pw = getpwnam (userName.toUTF8()))
210 path = addTrailingSeparator (pw->pw_dir) + path.fromFirstOccurrenceOf ("/", false, false);
211 }
212 }
213 else if (! path.startsWithChar (separator))
214 {
216 }
217#endif
218
219 while (path.endsWithChar (separator) && path != separatorString) // careful not to turn a single "/" into an empty string.
220 path = path.dropLastCharacters (1);
221
222 return path;
223}
224
226{
227 return path.endsWithChar (separator) ? path
228 : path + separator;
229}
230
231//==============================================================================
232#if ! (defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN))
233 #define NAMES_ARE_CASE_SENSITIVE 1
234#endif
235
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
254bool File::operator== (const File& other) const { return compareFilenames (fullPath, other.fullPath) == 0; }
255bool File::operator!= (const File& other) const { return compareFilenames (fullPath, other.fullPath) != 0; }
256bool File::operator< (const File& other) const { return compareFilenames (fullPath, other.fullPath) < 0; }
257bool File::operator> (const File& other) const { return compareFilenames (fullPath, other.fullPath) > 0; }
258
259//==============================================================================
261{
262 bool worked = true;
263
264 if (isDirectory())
265 {
266 std::vector<File> subFiles;
268
269 for (ssize_t i = subFiles.size(); --i >= 0;)
270 worked = subFiles[i].deleteRecursively() && worked;
271 }
272
273 return deleteFile() && worked;
274}
275
276bool File::moveFileTo (const File& newFile) const
277{
278 if (newFile.fullPath == fullPath)
279 return true;
280
281 if (! exists())
282 return false;
283
284 #if ! NAMES_ARE_CASE_SENSITIVE
285 if (*this != newFile)
286 #endif
287 if (! newFile.deleteFile())
288 return false;
289
290 return moveInternal (newFile);
291}
292
293bool File::copyFileTo (const File& newFile) const
294{
295 return (*this == newFile)
296 || (exists() && newFile.deleteFile() && copyInternal (newFile));
297}
298
299bool File::replaceFileIn (const File& newFile) const
300{
301 if (newFile.fullPath == fullPath)
302 return true;
303
304 if (! newFile.exists())
305 return moveFileTo (newFile);
306
307 if (! replaceInternal (newFile))
308 return false;
309
310 deleteFile();
311 return true;
312}
313
314bool File::copyDirectoryTo (const File& newDirectory) const
315{
316 if (isDirectory() && newDirectory.createDirectory())
317 {
318 std::vector<File> subFiles;
319 findChildFiles (subFiles, File::findFiles, false);
320
321 for (size_t i = 0; i < subFiles.size(); ++i)
322 {
323 const File& src (subFiles[i]);
324 const File& dst (newDirectory.getChildFile (src.getFileName()));
325
326 if (src.isSymbolicLink())
327 {
328 if (! src.getLinkedTarget().createSymbolicLink (dst, true))
329 return false;
330 }
331 else
332 {
333 if (! src.copyFileTo (dst))
334 return false;
335 }
336 }
337
338 subFiles.clear();
339 findChildFiles (subFiles, File::findDirectories, false);
340
341 for (size_t i = 0; i < subFiles.size(); ++i)
342 if (! subFiles[i].copyDirectoryTo (newDirectory.getChildFile (subFiles[i].getFileName())))
343 return false;
344
345 return true;
346 }
347
348 return false;
349}
350
351//==============================================================================
353{
354 const int lastSlash = fullPath.lastIndexOfChar (separator);
355
356 if (lastSlash > 0)
357 return fullPath.substring (0, lastSlash);
358
359 if (lastSlash == 0)
360 return separatorString;
361
362 return fullPath;
363}
364
366{
367 File f;
368 f.fullPath = getPathUpToLastSlash();
369 return f;
370}
371
372//==============================================================================
374{
375 return fullPath.substring (fullPath.lastIndexOfChar (separator) + 1);
376}
377
379{
380 const int lastSlash = fullPath.lastIndexOfChar (separator) + 1;
381 const int lastDot = fullPath.lastIndexOfChar ('.');
382
383 if (lastDot > lastSlash)
384 return fullPath.substring (lastSlash, lastDot);
385
386 return fullPath.substring (lastSlash);
387}
388
389bool File::isAChildOf (const File& potentialParent) const
390{
391 if (potentialParent.fullPath.isEmpty())
392 return false;
393
394 const String ourPath (getPathUpToLastSlash());
395
396 if (compareFilenames (potentialParent.fullPath, ourPath) == 0)
397 return true;
398
399 if (potentialParent.fullPath.length() >= ourPath.length())
400 return false;
401
402 return getParentDirectory().isAChildOf (potentialParent);
403}
404
405//==============================================================================
407{
408 const water_uchar firstChar = *(path.text);
409
410 return firstChar == separator
411 #ifdef CARLA_OS_WIN
412 || (firstChar != 0 && path.text[1] == ':');
413 #else
414 || firstChar == '~';
415 #endif
416}
417
419{
420 CharPointer_UTF8 r = relativePath.text;
421
422 if (isAbsolutePath (r))
423 return File (String (r));
424
425 #ifdef CARLA_OS_WIN
426 if (r.indexOf ((water_uchar) '/') >= 0)
427 return getChildFile (String (r).replaceCharacter ('/', '\\'));
428 #endif
429
430 String path (fullPath);
431
432 while (*r == '.')
433 {
434 CharPointer_UTF8 lastPos = r;
435 const water_uchar secondChar = *++r;
436
437 if (secondChar == '.') // remove "../"
438 {
439 const water_uchar thirdChar = *++r;
440
441 if (thirdChar == separator || thirdChar == 0)
442 {
443 const int lastSlash = path.lastIndexOfChar (separator);
444 if (lastSlash >= 0)
445 path = path.substring (0, lastSlash);
446
447 while (*r == separator) // ignore duplicate slashes
448 ++r;
449 }
450 else
451 {
452 r = lastPos;
453 break;
454 }
455 }
456 else if (secondChar == separator || secondChar == 0) // remove "./"
457 {
458 while (*r == separator) // ignore duplicate slashes
459 ++r;
460 }
461 else
462 {
463 r = lastPos;
464 break;
465 }
466 }
467
468 path = addTrailingSeparator (path);
469 path.appendCharPointer (r);
470 return File (path);
471}
472
474{
475 return getParentDirectory().getChildFile (fileName);
476}
477
478//==============================================================================
480{
481 const char* suffix;
482 double divisor = 0;
483
484 if (bytes == 1) { suffix = " byte"; }
485 else if (bytes < 1024) { suffix = " bytes"; }
486 else if (bytes < 1024 * 1024) { suffix = " KB"; divisor = 1024.0; }
487 else if (bytes < 1024 * 1024 * 1024) { suffix = " MB"; divisor = 1024.0 * 1024.0; }
488 else { suffix = " GB"; divisor = 1024.0 * 1024.0 * 1024.0; }
489
490 return (divisor > 0 ? String (bytes / divisor, 1) : String (bytes)) + suffix;
491}
492
493//==============================================================================
495{
496 if (exists())
497 return Result::ok();
498
499 const File parentDir (getParentDirectory());
500
501 if (parentDir == *this)
502 return Result::fail ("Cannot create parent directory");
503
504 Result r (parentDir.createDirectory());
505
506 if (r.wasOk())
507 {
508 FileOutputStream fo (*this, 8);
509 r = fo.getStatus();
510 }
511
512 return r;
513}
514
516{
517 if (isDirectory())
518 return Result::ok();
519
520 const File parentDir (getParentDirectory());
521
522 if (parentDir == *this)
523 return Result::fail ("Cannot create parent directory");
524
525 Result r (parentDir.createDirectory());
526
527 if (r.wasOk())
528 r = createDirectoryInternal (fullPath.trimCharactersAtEnd (separatorString));
529
530 return r;
531}
532
533//==============================================================================
535{
536 int64 m, _;
538 return m;
539}
540
542{
543 int64 a, _;
545 return a;
546}
547
549{
550 int64 c, _;
552 return c;
553}
554
555//==============================================================================
556bool File::loadFileAsData (MemoryBlock& destBlock) const
557{
558 if (! existsAsFile())
559 return false;
560
561 FileInputStream in (*this);
562 return in.openedOk() && getSize() == (int64) in.readIntoMemoryBlock (destBlock);
563}
564
566{
567 if (! existsAsFile())
568 return String();
569
570 FileInputStream in (*this);
571 return in.openedOk() ? in.readEntireStreamAsString()
572 : String();
573}
574
575void File::readLines (StringArray& destLines) const
576{
577 destLines.addLines (loadFileAsString());
578}
579
580//==============================================================================
581uint File::findChildFiles (std::vector<File>& results,
582 const int whatToLookFor,
583 const bool searchRecursively,
584 const String& wildCardPattern) const
585{
586 uint total = 0;
587
588 for (DirectoryIterator di (*this, searchRecursively, wildCardPattern, whatToLookFor); di.next();)
589 {
590 results.push_back (di.getFile());
591 ++total;
592 }
593
594 return total;
595}
596
597uint File::getNumberOfChildFiles (const int whatToLookFor, const String& wildCardPattern) const
598{
599 uint total = 0;
600
601 for (DirectoryIterator di (*this, false, wildCardPattern, whatToLookFor); di.next();)
602 ++total;
603
604 return total;
605}
606
608{
609 if (! isDirectory())
610 return false;
611
612 DirectoryIterator di (*this, false, "*", findDirectories);
613 return di.next();
614}
615
616//==============================================================================
618 const String& suffix,
619 bool putNumbersInBrackets) const
620{
621 File f (getChildFile (suggestedPrefix + suffix));
622
623 if (f.exists())
624 {
625 int number = 1;
626 String prefix (suggestedPrefix);
627
628 // remove any bracketed numbers that may already be on the end..
629 if (prefix.trim().endsWithChar (')'))
630 {
631 putNumbersInBrackets = true;
632
633 const int openBracks = prefix.lastIndexOfChar ('(');
634 const int closeBracks = prefix.lastIndexOfChar (')');
635
636 if (openBracks > 0
637 && closeBracks > openBracks
638 && prefix.substring (openBracks + 1, closeBracks).containsOnly ("0123456789"))
639 {
640 number = prefix.substring (openBracks + 1, closeBracks).getIntValue();
641 prefix = prefix.substring (0, openBracks);
642 }
643 }
644
645 do
646 {
647 String newName (prefix);
648
649 if (putNumbersInBrackets)
650 {
651 newName << '(' << ++number << ')';
652 }
653 else
654 {
656 newName << '_'; // pad with an underscore if the name already ends in a digit
657
658 newName << ++number;
659 }
660
661 f = getChildFile (newName + suffix);
662
663 } while (f.exists());
664 }
665
666 return f;
667}
668
669File File::getNonexistentSibling (const bool putNumbersInBrackets) const
670{
671 if (! exists())
672 return *this;
673
676 putNumbersInBrackets);
677}
678
679//==============================================================================
681{
682 const int indexOfDot = fullPath.lastIndexOfChar ('.');
683
684 if (indexOfDot > fullPath.lastIndexOfChar (separator))
685 return fullPath.substring (indexOfDot);
686
687 return String();
688}
689
690bool File::hasFileExtension (StringRef possibleSuffix) const
691{
692 if (possibleSuffix.isEmpty())
693 return fullPath.lastIndexOfChar ('.') <= fullPath.lastIndexOfChar (separator);
694
695 const int semicolon = possibleSuffix.text.indexOf ((water_uchar) ';');
696
697 if (semicolon >= 0)
698 return hasFileExtension (String (possibleSuffix.text).substring (0, semicolon).trimEnd())
699 || hasFileExtension ((possibleSuffix.text + (semicolon + 1)).findEndOfWhitespace());
700
701 if (fullPath.endsWithIgnoreCase (possibleSuffix))
702 {
703 if (possibleSuffix.text[0] == '.')
704 return true;
705
706 const int dotPos = fullPath.length() - possibleSuffix.length() - 1;
707
708 if (dotPos >= 0)
709 return fullPath [dotPos] == '.';
710 }
711
712 return false;
713}
714
716{
717 if (fullPath.isEmpty())
718 return File();
719
720 String filePart (getFileName());
721
722 const int i = filePart.lastIndexOfChar ('.');
723 if (i >= 0)
724 filePart = filePart.substring (0, i);
725
726 if (newExtension.isNotEmpty() && newExtension.text[0] != '.')
727 filePart << '.';
728
729 return getSiblingFile (filePart + newExtension);
730}
731
732//==============================================================================
734{
735 CarlaScopedPointer<FileInputStream> fin (new FileInputStream (*this));
736
737 if (fin->openedOk())
738 return fin.release();
739
740 return nullptr;
741}
742
743FileOutputStream* File::createOutputStream (const size_t bufferSize) const
744{
745 CarlaScopedPointer<FileOutputStream> out (new FileOutputStream (*this, bufferSize));
746
747 return out->failedToOpen() ? nullptr
748 : out.release();
749}
750
751//==============================================================================
752bool File::appendData (const void* const dataToAppend,
753 const size_t numberOfBytes) const
754{
755 wassert (((ssize_t) numberOfBytes) >= 0);
756
757 if (numberOfBytes == 0)
758 return true;
759
760 FileOutputStream out (*this, 8192);
761 return out.openedOk() && out.write (dataToAppend, numberOfBytes);
762}
763
764bool File::replaceWithData (const void* const dataToWrite,
765 const size_t numberOfBytes) const
766{
767 if (numberOfBytes == 0)
768 return deleteFile();
769
771 tempFile.getFile().appendData (dataToWrite, numberOfBytes);
772 return tempFile.overwriteTargetFileWithTemporary();
773}
774
776 const bool asUnicode,
777 const bool writeUnicodeHeaderBytes) const
778{
779 FileOutputStream out (*this);
780 CARLA_SAFE_ASSERT_RETURN (! out.failedToOpen(), false);
781
782 out.writeText (text, asUnicode, writeUnicodeHeaderBytes);
783 return true;
784}
785
786bool File::replaceWithText (const String& textToWrite,
787 const bool asUnicode,
788 const bool writeUnicodeHeaderBytes) const
789{
791 tempFile.getFile().appendText (textToWrite, asUnicode, writeUnicodeHeaderBytes);
792 return tempFile.overwriteTargetFileWithTemporary();
793}
794
795bool File::hasIdenticalContentTo (const File& other) const
796{
797 if (other == *this)
798 return true;
799
800 if (getSize() == other.getSize() && existsAsFile() && other.existsAsFile())
801 {
802 FileInputStream in1 (*this), in2 (other);
803
804 if (in1.openedOk() && in2.openedOk())
805 {
806 const int bufferSize = 4096;
807 HeapBlock<char> buffer1, buffer2;
808
809 CARLA_SAFE_ASSERT_RETURN(buffer1.malloc (bufferSize), false);
810 CARLA_SAFE_ASSERT_RETURN(buffer2.malloc (bufferSize), false);
811
812 for (;;)
813 {
814 const int num1 = in1.read (buffer1, bufferSize);
815 const int num2 = in2.read (buffer2, bufferSize);
816
817 if (num1 != num2)
818 break;
819
820 if (num1 <= 0)
821 return true;
822
823 if (memcmp (buffer1, buffer2, (size_t) num1) != 0)
824 break;
825 }
826 }
827 }
828
829 return false;
830}
831
832//==============================================================================
834{
835 String s (original);
837
838 if (s.isNotEmpty() && s[1] == ':')
839 {
840 start = s.substring (0, 2);
841 s = s.substring (2);
842 }
843
844 return start + s.removeCharacters ("\"#@,;:<>*^|?")
845 .substring (0, 1024);
846}
847
849{
850 String s (original.removeCharacters ("\"#@,;:<>*^|?\\/"));
851
852 const int maxLength = 128; // only the length of the filename, not the whole path
853 const int len = s.length();
854
855 if (len > maxLength)
856 {
857 const int lastDot = s.lastIndexOfChar ('.');
858
859 if (lastDot > jmax (0, len - 12))
860 {
861 s = s.substring (0, maxLength - (len - lastDot))
862 + s.substring (lastDot);
863 }
864 else
865 {
866 s = s.substring (0, maxLength);
867 }
868 }
869
870 return s;
871}
872
873//==============================================================================
875{
876 int num = 0;
877
878 for (;;)
879 {
880 const water_uchar c = s.getAndAdvance();
881
882 if (c == 0)
883 break;
884
885 if (c == File::separator)
886 ++num;
887 }
888
889 return num;
890}
891
893{
894 String thisPath (fullPath);
895
896 while (thisPath.endsWithChar (separator))
897 thisPath = thisPath.dropLastCharacters (1);
898
900 : dir.fullPath));
901
902 int commonBitLength = 0;
903 CharPointer_UTF8 thisPathAfterCommon (thisPath.getCharPointer());
904 CharPointer_UTF8 dirPathAfterCommon (dirPath.getCharPointer());
905
906 {
907 CharPointer_UTF8 thisPathIter (thisPath.getCharPointer());
908 CharPointer_UTF8 dirPathIter (dirPath.getCharPointer());
909
910 for (int i = 0;;)
911 {
912 const water_uchar c1 = thisPathIter.getAndAdvance();
913 const water_uchar c2 = dirPathIter.getAndAdvance();
914
915 #if NAMES_ARE_CASE_SENSITIVE
916 if (c1 != c2
917 #else
919 #endif
920 || c1 == 0)
921 break;
922
923 ++i;
924
925 if (c1 == separator)
926 {
927 thisPathAfterCommon = thisPathIter;
928 dirPathAfterCommon = dirPathIter;
929 commonBitLength = i;
930 }
931 }
932 }
933
934 // if the only common bit is the root, then just return the full path..
935 if (commonBitLength == 0 || (commonBitLength == 1 && thisPath[1] == separator))
936 return fullPath;
937
938 const int numUpDirectoriesNeeded = countNumberOfSeparators (dirPathAfterCommon);
939
940 if (numUpDirectoriesNeeded == 0)
941 return thisPathAfterCommon;
942
943 #ifdef CARLA_OS_WIN
944 String s (String::repeatedString ("..\\", numUpDirectoriesNeeded));
945 #else
946 String s (String::repeatedString ("../", numUpDirectoriesNeeded));
947 #endif
948 s.appendCharPointer (thisPathAfterCommon);
949 return s;
950}
951
952//==============================================================================
954{
955 const File tempFile (getSpecialLocation (tempDirectory)
957 .withFileExtension (fileNameEnding));
958
959 if (tempFile.exists())
960 return createTempFile (fileNameEnding);
961
962 return tempFile;
963}
964
965bool File::createSymbolicLink (const File& linkFileToCreate, bool overwriteExisting) const
966{
967 if (linkFileToCreate.exists())
968 {
969 // user has specified an existing file / directory as the link
970 // this is bad! the user could end up unintentionally destroying data
971 CARLA_SAFE_ASSERT_RETURN(linkFileToCreate.isSymbolicLink(), false);
972
973 if (overwriteExisting)
974 linkFileToCreate.deleteFile();
975 }
976
977 #ifdef CARLA_OS_WIN
978 carla_stderr("File::createSymbolicLink failed, unsupported");
979 return false;
980 #else
981 // one common reason for getting an error here is that the file already exists
982 return symlink(fullPath.toRawUTF8(), linkFileToCreate.getFullPathName().toRawUTF8()) != -1;
983 #endif
984}
985
986//=====================================================================================================================
987#ifdef CARLA_OS_WIN
988namespace WindowsFileHelpers
989{
990 DWORD getAtts (const String& path)
991 {
992 return GetFileAttributesW (path.toUTF16().c_str());
993 }
994
995 int64 fileTimeToTime (const FILETIME* const ft)
996 {
997#ifdef CARLA_PROPER_CPP11_SUPPORT
998 static_wassert (sizeof (ULARGE_INTEGER) == sizeof (FILETIME)); // tell me if this fails!
999#endif
1000
1001 return (int64) ((reinterpret_cast<const ULARGE_INTEGER*> (ft)->QuadPart - 116444736000000000LL) / 10000);
1002 }
1003
1004 File getSpecialFolderPath (int type)
1005 {
1006 WCHAR wpath [MAX_PATH + 256];
1007
1008 if (SHGetSpecialFolderPathW (nullptr, wpath, type, FALSE))
1009 {
1010 CHAR apath [MAX_PATH + 256];
1011
1012 if (WideCharToMultiByte (CP_UTF8, 0, wpath, -1, apath, numElementsInArray (apath), nullptr, nullptr))
1013 return File (String (apath));
1014 }
1015
1016 return File();
1017 }
1018
1019 File getModuleFileName (HINSTANCE moduleHandle)
1020 {
1021 WCHAR wdest [MAX_PATH + 256];
1022 CHAR adest [MAX_PATH + 256];
1023 wdest[0] = 0;
1024 GetModuleFileNameW (moduleHandle, wdest, (DWORD) numElementsInArray (wdest));
1025
1026 if (WideCharToMultiByte (CP_UTF8, 0, wdest, -1, adest, numElementsInArray (adest), nullptr, nullptr))
1027 return File (String (adest));
1028
1029 return File();
1030 }
1031}
1032
1033const water_uchar File::separator = '\\';
1034const String File::separatorString ("\\");
1035
1036bool File::isDirectory() const
1037{
1038 const DWORD attr = WindowsFileHelpers::getAtts (fullPath);
1039 return (attr & FILE_ATTRIBUTE_DIRECTORY) != 0 && attr != INVALID_FILE_ATTRIBUTES;
1040}
1041
1042bool File::exists() const
1043{
1044 return fullPath.isNotEmpty()
1045 && WindowsFileHelpers::getAtts (fullPath) != INVALID_FILE_ATTRIBUTES;
1046}
1047
1048bool File::existsAsFile() const
1049{
1050 return fullPath.isNotEmpty()
1051 && (WindowsFileHelpers::getAtts (fullPath) & FILE_ATTRIBUTE_DIRECTORY) == 0;
1052}
1053
1054bool File::hasWriteAccess() const
1055{
1056 if (fullPath.isEmpty())
1057 return true;
1058
1059 const DWORD attr = WindowsFileHelpers::getAtts (fullPath);
1060
1061 // NB: According to MS, the FILE_ATTRIBUTE_READONLY attribute doesn't work for
1062 // folders, and can be incorrectly set for some special folders, so we'll just say
1063 // that folders are always writable.
1064 return attr == INVALID_FILE_ATTRIBUTES
1065 || (attr & FILE_ATTRIBUTE_DIRECTORY) != 0
1066 || (attr & FILE_ATTRIBUTE_READONLY) == 0;
1067}
1068
1069int64 File::getSize() const
1070{
1071 WIN32_FILE_ATTRIBUTE_DATA attributes;
1072
1073 if (GetFileAttributesExW (fullPath.toUTF16().c_str(), GetFileExInfoStandard, &attributes))
1074 return (((int64) attributes.nFileSizeHigh) << 32) | attributes.nFileSizeLow;
1075
1076 return 0;
1077}
1078
1079void File::getFileTimesInternal (int64& modificationTime, int64& accessTime, int64& creationTime) const
1080{
1081 using namespace WindowsFileHelpers;
1082 WIN32_FILE_ATTRIBUTE_DATA attributes;
1083
1084 if (GetFileAttributesExW (fullPath.toUTF16().c_str(), GetFileExInfoStandard, &attributes))
1085 {
1086 modificationTime = fileTimeToTime (&attributes.ftLastWriteTime);
1087 creationTime = fileTimeToTime (&attributes.ftCreationTime);
1088 accessTime = fileTimeToTime (&attributes.ftLastAccessTime);
1089 }
1090 else
1091 {
1092 creationTime = accessTime = modificationTime = 0;
1093 }
1094}
1095
1096bool File::deleteFile() const
1097{
1098 if (! exists())
1099 return true;
1100
1101 return isDirectory() ? RemoveDirectoryW (fullPath.toUTF16().c_str()) != 0
1102 : DeleteFileW (fullPath.toUTF16().c_str()) != 0;
1103}
1104
1106{
1107 return *this;
1108}
1109
1110bool File::copyInternal (const File& dest) const
1111{
1112 return CopyFileW (fullPath.toUTF16().c_str(), dest.getFullPathName().toUTF16().c_str(), false) != 0;
1113}
1114
1115bool File::moveInternal (const File& dest) const
1116{
1117 return MoveFileW (fullPath.toUTF16().c_str(), dest.getFullPathName().toUTF16().c_str()) != 0;
1118}
1119
1120bool File::replaceInternal (const File& dest) const
1121{
1122 void* lpExclude = 0;
1123 void* lpReserved = 0;
1124
1125 return ReplaceFileW (dest.getFullPathName().toUTF16().c_str(),
1126 fullPath.toUTF16().c_str(),
1127 0, REPLACEFILE_IGNORE_MERGE_ERRORS, lpExclude, lpReserved) != 0;
1128}
1129
1130Result File::createDirectoryInternal (const String& fileName) const
1131{
1132 return CreateDirectoryW (fileName.toUTF16().c_str(), 0) ? Result::ok()
1133 : getResultForLastError();
1134}
1135
1137{
1138 WCHAR wdest [MAX_PATH + 256];
1139 CHAR adest [MAX_PATH + 256];
1140 wdest[0] = 0;
1141 GetCurrentDirectoryW ((DWORD) numElementsInArray (wdest), wdest);
1142
1143 if (WideCharToMultiByte (CP_UTF8, 0, wdest, -1, adest, numElementsInArray (adest), nullptr, nullptr))
1144 return File (String (adest));
1145
1146 return File();
1147}
1148
1150{
1151 return SetCurrentDirectoryW (getFullPathName().toUTF16().c_str()) != FALSE;
1152}
1153
1154bool File::isSymbolicLink() const
1155{
1156 return (GetFileAttributesW (fullPath.toUTF16().c_str()) & FILE_ATTRIBUTE_REPARSE_POINT) != 0;
1157}
1158
1159File File::getSpecialLocation (const SpecialLocationType type)
1160{
1161 int csidlType = 0;
1162
1163 switch (type)
1164 {
1165 case userHomeDirectory:
1166 csidlType = CSIDL_PROFILE;
1167 break;
1168
1169 case tempDirectory:
1170 {
1171 WCHAR wdest [MAX_PATH + 256];
1172 CHAR adest [MAX_PATH + 256];
1173 wdest[0] = 0;
1174 GetTempPathW ((DWORD) numElementsInArray (wdest), wdest);
1175
1176 if (WideCharToMultiByte (CP_UTF8, 0, wdest, -1, adest, numElementsInArray (adest), nullptr, nullptr))
1177 return File (String (adest));
1178
1179 return File();
1180 }
1181
1183 return WindowsFileHelpers::getModuleFileName (water::getCurrentModuleInstanceHandle());
1184
1186 return WindowsFileHelpers::getModuleFileName (nullptr);
1187
1188 case winAppData:
1189 csidlType = CSIDL_APPDATA;
1190 break;
1191
1192 case winProgramFiles:
1193 csidlType = CSIDL_PROGRAM_FILES;
1194 break;
1195
1197 csidlType = CSIDL_PROGRAM_FILES_COMMON;
1198 break;
1199
1200 case winMyDocuments:
1201 csidlType = CSIDL_MYDOCUMENTS;
1202 break;
1203
1204 default:
1205 wassertfalse; // unknown type?
1206 return File();
1207 }
1208
1209 return WindowsFileHelpers::getSpecialFolderPath (csidlType);
1210}
1211
1212//=====================================================================================================================
1214{
1215public:
1216 Pimpl (const File& directory, const String& wildCard)
1217 : directoryWithWildCard (directory.getFullPathName().isNotEmpty() ? File::addTrailingSeparator (directory.getFullPathName()) + wildCard : String()),
1218 handle (INVALID_HANDLE_VALUE)
1219 {
1220 }
1221
1222 ~Pimpl()
1223 {
1224 if (handle != INVALID_HANDLE_VALUE)
1225 FindClose (handle);
1226 }
1227
1228 bool next (String& filenameFound, bool* const isDir, int64* const fileSize, bool* const isReadOnly)
1229 {
1230 using namespace WindowsFileHelpers;
1231 WIN32_FIND_DATAW findData;
1232
1233 if (handle == INVALID_HANDLE_VALUE)
1234 {
1235 handle = FindFirstFileW (directoryWithWildCard.toUTF16().c_str(), &findData);
1236
1237 if (handle == INVALID_HANDLE_VALUE)
1238 return false;
1239 }
1240 else
1241 {
1242 if (FindNextFileW (handle, &findData) == 0)
1243 return false;
1244 }
1245
1246 CHAR apath [MAX_PATH + 256];
1247
1248 if (WideCharToMultiByte (CP_UTF8, 0, findData.cFileName, -1, apath, numElementsInArray (apath), nullptr, nullptr))
1249 filenameFound = apath;
1250
1251 if (isDir != nullptr) *isDir = ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0);
1252 if (isReadOnly != nullptr) *isReadOnly = ((findData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) != 0);
1253 if (fileSize != nullptr) *fileSize = findData.nFileSizeLow + (((int64) findData.nFileSizeHigh) << 32);
1254
1255 return true;
1256 }
1257
1258private:
1259 const String directoryWithWildCard;
1260 HANDLE handle;
1261
1263};
1264#else
1265//=====================================================================================================================
1266namespace
1267{
1268 #ifdef __GLIBC__
1269 typedef struct stat64 water_statStruct;
1270 #define WATER_STAT stat64
1271 #else
1272 typedef struct stat water_statStruct;
1273 #define WATER_STAT stat
1274 #endif
1275
1276 bool water_stat (const String& fileName, water_statStruct& info)
1277 {
1278 return fileName.isNotEmpty()
1279 && WATER_STAT (fileName.toUTF8(), &info) == 0;
1280 }
1281
1282 void updateStatInfoForFile (const String& path, bool* const isDir, int64* const fileSize, bool* const isReadOnly)
1283 {
1284 if (isDir != nullptr || fileSize != nullptr)
1285 {
1286 water_statStruct info;
1287 const bool statOk = water_stat (path, info);
1288
1289 if (isDir != nullptr) *isDir = statOk && ((info.st_mode & S_IFDIR) != 0);
1290 if (fileSize != nullptr) *fileSize = statOk ? (int64) info.st_size : 0;
1291 }
1292
1293 if (isReadOnly != nullptr)
1294 *isReadOnly = access (path.toUTF8(), W_OK) != 0;
1295 }
1296
1297 Result getResultForReturnValue (int value)
1298 {
1299 return value == -1 ? getResultForErrno() : Result::ok();
1300 }
1301}
1302
1303const water_uchar File::separator = '/';
1304const String File::separatorString ("/");
1305
1307{
1308 water_statStruct info;
1309
1310 return fullPath.isNotEmpty()
1311 && (water_stat (fullPath, info) && ((info.st_mode & S_IFDIR) != 0));
1312}
1313
1314bool File::exists() const
1315{
1316 return fullPath.isNotEmpty()
1317 && access (fullPath.toUTF8(), F_OK) == 0;
1318}
1319
1321{
1322 return exists() && ! isDirectory();
1323}
1324
1326{
1327 if (exists())
1328 return access (fullPath.toUTF8(), W_OK) == 0;
1329
1330 if ((! isDirectory()) && fullPath.containsChar (separator))
1332
1333 return false;
1334}
1335
1336void File::getFileTimesInternal (int64& modificationTime, int64& accessTime, int64& creationTime) const
1337{
1338 water_statStruct info;
1339
1340 if (water_stat (fullPath, info))
1341 {
1342 modificationTime = (int64) info.st_mtime * 1000;
1343 accessTime = (int64) info.st_atime * 1000;
1344 creationTime = (int64) info.st_ctime * 1000;
1345 }
1346 else
1347 {
1348 modificationTime = accessTime = creationTime = 0;
1349 }
1350}
1351
1353{
1354 water_statStruct info;
1355 return water_stat (fullPath, info) ? info.st_size : 0;
1356}
1357
1359{
1360 if (! exists() && ! isSymbolicLink())
1361 return true;
1362
1363 if (isDirectory())
1364 return rmdir (fullPath.toUTF8()) == 0;
1365
1366 return remove (fullPath.toUTF8()) == 0;
1367}
1368
1369bool File::moveInternal (const File& dest) const
1370{
1371 if (rename (fullPath.toUTF8(), dest.getFullPathName().toUTF8()) == 0)
1372 return true;
1373
1374 if (hasWriteAccess() && copyInternal (dest))
1375 {
1376 if (deleteFile())
1377 return true;
1378
1379 dest.deleteFile();
1380 }
1381
1382 return false;
1383}
1384
1385bool File::replaceInternal (const File& dest) const
1386{
1387 return moveInternal (dest);
1388}
1389
1391{
1392 return getResultForReturnValue (mkdir (fileName.toUTF8(), 0777));
1393}
1394
1396{
1397 HeapBlock<char> heapBuffer;
1398
1399 char localBuffer [1024];
1400 char* cwd = getcwd (localBuffer, sizeof (localBuffer) - 1);
1401
1402 size_t bufferSize = 4096;
1403 while (cwd == nullptr && errno == ERANGE)
1404 {
1405 CARLA_SAFE_ASSERT_RETURN(heapBuffer.malloc (bufferSize), File());
1406
1407 cwd = getcwd (heapBuffer, bufferSize - 1);
1408 bufferSize += 1024;
1409 }
1410
1411 return File (CharPointer_UTF8 (cwd));
1412}
1413
1415{
1416 return chdir (getFullPathName().toUTF8()) == 0;
1417}
1418
1421{
1422 struct DLAddrReader
1423 {
1424 static String getFilename()
1425 {
1426 Dl_info exeInfo;
1427 void* localSymbol = (void*) water_getExecutableFile;
1428 dladdr (localSymbol, &exeInfo);
1429 const CharPointer_UTF8 filename (exeInfo.dli_fname);
1430
1431 // if the filename is absolute simply return it
1433 return filename;
1434
1435 // if the filename is relative construct from CWD
1436 if (filename[0] == '.')
1438
1439 // filename is abstract, look up in PATH
1440 if (const char* const envpath = ::getenv ("PATH"))
1441 {
1442 StringArray paths (StringArray::fromTokens (envpath, ":", ""));
1443
1444 for (int i=paths.size(); --i>=0;)
1445 {
1446 const File filepath (File (paths[i]).getChildFile (filename));
1447
1448 if (filepath.existsAsFile())
1449 return filepath.getFullPathName();
1450 }
1451 }
1452
1453 // if we reach this, we failed to find ourselves...
1455 return filename;
1456 }
1457 };
1458
1459 static String filename (DLAddrReader::getFilename());
1460 return filename;
1461}
1462
1463#ifdef CARLA_OS_MAC
1464static NSString* getFileLink (const String& path)
1465{
1466 return [[NSFileManager defaultManager] destinationOfSymbolicLinkAtPath: waterStringToNS (path) error: nil];
1467}
1468
1469bool File::isSymbolicLink() const
1470{
1471 return getFileLink (fullPath) != nil;
1472}
1473
1475{
1476 if (NSString* dest = getFileLink (fullPath))
1477 return getSiblingFile (nsStringToWater (dest));
1478
1479 return *this;
1480}
1481
1482bool File::copyInternal (const File& dest) const
1483{
1484 const AutoNSAutoreleasePool arpool;
1485
1486 NSFileManager* fm = [NSFileManager defaultManager];
1487
1488 return [fm fileExistsAtPath: waterStringToNS (fullPath)]
1489 #if defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
1490 && [fm copyItemAtPath: waterStringToNS (fullPath)
1491 toPath: waterStringToNS (dest.getFullPathName())
1492 error: nil];
1493 #else
1494 && [fm copyPath: waterStringToNS (fullPath)
1495 toPath: waterStringToNS (dest.getFullPathName())
1496 handler: nil];
1497 #endif
1498}
1499
1500File File::getSpecialLocation (const SpecialLocationType type)
1501{
1502 const AutoNSAutoreleasePool arpool;
1503
1504 String resultPath;
1505
1506 switch (type)
1507 {
1508 case userHomeDirectory:
1509 resultPath = nsStringToWater (NSHomeDirectory());
1510 break;
1511
1512 case tempDirectory:
1513 {
1514 File tmp ("~/Library/Caches/" + water_getExecutableFile().getFileNameWithoutExtension());
1515 tmp.createDirectory();
1516 return File (tmp.getFullPathName());
1517 }
1518
1520 return water_getExecutableFile();
1521
1523 {
1524 unsigned int size = 8192;
1525 HeapBlock<char> buffer;
1526 buffer.calloc (size + 8);
1527
1528 _NSGetExecutablePath (buffer.getData(), &size);
1529 return File (String::fromUTF8 (buffer, (int) size));
1530 }
1531
1532 default:
1533 wassertfalse; // unknown type?
1534 break;
1535 }
1536
1537 if (resultPath.isNotEmpty())
1538 return File (resultPath.convertToPrecomposedUnicode());
1539
1540 return File();
1541}
1542//==============================================================================
1544{
1545public:
1546 Pimpl (const File& directory, const String& wildCard_)
1547 : parentDir (File::addTrailingSeparator (directory.getFullPathName())),
1548 wildCard (wildCard_),
1549 enumerator (nil)
1550 {
1551 const AutoNSAutoreleasePool arpool;
1552
1553 enumerator = [[[NSFileManager defaultManager] enumeratorAtPath: waterStringToNS (directory.getFullPathName())] retain];
1554 }
1555
1556 ~Pimpl()
1557 {
1558 [enumerator release];
1559 }
1560
1561 bool next (String& filenameFound, bool* const isDir, int64* const fileSize,bool* const isReadOnly)
1562 {
1563 const AutoNSAutoreleasePool arpool;
1564
1565 const char* wildcardUTF8 = nullptr;
1566
1567 for (;;)
1568 {
1569 NSString* file;
1570 if (enumerator == nil || (file = [enumerator nextObject]) == nil)
1571 return false;
1572
1573 [enumerator skipDescendents];
1574 filenameFound = nsStringToWater (file).convertToPrecomposedUnicode();
1575
1576 if (wildcardUTF8 == nullptr)
1577 wildcardUTF8 = wildCard.toUTF8();
1578
1579 if (fnmatch (wildcardUTF8, filenameFound.toUTF8(), FNM_CASEFOLD) != 0)
1580 continue;
1581
1582 const String fullPath (parentDir + filenameFound);
1583 updateStatInfoForFile (fullPath, isDir, fileSize, isReadOnly);
1584
1585 return true;
1586 }
1587 }
1588
1589private:
1590 String parentDir, wildCard;
1591 NSDirectoryEnumerator* enumerator;
1592
1594};
1595#else
1597{
1598 HeapBlock<char> buffer;
1599 CARLA_SAFE_ASSERT_RETURN(buffer.malloc(8194), String());
1600
1601 const int numBytes = (int) readlink (file.toRawUTF8(), buffer, 8192);
1602 return String::fromUTF8 (buffer, jmax (0, numBytes));
1603}
1604
1606{
1608}
1609
1611{
1613
1614 if (f.isNotEmpty())
1615 return getSiblingFile (f);
1616
1617 return *this;
1618}
1619
1620bool File::copyInternal (const File& dest) const
1621{
1622 FileInputStream in (*this);
1623
1624 if (dest.deleteFile())
1625 {
1626 {
1627 FileOutputStream out (dest);
1628
1629 if (out.failedToOpen())
1630 return false;
1631
1632 if (out.writeFromInputStream (in, -1) == getSize())
1633 return true;
1634 }
1635
1636 dest.deleteFile();
1637 }
1638
1639 return false;
1640}
1641
1643{
1644 switch (type)
1645 {
1646 case userHomeDirectory:
1647 {
1648 if (const char* homeDir = getenv ("HOME"))
1649 return File (CharPointer_UTF8 (homeDir));
1650
1651 if (struct passwd* const pw = getpwuid (getuid()))
1652 return File (CharPointer_UTF8 (pw->pw_dir));
1653
1654 return File();
1655 }
1656
1657 case tempDirectory:
1658 {
1659 File tmp ("/var/tmp");
1660
1661 if (! tmp.isDirectory())
1662 {
1663 tmp = "/tmp";
1664
1665 if (! tmp.isDirectory())
1667 }
1668
1669 return tmp;
1670 }
1671
1673 return water_getExecutableFile();
1674
1676 {
1677 const File f ("/proc/self/exe");
1678 return f.isSymbolicLink() ? f.getLinkedTarget() : water_getExecutableFile();
1679 }
1680
1681 default:
1682 wassertfalse; // unknown type?
1683 break;
1684 }
1685
1686 return File();
1687}
1688//==============================================================================
1690{
1691public:
1692 Pimpl (const File& directory, const String& wc)
1693 : parentDir (File::addTrailingSeparator (directory.getFullPathName())),
1694 wildCard (wc), dir (opendir (directory.getFullPathName().toUTF8()))
1695 {
1696 }
1697
1699 {
1700 if (dir != nullptr)
1701 closedir (dir);
1702 }
1703
1704 bool next (String& filenameFound, bool* const isDir, int64* const fileSize,bool* const isReadOnly)
1705 {
1706 if (dir != nullptr)
1707 {
1708 const char* wildcardUTF8 = nullptr;
1709
1710 for (;;)
1711 {
1712 struct dirent* const de = readdir (dir);
1713
1714 if (de == nullptr)
1715 break;
1716
1717 if (wildcardUTF8 == nullptr)
1718 wildcardUTF8 = wildCard.toUTF8();
1719
1720 if (fnmatch (wildcardUTF8, de->d_name, FNM_CASEFOLD) == 0)
1721 {
1722 filenameFound = CharPointer_UTF8 (de->d_name);
1723
1724 updateStatInfoForFile (parentDir + filenameFound, isDir, fileSize, isReadOnly);
1725
1726 return true;
1727 }
1728 }
1729 }
1730
1731 return false;
1732 }
1733
1734private:
1736 DIR* dir;
1737
1739};
1740#endif
1741#endif
1742
1744 : pimpl (new DirectoryIterator::NativeIterator::Pimpl (directory, wildCardStr))
1745{
1746}
1747
1749
1750bool DirectoryIterator::NativeIterator::next (String& filenameFound, bool* isDir, int64* fileSize,bool* isReadOnly)
1751{
1752 return pimpl->next (filenameFound, isDir, fileSize, isReadOnly);
1753}
1754
1755}
#define CARLA_SAFE_ASSERT_RETURN(cond, ret)
Definition CarlaDefines.h:190
unsigned int uint
Definition CarlaDefines.h:327
#define CARLA_DECLARE_NON_COPYABLE(ClassName)
Definition CarlaDefines.h:242
#define noexcept
Definition DistrhoDefines.h:72
#define nullptr
Definition DistrhoDefines.h:75
#define WATER_STAT
Definition File.cpp:1273
uint8_t a
Definition Spc_Cpu.h:141
CAdPlugDatabase::CRecord::RecordType type
Definition adplugdb.cpp:93
int64_t int64
Definition basics.h:91
static File getCurrentWorkingDirectory()
Definition File.cpp:1395
const String & getFullPathName() const noexcept
Definition File.h:152
Definition String.h:48
CharPointer_UTF8 toUTF8() const
Definition String.cpp:1906
bool isNotEmpty() const noexcept
Definition String.h:244
Definition CharPointer_UTF8.h:45
int indexOf(const CharPointer stringToFind) const noexcept
Definition CharPointer_UTF8.h:441
water_uchar getAndAdvance() noexcept
Definition CharPointer_UTF8.h:157
static bool isDigit(char character) noexcept
Definition CharacterFunctions.cpp:73
static water_uchar toLowerCase(water_uchar character) noexcept
Definition CharacterFunctions.cpp:39
Pimpl(const File &directory, const String &wc)
Definition File.cpp:1692
bool next(String &filenameFound, bool *const isDir, int64 *const fileSize, bool *const isReadOnly)
Definition File.cpp:1704
String wildCard
Definition File.cpp:1735
String parentDir
Definition File.cpp:1735
~NativeIterator()
Definition File.cpp:1748
bool next(String &filenameFound, bool *isDirectory, int64 *fileSize, bool *isReadOnly)
Definition File.cpp:1750
CarlaScopedPointer< Pimpl > pimpl
Definition DirectoryIterator.h:134
NativeIterator(const File &directory, const String &wildCard)
Definition File.cpp:1743
friend class DirectoryIterator
Definition DirectoryIterator.h:133
Definition DirectoryIterator.h:50
bool next()
Definition DirectoryIterator.cpp:70
Definition File.h:50
bool copyInternal(const File &) const
Definition File.cpp:1620
static const water_uchar separator
Definition File.h:691
bool hasFileExtension(StringRef extensionToTest) const
Definition File.cpp:690
bool hasIdenticalContentTo(const File &other) const
Definition File.cpp:795
bool existsAsFile() const
Definition File.cpp:1320
bool copyDirectoryTo(const File &newDirectory) const
Definition File.cpp:314
int64 getLastAccessTime() const
Definition File.cpp:541
File & operator=(const String &newAbsolutePath)
Definition File.cpp:77
File withFileExtension(StringRef newExtension) const
Definition File.cpp:715
static File createFileWithoutCheckingPath(const String &absolutePath) noexcept
Definition File.cpp:65
static File getCurrentWorkingDirectory()
Definition File.cpp:1395
static File createTempFile(StringRef fileNameEnding)
Definition File.cpp:953
bool deleteFile() const
Definition File.cpp:1358
int64 getCreationTime() const
Definition File.cpp:548
bool moveFileTo(const File &targetLocation) const
Definition File.cpp:276
uint getNumberOfChildFiles(int whatToLookFor, const String &wildCardPattern="*") const
Definition File.cpp:597
String fullPath
Definition File.h:767
String getFileExtension() const
Definition File.cpp:680
String getRelativePathFrom(const File &directoryToBeRelativeTo) const
Definition File.cpp:892
int64 getLastModificationTime() const
Definition File.cpp:534
String getPathUpToLastSlash() const
Definition File.cpp:352
File() noexcept
Definition File.cpp:55
bool operator<(const File &) const
Definition File.cpp:256
bool replaceWithData(const void *dataToWrite, size_t numberOfBytes) const
Definition File.cpp:764
static String parseAbsolutePath(const String &)
Definition File.cpp:138
static bool isAbsolutePath(StringRef path)
Definition File.cpp:406
@ findDirectories
Definition File.h:461
@ findFiles
Definition File.h:462
@ findFilesAndDirectories
Definition File.h:463
static String createLegalFileName(const String &fileNameToFix)
Definition File.cpp:848
static const String separatorString
Definition File.h:696
void getFileTimesInternal(int64 &m, int64 &a, int64 &c) const
Definition File.cpp:1336
FileInputStream * createInputStream() const
Definition File.cpp:733
File getNonexistentSibling(bool putNumbersInBrackets=true) const
Definition File.cpp:669
bool deleteRecursively() const
Definition File.cpp:260
bool isAChildOf(const File &potentialParentDirectory) const
Definition File.cpp:389
bool moveInternal(const File &) const
Definition File.cpp:1369
bool appendText(const String &textToAppend, bool asUnicode=false, bool writeUnicodeHeaderBytes=false) const
Definition File.cpp:775
SpecialLocationType
Definition File.h:633
@ winProgramFiles
Definition File.h:655
@ currentExecutableFile
Definition File.h:649
@ userHomeDirectory
Definition File.h:635
@ tempDirectory
Definition File.h:640
@ hostApplicationPath
Definition File.h:652
@ winMyDocuments
Definition File.h:655
@ winAppData
Definition File.h:655
@ winCommonProgramFiles
Definition File.h:655
static String addTrailingSeparator(const String &path)
Definition File.cpp:225
void readLines(StringArray &destLines) const
Definition File.cpp:575
Result create() const
Definition File.cpp:494
bool loadFileAsData(MemoryBlock &result) const
Definition File.cpp:556
Result createDirectory() const
Definition File.cpp:515
File getChildFile(StringRef relativeOrAbsolutePath) const
Definition File.cpp:418
bool setAsCurrentWorkingDirectory() const
Definition File.cpp:1414
bool replaceWithText(const String &textToWrite, bool asUnicode=false, bool writeUnicodeHeaderBytes=false) const
Definition File.cpp:786
String getFileNameWithoutExtension() const
Definition File.cpp:378
bool containsSubDirectories() const
Definition File.cpp:607
bool isNotNull() const
Definition File.cpp:94
bool replaceFileIn(const File &targetLocation) const
Definition File.cpp:299
bool isNull() const
Definition File.cpp:89
bool createSymbolicLink(const File &linkFileToCreate, bool overwriteExisting) const
Definition File.cpp:965
bool exists() const
Definition File.cpp:1314
File getLinkedTarget() const
Definition File.cpp:1610
static bool areFileNamesCaseSensitive()
Definition File.cpp:236
bool isDirectory() const
Definition File.cpp:1306
const String & getFullPathName() const noexcept
Definition File.h:152
int64 getSize() const
Definition File.cpp:1352
bool operator>(const File &) const
Definition File.cpp:257
bool operator==(const File &) const
Definition File.cpp:254
FileOutputStream * createOutputStream(size_t bufferSize=0x8000) const
Definition File.cpp:743
String getFileName() const
Definition File.cpp:373
bool operator!=(const File &) const
Definition File.cpp:255
bool copyFileTo(const File &targetLocation) const
Definition File.cpp:293
static String descriptionOfSizeInBytes(int64 bytes)
Definition File.cpp:479
File getSiblingFile(StringRef siblingFileName) const
Definition File.cpp:473
bool replaceInternal(const File &) const
Definition File.cpp:1385
String loadFileAsString() const
Definition File.cpp:565
static String createLegalPathName(const String &pathNameToFix)
Definition File.cpp:833
Result createDirectoryInternal(const String &) const
Definition File.cpp:1390
File getParentDirectory() const
Definition File.cpp:365
bool appendData(const void *dataToAppend, size_t numberOfBytes) const
Definition File.cpp:752
static File getSpecialLocation(const SpecialLocationType type)
Definition File.cpp:1642
File getNonexistentChildFile(const String &prefix, const String &suffix, bool putNumbersInBrackets=true) const
Definition File.cpp:617
bool isSymbolicLink() const
Definition File.cpp:1605
uint findChildFiles(std::vector< File > &results, int whatToLookFor, bool searchRecursively, const String &wildCardPattern="*") const
Definition File.cpp:581
bool hasWriteAccess() const
Definition File.cpp:1325
Definition FileInputStream.h:41
bool openedOk() const noexcept
Definition FileInputStream.h:73
int read(void *, int) override
Definition FileInputStream.cpp:50
Definition FileOutputStream.h:42
const Result & getStatus() const noexcept
Definition FileOutputStream.h:77
Definition HeapBlock.h:77
bool malloc(const size_t newNumElements, const size_t elementSize=sizeof(ElementType)) noexcept
Definition HeapBlock.h:171
Definition MemoryBlock.h:39
static Random & getSystemRandom() noexcept
Definition Random.cpp:66
Definition Result.h:64
static Result ok() noexcept
Definition Result.h:68
static Result fail(const std::string &errorMessage) noexcept
Definition Result.cpp:58
Definition StringArray.h:41
int size() const noexcept
Definition StringArray.h:97
static StringArray fromTokens(StringRef stringToTokenise, bool preserveQuotedStrings)
Definition StringArray.cpp:369
String joinIntoString(StringRef separatorString, int startIndex=0, int numberOfElements=-1) const
Definition StringArray.cpp:270
int addTokens(StringRef stringToTokenise, bool preserveQuotedStrings)
Definition StringArray.cpp:311
int addLines(StringRef stringToBreakUp)
Definition StringArray.cpp:340
void remove(int index)
Definition StringArray.cpp:181
void removeRange(int startIndex, int numberToRemove)
Definition StringArray.cpp:202
Definition String.h:48
String fromFirstOccurrenceOf(StringRef substringToStartFrom, bool includeSubStringInResult, bool ignoreCase) const
Definition String.cpp:1439
bool startsWithChar(water_uchar character) const noexcept
Definition String.cpp:1276
String trimEnd() const
Definition String.cpp:1572
bool containsChar(water_uchar character) const noexcept
Definition String.cpp:921
static String toHexString(int number)
Definition String.cpp:1830
String upToFirstOccurrenceOf(StringRef substringToEndWith, bool includeSubStringInResult, bool ignoreCase) const
Definition String.cpp:1463
CharPointer_UTF8 toUTF8() const
Definition String.cpp:1906
bool isNotEmpty() const noexcept
Definition String.h:244
int length() const noexcept
Definition String.cpp:451
String substring(int startIndex, int endIndex) const
Definition String.cpp:1373
bool endsWithChar(water_uchar character) const noexcept
Definition String.cpp:1284
String trim() const
Definition String.cpp:1540
static String repeatedString(StringRef stringToRepeat, int numberOfTimesToRepeat)
Definition String.cpp:1028
void appendCharPointer(const CharPointer_UTF8 startOfTextToAppend, const CharPointer_UTF8 endOfTextToAppend)
Definition String.cpp:639
String dropLastCharacters(int numberToDrop) const
Definition String.cpp:1429
const char * toRawUTF8() const
Definition String.cpp:1925
int getIntValue() const noexcept
Definition String.cpp:1781
int lastIndexOfChar(water_uchar character) const noexcept
Definition String.cpp:776
water_uchar getLastCharacter() const noexcept
Definition String.cpp:1368
bool containsOnly(StringRef charactersItMightContain) const noexcept
Definition String.cpp:1681
static String fromUTF8(const char *utf8buffer, int bufferSizeBytes=-1)
Definition String.cpp:1961
bool isEmpty() const noexcept
Definition String.h:238
bool contains(StringRef text) const noexcept
Definition String.cpp:916
String removeCharacters(StringRef charactersToRemove) const
Definition String.cpp:1642
CharPointer_UTF8 getCharPointer() const noexcept
Definition String.h:982
Definition StringRef.h:67
bool isEmpty() const noexcept
Definition StringRef.h:99
int length() const noexcept
Definition StringRef.h:103
CharPointer_UTF8 text
Definition StringRef.h:120
bool isNotEmpty() const noexcept
Definition StringRef.h:101
Definition TemporaryFile.h:73
const File & getFile() const noexcept
Definition TemporaryFile.h:134
@ useHiddenFile
Definition TemporaryFile.h:78
bool overwriteTargetFileWithTemporary() const
Definition TemporaryFile.cpp:82
unsigned * m
Definition inflate.c:1559
struct huft * t
Definition inflate.c:943
register unsigned i
Definition inflate.c:1575
unsigned s
Definition inflate.c:1555
unsigned f
Definition inflate.c:1572
static char filename[]
Definition features.c:5
static void c2(register WDL_FFT_COMPLEX *a)
Definition fft.c:270
#define _(msgid)
Definition getopt.c:86
static PuglViewHint int value
Definition pugl.h:1708
virtual ASIOError start()=0
struct backing_store_struct * info
Definition jmemsys.h:183
#define wassertfalse
#define static_wassert(expression)
#define wassert(expression)
#define INVALID_FILE_ATTRIBUTES
Definition juce_win32_Files.cpp:27
float in
Definition lilv_test.c:1460
float out
Definition lilv_test.c:1461
JOCTET * buffer
Definition juce_JPEGLoader.cpp:302
Definition AudioSampleBuffer.h:33
File water_getExecutableFile()
Definition File.cpp:1420
long long int64
Definition water.h:100
static String getLinkedFile(const String &file)
Definition File.cpp:1596
static String removeEllipsis(const String &path)
Definition File.cpp:100
Type jmax(const Type a, const Type b)
Definition MathsFunctions.h:48
static int countNumberOfSeparators(CharPointer_UTF8 s)
Definition File.cpp:874
static int compareFilenames(const String &name1, const String &name2) noexcept
Definition File.cpp:245
size_t numElementsInArray(Type(&array)[N])
Definition MathsFunctions.h:257
uint32 water_uchar
Definition CharacterFunctions.h:38
Definition swell-types.h:242
#define MAX_PATH
const char * text
Definition swell-functions.h:167
void * HINSTANCE
Definition swell-types.h:212
unsigned int DWORD
Definition swell-types.h:164
void * HANDLE
Definition swell-types.h:212
char CHAR
Definition swell-types.h:188
Definition swell-types.h:196
unsigned long long QuadPart
Definition swell-types.h:197
uch * p
Definition crypt.c:594
while passwd
Definition crypt.c:195
return c
Definition crypt.c:175
int r
Definition crypt.c:458
int error
Definition extract.c:1038
ulg size
Definition extract.c:2350
void handler(int signal)
Definition fileio.c:1632
#define dirent
Definition unix.c:70
closedir((DIR *) G.wild_dir)
char * getenv()
typedef int(UZ_EXP MsgFn)()
#define FALSE
Definition unzpriv.h:1298
struct zdirent * file
Definition win32.c:1500