git subrepo clone --branch=sono6good https://github.com/essej/JUCE.git deps/juce

subrepo:
  subdir:   "deps/juce"
  merged:   "b13f9084e"
upstream:
  origin:   "https://github.com/essej/JUCE.git"
  branch:   "sono6good"
  commit:   "b13f9084e"
git-subrepo:
  version:  "0.4.3"
  origin:   "https://github.com/ingydotnet/git-subrepo.git"
  commit:   "2f68596"
This commit is contained in:
essej
2022-04-18 17:51:22 -04:00
parent 63e175fee6
commit 25bd5d8adb
3210 changed files with 1045392 additions and 0 deletions

View File

@ -0,0 +1,439 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - 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
{
static File resolveFilename (const String& name)
{
return File::getCurrentWorkingDirectory().getChildFile (name.unquoted());
}
static File checkFileExists (const File& f)
{
if (! f.exists())
ConsoleApplication::fail ("Could not find file: " + f.getFullPathName());
return f;
}
static File checkFolderExists (const File& f)
{
if (! f.isDirectory())
ConsoleApplication::fail ("Could not find folder: " + f.getFullPathName());
return f;
}
static File resolveFilenameForOption (const ArgumentList& args, StringRef option, const String& filename)
{
if (filename.isEmpty())
{
args.failIfOptionIsMissing (option);
ConsoleApplication::fail ("Expected a filename after the " + option + " option");
}
return resolveFilename (filename);
}
File ArgumentList::Argument::resolveAsFile() const
{
return resolveFilename (text);
}
File ArgumentList::Argument::resolveAsExistingFile() const
{
return checkFileExists (resolveAsFile());
}
File ArgumentList::Argument::resolveAsExistingFolder() const
{
auto f = resolveAsFile();
if (! f.isDirectory())
ConsoleApplication::fail ("Could not find folder: " + f.getFullPathName());
return f;
}
static bool isShortOptionFormat (StringRef s) { return s[0] == '-' && s[1] != '-'; }
static bool isLongOptionFormat (StringRef s) { return s[0] == '-' && s[1] == '-' && s[2] != '-'; }
static bool isOptionFormat (StringRef s) { return s[0] == '-'; }
bool ArgumentList::Argument::isLongOption() const { return isLongOptionFormat (text); }
bool ArgumentList::Argument::isShortOption() const { return isShortOptionFormat (text); }
bool ArgumentList::Argument::isOption() const { return isOptionFormat (text); }
bool ArgumentList::Argument::isLongOption (const String& option) const
{
if (! isLongOptionFormat (option))
{
jassert (! isShortOptionFormat (option)); // this will always fail to match
return isLongOption ("--" + option);
}
return text.upToFirstOccurrenceOf ("=", false, false) == option;
}
String ArgumentList::Argument::getLongOptionValue() const
{
if (isLongOption())
{
auto equalsIndex = text.indexOfChar ('=');
if (equalsIndex > 0)
return text.substring (equalsIndex + 1);
}
return {};
}
bool ArgumentList::Argument::isShortOption (char option) const
{
jassert (option != '-'); // this is probably not what you intended to pass in
return isShortOption() && text.containsChar (String (option)[0]);
}
bool ArgumentList::Argument::operator== (StringRef wildcard) const
{
for (auto& o : StringArray::fromTokens (wildcard, "|", {}))
{
if (text == o)
return true;
if (isShortOptionFormat (o) && o.length() == 2 && isShortOption ((char) o[1]))
return true;
if (isLongOptionFormat (o) && isLongOption (o))
return true;
}
return false;
}
bool ArgumentList::Argument::operator!= (StringRef s) const { return ! operator== (s); }
//==============================================================================
ArgumentList::ArgumentList (String exeName, StringArray args)
: executableName (std::move (exeName))
{
args.trim();
args.removeEmptyStrings();
for (auto& a : args)
arguments.add ({ a.unquoted() });
}
ArgumentList::ArgumentList (int argc, char* argv[])
: ArgumentList (argv[0], StringArray (argv + 1, argc - 1))
{
}
ArgumentList::ArgumentList (const String& exeName, const String& args)
: ArgumentList (exeName, StringArray::fromTokens (args, true))
{
}
int ArgumentList::size() const { return arguments.size(); }
ArgumentList::Argument ArgumentList::operator[] (int index) const { return arguments[index]; }
void ArgumentList::checkMinNumArguments (int expectedMinNumberOfArgs) const
{
if (size() < expectedMinNumberOfArgs)
ConsoleApplication::fail ("Not enough arguments!");
}
int ArgumentList::indexOfOption (StringRef option) const
{
jassert (option == String (option).trim()); // passing non-trimmed strings will always fail to find a match!
for (int i = 0; i < arguments.size(); ++i)
if (arguments.getReference (i) == option)
return i;
return -1;
}
bool ArgumentList::containsOption (StringRef option) const
{
return indexOfOption (option) >= 0;
}
bool ArgumentList::removeOptionIfFound (StringRef option)
{
auto i = indexOfOption (option);
if (i >= 0)
arguments.remove (i);
return i >= 0;
}
void ArgumentList::failIfOptionIsMissing (StringRef option) const
{
if (indexOfOption (option) < 0)
ConsoleApplication::fail ("Expected the option " + option);
}
String ArgumentList::getValueForOption (StringRef option) const
{
jassert (isOptionFormat (option)); // the thing you're searching for must be an option
for (int i = 0; i < arguments.size(); ++i)
{
auto& arg = arguments.getReference(i);
if (arg == option)
{
if (arg.isShortOption())
{
if (i < arguments.size() - 1 && ! arguments.getReference (i + 1).isOption())
return arguments.getReference (i + 1).text;
return {};
}
if (arg.isLongOption())
return arg.getLongOptionValue();
}
}
return {};
}
String ArgumentList::removeValueForOption (StringRef option)
{
jassert (isOptionFormat (option)); // the thing you're searching for must be an option
for (int i = 0; i < arguments.size(); ++i)
{
auto& arg = arguments.getReference(i);
if (arg == option)
{
if (arg.isShortOption())
{
if (i < arguments.size() - 1 && ! arguments.getReference (i + 1).isOption())
{
auto result = arguments.getReference (i + 1).text;
arguments.removeRange (i, 2);
return result;
}
arguments.remove (i);
return {};
}
if (arg.isLongOption())
{
auto result = arg.getLongOptionValue();
arguments.remove (i);
return result;
}
}
}
return {};
}
File ArgumentList::getFileForOption (StringRef option) const
{
return resolveFilenameForOption (*this, option, getValueForOption (option));
}
File ArgumentList::getFileForOptionAndRemove (StringRef option)
{
return resolveFilenameForOption (*this, option, removeValueForOption (option));
}
File ArgumentList::getExistingFileForOption (StringRef option) const
{
return checkFileExists (getFileForOption (option));
}
File ArgumentList::getExistingFileForOptionAndRemove (StringRef option)
{
return checkFileExists (getFileForOptionAndRemove (option));
}
File ArgumentList::getExistingFolderForOption (StringRef option) const
{
return checkFolderExists (getFileForOption (option));
}
File ArgumentList::getExistingFolderForOptionAndRemove (StringRef option)
{
return checkFolderExists (getFileForOptionAndRemove (option));
}
//==============================================================================
struct ConsoleAppFailureCode
{
String errorMessage;
int returnCode;
};
void ConsoleApplication::fail (String errorMessage, int returnCode)
{
throw ConsoleAppFailureCode { std::move (errorMessage), returnCode };
}
int ConsoleApplication::invokeCatchingFailures (std::function<int()>&& f)
{
int returnCode = 0;
try
{
returnCode = f();
}
catch (const ConsoleAppFailureCode& error)
{
std::cerr << error.errorMessage << std::endl;
returnCode = error.returnCode;
}
return returnCode;
}
const ConsoleApplication::Command* ConsoleApplication::findCommand (const ArgumentList& args, bool optionMustBeFirstArg) const
{
for (auto& c : commands)
{
auto index = args.indexOfOption (c.commandOption);
if (optionMustBeFirstArg ? (index == 0) : (index >= 0))
return &c;
}
if (commandIfNoOthersRecognised >= 0)
return &commands[(size_t) commandIfNoOthersRecognised];
return {};
}
int ConsoleApplication::findAndRunCommand (const ArgumentList& args, bool optionMustBeFirstArg) const
{
return invokeCatchingFailures ([&args, optionMustBeFirstArg, this]
{
if (auto c = findCommand (args, optionMustBeFirstArg))
c->command (args);
else
fail ("Unrecognised arguments");
return 0;
});
}
int ConsoleApplication::findAndRunCommand (int argc, char* argv[]) const
{
return findAndRunCommand (ArgumentList (argc, argv));
}
void ConsoleApplication::addCommand (Command c)
{
commands.emplace_back (std::move (c));
}
void ConsoleApplication::addDefaultCommand (Command c)
{
commandIfNoOthersRecognised = (int) commands.size();
addCommand (std::move (c));
}
void ConsoleApplication::addHelpCommand (String arg, String helpMessage, bool makeDefaultCommand)
{
Command c { arg, arg, "Prints the list of commands", {},
[this, helpMessage] (const ArgumentList& args)
{
std::cout << helpMessage << std::endl;
printCommandList (args);
}};
if (makeDefaultCommand)
addDefaultCommand (std::move (c));
else
addCommand (std::move (c));
}
void ConsoleApplication::addVersionCommand (String arg, String versionText)
{
addCommand ({ arg, arg, "Prints the current version number", {},
[versionText] (const ArgumentList&)
{
std::cout << versionText << std::endl;
}});
}
const std::vector<ConsoleApplication::Command>& ConsoleApplication::getCommands() const
{
return commands;
}
static String getExeNameAndArgs (const ArgumentList& args, const ConsoleApplication::Command& command)
{
auto exeName = args.executableName.fromLastOccurrenceOf ("/", false, false)
.fromLastOccurrenceOf ("\\", false, false);
return " " + exeName + " " + command.argumentDescription;
}
static void printCommandDescription (const ArgumentList& args, const ConsoleApplication::Command& command,
int descriptionIndent)
{
auto nameAndArgs = getExeNameAndArgs (args, command);
if (nameAndArgs.length() > descriptionIndent)
std::cout << nameAndArgs << std::endl << String().paddedRight (' ', descriptionIndent);
else
std::cout << nameAndArgs.paddedRight (' ', descriptionIndent);
std::cout << command.shortDescription << std::endl;
}
void ConsoleApplication::printCommandList (const ArgumentList& args) const
{
int descriptionIndent = 0;
for (auto& c : commands)
descriptionIndent = std::max (descriptionIndent, getExeNameAndArgs (args, c).length());
descriptionIndent = std::min (descriptionIndent + 2, 40);
for (auto& c : commands)
printCommandDescription (args, c, descriptionIndent);
std::cout << std::endl;
}
void ConsoleApplication::printCommandDetails (const ArgumentList& args, const Command& command) const
{
auto len = getExeNameAndArgs (args, command).length();
printCommandDescription (args, command, std::min (len + 3, 40));
if (command.longDescription.isNotEmpty())
std::cout << std::endl << command.longDescription << std::endl;
}
} // namespace juce

