diff --git a/python/scripts/generate_functions.py b/python/scripts/generate_functions.py index 5d281cdd9..ab57f740f 100644 --- a/python/scripts/generate_functions.py +++ b/python/scripts/generate_functions.py @@ -8,6 +8,7 @@ to be installed. When the Detector API is updated this file should be run manually. """ +import os from clang import cindex import subprocess import argparse @@ -33,6 +34,24 @@ def green(msg): return f"{GREENC}{msg}{ENDC}" +def find_libclang(): + """Find libclang in the current Conda/Mamba environment.""" + conda_prefix = os.environ.get("CONDA_PREFIX") + if conda_prefix: + lib_dir = os.path.join(conda_prefix, "lib") + # Look for libclang*.so files + for f in os.listdir(lib_dir): + if f.startswith("libclang") and f.endswith(".so"): + return os.path.join(lib_dir, f) + + # fallback: system-wide search + path = ctypes.util.find_library("clang") + if path: + return path + + raise FileNotFoundError("libclang not found in CONDA_PREFIX or system paths.") + + def check_libclang_version(required="12"): # Use already-loaded libclang, or let cindex resolve it lib = ctypes.CDLL(cindex.Config.library_file or ctypes.util.find_library("clang")) @@ -201,7 +220,9 @@ if __name__ == "__main__": action="store_true", ) cargs = parser.parse_args() - + + libclang_path = find_libclang() + cindex.Config.set_library_file(libclang_path) check_libclang_version("12") check_clang_format_version(12) check_for_compile_commands_json(cargs.build_path) diff --git a/python/src/bit.cpp b/python/src/bit.cpp index d51233bec..a128aab4f 100644 --- a/python/src/bit.cpp +++ b/python/src/bit.cpp @@ -17,7 +17,6 @@ void init_bit(py::module &m) { py::class_(m, "RegisterAddress") .def(py::init()) - .def(py::init()) .def(py::init()) .def(py::init()) .def("__repr__", &RegisterAddress::str) @@ -29,7 +28,6 @@ void init_bit(py::module &m) { py::class_(m, "BitAddress") .def(py::init()) .def(py::init()) - .def(py::init()) .def("__repr__", &BitAddress::str) .def("str", &BitAddress::str) .def("address", &BitAddress::address) @@ -39,7 +37,6 @@ void init_bit(py::module &m) { py::class_(m, "RegisterValue") .def(py::init<>()) - .def(py::init()) .def(py::init()) .def(py::init()) .def("__repr__", &RegisterValue::str) @@ -47,14 +44,15 @@ void init_bit(py::module &m) { .def("value", &RegisterValue::value) .def(py::self == py::self) .def(py::self != py::self) - .def("__or__", [](const RegisterValue &lhs, const RegisterValue &rhs) { - return lhs | rhs; - }) - .def("__or__", [](const RegisterValue& lhs, uint32_t rhs) { - return lhs | rhs; - }) - .def("__ior__", [](RegisterValue &lhs, uint32_t rhs) -> RegisterValue& { - lhs |= rhs; - return lhs; - }, py::return_value_policy::reference_internal); + .def("__or__", [](const RegisterValue &lhs, + const RegisterValue &rhs) { return lhs | rhs; }) + .def("__or__", + [](const RegisterValue &lhs, uint32_t rhs) { return lhs | rhs; }) + .def( + "__ior__", + [](RegisterValue &lhs, uint32_t rhs) -> RegisterValue & { + lhs |= rhs; + return lhs; + }, + py::return_value_policy::reference_internal); } diff --git a/slsDetectorSoftware/generator/Caller.in.h b/slsDetectorSoftware/generator/Caller.in.h index 769d919bb..14dfb22d6 100644 --- a/slsDetectorSoftware/generator/Caller.in.h +++ b/slsDetectorSoftware/generator/Caller.in.h @@ -75,9 +75,22 @@ class Caller { uint32_t subFrameIndex, void *this_pointer); std::string bitoperations(int action); - RegisterAddress parseAddress(const std::string &saddr) const; + + // parsing from args + // parse from string to RegisterAddress + RegisterAddress parseRegisterAddress(const std::string &addr) const; + // parse from 2 strings to BitAddress + BitAddress parseBitAddress(const std::string &addr, + const std::string &bitPos) const; + // parse from string to RegisterValue + RegisterValue parseRegisterValue(const std::string &addr) const; + // parse validate flag from args and remove it from args bool parseValidate(); - BitAddress parseBitAddress() const; + + // parses from args, but also gets addresses from shared memory if + // applicable + RegisterAddress getRegisterAddress(const std::string &saddr) const; + BitAddress getBitAddress() const; FunctionMap functions{ {"list", &Caller::list}, diff --git a/slsDetectorSoftware/include/sls/Detector.h b/slsDetectorSoftware/include/sls/Detector.h index b805ba650..c1897745c 100644 --- a/slsDetectorSoftware/include/sls/Detector.h +++ b/slsDetectorSoftware/include/sls/Detector.h @@ -1878,6 +1878,9 @@ class Detector { /** [CTB][Xilinx CTB] */ bool hasBitDefinition(BitAddress addr) const; + /** [CTB][Xilinx CTB] */ + std::string toRegisterNameBitString(BitAddress addr) const; + /** [CTB][Xilinx CTB] returns bit position and address */ BitAddress getBitDefinitionAddress(const std::string &name) const; diff --git a/slsDetectorSoftware/src/Caller.h b/slsDetectorSoftware/src/Caller.h index 0c45cc666..9211caedb 100644 --- a/slsDetectorSoftware/src/Caller.h +++ b/slsDetectorSoftware/src/Caller.h @@ -3,7 +3,7 @@ #include "CmdParser.h" #include "HelpDacs.h" #include "sls/Detector.h" -#include "sls/bit_utils.h" + #include #include #include @@ -403,9 +403,22 @@ class Caller { uint32_t subFrameIndex, void *this_pointer); std::string bitoperations(int action); - RegisterAddress parseAddress(const std::string &saddr) const; + + // parsing from args + // parse from string to RegisterAddress + RegisterAddress parseRegisterAddress(const std::string &addr) const; + // parse from 2 strings to BitAddress + BitAddress parseBitAddress(const std::string &addr, + const std::string &bitPos) const; + // parse from string to RegisterValue + RegisterValue parseRegisterValue(const std::string &addr) const; + // parse validate flag from args and remove it from args bool parseValidate(); - BitAddress parseBitAddress() const; + + // parses from args, but also gets addresses from shared memory if + // applicable + RegisterAddress getRegisterAddress(const std::string &saddr) const; + BitAddress getBitAddress() const; FunctionMap functions{ {"list", &Caller::list}, diff --git a/slsDetectorSoftware/src/CallerSpecial.cpp b/slsDetectorSoftware/src/CallerSpecial.cpp index 1e627217a..67f044275 100644 --- a/slsDetectorSoftware/src/CallerSpecial.cpp +++ b/slsDetectorSoftware/src/CallerSpecial.cpp @@ -1462,12 +1462,6 @@ std::string Caller::define_reg(int action) { << '\n'; return os.str(); } - auto det_type = det->getDetectorType().squash(); - if (det_type != defs::XILINX_CHIPTESTBOARD && - det_type != defs::CHIPTESTBOARD) { - throw RuntimeError( - "define_reg command only supported for ctb and xilinx_ctb"); - } if (det_id != -1) { throw RuntimeError("Cannot use define at module level. Use the default " "multi-module level"); @@ -1478,7 +1472,7 @@ std::string Caller::define_reg(int action) { } // get name from address if (is_hex_or_dec_uint(args[0])) { - auto addr = RegisterAddress(args[0]); + auto addr = parseRegisterAddress(args[0]); auto t = det->getRegisterDefinitionName(addr); os << t << '\n'; } @@ -1492,7 +1486,7 @@ std::string Caller::define_reg(int action) { WrongNumberOfParameters(2); } auto name = args[0]; - auto addr = RegisterAddress(args[1]); + auto addr = parseRegisterAddress(args[1]); det->setRegisterDefinition(name, addr); os << "addr " << name << ' ' << addr.str() << '\n'; } else { @@ -1531,12 +1525,6 @@ std::string Caller::define_bit(int action) { << '\n'; return os.str(); } - auto det_type = det->getDetectorType().squash(); - if (det_type != defs::XILINX_CHIPTESTBOARD && - det_type != defs::CHIPTESTBOARD) { - throw RuntimeError( - "define_bit command only supported for ctb and xilinx_ctb"); - } if (det_id != -1) { throw RuntimeError("Cannot use define at module level. Use the default " "multi-module level"); @@ -1545,31 +1533,14 @@ std::string Caller::define_bit(int action) { // get position from name if (args.size() == 1) { auto t = det->getBitDefinitionAddress(args[0]); - bool found_addr = det->hasRegisterDefinition(t.address()); - if (found_addr) { - os << '[' << det->getRegisterDefinitionName(t.address()) << ", " - << std::to_string(t.bitPosition()) << "]\n"; - } else { - os << t.str() << '\n'; - } + os << det->toRegisterNameBitString(t) << '\n'; } // get name from position and address else if (args.size() == 2) { - auto reg = parseAddress(args[0]); - BitAddress addr(reg.str(), args[1]); - try { - auto t = det->getBitDefinitionName(addr); - os << t << '\n'; - } catch (const RuntimeError &e) { - std::string err_str = e.what(); - if (err_str.find("No bit definition found") != - std::string::npos && - !is_hex_or_dec_uint(args[0])) { - err_str += " and addr = " + args[0]; - throw RuntimeError(err_str); - } - throw; - } + auto addr = parseBitAddress(args[0], args[1]); + auto t = det->getBitDefinitionName(addr); + os << t << '\n'; + } else { WrongNumberOfParameters(1); } @@ -1581,8 +1552,7 @@ std::string Caller::define_bit(int action) { throw RuntimeError("Bit position must be an integer value."); } auto name = args[0]; - auto reg = parseAddress(args[1]); - BitAddress addr(reg.str(), args[2]); + auto addr = parseBitAddress(args[1], args[2]); det->setBitDefinition(name, addr); os << ToString(args) << '\n'; } else { @@ -1600,12 +1570,6 @@ std::string Caller::definelist_reg(int action) { } else if (action == defs::PUT_ACTION) { throw RuntimeError("cannot put"); } else if (action == defs::GET_ACTION) { - auto det_type = det->getDetectorType().squash(); - if (det_type != defs::XILINX_CHIPTESTBOARD && - det_type != defs::CHIPTESTBOARD) { - throw RuntimeError( - "definelist_reg command only supported for ctb and xilinx_ctb"); - } if (!args.empty()) { WrongNumberOfParameters(0); } @@ -1624,12 +1588,6 @@ std::string Caller::definelist_bit(int action) { } else if (action == defs::PUT_ACTION) { throw RuntimeError("cannot put"); } else if (action == defs::GET_ACTION) { - auto det_type = det->getDetectorType().squash(); - if (det_type != defs::XILINX_CHIPTESTBOARD && - det_type != defs::CHIPTESTBOARD) { - throw RuntimeError( - "definelist_bit command only supported for ctb and xilinx_ctb"); - } if (!args.empty()) { WrongNumberOfParameters(0); } @@ -1637,13 +1595,7 @@ std::string Caller::definelist_bit(int action) { os << "\n["; for (const auto &[key, val] : t) { os << key << ": "; - bool found_addr = det->hasRegisterDefinition(val.address()); - if (found_addr) { - os << '[' << det->getRegisterDefinitionName(val.address()) - << ", " << std::to_string(val.bitPosition()) << "]"; - } else { - os << val.str(); - } + os << det->toRegisterNameBitString(val); if (&key != &t.rbegin()->first) { os << ", "; } @@ -1679,15 +1631,15 @@ std::string Caller::reg(int action) { WrongNumberOfParameters(2); } auto validate = parseValidate(); - auto addr = parseAddress(args[0]); - auto val = RegisterValue(args[1]); + auto addr = getRegisterAddress(args[0]); + auto val = parseRegisterValue(args[1]); det->writeRegister(addr, val, validate, std::vector{det_id}); os << addr.str() << " " << val.str() << '\n'; } else if (action == defs::GET_ACTION) { if (args.size() != 1) { WrongNumberOfParameters(1); } - auto addr = parseAddress(args[0]); + auto addr = getRegisterAddress(args[0]); auto t = det->readRegister(addr, std::vector{det_id}); os << OutString(t) << '\n'; } else { @@ -1739,20 +1691,20 @@ std::string Caller::bitoperations(int action) { } auto validate = parseValidate(); - auto BitAddress = parseBitAddress(); + auto addr = getBitAddress(); if (action == defs::GET_ACTION) { if (cmd == "setbit" || cmd == "clearbit") throw RuntimeError("Cannot get"); - auto t = det->getBit(BitAddress, std::vector{det_id}); + auto t = det->getBit(addr, std::vector{det_id}); os << OutString(t) << '\n'; } else { if (cmd == "getbit") throw RuntimeError("Cannot put"); if (cmd == "setbit") - det->setBit(BitAddress, validate, std::vector{det_id}); + det->setBit(addr, validate, std::vector{det_id}); else if (cmd == "clearbit") - det->clearBit(BitAddress, validate, std::vector{det_id}); + det->clearBit(addr, validate, std::vector{det_id}); else throw RuntimeError("Unknown command"); os << ToString(args) << "\n"; @@ -1761,26 +1713,47 @@ std::string Caller::bitoperations(int action) { return os.str(); } -RegisterAddress Caller::parseAddress(const std::string &saddr) const { - if (is_hex_or_dec_uint(saddr)) { - return RegisterAddress(saddr); +RegisterAddress Caller::parseRegisterAddress(const std::string &addr) const { + try { + return RegisterAddress(StringTo(addr)); + } catch (const std::exception &e) { + throw RuntimeError("Could not parse register address " + addr + + ". Must be an integer value"); } - auto det_type = det->getDetectorType().squash(); - if (det_type != defs::XILINX_CHIPTESTBOARD && - det_type != defs::CHIPTESTBOARD) { - throw RuntimeError( - "Could not parse address " + saddr + - ". User defined register definitions only supported for ctb and " - "xilinx_ctb. Use an actual hard coded address for this detector."); +} + +BitAddress Caller::parseBitAddress(const std::string &addr, + const std::string &bitPos) const { + auto address = getRegisterAddress(addr); + uint32_t bitPosition = 0; + + // parse bit position + if (!is_hex_or_dec_uint(bitPos)) { + throw RuntimeError("Bit position must be an integer value."); + } + try { + bitPosition = StringTo(bitPos); + } catch (const std::exception &e) { + throw RuntimeError("Could not parse bit position " + bitPos + + ". Must be an integer value"); + } + return BitAddress(address, bitPosition); +} + +RegisterValue Caller::parseRegisterValue(const std::string &addr) const { + try { + return RegisterValue(StringTo(addr)); + } catch (const std::exception &e) { + throw RuntimeError("Could not parse register value " + addr + + ". Must be an integer value"); } - return det->getRegisterDefinitionAddress(saddr); } bool Caller::parseValidate() { auto it = std::find(args.begin(), args.end(), "--validate"); bool validate = (it != args.end()); - // throw for any -- options other than --validate + // invalid argument (--options), throw if (!validate) { auto invalid_it = std::find_if(args.begin(), args.end(), [](const auto &s) { @@ -1793,7 +1766,7 @@ bool Caller::parseValidate() { } } - // --validate should be the last argument + // --validate should be the last argument (remove it from args) else { if (it != args.end() - 1) { throw RuntimeError("'--validate' should be the last argument."); @@ -1803,32 +1776,26 @@ bool Caller::parseValidate() { return validate; } -BitAddress Caller::parseBitAddress() const { - int argsSize = args.size(); - std::string addr_or_bitname = args[0]; - - // bit name - if (argsSize == 1) { - auto det_type = det->getDetectorType().squash(); - if (det_type != defs::XILINX_CHIPTESTBOARD && - det_type != defs::CHIPTESTBOARD) { - throw RuntimeError("Could not parse bit name " + addr_or_bitname + - ". User defined bit definitions only supported " - "for ctb and xilinx_ctb. Use an actual hard " - "coded bit position for this detector."); - } - return det->getBitDefinitionAddress(addr_or_bitname); +RegisterAddress Caller::getRegisterAddress(const std::string &saddr) const { + if (is_hex_or_dec_uint(saddr)) { + return parseRegisterAddress(saddr); } + return det->getRegisterDefinitionAddress(saddr); +} + +BitAddress Caller::getBitAddress() const { + int args_size = args.size(); // address and bit position - else if (argsSize == 2) { - auto reg = parseAddress(addr_or_bitname); - return BitAddress(reg.str(), args[1]); - } else { - throw RuntimeError("Command " + cmd + - " expected (1-4) parameter/s but got " + - std::to_string(args.size()) + "\n"); + if (args_size == 2) { + return parseBitAddress(args[0], args[1]); } + + // bit name + if (args_size == 1) { + return det->getBitDefinitionAddress(args[0]); + } + throw RuntimeError("Invalid number of parameters for bit address."); } } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/src/CtbConfig.cpp b/slsDetectorSoftware/src/CtbConfig.cpp index de919baeb..12b987a44 100644 --- a/slsDetectorSoftware/src/CtbConfig.cpp +++ b/slsDetectorSoftware/src/CtbConfig.cpp @@ -246,16 +246,16 @@ bool CtbConfig::hasBitName(const std::string &name) const { return bits.containsKey(fixed_name); } -bool CtbConfig::hasBitAddress(BitAddress bitPos) const { - return bits.hasValue(bitPos); +bool CtbConfig::hasBitAddress(BitAddress addr) const { + return bits.hasValue(addr); } void CtbConfig::clearBitNames() { bits.clear(); } -void CtbConfig::setBitName(const std::string &name, BitAddress bitPos) { +void CtbConfig::setBitName(const std::string &name, BitAddress addr) { try { auto fixed_name = FixedString(name); - bits.addKeyOrSetValue(fixed_name, bitPos); + bits.addKeyOrSetValue(fixed_name, addr); } catch (const std::runtime_error &e) { std::ostringstream oss; oss << e.what(); @@ -277,12 +277,26 @@ BitAddress CtbConfig::getBitAddress(const std::string &name) const { } } -std::string CtbConfig::getBitName(BitAddress bitPos) const { +std::string CtbConfig::toRegisterNameBitString(BitAddress addr) const { + std::ostringstream oss; + if (registers.hasValue(addr.address())) { + oss << "'[" << registers.getKey(addr.address()).str() << ", " + << std::to_string(addr.bitPosition()) << "]' "; + } else { + oss << "'" << addr.str() << "' "; + } + return oss.str(); +} + +std::string CtbConfig::getBitName(BitAddress addr) const { try { - return bits.getKey(bitPos).str(); + return bits.getKey(addr).str(); } catch (const std::runtime_error &e) { - throw RuntimeError("Could not get bit name for address '" + - bitPos.str() + "': " + std::string(e.what())); + std::ostringstream oss; + oss << "Could not get bit name for bit address "; + oss << toRegisterNameBitString(addr); + oss << ":" << e.what(); + throw RuntimeError(oss.str()); } } diff --git a/slsDetectorSoftware/src/CtbConfig.h b/slsDetectorSoftware/src/CtbConfig.h index 6cb620a8d..be5fc66a8 100644 --- a/slsDetectorSoftware/src/CtbConfig.h +++ b/slsDetectorSoftware/src/CtbConfig.h @@ -91,10 +91,11 @@ class CtbConfig { int getBitNamesCount() const; void clearBitNames(); bool hasBitName(const std::string &name) const; - bool hasBitAddress(BitAddress bitPos) const; - void setBitName(const std::string &name, BitAddress bitPos); + bool hasBitAddress(BitAddress addr) const; + std::string toRegisterNameBitString(BitAddress addr) const; + void setBitName(const std::string &name, BitAddress addr); BitAddress getBitAddress(const std::string &name) const; - std::string getBitName(BitAddress bitPos) const; + std::string getBitName(BitAddress addr) const; void setBitNames(const std::map &list); std::map getBitNames() const; }; diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 45726fad0..b726e6d51 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -2563,6 +2563,10 @@ bool Detector::hasBitDefinition(BitAddress addr) const { return pimpl->hasBitDefinition(addr); } +std::string Detector::toRegisterNameBitString(BitAddress addr) const { + return pimpl->toRegisterNameBitString(addr); +} + BitAddress Detector::getBitDefinitionAddress(const std::string &name) const { return pimpl->getBitDefinitionAddress(name); } diff --git a/slsDetectorSoftware/src/DetectorImpl.cpp b/slsDetectorSoftware/src/DetectorImpl.cpp index 1e49c7e25..2cccd17e3 100644 --- a/slsDetectorSoftware/src/DetectorImpl.cpp +++ b/slsDetectorSoftware/src/DetectorImpl.cpp @@ -2122,11 +2122,10 @@ int DetectorImpl::getBitDefinitionsCount() const { return ctb_shm()->getBitNamesCount(); } -void DetectorImpl::setBitDefinition(const std::string &name, - BitAddress bitPos) { +void DetectorImpl::setBitDefinition(const std::string &name, BitAddress addr) { if (!isChipTestBoard()) throw RuntimeError("Bit Definitions only for CTB"); - ctb_shm()->setBitName(name, bitPos); + ctb_shm()->setBitName(name, addr); } bool DetectorImpl::hasBitDefinition(const std::string &name) const { @@ -2135,10 +2134,16 @@ bool DetectorImpl::hasBitDefinition(const std::string &name) const { return ctb_shm()->hasBitName(name); } -bool DetectorImpl::hasBitDefinition(BitAddress bitPos) const { +bool DetectorImpl::hasBitDefinition(BitAddress addr) const { if (!isChipTestBoard()) throw RuntimeError("Bit Definitions only for CTB"); - return ctb_shm()->hasBitAddress(bitPos); + return ctb_shm()->hasBitAddress(addr); +} + +std::string DetectorImpl::toRegisterNameBitString(BitAddress addr) const { + if (!isChipTestBoard()) + throw RuntimeError("Bit Definitions only for CTB"); + return ctb_shm()->toRegisterNameBitString(addr); } BitAddress @@ -2148,10 +2153,10 @@ DetectorImpl::getBitDefinitionAddress(const std::string &name) const { return ctb_shm()->getBitAddress(name); } -std::string DetectorImpl::getBitDefinitionName(BitAddress bitPos) const { +std::string DetectorImpl::getBitDefinitionName(BitAddress addr) const { if (!isChipTestBoard()) throw RuntimeError("Bit Definitions only for CTB"); - return ctb_shm()->getBitName(bitPos); + return ctb_shm()->getBitName(addr); } void DetectorImpl::clearBitDefinitions() { diff --git a/slsDetectorSoftware/src/DetectorImpl.h b/slsDetectorSoftware/src/DetectorImpl.h index 31d54d609..39a55b62e 100644 --- a/slsDetectorSoftware/src/DetectorImpl.h +++ b/slsDetectorSoftware/src/DetectorImpl.h @@ -344,11 +344,12 @@ class DetectorImpl : public virtual slsDetectorDefs { setRegisterDefinitions(const std::map &list); std::map getRegisterDefinitions() const; int getBitDefinitionsCount() const; - void setBitDefinition(const std::string &name, BitAddress bitPos); + void setBitDefinition(const std::string &name, BitAddress addr); bool hasBitDefinition(const std::string &name) const; - bool hasBitDefinition(BitAddress bitPos) const; + bool hasBitDefinition(BitAddress addr) const; + std::string toRegisterNameBitString(BitAddress addr) const; BitAddress getBitDefinitionAddress(const std::string &name) const; - std::string getBitDefinitionName(BitAddress bitPos) const; + std::string getBitDefinitionName(BitAddress addr) const; void clearBitDefinitions(); void setBitDefinitions(const std::map &list); std::map getBitDefinitions() const; diff --git a/slsDetectorSoftware/src/MapOnStack.h b/slsDetectorSoftware/src/MapOnStack.h index 1474ac4bb..70a7aada1 100644 --- a/slsDetectorSoftware/src/MapOnStack.h +++ b/slsDetectorSoftware/src/MapOnStack.h @@ -1,18 +1,17 @@ #pragma once -//#include "sls/StaticVector.h" +// #include "sls/StaticVector.h" #include "sls/string_utils.h" -#include -#include -#include -#include #include +#include +#include +#include +#include namespace sls { -template -struct FixedString { +template struct FixedString { char data_[N]{}; constexpr FixedString() noexcept { memset(data_, 0, N); } FixedString(const char (&s)[N]) { @@ -21,21 +20,19 @@ struct FixedString { } strcpy_checked(data_, s); } - FixedString(const std::string& s) { + FixedString(const std::string &s) { if (s.size() <= 1) { throw std::runtime_error("FixedString cannot be empty"); } strcpy_checked(data_, s); } - bool operator==(const FixedString& other) const noexcept { + bool operator==(const FixedString &other) const noexcept { return std::strncmp(data_, other.data_, N) == 0; } - bool operator<(const FixedString& other) const noexcept { + bool operator<(const FixedString &other) const noexcept { return std::strncmp(data_, other.data_, N) < 0; } - std::string str() const { - return std::string(data_); - } + std::string str() const { return std::string(data_); } }; template @@ -49,26 +46,23 @@ class MapOnStack { static_assert(!std::is_pointer_v); static_assert(!std::is_pointer_v); - public: - + public: constexpr MapOnStack() noexcept = default; constexpr size_t size() const noexcept { return current_size_; } constexpr size_t capacity() const noexcept { return Capacity; } constexpr bool empty() const noexcept { return current_size_ == 0; } - void clear() noexcept { - current_size_ = 0; - } - - bool containsKey(const Key& key) const { + void clear() noexcept { current_size_ = 0; } + + bool containsKey(const Key &key) const { return lookupEntryByKey(key).has_value(); } - bool hasValue(const Value& value) const { + bool hasValue(const Value &value) const { return lookupEntryByValue(value).has_value(); } - void addKeyOrSetValue(const Key& key, const Value& value) { + void addKeyOrSetValue(const Key &key, const Value &value) { if (auto entry = findEntryByKey(key)) { (*entry)->setValue(value); return; @@ -76,19 +70,17 @@ class MapOnStack { addEntry(key, value); } - void addKey(const Key& key, const Value& value) { - addEntry(key, value); - } + void addKey(const Key &key, const Value &value) { addEntry(key, value); } - void setValue(const Key& key, const Value& value) { + void setValue(const Key &key, const Value &value) { if (auto entry = findEntryByKey(key)) { (*entry)->setValue(value); return; } throw std::runtime_error("Key not found. Cannot set value."); - } + } - Value getValue(const Key& key) const { + Value getValue(const Key &key) const { auto val = lookupEntryByKey(key); if (!val.has_value()) { throw std::runtime_error("No entry found for key"); @@ -96,7 +88,7 @@ class MapOnStack { return val.value(); } - Key getKey(const Value& value) const { + Key getKey(const Value &value) const { auto key = lookupEntryByValue(value); if (!key.has_value()) { throw std::runtime_error("No entry found for value"); @@ -126,30 +118,29 @@ class MapOnStack { Key key_{}; Value value_{}; constexpr Entry() noexcept = default; - constexpr Entry(const Key& key, const Value& value) : key_(key),value_(value) {} + constexpr Entry(const Key &key, const Value &value) + : key_(key), value_(value) {} constexpr Key key() const noexcept { return key_; } constexpr Value value() const noexcept { return value_; } constexpr void setValue(Value value) noexcept { value_ = value; } }; - Entry data_[Capacity]; size_t current_size_{0}; - //StaticVector entries_; + // StaticVector entries_; - std::optional findEntryByKey(const Key& key) { + std::optional findEntryByKey(const Key &key) { auto it = std::find_if(data_, data_ + current_size_, - [&key](Entry &e) { - return (e.key() == key); }); + [&key](Entry &e) { return (e.key() == key); }); if (it != data_ + current_size_) return it; return std::nullopt; } - std::optional findEntryByKey(const Key& key) const { - auto it = std::find_if(data_, data_ + current_size_, - [&key](const Entry &e) { - return (e.key() == key); }); + std::optional findEntryByKey(const Key &key) const { + auto it = + std::find_if(data_, data_ + current_size_, + [&key](const Entry &e) { return (e.key() == key); }); if (it != data_ + current_size_) return it; return std::nullopt; @@ -160,9 +151,9 @@ class MapOnStack { throw std::runtime_error( "Cannot lookup by value when unique values are not enforced."); } - auto it = std::find_if(data_, data_ + current_size_, - [&value](Entry &e) { - return e.value() == value; }); + auto it = + std::find_if(data_, data_ + current_size_, + [&value](Entry &e) { return e.value() == value; }); if (it != data_ + current_size_) return it; return std::nullopt; @@ -173,35 +164,37 @@ class MapOnStack { throw std::runtime_error( "Cannot lookup by value when unique values are not enforced."); } - auto it = std::find_if(data_, data_ + current_size_, - [&value](const Entry &e) { - return e.value() == value; }); + auto it = std::find_if( + data_, data_ + current_size_, + [&value](const Entry &e) { return e.value() == value; }); if (it != data_ + current_size_) return it; return std::nullopt; } - std::optional lookupEntryByKey(const Key& key) const { + std::optional lookupEntryByKey(const Key &key) const { auto entry = findEntryByKey(key); return (entry ? std::optional((*entry)->value()) : std::nullopt); } std::optional lookupEntryByValue(Value value) const { auto entry = findEntryByValue(value); - return (entry ? std::optional((*entry)->key()) - : std::nullopt); + return (entry ? std::optional((*entry)->key()) : std::nullopt); } - void checkDuplicateKey(const Key& key) const { + void checkDuplicateKey(const Key &key) const { if (auto entry = findEntryByKey(key)) { - throw std::runtime_error("Key already exists. Cannot have duplicate keys."); + throw std::runtime_error( + "Key already exists. Cannot have duplicate keys."); } } void checkDuplicateValue(Value value) const { if (Unique_Values) { if (auto entry = findEntryByValue(value)) { - throw std::runtime_error("Value already assigned to another key '" + (*entry)->key().str() + "'. Cannot assign it again."); + throw std::runtime_error( + "Value already assigned to another key '" + + (*entry)->key().str() + "'. Cannot assign it again."); } } } @@ -212,7 +205,7 @@ class MapOnStack { } } - void addEntry(const Key& key, const Value& value) { + void addEntry(const Key &key, const Value &value) { checkSize(); checkDuplicateKey(key); checkDuplicateValue(value); diff --git a/slsDetectorSoftware/tests/test-MapOnStack.cpp b/slsDetectorSoftware/tests/test-MapOnStack.cpp index df15a4fd1..a0d996670 100644 --- a/slsDetectorSoftware/tests/test-MapOnStack.cpp +++ b/slsDetectorSoftware/tests/test-MapOnStack.cpp @@ -1,5 +1,5 @@ -#include "catch.hpp" #include "MapOnStack.h" +#include "catch.hpp" #include "sls/bit_utils.h" #include diff --git a/slsSupportLib/include/sls/ToString.h b/slsSupportLib/include/sls/ToString.h index cde330962..5b56fbfc9 100644 --- a/slsSupportLib/include/sls/ToString.h +++ b/slsSupportLib/include/sls/ToString.h @@ -11,6 +11,7 @@ #include "sls/TimeHelper.h" #include "sls/TypeTraits.h" +#include "sls/bit_utils.h" #include "sls/sls_detector_defs.h" #include "sls/sls_detector_exceptions.h" #include "sls/string_utils.h" @@ -325,6 +326,8 @@ 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 <> RegisterAddress StringTo(const std::string &s); +template <> RegisterValue StringTo(const std::string &s); template <> uint8_t StringTo(const std::string &s); template <> uint16_t StringTo(const std::string &s); diff --git a/slsSupportLib/include/sls/bit_utils.h b/slsSupportLib/include/sls/bit_utils.h index 414c39d86..af86a8462 100644 --- a/slsSupportLib/include/sls/bit_utils.h +++ b/slsSupportLib/include/sls/bit_utils.h @@ -27,7 +27,6 @@ class RegisterAddress { public: constexpr RegisterAddress() noexcept = default; constexpr explicit RegisterAddress(uint32_t value) : value_(value) {} - explicit RegisterAddress(const std::string &value); std::string str() const; constexpr uint32_t value() const noexcept { return value_; } @@ -47,7 +46,6 @@ class BitAddress { public: constexpr BitAddress() noexcept = default; BitAddress(RegisterAddress address, uint32_t bitPosition); - BitAddress(const std::string &address, const std::string &bitPosition); std::string str() const; constexpr RegisterAddress address() const noexcept { return addr_; } constexpr uint32_t bitPosition() const noexcept { return bitPos_; } @@ -67,8 +65,6 @@ class RegisterValue { public: constexpr RegisterValue() noexcept = default; explicit constexpr RegisterValue(uint32_t value) noexcept : value_(value) {} - explicit RegisterValue(const std::string &value); - std::string str() const; constexpr uint32_t value() const noexcept { return value_; } diff --git a/slsSupportLib/src/bit_utils.cpp b/slsSupportLib/src/bit_utils.cpp index e779cceb0..e0ce84cc0 100644 --- a/slsSupportLib/src/bit_utils.cpp +++ b/slsSupportLib/src/bit_utils.cpp @@ -6,13 +6,6 @@ namespace sls { -RegisterAddress::RegisterAddress(const std::string &value) { - if (!is_hex_or_dec_uint(value)) { - throw RuntimeError("Address must be an integer value."); - } - value_ = StringTo(value); -} - std::string RegisterAddress::str() const { return ToStringHex(value_); } BitAddress::BitAddress(RegisterAddress address, uint32_t bitPosition) @@ -23,32 +16,12 @@ BitAddress::BitAddress(RegisterAddress address, uint32_t bitPosition) bitPos_ = bitPosition; } -BitAddress::BitAddress(const std::string &address, - const std::string &bitPosition) { - addr_ = RegisterAddress(address); - if (!is_hex_or_dec_uint(bitPosition)) { - throw RuntimeError("Bit position must be an integer value."); - } - uint32_t bitPos = StringTo(bitPosition); - if (bitPos > 31) { - throw RuntimeError("Bit position must be between 0 and 31."); - } - bitPos_ = bitPos; -} - std::string BitAddress::str() const { std::ostringstream os; os << '[' << addr_.str() << ", " << ToString(bitPos_) << ']'; return os.str(); } -RegisterValue::RegisterValue(const std::string &value) { - if (!is_hex_or_dec_uint(value)) { - throw RuntimeError("Value must be an integer value."); - } - value_ = StringTo(value); -} - std::string RegisterValue::str() const { return ToStringHex(value_); } std::ostream &operator<<(std::ostream &os, const RegisterAddress &r) { diff --git a/slsSupportLib/tests/test-bit_utils.cpp b/slsSupportLib/tests/test-bit_utils.cpp index d69a969b3..7f60b21b8 100644 --- a/slsSupportLib/tests/test-bit_utils.cpp +++ b/slsSupportLib/tests/test-bit_utils.cpp @@ -72,19 +72,15 @@ TEST_CASE("Convert RegisterValue using classes ", "[support][.bit_utils]") { for (size_t i = 0; i != vec_addr.size(); ++i) { auto reg0 = RegisterValue(vec_addr[i]); - auto reg1 = RegisterValue(vec_ans[i]); auto reg2 = RegisterValue(vec_addr[0]); - CHECK(reg0 == reg1); if (i != 0) - CHECK(reg2 != reg1); + CHECK(reg2 != reg0); CHECK(reg0.value() == vec_addr[i]); - CHECK(reg1.value() == vec_addr[i]); CHECK(reg0.str() == vec_ans[i]); - CHECK(reg1.str() == vec_ans[i]); CHECK((reg0 | 0xffffffffu) == RegisterValue(0xffffffffu)); CHECK((reg0 | 0x0) == reg0); - CHECK((reg0 | reg1) == reg0); + CHECK((reg0 | 0x1) == reg0); } } @@ -105,7 +101,7 @@ TEST_CASE("Convert BitAddress using classes", "[support][.bit_utils]") { for (size_t i = 0; i != vec_addr.size(); ++i) { auto reg0 = BitAddress(vec_addr[i], vec_bitpos[i]); - BitAddress reg1(vec_addr_str[i], vec_bitpos_str[i]); + BitAddress reg1(vec_addr[i], vec_bitpos[i]); CHECK(reg1.address() == vec_addr[i]); CHECK(reg1.bitPosition() == vec_bitpos[i]); @@ -129,21 +125,21 @@ TEST_CASE("Convert BitAddress using classes", "[support][.bit_utils]") { TEST_CASE("Output operator gives same result as string", "[support][.bit_utils]") { { - RegisterAddress addr{"0x3456af"}; + RegisterAddress addr{0x3456af}; std::ostringstream os; os << addr; CHECK(os.str() == "0x3456af"); CHECK(os.str() == addr.str()); } { - BitAddress addr("0x3456af", "15"); + BitAddress addr{RegisterAddress(0x3456af), 15}; std::ostringstream os; os << addr; CHECK(os.str() == "[0x3456af, 15]"); CHECK(os.str() == addr.str()); } { - RegisterValue addr{"0x3456af"}; + RegisterValue addr{0x3456af}; std::ostringstream os; os << addr; CHECK(os.str() == "0x3456af"); @@ -151,40 +147,4 @@ TEST_CASE("Output operator gives same result as string", } } -TEST_CASE("Strange input throws", "[support][.bit_utils]") { - REQUIRE_THROWS(RegisterAddress("hej")); - // ensure correct exception message - try { - RegisterAddress("hej"); - } catch (const std::exception &e) { - REQUIRE(std::string(e.what()) == "Address must be an integer value."); - } - - REQUIRE_THROWS(BitAddress("0x305", "hej")); - // ensure correct exception message - try { - BitAddress("0x305", "hej"); - } catch (const std::exception &e) { - REQUIRE(std::string(e.what()) == - "Bit position must be an integer value."); - } - - REQUIRE_THROWS(BitAddress(RegisterAddress(0x305), 32)); - // ensure correct exception message - try { - BitAddress(RegisterAddress(0x305), 32); - } catch (const std::exception &e) { - REQUIRE(std::string(e.what()) == - "Bit position must be between 0 and 31."); - } - - REQUIRE_THROWS(RegisterValue("hej")); - // ensure correct exception message - try { - RegisterValue("hej"); - } catch (const std::exception &e) { - REQUIRE(std::string(e.what()) == "Value must be an integer value."); - } -} - } // namespace sls