diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d0d953..58253cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -358,6 +358,9 @@ set(PUBLICHEADERS include/aare/ClusterVector.hpp include/aare/decode.hpp include/aare/type_traits.hpp + include/aare/scan_parameters.hpp + include/aare/to_string.hpp + include/aare/string_utils.hpp include/aare/defs.hpp include/aare/Dtype.hpp include/aare/File.hpp @@ -386,6 +389,8 @@ set(PUBLICHEADERS set(SourceFiles ${CMAKE_CURRENT_SOURCE_DIR}/src/CtbRawFile.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/defs.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/to_string.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/string_utils.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Dtype.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/decode.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Frame.cpp @@ -466,6 +471,7 @@ if(AARE_TESTS) set(TestSources ${CMAKE_CURRENT_SOURCE_DIR}/src/algorithm.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/defs.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/to_string.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/decode.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Dtype.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Frame.test.cpp diff --git a/include/aare/FileInterface.hpp b/include/aare/FileInterface.hpp index c4d3cce..99daa56 100644 --- a/include/aare/FileInterface.hpp +++ b/include/aare/FileInterface.hpp @@ -1,7 +1,7 @@ #pragma once #include "aare/Dtype.hpp" #include "aare/Frame.hpp" -#include "aare/defs.hpp" +#include "aare/to_string.hpp" #include #include diff --git a/include/aare/defs.hpp b/include/aare/defs.hpp index 81b8d84..5c26b0e 100644 --- a/include/aare/defs.hpp +++ b/include/aare/defs.hpp @@ -1,16 +1,15 @@ #pragma once #include "aare/Dtype.hpp" +#include "aare/scan_parameters.hpp" #include "aare/type_traits.hpp" #include #include #include -#include #include #include #include -#include #include #include #include @@ -224,45 +223,6 @@ struct ROI { using dynamic_shape = std::vector; -class ScanParameters { - bool m_enabled = false; - std::string m_dac; - int m_start = 0; - int m_stop = 0; - int m_step = 0; - // TODO! add settleTime, requires string to time conversion - - public: - // "[enabled\ndac dac 4\nstart 500\nstop 2200\nstep 5\nsettleTime 100us\n]" - ScanParameters(const std::string &par) { - std::istringstream iss(par.substr(1, par.size() - 2)); - std::string line; - while (std::getline(iss, line)) { - if (line == "enabled") { - m_enabled = true; - } else if (line.find("dac") != std::string::npos) { - m_dac = line.substr(4); - } else if (line.find("start") != std::string::npos) { - m_start = std::stoi(line.substr(6)); - } else if (line.find("stop") != std::string::npos) { - m_stop = std::stoi(line.substr(5)); - } else if (line.find("step") != std::string::npos) { - m_step = std::stoi(line.substr(5)); - } - } - }; - ScanParameters() = default; - ScanParameters(const ScanParameters &) = default; - ScanParameters &operator=(const ScanParameters &) = default; - ScanParameters(ScanParameters &&) = default; - int start() const { return m_start; }; - int stop() const { return m_stop; }; - int step() const { return m_step; }; - const std::string &dac() const { return m_dac; }; - bool enabled() const { return m_enabled; }; - void increment_stop() { m_stop += 1; }; -}; - // TODO! Can we uniform enums between the libraries? /** @@ -298,293 +258,6 @@ enum class BurstMode { Continuous_External }; -/** ToString and StringTo Conversions */ - -// generic -template ::value>> -std::string ToString(T arg) { - return T(arg); -} - -template ::value && !is_container::value, - int> = 0> -T StringTo(const std::string &arg) { - return T(arg); -} - -// time -std::string RemoveUnit(std::string &str); -inline void TrimWhiteSpaces(std::string &s) { - s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char c) { - return !std::isspace(c); - })); - s.erase(std::find_if(s.rbegin(), s.rend(), - [](unsigned char c) { return !std::isspace(c); }) - .base(), - s.end()); -} - -/** 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) { - - using std::chrono::abs; - using std::chrono::duration_cast; - using std::chrono::microseconds; - using std::chrono::milliseconds; - using std::chrono::nanoseconds; - auto tns = duration_cast(t); - if (abs(tns) < microseconds(1)) { - return ToString(tns, "ns"); - } else if (abs(tns) < milliseconds(1)) { - return ToString(tns, "us"); - } else if (abs(tns) < milliseconds(99)) { - return ToString(tns, "ms"); - } else { - return ToString(tns, "s"); - } -} -template -std::ostream &operator<<(std::ostream &os, - const std::chrono::duration &d) { - return os << ToString(d); -} - -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 std::invalid_argument("[ERROR] 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 std::invalid_argument("[ERROR] Invalid unit in conversion from " - "string to std::chrono::duration"); - } -} - -template ::value, int> = 0> -T StringTo(const std::string &t) { - std::string tmp{t}; - auto unit = RemoveUnit(tmp); - return StringTo(tmp, unit); -} - -template <> inline bool StringTo(const std::string &s) { - int i = std::stoi(s, nullptr, 10); - switch (i) { - case 0: - return false; - case 1: - return true; - default: - throw std::runtime_error("Unknown boolean. Expecting be 0 or 1."); - } -} - -template <> inline uint8_t StringTo(const std::string &s) { - int base = s.find("0x") != std::string::npos ? 16 : 10; - int value = std::stoi(s, nullptr, base); - if (value < std::numeric_limits::min() || - value > std::numeric_limits::max()) { - throw std::runtime_error("Cannot scan uint8_t from string '" + s + - "'. Value must be in range 0 - 255."); - } - return static_cast(value); -} - -template <> inline uint16_t StringTo(const std::string &s) { - int base = s.find("0x") != std::string::npos ? 16 : 10; - int value = std::stoi(s, nullptr, base); - if (value < std::numeric_limits::min() || - value > std::numeric_limits::max()) { - throw std::runtime_error("Cannot scan uint16_t from string '" + s + - "'. Value must be in range 0 - 65535."); - } - return static_cast(value); -} - -template <> inline uint32_t StringTo(const std::string &s) { - int base = s.find("0x") != std::string::npos ? 16 : 10; - return std::stoul(s, nullptr, base); -} - -template <> inline uint64_t StringTo(const std::string &s) { - int base = s.find("0x") != std::string::npos ? 16 : 10; - return std::stoull(s, nullptr, base); -} - -template <> inline int StringTo(const std::string &s) { - int base = s.find("0x") != std::string::npos ? 16 : 10; - return std::stoi(s, nullptr, base); -} - -/*template <> inline size_t StringTo(const std::string &s) { - int base = s.find("0x") != std::string::npos ? 16 : 10; - return std::stoull(s, nullptr, base); -}*/ - -// vector -template std::string ToString(const std::vector &vec) { - std::ostringstream oss; - oss << "["; - for (size_t i = 0; i < vec.size(); ++i) { - oss << vec[i]; - if (i != vec.size() - 1) - oss << ", "; - } - oss << "]"; - return oss.str(); -} - -template -std::ostream &operator<<(std::ostream &os, const std::vector &v) { - return os << ToString(v); -} - -template ::value && - !is_std_string_v /*&& - !is_map_v*/ - , - int> = 0> -Container StringTo(const std::string &s) { - using Value = typename Container::value_type; - - // strip outer brackets - std::string str = s; - str.erase( - std::remove_if(str.begin(), str.end(), - [](unsigned char c) { return c == '[' || c == ']'; }), - str.end()); - - std::stringstream ss(str); - std::string item; - Container result; - - while (std::getline(ss, item, ',')) { - TrimWhiteSpaces(item); - if (!item.empty()) { - result.push_back(StringTo(item)); - } - } - return result; -} - -// map -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(); -} - -template <> -inline std::map StringTo(const std::string &s) { - std::map result; - std::string str = s; - - // Remove outer braces if present - if (!str.empty() && str.front() == '{' && str.back() == '}') { - str = str.substr(1, str.size() - 2); - } - - std::stringstream ss(str); - std::string item; - - while (std::getline(ss, item, ',')) { - auto colon_pos = item.find(':'); - if (colon_pos == std::string::npos) - throw std::runtime_error("Missing ':' in item: " + item); - - std::string key = item.substr(0, colon_pos); - std::string value = item.substr(colon_pos + 1); - - TrimWhiteSpaces(key); - TrimWhiteSpaces(value); - - result[key] = value; - } - return result; -} - -// optional -template std::string ToString(const std::optional &opt) { - return opt ? ToString(*opt) : "nullopt"; -} - -template -std::ostream &operator<<(std::ostream &os, const std::optional &opt) { - if (opt) - os << *opt; - else - os << "nullopt"; - return os; -} - -// enums -template <> DetectorType StringTo(const std::string & /*name*/); -template <> std::string ToString(DetectorType arg); - -template <> TimingMode StringTo(const std::string & /*mode*/); -template <> std::string ToString(TimingMode arg); - -template <> FrameDiscardPolicy StringTo(const std::string & /*mode*/); -template <> std::string ToString(FrameDiscardPolicy arg); - -template <> BurstMode StringTo(const std::string & /*mode*/); -template <> std::string ToString(BurstMode arg); - -std::ostream &operator<<(std::ostream &os, const ScanParameters &r); -template <> std::string ToString(ScanParameters arg); - -std::ostream &operator<<(std::ostream &os, const ROI &roi); -template <> std::string ToString(ROI arg); - using DataTypeVariants = std::variant; } // namespace aare \ No newline at end of file diff --git a/include/aare/scan_parameters.hpp b/include/aare/scan_parameters.hpp new file mode 100644 index 0000000..e2cfdcc --- /dev/null +++ b/include/aare/scan_parameters.hpp @@ -0,0 +1,48 @@ +#pragma once + +#include +#include + + +namespace aare { + +class ScanParameters { + bool m_enabled = false; + std::string m_dac; + int m_start = 0; + int m_stop = 0; + int m_step = 0; + // TODO! add settleTime, requires string to time conversion + + public: + // "[enabled\ndac dac 4\nstart 500\nstop 2200\nstep 5\nsettleTime 100us\n]" + ScanParameters(const std::string &par) { + std::istringstream iss(par.substr(1, par.size() - 2)); + std::string line; + while (std::getline(iss, line)) { + if (line == "enabled") { + m_enabled = true; + } else if (line.find("dac") != std::string::npos) { + m_dac = line.substr(4); + } else if (line.find("start") != std::string::npos) { + m_start = std::stoi(line.substr(6)); + } else if (line.find("stop") != std::string::npos) { + m_stop = std::stoi(line.substr(5)); + } else if (line.find("step") != std::string::npos) { + m_step = std::stoi(line.substr(5)); + } + } + }; + ScanParameters() = default; + ScanParameters(const ScanParameters &) = default; + ScanParameters &operator=(const ScanParameters &) = default; + ScanParameters(ScanParameters &&) = default; + int start() const { return m_start; }; + int stop() const { return m_stop; }; + int step() const { return m_step; }; + const std::string &dac() const { return m_dac; }; + bool enabled() const { return m_enabled; }; + void increment_stop() { m_stop += 1; }; +}; + +} // namespace aare \ No newline at end of file diff --git a/include/aare/string_utils.hpp b/include/aare/string_utils.hpp new file mode 100644 index 0000000..33024f2 --- /dev/null +++ b/include/aare/string_utils.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include + +namespace aare { + +std::string RemoveUnit(std::string &str); + +void TrimWhiteSpaces(std::string &s); + +} // namespace aare \ No newline at end of file diff --git a/include/aare/to_string.hpp b/include/aare/to_string.hpp new file mode 100644 index 0000000..0d95130 --- /dev/null +++ b/include/aare/to_string.hpp @@ -0,0 +1,287 @@ +#pragma once + +#include "aare/defs.hpp" +#include "aare/string_utils.hpp" + +#include +#include + + +namespace aare { + +// generic +template ::value>> +std::string ToString(T arg) { + return T(arg); +} + +template ::value && !is_container::value, + int> = 0> +T StringTo(const std::string &arg) { + return T(arg); +} + +// time + +/** 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) { + + using std::chrono::abs; + using std::chrono::duration_cast; + using std::chrono::microseconds; + using std::chrono::milliseconds; + using std::chrono::nanoseconds; + auto tns = duration_cast(t); + if (abs(tns) < microseconds(1)) { + return ToString(tns, "ns"); + } else if (abs(tns) < milliseconds(1)) { + return ToString(tns, "us"); + } else if (abs(tns) < milliseconds(99)) { + return ToString(tns, "ms"); + } else { + return ToString(tns, "s"); + } +} +template +std::ostream &operator<<(std::ostream &os, + const std::chrono::duration &d) { + return os << ToString(d); +} + +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 std::invalid_argument("[ERROR] 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 std::invalid_argument("[ERROR] Invalid unit in conversion from " + "string to std::chrono::duration"); + } +} + +template ::value, int> = 0> +T StringTo(const std::string &t) { + std::string tmp{t}; + auto unit = RemoveUnit(tmp); + return StringTo(tmp, unit); +} + +template <> inline bool StringTo(const std::string &s) { + int i = std::stoi(s, nullptr, 10); + switch (i) { + case 0: + return false; + case 1: + return true; + default: + throw std::runtime_error("Unknown boolean. Expecting be 0 or 1."); + } +} + +template <> inline uint8_t StringTo(const std::string &s) { + int base = s.find("0x") != std::string::npos ? 16 : 10; + int value = std::stoi(s, nullptr, base); + if (value < std::numeric_limits::min() || + value > std::numeric_limits::max()) { + throw std::runtime_error("Cannot scan uint8_t from string '" + s + + "'. Value must be in range 0 - 255."); + } + return static_cast(value); +} + +template <> inline uint16_t StringTo(const std::string &s) { + int base = s.find("0x") != std::string::npos ? 16 : 10; + int value = std::stoi(s, nullptr, base); + if (value < std::numeric_limits::min() || + value > std::numeric_limits::max()) { + throw std::runtime_error("Cannot scan uint16_t from string '" + s + + "'. Value must be in range 0 - 65535."); + } + return static_cast(value); +} + +template <> inline uint32_t StringTo(const std::string &s) { + int base = s.find("0x") != std::string::npos ? 16 : 10; + return std::stoul(s, nullptr, base); +} + +template <> inline uint64_t StringTo(const std::string &s) { + int base = s.find("0x") != std::string::npos ? 16 : 10; + return std::stoull(s, nullptr, base); +} + +template <> inline int StringTo(const std::string &s) { + int base = s.find("0x") != std::string::npos ? 16 : 10; + return std::stoi(s, nullptr, base); +} + +/*template <> inline size_t StringTo(const std::string &s) { + int base = s.find("0x") != std::string::npos ? 16 : 10; + return std::stoull(s, nullptr, base); +}*/ + +// vector +template std::string ToString(const std::vector &vec) { + std::ostringstream oss; + oss << "["; + for (size_t i = 0; i < vec.size(); ++i) { + oss << vec[i]; + if (i != vec.size() - 1) + oss << ", "; + } + oss << "]"; + return oss.str(); +} + +template +std::ostream &operator<<(std::ostream &os, const std::vector &v) { + return os << ToString(v); +} + +template ::value && + !is_std_string_v /*&& + !is_map_v*/ + , + int> = 0> +Container StringTo(const std::string &s) { + using Value = typename Container::value_type; + + // strip outer brackets + std::string str = s; + str.erase( + std::remove_if(str.begin(), str.end(), + [](unsigned char c) { return c == '[' || c == ']'; }), + str.end()); + + std::stringstream ss(str); + std::string item; + Container result; + + while (std::getline(ss, item, ',')) { + TrimWhiteSpaces(item); + if (!item.empty()) { + result.push_back(StringTo(item)); + } + } + return result; +} + +// map +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(); +} + +template <> +inline std::map StringTo(const std::string &s) { + std::map result; + std::string str = s; + + // Remove outer braces if present + if (!str.empty() && str.front() == '{' && str.back() == '}') { + str = str.substr(1, str.size() - 2); + } + + std::stringstream ss(str); + std::string item; + + while (std::getline(ss, item, ',')) { + auto colon_pos = item.find(':'); + if (colon_pos == std::string::npos) + throw std::runtime_error("Missing ':' in item: " + item); + + std::string key = item.substr(0, colon_pos); + std::string value = item.substr(colon_pos + 1); + + TrimWhiteSpaces(key); + TrimWhiteSpaces(value); + + result[key] = value; + } + return result; +} + +// optional +template std::string ToString(const std::optional &opt) { + return opt ? ToString(*opt) : "nullopt"; +} + +template +std::ostream &operator<<(std::ostream &os, const std::optional &opt) { + if (opt) + os << *opt; + else + os << "nullopt"; + return os; +} + +// enums +template <> DetectorType StringTo(const std::string & /*name*/); +template <> std::string ToString(DetectorType arg); + +template <> TimingMode StringTo(const std::string & /*mode*/); +template <> std::string ToString(TimingMode arg); + +template <> FrameDiscardPolicy StringTo(const std::string & /*mode*/); +template <> std::string ToString(FrameDiscardPolicy arg); + +template <> BurstMode StringTo(const std::string & /*mode*/); +template <> std::string ToString(BurstMode arg); + +std::ostream &operator<<(std::ostream &os, const ScanParameters &r); +template <> std::string ToString(ScanParameters arg); + +std::ostream &operator<<(std::ostream &os, const ROI &roi); +template <> std::string ToString(ROI arg); + +} // namespace aare \ No newline at end of file diff --git a/src/Hdf5MasterFile.cpp b/src/Hdf5MasterFile.cpp index 8690122..55d74dd 100644 --- a/src/Hdf5MasterFile.cpp +++ b/src/Hdf5MasterFile.cpp @@ -1,5 +1,6 @@ #include "aare/Hdf5MasterFile.hpp" #include "aare/logger.hpp" +#include "aare/to_string.hpp" #include #include namespace aare { diff --git a/src/RawMasterFile.cpp b/src/RawMasterFile.cpp index ee51f5b..8dc3447 100644 --- a/src/RawMasterFile.cpp +++ b/src/RawMasterFile.cpp @@ -1,4 +1,5 @@ #include "aare/RawMasterFile.hpp" +#include "aare/to_string.hpp" #include namespace aare { diff --git a/src/defs.cpp b/src/defs.cpp index d403fbc..ec592d5 100644 --- a/src/defs.cpp +++ b/src/defs.cpp @@ -1,7 +1,4 @@ #include "aare/defs.hpp" -#include -#include -#include #include namespace aare { @@ -11,240 +8,4 @@ void assert_failed(const std::string &msg) { exit(1); } -/** - * @brief Convert a DetectorType to a string - * @param type DetectorType - * @return string representation of the DetectorType - */ -template <> std::string ToString(DetectorType arg) { - switch (arg) { - case DetectorType::Generic: - return "Generic"; - case DetectorType::Eiger: - return "Eiger"; - case DetectorType::Gotthard: - return "Gotthard"; - case DetectorType::Jungfrau: - return "Jungfrau"; - case DetectorType::ChipTestBoard: - return "ChipTestBoard"; - case DetectorType::Moench: - return "Moench"; - case DetectorType::Mythen3: - return "Mythen3"; - case DetectorType::Gotthard2: - return "Gotthard2"; - case DetectorType::Xilinx_ChipTestBoard: - return "Xilinx_ChipTestBoard"; - - // Custom ones - case DetectorType::Moench03: - return "Moench03"; - case DetectorType::Moench03_old: - return "Moench03_old"; - case DetectorType::Unknown: - return "Unknown"; - - // no default case to trigger compiler warning if not all - // enum values are handled - } - throw std::runtime_error("Could not decode detector to string"); -} - -/** - * @brief Convert a string to a DetectorType - * @param name string representation of the DetectorType - * @return DetectorType - * @throw runtime_error if the string does not match any DetectorType - */ -template <> DetectorType StringTo(const std::string &arg) { - if (arg == "Generic") - return DetectorType::Generic; - if (arg == "Eiger") - return DetectorType::Eiger; - if (arg == "Gotthard") - return DetectorType::Gotthard; - if (arg == "Jungfrau") - return DetectorType::Jungfrau; - if (arg == "ChipTestBoard") - return DetectorType::ChipTestBoard; - if (arg == "Moench") - return DetectorType::Moench; - if (arg == "Mythen3") - return DetectorType::Mythen3; - if (arg == "Gotthard2") - return DetectorType::Gotthard2; - if (arg == "Xilinx_ChipTestBoard") - return DetectorType::Xilinx_ChipTestBoard; - - // Custom ones - if (arg == "Moench03") - return DetectorType::Moench03; - if (arg == "Moench03_old") - return DetectorType::Moench03_old; - if (arg == "Unknown") - return DetectorType::Unknown; - - throw std::runtime_error("Could not decode detector from: \"" + arg + "\""); -} - -/** - * @brief Convert a TimingMode to a string - * @param type TimingMode - * @return string representation of the TimingMode - */ -template <> std::string ToString(TimingMode arg) { - switch (arg) { - case TimingMode::Auto: - return "Auto"; - case TimingMode::Trigger: - return "Trigger"; - - // no default case to trigger compiler warning if not all - // enum values are handled - } - throw std::runtime_error("Could not decode timing mode to string"); -} - -/** - * @brief Convert a string to a TimingMode - * @param mode string representation of the TimingMode - * @return TimingMode - * @throw runtime_error if the string does not match any TimingMode - */ -template <> TimingMode StringTo(const std::string &arg) { - if (arg == "auto") - return TimingMode::Auto; - if (arg == "trigger") - return TimingMode::Trigger; - throw std::runtime_error("Could not decode timing mode from: \"" + arg + - "\""); -} - -/** - * @brief Convert a FrameDiscardPolicy to a string - * @param type FrameDiscardPolicy - * @return string representation of the FrameDiscardPolicy - */ -template <> std::string ToString(FrameDiscardPolicy arg) { - switch (arg) { - case FrameDiscardPolicy::NoDiscard: - return "nodiscard"; - case FrameDiscardPolicy::Discard: - return "discard"; - case FrameDiscardPolicy::DiscardPartial: - return "discardpartial"; - - // no default case to trigger compiler warning if not all - // enum values are handled - } - throw std::runtime_error("Could not decode frame discard policy to string"); -} - -template <> FrameDiscardPolicy StringTo(const std::string &arg) { - if (arg == "nodiscard") - return FrameDiscardPolicy::NoDiscard; - if (arg == "discard") - return FrameDiscardPolicy::Discard; - if (arg == "discardpartial") - return FrameDiscardPolicy::DiscardPartial; - throw std::runtime_error("Could not decode frame discard policy from: \"" + - arg + "\""); -} - -/** - * @brief Convert a BurstMode to a string - * @param type BurstMode - * @return string representation of the BurstMode - */ -template <> std::string ToString(BurstMode arg) { - switch (arg) { - case BurstMode::Burst_Interal: - return "burst_internal"; - case BurstMode::Burst_External: - return "burst_external"; - case BurstMode::Continuous_Internal: - return "continuous_internal"; - case BurstMode::Continuous_External: - return "continuous_external"; - } - throw std::runtime_error("Could not decode burst mode to string"); -} - -template <> BurstMode StringTo(const std::string &arg) { - if (arg == "burst_internal") - return BurstMode::Burst_Interal; - if (arg == "burst_external") - return BurstMode::Burst_External; - if (arg == "continuous_internal") - return BurstMode::Continuous_Internal; - if (arg == "continuous_external") - return BurstMode::Continuous_External; - throw std::runtime_error("Could not decode burst mode from: \"" + arg + - "\""); -} - -/** - * @brief Convert a ScanParameters to a string - * @param type ScanParameters - * @return string representation of the ScanParameters - */ -template <> std::string ToString(ScanParameters arg) { - std::ostringstream oss; - oss << '['; - if (arg.enabled()) { - oss << "enabled" << std::endl - << "dac " << arg.dac() << std::endl - << "start " << arg.start() << std::endl - << "stop " << arg.stop() << std::endl - << "step " << arg.step() - << std::endl - //<< "settleTime " - // << ToString(std::chrono::nanoseconds{arg.dacSettleTime_ns}) - << std::endl; - } else { - oss << "disabled"; - } - oss << ']'; - return oss.str(); -} - -std::ostream &operator<<(std::ostream &os, const ScanParameters &r) { - return os << ToString(r); -} - -/** - * @brief Convert a ROI to a string - * @param type ROI - * @return string representation of the ROI - */ -template <> std::string ToString(ROI arg) { - std::ostringstream oss; - oss << '[' << arg.xmin << ", " << arg.xmax; - if (arg.ymin != -1 || arg.ymax != -1) { - oss << ", " << arg.ymin << ", " << arg.ymax; - } - oss << ']'; - return oss.str(); -} - -std::ostream &operator<<(std::ostream &os, const ROI &roi) { - return os << ToString(roi); -} - -std::string RemoveUnit(std::string &str) { - auto it = str.begin(); - while (it != str.end()) { - if (std::isalpha(*it)) - break; - ++it; - } - auto pos = it - str.begin(); - auto unit = str.substr(pos); - str.erase(it, end(str)); - return unit; -} - -// template <> TimingMode StringTo(std::string mode); - } // namespace aare \ No newline at end of file diff --git a/src/defs.test.cpp b/src/defs.test.cpp index 2106d86..3501a97 100644 --- a/src/defs.test.cpp +++ b/src/defs.test.cpp @@ -1,54 +1,6 @@ #include "aare/defs.hpp" #include -#include - -using aare::StringTo; -using aare::ToString; - -TEST_CASE("Enum to string conversion") { - // TODO! By the way I don't think the enum string conversions should be in - // the defs.hpp file but let's use this to show a test - REQUIRE(ToString(aare::DetectorType::Generic) == "Generic"); - REQUIRE(ToString(aare::DetectorType::Eiger) == "Eiger"); - REQUIRE(ToString(aare::DetectorType::Gotthard) == "Gotthard"); - REQUIRE(ToString(aare::DetectorType::Jungfrau) == "Jungfrau"); - REQUIRE(ToString(aare::DetectorType::ChipTestBoard) == "ChipTestBoard"); - REQUIRE(ToString(aare::DetectorType::Moench) == "Moench"); - REQUIRE(ToString(aare::DetectorType::Mythen3) == "Mythen3"); - REQUIRE(ToString(aare::DetectorType::Gotthard2) == "Gotthard2"); - REQUIRE(ToString(aare::DetectorType::Xilinx_ChipTestBoard) == - "Xilinx_ChipTestBoard"); - REQUIRE(ToString(aare::DetectorType::Moench03) == "Moench03"); - REQUIRE(ToString(aare::DetectorType::Moench03_old) == "Moench03_old"); - REQUIRE(ToString(aare::DetectorType::Unknown) == "Unknown"); -} - -TEST_CASE("String to enum") { - REQUIRE(StringTo("Generic") == - aare::DetectorType::Generic); - REQUIRE(StringTo("Eiger") == aare::DetectorType::Eiger); - REQUIRE(StringTo("Gotthard") == - aare::DetectorType::Gotthard); - REQUIRE(StringTo("Jungfrau") == - aare::DetectorType::Jungfrau); - REQUIRE(StringTo("ChipTestBoard") == - aare::DetectorType::ChipTestBoard); - REQUIRE(StringTo("Moench") == - aare::DetectorType::Moench); - REQUIRE(StringTo("Mythen3") == - aare::DetectorType::Mythen3); - REQUIRE(StringTo("Gotthard2") == - aare::DetectorType::Gotthard2); - REQUIRE(StringTo("Xilinx_ChipTestBoard") == - aare::DetectorType::Xilinx_ChipTestBoard); - REQUIRE(StringTo("Moench03") == - aare::DetectorType::Moench03); - REQUIRE(StringTo("Moench03_old") == - aare::DetectorType::Moench03_old); - REQUIRE(StringTo("Unknown") == - aare::DetectorType::Unknown); -} TEST_CASE("Enum values") { // Since some of the enums are written to file we need to make sure diff --git a/src/string_utils.cpp b/src/string_utils.cpp new file mode 100644 index 0000000..b8e1f58 --- /dev/null +++ b/src/string_utils.cpp @@ -0,0 +1,30 @@ +#include "aare/string_utils.hpp" + +#include + +namespace aare { + +std::string RemoveUnit(std::string &str) { + auto it = str.begin(); + while (it != str.end()) { + if (std::isalpha(*it)) + break; + ++it; + } + auto pos = it - str.begin(); + auto unit = str.substr(pos); + str.erase(it, end(str)); + return unit; +} + +void TrimWhiteSpaces(std::string &s) { + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char c) { + return !std::isspace(c); + })); + s.erase(std::find_if(s.rbegin(), s.rend(), + [](unsigned char c) { return !std::isspace(c); }) + .base(), + s.end()); +} + +} // namespace aare \ No newline at end of file diff --git a/src/to_string.cpp b/src/to_string.cpp new file mode 100644 index 0000000..b1b87ab --- /dev/null +++ b/src/to_string.cpp @@ -0,0 +1,226 @@ +#include "aare/to_string.hpp" + +namespace aare { + +/** + * @brief Convert a DetectorType to a string + * @param type DetectorType + * @return string representation of the DetectorType + */ +template <> std::string ToString(DetectorType arg) { + switch (arg) { + case DetectorType::Generic: + return "Generic"; + case DetectorType::Eiger: + return "Eiger"; + case DetectorType::Gotthard: + return "Gotthard"; + case DetectorType::Jungfrau: + return "Jungfrau"; + case DetectorType::ChipTestBoard: + return "ChipTestBoard"; + case DetectorType::Moench: + return "Moench"; + case DetectorType::Mythen3: + return "Mythen3"; + case DetectorType::Gotthard2: + return "Gotthard2"; + case DetectorType::Xilinx_ChipTestBoard: + return "Xilinx_ChipTestBoard"; + + // Custom ones + case DetectorType::Moench03: + return "Moench03"; + case DetectorType::Moench03_old: + return "Moench03_old"; + case DetectorType::Unknown: + return "Unknown"; + + // no default case to trigger compiler warning if not all + // enum values are handled + } + throw std::runtime_error("Could not decode detector to string"); +} + +/** + * @brief Convert a string to a DetectorType + * @param name string representation of the DetectorType + * @return DetectorType + * @throw runtime_error if the string does not match any DetectorType + */ +template <> DetectorType StringTo(const std::string &arg) { + if (arg == "Generic") + return DetectorType::Generic; + if (arg == "Eiger") + return DetectorType::Eiger; + if (arg == "Gotthard") + return DetectorType::Gotthard; + if (arg == "Jungfrau") + return DetectorType::Jungfrau; + if (arg == "ChipTestBoard") + return DetectorType::ChipTestBoard; + if (arg == "Moench") + return DetectorType::Moench; + if (arg == "Mythen3") + return DetectorType::Mythen3; + if (arg == "Gotthard2") + return DetectorType::Gotthard2; + if (arg == "Xilinx_ChipTestBoard") + return DetectorType::Xilinx_ChipTestBoard; + + // Custom ones + if (arg == "Moench03") + return DetectorType::Moench03; + if (arg == "Moench03_old") + return DetectorType::Moench03_old; + if (arg == "Unknown") + return DetectorType::Unknown; + + throw std::runtime_error("Could not decode detector from: \"" + arg + "\""); +} + +/** + * @brief Convert a TimingMode to a string + * @param type TimingMode + * @return string representation of the TimingMode + */ +template <> std::string ToString(TimingMode arg) { + switch (arg) { + case TimingMode::Auto: + return "Auto"; + case TimingMode::Trigger: + return "Trigger"; + + // no default case to trigger compiler warning if not all + // enum values are handled + } + throw std::runtime_error("Could not decode timing mode to string"); +} + +/** + * @brief Convert a string to a TimingMode + * @param mode string representation of the TimingMode + * @return TimingMode + * @throw runtime_error if the string does not match any TimingMode + */ +template <> TimingMode StringTo(const std::string &arg) { + if (arg == "auto") + return TimingMode::Auto; + if (arg == "trigger") + return TimingMode::Trigger; + throw std::runtime_error("Could not decode timing mode from: \"" + arg + + "\""); +} + +/** + * @brief Convert a FrameDiscardPolicy to a string + * @param type FrameDiscardPolicy + * @return string representation of the FrameDiscardPolicy + */ +template <> std::string ToString(FrameDiscardPolicy arg) { + switch (arg) { + case FrameDiscardPolicy::NoDiscard: + return "nodiscard"; + case FrameDiscardPolicy::Discard: + return "discard"; + case FrameDiscardPolicy::DiscardPartial: + return "discardpartial"; + + // no default case to trigger compiler warning if not all + // enum values are handled + } + throw std::runtime_error("Could not decode frame discard policy to string"); +} + +template <> FrameDiscardPolicy StringTo(const std::string &arg) { + if (arg == "nodiscard") + return FrameDiscardPolicy::NoDiscard; + if (arg == "discard") + return FrameDiscardPolicy::Discard; + if (arg == "discardpartial") + return FrameDiscardPolicy::DiscardPartial; + throw std::runtime_error("Could not decode frame discard policy from: \"" + + arg + "\""); +} + +/** + * @brief Convert a BurstMode to a string + * @param type BurstMode + * @return string representation of the BurstMode + */ +template <> std::string ToString(BurstMode arg) { + switch (arg) { + case BurstMode::Burst_Interal: + return "burst_internal"; + case BurstMode::Burst_External: + return "burst_external"; + case BurstMode::Continuous_Internal: + return "continuous_internal"; + case BurstMode::Continuous_External: + return "continuous_external"; + } + throw std::runtime_error("Could not decode burst mode to string"); +} + +template <> BurstMode StringTo(const std::string &arg) { + if (arg == "burst_internal") + return BurstMode::Burst_Interal; + if (arg == "burst_external") + return BurstMode::Burst_External; + if (arg == "continuous_internal") + return BurstMode::Continuous_Internal; + if (arg == "continuous_external") + return BurstMode::Continuous_External; + throw std::runtime_error("Could not decode burst mode from: \"" + arg + + "\""); +} + +/** + * @brief Convert a ScanParameters to a string + * @param type ScanParameters + * @return string representation of the ScanParameters + */ +template <> std::string ToString(ScanParameters arg) { + std::ostringstream oss; + oss << '['; + if (arg.enabled()) { + oss << "enabled" << std::endl + << "dac " << arg.dac() << std::endl + << "start " << arg.start() << std::endl + << "stop " << arg.stop() << std::endl + << "step " << arg.step() + << std::endl + //<< "settleTime " + // << ToString(std::chrono::nanoseconds{arg.dacSettleTime_ns}) + << std::endl; + } else { + oss << "disabled"; + } + oss << ']'; + return oss.str(); +} + +std::ostream &operator<<(std::ostream &os, const ScanParameters &r) { + return os << ToString(r); +} + +/** + * @brief Convert a ROI to a string + * @param type ROI + * @return string representation of the ROI + */ +template <> std::string ToString(ROI arg) { + std::ostringstream oss; + oss << '[' << arg.xmin << ", " << arg.xmax; + if (arg.ymin != -1 || arg.ymax != -1) { + oss << ", " << arg.ymin << ", " << arg.ymax; + } + oss << ']'; + return oss.str(); +} + +std::ostream &operator<<(std::ostream &os, const ROI &roi) { + return os << ToString(roi); +} + +} // namespace aare \ No newline at end of file diff --git a/src/to_string.test.cpp b/src/to_string.test.cpp new file mode 100644 index 0000000..8efb0ad --- /dev/null +++ b/src/to_string.test.cpp @@ -0,0 +1,50 @@ +#include "aare/to_string.hpp" + +#include + +using aare::StringTo; +using aare::ToString; + +TEST_CASE("Enum to string conversion") { + // TODO! By the way I don't think the enum string conversions should be in + // the defs.hpp file but let's use this to show a test + REQUIRE(ToString(aare::DetectorType::Generic) == "Generic"); + REQUIRE(ToString(aare::DetectorType::Eiger) == "Eiger"); + REQUIRE(ToString(aare::DetectorType::Gotthard) == "Gotthard"); + REQUIRE(ToString(aare::DetectorType::Jungfrau) == "Jungfrau"); + REQUIRE(ToString(aare::DetectorType::ChipTestBoard) == "ChipTestBoard"); + REQUIRE(ToString(aare::DetectorType::Moench) == "Moench"); + REQUIRE(ToString(aare::DetectorType::Mythen3) == "Mythen3"); + REQUIRE(ToString(aare::DetectorType::Gotthard2) == "Gotthard2"); + REQUIRE(ToString(aare::DetectorType::Xilinx_ChipTestBoard) == + "Xilinx_ChipTestBoard"); + REQUIRE(ToString(aare::DetectorType::Moench03) == "Moench03"); + REQUIRE(ToString(aare::DetectorType::Moench03_old) == "Moench03_old"); + REQUIRE(ToString(aare::DetectorType::Unknown) == "Unknown"); +} + +TEST_CASE("String to enum") { + REQUIRE(StringTo("Generic") == + aare::DetectorType::Generic); + REQUIRE(StringTo("Eiger") == aare::DetectorType::Eiger); + REQUIRE(StringTo("Gotthard") == + aare::DetectorType::Gotthard); + REQUIRE(StringTo("Jungfrau") == + aare::DetectorType::Jungfrau); + REQUIRE(StringTo("ChipTestBoard") == + aare::DetectorType::ChipTestBoard); + REQUIRE(StringTo("Moench") == + aare::DetectorType::Moench); + REQUIRE(StringTo("Mythen3") == + aare::DetectorType::Mythen3); + REQUIRE(StringTo("Gotthard2") == + aare::DetectorType::Gotthard2); + REQUIRE(StringTo("Xilinx_ChipTestBoard") == + aare::DetectorType::Xilinx_ChipTestBoard); + REQUIRE(StringTo("Moench03") == + aare::DetectorType::Moench03); + REQUIRE(StringTo("Moench03_old") == + aare::DetectorType::Moench03_old); + REQUIRE(StringTo("Unknown") == + aare::DetectorType::Unknown); +}