View File

@ -0,0 +1,353 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - 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
{
//==============================================================================
/**
Holds a list of command-line arguments, and provides useful methods for searching
and operating on them.
You can create an ArgumentList manually, or give it some argv/argc values from a
main() function to parse.
@see ConsoleApplication
@tags{Core}
*/
struct ArgumentList
{
/** Creates an argument list for a given executable. */
ArgumentList (String executable, StringArray arguments);
/** Parses a standard argv/argc pair to create an argument list. */
ArgumentList (int argc, char* argv[]);
/** Tokenises a string containing all the arguments to create an argument list. */
ArgumentList (const String& executable, const String& arguments);
ArgumentList (const ArgumentList&) = default;
ArgumentList& operator= (const ArgumentList&) = default;
//==============================================================================
/**
One of the arguments in an ArgumentList.
@tags{Core}
*/
struct Argument
{
/** The original text of this argument. */
String text;
/** Resolves this argument as an absolute File, using the current working
directory as a base for resolving relative paths, and stripping quotes, etc.
*/
File resolveAsFile() const;
/** Resolves this argument as an absolute File, using the current working
directory as a base for resolving relative paths, and also doing a check to
make sure the file exists.
If the file doesn't exist, this will call fail() with a suitable error.
@see resolveAsFile, resolveAsExistingFolder
*/
File resolveAsExistingFile() const;
/** Resolves a user-supplied folder name into an absolute File, using the current working
directory as a base for resolving relative paths, and also doing a check to make
sure the folder exists.
If the folder doesn't exist, this will call fail() with a suitable error.
@see resolveAsFile, resolveAsExistingFile
*/
File resolveAsExistingFolder() const;
/** Returns true if this argument starts with a double dash. */
bool isLongOption() const;
/** Returns true if this argument starts with a single dash. */
bool isShortOption() const;
/** Returns true if this argument starts with a double dash, followed by the given string. */
bool isLongOption (const String& optionRoot) const;
/** If this argument is a long option with a value, this returns the value.
e.g. for "--foo=bar", this would return 'bar'.
*/
String getLongOptionValue() const;
/** Returns true if this argument starts with a single dash and then contains the given character somewhere inside it. */
bool isShortOption (char shortOptionCharacter) const;
/** Returns true if this argument starts with one or more dashes. */
bool isOption() const;
/** Compares this argument against a string.
The string may be a pipe-separated list of options, e.g. "--help|-h"
*/
bool operator== (StringRef stringToCompare) const;
/** Compares this argument against a string.
The string may be a pipe-separated list of options, e.g. "--help|-h"
*/
bool operator!= (StringRef stringToCompare) const;
};
//==============================================================================
/** Returns the number of arguments in the list. */
int size() const;
/** Returns one of the arguments */
Argument operator[] (int index) const;
/** Throws an error unless there are at least the given number of arguments. */
void checkMinNumArguments (int expectedMinNumberOfArgs) const;
/** Returns true if the given string matches one of the arguments.
The option can also be a list of different versions separated by pipes, e.g. "--help|-h"
@see removeOptionIfFound
*/
bool containsOption (StringRef option) const;
/** Returns true if the given string matches one of the arguments, and also removes the
argument from the list if found.
The option can also be a list of different versions separated by pipes, e.g. "--help|-h"
@see containsOption
*/
bool removeOptionIfFound (StringRef option);
/** Returns the index of the given string if it matches one of the arguments, or -1 if it doesn't.
The option can also be a list of different versions separated by pipes, e.g. "--help|-h"
*/
int indexOfOption (StringRef option) const;
/** Throws an error unless the given option is found in the argument list. */
void failIfOptionIsMissing (StringRef option) const;
/** Looks for a given argument and returns either its assigned value (for long options) or the
string that follows it (for short options).
The option can also be a list of different versions separated by pipes, e.g. "--help|-h"
If it finds a long option, it will look for an assignment with a '=' sign, e.g. "--file=foo.txt",
and will return the string following the '='. If there's no '=', it will return an empty string.
If it finds a short option, it will attempt to return the argument that follows it, unless
it's another option.
If the argument isn't found, this returns an empty string.
*/
String getValueForOption (StringRef option) const;
/** Looks for a given argument and returns either its assigned value (for long options) or the
string that follows it (for short options).
This works like getValueForOption() but also removes the option argument (and any value arguments)
from the list if they are found.
*/
String removeValueForOption (StringRef option);
/** Looks for the value of argument using getValueForOption() and tries to parse that value as a file.
If the option isn't found, or if the value can't be parsed as a filename, it will throw an error.
*/
File getFileForOption (StringRef option) const;
/** Looks for the value of argument using getValueForOption() and tries to parse that value as a file.
This works like getFileForOption() but also removes the option argument (and any value arguments)
from the list if they are found.
*/
File getFileForOptionAndRemove (StringRef option);
/** Looks for a file argument using getFileForOption() and fails with a suitable error if
the file doesn't exist.
*/
File getExistingFileForOption (StringRef option) const;
/** Looks for a file argument using getFileForOption() and fails with a suitable error if
the file doesn't exist.
This works like getExistingFileForOption() but also removes the option argument (and any
value arguments) from the list if they are found.
*/
File getExistingFileForOptionAndRemove (StringRef option);
/** Looks for a filename argument using getFileForOption() and fails with a suitable error if
the file isn't a folder that exists.
*/
File getExistingFolderForOption (StringRef option) const;
/** Looks for a filename argument using getFileForOption() and fails with a suitable error if
the file isn't a folder that exists.
This works like getExistingFolderForOption() but also removes the option argument (and any
value arguments) from the list if they are found.
*/
File getExistingFolderForOptionAndRemove (StringRef option);
/** The name or path of the executable that was invoked, as it was specified on the command-line. */
String executableName;
/** The list of arguments (not including the name of the executable that was invoked). */
Array<Argument> arguments;
};
//==============================================================================
/**
Represents a the set of commands that a console app can perform, and provides
helper functions for performing them.
When using these helper classes to implement a console app, you probably want to
do something along these lines:
@code
int main (int argc, char* argv[])
{
ConsoleApplication app;
app.addHelpCommand ("--help|-h", "Usage:", true);
app.addVersionCommand ("--version|-v", "MyApp version 1.2.3");
app.addCommand ({ "--foo",
"--foo filename",
"Performs a foo operation on the given file",
[] (const auto& args) { doFoo (args); }});
return app.findAndRunCommand (argc, argv);
}
@endcode
@see ArgumentList
@tags{Core}
*/
struct ConsoleApplication
{
//==============================================================================
/**
Represents a command that can be executed if its command-line arguments are matched.
@see ConsoleApplication::addCommand(), ConsoleApplication::findAndRunCommand()
@tags{Core}
*/
struct Command
{
/** The option string that must appear in the argument list for this command to be invoked.
This can also be a list of different versions separated by pipes, e.g. "--help|-h"
*/
String commandOption;
/** A description of the command-line arguments needed for this command, which will be
printed as part of the help text.
*/
String argumentDescription;
/** A short (one line) description of this command, which can be printed by
ConsoleApplication::printCommandList().
*/
String shortDescription;
/** A longer description of this command, for use in extended help. */
String longDescription;
/** The actual command that should be invoked to perform this action. */
std::function<void (const ArgumentList&)> command;
};
//==============================================================================
/** Adds a command to the list. */
void addCommand (Command);
/** Adds a command to the list, and marks it as one which is invoked if no other
command matches.
*/
void addDefaultCommand (Command);
/** Adds a command that will print the given text in response to the "--version" option. */
void addVersionCommand (String versionArgument, String versionText);
/** Adds a help command to the list.
This command will print the user-supplied message that's passed in here as an
argument, followed by a list of all the registered commands.
*/
void addHelpCommand (String helpArgument, String helpMessage, bool makeDefaultCommand);
/** Prints out the list of commands and their short descriptions in a format that's
suitable for use as help.
*/
void printCommandList (const ArgumentList&) const;
/** Prints out a longer description of a particular command, based on its
longDescription member.
*/
void printCommandDetails (const ArgumentList&, const Command&) const;
//==============================================================================
/** Throws a failure exception to cause a command-line app to terminate.
This is intended to be called from code in a Command, so that the
exception will be automatically caught and turned into a printed error message
and a return code which will be returned from main().
@see ConsoleApplication::invokeCatchingFailures()
*/
static void fail (String errorMessage, int returnCode = 1);
/** Invokes a function, catching any fail() calls that it might trigger, and handling
them by printing their error message and returning their error code.
@see ConsoleApplication::fail()
*/
static int invokeCatchingFailures (std::function<int()>&& functionToCall);
//==============================================================================
/** Looks for the first command in the list which matches the given arguments, and
tries to invoke it.
If no command is found, and if there is no default command to run, it fails with
a suitable error message.
If the command calls the fail() function, this will throw an exception that gets
automatically caught and handled, and this method will return the error code that
was passed into the fail() call.
If optionMustBeFirstArg is true, then only the first argument will be looked at
when searching the available commands - this lets you do 'git' style commands where
the executable name is followed by a verb.
*/
int findAndRunCommand (const ArgumentList&,
bool optionMustBeFirstArg = false) const;
/** Creates an ArgumentList object from the argc and argv variablrs, and invokes
findAndRunCommand() using it.
*/
int findAndRunCommand (int argc, char* argv[]) const;
/** Looks for the first command in the list which matches the given arguments.
If none is found, this returns either the default command (if one is set)
or nullptr.
If optionMustBeFirstArg is true, then only the first argument will be looked at
when searching the available commands - this lets you do 'git' style commands where
the executable name is followed by a verb.
*/
const Command* findCommand (const ArgumentList&, bool optionMustBeFirstArg) const;
/** Gives read-only access to the list of registered commands. */
const std::vector<Command>& getCommands() const;
private:
//==============================================================================
std::vector<Command> commands;
int commandIfNoOthersRecognised = -1;
};
} // namespace juce

