// SPDX-License-Identifier: LGPL-3.0-or-other // Copyright (C) 2021 Contributors to the SLS Detector Package #pragma once /** * \file ToString.h * * Conversion from various types to std::string * */ #include "sls/TimeHelper.h" #include "sls/TypeTraits.h" #include "sls/sls_detector_defs.h" #include "sls/sls_detector_exceptions.h" #include "sls/string_utils.h" #include #include #include #include #include #include #include namespace sls { using defs = slsDetectorDefs; std::string ToString(const defs::runStatus s); std::string ToString(const defs::detectorType s); std::string ToString(const defs::detectorSettings s); std::string ToString(const defs::speedLevel s); std::string ToString(const defs::timingMode s); std::string ToString(const defs::frameDiscardPolicy s); std::string ToString(const defs::fileFormat s); std::string ToString(const defs::externalSignalFlag s); std::string ToString(const defs::readoutMode s); std::string ToString(const defs::dacIndex s); std::string ToString(const std::vector &vec); std::string ToString(const defs::burstMode s); std::string ToString(const defs::timingSourceType s); std::string ToString(const defs::M3_GainCaps s); std::string ToString(const defs::portPosition s); std::string ToString(const defs::streamingInterface s); std::string ToString(const defs::vetoAlgorithm s); std::string ToString(const defs::gainMode s); std::string ToString(const defs::polarity s); std::string ToString(const defs::timingInfoDecoder s); std::string ToString(const defs::collectionMode s); std::string ToString(const slsDetectorDefs::xy &coord); std::ostream &operator<<(std::ostream &os, const slsDetectorDefs::xy &coord); std::string ToString(const slsDetectorDefs::ROI &roi); std::ostream &operator<<(std::ostream &os, const slsDetectorDefs::ROI &roi); std::string ToString(const slsDetectorDefs::rxParameters &r); std::ostream &operator<<(std::ostream &os, const slsDetectorDefs::rxParameters &r); std::string ToString(const slsDetectorDefs::scanParameters &r); std::ostream &operator<<(std::ostream &os, const slsDetectorDefs::scanParameters &r); std::string ToString(const slsDetectorDefs::currentSrcParameters &r); std::ostream &operator<<(std::ostream &os, const slsDetectorDefs::currentSrcParameters &r); std::string ToString(const slsDetectorDefs::pedestalParameters &r); std::ostream &operator<<(std::ostream &os, const slsDetectorDefs::pedestalParameters &r); const std::string &ToString(const std::string &s); /** 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); } /** Conversion of integer types, do not remove trailing zeros */ template typename std::enable_if::value, std::string>::type ToStringHex(const T &value) { std::ostringstream os; os << "0x" << std::hex << value << std::dec; return os.str(); } /** Conversion of integer types, do not remove trailing zeros */ template typename std::enable_if::value, std::string>::type ToStringHex(const T &value, int width) { std::ostringstream os; os << "0x" << std::hex << std::setfill('0') << std::setw(width) << value << std::dec; return os.str(); } /** * hex * For a container loop over all elements and call ToString on the element * Container is excluded */ template typename std::enable_if< is_container::value && !std::is_same::value, std::string>::type ToStringHex(const T &container) { std::ostringstream os; os << '['; if (!container.empty()) { auto it = container.cbegin(); os << ToStringHex(*it++); while (it != container.cend()) os << ", " << ToStringHex(*it++); } os << ']'; return os.str(); } template typename std::enable_if< is_container::value && !std::is_same::value, std::string>::type ToStringHex(const T &container, int width) { std::ostringstream os; os << '['; if (!container.empty()) { auto it = container.cbegin(); os << ToStringHex(*it++, width); while (it != container.cend()) os << ", " << ToStringHex(*it++, width); } os << ']'; return os.str(); } template std::string ToString(const std::map &m) { std::ostringstream os; os << '{'; if (!m.empty()) { auto it = m.cbegin(); os << ToString(it->first) << ": " << ToString(it->second); it++; while (it != m.cend()) { os << ", " << ToString(it->first) << ": " << ToString(it->second); it++; } } os << '}'; return os.str(); } /** * Print a c style array */ template std::string ToString(const T (&arr)[size]) { std::ostringstream os; os << '['; if (size) { size_t i = 0; os << ToString(arr[i++]); for (; i < size; ++i) os << ", " << ToString(arr[i]); } os << ']'; return os.str(); } /** * For a container loop over all elements and call ToString on the element * Container is excluded */ template typename std::enable_if< is_container::value && !std::is_same::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(); } /** * Special case when container holds a string, don't call ToString again but * print directly to stream */ template typename std::enable_if< is_container::value && std::is_same::value, std::string>::type ToString(const T &vec) { std::ostringstream os; os << '['; if (!vec.empty()) { auto it = vec.begin(); os << *it++; while (it != vec.end()) os << ", " << *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 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 RuntimeError( "Invalid unit in conversion from string to std::chrono::duration"); } } template T StringTo(const std::string &t) { std::string tmp{t}; auto unit = RemoveUnit(tmp); return StringTo(tmp, unit); } template <> defs::detectorType StringTo(const std::string &s); template <> defs::detectorSettings StringTo(const std::string &s); template <> defs::speedLevel StringTo(const std::string &s); template <> defs::timingMode StringTo(const std::string &s); template <> defs::frameDiscardPolicy StringTo(const std::string &s); template <> defs::fileFormat StringTo(const std::string &s); template <> defs::externalSignalFlag StringTo(const std::string &s); template <> defs::readoutMode StringTo(const std::string &s); template <> defs::dacIndex StringTo(const std::string &s); template <> defs::burstMode StringTo(const std::string &s); template <> defs::timingSourceType StringTo(const std::string &s); template <> defs::M3_GainCaps StringTo(const std::string &s); template <> defs::portPosition StringTo(const std::string &s); template <> defs::streamingInterface StringTo(const std::string &s); template <> defs::vetoAlgorithm StringTo(const std::string &s); template <> defs::gainMode StringTo(const std::string &s); template <> defs::polarity StringTo(const std::string &s); template <> defs::timingInfoDecoder StringTo(const std::string &s); template <> defs::collectionMode StringTo(const std::string &s); template <> uint8_t StringTo(const std::string &s); template <> uint16_t StringTo(const std::string &s); template <> uint32_t StringTo(const std::string &s); template <> uint64_t StringTo(const std::string &s); template <> int StringTo(const std::string &s); template <> bool StringTo(const std::string &s); template <> int64_t StringTo(const std::string &s); /** For types with a .str() method use this for conversion */ template typename std::enable_if::value, std::string>::type ToString(const T &obj) { return obj.str(); } template std::vector StringTo(const std::vector &strings) { std::vector result; result.reserve(strings.size()); for (const auto &s : strings) result.push_back(StringTo(s)); return result; } } // namespace sls