Added toHex/Oct/BinString for forward ranges

This commit is contained in:
matthias@arch 2022-10-30 01:16:16 +02:00
parent 9eb1a7fcb0
commit dcc00c4be0
2 changed files with 131 additions and 7 deletions

View File

@ -1,9 +1,12 @@
#pragma once #pragma once
#include<ranges>
#include <concepts> #include <concepts>
#include <string> #include <string>
#include <string_view> #include <string_view>
#define GZ_UTIL_STRING_CONCEPTS
namespace gz::util { namespace gz::util {
// //
@ -59,7 +62,7 @@ namespace gz::util {
concept _ElementaryTypeOrContainerConvertibleToString = _ElementaryTypeConvertibleToString<T> || _ContainerTypeConvertibleToString<T>; concept _ElementaryTypeOrContainerConvertibleToString = _ElementaryTypeConvertibleToString<T> || _ContainerTypeConvertibleToString<T>;
// VECTOR // VECTOR
/// Type having string-convertible x, y members /// Type having string-convertible x, y members and sizeof(T) == 2 * sizeof(x)
template<typename T> template<typename T>
concept Vector2ConvertibleToString = !_ElementaryTypeOrContainerConvertibleToString<T> && concept Vector2ConvertibleToString = !_ElementaryTypeOrContainerConvertibleToString<T> &&
requires(T t) { requires(T t) {
@ -67,7 +70,7 @@ namespace gz::util {
{ t.y } -> _ElementaryTypeOrContainerConvertibleToString; { t.y } -> _ElementaryTypeOrContainerConvertibleToString;
requires sizeof(t.x) * 2 == sizeof(T); requires sizeof(t.x) * 2 == sizeof(T);
}; };
/// Type having string-convertible x, y, z members /// Type having string-convertible x, y, z members and sizeof(T) == 3 * sizeof(x)
template<typename T> template<typename T>
concept Vector3ConvertibleToString = !_ElementaryTypeOrContainerConvertibleToString<T> && concept Vector3ConvertibleToString = !_ElementaryTypeOrContainerConvertibleToString<T> &&
requires(T t) { requires(T t) {
@ -76,7 +79,7 @@ namespace gz::util {
{ t.z } -> _ElementaryTypeOrContainerConvertibleToString; { t.z } -> _ElementaryTypeOrContainerConvertibleToString;
requires sizeof(t.x) * 3 == sizeof(T); requires sizeof(t.x) * 3 == sizeof(T);
}; };
/// Type having string-convertible x, y, z, w members /// Type having string-convertible x, y, z, w members and sizeof(T) == 4 * sizeof(x)
template<typename T> template<typename T>
concept Vector4ConvertibleToString = !_ElementaryTypeOrContainerConvertibleToString<T> && concept Vector4ConvertibleToString = !_ElementaryTypeOrContainerConvertibleToString<T> &&
requires(T t) { requires(T t) {
@ -87,12 +90,36 @@ namespace gz::util {
requires sizeof(t.x) * 4 == sizeof(T); requires sizeof(t.x) * 4 == sizeof(T);
}; };
/// Type having string-convertible width, height members and sizeof(T) == 2 * sizeof(width)
template<typename T>
concept Extent2DConvertibleToString = !_ElementaryTypeOrContainerConvertibleToString<T> &&
requires(T t) {
{ t.width } -> _ElementaryTypeOrContainerConvertibleToString;
{ t.height } -> _ElementaryTypeOrContainerConvertibleToString;
requires sizeof(t.width) * 2 == sizeof(T);
};
/// Type having string-convertible width, height, depth members and sizeof(T) == 3 * sizeof(width)
template<typename T>
concept Extent3DConvertibleToString = !_ElementaryTypeOrContainerConvertibleToString<T> &&
requires(T t) {
{ t.width } -> _ElementaryTypeOrContainerConvertibleToString;
{ t.height } -> _ElementaryTypeOrContainerConvertibleToString;
{ t.depth } -> _ElementaryTypeOrContainerConvertibleToString;
requires sizeof(t.width) * 3 == sizeof(T);
};
// POINTER // POINTER
/// Everything from string-convertibleNoPtr but "behind" a pointer /// Everything from string-convertibleNoPtr but "behind" a pointer
template<typename T> template<typename T>
concept PointerConvertibleToString = !_ElementaryTypeOrContainerConvertibleToString<T> and concept PointerConvertibleToString = !_ElementaryTypeOrContainerConvertibleToString<T> and
requires(const T t) { { *t } -> _ElementaryTypeOrContainerConvertibleToString; }; requires(const T t) { { *t } -> _ElementaryTypeOrContainerConvertibleToString; };
// HEX/OCT/BIN
// Forward range holding integers
template<typename T>
concept IntegralForwardRange = std::ranges::forward_range<T> and std::integral<std::ranges::range_value_t<T>>;
} // namespace gz::util } // namespace gz::util

View File

@ -87,6 +87,7 @@ namespace gz {
*/ */
/** /**
* @brief Return the string * @brief Return the string
* @returns static_cast<std::string>(t)
*/ */
template<util::Stringy T> template<util::Stringy T>
inline std::string toString(const T& t) { inline std::string toString(const T& t) {
@ -95,6 +96,7 @@ namespace gz {
/** /**
* @brief Construct a string from a string like-type * @brief Construct a string from a string like-type
* @returns std::string(t)
*/ */
template<util::CanConstructString T> template<util::CanConstructString T>
inline std::string toString(const T& t) { inline std::string toString(const T& t) {
@ -104,6 +106,7 @@ namespace gz {
/** /**
* @overload * @overload
* @brief Construct a string from a type having a toString() const member function * @brief Construct a string from a type having a toString() const member function
* @returns t.toString()
*/ */
template<util::HasToStringMember T> template<util::HasToStringMember T>
inline std::string toString(const T& t) { inline std::string toString(const T& t) {
@ -133,6 +136,7 @@ namespace gz {
/** /**
* @overload * @overload
* @brief Construct a string from a forward range * @brief Construct a string from a forward range
* @returns [ x1, x2, ... ]
*/ */
template<util::ContainerConvertibleToString T> template<util::ContainerConvertibleToString T>
std::string toString(const T& t) { std::string toString(const T& t) {
@ -150,15 +154,17 @@ namespace gz {
/** /**
* @overload * @overload
* @brief Construct a string from a pair * @brief Construct a string from a pair
* @returns ( first, second )
*/ */
template<util::PairConvertibleToString T> template<util::PairConvertibleToString T>
inline std::string toString(const T& t) { inline std::string toString(const T& t) {
return "{ " + toString(t.first) + ", " + toString(t.second) + " }"; return "( " + toString(t.first) + ", " + toString(t.second) + " )";
} }
/** /**
* @overload * @overload
* @brief Construct a string from a forward range holding a pair, eg a map * @brief Construct a string from a forward range holding a pair, eg a map
* @returns { first: second, first: second, ... }
*/ */
template<util::MapConvertibleToString T> template<util::MapConvertibleToString T>
std::string toString(const T& t) { std::string toString(const T& t) {
@ -177,6 +183,7 @@ namespace gz {
/** /**
* @overload * @overload
* @brief Construct a string from the element the pointer points at * @brief Construct a string from the element the pointer points at
* @returns *t
*/ */
template<util::PointerConvertibleToString T> template<util::PointerConvertibleToString T>
inline std::string toString(const T& t) { inline std::string toString(const T& t) {
@ -186,6 +193,7 @@ namespace gz {
/** /**
* @overload * @overload
* @brief Construct a string from a vector with x, y members * @brief Construct a string from a vector with x, y members
* @returns ( x, y )
*/ */
template<util::Vector2ConvertibleToString T> template<util::Vector2ConvertibleToString T>
inline std::string toString(const T& t) { inline std::string toString(const T& t) {
@ -198,6 +206,7 @@ namespace gz {
/** /**
* @overload * @overload
* @brief Construct a string from a vector with x, y members * @brief Construct a string from a vector with x, y members
* @returns ( x, y, z )
*/ */
template<util::Vector3ConvertibleToString T> template<util::Vector3ConvertibleToString T>
inline std::string toString(const T& t) { inline std::string toString(const T& t) {
@ -211,6 +220,7 @@ namespace gz {
/** /**
* @overload * @overload
* @brief Construct a string from a vector with x, y, z, w members * @brief Construct a string from a vector with x, y, z, w members
* @returns ( x, y, z, w )
*/ */
template<util::Vector4ConvertibleToString T> template<util::Vector4ConvertibleToString T>
inline std::string toString(const T& t) { inline std::string toString(const T& t) {
@ -222,6 +232,32 @@ namespace gz {
return s; return s;
} }
/**
* @overload
* @brief Construct a string from a type having width and height members
* @returns ( width, height )
*/
template<util::Extent2DConvertibleToString T>
inline std::string toString(const T& t) {
std::string s = "( ";
s += toString(t.width) + ", ";
s += toString(t.height) + " ) ";
return s;
}
/**
* @overload
* @brief Construct a string from a type having width and height members
* @returns ( width, height, depth )
*/
template<util::Extent3DConvertibleToString T>
inline std::string toString(const T& t) {
std::string s = "( ";
s += toString(t.width) + ", ";
s += toString(t.height) + ", ";
s += toString(t.depth) + " ) ";
return s;
}
/** /**
* @overload * @overload
* @brief Construct a string from a type that has toString declared in global namespace * @brief Construct a string from a type that has toString declared in global namespace
@ -428,6 +464,59 @@ namespace gz {
return static_cast<T>(std::bitset<sizeof(T)*8>(s).to_ullong()); return static_cast<T>(std::bitset<sizeof(T)*8>(s).to_ullong());
} }
} }
/**
* @overload
* @brief Construct a string where the elements from a forward range are in hexadecimal format
* @returns [ 0x0001, 0x0002, ... ]
*/
template<util::IntegralForwardRange T>
std::string toHexString(const T& t) {
std::string s = "[ ";
for (auto it = t.begin(); it != t.end(); it++) {
s += toHexString(*it) + ", ";
}
if (s.size() > 2) {
s.erase(s.size() - 2);
}
s += " ]";
return s;
}
/**
* @overload
* @brief Construct a string where the elements from a forward range are in octal format
* @returns [ 00001, 00002, ... ]
*/
template<util::IntegralForwardRange T>
std::string toOctString(const T& t) {
std::string s = "[ ";
for (auto it = t.begin(); it != t.end(); it++) {
s += toOctString(*it) + ", ";
}
if (s.size() > 2) {
s.erase(s.size() - 2);
}
s += " ]";
return s;
}
/**
* @overload
* @brief Construct a string where the elements from a forward range are in octal format
* @returns [ 0b0001, 0b0010, ... ]
*/
template<util::IntegralForwardRange T>
std::string toBinString(const T& t) {
std::string s = "[ ";
for (auto it = t.begin(); it != t.end(); it++) {
s += toBinString(*it) + ", ";
}
if (s.size() > 2) {
s.erase(s.size() - 2);
}
s += " ]";
return s;
}
/// @} /// @}
} // namespace gz } // namespace gz
@ -478,9 +567,17 @@ namespace gz {
* return s; * return s;
* } * }
* @endcode * @endcode
* To satisfy the concept, this overload must of course be visible to the compiler, * @note
* so you have to declare it before including string_conversion.hpp. * To satisfy the concept, any overload must be visible to the compiler when the concept is processed,
* so you have to declare it before including `util/string_concepts.hpp` (which is also included by `util/string_conversion.hpp`, `settings_manager.hpp` and `log.hpp`).
* To ease troubleshooting the include order, `util/string_conversion.hpp` defines the macro `GZ_UTIL_STRING_CONCEPTS`,
* so you can place an assertion like this before declaring your overloads:
* @code
* #ifdef GZ_UTIL_STRING_CONCEPTS
* static_assert(false, "gz-util/util/string_conversion.hpp must not be included before this file!");
* #endif
* @endcode
*
* @subsection sc_fromString_ov Overload for fromString * @subsection sc_fromString_ov Overload for fromString
* Writing an overload for fromString needs a little bit more boiler plate. * Writing an overload for fromString needs a little bit more boiler plate.
* Since fromString is a templated function, you need to declare it as such. * Since fromString is a templated function, you need to declare it as such.