View File

@ -0,0 +1,53 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - 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
{
/** Some helper methods for checking a callable object before invoking with
the specified arguments.
If the object is a std::function it will check for nullptr before
calling. For a callable object it will invoke the function call operator.
@tags{Core}
*/
struct NullCheckedInvocation
{
template <typename... Signature, typename... Args>
static void invoke (std::function<Signature...>&& fn, Args&&... args)
{
if (fn != nullptr)
fn (std::forward<Args> (args)...);
}
template <typename Callable, typename... Args>
static void invoke (Callable&& fn, Args&&... args)
{
fn (std::forward<Args> (args)...);
}
template <typename... Args>
static void invoke (std::nullptr_t, Args&&...) {}
};
} // namespace juce

View File

@ -0,0 +1,80 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - 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
{
Result::Result() noexcept {}
Result::Result (const String& message) noexcept
: errorMessage (message)
{
}
Result::Result (const Result& other)
: errorMessage (other.errorMessage)
{
}
Result& Result::operator= (const Result& other)
{
errorMessage = other.errorMessage;
return *this;
}
Result::Result (Result&& other) noexcept
: errorMessage (std::move (other.errorMessage))
{
}
Result& Result::operator= (Result&& other) noexcept
{
errorMessage = std::move (other.errorMessage);
return *this;
}
bool Result::operator== (const Result& other) const noexcept
{
return errorMessage == other.errorMessage;
}
bool Result::operator!= (const Result& other) const noexcept
{
return errorMessage != other.errorMessage;
}
Result Result::fail (const String& errorMessage) noexcept
{
return Result (errorMessage.isEmpty() ? "Unknown Error" : errorMessage);
}
const String& Result::getErrorMessage() const noexcept
{
return errorMessage;
}
bool Result::wasOk() const noexcept { return errorMessage.isEmpty(); }
Result::operator bool() const noexcept { return errorMessage.isEmpty(); }
bool Result::failed() const noexcept { return errorMessage.isNotEmpty(); }
bool Result::operator!() const noexcept { return errorMessage.isNotEmpty(); }
} // namespace juce

