* WIP

* WIP

* WIP

* cleaned up multi

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* split up python module

* WIP

* WIP

* WIP

* WIP

* WIP

* ok

* fixed bugs from rebase

* WIP

* fixed broken test

* WIP

* fixed python

* WIP

* sphinx help

* including new commands

* docs

* WIP

* WIP

* more tests

* added missing public header

* WIP
This commit is contained in:
Dhanya Thattil
2019-08-07 11:21:07 +02:00
committed by GitHub
parent 98ddf154b2
commit 4ceee97c03
58 changed files with 2317 additions and 571 deletions

View File

@ -1,5 +1,6 @@
#pragma once
#include <chrono>
#include <iomanip>
#include <iostream>
#include <map>
@ -7,12 +8,48 @@
#include <string>
#include <vector>
#include "Result.h"
#include "TimeHelper.h"
#include "ToString.h"
#include "container_utils.h"
#include "logger.h"
#include "slsDetectorCommand.h"
#include "sls_detector_exceptions.h"
#include "sls_detector_defs.h"
#include "sls_detector_exceptions.h"
#include "string_utils.h"
#define TIME_COMMAND(GETFCN, SETFCN, HLPSTR) \
std::ostringstream os; \
os << cmd << ' '; \
if (action == slsDetectorDefs::HELP_ACTION) \
os << HLPSTR << '\n'; \
else if (action == slsDetectorDefs::GET_ACTION) { \
auto t = det->GETFCN({det_id}); \
if (args.size() == 0) { \
os << OutString(t) << '\n'; \
} else if (args.size() == 1) { \
os << OutString(t, args[0]) << '\n'; \
} else { \
WrongNumberOfParameters(2); \
} \
} else if (action == slsDetectorDefs::PUT_ACTION) { \
if (args.size() == 1) { \
std::string time_str(args[0]); \
std::string unit = RemoveUnit(time_str); \
auto t = StringTo<time::ns>(time_str, unit); \
det->SETFCN(t, {det_id}); \
} else if (args.size() == 2) { \
auto t = StringTo<time::ns>(args[0], args[1]); \
det->SETFCN(t, {det_id}); \
} else { \
WrongNumberOfParameters(2); \
} \
os << ToString(args) << '\n'; \
} else { \
throw sls::RuntimeError("Unknown action"); \
} \
return os.str();
namespace sls {
template <typename T> class CmdProxy {
@ -20,9 +57,8 @@ template <typename T> class CmdProxy {
explicit CmdProxy(T *detectorPtr) : det(detectorPtr) {}
std::string Call(const std::string &command,
const std::vector<std::string> &arguments,
int detector_id,
int action=-1) {
const std::vector<std::string> &arguments, int detector_id,
int action = -1, std::ostream &os = std::cout) {
cmd = command;
args = arguments;
det_id = detector_id;
@ -31,7 +67,7 @@ template <typename T> class CmdProxy {
auto it = functions.find(cmd);
if (it != functions.end()) {
std::cout << ((*this).*(it->second))(action);
os << ((*this).*(it->second))(action);
return {};
} else {
return cmd;
@ -53,17 +89,47 @@ template <typename T> class CmdProxy {
size_t GetFunctionMapSize() const noexcept { return functions.size(); };
std::vector<std::string> GetAllCommands() {
auto commands = slsDetectorCommand(nullptr).getAllCommands();
for (const auto &it : functions)
commands.emplace_back(it.first);
std::sort(begin(commands), end(commands));
return commands;
}
std::vector<std::string> GetProxyCommands() {
std::vector<std::string> commands;
for (const auto &it : functions)
commands.emplace_back(it.first);
std::sort(begin(commands), end(commands));
return commands;
}
private:
T *det;
std::string cmd;
std::vector<std::string> args;
int det_id{-1};
template <typename V> std::string OutString(const V &value) {
if (value.equal())
return ToString(value.front());
return ToString(value);
}
template <typename V>
std::string OutString(const V &value, const std::string &unit) {
if (value.equal())
return ToString(value.front(), unit);
return ToString(value, unit);
}
using FunctionMap = std::map<std::string, std::string (CmdProxy::*)(int)>;
using StringMap = std::map<std::string, std::string>;
// Initialize maps for translating name and function
FunctionMap functions{{"list", &CmdProxy::ListCommands}};
FunctionMap functions{{"list", &CmdProxy::ListCommands},
{"exptime2", &CmdProxy::Exptime},
{"period2", &CmdProxy::Period},
{"subexptime2", &CmdProxy::SubExptime}};
StringMap depreciated_functions{{"r_readfreq", "rx_readfreq"},
{"r_padding", "rx_padding"},
@ -92,10 +158,10 @@ template <typename T> class CmdProxy {
}
// Mapped functions
std::string ListCommands(int action) {
if (action==slsDetectorDefs::HELP_ACTION)
return "list - lists all available commands, list deprecated - list deprecated commands\n";
if (action == slsDetectorDefs::HELP_ACTION)
return "list\n\tlists all available commands, list deprecated - "
"list deprecated commands\n";
if (args.size() == 0) {
auto commands = slsDetectorCommand(nullptr).getAllCommands();
@ -127,6 +193,22 @@ template <typename T> class CmdProxy {
return "";
}
}
std::string Period(int action) {
TIME_COMMAND(
getPeriod, setPeriod,
"[duration] [(optional unit) ns|us|ms|s]\n\tSet the period");
}
std::string Exptime(int action) {
TIME_COMMAND(
getExptime, setExptime,
"[duration] [(optional unit) ns|us|ms|s]\n\tSet the exposure time");
}
std::string SubExptime(int action) {
TIME_COMMAND(getSubExptime, setSubExptime,
"[duration] [(optional unit) ns|us|ms|s]\n\tSet the "
"exposure time of EIGER subframes");
}
};
} // namespace sls

View File

@ -0,0 +1,19 @@
#pragma once
#include <chrono>
#include "TypeTraits.h"
namespace sls {
namespace time {
using ns = std::chrono::nanoseconds;
using us = std::chrono::microseconds;
using ms = std::chrono::milliseconds;
using s = std::chrono::seconds;
//Absolute value of std::chrono::duration
template <class Rep, class Period>
constexpr std::chrono::duration<Rep, Period> abs(std::chrono::duration<Rep, Period> d) {
return d >= d.zero() ? d : -d;
}
} // namespace time
} // namespace sls

View File

@ -0,0 +1,140 @@
#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

View File

@ -0,0 +1,48 @@
#pragma once
#include <type_traits>
namespace sls {
/**
* Type trait to check if atemplate parameter is a std::chrono::duration
*/
template <typename T, typename _ = void>
struct is_duration : std::false_type {};
template <typename... Ts> struct is_duration_helper {};
template <typename T>
struct is_duration<T,
typename std::conditional<
false,
is_duration_helper<typename T::rep, typename T::period,
decltype(std::declval<T>().min()),
decltype(std::declval<T>().max()),
decltype(std::declval<T>().zero())>,
void>::type> : public std::true_type {};
/**
* Type trait to evaluate if template parameter is
* complying with a standard container
*/
template <typename T, typename _ = void>
struct is_container : std::false_type {};
template <typename... Ts> struct is_container_helper {};
template <typename T>
struct is_container<
T, typename std::conditional<
false,
is_container_helper<typename T::value_type, typename T::size_type,
typename T::iterator, typename T::const_iterator,
decltype(std::declval<T>().size()),
decltype(std::declval<T>().begin()),
decltype(std::declval<T>().end()),
decltype(std::declval<T>().cbegin()),
decltype(std::declval<T>().cend()),
decltype(std::declval<T>().empty())>,
void>::type> : public std::true_type {};
} // namespace sls

View File

@ -9,6 +9,8 @@
#include <type_traits>
#include <vector>
#include "TypeTraits.h"
namespace sls {
// C++11 make_unique implementation for exception safety
@ -26,14 +28,21 @@ make_unique(std::size_t n) {
return std::unique_ptr<T>(new RT[n]);
}
template <typename T> bool allEqual(const std::vector<T> &container) {
if (container.empty())
return false;
const auto &first = container[0];
return std::all_of(container.cbegin(), container.cend(),
[first](const T &element) { return element == first; });
/** Compare elements in a Container to see if they are all equal */
template <typename Container> bool allEqual(const Container &c) {
if (!c.empty() &&
std::all_of(begin(c), end(c),
[c](const typename Container::value_type &element) {
return element == c.front();
}))
return true;
return false;
}
/**
* Compare elements but with specified tolerance, useful
* for floating point values.
*/
template <typename T>
typename std::enable_if<std::is_arithmetic<T>::value, bool>::type
allEqualWithTol(const std::vector<T> &container, const T tol) {
@ -111,15 +120,31 @@ minusOneIfDifferent(const std::vector<std::vector<T>> &container) {
template <typename T, size_t size>
std::array<T, size>
minusOneIfDifferent(const std::vector<std::array<T,size>> &container) {
minusOneIfDifferent(const std::vector<std::array<T, size>> &container) {
if (allEqual(container))
return container.front();
std::array<T,size> arr;
std::array<T, size> arr;
arr.fill(static_cast<T>(-1));
return arr;
}
/**
* Return the first value if all values are equal
* otherwise return default_value. If no default
* value is supplied it will be default constructed
*/
template <typename Container>
typename Container::value_type
Squash(const Container &c, typename Container::value_type default_value = {}) {
if (!c.empty() &&
std::all_of(begin(c), end(c),
[c](const typename Container::value_type &element) {
return element == c.front();
}))
return c.front();
return default_value;
}
} // namespace sls

View File

@ -1,14 +1,6 @@
#pragma once
/************************************************
* @file sls_detector_exceptions.h
* @short exceptions defined
***********************************************/
/**
*@short exceptions defined
*/
#include "logger.h"
#include <iostream>
#include <stdexcept>

View File

@ -1,30 +1,30 @@
#pragma once
#include <string>
#include <vector>
#include <cassert>
#include <cstring>
#include <string>
#include <vector>
namespace sls {
/* Implementation of a safe string copy function for setting fields in
for example the multi sls detector. It tries to copy the size of the
destination from the source, stopping on '\0'.
/* Implementation of a safe string copy function for setting fields in
for example the multi sls detector. It tries to copy the size of the
destination from the source, stopping on '\0'.
Warning this will truncate the source string and should be used with care.
Warning this will truncate the source string and should be used with care.
Still this is better than strcpy and a buffer overflow...
*/
template <size_t array_size>
void strcpy_safe(char (&destination)[array_size], const char *source) {
assert(array_size > strlen(source));
strncpy(destination, source, array_size-1);
strncpy(destination, source, array_size - 1);
destination[array_size - 1] = '\0';
}
template <size_t array_size>
void strcpy_safe(char (&destination)[array_size], const std::string& source) {
void strcpy_safe(char (&destination)[array_size], const std::string &source) {
assert(array_size > source.size());
strncpy(destination, source.c_str(), array_size-1);
strncpy(destination, source.c_str(), array_size - 1);
destination[array_size - 1] = '\0';
}
@ -32,8 +32,7 @@ void strcpy_safe(char (&destination)[array_size], const std::string& source) {
Removes all occurrences of the specified char from a c string
Templated on array size to ensure no access after buffer limits.
*/
template <size_t array_size>
void removeChar(char (&str)[array_size], char ch) {
template <size_t array_size> void removeChar(char (&str)[array_size], char ch) {
int count = 0;
for (int i = 0; str[i]; i++) {
if (str[i] != ch)
@ -44,7 +43,7 @@ void removeChar(char (&str)[array_size], char ch) {
str[count] = '\0';
}
/*
/*
Split a string using the specified delimeter and return a vector of strings.
TODO! Look into switching to absl or a string_view based implementation. Current
implementation should not be used in a performance critical place.
@ -62,9 +61,10 @@ Concatenate strings using + if the strings are different
std::string concatenateIfDifferent(const std::vector<std::string> &container);
/*
Concatenate vector of things with str method using + if the strings are different
Concatenate vector of things with str method using + if the strings are
different
*/
template<typename T>
template <typename T>
std::string concatenateIfDifferent(const std::vector<T> &container);
/*
@ -72,4 +72,7 @@ Convert an ip address string to a string in hex format. (removing dots)
*/
std::string stringIpToHex(const std::string &ip);
// remove the end of the string starting with the first aplhabetic character
// return the end
std::string RemoveUnit(std::string &str);
}; // namespace sls