upgrade to JUCE 5.4.3. Remove (probably) unused JUCE modules. Remove VST2 target (it's been end-of-life'd by Steinberg and by JUCE)
This commit is contained in:
356
modules/juce_core/misc/juce_ConsoleApplication.cpp
Normal file
356
modules/juce_core/misc/juce_ConsoleApplication.cpp
Normal file
@ -0,0 +1,356 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
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 inline File resolveFilename (const String& name)
|
||||
{
|
||||
return File::getCurrentWorkingDirectory().getChildFile (name.unquoted());
|
||||
}
|
||||
|
||||
static inline void checkFileExists (const File& f)
|
||||
{
|
||||
if (! f.exists())
|
||||
ConsoleApplication::fail ("Could not find file: " + f.getFullPathName());
|
||||
}
|
||||
|
||||
static inline void checkFolderExists (const File& f)
|
||||
{
|
||||
if (! f.isDirectory())
|
||||
ConsoleApplication::fail ("Could not find folder: " + f.getFullPathName());
|
||||
}
|
||||
|
||||
File ArgumentList::Argument::resolveAsFile() const
|
||||
{
|
||||
return resolveFilename (text);
|
||||
}
|
||||
|
||||
File ArgumentList::Argument::resolveAsExistingFile() const
|
||||
{
|
||||
auto f = resolveAsFile();
|
||||
checkFileExists (f);
|
||||
return f;
|
||||
}
|
||||
|
||||
File ArgumentList::Argument::resolveAsExistingFolder() const
|
||||
{
|
||||
auto f = resolveAsFile();
|
||||
|
||||
if (! f.isDirectory())
|
||||
ConsoleApplication::fail ("Could not find folder: " + f.getFullPathName());
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
static inline bool isShortOptionFormat (StringRef s) { return s[0] == '-' && s[1] != '-'; }
|
||||
static inline bool isLongOptionFormat (StringRef s) { return s[0] == '-' && s[1] == '-' && s[2] != '-'; }
|
||||
static inline 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())
|
||||
if (auto equalsIndex = text.indexOfChar ('='))
|
||||
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 (option);
|
||||
}
|
||||
|
||||
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 });
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void ArgumentList::failIfOptionIsMissing (StringRef option) const
|
||||
{
|
||||
if (! containsOption (option))
|
||||
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 {};
|
||||
}
|
||||
|
||||
File ArgumentList::getFileForOption (StringRef option) const
|
||||
{
|
||||
auto text = getValueForOption (option);
|
||||
|
||||
if (text.isEmpty())
|
||||
{
|
||||
failIfOptionIsMissing (option);
|
||||
ConsoleApplication::fail ("Expected a filename after the " + option + " option");
|
||||
}
|
||||
|
||||
return resolveFilename (text);
|
||||
}
|
||||
|
||||
File ArgumentList::getExistingFileForOption (StringRef option) const
|
||||
{
|
||||
auto file = getFileForOption (option);
|
||||
checkFileExists (file);
|
||||
return file;
|
||||
}
|
||||
|
||||
File ArgumentList::getExistingFolderForOption (StringRef option) const
|
||||
{
|
||||
auto file = getFileForOption (option);
|
||||
checkFolderExists (file);
|
||||
return file;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
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::cout << 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
|
||||
{
|
||||
if (auto c = findCommand (args, optionMustBeFirstArg))
|
||||
return invokeCatchingFailures ([=] { c->command (args); return 0; });
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void ConsoleApplication::printCommandList (const ArgumentList& args) const
|
||||
{
|
||||
auto exeName = args.executableName.fromLastOccurrenceOf ("/", false, false)
|
||||
.fromLastOccurrenceOf ("\\", false, false);
|
||||
|
||||
StringArray namesAndArgs;
|
||||
int descriptionIndent = 0;
|
||||
|
||||
for (auto& c : commands)
|
||||
{
|
||||
auto nameAndArgs = exeName + " " + c.argumentDescription;
|
||||
namesAndArgs.add (nameAndArgs);
|
||||
descriptionIndent = std::max (descriptionIndent, nameAndArgs.length());
|
||||
}
|
||||
|
||||
descriptionIndent = std::min (descriptionIndent + 1, 40);
|
||||
|
||||
for (size_t i = 0; i < commands.size(); ++i)
|
||||
{
|
||||
auto nameAndArgs = namesAndArgs[(int) i];
|
||||
std::cout << ' ';
|
||||
|
||||
if (nameAndArgs.length() > descriptionIndent)
|
||||
std::cout << nameAndArgs << std::endl << String::repeatedString (" ", descriptionIndent + 1);
|
||||
else
|
||||
std::cout << nameAndArgs.paddedRight (' ', descriptionIndent);
|
||||
|
||||
std::cout << commands[i].shortDescription << std::endl;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
} // namespace juce
|
306
modules/juce_core/misc/juce_ConsoleApplication.h
Normal file
306
modules/juce_core/misc/juce_ConsoleApplication.h
Normal file
@ -0,0 +1,306 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
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
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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"
|
||||
*/
|
||||
bool containsOption (StringRef option) const;
|
||||
|
||||
/** 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 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 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 filename argument using getFileForOption() and fails with a suitable error if
|
||||
the file isn't a folder that exists.
|
||||
*/
|
||||
File getExistingFolderForOption (StringRef option) const;
|
||||
|
||||
/** 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
|
||||
*/
|
||||
struct ConsoleApplication
|
||||
{
|
||||
//==============================================================================
|
||||
/**
|
||||
Represents a command that can be executed if its command-line arguments are matched.
|
||||
@see ConsoleApplication::addCommand(), ConsoleApplication::findAndRunCommand()
|
||||
*/
|
||||
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;
|
||||
|
||||
//==============================================================================
|
||||
/** 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
|
@ -42,13 +42,13 @@ Result& Result::operator= (const Result& other)
|
||||
}
|
||||
|
||||
Result::Result (Result&& other) noexcept
|
||||
: errorMessage (static_cast<String&&> (other.errorMessage))
|
||||
: errorMessage (std::move (other.errorMessage))
|
||||
{
|
||||
}
|
||||
|
||||
Result& Result::operator= (Result&& other) noexcept
|
||||
{
|
||||
errorMessage = static_cast<String&&> (other.errorMessage);
|
||||
errorMessage = std::move (other.errorMessage);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -91,7 +91,7 @@ public:
|
||||
|
||||
//==============================================================================
|
||||
/** Function type of runtime permission request callbacks. */
|
||||
typedef std::function<void (bool)> Callback;
|
||||
using Callback = std::function<void (bool)>;
|
||||
|
||||
//==============================================================================
|
||||
/** Call this method to request a runtime permission.
|
||||
|
@ -62,7 +62,7 @@ namespace FunctionTestsHelpers
|
||||
|
||||
struct FunctionObject
|
||||
{
|
||||
FunctionObject() {}
|
||||
FunctionObject() = default;
|
||||
|
||||
FunctionObject (const FunctionObject& other)
|
||||
{
|
||||
@ -72,6 +72,26 @@ namespace FunctionTestsHelpers
|
||||
int operator()(int i) const { return bigData->sum() + i; }
|
||||
|
||||
std::unique_ptr<BigData> bigData { new BigData() };
|
||||
|
||||
JUCE_LEAK_DETECTOR (FunctionObject)
|
||||
};
|
||||
|
||||
struct BigFunctionObject
|
||||
{
|
||||
BigFunctionObject() = default;
|
||||
|
||||
BigFunctionObject (const BigFunctionObject& other)
|
||||
{
|
||||
bigData.reset (new BigData (*other.bigData));
|
||||
}
|
||||
|
||||
int operator()(int i) const { return bigData->sum() + i; }
|
||||
|
||||
std::unique_ptr<BigData> bigData { new BigData() };
|
||||
|
||||
int stackUsage[32];
|
||||
|
||||
JUCE_LEAK_DETECTOR (BigFunctionObject)
|
||||
};
|
||||
}
|
||||
|
||||
@ -95,13 +115,16 @@ public:
|
||||
|
||||
std::function<double(double, double)> f2 (FunctionTestsHelpers::multiply);
|
||||
expectEquals (6.0, f2 (2.0, 3.0));
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
beginTest ("Function objects");
|
||||
|
||||
std::function<int(int)> f1 = FunctionTestsHelpers::FunctionObject();
|
||||
expectEquals (f1 (5), FunctionTestsHelpers::BigData::bigDataSum + 5);
|
||||
|
||||
std::function<int(int)> f2 { FunctionTestsHelpers::BigFunctionObject() };
|
||||
expectEquals (f2 (5), FunctionTestsHelpers::BigData::bigDataSum + 5);
|
||||
}
|
||||
|
||||
{
|
||||
@ -174,13 +197,13 @@ public:
|
||||
beginTest ("move constructor");
|
||||
|
||||
std::unique_ptr<std::function<int()>> fStackTmp (new std::function<int()> (fStack));
|
||||
std::function<int()> f1 (static_cast<std::function<int()>&&> (*fStackTmp));
|
||||
std::function<int()> f1 (std::move (*fStackTmp));
|
||||
|
||||
fStackTmp.reset();
|
||||
expectEquals (f1(), 3);
|
||||
|
||||
std::unique_ptr<std::function<int()>> fHeapTmp (new std::function<int()> (fHeap));
|
||||
std::function<int()> f2 (static_cast<std::function<int()>&&> (*fHeapTmp));
|
||||
std::function<int()> f2 (std::move (*fHeapTmp));
|
||||
if (*fHeapTmp)
|
||||
expect (false);
|
||||
|
||||
@ -188,7 +211,7 @@ public:
|
||||
expectEquals (f2(), FunctionTestsHelpers::BigData::bigDataSum);
|
||||
|
||||
std::unique_ptr<std::function<int()>> fEmptyTmp (new std::function<int()>());
|
||||
std::function<int()> f3 (static_cast<std::function<int()>&&> (*fEmptyTmp));
|
||||
std::function<int()> f3 (std::move (*fEmptyTmp));
|
||||
fEmptyTmp.reset();
|
||||
if (f3)
|
||||
expect (false);
|
||||
@ -199,14 +222,14 @@ public:
|
||||
|
||||
std::function<int()> f1 (fHeap);
|
||||
std::unique_ptr<std::function<int()>> fStackTmp (new std::function<int()> (fStack));
|
||||
f1 = static_cast<std::function<int()>&&> (*fStackTmp);
|
||||
f1 = std::move (*fStackTmp);
|
||||
|
||||
fStackTmp.reset();
|
||||
expectEquals (f1(), 3);
|
||||
|
||||
std::function<int()> f2 (fStack);
|
||||
std::unique_ptr<std::function<int()>> fHeapTmp (new std::function<int()> (fHeap));
|
||||
f2 = static_cast<std::function<int()>&&> (*fHeapTmp);
|
||||
f2 = std::move (*fHeapTmp);
|
||||
if (*fHeapTmp)
|
||||
expect (false);
|
||||
|
||||
@ -215,7 +238,7 @@ public:
|
||||
|
||||
std::function<int()> f3 (fHeap);
|
||||
std::unique_ptr<std::function<int()>> fEmptyTmp (new std::function<int()>());
|
||||
f3 = static_cast<std::function<int()>&&> (*fEmptyTmp);
|
||||
f3 = std::move (*fEmptyTmp);
|
||||
fEmptyTmp.reset();
|
||||
if (f3)
|
||||
expect (false);
|
||||
|
@ -51,7 +51,7 @@ namespace std
|
||||
/** Creates an empty function. */
|
||||
function (decltype (nullptr)) noexcept {}
|
||||
|
||||
/** Creates a function targetting the provided Functor. */
|
||||
/** Creates a function targeting the provided Functor. */
|
||||
template <typename Functor>
|
||||
function (Functor f)
|
||||
{
|
||||
@ -192,11 +192,7 @@ namespace std
|
||||
{
|
||||
if (functorHolderHelper != nullptr)
|
||||
{
|
||||
if (functorHolderHelper->getSize() > functorHolderStackSize)
|
||||
delete[] reinterpret_cast<char*> (functorHolderHelper);
|
||||
else
|
||||
functorHolderHelper->~FunctorHolderBase<Result, Arguments...>();
|
||||
|
||||
functorHolderHelper->~FunctorHolderBase<Result, Arguments...>();
|
||||
functorHolderHelper = nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -145,13 +145,3 @@ uint64 Uuid::hash() const noexcept
|
||||
}
|
||||
|
||||
} // namespace juce
|
||||
|
||||
#if ! DOXYGEN
|
||||
namespace std
|
||||
{
|
||||
template <> struct hash<juce::Uuid>
|
||||
{
|
||||
size_t operator() (const juce::Uuid& u) const noexcept { return (size_t) u.hash(); }
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
@ -135,3 +135,13 @@ private:
|
||||
};
|
||||
|
||||
} // namespace juce
|
||||
|
||||
#if ! DOXYGEN
|
||||
namespace std
|
||||
{
|
||||
template <> struct hash<juce::Uuid>
|
||||
{
|
||||
size_t operator() (const juce::Uuid& u) const noexcept { return (size_t) u.hash(); }
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user