mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2026-01-22 09:22:54 +01:00
Merge branch 'developer' into MH01_debug
This commit is contained in:
@@ -17,6 +17,7 @@ set(SOURCES
|
||||
src/sls_detector_exceptions.cpp
|
||||
src/md5_helper.cpp
|
||||
src/Version.cpp
|
||||
src/bit_utils.cpp
|
||||
)
|
||||
|
||||
# Header files to install as a part of the library
|
||||
@@ -29,6 +30,7 @@ set(PUBLICHEADERS
|
||||
include/sls/ToString.h
|
||||
include/sls/TypeTraits.h
|
||||
include/sls/TimeHelper.h
|
||||
include/sls/bit_utils.h
|
||||
)
|
||||
|
||||
# Additional headers to be installed if SLS_DEVEL_HEADERS
|
||||
|
||||
@@ -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"
|
||||
@@ -65,6 +66,7 @@ std::ostream &operator<<(std::ostream &os,
|
||||
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 */
|
||||
@@ -324,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);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <bitset>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
namespace sls {
|
||||
template <typename T> std::vector<int> getSetBits(T val) {
|
||||
@@ -18,4 +19,87 @@ template <typename T> std::vector<int> getSetBits(T val) {
|
||||
}
|
||||
return set_bits;
|
||||
}
|
||||
|
||||
class RegisterAddress {
|
||||
private:
|
||||
uint32_t value_{0};
|
||||
|
||||
public:
|
||||
constexpr RegisterAddress() noexcept = default;
|
||||
constexpr explicit RegisterAddress(uint32_t value) : value_(value) {}
|
||||
std::string str() const;
|
||||
constexpr uint32_t value() const noexcept { return value_; }
|
||||
|
||||
constexpr bool operator==(const RegisterAddress &other) const {
|
||||
return (value_ == other.value_);
|
||||
}
|
||||
constexpr bool operator!=(const RegisterAddress &other) const {
|
||||
return (value_ != other.value_);
|
||||
}
|
||||
};
|
||||
|
||||
class BitAddress {
|
||||
private:
|
||||
RegisterAddress addr_{0};
|
||||
uint32_t bitPos_{0};
|
||||
|
||||
public:
|
||||
constexpr BitAddress() noexcept = default;
|
||||
BitAddress(RegisterAddress address, uint32_t bitPosition);
|
||||
std::string str() const;
|
||||
constexpr RegisterAddress address() const noexcept { return addr_; }
|
||||
constexpr uint32_t bitPosition() const noexcept { return bitPos_; }
|
||||
|
||||
constexpr bool operator==(const BitAddress &other) const {
|
||||
return (addr_ == other.addr_ && bitPos_ == other.bitPos_);
|
||||
}
|
||||
constexpr bool operator!=(const BitAddress &other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
};
|
||||
|
||||
class RegisterValue {
|
||||
private:
|
||||
uint32_t value_{0};
|
||||
|
||||
public:
|
||||
constexpr RegisterValue() noexcept = default;
|
||||
explicit constexpr RegisterValue(uint32_t value) noexcept : value_(value) {}
|
||||
std::string str() const;
|
||||
constexpr uint32_t value() const noexcept { return value_; }
|
||||
|
||||
constexpr RegisterValue &operator|=(const RegisterValue &rhs) noexcept {
|
||||
value_ |= rhs.value();
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr RegisterValue operator|(const RegisterValue &rhs) const noexcept {
|
||||
RegisterValue tmp(*this);
|
||||
tmp |= rhs;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
constexpr RegisterValue &operator|=(uint32_t rhs) noexcept {
|
||||
value_ |= rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr RegisterValue operator|(uint32_t rhs) const noexcept {
|
||||
RegisterValue tmp(*this);
|
||||
tmp |= rhs;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
constexpr bool operator==(const RegisterValue &other) const noexcept {
|
||||
return value_ == other.value_;
|
||||
}
|
||||
constexpr bool operator!=(const RegisterValue &other) const noexcept {
|
||||
return value_ != other.value_;
|
||||
}
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const RegisterAddress &r);
|
||||
std::ostream &operator<<(std::ostream &os, const BitAddress &r);
|
||||
std::ostream &operator<<(std::ostream &os, const RegisterValue &r);
|
||||
|
||||
} // namespace sls
|
||||
|
||||
@@ -181,20 +181,18 @@ typename std::enable_if<is_container<T>::value, bool>::type
|
||||
stableRemoveDuplicates(T &c) {
|
||||
auto containerSize = c.size();
|
||||
std::set<typename T::value_type> seen;
|
||||
c.erase(
|
||||
std::remove_if(c.begin(), c.end(),
|
||||
[&](const typename T::value_type& val) {
|
||||
return !seen.insert(val).second; // erase if already seen
|
||||
}),
|
||||
c.end()
|
||||
);
|
||||
c.erase(std::remove_if(
|
||||
c.begin(), c.end(),
|
||||
[&](const typename T::value_type &val) {
|
||||
return !seen.insert(val).second; // erase if already seen
|
||||
}),
|
||||
c.end());
|
||||
if (c.size() != containerSize) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
} // namespace sls
|
||||
|
||||
#endif // CONTAINER_UTILS_H
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
@@ -33,6 +34,35 @@ void strcpy_safe(char (&destination)[array_size], const std::string &source) {
|
||||
destination[array_size - 1] = '\0';
|
||||
}
|
||||
|
||||
// Runtime-checked variant — throws if it won't fit
|
||||
template <size_t array_size>
|
||||
void strcpy_checked(char (&destination)[array_size], const char *source) {
|
||||
if (!source)
|
||||
throw std::runtime_error("Null source pointer in strcpy_checked");
|
||||
|
||||
size_t len = std::strlen(source);
|
||||
if (len >= (array_size - 1)) {
|
||||
throw std::runtime_error("String length (" + std::to_string(len) +
|
||||
") should be less than " +
|
||||
std::to_string(array_size - 1) + " chars");
|
||||
}
|
||||
std::strncpy(destination, source, array_size - 1);
|
||||
destination[array_size - 1] = '\0';
|
||||
}
|
||||
|
||||
template <size_t array_size>
|
||||
void strcpy_checked(char (&destination)[array_size],
|
||||
const std::string &source) {
|
||||
if (source.size() >= (array_size - 1)) {
|
||||
throw std::runtime_error("String length (" +
|
||||
std::to_string(source.size()) +
|
||||
") should be less than " +
|
||||
std::to_string(array_size - 1) + " chars");
|
||||
}
|
||||
std::strncpy(destination, source.c_str(), array_size - 1);
|
||||
destination[array_size - 1] = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
Removes all occurrences of the specified char from a c string
|
||||
Templated on array size to ensure no access after buffer limits.
|
||||
@@ -58,6 +88,8 @@ std::vector<std::string> split(const std::string &strToSplit, char delimeter);
|
||||
std::string RemoveUnit(std::string &str);
|
||||
|
||||
bool is_int(const std::string &s);
|
||||
/** '0x200' is also an int here */
|
||||
bool is_hex_or_dec_uint(const std::string &s);
|
||||
|
||||
bool replace_first(std::string *s, const std::string &substr,
|
||||
const std::string &repl);
|
||||
|
||||
42
slsSupportLib/src/bit_utils.cpp
Normal file
42
slsSupportLib/src/bit_utils.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
#include "sls/bit_utils.h"
|
||||
#include "sls/ToString.h"
|
||||
#include "sls/sls_detector_exceptions.h"
|
||||
|
||||
namespace sls {
|
||||
|
||||
std::string RegisterAddress::str() const { return ToStringHex(value_); }
|
||||
|
||||
BitAddress::BitAddress(RegisterAddress address, uint32_t bitPosition)
|
||||
: addr_(address) {
|
||||
if (bitPosition > 31) {
|
||||
throw RuntimeError("Bit position must be between 0 and 31.");
|
||||
}
|
||||
bitPos_ = bitPosition;
|
||||
}
|
||||
|
||||
std::string BitAddress::str() const {
|
||||
std::ostringstream os;
|
||||
os << '[' << addr_.str() << ", " << ToString(bitPos_) << ']';
|
||||
return os.str();
|
||||
}
|
||||
|
||||
std::string RegisterValue::str() const { return ToStringHex(value_); }
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const RegisterAddress &r) {
|
||||
os << r.str();
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const BitAddress &r) {
|
||||
os << r.str();
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const RegisterValue &r) {
|
||||
os << r.str();
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace sls
|
||||
@@ -256,24 +256,22 @@ std::string getAbsolutePathFromCurrentProcess(const std::string &fname) {
|
||||
return fname;
|
||||
}
|
||||
|
||||
//in case PATH_MAX defines the longest possible path on linux and macOS
|
||||
//use string instead of char array to avoid overflow
|
||||
std::string path(PATH_MAX, '\0');
|
||||
// in case PATH_MAX defines the longest possible path on linux and macOS
|
||||
// use string instead of char array to avoid overflow
|
||||
std::string path(PATH_MAX, '\0');
|
||||
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#if defined(__APPLE__)
|
||||
uint32_t size = PATH_MAX;
|
||||
if (_NSGetExecutablePath(path.data(), &size) != 0) {
|
||||
throw std::runtime_error("Failed to get executable path");
|
||||
}
|
||||
// Resolve any symlinks and .. components
|
||||
std::string resolved(PATH_MAX, '\0');
|
||||
std::string resolved(PATH_MAX, '\0');
|
||||
if (!realpath(path.data(), resolved.data())) {
|
||||
throw std::runtime_error("realpath failed for executable");
|
||||
}
|
||||
path = resolved;
|
||||
#else
|
||||
|
||||
#else
|
||||
|
||||
ssize_t len = readlink("/proc/self/exe", path.data(), PATH_MAX - 1);
|
||||
if (len < 0) {
|
||||
@@ -281,7 +279,7 @@ std::string getAbsolutePathFromCurrentProcess(const std::string &fname) {
|
||||
}
|
||||
path[len] = '\0';
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// get dir path and attach file name
|
||||
std::string absPath = (std::string(dirname(path.data())) + '/' + fname);
|
||||
|
||||
@@ -179,8 +179,7 @@ IpAddr InterfaceNameToIp(const std::string &ifn) {
|
||||
MacAddr InterfaceNameToMac(const std::string &inf) {
|
||||
|
||||
#ifdef __APPLE__
|
||||
throw RuntimeError(
|
||||
"InterfaceNameToMac not implemented on macOS yet");
|
||||
throw RuntimeError("InterfaceNameToMac not implemented on macOS yet");
|
||||
#else
|
||||
|
||||
// TODO! Copied from genericSocket needs to be refactored!
|
||||
|
||||
@@ -43,6 +43,15 @@ bool is_int(const std::string &s) {
|
||||
}) == s.end();
|
||||
}
|
||||
|
||||
bool is_hex_or_dec_uint(const std::string &s) {
|
||||
try {
|
||||
StringTo<uint32_t>(s);
|
||||
return true;
|
||||
} catch (...) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool replace_first(std::string *s, const std::string &substr,
|
||||
const std::string &repl) {
|
||||
auto pos = s->find(substr);
|
||||
|
||||
@@ -84,8 +84,8 @@ TEST_CASE("Shutdown socket without hanging when waiting for data") {
|
||||
|
||||
// Start a thread and wait for package
|
||||
// if the socket is left open we would block
|
||||
std::future<bool> ret =
|
||||
std::async(std::launch::async, &UdpRxSocket::ReceivePacket, &s, (char *)&buff);
|
||||
std::future<bool> ret = std::async(
|
||||
std::launch::async, &UdpRxSocket::ReceivePacket, &s, (char *)&buff);
|
||||
|
||||
s.Shutdown();
|
||||
auto r = ret.get();
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
#include "catch.hpp"
|
||||
#include "sls/bit_utils.h"
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
namespace sls {
|
||||
@@ -42,4 +43,108 @@ TEST_CASE("Get set bits from 523") {
|
||||
REQUIRE(vec == std::vector<int>{0, 1, 3, 9});
|
||||
}
|
||||
|
||||
TEST_CASE("Convert RegisterAddress using classes ", "[support][.bit_utils]") {
|
||||
std::vector<uint32_t> vec_addr{0x305, 0xffffffff, 0x0, 0x34550987,
|
||||
0x1fff1fff};
|
||||
std::vector<std::string> vec_ans{"0x305", "0xffffffff", "0x0", "0x34550987",
|
||||
"0x1fff1fff"};
|
||||
|
||||
for (size_t i = 0; i != vec_addr.size(); ++i) {
|
||||
auto reg0 = RegisterAddress(vec_addr[i]);
|
||||
auto reg1 = RegisterAddress(vec_addr[i]);
|
||||
auto reg2 = RegisterAddress(vec_addr[0]);
|
||||
|
||||
CHECK(reg0 == reg1);
|
||||
if (i != 0)
|
||||
CHECK(reg2 != reg1);
|
||||
CHECK(reg0.value() == vec_addr[i]);
|
||||
CHECK(reg1.value() == vec_addr[i]);
|
||||
CHECK(reg0.str() == vec_ans[i]);
|
||||
CHECK(reg1.str() == vec_ans[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Convert RegisterValue using classes ", "[support][.bit_utils]") {
|
||||
std::vector<uint32_t> vec_addr{0x305, 0xffffffff, 0x0, 500254562,
|
||||
0x1fff1fff};
|
||||
std::vector<std::string> vec_ans{"0x305", "0xffffffff", "0x0", "0x1dd14762",
|
||||
"0x1fff1fff"};
|
||||
|
||||
for (size_t i = 0; i != vec_addr.size(); ++i) {
|
||||
auto reg0 = RegisterValue(vec_addr[i]);
|
||||
auto reg2 = RegisterValue(vec_addr[0]);
|
||||
|
||||
if (i != 0)
|
||||
CHECK(reg2 != reg0);
|
||||
CHECK(reg0.value() == vec_addr[i]);
|
||||
CHECK(reg0.str() == vec_ans[i]);
|
||||
CHECK((reg0 | 0xffffffffu) == RegisterValue(0xffffffffu));
|
||||
CHECK((reg0 | 0x0) == reg0);
|
||||
CHECK((reg0 | 0x1) == reg0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Convert BitAddress using classes", "[support][.bit_utils]") {
|
||||
std::vector<RegisterAddress> vec_addr{
|
||||
RegisterAddress(0x305), RegisterAddress(0xffffffffu),
|
||||
RegisterAddress(0x0), RegisterAddress(0x34550987),
|
||||
RegisterAddress(0x1fff1fff)};
|
||||
std::vector<std::string> vec_addr_str{"0x305", "0xffffffff", "0x0",
|
||||
"0x34550987", "0x1fff1fff"};
|
||||
std::vector<uint32_t> vec_bitpos{0, 15, 31, 7, 23};
|
||||
std::vector<std::string> vec_bitpos_str{"0", "15", "31", "7", "23"};
|
||||
std::vector<std::string> vec_ans{
|
||||
"[0x305, 0]", "[0xffffffff, 15]", "[0x0, 31]",
|
||||
"[0x34550987, 7]", "[0x1fff1fff, 23]",
|
||||
};
|
||||
|
||||
for (size_t i = 0; i != vec_addr.size(); ++i) {
|
||||
auto reg0 = BitAddress(vec_addr[i], vec_bitpos[i]);
|
||||
|
||||
BitAddress reg1(vec_addr[i], vec_bitpos[i]);
|
||||
CHECK(reg1.address() == vec_addr[i]);
|
||||
CHECK(reg1.bitPosition() == vec_bitpos[i]);
|
||||
|
||||
auto reg2 = BitAddress(vec_addr[0], vec_bitpos[0]);
|
||||
|
||||
CHECK(reg0 == reg1);
|
||||
if (i != 0)
|
||||
CHECK(reg2 != reg1);
|
||||
CHECK(reg0.address() == vec_addr[i]);
|
||||
CHECK(reg1.address() == vec_addr[i]);
|
||||
CHECK(reg0.bitPosition() == vec_bitpos[i]);
|
||||
CHECK(reg1.bitPosition() == vec_bitpos[i]);
|
||||
CHECK(std::to_string(reg0.bitPosition()) == vec_bitpos_str[i]);
|
||||
CHECK(std::to_string(reg1.bitPosition()) == vec_bitpos_str[i]);
|
||||
|
||||
CHECK(reg0.str() == vec_ans[i]);
|
||||
CHECK(reg1.str() == vec_ans[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Output operator gives same result as string",
|
||||
"[support][.bit_utils]") {
|
||||
{
|
||||
RegisterAddress addr{0x3456af};
|
||||
std::ostringstream os;
|
||||
os << addr;
|
||||
CHECK(os.str() == "0x3456af");
|
||||
CHECK(os.str() == addr.str());
|
||||
}
|
||||
{
|
||||
BitAddress addr{RegisterAddress(0x3456af), 15};
|
||||
std::ostringstream os;
|
||||
os << addr;
|
||||
CHECK(os.str() == "[0x3456af, 15]");
|
||||
CHECK(os.str() == addr.str());
|
||||
}
|
||||
{
|
||||
RegisterValue addr{0x3456af};
|
||||
std::ostringstream os;
|
||||
os << addr;
|
||||
CHECK(os.str() == "0x3456af");
|
||||
CHECK(os.str() == addr.str());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sls
|
||||
|
||||
@@ -175,13 +175,12 @@ TEST_CASE("remove duplicates but keep order, all elements the same ") {
|
||||
}
|
||||
|
||||
TEST_CASE("remove duplicates but keep order, pattern ") {
|
||||
std::vector<int> v{8,1,2,8,8,3,2};
|
||||
std::vector<int> v{8, 1, 2, 8, 8, 3, 2};
|
||||
auto r = stableRemoveDuplicates(v);
|
||||
CHECK(r == true); // did indeed remove elements
|
||||
CHECK(v == std::vector<int>{8,1,2,3});
|
||||
CHECK(v == std::vector<int>{8, 1, 2, 3});
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("remove duplicated empty vector") {
|
||||
std::vector<int> v;
|
||||
auto r = removeDuplicates(v);
|
||||
|
||||
Reference in New Issue
Block a user