Loading...
Searching...
No Matches
juce_File.cpp
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. Permission
To use, copy, modify, and/or distribute this software for any purpose with or
without fee is hereby granted provided that the above copyright notice and
this permission notice appear in all copies.
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
File::File (const String& fullPathName)
: fullPath (parseAbsolutePath (fullPathName))
{
}
File File::createFileWithoutCheckingPath (const String& path) noexcept
{
File f;
f.fullPath = path;
return f;
}
File::File (const File& other)
: fullPath (other.fullPath)
{
}
File& File::operator= (const String& newPath)
{
fullPath = parseAbsolutePath (newPath);
return *this;
}
File& File::operator= (const File& other)
{
fullPath = other.fullPath;
return *this;
}
File::File (File&& other) noexcept
: fullPath (std::move (other.fullPath))
{
}
File& File::operator= (File&& other) noexcept
{
fullPath = std::move (other.fullPath);
return *this;
}
//==============================================================================
static String removeEllipsis (const String& path)
{
// This will quickly find both /../ and /./ at the expense of a minor
// false-positive performance hit when path elements end in a dot.
#if JUCE_WINDOWS
if (path.contains (".\\"))
#else
if (path.contains ("./"))
#endif
{
StringArray toks;
toks.addTokens (path, File::getSeparatorString(), {});
bool anythingChanged = false;
for (int i = 1; i < toks.size(); ++i)
{
auto& t = toks[i];
if (t == ".." && toks[i - 1] != "..")
{
anythingChanged = true;
toks.removeRange (i - 1, 2);
i = jmax (0, i - 2);
}
else if (t == ".")
{
anythingChanged = true;
toks.remove (i--);
}
}
if (anythingChanged)
return toks.joinIntoString (File::getSeparatorString());
}
return path;
}
static String normaliseSeparators (const String& path)
{
auto normalisedPath = path;
String separator (File::getSeparatorString());
String doubleSeparator (separator + separator);
auto uncPath = normalisedPath.startsWith (doubleSeparator)
&& ! normalisedPath.fromFirstOccurrenceOf (doubleSeparator, false, false).startsWith (separator);
if (uncPath)
normalisedPath = normalisedPath.fromFirstOccurrenceOf (doubleSeparator, false, false);
while (normalisedPath.contains (doubleSeparator))
normalisedPath = normalisedPath.replace (doubleSeparator, separator);
return uncPath ? doubleSeparator + normalisedPath
: normalisedPath;
}
bool File::isRoot() const
{
return fullPath.isNotEmpty() && *this == getParentDirectory();
}
String File::parseAbsolutePath (const String& p)
{
if (p.isEmpty())
return {};
#if JUCE_WINDOWS
// Windows..
auto path = normaliseSeparators (removeEllipsis (p.replaceCharacter ('/', '\\')));
if (path.startsWithChar (getSeparatorChar()))
{
if (path[1] != getSeparatorChar())
{
/* When you supply a raw string to the File object constructor, it must be an absolute path.
If you're trying to parse a string that may be either a relative path or an absolute path,
you MUST provide a context against which the partial path can be evaluated - you can do
this by simply using File::getChildFile() instead of the File constructor. E.g. saying
"File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
path if that's what was supplied, or would evaluate a partial path relative to the CWD.
*/
jassertfalse;
path = File::getCurrentWorkingDirectory().getFullPathName().substring (0, 2) + path;
}
}
else if (! path.containsChar (':'))
{
/* When you supply a raw string to the File object constructor, it must be an absolute path.
If you're trying to parse a string that may be either a relative path or an absolute path,
you MUST provide a context against which the partial path can be evaluated - you can do
this by simply using File::getChildFile() instead of the File constructor. E.g. saying
"File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
path if that's what was supplied, or would evaluate a partial path relative to the CWD.
*/
jassertfalse;
return File::getCurrentWorkingDirectory().getChildFile (path).getFullPathName();
}
#else
// Mac or Linux..
// Yes, I know it's legal for a unix pathname to contain a backslash, but this assertion is here
// to catch anyone who's trying to run code that was written on Windows with hard-coded path names.
// If that's why you've ended up here, use File::getChildFile() to build your paths instead.
jassert ((! p.containsChar ('\\')) || (p.indexOfChar ('/') >= 0 && p.indexOfChar ('/') < p.indexOfChar ('\\')));
auto path = normaliseSeparators (removeEllipsis (p));
if (path.startsWithChar ('~'))
{
if (path[1] == getSeparatorChar() || path[1] == 0)
{
// expand a name of the form "~/abc"
path = File::getSpecialLocation (File::userHomeDirectory).getFullPathName()
+ path.substring (1);
}
else
{
// expand a name of type "~dave/abc"
auto userName = path.substring (1).upToFirstOccurrenceOf ("/", false, false);
if (auto* pw = getpwnam (userName.toUTF8()))
path = addTrailingSeparator (pw->pw_dir) + path.fromFirstOccurrenceOf ("/", false, false);
}
}
else if (! path.startsWithChar (getSeparatorChar()))
{
#if JUCE_DEBUG || JUCE_LOG_ASSERTIONS
if (! (path.startsWith ("./") || path.startsWith ("../")))
{
/* When you supply a raw string to the File object constructor, it must be an absolute path.
If you're trying to parse a string that may be either a relative path or an absolute path,
you MUST provide a context against which the partial path can be evaluated - you can do
this by simply using File::getChildFile() instead of the File constructor. E.g. saying
"File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
path if that's what was supplied, or would evaluate a partial path relative to the CWD.
*/
jassertfalse;
#if JUCE_LOG_ASSERTIONS
Logger::writeToLog ("Illegal absolute path: " + path);
#endif
}
#endif
return File::getCurrentWorkingDirectory().getChildFile (path).getFullPathName();
}
#endif
while (path.endsWithChar (getSeparatorChar()) && path != getSeparatorString()) // careful not to turn a single "/" into an empty string.
path = path.dropLastCharacters (1);
return path;
}
String File::addTrailingSeparator (const String& path)
{
return path.endsWithChar (getSeparatorChar()) ? path
: path + getSeparatorChar();
}
//==============================================================================
#if JUCE_LINUX || JUCE_BSD
#define NAMES_ARE_CASE_SENSITIVE 1
#endif
bool File::areFileNamesCaseSensitive()
{
#if NAMES_ARE_CASE_SENSITIVE
return true;
#else
return false;
#endif
}
static int compareFilenames (const String& name1, const String& name2) noexcept
{
#if NAMES_ARE_CASE_SENSITIVE
return name1.compare (name2);
#else
return name1.compareIgnoreCase (name2);
#endif
}
bool File::operator== (const File& other) const { return compareFilenames (fullPath, other.fullPath) == 0; }
bool File::operator!= (const File& other) const { return compareFilenames (fullPath, other.fullPath) != 0; }
bool File::operator< (const File& other) const { return compareFilenames (fullPath, other.fullPath) < 0; }
bool File::operator> (const File& other) const { return compareFilenames (fullPath, other.fullPath) > 0; }
//==============================================================================
bool File::setReadOnly (const bool shouldBeReadOnly,
const bool applyRecursively) const
{
bool worked = true;
if (applyRecursively && isDirectory())
for (auto& f : findChildFiles (File::findFilesAndDirectories, false))
worked = f.setReadOnly (shouldBeReadOnly, true) && worked;
return setFileReadOnlyInternal (shouldBeReadOnly) && worked;
}
bool File::setExecutePermission (bool shouldBeExecutable) const
{
return setFileExecutableInternal (shouldBeExecutable);
}
bool File::deleteRecursively (bool followSymlinks) const
{
bool worked = true;
if (isDirectory() && (followSymlinks || ! isSymbolicLink()))
for (auto& f : findChildFiles (File::findFilesAndDirectories, false))
worked = f.deleteRecursively (followSymlinks) && worked;
return deleteFile() && worked;
}
bool File::moveFileTo (const File& newFile) const
{
if (newFile.fullPath == fullPath)
return true;
if (! exists())
return false;
#if ! NAMES_ARE_CASE_SENSITIVE
if (*this != newFile)
#endif
if (! newFile.deleteFile())
return false;
return moveInternal (newFile);
}
bool File::copyFileTo (const File& newFile) const
{
return (*this == newFile)
|| (exists() && newFile.deleteFile() && copyInternal (newFile));
}
bool File::replaceFileIn (const File& newFile) const
{
if (newFile.fullPath == fullPath)
return true;
if (! newFile.exists())
return moveFileTo (newFile);
if (! replaceInternal (newFile))
return false;
deleteFile();
return true;
}
bool File::copyDirectoryTo (const File& newDirectory) const
{
if (isDirectory() && newDirectory.createDirectory())
{
for (auto& f : findChildFiles (File::findFiles, false))
if (! f.copyFileTo (newDirectory.getChildFile (f.getFileName())))
return false;
for (auto& f : findChildFiles (File::findDirectories, false))
if (! f.copyDirectoryTo (newDirectory.getChildFile (f.getFileName())))
return false;
return true;
}
return false;
}
//==============================================================================
String File::getPathUpToLastSlash() const
{
auto lastSlash = fullPath.lastIndexOfChar (getSeparatorChar());
if (lastSlash > 0)
return fullPath.substring (0, lastSlash);
if (lastSlash == 0)
return getSeparatorString();
return fullPath;
}
File File::getParentDirectory() const
{
return createFileWithoutCheckingPath (getPathUpToLastSlash());
}
bool File::isNonEmptyDirectory() const
{
if (! isDirectory())
return false;
return RangedDirectoryIterator (*this, false, "*", findFilesAndDirectories) != RangedDirectoryIterator();
}
//==============================================================================
String File::getFileName() const
{
return fullPath.substring (fullPath.lastIndexOfChar (getSeparatorChar()) + 1);
}
String File::getFileNameWithoutExtension() const
{
auto lastSlash = fullPath.lastIndexOfChar (getSeparatorChar()) + 1;
auto lastDot = fullPath.lastIndexOfChar ('.');
if (lastDot > lastSlash)
return fullPath.substring (lastSlash, lastDot);
return fullPath.substring (lastSlash);
}
bool File::isAChildOf (const File& potentialParent) const
{
if (potentialParent.fullPath.isEmpty())
return false;
auto ourPath = getPathUpToLastSlash();
if (compareFilenames (potentialParent.fullPath, ourPath) == 0)
return true;
if (potentialParent.fullPath.length() >= ourPath.length())
return false;
return getParentDirectory().isAChildOf (potentialParent);
}
int File::hashCode() const { return fullPath.hashCode(); }
int64 File::hashCode64() const { return fullPath.hashCode64(); }
//==============================================================================
bool File::isAbsolutePath (StringRef path)
{
auto firstChar = *(path.text);
return firstChar == getSeparatorChar()
#if JUCE_WINDOWS
|| (firstChar != 0 && path.text[1] == ':');
#else
|| firstChar == '~';
#endif
}
File File::getChildFile (StringRef relativePath) const
{
auto r = relativePath.text;
if (isAbsolutePath (r))
return File (String (r));
#if JUCE_WINDOWS
if (r.indexOf ((juce_wchar) '/') >= 0)
return getChildFile (String (r).replaceCharacter ('/', '\\'));
#endif
auto path = fullPath;
auto separatorChar = getSeparatorChar();
while (*r == '.')
{
auto lastPos = r;
auto secondChar = *++r;
if (secondChar == '.') // remove "../"
{
auto thirdChar = *++r;
if (thirdChar == separatorChar || thirdChar == 0)
{
auto lastSlash = path.lastIndexOfChar (separatorChar);
if (lastSlash >= 0)
path = path.substring (0, lastSlash);
while (*r == separatorChar) // ignore duplicate slashes
++r;
}
else
{
r = lastPos;
break;
}
}
else if (secondChar == separatorChar || secondChar == 0) // remove "./"
{
while (*r == separatorChar) // ignore duplicate slashes
++r;
}
else
{
r = lastPos;
break;
}
}
path = addTrailingSeparator (path);
path.appendCharPointer (r);
return File (path);
}
File File::getSiblingFile (StringRef fileName) const
{
return getParentDirectory().getChildFile (fileName);
}
//==============================================================================
String File::descriptionOfSizeInBytes (const int64 bytes)
{
const char* suffix;
double divisor = 0;
if (bytes == 1) { suffix = " byte"; }
else if (bytes < 1024) { suffix = " bytes"; }
else if (bytes < 1024 * 1024) { suffix = " KB"; divisor = 1024.0; }
else if (bytes < 1024 * 1024 * 1024) { suffix = " MB"; divisor = 1024.0 * 1024.0; }
else { suffix = " GB"; divisor = 1024.0 * 1024.0 * 1024.0; }
return (divisor > 0 ? String ((double) bytes / divisor, 1) : String (bytes)) + suffix;
}
//==============================================================================
Result File::create() const
{
if (exists())
return Result::ok();
auto parentDir = getParentDirectory();
if (parentDir == *this)
return Result::fail ("Cannot create parent directory");
auto r = parentDir.createDirectory();
if (r.wasOk())
{
FileOutputStream fo (*this, 8);
r = fo.getStatus();
}
return r;
}
Result File::createDirectory() const
{
if (isDirectory())
return Result::ok();
auto parentDir = getParentDirectory();
if (parentDir == *this)
return Result::fail ("Cannot create parent directory");
auto r = parentDir.createDirectory();
if (r.wasOk())
r = createDirectoryInternal (fullPath.trimCharactersAtEnd (getSeparatorString()));
return r;
}
//==============================================================================
Time File::getLastModificationTime() const { int64 m, a, c; getFileTimesInternal (m, a, c); return Time (m); }
Time File::getLastAccessTime() const { int64 m, a, c; getFileTimesInternal (m, a, c); return Time (a); }
Time File::getCreationTime() const { int64 m, a, c; getFileTimesInternal (m, a, c); return Time (c); }
bool File::setLastModificationTime (Time t) const { return setFileTimesInternal (t.toMilliseconds(), 0, 0); }
bool File::setLastAccessTime (Time t) const { return setFileTimesInternal (0, t.toMilliseconds(), 0); }
bool File::setCreationTime (Time t) const { return setFileTimesInternal (0, 0, t.toMilliseconds()); }
//==============================================================================
bool File::loadFileAsData (MemoryBlock& destBlock) const
{
if (! existsAsFile())
return false;
FileInputStream in (*this);
return in.openedOk() && getSize() == (int64) in.readIntoMemoryBlock (destBlock);
}
String File::loadFileAsString() const
{
if (! existsAsFile())
return {};
FileInputStream in (*this);
return in.openedOk() ? in.readEntireStreamAsString()
: String();
}
void File::readLines (StringArray& destLines) const
{
destLines.addLines (loadFileAsString());
}
//==============================================================================
Array<File> File::findChildFiles (int whatToLookFor, bool searchRecursively, const String& wildcard, FollowSymlinks followSymlinks) const
{
Array<File> results;
findChildFiles (results, whatToLookFor, searchRecursively, wildcard, followSymlinks);
return results;
}
int File::findChildFiles (Array<File>& results, int whatToLookFor, bool searchRecursively, const String& wildcard, FollowSymlinks followSymlinks) const
{
int total = 0;
for (const auto& di : RangedDirectoryIterator (*this, searchRecursively, wildcard, whatToLookFor, followSymlinks))
{
results.add (di.getFile());
++total;
}
return total;
}
int File::getNumberOfChildFiles (const int whatToLookFor, const String& wildCardPattern) const
{
return std::accumulate (RangedDirectoryIterator (*this, false, wildCardPattern, whatToLookFor),
RangedDirectoryIterator(),
0,
[] (int acc, const DirectoryEntry&) { return acc + 1; });
}
bool File::containsSubDirectories() const
{
if (! isDirectory())
return false;
return RangedDirectoryIterator (*this, false, "*", findDirectories) != RangedDirectoryIterator();
}
//==============================================================================
File File::getNonexistentChildFile (const String& suggestedPrefix,
const String& suffix,
bool putNumbersInBrackets) const
{
auto f = getChildFile (suggestedPrefix + suffix);
if (f.exists())
{
int number = 1;
auto prefix = suggestedPrefix;
// remove any bracketed numbers that may already be on the end..
if (prefix.trim().endsWithChar (')'))
{
putNumbersInBrackets = true;
auto openBracks = prefix.lastIndexOfChar ('(');
auto closeBracks = prefix.lastIndexOfChar (')');
if (openBracks > 0
&& closeBracks > openBracks
&& prefix.substring (openBracks + 1, closeBracks).containsOnly ("0123456789"))
{
number = prefix.substring (openBracks + 1, closeBracks).getIntValue();
prefix = prefix.substring (0, openBracks);
}
}
do
{
auto newName = prefix;
if (putNumbersInBrackets)
{
newName << '(' << ++number << ')';
}
else
{
if (CharacterFunctions::isDigit (prefix.getLastCharacter()))
newName << '_'; // pad with an underscore if the name already ends in a digit
newName << ++number;
}
f = getChildFile (newName + suffix);
} while (f.exists());
}
return f;
}
File File::getNonexistentSibling (const bool putNumbersInBrackets) const
{
if (! exists())
return *this;
return getParentDirectory().getNonexistentChildFile (getFileNameWithoutExtension(),
getFileExtension(),
putNumbersInBrackets);
}
//==============================================================================
String File::getFileExtension() const
{
auto indexOfDot = fullPath.lastIndexOfChar ('.');
if (indexOfDot > fullPath.lastIndexOfChar (getSeparatorChar()))
return fullPath.substring (indexOfDot);
return {};
}
bool File::hasFileExtension (StringRef possibleSuffix) const
{
if (possibleSuffix.isEmpty())
return fullPath.lastIndexOfChar ('.') <= fullPath.lastIndexOfChar (getSeparatorChar());
auto semicolon = possibleSuffix.text.indexOf ((juce_wchar) ';');
if (semicolon >= 0)
return hasFileExtension (String (possibleSuffix.text).substring (0, semicolon).trimEnd())
|| hasFileExtension ((possibleSuffix.text + (semicolon + 1)).findEndOfWhitespace());
if (fullPath.endsWithIgnoreCase (possibleSuffix))
{
if (possibleSuffix.text[0] == '.')
return true;
auto dotPos = fullPath.length() - possibleSuffix.length() - 1;
if (dotPos >= 0)
return fullPath[dotPos] == '.';
}
return false;
}
File File::withFileExtension (StringRef newExtension) const
{
if (fullPath.isEmpty())
return {};
auto filePart = getFileName();
auto lastDot = filePart.lastIndexOfChar ('.');
if (lastDot >= 0)
filePart = filePart.substring (0, lastDot);
if (newExtension.isNotEmpty() && newExtension.text[0] != '.')
filePart << '.';
return getSiblingFile (filePart + newExtension);
}
//==============================================================================
bool File::startAsProcess (const String& parameters) const
{
return exists() && Process::openDocument (fullPath, parameters);
}
//==============================================================================
std::unique_ptr<FileInputStream> File::createInputStream() const
{
auto fin = std::make_unique<FileInputStream> (*this);
if (fin->openedOk())
return fin;
return nullptr;
}
std::unique_ptr<FileOutputStream> File::createOutputStream (size_t bufferSize) const
{
auto fout = std::make_unique<FileOutputStream> (*this, bufferSize);
if (fout->openedOk())
return fout;
return nullptr;
}
//==============================================================================
bool File::appendData (const void* const dataToAppend,
const size_t numberOfBytes) const
{
jassert (((ssize_t) numberOfBytes) >= 0);
if (numberOfBytes == 0)
return true;
FileOutputStream fout (*this, 8192);
return fout.openedOk() && fout.write (dataToAppend, numberOfBytes);
}
bool File::replaceWithData (const void* const dataToWrite,
const size_t numberOfBytes) const
{
if (numberOfBytes == 0)
return deleteFile();
TemporaryFile tempFile (*this, TemporaryFile::useHiddenFile);
tempFile.getFile().appendData (dataToWrite, numberOfBytes);
return tempFile.overwriteTargetFileWithTemporary();
}
bool File::appendText (const String& text, bool asUnicode, bool writeHeaderBytes, const char* lineFeed) const
{
FileOutputStream fout (*this);
if (fout.failedToOpen())
return false;
return fout.writeText (text, asUnicode, writeHeaderBytes, lineFeed);
}
bool File::replaceWithText (const String& textToWrite, bool asUnicode, bool writeHeaderBytes, const char* lineFeed) const
{
TemporaryFile tempFile (*this, TemporaryFile::useHiddenFile);
tempFile.getFile().appendText (textToWrite, asUnicode, writeHeaderBytes, lineFeed);
return tempFile.overwriteTargetFileWithTemporary();
}
bool File::hasIdenticalContentTo (const File& other) const
{
if (other == *this)
return true;
if (getSize() == other.getSize() && existsAsFile() && other.existsAsFile())
{
FileInputStream in1 (*this), in2 (other);
if (in1.openedOk() && in2.openedOk())
{
const int bufferSize = 4096;
HeapBlock<char> buffer1 (bufferSize), buffer2 (bufferSize);
for (;;)
{
auto num1 = in1.read (buffer1, bufferSize);
auto num2 = in2.read (buffer2, bufferSize);
if (num1 != num2)
break;
if (num1 <= 0)
return true;
if (memcmp (buffer1, buffer2, (size_t) num1) != 0)
break;
}
}
}
return false;
}
//==============================================================================
String File::createLegalPathName (const String& original)
{
auto s = original;
String start;
if (s.isNotEmpty() && s[1] == ':')
{
start = s.substring (0, 2);
s = s.substring (2);
}
return start + s.removeCharacters ("\"#@,;:<>*^|?")
.substring (0, 1024);
}
String File::createLegalFileName (const String& original)
{
auto s = original.removeCharacters ("\"#@,;:<>*^|?\\/");
const int maxLength = 128; // only the length of the filename, not the whole path
auto len = s.length();
if (len > maxLength)
{
auto lastDot = s.lastIndexOfChar ('.');
if (lastDot > jmax (0, len - 12))
{
s = s.substring (0, maxLength - (len - lastDot))
+ s.substring (lastDot);
}
else
{
s = s.substring (0, maxLength);
}
}
return s;
}
//==============================================================================
static int countNumberOfSeparators (String::CharPointerType s)
{
int num = 0;
for (;;)
{
auto c = s.getAndAdvance();
if (c == 0)
break;
if (c == File::getSeparatorChar())
++num;
}
return num;
}
String File::getRelativePathFrom (const File& dir) const
{
if (dir == *this)
return ".";
auto thisPath = fullPath;
while (thisPath.endsWithChar (getSeparatorChar()))
thisPath = thisPath.dropLastCharacters (1);
auto dirPath = addTrailingSeparator (dir.existsAsFile() ? dir.getParentDirectory().getFullPathName()
: dir.fullPath);
int commonBitLength = 0;
auto thisPathAfterCommon = thisPath.getCharPointer();
auto dirPathAfterCommon = dirPath.getCharPointer();
{
auto thisPathIter = thisPath.getCharPointer();
auto dirPathIter = dirPath.getCharPointer();
for (int i = 0;;)
{
auto c1 = thisPathIter.getAndAdvance();
auto c2 = dirPathIter.getAndAdvance();
#if NAMES_ARE_CASE_SENSITIVE
if (c1 != c2
#else
if ((c1 != c2 && CharacterFunctions::toLowerCase (c1) != CharacterFunctions::toLowerCase (c2))
#endif
|| c1 == 0)
break;
++i;
if (c1 == getSeparatorChar())
{
thisPathAfterCommon = thisPathIter;
dirPathAfterCommon = dirPathIter;
commonBitLength = i;
}
}
}
// if the only common bit is the root, then just return the full path..
if (commonBitLength == 0 || (commonBitLength == 1 && thisPath[1] == getSeparatorChar()))
return fullPath;
auto numUpDirectoriesNeeded = countNumberOfSeparators (dirPathAfterCommon);
if (numUpDirectoriesNeeded == 0)
return thisPathAfterCommon;
#if JUCE_WINDOWS
auto s = String::repeatedString ("..\\", numUpDirectoriesNeeded);
#else
auto s = String::repeatedString ("../", numUpDirectoriesNeeded);
#endif
s.appendCharPointer (thisPathAfterCommon);
return s;
}
//==============================================================================
File File::createTempFile (StringRef fileNameEnding)
{
auto tempFile = getSpecialLocation (tempDirectory)
.getChildFile ("temp_" + String::toHexString (Random::getSystemRandom().nextInt()))
.withFileExtension (fileNameEnding);
if (tempFile.exists())
return createTempFile (fileNameEnding);
return tempFile;
}
bool File::createSymbolicLink (const File& linkFileToCreate,
[[maybe_unused]] const String& nativePathOfTarget,
bool overwriteExisting)
{
if (linkFileToCreate.exists())
{
if (! linkFileToCreate.isSymbolicLink())
{
// user has specified an existing file / directory as the link
// this is bad! the user could end up unintentionally destroying data
jassertfalse;
return false;
}
if (overwriteExisting)
linkFileToCreate.deleteFile();
}
#if JUCE_MAC || JUCE_LINUX || JUCE_BSD
// one common reason for getting an error here is that the file already exists
if (symlink (nativePathOfTarget.toRawUTF8(), linkFileToCreate.getFullPathName().toRawUTF8()) == -1)
{
jassertfalse;
return false;
}
return true;
#elif JUCE_MSVC
File targetFile (linkFileToCreate.getSiblingFile (nativePathOfTarget));
return CreateSymbolicLink (linkFileToCreate.getFullPathName().toWideCharPointer(),
nativePathOfTarget.toWideCharPointer(),
targetFile.isDirectory() ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0) != FALSE;
#else
jassertfalse; // symbolic links not supported on this platform!
return false;
#endif
}
bool File::createSymbolicLink (const File& linkFileToCreate, bool overwriteExisting) const
{
return createSymbolicLink (linkFileToCreate, getFullPathName(), overwriteExisting);
}
#if ! JUCE_WINDOWS
File File::getLinkedTarget() const
{
if (isSymbolicLink())
return getSiblingFile (getNativeLinkedTarget());
return *this;
}
#endif
//==============================================================================
#if JUCE_ALLOW_STATIC_NULL_VARIABLES
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-declarations")
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4996)
const File File::nonexistent{};
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
JUCE_END_IGNORE_WARNINGS_MSVC
#endif
//==============================================================================
MemoryMappedFile::MemoryMappedFile (const File& file, MemoryMappedFile::AccessMode mode, bool exclusive)
: range (0, file.getSize())
{
openInternal (file, mode, exclusive);
}
MemoryMappedFile::MemoryMappedFile (const File& file, const Range<int64>& fileRange, AccessMode mode, bool exclusive)
: range (fileRange.getIntersectionWith (Range<int64> (0, file.getSize())))
{
openInternal (file, mode, exclusive);
}
//==============================================================================
//==============================================================================
#if JUCE_UNIT_TESTS
class FileTests final : public UnitTest
{
public:
FileTests()
: UnitTest ("Files", UnitTestCategories::files)
{}
void runTest() override
{
beginTest ("Reading");
const File home (File::getSpecialLocation (File::userHomeDirectory));
const File temp (File::getSpecialLocation (File::tempDirectory));
expect (! File().exists());
expect (! File().existsAsFile());
expect (! File().isDirectory());
#if ! JUCE_WINDOWS
expect (File ("/").isDirectory());
#endif
expect (home.isDirectory());
expect (home.exists());
expect (! home.existsAsFile());
expect (File::getSpecialLocation (File::userApplicationDataDirectory).isDirectory());
expect (File::getSpecialLocation (File::currentExecutableFile).exists());
expect (File::getSpecialLocation (File::currentApplicationFile).exists());
expect (File::getSpecialLocation (File::invokedExecutableFile).exists());
expect (home.getVolumeTotalSize() > 1024 * 1024);
expect (home.getBytesFreeOnVolume() > 0);
expect (! home.isHidden());
expect (home.isOnHardDisk());
expect (! home.isOnCDRomDrive());
expect (File::getCurrentWorkingDirectory().exists());
expect (home.setAsCurrentWorkingDirectory());
{
auto homeParent = home;
bool noSymlinks = true;
while (! homeParent.isRoot())
{
if (homeParent.isSymbolicLink())
{
noSymlinks = false;
break;
}
homeParent = homeParent.getParentDirectory();
}
if (noSymlinks)
expect (File::getCurrentWorkingDirectory() == home);
}
{
Array<File> roots;
File::findFileSystemRoots (roots);
expect (roots.size() > 0);
int numRootsExisting = 0;
for (int i = 0; i < roots.size(); ++i)
if (roots[i].exists())
++numRootsExisting;
// (on windows, some of the drives may not contain media, so as long as at least one is ok..)
expect (numRootsExisting > 0);
}
beginTest ("Writing");
auto random = getRandom();
const auto tempFolderName = "JUCE UnitTests Temp Folder "
+ String::toHexString (random.nextInt())
+ ".folder";
File demoFolder (temp.getChildFile (tempFolderName));
expect (demoFolder.deleteRecursively());
expect (demoFolder.createDirectory());
expect (demoFolder.isDirectory());
expect (demoFolder.getParentDirectory() == temp);
expect (temp.isDirectory());
expect (temp.findChildFiles (File::findFilesAndDirectories, false, "*").contains (demoFolder));
expect (temp.findChildFiles (File::findDirectories, true, "*.folder").contains (demoFolder));
File tempFile (demoFolder.getNonexistentChildFile ("test", ".txt", false));
expect (tempFile.getFileExtension() == ".txt");
expect (tempFile.hasFileExtension (".txt"));
expect (tempFile.hasFileExtension ("txt"));
expect (tempFile.withFileExtension ("xyz").hasFileExtension (".xyz"));
expect (tempFile.withFileExtension ("xyz").hasFileExtension ("abc;xyz;foo"));
expect (tempFile.withFileExtension ("xyz").hasFileExtension ("xyz;foo"));
expect (! tempFile.withFileExtension ("h").hasFileExtension ("bar;foo;xx"));
expect (tempFile.getSiblingFile ("foo").isAChildOf (temp));
expect (tempFile.hasWriteAccess());
expect (home.getChildFile (".") == home);
expect (home.getChildFile ("..") == home.getParentDirectory());
expect (home.getChildFile (".xyz").getFileName() == ".xyz");
expect (home.getChildFile ("..xyz").getFileName() == "..xyz");
expect (home.getChildFile ("...xyz").getFileName() == "...xyz");
expect (home.getChildFile ("./xyz") == home.getChildFile ("xyz"));
expect (home.getChildFile ("././xyz") == home.getChildFile ("xyz"));
expect (home.getChildFile ("../xyz") == home.getParentDirectory().getChildFile ("xyz"));
expect (home.getChildFile (".././xyz") == home.getParentDirectory().getChildFile ("xyz"));
expect (home.getChildFile (".././xyz/./abc") == home.getParentDirectory().getChildFile ("xyz/abc"));
expect (home.getChildFile ("./../xyz") == home.getParentDirectory().getChildFile ("xyz"));
expect (home.getChildFile ("a1/a2/a3/./../../a4") == home.getChildFile ("a1/a4"));
expect (! File().hasReadAccess());
expect (! File().hasWriteAccess());
expect (! tempFile.hasReadAccess());
{
FileOutputStream fo (tempFile);
fo.write ("0123456789", 10);
}
expect (tempFile.hasReadAccess());
expect (tempFile.exists());
expect (tempFile.getSize() == 10);
expect (std::abs ((int) (tempFile.getLastModificationTime().toMilliseconds() - Time::getCurrentTime().toMilliseconds())) < 3000);
expectEquals (tempFile.loadFileAsString(), String ("0123456789"));
expect (! demoFolder.containsSubDirectories());
expectEquals (tempFile.getRelativePathFrom (demoFolder.getParentDirectory()), demoFolder.getFileName() + File::getSeparatorString() + tempFile.getFileName());
expectEquals (demoFolder.getParentDirectory().getRelativePathFrom (tempFile), ".." + File::getSeparatorString() + ".." + File::getSeparatorString() + demoFolder.getParentDirectory().getFileName());
expect (demoFolder.getNumberOfChildFiles (File::findFiles) == 1);
expect (demoFolder.getNumberOfChildFiles (File::findFilesAndDirectories) == 1);
expect (demoFolder.getNumberOfChildFiles (File::findDirectories) == 0);
demoFolder.getNonexistentChildFile ("tempFolder", "", false).createDirectory();
expect (demoFolder.getNumberOfChildFiles (File::findDirectories) == 1);
expect (demoFolder.getNumberOfChildFiles (File::findFilesAndDirectories) == 2);
expect (demoFolder.containsSubDirectories());
expect (tempFile.hasWriteAccess());
tempFile.setReadOnly (true);
expect (! tempFile.hasWriteAccess());
tempFile.setReadOnly (false);
expect (tempFile.hasWriteAccess());
Time t (Time::getCurrentTime());
tempFile.setLastModificationTime (t);
Time t2 = tempFile.getLastModificationTime();
expect (std::abs ((int) (t2.toMilliseconds() - t.toMilliseconds())) <= 1000);
{
MemoryBlock mb;
tempFile.loadFileAsData (mb);
expect (mb.getSize() == 10);
expect (mb[0] == '0');
}
{
expect (tempFile.getSize() == 10);
FileOutputStream fo (tempFile);
expect (fo.openedOk());
expect (fo.setPosition (7));
expect (fo.truncate().wasOk());
expect (tempFile.getSize() == 7);
fo.write ("789", 3);
fo.flush();
expect (tempFile.getSize() == 10);
}
beginTest ("Memory-mapped files");
{
MemoryMappedFile mmf (tempFile, MemoryMappedFile::readOnly);
expect (mmf.getSize() == 10);
expect (mmf.getData() != nullptr);
expect (memcmp (mmf.getData(), "0123456789", 10) == 0);
}
{
const File tempFile2 (tempFile.getNonexistentSibling (false));
expect (tempFile2.create());
expect (tempFile2.appendData ("xxxxxxxxxx", 10));
{
MemoryMappedFile mmf (tempFile2, MemoryMappedFile::readWrite);
expect (mmf.getSize() == 10);
expect (mmf.getData() != nullptr);
memcpy (mmf.getData(), "abcdefghij", 10);
}
{
MemoryMappedFile mmf (tempFile2, MemoryMappedFile::readWrite);
expect (mmf.getSize() == 10);
expect (mmf.getData() != nullptr);
expect (memcmp (mmf.getData(), "abcdefghij", 10) == 0);
}
expect (tempFile2.deleteFile());
}
beginTest ("More writing");
expect (tempFile.appendData ("abcdefghij", 10));
expect (tempFile.getSize() == 20);
expect (tempFile.replaceWithData ("abcdefghij", 10));
expect (tempFile.getSize() == 10);
File tempFile2 (tempFile.getNonexistentSibling (false));
expect (tempFile.copyFileTo (tempFile2));
expect (tempFile2.exists());
expect (tempFile2.hasIdenticalContentTo (tempFile));
expect (tempFile.deleteFile());
expect (! tempFile.exists());
expect (tempFile2.moveFileTo (tempFile));
expect (tempFile.exists());
expect (! tempFile2.exists());
expect (demoFolder.deleteRecursively());
expect (! demoFolder.exists());
{
URL url ("https://audio.dev/foo/bar/");
expectEquals (url.toString (false), String ("https://audio.dev/foo/bar/"));
expectEquals (url.getChildURL ("x").toString (false), String ("https://audio.dev/foo/bar/x"));
expectEquals (url.getParentURL().toString (false), String ("https://audio.dev/foo"));
expectEquals (url.getParentURL().getParentURL().toString (false), String ("https://audio.dev/"));
expectEquals (url.getParentURL().getParentURL().getParentURL().toString (false), String ("https://audio.dev/"));
expectEquals (url.getParentURL().getChildURL ("x").toString (false), String ("https://audio.dev/foo/x"));
expectEquals (url.getParentURL().getParentURL().getParentURL().getChildURL ("x").toString (false), String ("https://audio.dev/x"));
}
{
URL url ("https://audio.dev/foo/bar");
expectEquals (url.toString (false), String ("https://audio.dev/foo/bar"));
expectEquals (url.getChildURL ("x").toString (false), String ("https://audio.dev/foo/bar/x"));
expectEquals (url.getParentURL().toString (false), String ("https://audio.dev/foo"));
expectEquals (url.getParentURL().getParentURL().toString (false), String ("https://audio.dev/"));
expectEquals (url.getParentURL().getParentURL().getParentURL().toString (false), String ("https://audio.dev/"));
expectEquals (url.getParentURL().getChildURL ("x").toString (false), String ("https://audio.dev/foo/x"));
expectEquals (url.getParentURL().getParentURL().getParentURL().getChildURL ("x").toString (false), String ("https://audio.dev/x"));
}
}
};
static FileTests fileUnitTests;
#endif
} // namespace juce
juce::Array
Definition juce_Array.h:56
juce::Array::add
void add(const ElementType &newElement)
Definition juce_Array.h:418
juce::CharacterFunctions::toLowerCase
static juce_wchar toLowerCase(juce_wchar character) noexcept
Definition juce_CharacterFunctions.cpp:33
juce::CharacterFunctions::isDigit
static bool isDigit(char character) noexcept
Definition juce_CharacterFunctions.cpp:69
juce::DirectoryEntry
Definition juce_RangedDirectoryIterator.h:36
juce::FileInputStream
Definition juce_FileInputStream.h:35
juce::FileInputStream::read
int read(void *, int) override
Definition juce_FileInputStream.cpp:43
juce::FileInputStream::openedOk
bool openedOk() const noexcept
Definition juce_FileInputStream.h:67
juce::FileOutputStream
Definition juce_FileOutputStream.h:35
juce::FileOutputStream::getStatus
const Result & getStatus() const noexcept
Definition juce_FileOutputStream.h:81
juce::FileOutputStream::write
bool write(const void *, size_t) override
Definition juce_FileOutputStream.cpp:76
juce::FileOutputStream::failedToOpen
bool failedToOpen() const noexcept
Definition juce_FileOutputStream.h:86
juce::FileOutputStream::openedOk
bool openedOk() const noexcept
Definition juce_FileOutputStream.h:91
juce::File
Definition juce_File.h:45
juce::File::createOutputStream
std::unique_ptr< FileOutputStream > createOutputStream(size_t bufferSize=0x8000) const
Definition juce_File.cpp:742
juce::File::replaceWithText
bool replaceWithText(const String &textToWrite, bool asUnicode=false, bool writeUnicodeHeaderBytes=false, const char *lineEndings="\r\n") const
Definition juce_File.cpp:786
juce::File::isSymbolicLink
bool isSymbolicLink() const
juce::File::getNumberOfChildFiles
int getNumberOfChildFiles(int whatToLookFor, const String &wildCardPattern="*") const
Definition juce_File.cpp:592
juce::File::moveFileTo
bool moveFileTo(const File &targetLocation) const
Definition juce_File.cpp:288
juce::File::operator==
bool operator==(const File &) const
Definition juce_File.cpp:254
juce::File::hashCode64
int64 hashCode64() const
Definition juce_File.cpp:405
juce::File::containsSubDirectories
bool containsSubDirectories() const
Definition juce_File.cpp:600
juce::File::isDirectory
bool isDirectory() const
juce::File::findChildFiles
Array< File > findChildFiles(int whatToLookFor, bool searchRecursively, const String &wildCardPattern="*", FollowSymlinks followSymlinks=FollowSymlinks::yes) const
Definition juce_File.cpp:572
juce::File::hasIdenticalContentTo
bool hasIdenticalContentTo(const File &other) const
Definition juce_File.cpp:793
juce::File::createLegalPathName
static String createLegalPathName(const String &pathNameToFix)
Definition juce_File.cpp:828
juce::File::addTrailingSeparator
static String addTrailingSeparator(const String &path)
Definition juce_File.cpp:225
juce::File::getFileExtension
String getFileExtension() const
Definition juce_File.cpp:672
juce::File::getLastModificationTime
Time getLastModificationTime() const
Definition juce_File.cpp:538
juce::File::existsAsFile
bool existsAsFile() const
juce::File::copyFileTo
bool copyFileTo(const File &targetLocation) const
Definition juce_File.cpp:305
juce::File::getSize
int64 getSize() const
juce::File::deleteRecursively
bool deleteRecursively(bool followSymlinks=false) const
Definition juce_File.cpp:277
juce::File::getSpecialLocation
static File JUCE_CALLTYPE getSpecialLocation(const SpecialLocationType type)
juce::File::getFullPathName
const String & getFullPathName() const noexcept
Definition juce_File.h:153
juce::File::getFileName
String getFileName() const
Definition juce_File.cpp:372
juce::File::replaceWithData
bool replaceWithData(const void *dataToWrite, size_t numberOfBytes) const
Definition juce_File.cpp:765
juce::File::setLastAccessTime
bool setLastAccessTime(Time newTime) const
Definition juce_File.cpp:543
juce::File::getChildFile
File getChildFile(StringRef relativeOrAbsolutePath) const
Definition juce_File.cpp:420
juce::File::readLines
void readLines(StringArray &destLines) const
Definition juce_File.cpp:566
juce::File::isAbsolutePath
static bool isAbsolutePath(StringRef path)
Definition juce_File.cpp:408
juce::File::getSiblingFile
File getSiblingFile(StringRef siblingFileName) const
Definition juce_File.cpp:477
juce::File::createSymbolicLink
bool createSymbolicLink(const File &linkFileToCreate, bool overwriteExisting) const
Definition juce_File.cpp:1002
juce::File::getFileNameWithoutExtension
String getFileNameWithoutExtension() const
Definition juce_File.cpp:377
juce::File::getNonexistentSibling
File getNonexistentSibling(bool putNumbersInBrackets=true) const
Definition juce_File.cpp:661
juce::File::tempDirectory
@ tempDirectory
Definition juce_File.h:919
juce::File::userHomeDirectory
@ userHomeDirectory
Definition juce_File.h:869
juce::File::getRelativePathFrom
String getRelativePathFrom(const File &directoryToBeRelativeTo) const
Definition juce_File.cpp:887
juce::File::appendText
bool appendText(const String &textToAppend, bool asUnicode=false, bool writeUnicodeHeaderBytes=false, const char *lineEndings="\r\n") const
Definition juce_File.cpp:776
juce::File::hashCode
int hashCode() const
Definition juce_File.cpp:404
juce::File::create
Result create() const
Definition juce_File.cpp:498
juce::File::findDirectories
@ findDirectories
Definition juce_File.h:565
juce::File::findFilesAndDirectories
@ findFilesAndDirectories
Definition juce_File.h:567
juce::File::findFiles
@ findFiles
Definition juce_File.h:566
juce::File::getNonexistentChildFile
File getNonexistentChildFile(const String &prefix, const String &suffix, bool putNumbersInBrackets=true) const
Definition juce_File.cpp:609
juce::File::operator!=
bool operator!=(const File &) const
Definition juce_File.cpp:255
juce::File::setCreationTime
bool setCreationTime(Time newTime) const
Definition juce_File.cpp:544
juce::File::descriptionOfSizeInBytes
static String descriptionOfSizeInBytes(int64 bytes)
Definition juce_File.cpp:483
juce::File::setReadOnly
bool setReadOnly(bool shouldBeReadOnly, bool applyRecursively=false) const
Definition juce_File.cpp:260
juce::File::createTempFile
static File createTempFile(StringRef fileNameEnding)
Definition juce_File.cpp:951
juce::File::getSeparatorChar
static juce_wchar getSeparatorChar()
juce::File::areFileNamesCaseSensitive
static bool areFileNamesCaseSensitive()
Definition juce_File.cpp:236
juce::File::FollowSymlinks
FollowSymlinks
Definition juce_File.h:572
juce::File::isRoot
bool isRoot() const
Definition juce_File.cpp:125
juce::File::loadFileAsString
String loadFileAsString() const
Definition juce_File.cpp:556
juce::File::operator>
bool operator>(const File &) const
Definition juce_File.cpp:257
juce::File::getLinkedTarget
File getLinkedTarget() const
Definition juce_File.cpp:1008
juce::File::getParentDirectory
File getParentDirectory() const
Definition juce_File.cpp:358
juce::File::appendData
bool appendData(const void *dataToAppend, size_t numberOfBytes) const
Definition juce_File.cpp:753
juce::File::createInputStream
std::unique_ptr< FileInputStream > createInputStream() const
Definition juce_File.cpp:732
juce::File::operator<
bool operator<(const File &) const
Definition juce_File.cpp:256
juce::File::getCreationTime
Time getCreationTime() const
Definition juce_File.cpp:540
juce::File::setExecutePermission
bool setExecutePermission(bool shouldBeExecutable) const
Definition juce_File.cpp:272
juce::File::withFileExtension
File withFileExtension(StringRef newExtension) const
Definition juce_File.cpp:707
juce::File::createLegalFileName
static String createLegalFileName(const String &fileNameToFix)
Definition juce_File.cpp:843
juce::File::File
File()=default
juce::File::deleteFile
bool deleteFile() const
juce::File::replaceFileIn
bool replaceFileIn(const File &targetLocation) const
Definition juce_File.cpp:311
juce::File::isAChildOf
bool isAChildOf(const File &potentialParentDirectory) const
Definition juce_File.cpp:388
juce::File::createFileWithoutCheckingPath
static File createFileWithoutCheckingPath(const String &absolutePath) noexcept
Definition juce_File.cpp:31
juce::File::startAsProcess
bool startAsProcess(const String &parameters=String()) const
Definition juce_File.cpp:726
juce::File::getNativeLinkedTarget
String getNativeLinkedTarget() const
juce::File::hasFileExtension
bool hasFileExtension(StringRef extensionToTest) const
Definition juce_File.cpp:682
juce::File::exists
bool exists() const
juce::File::copyDirectoryTo
bool copyDirectoryTo(const File &newDirectory) const
Definition juce_File.cpp:326
juce::File::loadFileAsData
bool loadFileAsData(MemoryBlock &result) const
Definition juce_File.cpp:547
juce::File::setLastModificationTime
bool setLastModificationTime(Time newTime) const
Definition juce_File.cpp:542
juce::File::getLastAccessTime
Time getLastAccessTime() const
Definition juce_File.cpp:539
juce::File::createDirectory
Result createDirectory() const
Definition juce_File.cpp:519
juce::File::getCurrentWorkingDirectory
static File getCurrentWorkingDirectory()
juce::File::getSeparatorString
static StringRef getSeparatorString()
juce::File::operator=
File & operator=(const String &newAbsolutePath)
Definition juce_File.cpp:43
juce::HeapBlock
Definition juce_HeapBlock.h:87
juce::InputStream::readIntoMemoryBlock
virtual size_t readIntoMemoryBlock(MemoryBlock &destBlock, ssize_t maxNumBytesToRead=-1)
Definition juce_InputStream.cpp:223
juce::InputStream::readEntireStreamAsString
virtual String readEntireStreamAsString()
Definition juce_InputStream.cpp:229
juce::Logger::writeToLog
static void JUCE_CALLTYPE writeToLog(const String &message)
Definition juce_Logger.cpp:40
juce::MemoryBlock
Definition juce_MemoryBlock.h:33
juce::MemoryMappedFile::MemoryMappedFile
MemoryMappedFile(const File &file, AccessMode mode, bool exclusive=false)
Definition juce_File.cpp:1031
juce::MemoryMappedFile::getSize
size_t getSize() const noexcept
Definition juce_MemoryMappedFile.h:94
juce::MemoryMappedFile::AccessMode
AccessMode
Definition juce_MemoryMappedFile.h:37
juce::OutputStream::writeText
virtual bool writeText(const String &text, bool asUTF16, bool writeUTF16ByteOrderMark, const char *lineEndings)
Definition juce_OutputStream.cpp:198
juce::Process::openDocument
static bool JUCE_CALLTYPE openDocument(const String &documentURL, const String &parameters)
juce::Random::getSystemRandom
static Random & getSystemRandom() noexcept
Definition juce_Random.cpp:67
juce::Range
Definition juce_Range.h:40
juce::RangedDirectoryIterator
Definition juce_RangedDirectoryIterator.h:100
juce::Result
Definition juce_Result.h:57
juce::Result::fail
static Result fail(const String &errorMessage) noexcept
Definition juce_Result.cpp:65
juce::Result::ok
static Result ok() noexcept
Definition juce_Result.h:61
juce::StringArray
Definition juce_StringArray.h:35
juce::StringArray::joinIntoString
String joinIntoString(StringRef separatorString, int startIndex=0, int numberOfElements=-1) const
Definition juce_StringArray.cpp:289
juce::StringArray::size
int size() const noexcept
Definition juce_StringArray.h:136
juce::StringArray::addLines
int addLines(StringRef stringToBreakUp)
Definition juce_StringArray.cpp:358
juce::StringArray::removeRange
void removeRange(int startIndex, int numberToRemove)
Definition juce_StringArray.cpp:244
juce::StringArray::remove
void remove(int index)
Definition juce_StringArray.cpp:223
juce::StringArray::addTokens
int addTokens(StringRef stringToTokenise, bool preserveQuotedStrings)
Definition juce_StringArray.cpp:329
juce::StringRef
Definition juce_StringRef.h:62
juce::StringRef::isNotEmpty
bool isNotEmpty() const noexcept
Definition juce_StringRef.h:103
juce::StringRef::length
int length() const noexcept
Definition juce_StringRef.h:105
juce::StringRef::text
String::CharPointerType text
Definition juce_StringRef.h:130
juce::StringRef::isEmpty
bool isEmpty() const noexcept
Definition juce_StringRef.h:101
juce::String
Definition juce_String.h:53
juce::String::repeatedString
static String repeatedString(StringRef stringToRepeat, int numberOfTimesToRepeat)
Definition juce_String.cpp:1147
juce::String::indexOfChar
int indexOfChar(juce_wchar characterToLookFor) const noexcept
Definition juce_String.cpp:874
juce::String::length
int length() const noexcept
Definition juce_String.cpp:511
juce::String::endsWithChar
bool endsWithChar(juce_wchar character) const noexcept
Definition juce_String.cpp:1410
juce::String::isEmpty
bool isEmpty() const noexcept
Definition juce_String.h:310
juce::String::toRawUTF8
const char * toRawUTF8() const
Definition juce_String.cpp:2074
juce::String::containsChar
bool containsChar(juce_wchar character) const noexcept
Definition juce_String.cpp:1040
juce::String::removeCharacters
String removeCharacters(StringRef charactersToRemove) const
Definition juce_String.cpp:1757
juce::String::dropLastCharacters
String dropLastCharacters(int numberToDrop) const
Definition juce_String.cpp:1555
juce::String::contains
bool contains(StringRef text) const noexcept
Definition juce_String.cpp:1035
juce::String::trimEnd
String trimEnd() const
Definition juce_String.cpp:1687
juce::String::toHexString
static String toHexString(IntegerType number)
Definition juce_String.h:1097
juce::String::lastIndexOfChar
int lastIndexOfChar(juce_wchar character) const noexcept
Definition juce_String.cpp:899
juce::String::toWideCharPointer
const wchar_t * toWideCharPointer() const
Definition juce_String.cpp:2079
juce::String::replaceCharacter
String replaceCharacter(juce_wchar characterToReplace, juce_wchar characterToInsertInstead) const
Definition juce_String.cpp:1344
juce::String::substring
String substring(int startIndex, int endIndex) const
Definition juce_String.cpp:1498
juce::String::fromFirstOccurrenceOf
String fromFirstOccurrenceOf(StringRef substringToStartFrom, bool includeSubStringInResult, bool ignoreCase) const
Definition juce_String.cpp:1565
juce::TemporaryFile
Definition juce_TemporaryFile.h:65
juce::TemporaryFile::useHiddenFile
@ useHiddenFile
Definition juce_TemporaryFile.h:70
juce::TemporaryFile::overwriteTargetFileWithTemporary
bool overwriteTargetFileWithTemporary() const
Definition juce_TemporaryFile.cpp:93
juce::TemporaryFile::getFile
const File & getFile() const noexcept
Definition juce_TemporaryFile.h:126
juce::Time
Definition juce_Time.h:37
juce::Time::toMilliseconds
int64 toMilliseconds() const noexcept
Definition juce_Time.h:98
juce::UnitTest
Definition juce_UnitTest.h:70