View File

@ -0,0 +1,116 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - 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
{
//==============================================================================
/**
Represents the 'success' or 'failure' of an operation, and holds an associated
error message to describe the error when there's a failure.
E.g.
@code
Result myOperation()
{
if (doSomeKindOfFoobar())
return Result::ok();
else
return Result::fail ("foobar didn't work!");
}
const Result result (myOperation());
if (result.wasOk())
{
...it's all good...
}
else
{
warnUserAboutFailure ("The foobar operation failed! Error message was: "
+ result.getErrorMessage());
}
@endcode
@tags{Core}
*/
class JUCE_API Result
{
public:
//==============================================================================
/** Creates and returns a 'successful' result. */
static Result ok() noexcept { return Result(); }
/** Creates a 'failure' result.
If you pass a blank error message in here, a default "Unknown Error" message
will be used instead.
*/
static Result fail (const String& errorMessage) noexcept;
//==============================================================================
/** Returns true if this result indicates a success. */
bool wasOk() const noexcept;
/** Returns true if this result indicates a failure.
You can use getErrorMessage() to retrieve the error message associated
with the failure.
*/
bool failed() const noexcept;
/** Returns true if this result indicates a success.
This is equivalent to calling wasOk().
*/
operator bool() const noexcept;
/** Returns true if this result indicates a failure.
This is equivalent to calling failed().
*/
bool operator!() const noexcept;
/** Returns the error message that was set when this result was created.
For a successful result, this will be an empty string;
*/
const String& getErrorMessage() const noexcept;
//==============================================================================
Result (const Result&);
Result& operator= (const Result&);
Result (Result&&) noexcept;
Result& operator= (Result&&) noexcept;
bool operator== (const Result& other) const noexcept;
bool operator!= (const Result& other) const noexcept;
private:
String errorMessage;
// The default constructor is not for public use!
// Instead, use Result::ok() or Result::fail()
Result() noexcept;
explicit Result (const String&) noexcept;
// These casts are private to prevent people trying to use the Result object in numeric contexts
operator int() const;
operator void*() const;
};
} // namespace juce

