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