radio_tool 0.2.1
Loading...
Searching...
No Matches
util.hpp
1
18#pragma once
19
20#include <vector>
21#include <stdint.h>
22#include <iostream>
23#include <sstream>
24#include <chrono>
25#include <algorithm>
26#include <iterator>
27#include <iomanip>
28
29namespace radio_tool
30{
31 constexpr auto kiB = (1UL << 10);
32
33 constexpr auto MiB = (1UL << 20);
34
35 constexpr auto GiB = (1UL << 30);
36
37 constexpr auto TiB = (1ULL << 40);
38
39 constexpr auto PiB = (1ULL << 50);
40
41 constexpr auto EiB = (1ULL << 60);
42
43 static auto PrintHex(std::vector<uint8_t>::const_iterator&& begin, std::vector<uint8_t>::const_iterator&& end) -> void
44 {
45 auto c = 1u;
46
47 constexpr auto asciiZero = 0x30;
48 constexpr auto asciiA = 0x61 - 0x0a;
49
50 constexpr auto wordSize = 4;
51 constexpr auto wordCount = 4;
52
53 char eol_ascii[wordSize * wordCount + 1] = {};
54 char aV, bV;
55 std::stringstream prnt;
56 auto size = std::distance(begin, end);
57 while (begin != end)
58 {
59 auto v = (*begin);
60 auto a = v & 0x0f;
61 auto b = v >> 4;
62 aV = (a <= 9 ? asciiZero : asciiA) + a;
63 bV = (b <= 9 ? asciiZero : asciiA) + b;
64 prnt << bV << aV << " ";
65
66 auto col = c % (wordSize * wordCount);
67 eol_ascii[col] = v >= 32 && v <= 127 ? (char)v : '.';
68 if (col == 0 && c != size)
69 {
70 prnt << " " << eol_ascii << std::endl;
71 }
72 else if (c % wordSize == 0)
73 {
74 prnt << " ";
75 }
76 if (c == size)
77 {
78 if (col > 0)
79 {
80 eol_ascii[col + 1] = 0;
81 }
82 prnt << (col != 0 ? " " : "") << eol_ascii;
83 }
84 c++;
85 std::advance(begin, 1);
86 }
87
88 std::cerr << prnt.str() << std::endl;
89 }
90
91 static constexpr auto _bcd(const uint8_t& c)
92 {
93 return (c & 0x0f) + ((c >> 4) * 10);
94 }
95
96 static constexpr auto _dcb(const uint8_t& c)
97 {
98 return ((int)(c / 10) * 16) + (c % 10);
99 }
100
101 static auto ParseBCDTimestamp(const uint8_t time[7]) -> time_t
102 {
103 std::tm t = {};
104 t.tm_year = ((_bcd(time[0]) * 100) + _bcd(time[1])) - 1900;
105 t.tm_mon = _bcd(time[2]) - 1;
106 t.tm_mday = _bcd(time[3]);
107 t.tm_hour = _bcd(time[4]);
108 t.tm_min = _bcd(time[5]);
109 t.tm_sec = _bcd(time[6]);
110
111 return mktime(&t);
112 }
113
114 static auto MakeBCDTimestamp(const struct std::tm& timeinfo) -> std::vector<uint8_t>
115 {
116 return {
117 static_cast<uint8_t>(_dcb((1900 + timeinfo.tm_year) / 100)),
118 static_cast<uint8_t>(_dcb(timeinfo.tm_year + 1900 - (timeinfo.tm_year + 1900) / 100 * 100)),
119 static_cast<uint8_t>(_dcb(timeinfo.tm_mon + 1)),
120 static_cast<uint8_t>(_dcb(timeinfo.tm_mday)),
121 static_cast<uint8_t>(_dcb(timeinfo.tm_hour)),
122 static_cast<uint8_t>(_dcb(timeinfo.tm_min)),
123 static_cast<uint8_t>(_dcb(timeinfo.tm_sec)),
124 };
125 }
126
127 static inline auto ApplyXOR(std::vector<uint8_t>& data, const uint8_t* xor_key, const uint16_t& key_len, const uint16_t& xor_offset = 0) -> void
128 {
129 for (size_t z = 0; z < data.size(); z++)
130 {
131 data[z] = data[z] ^ xor_key[(xor_offset + z) % key_len];
132 }
133 }
134
135 static inline auto ApplyXOR(std::vector<uint8_t>::iterator&& begin, std::vector<uint8_t>::iterator&& end, const uint8_t* xor_key, const uint16_t& key_len, const uint16_t& xor_offset = 0) -> void
136 {
137 auto z = 0;
138 while (begin != end)
139 {
140 (*begin) = (*begin) ^ xor_key[(xor_offset + z++) % key_len];
141 std::advance(begin, 1);
142 }
143 }
144
145 static auto BSDChecksum(std::vector<uint8_t>::iterator& data, const uint32_t& size) -> uint16_t
146 {
147 int32_t checksum = 0u;
148
149 for (size_t i = 0; i < size; i++)
150 {
151 checksum = (checksum >> 1) + ((checksum & 1) << 15);
152 checksum += *data;
153 checksum &= 0xffff;
154 std::advance(data, 1);
155 }
156 return checksum;
157 }
158
159 static auto Fletcher16(std::vector<uint8_t>::iterator& data, const uint32_t& size) -> uint16_t
160 {
161 constexpr auto block_size = 5802;
162 uint32_t c0 = 0, c1 = 0;
163 uint32_t i;
164 int32_t len = size;
165
166 // Found by solving for c1 overflow:
167 // n > 0 and n * (n+1) / 2 * (2^8-1) < (2^32-1).
168 for (c0 = c1 = 0; len > 0; len -= block_size)
169 {
170 uint32_t blocklen = std::min(block_size, len);
171 for (i = 0; i < blocklen; ++i)
172 {
173 c0 = c0 + (*data);
174 c1 = c1 + c0;
175 std::advance(data, 1);
176 }
177 c0 = c0 % 255;
178 c1 = c1 % 255;
179 }
180 //auto f0 = c0;
181 //c0 = 0xff - ((c0 + c1) % 0xff);
182 //c1 = 0xff - ((f0 + c0) % 0xff);
183 return (c1 << 8 | c0);
184 }
185
186 static auto InternetChecksum(std::vector<uint8_t>::iterator& data, const uint32_t& size) -> uint16_t
187 {
188 int32_t sum = 0,
189 count = size;
190
191 // Main summing loop
192 while (count > 1)
193 {
194 sum = sum + (*data);
195 count = count - 2;
196 std::advance(data, 1);
197 }
198
199 // Add left-over byte, if any
200 if (count > 0)
201 {
202 sum = sum + (*data);
203 }
204
205 // Fold 32-bit sum to 16 bits
206 while (sum >> 16)
207 {
208 sum = (sum & 0xFFFF) + (sum >> 16);
209 }
210
211 return (~sum);
212 }
213
217 static auto CSChecksum(std::vector<uint8_t>::const_iterator&& begin, const std::vector<uint8_t>::const_iterator&& end) -> uint16_t
218 {
219 uint16_t sum = 0;
220
221 while (begin != end)
222 {
223 sum += (*begin);
224 std::advance(begin, 1);
225 }
226
227 auto c0 = (int32_t)(sum / 5) >> 8;
228 auto c1 = (sum / 5) & 0xff;
229 return (c1 << 8 | c0);
230 }
231
232 static auto FormatBytes(const uint64_t& bytes, const uint8_t& precision = 2) -> std::string
233 {
234 std::stringstream ss;
235 ss << std::fixed << std::setprecision(precision);
236 if (bytes >= EiB)
237 {
238 ss << (bytes / (double)EiB) << " EiB";
239 }
240 else if (bytes >= PiB)
241 {
242 ss << (bytes / (double)PiB) << " PiB";
243 }
244 else if (bytes >= TiB)
245 {
246 ss << (bytes / (double)TiB) << " TiB";
247 }
248 else if (bytes >= GiB)
249 {
250 ss << (bytes / (double)GiB) << " GiB";
251 }
252 else if (bytes >= kiB)
253 {
254 ss << (bytes / (double)kiB) << " kiB";
255 }
256 else
257 {
258 ss << bytes << " B";
259 }
260 return ss.str();
261 }
262} // namespace radio_tool