View File

@ -0,0 +1,36 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - 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
{
#if ! JUCE_ANDROID // We currently don't request runtime permissions on any other platform
// than Android, so this file contains a dummy implementation for those.
// This may change in the future.
void RuntimePermissions::request (PermissionID, Callback callback) { callback (true); }
bool RuntimePermissions::isRequired (PermissionID) { return false; }
bool RuntimePermissions::isGranted (PermissionID) { return true; }
#endif
} // namespace juce

View File

@ -0,0 +1,131 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - 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
{
//==============================================================================
/**
Class to handle app runtime permissions for certain functionality on some platforms.
The use of this class is currently only required if the app should run on
Android API level 23 and higher.
On lower API levels, the permissions are specified in the app manifest. On iOS,
runtime permission requests are handled automatically by the Apple APIs and not
manually in the app code. On Windows, OS X, and Linux, runtime permissions are not
used at all. In all these cases, request() will simply call through to the
callback with no overhead and pass true (making it safe to use on all platforms).
For example, to enable audio recording on Android in your cross-platform app,
you could modify your code as follows:
Old code:
audioDeviceManager.initialise (2, 2, nullptr, true, String(), nullptr);
New code:
RuntimePermissions::request (
RuntimePermissions::audioRecording,
[this] (bool wasGranted)
{
if (! wasGranted)
{
// e.g. display an error or initialise with 0 input channels
return;
}
audioDeviceManager.initialise (2, 2, nullptr, true, String(), nullptr);
}
);
@tags{Core}
*/
class JUCE_API RuntimePermissions
{
public:
//==============================================================================
enum PermissionID
{
/** Permission to access the microphone (required on Android).
You need to request this, for example, to initialise an AudioDeviceManager with
a non-zero number of input channels, and to open the default audio input device.
*/
recordAudio = 1,
/** Permission to scan for and pair to Bluetooth MIDI devices (required on Android).
You need to request this before calling BluetoothMidiDevicePairingDialogue::open(),
otherwise no devices will be found.
*/
bluetoothMidi = 2,
/** Permission to read from external storage such as SD cards */
readExternalStorage = 3,
/** Permission to write to external storage such as SD cards */
writeExternalStorage = 4,
/** Permission to use camera */
camera = 5
};
//==============================================================================
/** Function type of runtime permission request callbacks. */
using Callback = std::function<void (bool)>;
//==============================================================================
/** Call this method to request a runtime permission.
@param permission The PermissionID of the permission you want to request.
@param callback The callback to be called after the request has been granted
or denied; the argument passed will be true if the permission
has been granted and false otherwise.
If no runtime request is required or possible to obtain the permission, the
callback will be called immediately. The argument passed in will be true
if the permission is granted or no permission is required on this platform,
and false otherwise.
If a runtime request is required to obtain the permission, the callback
will be called asynchronously after the OS has granted or denied the requested
permission (typically by displaying a dialog box to the user and waiting until
the user has responded).
*/
static void request (PermissionID permission, Callback callback);
/** Returns whether a runtime request is required to obtain the permission
on the current platform.
*/
static bool isRequired (PermissionID permission);
/** Returns true if the app has been already granted this permission, either
via a previous runtime request or otherwise, or no permission is necessary.
Note that this can be false even if isRequired returns false. In this case,
the permission can not be obtained at all at runtime.
*/
static bool isGranted (PermissionID permission);
};
} // namespace juce

