From 1fad554a1f94aea4c83616dfcb4595fb9339c1d5 Mon Sep 17 00:00:00 2001 From: "matthias@arch" Date: Mon, 26 Sep 2022 20:31:55 +0200 Subject: [PATCH] Moved string stuff to new files --- src/util/string.cpp | 31 +++ src/util/string.hpp | 38 ++++ src/util/string_concepts.hpp | 99 ++++++++ src/util/string_conversion.cpp | 119 ++++++++++ src/util/string_conversion.hpp | 398 +++++++++++++++++++++++++++++++++ src/util/util.cpp | 125 ----------- src/util/util.hpp | 108 ++------- 7 files changed, 708 insertions(+), 210 deletions(-) create mode 100644 src/util/string.cpp create mode 100644 src/util/string.hpp create mode 100644 src/util/string_concepts.hpp create mode 100644 src/util/string_conversion.cpp create mode 100644 src/util/string_conversion.hpp diff --git a/src/util/string.cpp b/src/util/string.cpp new file mode 100644 index 0000000..6045a1a --- /dev/null +++ b/src/util/string.cpp @@ -0,0 +1,31 @@ +#include "string.hpp" + +#include + + +namespace gz::util { + +std::vector splitStringInVector(std::string& s, char separator) { + // remove linebreaks from the end + if (*(s.end()) == '\n') { s.erase(s.end()); } + + /* std::unique_ptr> params (new std::unordered_map); */ + std::vector v; + std::stringstream ss(s); + std::string temp; + + while (std::getline(ss, temp, separator)) { + // if has "=": store latter part in vector + if (temp.find("=") != std::string::npos) { + int eqPos = temp.find("="); + v.emplace_back(temp.substr(eqPos + 1, temp.length())); + } + else { + v.emplace_back(temp); + } + } + return v; + +} + +} // namespace gz::util diff --git a/src/util/string.hpp b/src/util/string.hpp new file mode 100644 index 0000000..18808d2 --- /dev/null +++ b/src/util/string.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include +#include +#include + +namespace gz::util { + + /** + * @todo document + */ + std::vector splitStringInVector(std::string& s, char separator = ','); + + /** + * @name Map with string type as key, works with strings, string_view and char* + * @{ + */ + struct string_hash + { + using hash_type = std::hash; + using is_transparent = void; + + size_t operator()(const char* str) const { return hash_type{}(str); } + size_t operator()(std::string_view str) const { return hash_type{}(str); } + size_t operator()(std::string const& str) const { return hash_type{}(str); } + }; + template + using unordered_string_map = std::unordered_map>; + /** + * @} + */ + +} // namespace gz::util + +/** + * @file + * @brief Contains utility for strings + */ diff --git a/src/util/string_concepts.hpp b/src/util/string_concepts.hpp new file mode 100644 index 0000000..b398844 --- /dev/null +++ b/src/util/string_concepts.hpp @@ -0,0 +1,99 @@ +#pragma once + +#include +#include +#include + +namespace gz::util { + +// +// CONVERT TO STRING CONCEPTS +// + // ELEMENTARY TYPES + /// is (similar or convertible to) std::string + template + concept Stringy = std::same_as || std::convertible_to; + + /// has .to_string() const member + template + concept HasToStringMember = !Stringy && requires(const T& t) { { t.to_string() }-> Stringy; }; + + /// works with std::to_string(), except bool + template + concept WorksWithStdToString = !std::same_as && !Stringy && !HasToStringMember && requires(const T& t) { { std::to_string(t) } -> Stringy; }; + + template + concept _ElementaryTypeConvertibleToString = Stringy || HasToStringMember || WorksWithStdToString; + + + // CONTAINER + /// Forward range having string-convertible elements + template + concept ContainerConvertibleToString = !_ElementaryTypeConvertibleToString and std::ranges::forward_range and _ElementaryTypeConvertibleToString>; + + template + concept _ElementaryTypeOrForwardRangeConvertibleToString = _ElementaryTypeConvertibleToString || ContainerConvertibleToString; + + /// Pair having string-convertible elements + template + concept PairConvertibleToString = !ContainerConvertibleToString and requires(const T& p) { + requires _ElementaryTypeOrForwardRangeConvertibleToString; + requires _ElementaryTypeOrForwardRangeConvertibleToString; + }; + + /// Container having string-convertible pairs + template + concept MapConvertibleToString = !PairConvertibleToString and !_ElementaryTypeOrForwardRangeConvertibleToString and + std::ranges::forward_range and PairConvertibleToString>; + + template + concept _ContainerTypeConvertibleToString = PairConvertibleToString || ContainerConvertibleToString || MapConvertibleToString; + + template + concept _ElementaryTypeOrContainerConvertibleToString = _ElementaryTypeConvertibleToString || _ContainerTypeConvertibleToString; + + // VECTOR + /// Type having string-convertible x, y members + template + concept Vector2ConvertibleToString = !_ElementaryTypeOrContainerConvertibleToString && + requires(T t) { + { t.x } -> _ElementaryTypeOrContainerConvertibleToString; + { t.y } -> _ElementaryTypeOrContainerConvertibleToString; + requires sizeof(t.x) * 2 == sizeof(T); + }; + /// Type having string-convertible x, y, z members + template + concept Vector3ConvertibleToString = !_ElementaryTypeOrContainerConvertibleToString && + requires(T t) { + { t.x } -> _ElementaryTypeOrContainerConvertibleToString; + { t.y } -> _ElementaryTypeOrContainerConvertibleToString; + { t.z } -> _ElementaryTypeOrContainerConvertibleToString; + requires sizeof(t.x) * 3 == sizeof(T); + }; + /// Type having string-convertible x, y, z, w members + template + concept Vector4ConvertibleToString = !_ElementaryTypeOrContainerConvertibleToString && + requires(T t) { + { t.x } -> _ElementaryTypeOrContainerConvertibleToString; + { t.y } -> _ElementaryTypeOrContainerConvertibleToString; + { t.z } -> _ElementaryTypeOrContainerConvertibleToString; + { t.w } -> _ElementaryTypeOrContainerConvertibleToString; + requires sizeof(t.x) * 4 == sizeof(T); + }; + + // POINTER + /// Everything from string-convertibleNoPtr but "behind" a pointer + template + concept PointerConvertibleToString = requires(const T t) { { *t } -> _ElementaryTypeOrContainerConvertibleToString; }; + +} // namespace gz::util + +namespace gz { +} + +/** + * @file + * @brief Concepts used for the to_string() functions + * @details + * These concepts are used + */ diff --git a/src/util/string_conversion.cpp b/src/util/string_conversion.cpp new file mode 100644 index 0000000..43daa37 --- /dev/null +++ b/src/util/string_conversion.cpp @@ -0,0 +1,119 @@ +#include "string_conversion.hpp" +#include "../exceptions.hpp" +#include "regex.hpp" + + +namespace gz { + +bool isInt(const std::string& s) { + return std::regex_match(s, re::types::intT); +} +bool isInt(const std::string_view& s) { + return re::regex_match(s, re::types::intT); +} +bool isUInt(const std::string& s) { + return std::regex_match(s, re::types::uintT); +} +bool isUInt(const std::string_view& s) { + return re::regex_match(s, re::types::uintT); +} +bool isFloal(const std::string& s) { + return std::regex_match(s, re::types::floatT); +} +bool isFloat(const std::string_view& s) { + return re::regex_match(s, re::types::floatT); +} + + +int getIntOr(const std::string& s, int fallback) noexcept { + try { + fallback = std::stoi(s); + } + catch (...) {} + return fallback; +} + + +unsigned int getUnsignedIntOr(const std::string& s, unsigned int fallback) noexcept { + try { + fallback = std::stoul(s); + } + catch (...) {} + return fallback; +} + + +double getDoubleOr(const std::string& s, double fallback) noexcept { + try { + fallback = std::stod(s); + } + catch (...) {} + return fallback; +} + + +float getFloatOr(const std::string& s, float fallback) noexcept { + try { + fallback = std::stof(s); + } + catch (...) {} + return fallback; +} + + +bool getBoolOr(const std::string& s, bool fallback) noexcept { + if (s == "true" or s == "True" or s == "1") { + fallback = true; + } + else if (s == "false" or s == "False" or s == "0") { + fallback = false; + } + return fallback; +} + + +std::string getStringOr(const std::string& s, const std::string& fallback) noexcept { + if (s == "") { return fallback; } + else { return s; } +} + + +// TODO: remove? +/* // int = 0, double = 1, string = 2 */ +/* std::variant getVariant(std::string value, GetVariantType type, bool bFallback, int iFallback, double dFallback, const char* sFallback) { */ +/* std::variant val = value; */ +/* /1* cout << "id-attr" << id << attr << "val: " << std::get(val); *1/ */ +/* switch (type) { */ +/* // to integer */ +/* case INT: */ +/* val = getIntOr(value, iFallback); */ +/* break; */ +/* case DOUBLE: */ +/* val = getDoubleOr(value, dFallback); */ +/* break; */ +/* case BOOL: */ +/* val = getBoolOr(value, bFallback); */ +/* break; */ +/* case STRING: */ +/* val = getStringOr(value, sFallback); */ +/* break; */ +/* } */ +/* return val; */ +/* } */ + +// +// CONVERT FROM STRING +// +template<> +bool from_string(const std::string& s) { + if (s == "true" or s == "True" or s == "1") { + return true; + } + else if (s == "false" or s == "False" or s == "0") { + return false; + } + throw InvalidArgument("s is not a bool: '" + s + "'", "from_string"); +} + + +} // namespace gz diff --git a/src/util/string_conversion.hpp b/src/util/string_conversion.hpp new file mode 100644 index 0000000..a0110d3 --- /dev/null +++ b/src/util/string_conversion.hpp @@ -0,0 +1,398 @@ +#pragma once + +#include "string_concepts.hpp" + +#include + +namespace gz { + +/** + * @name Functions that determine if s is a string representation of a certain type, using regex. + * @{ + */ + bool isInt(const std::string& s); + bool isInt(const std::string_view& s); + bool isUInt(const std::string& s); + bool isUInt(const std::string_view& s); + bool isFloat(const std::string& s); + bool isFloat(const std::string_view& s); +/** + * @} + */ + + +/** + * @name Convert to type or return fallback + * @todo Use string_views wothout constructing a std::string + * @{ + */ + int getIntOr(const std::string& s, int fallback=0) noexcept; + inline int getIntOr(const std::string_view& s, int fallback=0) noexcept { return getIntOr(std::string(s), fallback); } + + unsigned int getUnsignedIntOr(const std::string& s, unsigned int fallback=0) noexcept; + /* inline unsigned int getUnsignedIntOr(const std::string&& s, unsigned int fallback=0) { return getUnsignedIntOr(s, fallback); } */ + inline unsigned int getUnsignedIntOr(const std::string_view& s, unsigned int fallback=0) noexcept { return getUnsignedIntOr(std::string(s), fallback); } + + double getDoubleOr(const std::string& s, double fallback=0) noexcept; + /* inline double getDoubleOr(const std::string&& s, double fallback=0) { return getDoubleOr(s, fallback); } */ + inline double getDoubleOr(const std::string_view& s, double fallback=0) noexcept { return getDoubleOr(std::string(s), fallback); } + + float getFloatOr(const std::string& s, float fallback=0) noexcept; + /* inline float getFloatOr(const std::string&& s, float fallback=0) { return getDoubleOr(s, fallback); } */ + inline float getFloatOr(const std::string_view& s, float fallback=0) noexcept { return getDoubleOr(std::string(s), fallback); } + + bool getBoolOr(const std::string& s, bool fallback=false) noexcept; + /* inline bool getBoolOr(const std::string&& s, bool fallback=false) { return getBoolOr(s, fallback); } */ + inline bool getBoolOr(const std::string_view& s, bool fallback=false) noexcept { return getBoolOr(std::string(s), fallback); } + + /** + * @brief Returns the string or fallback if string is empty. + */ + std::string getStringOr(const std::string& s, const std::string& fallback="none") noexcept; +/** + * @} + */ + // TODO: remove? + /* enum GetVariantType { */ + /* INT, DOUBLE, STRING, BOOL, */ + /* }; */ + /* + * @brief Converts the given string to the requested type and puts returns it in a variant + * @details + * Tries to convert the string to the specified type. + * If that fails a default value is returned. + * This is either 1 for int or double or "none" for strings. + * + * @param value String which should be converted + * @param type GetVariantType datatype to return in the variant + * + * @returns Variant containing the value in the given datatype. + */ + /* std::variant getVariant(std::string value, GetVariantType type=STRING, bool bFallback=false, int iFallback=0, double dFallback=0, const char* sFallback="none"); */ + +// +// CONVERT TO STRING +// +/** + * @name Converting a type to string + * @{ + */ + /** + * @brief Construct a string from a string like-type + */ + template + inline std::string to_string(const T& t) { + return t; + } + + /** + * @overload + * @brief Construct a string from a type having a to_string() const member function + */ + template + inline std::string to_string(const T& t) { + return t.to_string(); + } + + /** + * @overload + * @brief Construct a string from a number + * @returns std::to_string(t) + */ + template + inline std::string to_string(const T& t) { + return std::to_string(t); + } + + /** + * @brief Construct a string from a boolean + * @details + * Unlike std::to_string(bool), which returns 0 or 1, this function returns "true" or "false" + * @returns "true" or "false" + */ + inline std::string to_string(const bool& b) { + return b ? "true" : "false"; + } + + /** + * @overload + * @brief Construct a string from a forward range + */ + template + std::string to_string(const T& t) { + std::string s = "[ "; + for (auto it = t.begin(); it != t.end(); it++) { + s += to_string(*it) + ", "; + } + if (s.size() > 2) { + s.erase(s.size() - 2); + } + s += " ]"; + return s; + } + + /** + * @overload + * @brief Construct a string from a pair + */ + template + inline std::string to_string(const T& t) { + return "{ " + to_string(t.first) + ", " + to_string(t.second) + " }"; + } + + /** + * @overload + * @brief Construct a string from a forward range holding a pair, eg a map + */ + template + std::string to_string(const T& t) { + std::string s = "{ "; + for (const auto& [k, v] : t) { + s += to_string(k) + ": "; + s += to_string(v) + ", "; + } + if (s.size() > 2) { + s.erase(s.size() - 2); + } + s += " }"; + return s; + } + + /** + * @overload + * @brief Construct a string from the element the pointer points at + */ + template + inline std::string to_string(const T& t) { + return to_string(*t); + } + + /** + * @overload + * @brief Construct a string from a vector with x, y members + */ + template + inline std::string to_string(const T& t) { + std::string s = "( "; + s += to_string(t.x) + ", "; + s += to_string(t.z) + " )"; + return s; + } + + /** + * @overload + * @brief Construct a string from a vector with x, y members + */ + template + inline std::string to_string(const T& t) { + std::string s = "( "; + s += to_string(t.x) + ", "; + s += to_string(t.y) + ", "; + s += to_string(t.z) + " )"; + return s; + } + + /** + * @overload + * @brief Construct a string from a vector with x, y, z, w members + */ + template + inline std::string to_string(const T& t) { + std::string s = "( "; + s += to_string(t.x) + ", "; + s += to_string(t.y) + ", "; + s += to_string(t.z) + ", "; + s += to_string(t.w) + " )"; + return s; + } +/** +* @} +*/ + +// +// CONVERT FROM STRING +// +/** + * @name Construct a type from a string + * @note + * The from_string()functions (except for the bool one) simply return std::stoXX. These can throw std::invalid_argument and std::out_of_range. + * See https://en.cppreference.com/w/cpp/string/basic_string/stol + */ + template + concept GetTypeFromStringImplemented = + std::same_as or + std::same_as or + std::same_as or + std::same_as or + std::same_as or + std::same_as or + std::same_as or + std::same_as or + std::same_as or + std::same_as; + + template + T from_string(const std::string& s); + + /// @returns std::stoi(s) + template<> inline int from_string(const std::string& s) { + return std::stoi(s); + } + /// @returns std::stol(s) + template<> inline long from_string(const std::string& s) { + return std::stol(s); + } + /// @returns std::stoll(s) + template<> inline long long from_string(const std::string& s) { + return std::stoll(s); + } + /// @returns std::stoul(s) + template<> inline unsigned int from_string(const std::string& s) { + return std::stoul(s); + } + /// @returns std::stoul(s) + template<> inline unsigned long from_string(const std::string& s) { + return std::stoul(s); + } + /// @returns std::stoull(s) + template<> inline unsigned long long from_string(const std::string& s) { + return std::stoull(s); + } + /// @returns std::stof(s) + template<> inline float from_string(const std::string& s) { + return std::stof(s); + } + /// @returns std::stod(s) + template<> inline double from_string(const std::string& s) { + return std::stod(s); + } + /// @returns std::stold(s) + template<> inline long double from_string(const std::string& s) { + return std::stold(s); + } + /** + * @brief Convert a string to bool + * @details + * - returns true if s = "true" or "True" or "1" + * - returns false if s = "false" or "False" or "0" + * - throws InvalidArgument otherwise + */ + template<> bool from_string(const std::string& s); +/** +* @} +*/ + + +// +// CONCEPTS +// + /** + * @brief Any type where to_string(t) const exists returns a string-like type + * @note The function only has to exist, it does not have to be noexcept! + */ + template + concept ConvertibleToString = requires(const T& t) { { to_string(t) } -> util::Stringy; }; + /* concept CovertibleToString = requires(const T& t) { { to_string(t) }; }; */ + + /** + * @brief Any type where from_string(string) exists and returns T + * @note The function only has to exist, it does not have to be noexcept! + */ + template + concept ConstructibleFromString = requires(const std::string& s) { + { from_string(s) } -> std::same_as; + }; + + /** + * @brief Any type where to_string(t) and from_string(string) exist + */ + template + concept StringConvertible = ConvertibleToString and ConstructibleFromString; + +} // namespace gz + +/** + * @file + * @brief Contains utilities for type conversions from string + */ + +namespace gz { +/** + * @page string_conversion String conversion + * @section sc_about About + * This library provides utility for string conversion, from and to std::string. + * + * There also three important concepts, ConvertibleToString, ConstructibleFromString and @ref StringConvertible which are + * used in the @ref Log "logger" and the @ref SettingsManager "settings manager" to log and store types. + * + * If you want to use your own data type with one of these, + * you can easily @ref sc_overloads "write your own string conversion" function for your custom datatype. + * + * @section sc_to_string Convert to string + * You can use the to_string() function to turn certain types into strings. + * Concepts are used to determine the correct overload of the function. + * + * The concept ConvertibleToString is satisfied for types that can be converted to string + * using to_string(). + * + * @section sc_from_string Construct from string + * You can use the from_string() function to create certain types from a string. + * + * The concept ConstructibleFromString is satisfied for types that can be constructed from a string with from_string(). + * + * When constructing something from a string, there is of course the problem that errors occur at runtime when + * the string is unsuitable for construction. In this case, the from_string functions from this library throw a InvalidArgument exception. + * + * @section sc_overloads Overloading the string conversion functions + * @subsection sc_to_string_ov Overload for to_string + * If you want your custom type to be convertible to string, you have different options. + * You can either add an to_string() const member to your class or overload + * std::string to_string(const T&). + * Example for a class called Custom + * @code + * std::string to_string(const Custom& c) { + * std::string s; + * ... + * return s; + * } + * @endcode + * To satisfy the concept, this overload has of course to visible by the compiler, + * so you have to at least declare it in a header file. + * + + * @subsection sc_from_string_ov Overload for from_string + * Writing an overload for from_string needs a little bit more boiler plate. + * Since from_string is a templated function, you need to declare it as such. + * The function declaration in this library uses a concept so that it is only + * declared for the types that are actully implemented. + * Example for a class called Custom + * @code + * // declare as template, but only for Custom + * template T> + * Custom from_string(const std::string& s); + * + * // instantiation/definition, but only for Custom + * template<> + * Custom from_string(const std::string& s) { + * ... + * return Custom(...); + * }; + * @endcode + * + * @subsection sc_notes Notes + * You should write your function so that the output of one can be used as input of the other. + * In other words: + * @code + * Custom c1; + * Custom c2 = from_string(to_string(c1)); + * assert(c1 == c2); + * @endcode + * + * SettingsManager expects the strings from to_string() to be a single line. + * If it has multiple lines, it will not load it correctly when loading from a file. + * + * @todo Implement from_string for vectors that hold ConstructibleFromString types + * @todo Make from_string throw InvalidArgument, write docs + * @todo Make macro for all types/concepts where someone would want to implement from_string and to_string explicitly, eg vectors + */ +} // namespace gz diff --git a/src/util/util.cpp b/src/util/util.cpp index 43c7d4d..e69de29 100755 --- a/src/util/util.cpp +++ b/src/util/util.cpp @@ -1,125 +0,0 @@ -#include "util.hpp" - -#include "gz_regex.hpp" - -namespace gz::util { -// -// Type Conversion -// -bool isInt(std::string& s) { - return std::regex_match(s, re::types::intT); -} -bool isInt(std::string_view& s) { - return re::regex_match(s, re::types::intT); -} -int getInt(std::string& s, int fallback) { - try { - fallback = std::stoi(s); - } - catch (std::invalid_argument& e) {} - return fallback; -} - - -bool isUInt(std::string& s) { - return std::regex_match(s, re::types::uintT); -} -bool isUInt(std::string_view& s) { - return re::regex_match(s, re::types::uintT); -} -unsigned int getUnsignedInt(std::string& s, unsigned int fallback) { - try { - fallback = std::stoul(s); - } - catch (std::invalid_argument& e) {} - return fallback; -} - - -double getDouble(std::string& s, double fallback) { - try { - fallback = std::stod(s); - } - catch (std::invalid_argument& e) {} - return fallback; -} - - -bool isFloal(std::string& s) { - return std::regex_match(s, re::types::floatT); -} -bool isFloat(std::string_view& s) { - return re::regex_match(s, re::types::floatT); -} -float getFloat(std::string& s, float fallback) { - try { - fallback = std::stof(s); - } - catch (std::invalid_argument& e) {} - return fallback; -} - - - -bool getBool(std::string& s, bool fallback) { - if (s == "true" or s == "True" or s == "1") { - fallback = true; - } - return fallback; -} - - -std::string getString(std::string s, std::string fallback) { - if (s == "") { return fallback; } - else { return s; } -} - - -// int = 0, double = 1, string = 2 -std::variant getVariant(std::string value, Type type, bool bFallback, int iFallback, double dFallback, const char* sFallback) { - std::variant val = value; - /* cout << "id-attr" << id << attr << "val: " << std::get(val); */ - switch (type) { - // to integer - case INT: - val = getInt(value, iFallback); - break; - case DOUBLE: - val = getDouble(value, dFallback); - break; - case BOOL: - val = getBool(value, bFallback); - break; - default: - val = getString(value, sFallback); - break; - } - return val; -} - - - -std::vector splitStringInVector(std::string& s, char separator) { - // remove linebreaks from the end - if (*(s.end()) == '\n') { s.erase(s.end()); } - - /* std::unique_ptr> params (new std::unordered_map); */ - std::vector v; - std::stringstream ss(s); - std::string temp; - - while (std::getline(ss, temp, separator)) { - // if has "=": store latter part in vector - if (temp.find("=") != std::string::npos) { - int eqPos = temp.find("="); - v.emplace_back(temp.substr(eqPos + 1, temp.length())); - } - else { - v.emplace_back(temp); - } - } - return v; - -} - -} // namespace gz::util diff --git a/src/util/util.hpp b/src/util/util.hpp index 7a756ea..029ca96 100755 --- a/src/util/util.hpp +++ b/src/util/util.hpp @@ -1,96 +1,56 @@ #pragma once -#include -#include -#include -#include +#include namespace gz::util { - -// -// Type conversion -// - enum Type { - UINT, INT, DOUBLE, FLOAT, STRING, BOOL, - }; - - bool isInt(std::string& s); - bool isInt(std::string_view& s); - int getInt(std::string& s, int fallback=0); - inline int getInt(std::string&& s, int fallback=0) { return getInt(s, fallback); } - /** - * @todo Find a way to convert string_view to int without creating a string from it - */ - inline int getInt(std::string_view s, int fallback=0) { return getInt(std::string(s), fallback); } - - bool isUInt(std::string& s); - bool isUInt(std::string_view& s); - unsigned int getUnsignedInt(std::string& s, unsigned int fallback=0); - inline unsigned int getUnsignedInt(std::string&& s, unsigned int fallback=0) { return getUnsignedInt(s, fallback); } - inline unsigned int getUnsignedInt(std::string_view s, unsigned int fallback=0) { return getUnsignedInt(std::string(s), fallback); } - - double getDouble(std::string& s, double fallback=0); - inline double getDouble(std::string&& s, double fallback=0) { return getDouble(s, fallback); } - inline double getDouble(std::string_view s, double fallback=0) { return getDouble(std::string(s), fallback); } - - bool isFloat(std::string& s); - bool isFloat(std::string_view& s); - float getFloat(std::string& s, float fallback=0); - inline float getFloat(std::string&& s, float fallback=0) { return getDouble(s, fallback); } - inline float getFloat(std::string_view s, float fallback=0) { return getDouble(std::string(s), fallback); } - - bool getBool(std::string& s, bool fallback=false); - inline bool getBool(std::string&& s, bool fallback=false) { return getBool(s, fallback); } - inline bool getBool(std::string_view s, bool fallback=false) { return getBool(std::string(s), fallback); } - - /** - * @brief Returns the string or fallback if string is empty. - */ - std::string getString(std::string s, std::string fallback="none"); - /** - * @brief Converts the given string to the requested type and puts returns it in a variant - * @details - * Tries to convert the string to the specified type. - * If that fails a default value is returned. - * This is either 1 for int or double or "none" for strings. - * - * @param value String which should be converted - * @param type Datatype: 0 = int, 1 = double, 2 = string (default when wrong numer is given) - * - * @returns Variant containing the value in the given datatype. - * @warning Make sure to use the correct type when extracting the value from the returned variant! - */ - std::variant getVariant(std::string value, Type type=STRING, bool bFallback=false, int iFallback=0, double dFallback=0, const char* sFallback="none"); - // // INDEX UTILITY // + /** + * @brief Increment an index. Up to containerSize, then restart at 0 + */ template inline void incrementIndex(I& i, const S containerSize) { if (i < containerSize - 1) { i++; } else { i = 0; } } + /** + * @brief Decrement an index. Down to 0, then restart at containerSize - 1 + */ template inline void decrementIndex(I& i, const S containerSize) { if (i > 0) { i--; } else { i = containerSize - 1; } } + /** + * @brief Like incrementIndex, but returns a new number + */ template inline I getIncrementedIndex(const I i, const S containerSize) { if (i < containerSize - 1) { return i + 1; } else { return 0; } } + /** + * @brief Like decrementIndex, but returns a new number + */ template inline I getDecrementedIndex(const I i, const S containerSize) { if (i > 0) { return i - 1; } else { return containerSize - 1; } } - /// Make wrap incices around: i = size + 2 -> i = 2, i = -2 -> i = size - 2 + + /** + * @brief Wrap an index around, to make it valid + * @details + * Example: + * - i = containerSize + 2 -> return 2 + * - i = -2 -> return (containerSize - 1) - 2 + */ template - size_t getValidIndex(const I i, const S containerSize) { + std::size_t getValidIndex(const I i, const S containerSize) { if (i < 0) { - return containerSize - (-i) % containerSize - 1; + return (containerSize - 1) - (-i) % containerSize; } else if (i >= static_cast(containerSize)) { return i % containerSize; @@ -98,31 +58,9 @@ namespace gz::util { return i; } -// -// STRING -// - std::vector splitStringInVector(std::string& s, char separator = '|'); - - /** - * @name Map with string type as key, works with strings, string_view and char* - * @{ - */ - struct string_hash - { - using hash_type = std::hash; - using is_transparent = void; - - size_t operator()(const char* str) const { return hash_type{}(str); } - size_t operator()(std::string_view str) const { return hash_type{}(str); } - size_t operator()(std::string const& str) const { return hash_type{}(str); } - }; - template - using string_map = std::unordered_map>; } // namespace gz::util -#undef umap - /** * @file * @brief Various utilites