mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2025-04-23 06:50:02 +02:00
141 lines
4.3 KiB
C++
141 lines
4.3 KiB
C++
#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 <chrono>
|
|
#include <iomanip>
|
|
#include <sstream>
|
|
#include <type_traits>
|
|
#include <vector>
|
|
|
|
namespace sls {
|
|
|
|
// std::string ToString(const std::vector<std::string> &vec,
|
|
// const char delimiter = ' ');
|
|
|
|
/** Convert std::chrono::duration with specified output unit */
|
|
template <typename T, typename Rep = double>
|
|
typename std::enable_if<is_duration<T>::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<duration<Rep, std::nano>>(t).count() << unit;
|
|
else if (unit == "us")
|
|
os << duration_cast<duration<Rep, std::micro>>(t).count() << unit;
|
|
else if (unit == "ms")
|
|
os << duration_cast<duration<Rep, std::milli>>(t).count() << unit;
|
|
else if (unit == "s")
|
|
os << duration_cast<duration<Rep>>(t).count() << unit;
|
|
else
|
|
throw std::runtime_error("Unknown unit: " + unit);
|
|
return os.str();
|
|
}
|
|
|
|
/** Convert std::chrono::duration automatically selecting the unit */
|
|
template <typename From>
|
|
typename std::enable_if<is_duration<From>::value, std::string>::type
|
|
ToString(From t) {
|
|
auto tns = std::chrono::duration_cast<std::chrono::nanoseconds>(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 T>
|
|
typename std::enable_if<std::is_floating_point<T>::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 T>
|
|
typename std::enable_if<std::is_integral<T>::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 T>
|
|
typename std::enable_if<is_container<T>::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 T>
|
|
typename std::enable_if<is_container<T>::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 <typename T>
|
|
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<T>(duration<double, std::nano>(tval));
|
|
} else if (unit == "us") {
|
|
return duration_cast<T>(duration<double, std::micro>(tval));
|
|
} else if (unit == "ms") {
|
|
return duration_cast<T>(duration<double, std::milli>(tval));
|
|
} else if (unit == "s" || unit.empty()) {
|
|
return duration_cast<T>(std::chrono::duration<double>(tval));
|
|
} else {
|
|
throw sls::RuntimeError(
|
|
"Invalid unit in conversion from string to std::chrono::duration");
|
|
}
|
|
}
|
|
|
|
template <typename T> T StringTo(std::string t) {
|
|
auto unit = RemoveUnit(t);
|
|
return StringTo<T>(t, unit);
|
|
}
|
|
|
|
} // namespace sls
|