View File

@ -0,0 +1,147 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - 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
{
Uuid::Uuid()
{
Random r;
for (size_t i = 0; i < sizeof (uuid); ++i)
uuid[i] = (uint8) (r.nextInt (256));
// To make it RFC 4122 compliant, need to force a few bits...
uuid[6] = (uuid[6] & 0x0f) | 0x40;
uuid[8] = (uuid[8] & 0x3f) | 0x80;
}
Uuid::~Uuid() noexcept {}
Uuid::Uuid (const Uuid& other) noexcept
{
memcpy (uuid, other.uuid, sizeof (uuid));
}
Uuid& Uuid::operator= (const Uuid& other) noexcept
{
memcpy (uuid, other.uuid, sizeof (uuid));
return *this;
}
bool Uuid::operator== (const Uuid& other) const noexcept { return memcmp (uuid, other.uuid, sizeof (uuid)) == 0; }
bool Uuid::operator!= (const Uuid& other) const noexcept { return ! operator== (other); }
bool Uuid::operator< (const Uuid& other) const noexcept { return compare (other) < 0; }
bool Uuid::operator> (const Uuid& other) const noexcept { return compare (other) > 0; }
bool Uuid::operator<= (const Uuid& other) const noexcept { return compare (other) <= 0; }
bool Uuid::operator>= (const Uuid& other) const noexcept { return compare (other) >= 0; }
int Uuid::compare (Uuid other) const noexcept
{
for (size_t i = 0; i < sizeof (uuid); ++i)
if (int diff = uuid[i] - (int) other.uuid[i])
return diff > 0 ? 1 : -1;
return 0;
}
Uuid Uuid::null() noexcept
{
return Uuid ((const uint8*) nullptr);
}
bool Uuid::isNull() const noexcept
{
for (auto i : uuid)
if (i != 0)
return false;
return true;
}
String Uuid::getHexRegion (int start, int length) const
{
return String::toHexString (uuid + start, length, 0);
}
String Uuid::toString() const
{
return getHexRegion (0, 16);
}
String Uuid::toDashedString() const
{
return getHexRegion (0, 4)
+ "-" + getHexRegion (4, 2)
+ "-" + getHexRegion (6, 2)
+ "-" + getHexRegion (8, 2)
+ "-" + getHexRegion (10, 6);
}
Uuid::Uuid (const String& uuidString)
{
operator= (uuidString);
}
Uuid& Uuid::operator= (const String& uuidString)
{
MemoryBlock mb;
mb.loadFromHexString (uuidString);
mb.ensureSize (sizeof (uuid), true);
mb.copyTo (uuid, 0, sizeof (uuid));
return *this;
}
Uuid::Uuid (const uint8* const rawData) noexcept
{
operator= (rawData);
}
Uuid& Uuid::operator= (const uint8* const rawData) noexcept
{
if (rawData != nullptr)
memcpy (uuid, rawData, sizeof (uuid));
else
zeromem (uuid, sizeof (uuid));
return *this;
}
uint32 Uuid::getTimeLow() const noexcept { return ByteOrder::bigEndianInt (uuid); }
uint16 Uuid::getTimeMid() const noexcept { return ByteOrder::bigEndianShort (uuid + 4); }
uint16 Uuid::getTimeHighAndVersion() const noexcept { return ByteOrder::bigEndianShort (uuid + 6); }
uint8 Uuid::getClockSeqAndReserved() const noexcept { return uuid[8]; }
uint8 Uuid::getClockSeqLow() const noexcept { return uuid[9]; }
uint64 Uuid::getNode() const noexcept { return (((uint64) ByteOrder::bigEndianShort (uuid + 10)) << 32) + ByteOrder::bigEndianInt (uuid + 12); }
uint64 Uuid::hash() const noexcept
{
uint64 result = 0;
for (auto n : uuid)
result = ((uint64) 101) * result + n;
return result;
}
} // namespace juce

