-
Notifications
You must be signed in to change notification settings - Fork 0
/
utils.hpp
85 lines (77 loc) · 2.47 KB
/
utils.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#pragma once
extern "C" {
#include "nexoid-ed/include/dmapi.h"
}
#include <limits>
#include <string>
#include <iomanip>
#include <iostream>
#include <chrono>
#include <ctime>
#include <stdexcept>
template <typename L, typename R>
inline constexpr L
integer_cast(const R r) {
if (r < 0) {
if (::std::numeric_limits<L>::is_signed) {
if (::std::numeric_limits<L>::min() > static_cast<intmax_t>(r)) {
throw ::std::range_error("Integer conversion undeflow");
}
} else {
throw ::std::range_error("Integer conversion failed. Can't fit negative number to unsigned type");
}
} else {
if (r > ::std::numeric_limits<L>::max()) {
throw ::std::range_error("Integer conversion overflow");
}
}
return static_cast<L>(r);
}
template <typename Container>
static auto
join(const Container& c, const std::string& delimeter = ", ") {
auto it = c.begin();
std::string ret = *it;
it++;
for (; it != c.end(); it++) {
ret += delimeter + *it;
}
return ret;
}
template<typename Clock, typename Duration>
std::ostream&
operator << (std::ostream& os, const std::chrono::time_point<Clock, Duration>& tp) {
const time_t t = Clock::to_time_t(tp);
const auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(tp.time_since_epoch()).count();
struct tm tm = {};
return os << std::put_time(localtime_r(&t, &tm), "%F %T.") <<
std::setfill('0') << std::setw(3) << (ms - t * 1000);
}
template <typename UnsignedInteger, typename Bcd>
Bcd convert_int_to_bcd(const UnsignedInteger from) {
Bcd ret = { };
UnsignedInteger tmp = from;
for (ssize_t j = sizeof(ret.v) - 1; tmp && j >= 0; tmp /= 100, j--) {
ret.v[j] = (uint8_t)((((tmp % 100) / 10) << 4) | (tmp % 10));
}
if (tmp != 0) {
throw ::std::runtime_error("Integer conversion failed it didn't fit into requested BCD type");
}
return ret;
}
template <typename UnsignedInteger, typename Bcd>
UnsignedInteger convert_bcd_to_int(const Bcd from) {
UnsignedInteger ret = 0, power = 1;
for (size_t j = sizeof(from.v)/sizeof(from.v[0]) - 1; j != 0; j--, power *= 100) {
ret += (from.v[j] & 0x0F) * power;
ret += ((from.v[j] & 0xF0) >> 4) * power * 10;
// TODO: Detect overflow
}
return ret;
}
template <typename T>
T* acp(const T& prototype) {
auto ret = reinterpret_cast<T*>(dmapi_malloc(sizeof(T)));
*ret = prototype;
return ret;
}