Add SimpleConfig.
https://godocs.io/git.wntrmute.dev/kyle/goutils/config is one of the more useful Go packages in my standard go library that gets used for building services. I needed something similar for another Shimmering Clarity project, and thus I figured I'd add it into SCSL.
This commit is contained in:
parent
9a8dc08a4f
commit
c5308dedba
|
@ -42,6 +42,7 @@ set(HEADER_FILES
|
|||
include/scsl/Commander.h
|
||||
include/scsl/Dictionary.h
|
||||
include/scsl/Flags.h
|
||||
include/scsl/SimpleConfig.h
|
||||
include/scsl/StringUtil.h
|
||||
include/scsl/TLV.h
|
||||
|
||||
|
@ -72,6 +73,7 @@ set(SOURCE_FILES
|
|||
src/sl/Dictionary.cc
|
||||
src/test/Exceptions.cc
|
||||
src/sl/Flags.cc
|
||||
src/sl/SimpleConfig.cc
|
||||
src/sl/StringUtil.cc
|
||||
src/sl/TLV.cc
|
||||
|
||||
|
@ -123,7 +125,6 @@ generate_test(orientation)
|
|||
generate_test(quaternion)
|
||||
generate_test(vector)
|
||||
|
||||
|
||||
# test tooling
|
||||
add_executable(flags-demo test/flags.cc)
|
||||
target_link_libraries(flags-demo ${PROJECT_NAME})
|
||||
|
@ -131,6 +132,9 @@ target_link_libraries(flags-demo ${PROJECT_NAME})
|
|||
add_executable(simple-test-demo test/simple_suite_example.cc)
|
||||
target_link_libraries(simple-test-demo ${PROJECT_NAME})
|
||||
|
||||
add_executable(config-explorer test/config-explorer.cc)
|
||||
target_link_libraries(config-explorer ${PROJECT_NAME})
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
write_basic_package_version_file(
|
||||
scslConfig.cmake
|
||||
|
|
|
@ -245,6 +245,17 @@ public:
|
|||
std::string defaultValue,
|
||||
std::string fDescription);
|
||||
|
||||
/// Register a new string command line flag with a default value.
|
||||
///
|
||||
/// \param fName The name of the flag, including a leading dash.
|
||||
/// \param defaultValue The default value for the flag.
|
||||
/// \param fDescription A short description of the flag.
|
||||
/// \return True if the flag was registered, false if the flag could
|
||||
/// not be registered (e.g. a duplicate flag was registered).
|
||||
bool Register(std::string fName,
|
||||
const char *defaultValue,
|
||||
std::string fDescription);
|
||||
|
||||
/// Return the number of registered flags.
|
||||
size_t Size();
|
||||
|
||||
|
|
|
@ -0,0 +1,185 @@
|
|||
///
|
||||
/// \file include/scsl/SimpleConfig.h
|
||||
/// \author K. Isom <kyle@imap.cc>
|
||||
/// \date 2023-10-21
|
||||
/// \brief Simple project configuration.
|
||||
///
|
||||
/// This is an implementation of a simple global configuration system
|
||||
/// for projects based on a Go version I've used successfully in
|
||||
/// several projects.
|
||||
///
|
||||
/// Copyright 2023 K. Isom <kyle@imap.cc>
|
||||
///
|
||||
/// 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.
|
||||
///
|
||||
/// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
/// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
/// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
/// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
/// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
|
||||
/// OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
/// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
/// PERFORMANCE OF THIS SOFTWARE.
|
||||
///
|
||||
|
||||
#ifndef SCSL_SIMPLECONFIG_H
|
||||
#define SCSL_SIMPLECONFIG_H
|
||||
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace scsl {
|
||||
|
||||
|
||||
/// \brief SimpleConfig is a basic configuration for projects.
|
||||
///
|
||||
/// SimpleConfig is a basic key-value system. It can optionally load
|
||||
/// key-value pairs from a file, which should consist of key = value
|
||||
/// lines. Comments may be added by starting the line with a '#'; these
|
||||
/// lines will be skipped. Comments may have leading whitespace. Any
|
||||
/// empty lines or lines consisting solely of whitespace will also be
|
||||
/// skipped.
|
||||
///
|
||||
/// When values are retrieved by one of the variants on Get, they are
|
||||
/// looked up in the following order, assuming `key` and an optional
|
||||
/// `prefix` set on the config:
|
||||
///
|
||||
/// 1. Any cached key-value pairs. Loading a file caches the key-value
|
||||
/// pairs in the file. The file is not used again, unless another
|
||||
/// call to Load is made. If the cache has a name for `key`, it will
|
||||
/// be returned.
|
||||
/// 2. The value is looked up from the environment. An optional prefix
|
||||
/// can be set; if so, if there is an environment named
|
||||
/// `{prefix}{key}`, the value will be cached and it will be
|
||||
/// returned.
|
||||
/// 3. If a default value has been provided, it will be cached and
|
||||
/// returned.
|
||||
/// 4. If none of the previous steps has provided a value, an empty
|
||||
/// string will be returned.
|
||||
///
|
||||
/// In Go projects, I've used the global config to great success.
|
||||
/// However, callers may set up an explicit configuration instance.
|
||||
class SimpleConfig {
|
||||
public:
|
||||
#if defined(SCSL_DESKTOP_BUILD)
|
||||
/// \brief Load key-value pairs from a file.
|
||||
///
|
||||
/// \note This operates on the global config.
|
||||
///
|
||||
/// \param path The path to a config file.
|
||||
/// \return 0 if the file was loaded successfully.
|
||||
static int LoadGlobal(const char *path);
|
||||
|
||||
/// \brief Load key-value pairs from a file.
|
||||
///
|
||||
/// \note This operates on the global config.
|
||||
///
|
||||
/// \param path The path to a config file.
|
||||
/// \return 0 if the file was loaded successfully.
|
||||
static int LoadGlobal(std::string &path);
|
||||
|
||||
/// \brief Set the prefix in use by the config.
|
||||
///
|
||||
/// \note This operates on the global config.
|
||||
///
|
||||
/// \param prefix The prefix to prepend to the key when looking
|
||||
/// up values from the environment.
|
||||
static void SetPrefixGlobal(const std::string prefix);
|
||||
|
||||
/// \brief Return the keys cached in the config.
|
||||
///
|
||||
/// Note that this won't returned any non-cached environment
|
||||
/// values.
|
||||
///
|
||||
/// \note This operates on the global config.
|
||||
///
|
||||
/// \return A list of keys stored under the config.
|
||||
static std::vector<std::string> KeyListGlobal();
|
||||
|
||||
/// \brief Get the value stored for the key from the config.
|
||||
///
|
||||
/// \note This operates on the global config.
|
||||
///
|
||||
/// \param key The key to look up. See the class documentation
|
||||
/// for information on how this is used.
|
||||
/// \return The value stored under the key, or an empty string.
|
||||
static std::string GetGlobal(std::string key);
|
||||
|
||||
/// \brief Get the value stored for the key from the config.
|
||||
///
|
||||
/// \note This operates on the global config.
|
||||
///
|
||||
/// \param key The key to look up. See the class documentation
|
||||
/// for information on how this is used.
|
||||
/// \param defaultValue A default value to cache and use if no
|
||||
/// value is stored under the key.
|
||||
/// \return The value stored under the key, or the default
|
||||
/// value.
|
||||
static std::string GetGlobal(std::string key, std::string defaultValue);
|
||||
#endif
|
||||
|
||||
/// \brief The constructor doesn't need any initialisation.
|
||||
SimpleConfig();
|
||||
|
||||
/// \brief The constructor can explicitly set the environment
|
||||
/// prefix.
|
||||
SimpleConfig(std::string prefix);
|
||||
|
||||
/// \brief Load key-value pairs from a file.
|
||||
///
|
||||
/// \param path The path to a config file.
|
||||
/// \return 0 if the file was loaded successfully.
|
||||
int Load(const char *path);
|
||||
|
||||
/// \brief Load key-value pairs from a file.
|
||||
///
|
||||
/// \param path The path to a config file.
|
||||
/// \return 0 if the file was loaded successfully.
|
||||
int Load(std::string& path);
|
||||
|
||||
/// \brief Set the prefix in use by the config.
|
||||
///
|
||||
/// \param prefix The prefix to prepend to the key when looking
|
||||
/// up values from the environment.
|
||||
void SetPrefix(const std::string prefix);
|
||||
|
||||
/// \brief Return the keys cached in the config.
|
||||
///
|
||||
/// Note that this won't returned any non-cached environment
|
||||
/// values.
|
||||
///
|
||||
/// \return A list of keys stored under the config.
|
||||
std::vector<std::string> KeyList();
|
||||
|
||||
/// \brief Get the value stored for the key from the config.
|
||||
///
|
||||
/// \param key The key to look up. See the class documentation
|
||||
/// for information on how this is used.
|
||||
/// \return The value stored under the key, or an empty string.
|
||||
std::string Get(std::string key);
|
||||
|
||||
/// \brief Get the value stored for the key from the config.
|
||||
///
|
||||
/// \param key The key to look up. See the class documentation
|
||||
/// for information on how this is used.
|
||||
/// \param defaultValue A default value to cache and use if no
|
||||
/// value is stored under the key.
|
||||
/// \return The value stored under the key, or the default
|
||||
/// value.
|
||||
std::string Get(std::string key, std::string defaultValue);
|
||||
|
||||
private:
|
||||
std::string envPrefix;
|
||||
std::map<std::string, std::string> vars;
|
||||
};
|
||||
|
||||
|
||||
} // namespace scsl
|
||||
|
||||
|
||||
#endif //SCSL_SIMPLECONFIG_H
|
|
@ -33,7 +33,7 @@
|
|||
namespace scsl {
|
||||
|
||||
/// String-related utility functions.
|
||||
namespace string {
|
||||
namespace scstring {
|
||||
|
||||
|
||||
/// Remove any whitespace At the beginning of the string. The string
|
||||
|
|
|
@ -80,7 +80,7 @@ hasKey(std::vector<std::string> argv)
|
|||
}
|
||||
|
||||
cout << "not found\n";
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
/// PERFORMANCE OF THIS SOFTWARE.
|
||||
///
|
||||
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <regex>
|
||||
|
@ -172,6 +171,18 @@ Flags::Register(std::string fName, std::string defaultValue, std::string fDescri
|
|||
}
|
||||
|
||||
|
||||
bool
|
||||
Flags::Register(std::string fName, const char *defaultValue, std::string fDescription)
|
||||
{
|
||||
if (!this->Register(fName, FlagType::String, std::move(fDescription))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this->flags[fName]->Value.s = new std::string(defaultValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
Flags::Size()
|
||||
{
|
||||
|
@ -206,7 +217,7 @@ Flags::ParseStatus
|
|||
Flags::parseArg(int argc, char **argv, int &index)
|
||||
{
|
||||
std::string arg(argv[index]);
|
||||
string::TrimWhitespace(arg);
|
||||
scstring::TrimWhitespace(arg);
|
||||
|
||||
if (!std::regex_search(arg, isFlag)) {
|
||||
return ParseStatus::EndOfFlags;
|
||||
|
@ -302,7 +313,7 @@ Flags::Usage(std::ostream &os, int exitCode)
|
|||
os << this->name << ":\t";
|
||||
auto indent = this->name.size() + 7;
|
||||
|
||||
string::WriteTabIndented(os, description, 72 - indent, indent / 8, false);
|
||||
scstring::WriteTabIndented(os, description, 72 - indent, indent / 8, false);
|
||||
os << "\n\n";
|
||||
|
||||
for (const auto &pair : this->flags) {
|
||||
|
@ -312,16 +323,16 @@ Flags::Usage(std::ostream &os, int exitCode)
|
|||
argLine += "\t\t";
|
||||
break;
|
||||
case FlagType::Integer:
|
||||
argLine += "int\t\t";
|
||||
argLine += " int\t\t";
|
||||
break;
|
||||
case FlagType::UnsignedInteger:
|
||||
argLine += "uint\t\t";
|
||||
argLine += " uint\t\t";
|
||||
break;
|
||||
case FlagType::SizeT:
|
||||
argLine += "size_t\t";
|
||||
argLine += " size_t\t";
|
||||
break;
|
||||
case FlagType::String:
|
||||
argLine += "string\t";
|
||||
argLine += " string\t";
|
||||
break;
|
||||
case FlagType::Unknown:
|
||||
// fallthrough
|
||||
|
@ -336,7 +347,7 @@ Flags::Usage(std::ostream &os, int exitCode)
|
|||
|
||||
os << argLine;
|
||||
indent = argLine.size();
|
||||
string::WriteTabIndented(os, pair.second->Description,
|
||||
scstring::WriteTabIndented(os, pair.second->Description,
|
||||
72-indent, (indent/8)+2, false);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,189 @@
|
|||
///
|
||||
/// \file src/sl/SimpleConfig.cc
|
||||
/// \author K. Isom <kyle@imap.cc>
|
||||
/// \date 2023-10-21
|
||||
/// \brief Simple project configuration.
|
||||
///
|
||||
/// This is an implementation of a simple global configuration system
|
||||
/// for projects based on a Go version I've used successfully in
|
||||
/// several projects.
|
||||
///
|
||||
/// Copyright 2023 K. Isom <kyle@imap.cc>
|
||||
///
|
||||
/// 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.
|
||||
///
|
||||
/// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
/// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
/// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
/// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
/// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
|
||||
/// OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
/// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
/// PERFORMANCE OF THIS SOFTWARE.
|
||||
///
|
||||
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <regex>
|
||||
|
||||
#include <scsl/SimpleConfig.h>
|
||||
#include <scsl/StringUtil.h>
|
||||
|
||||
|
||||
namespace scsl {
|
||||
|
||||
|
||||
#if defined(SCSL_DESKTOP_BUILD)
|
||||
static SimpleConfig globalConfig;
|
||||
#endif
|
||||
|
||||
|
||||
static constexpr auto regexOpts = std::regex_constants::nosubs |
|
||||
std::regex_constants::optimize |
|
||||
std::regex_constants::ECMAScript;
|
||||
|
||||
static const std::regex commentLine("^\\s*#.*$", regexOpts);
|
||||
static const std::regex keyValueLine("^\\s*\\w+\\s*=\\s*\\w+", regexOpts);
|
||||
|
||||
|
||||
int
|
||||
SimpleConfig::LoadGlobal(const char *path)
|
||||
{
|
||||
return globalConfig.Load(path);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
SimpleConfig::LoadGlobal(std::string &path)
|
||||
{
|
||||
return globalConfig.Load(path);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SimpleConfig::SetPrefixGlobal(const std::string prefix)
|
||||
{
|
||||
globalConfig.SetPrefix(prefix);
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::string>
|
||||
SimpleConfig::KeyListGlobal()
|
||||
{
|
||||
return globalConfig.KeyList();
|
||||
}
|
||||
|
||||
|
||||
std::string
|
||||
SimpleConfig::GetGlobal(std::string key)
|
||||
{
|
||||
return globalConfig.Get(key);
|
||||
}
|
||||
|
||||
|
||||
std::string
|
||||
SimpleConfig::GetGlobal(std::string key, std::string defaultValue)
|
||||
{
|
||||
return globalConfig.Get(key, defaultValue);
|
||||
}
|
||||
|
||||
|
||||
SimpleConfig::SimpleConfig()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
SimpleConfig::SimpleConfig(std::string prefix)
|
||||
: envPrefix(prefix)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
SimpleConfig::Load(const char *path)
|
||||
{
|
||||
auto spath = std::string(path);
|
||||
return this->Load(spath);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
SimpleConfig::Load(std::string &path)
|
||||
{
|
||||
std::ifstream configFile(path);
|
||||
std::string line;
|
||||
|
||||
while (std::getline(configFile, line)) {
|
||||
scstring::TrimWhitespace(line);
|
||||
if (line.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (std::regex_search(line, commentLine)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (std::regex_search(line, keyValueLine)) {
|
||||
auto pair = scstring::SplitKeyValuePair(line, "=");
|
||||
if (pair.size() < 2) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
this->vars[pair[0]] = pair[1];
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SimpleConfig::SetPrefix(const std::string prefix)
|
||||
{
|
||||
this->envPrefix = std::move(prefix);
|
||||
}
|
||||
|
||||
|
||||
std::string
|
||||
SimpleConfig::Get(std::string key)
|
||||
{
|
||||
return this->Get(key, "");
|
||||
}
|
||||
|
||||
|
||||
std::string
|
||||
SimpleConfig::Get(std::string key, std::string defaultValue)
|
||||
{
|
||||
if (this->vars.count(key)) {
|
||||
return this->vars[key];
|
||||
}
|
||||
|
||||
auto envKey = this->envPrefix + key;
|
||||
|
||||
const char *envValue = getenv(envKey.c_str());
|
||||
if (envValue != nullptr) {
|
||||
this->vars[key] = std::string(envValue);
|
||||
return this->Get(key);
|
||||
}
|
||||
|
||||
this->vars[key] = defaultValue;
|
||||
return this->Get(key);
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::string>
|
||||
SimpleConfig::KeyList()
|
||||
{
|
||||
std::vector<std::string> keyList;
|
||||
|
||||
for (auto &entry : this->vars) {
|
||||
keyList.push_back(entry.first);
|
||||
}
|
||||
|
||||
return keyList;
|
||||
}
|
||||
|
||||
|
||||
} // namespace SimpleConfig
|
|
@ -28,7 +28,7 @@
|
|||
|
||||
|
||||
namespace scsl {
|
||||
namespace string {
|
||||
namespace scstring {
|
||||
|
||||
|
||||
std::vector<std::string>
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
///
|
||||
/// \file test/config-explorer.cc
|
||||
/// \author K. Isom <kyle@imap.cc>
|
||||
/// \date 2023-10-21
|
||||
/// \brief Commandline tools for interacting with simple configurations.
|
||||
///
|
||||
/// Copyright 2023 K. Isom <kyle@imap.cc>
|
||||
///
|
||||
/// 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.
|
||||
///
|
||||
/// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
/// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
/// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
/// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
/// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
|
||||
/// OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
/// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
/// PERFORMANCE OF THIS SOFTWARE.
|
||||
///
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include <scsl/Flags.h>
|
||||
#include <scsl/SimpleConfig.h>
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int retc = 1;
|
||||
bool listKeys;
|
||||
std::string fileName;
|
||||
std::string prefix;
|
||||
std::string defaultValue;
|
||||
|
||||
auto *flags = new scsl::Flags("config-explorer",
|
||||
"interact with a simple configuration system");
|
||||
flags->Register("-d", "", "set a default value");
|
||||
flags->Register("-f", scsl::FlagType::String, "path to a configuration file");
|
||||
flags->Register("-l", false, "list cached keys at the end");
|
||||
flags->Register("-p", "CX_",
|
||||
"prefix for configuration environment variables");
|
||||
auto parsed = flags->Parse(argc, argv);
|
||||
if (parsed != scsl::Flags::ParseStatus::OK) {
|
||||
std::cerr << "Failed to parse flags: "
|
||||
<< scsl::Flags::ParseStatusToString(parsed) << "\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
flags->GetString("-d", defaultValue);
|
||||
flags->GetString("-f", fileName);
|
||||
flags->GetBool("-l", listKeys);
|
||||
flags->GetString("-p", prefix);
|
||||
scsl::SimpleConfig::SetPrefixGlobal(prefix);
|
||||
|
||||
if (!fileName.empty()) {
|
||||
if (scsl::SimpleConfig::LoadGlobal(fileName) != 0) {
|
||||
std::cerr << "[!] failed to load " << fileName << "\n";
|
||||
return retc;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &key : flags->Args()) {
|
||||
auto val = scsl::SimpleConfig::GetGlobal(key, defaultValue);
|
||||
std::cout << key << ": " << val << "\n";
|
||||
}
|
||||
|
||||
if (listKeys) {
|
||||
std::cout << "[+] cached keys\n";
|
||||
for (auto &key : scsl::SimpleConfig::KeyListGlobal()) {
|
||||
std::cout << "\t- " << key << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
delete flags;
|
||||
return retc;
|
||||
}
|
|
@ -42,30 +42,30 @@ TestTrimming(std::string line, std::string lExpected, std::string rExpected, std
|
|||
std::string result;
|
||||
std::string message;
|
||||
|
||||
result = string::TrimLeadingWhitespaceDup(line);
|
||||
result = scstring::TrimLeadingWhitespaceDup(line);
|
||||
message = "TrimLeadingDup(\"" + line + "\"): '" + result + "'";
|
||||
sctest::Assert(result == lExpected, message);
|
||||
|
||||
result = string::TrimTrailingWhitespaceDup(line);
|
||||
result = scstring::TrimTrailingWhitespaceDup(line);
|
||||
message = "TrimTrailingDup(\"" + line + "\"): '" + result + "'";
|
||||
sctest::Assert(result == rExpected, message);
|
||||
|
||||
result = string::TrimWhitespaceDup(line);
|
||||
result = scstring::TrimWhitespaceDup(line);
|
||||
message = "TrimDup(\"" + line + "\"): '" + result + "'";
|
||||
sctest::Assert(result == expected, message);
|
||||
|
||||
result = line;
|
||||
string::TrimLeadingWhitespace(result);
|
||||
scstring::TrimLeadingWhitespace(result);
|
||||
message = "TrimLeadingDup(\"" + line + "\"): '" + result + "'";
|
||||
sctest::Assert(result == lExpected, message);
|
||||
|
||||
result = line;
|
||||
string::TrimTrailingWhitespace(result);
|
||||
scstring::TrimTrailingWhitespace(result);
|
||||
message = "TrimTrailingDup(\"" + line + "\"): '" + result + "'";
|
||||
sctest::Assert(result == rExpected, message);
|
||||
|
||||
result = line;
|
||||
string::TrimWhitespace(result);
|
||||
scstring::TrimWhitespace(result);
|
||||
message = "TrimDup(\"" + line + "\"): '" + result + "'";
|
||||
sctest::Assert(result == expected, message);
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ std::function<bool()>
|
|||
TestSplit(std::string line, std::string delim, size_t maxCount, std::vector<std::string> expected)
|
||||
{
|
||||
return [line, delim, maxCount, expected]() {
|
||||
return string::SplitN(line, delim, maxCount) == expected;
|
||||
return scstring::SplitN(line, delim, maxCount) == expected;
|
||||
|
||||
};
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ TestSplitChar()
|
|||
{
|
||||
auto expected = std::vector<std::string>{"hello", "world"};
|
||||
const auto *inputLine = "hello=world\n";
|
||||
auto actual = string::SplitKeyValuePair(inputLine, '=');
|
||||
auto actual = scstring::SplitKeyValuePair(inputLine, '=');
|
||||
|
||||
return actual == expected;
|
||||
}
|
||||
|
@ -109,11 +109,11 @@ TestWrapping()
|
|||
"hope so.",
|
||||
};
|
||||
|
||||
auto wrapped = string::WrapText(testLine, 16);
|
||||
auto wrapped = scstring::WrapText(testLine, 16);
|
||||
if (wrapped.size() != expected.size()) {
|
||||
std::cerr << string::VectorToString(wrapped)
|
||||
std::cerr << scstring::VectorToString(wrapped)
|
||||
<< " != "
|
||||
<< string::VectorToString(expected)
|
||||
<< scstring::VectorToString(expected)
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
|
@ -127,7 +127,7 @@ TestWrapping()
|
|||
return false;
|
||||
}
|
||||
|
||||
// string::WriteTabIndented(std::cout, wrapped, 4, true);
|
||||
// scstring::WriteTabIndented(std::cout, wrapped, 4, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -149,7 +149,6 @@ main(int argc, char *argv[])
|
|||
if (parsed != scsl::Flags::ParseStatus::OK) {
|
||||
std::cerr << "Failed to parse flags: "
|
||||
<< scsl::Flags::ParseStatusToString(parsed) << "\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
sctest::SimpleSuite suite;
|
||||
|
|
Loading…
Reference in New Issue