View File

@ -0,0 +1,147 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - 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
{
//==============================================================================
/**
A universally unique 128-bit identifier.
This class generates very random unique numbers. It's vanishingly unlikely
that two identical UUIDs would ever be created by chance. The values are
formatted to meet the RFC 4122 version 4 standard.
The class includes methods for saving the ID as a string or as raw binary data.
@tags{Core}
*/
class JUCE_API Uuid
{
public:
//==============================================================================
/** Creates a new unique ID, compliant with RFC 4122 version 4. */
Uuid();
/** Destructor. */
~Uuid() noexcept;
/** Creates a copy of another UUID. */
Uuid (const Uuid&) noexcept;
/** Copies another UUID. */
Uuid& operator= (const Uuid&) noexcept;
//==============================================================================
/** Returns true if the ID is zero. */
bool isNull() const noexcept;
/** Returns a null Uuid object. */
static Uuid null() noexcept;
bool operator== (const Uuid&) const noexcept;
bool operator!= (const Uuid&) const noexcept;
bool operator< (const Uuid&) const noexcept;
bool operator> (const Uuid&) const noexcept;
bool operator<= (const Uuid&) const noexcept;
bool operator>= (const Uuid&) const noexcept;
//==============================================================================
/** Returns a stringified version of this UUID.
A Uuid object can later be reconstructed from this string using operator= or
the constructor that takes a string parameter.
@returns a 32 character hex string.
*/
String toString() const;
/** Returns a stringified version of this UUID, separating it into sections with dashes.
@returns a string in the format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
*/
String toDashedString() const;
/** Creates an ID from an encoded string version.
@see toString
*/
Uuid (const String& uuidString);
/** Copies from a stringified UUID.
The string passed in should be one that was created with the toString() method.
*/
Uuid& operator= (const String& uuidString);
//==============================================================================
/** Returns the time-low section of the UUID. */
uint32 getTimeLow() const noexcept;
/** Returns the time-mid section of the UUID. */
uint16 getTimeMid() const noexcept;
/** Returns the time-high-and-version section of the UUID. */
uint16 getTimeHighAndVersion() const noexcept;
/** Returns the clock-seq-and-reserved section of the UUID. */
uint8 getClockSeqAndReserved() const noexcept;
/** Returns the clock-seq-low section of the UUID. */
uint8 getClockSeqLow() const noexcept;
/** Returns the node section of the UUID. */
uint64 getNode() const noexcept;
/** Returns a hash of the UUID. */
uint64 hash() const noexcept;
//==============================================================================
/** Returns a pointer to the internal binary representation of the ID.
This is an array of 16 bytes. To reconstruct a Uuid from its data, use
the constructor or operator= method that takes an array of uint8s.
*/
const uint8* getRawData() const noexcept { return uuid; }
/** Creates a UUID from a 16-byte array.
@see getRawData
*/
Uuid (const uint8* rawData) noexcept;
/** Sets this UUID from 16-bytes of raw data. */
Uuid& operator= (const uint8* rawData) noexcept;
private:
//==============================================================================
uint8 uuid[16];
String getHexRegion (int, int) const;
int compare (Uuid) const noexcept;
JUCE_LEAK_DETECTOR (Uuid)
};
} // namespace juce
#ifndef DOXYGEN
namespace std
{
template <> struct hash<juce::Uuid>
{
size_t operator() (const juce::Uuid& u) const noexcept { return (size_t) u.hash(); }
};
}
#endif

