#pragma once /** * \file ToString.h * * Conversion from various types to std::string * */ #include "TimeHelper.h" #include "TypeTraits.h" #include "sls_detector_exceptions.h" #include "string_utils.h" #include #include #include #include #include namespace sls { std::string ToString(const std::vector &vec, const char delimiter = ' '); /** Convert std::chrono::duration with specified output unit */ template typename std::enable_if::value, std::string>::type ToString(T t, const std::string &unit) { using std::chrono::duration; using std::chrono::duration_cast; std::ostringstream os; if (unit == "ns") os << duration_cast>(t).count() << unit; else if (unit == "us") os << duration_cast>(t).count() << unit; else if (unit == "ms") os << duration_cast>(t).count() << unit; else if (unit == "s") os << duration_cast>(t).count() << unit; else throw std::runtime_error("Unknown unit: " + unit); return os.str(); } /** Convert std::chrono::duration automatically selecting the unit */ template typename std::enable_if::value, std::string>::type ToString(From t) { auto tns = std::chrono::duration_cast(t); if (time::abs(tns) < std::chrono::microseconds(1)) { return ToString(tns, "ns"); } else if (time::abs(tns) < std::chrono::milliseconds(1)) { return ToString(tns, "us"); } else if (time::abs(tns) < std::chrono::milliseconds(99)) { return ToString(tns, "ms"); } else { return ToString(tns, "s"); } } /** Conversion of floating point values, removes trailing zeros*/ template typename std::enable_if::value, std::string>::type ToString(const T &value) { auto s = std::to_string(value); s.erase(s.find_last_not_of('0') + 1u, std::string::npos); s.erase(s.find_last_not_of('.') + 1u, std::string::npos); return s; } /** Conversion of integer types, do not remove trailing zeros */ template typename std::enable_if::value, std::string>::type ToString(const T &value) { return std::to_string(value); } /** For a container loop over all elements and call ToString */ template typename std::enable_if::value, std::string>::type ToString(const T &container) { std::ostringstream os; os << '['; if (!container.empty()) { auto it = container.cbegin(); os << ToString(*it++); while (it != container.cend()) os << ", " << ToString(*it++); } os << ']'; return os.str(); } /** Container and specified unit, call ToString(value, unit) */ template typename std::enable_if::value, std::string>::type ToString(const T &container, const std::string &unit) { std::ostringstream os; os << '['; if (!container.empty()) { auto it = container.cbegin(); os << ToString(*it++, unit); while (it != container.cend()) os << ", " << ToString(*it++, unit); } os << ']'; return os.str(); } template T StringTo(const std::string &t, const std::string &unit) { double tval{0}; try { tval = std::stod(t); } catch (const std::invalid_argument &e) { throw sls::RuntimeError("Could not convert string to time"); } using std::chrono::duration; using std::chrono::duration_cast; if (unit == "ns") { return duration_cast(duration(tval)); } else if (unit == "us") { return duration_cast(duration(tval)); } else if (unit == "ms") { return duration_cast(duration(tval)); } else if (unit == "s" || unit.empty()) { return duration_cast(std::chrono::duration(tval)); } else { throw sls::RuntimeError( "Invalid unit in conversion from string to std::chrono::duration"); } } template T StringTo(std::string t) { auto unit = RemoveUnit(t); return StringTo(t, unit); } } // namespace sls