Add a CLI flag that forces debug output to stdout while configuration files are loading. This overrides the configuration files, so conflicting settings in configuration files won't block log output between each file load.
278 lines
9.9 KiB
C++
278 lines
9.9 KiB
C++
/*! /\ +=======================================================+
|
|
* ____/ \____ /: Open source game framework licensed to freely use, :
|
|
* \ / / : copy, and modify - created for dank.game :
|
|
* +==\ ^__^ /==+ : :
|
|
* : ~/ \~ : : Download at https://open.shampoo.ooo/shampoo/spacebox :
|
|
* : ~~~~~~~~~~~~ : +=======================================================+
|
|
* : SPACE ~~~~~ : /
|
|
* : ~~~~~~~ BOX :/
|
|
* +==============+
|
|
*
|
|
* @file sb.hpp
|
|
*
|
|
* Initialize the framework and its environment. Initialize and parse the command line interface. Define exceptions.
|
|
*
|
|
* sb::cli
|
|
* -------
|
|
*
|
|
* Define options and parse option values passed from the command line.
|
|
*
|
|
* Once the command line is parsed, the options and values are available via sb::cli::app, which is a read-only
|
|
* CLI11::App object.
|
|
*
|
|
* Some default options are defined by sb::cli::init. More options can be added with sb::cli::add.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <vector>
|
|
#include <exception>
|
|
#include <string>
|
|
#include <sstream>
|
|
#include <initializer_list>
|
|
|
|
#if defined(__EMSCRIPTEN__)
|
|
#include <emscripten.h>
|
|
#include <emscripten/html5.h>
|
|
#endif
|
|
|
|
#include "SDL.h"
|
|
|
|
#include "cli11/CLI11.hpp"
|
|
#include "json/json.hpp"
|
|
|
|
namespace sb
|
|
{
|
|
/*!
|
|
* Indicates that a value used is reserved for internal use.
|
|
*/
|
|
class ReservedError : public std::logic_error
|
|
{
|
|
public:
|
|
ReservedError(std::string message = "Reserved for internal use") : std::logic_error(message) {}
|
|
};
|
|
|
|
/*!
|
|
* An error to be thrown when part of the program that is only necessary to be run once is run again.
|
|
*/
|
|
class AlreadyInitializedError : public std::logic_error
|
|
{
|
|
public:
|
|
AlreadyInitializedError(std::string message = "Initialization was already run") : std::logic_error(message) {}
|
|
};
|
|
}
|
|
|
|
#include "filesystem.hpp"
|
|
#include "extension.hpp"
|
|
#include "cloud.hpp"
|
|
|
|
namespace sb
|
|
{
|
|
|
|
class cli
|
|
{
|
|
static CLI::App _app;
|
|
static std::vector<std::string> _reserved;
|
|
static std::vector<std::string> _config_strings;
|
|
static std::vector<fs::path> _config_files;
|
|
|
|
/*!
|
|
* Force add an option without checking if the name is reserved.
|
|
*
|
|
* @param name The option name to be passed on the command line
|
|
* @param option_value_storage This variable will be filled with the value passed on the command line
|
|
* @param description Help message to be printed for this option when the program is given the `-h`
|
|
* flag
|
|
*
|
|
* @throw CLI::OptionAlreadyAdded If the option is already in sb::cli::app()
|
|
*/
|
|
template<typename OptionType>
|
|
static void _add(const std::string& name, OptionType& option_value_storage, const std::string& description = "")
|
|
{
|
|
try
|
|
{
|
|
_app.add_option(name, option_value_storage, description);
|
|
}
|
|
catch (const CLI::OptionAlreadyAdded& error)
|
|
{
|
|
std::ostringstream message;
|
|
message << "Error while trying to create option " << name <<
|
|
". This option has already been added.";
|
|
throw CLI::OptionAlreadyAdded(message.str());
|
|
}
|
|
}
|
|
|
|
/*!
|
|
* Force add a flag without checking if the name is reserved.
|
|
*
|
|
* @param name The name of the boolean flag
|
|
* @param storage Reference to a variable which will be filled with the value of the flag
|
|
* @param description Help message to display for this flag when the program is given the `-h` flag
|
|
*
|
|
* @throw CLI::OptionAlreadyAdded If the flag is already in sb::cli::app()
|
|
*/
|
|
static void _add_flag(const std::string& name, bool& storage, const std::string& description = "");
|
|
|
|
public:
|
|
|
|
/*!
|
|
* This class is entirely static data and functions and should not be instantiated.
|
|
*/
|
|
cli() = delete;
|
|
|
|
/*!
|
|
* This must be run before parsing to add the internally reserved names to the options list.
|
|
*
|
|
* It's expected that `sb::init()` will run this, so it shouldn't need to be run manually.
|
|
*/
|
|
static void init();
|
|
|
|
/*!
|
|
* @return A const reference to the CLI11::App object containing the options and option values
|
|
*/
|
|
static const CLI::App& app();
|
|
|
|
/*!
|
|
* @return Read-only list of option names reserved by the framework that cannot be overwritten
|
|
*/
|
|
static const std::vector<std::string> reserved();
|
|
|
|
/*!
|
|
* Add an option by providing a option name and a reference to a variable be filled with with the value passed on
|
|
* the command line.
|
|
*
|
|
* @param name The option name to be passed on the command line
|
|
* @param value_storage This variable will be filled with the value passed on the command line
|
|
* @param description Help message to be printed for this option when the program is given the `-h` flag
|
|
*
|
|
* @throw sb::ReservedError If the name is needed by the framework
|
|
* @throw CLI::OptionAlreadyAdded If the option is already in sb::cli::app()
|
|
*/
|
|
template<typename OptionType>
|
|
static void add(const std::string& name, OptionType& option_value_storage, const std::string& description = "")
|
|
{
|
|
/* Check if a reserved name was used. */
|
|
for (std::string reserved_name : reserved())
|
|
{
|
|
if (name == reserved_name)
|
|
{
|
|
std::ostringstream message;
|
|
message << name << " is a reserved name in the framework.";
|
|
throw ReservedError(message.str());
|
|
}
|
|
}
|
|
|
|
/* Otherwise, add the new option */
|
|
_add(name, option_value_storage, description);
|
|
}
|
|
|
|
/*!
|
|
* Store the values given for the options passed on the command line. The parameters are expected to be the same
|
|
* values passed to the main function.
|
|
*
|
|
* If there is a parse error, or if the "-h"/"--help" flag is parsed, the CLI::App object exits, causing the
|
|
* program to exit immediately. For this reason, it is suggested to parse the command line as early as possible
|
|
* before other parts of the framework which require cleaner exits are initialized.
|
|
*
|
|
* @see CLI::App::parse(int, const char* const*)
|
|
*
|
|
* @param argc Count of arguments passed on the command line
|
|
* @param argv Arguments passed on the command line as strings
|
|
*/
|
|
static void parse(int argc, char** argv);
|
|
|
|
/*!
|
|
* @overload sb::cli::parse(int, char**)
|
|
*
|
|
* @param command_line Command line split into words
|
|
*/
|
|
static void parse(std::vector<std::string>& command_line);
|
|
|
|
/*!
|
|
* @overload sb::cli::parse(int, char**)
|
|
*
|
|
* @param command_line Command line split into words
|
|
*/
|
|
static void parse(std::initializer_list<std::string> _command_line);
|
|
|
|
/*!
|
|
* @return The strings passed to --config during parse
|
|
*/
|
|
static const std::vector<std::string>& config_strings();
|
|
|
|
/*!
|
|
* @return The paths passed to --config-files during parse
|
|
*/
|
|
static const std::vector<fs::path>& config_files();
|
|
};
|
|
|
|
/*!
|
|
* Initialize the framework, optionally passing in arguments to the CLI. The supported options can be viewed using
|
|
* the `--help` flag.
|
|
*
|
|
* ./project --help
|
|
*
|
|
* If a command line is passed, this will parse the command line and store the values in `sb::cli::app`.
|
|
*
|
|
* If --config or --config-files options are parsed, the given values will be further parsed as JSON and stored in
|
|
* `sb::cli_configs`. If any syntax errors are encountered, an error will be thrown.
|
|
*
|
|
* @warning Parsed arguments are reset every time this is run. If command line arguments were passed previously,
|
|
* they must be passed again if they are still needed.
|
|
*
|
|
* @throw nlohmann::json::parse_error If the configuration passed on the command line is invalid JSON
|
|
*/
|
|
void init();
|
|
|
|
/*!
|
|
* @overload sb::init()
|
|
*
|
|
* @param command_line Command line separated into words, not including the program name
|
|
*/
|
|
void init(std::vector<std::string>& _command_line);
|
|
|
|
/*!
|
|
* @overload sb::init()
|
|
*
|
|
* This form is used to forward arguments directly from the program's main function. The first argv will be
|
|
* discarded because it is assumed to be the program name.
|
|
*
|
|
* If `argc` is 0, sb::init() will be called without any arguments. This allows argc and argv to be passed
|
|
* directly from the program's main function without any sanitization.
|
|
*
|
|
* @param argc Count of arguments passed on the command line
|
|
* @param argv Arguments passed on the command line as strings
|
|
*/
|
|
void init(int argc, char** argv);
|
|
|
|
/*!
|
|
* @overload sb::init()
|
|
*
|
|
* @param command_line Command line separated into words, not including the program name
|
|
*/
|
|
void init(std::initializer_list<std::string> command_line);
|
|
|
|
/*!
|
|
* @return Read-only list of config JSON passed in from the command line
|
|
*/
|
|
const std::vector<nlohmann::json> cli_configs();
|
|
|
|
/*!
|
|
* @return Indicates whether or not logging should be enabled during configuration file loading
|
|
*/
|
|
bool cli_debug_config_load();
|
|
|
|
/*!
|
|
* Currently just shuts down the Steam API.
|
|
*/
|
|
void quit();
|
|
|
|
#if defined(STEAM_ENABLED)
|
|
|
|
/* Setting to false before calling sb::init will turn off Steam initialization even when compiled with Steam API
|
|
* support */
|
|
extern bool initialize_steam;
|
|
|
|
#endif
|
|
}
|