View File

@ -0,0 +1,140 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - 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
{
#if JUCE_WINDOWS || DOXYGEN
/**
Contains some static helper functions for manipulating the MS Windows registry
(Only available on Windows, of course!)
@tags{Core}
*/
class JUCE_API WindowsRegistry
{
public:
/** These values can be used to specify whether the 32- or 64-bit registry should be used.
When running on a 32-bit OS, there is no 64-bit registry, so the mode will be ignored.
*/
enum WoW64Mode
{
/** Default handling: 32-bit apps will use the 32-bit registry, and 64-bit apps
will use the 64-bit registry. */
WoW64_Default = 0,
/** Always use the 64-bit registry store. (KEY_WOW64_64KEY). */
WoW64_64bit = 0x100,
/** Always use the 32-bit registry store. (KEY_WOW64_32KEY). */
WoW64_32bit = 0x200
};
//==============================================================================
/** Returns a string from the registry.
The path is a string for the entire path of a value in the registry,
e.g. "HKEY_CURRENT_USER\Software\foo\bar"
*/
static String JUCE_CALLTYPE getValue (const String& regValuePath,
const String& defaultValue = String(),
WoW64Mode mode = WoW64_Default);
/** Reads a binary block from the registry.
The path is a string for the entire path of a value in the registry,
e.g. "HKEY_CURRENT_USER\Software\foo\bar"
@returns a DWORD indicating the type of the key.
*/
static uint32 JUCE_CALLTYPE getBinaryValue (const String& regValuePath, MemoryBlock& resultData, WoW64Mode mode = WoW64_Default);
/** Sets a registry value as a string.
This will take care of creating any groups needed to get to the given registry value.
*/
static bool JUCE_CALLTYPE setValue (const String& regValuePath, const String& value, WoW64Mode mode = WoW64_Default);
/** Sets a registry value as a DWORD.
This will take care of creating any groups needed to get to the given registry value.
*/
static bool JUCE_CALLTYPE setValue (const String& regValuePath, uint32 value, WoW64Mode mode = WoW64_Default);
/** Sets a registry value as a QWORD.
This will take care of creating any groups needed to get to the given registry value.
*/
static bool JUCE_CALLTYPE setValue (const String& regValuePath, uint64 value, WoW64Mode mode = WoW64_Default);
/** Sets a registry value as a binary block.
This will take care of creating any groups needed to get to the given registry value.
*/
static bool JUCE_CALLTYPE setValue (const String& regValuePath, const MemoryBlock& value, WoW64Mode mode = WoW64_Default);
/** Returns true if the given value exists in the registry. */
static bool JUCE_CALLTYPE valueExists (const String& regValuePath, WoW64Mode mode = WoW64_Default);
/** Returns true if the given key exists in the registry. */
static bool JUCE_CALLTYPE keyExists (const String& regKeyPath, WoW64Mode mode = WoW64_Default);
/** Deletes a registry value. */
static bool JUCE_CALLTYPE deleteValue (const String& regValuePath, WoW64Mode mode = WoW64_Default);
/** Deletes a registry key (which is registry-talk for 'folder'). */
static bool JUCE_CALLTYPE deleteKey (const String& regKeyPath, WoW64Mode mode = WoW64_Default);
/** Creates a file association in the registry.
This lets you set the executable that should be launched by a given file extension.
@param fileExtension the file extension to associate, including the
initial dot, e.g. ".txt"
@param symbolicDescription a space-free short token to identify the file type
@param fullDescription a human-readable description of the file type
@param targetExecutable the executable that should be launched
@param iconResourceNumber the icon that gets displayed for the file type will be
found by looking up this resource number in the
executable. Pass 0 here to not use an icon
@param registerForCurrentUserOnly if false, this will try to register the association
for all users (you might not have permission to do this
unless running in an installer). If true, it will register the
association in HKEY_CURRENT_USER.
@param mode the WoW64 mode to use for choosing the database
*/
static bool JUCE_CALLTYPE registerFileAssociation (const String& fileExtension,
const String& symbolicDescription,
const String& fullDescription,
const File& targetExecutable,
int iconResourceNumber,
bool registerForCurrentUserOnly,
WoW64Mode mode = WoW64_Default);
#ifndef DOXYGEN
// DEPRECATED: use the other methods with a WoW64Mode parameter of WoW64_64bit instead.
[[deprecated]] static String getValueWow64 (const String&, const String& defaultValue = String());
[[deprecated]] static bool valueExistsWow64 (const String&);
[[deprecated]] static bool keyExistsWow64 (const String&);
#endif
private:
WindowsRegistry() = delete;
JUCE_DECLARE_NON_COPYABLE (WindowsRegistry)
};
#endif
} // namespace juce