SOMHunter Core
utils.hpp
Go to the documentation of this file.
1 /* This file is part of SOMHunter.
2  *
3  * Copyright (C) 2021 Frantisek Mejzlik <frankmejzlik@protonmail.com>
4  * Mirek Kratochvil <exa.exa@gmail.com>
5  * Patrik Vesely <prtrikvesely@gmail.com>
6  *
7  * SOMHunter is free software: you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License as published by the Free
9  * Software Foundation, either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * SOMHunter is distributed in the hope that it will be useful, but WITHOUT ANY
13  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
15  * details.
16  *
17  * You should have received a copy of the GNU General Public License along with
18  * SOMHunter. If not, see <https://www.gnu.org/licenses/>.
19  */
20 
21 #ifndef UTILS_H_
22 #define UTILS_H_
23 
24 #include <algorithm>
25 #include <charconv>
26 #include <chrono>
27 #include <cmath>
28 #include <filesystem>
29 #include <functional>
30 #include <iomanip>
31 #include <numeric>
32 #include <random>
33 #include <sstream>
34 #include <stdexcept>
35 #include <string>
36 #include <string_view>
37 
38 #include <sha256.h>
39 #include <cereal/archives/binary.hpp>
40 #include <cereal/types/variant.hpp>
41 #include <cereal/types/vector.hpp>
42 
43 #include "common.h"
44 
45 namespace sh {
46 namespace utils {
47 
53 template <typename DataType_>
54 void serialize_to_file(DataType_ data, const std::string filepath) {
55  std::ofstream ofs(filepath, std::ios::out | std::ios::binary);
56  if (!ofs) {
57  SHLOG_E_THROW("Error openning file: " << filepath);
58  }
59 
60  cereal::BinaryOutputArchive out_archive(ofs);
61  out_archive(data);
62 }
63 
69 template <typename DataType_>
70 DataType_ deserialize_from_file(const std::string filepath) {
71  std::ifstream ifs(filepath, std::ios::in | std::ios::binary);
72  if (!ifs) {
73  SHLOG_E_THROW("Error openning file: " << filepath);
74  }
75 
76  cereal::BinaryInputArchive in_archive(ifs);
77 
78  DataType_ data;
79  in_archive(data);
80 
81  return data;
82 }
83 
87 inline int64_t timestamp() {
88  using namespace std::chrono;
89  return duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
90 }
91 
105 inline std::string get_formated_timestamp(const std::string& fmt, UnixTimestamp ts = timestamp()) {
106  auto x = std::chrono::duration<std::size_t, std::milli>(ts);
107  std::chrono::time_point<std::chrono::system_clock> tp{ x };
108  auto tts{ std::chrono::system_clock::to_time_t(tp) };
109 
110  std::stringstream ss;
111  ss << std::put_time(std::localtime(&tts), fmt.data());
112  return ss.str();
113 }
114 
123 inline int str_to_int(const std::string& str) {
124  int result = 0;
125 
126  // Convert and check if successful
127  auto conv_res = std::from_chars(str.data(), str.data() + str.size(), result);
128 
129  if (conv_res.ptr != (str.data() + str.size())) {
130  SHLOG_E_THROW("Incorrect string to covnert: " << str);
131  }
132 
133  return result;
134 }
135 
143 template <typename T_, typename S_>
144 static inline T_ str2(const S_& s) {
145  std::stringstream ss(s);
146  T_ r;
147  ss >> r;
148  return r;
149 }
150 
157 template <typename T_>
158 inline static T_ square(T_ a) {
159  return a * a;
160 }
161 
169 template <typename T_>
170 T_ irand(T_ from, T_ to) {
171  std::random_device rd;
172  std::mt19937 gen(rd());
173  std::uniform_int_distribution<T_> dist(from, to);
174 
175  return dist(gen);
176 }
177 
185 template <typename T_>
186 T_ frand(T_ from, T_ to) {
187  std::random_device rd;
188  std::mt19937 gen(rd());
189  std::uniform_real_distribution<T_> dist(from, to);
190 
191  return dist(gen);
192 }
193 
201 inline std::vector<std::string> split(const std::string& str, char delim) {
202  std::vector<std::string> result;
203  std::stringstream ss(str);
204  std::string item;
205 
206  while (getline(ss, item, delim)) {
207  result.emplace_back(item);
208  }
209 
210  return result;
211 }
212 
220 template <typename T_>
221 bool is_set(T_ mask, size_t i) {
222  return ((mask >> i) & 0x01) == 1;
223 }
224 
231 template <typename Container_>
232 void print_matrix(const Container_& mat) {
233  for (auto&& row : mat) {
234  print_vector(row);
235  }
236 }
237 
244 template <typename Container_>
245 void print_vector(const Container_& row) {
246  for (auto&& v : row) {
247  std::cout << "\t" << std::fixed << std::setprecision(4) << v;
248  }
249  std::cout << std::endl;
250 }
251 
258 inline std::string to_lowercase(const std::string& old) {
259  std::string transformed;
260 
261  std::transform(old.begin(), old.end(), std::back_inserter(transformed), ::tolower);
262 
263  return transformed;
264 }
265 
272 inline std::string sha256_sum(const std::string& filepath) {
273  // \todo test with large files
274  third_party::SHA256 hash;
275 
276  std::ifstream f(filepath, std::ios::binary);
277  if (!f.is_open()) {
278  SHLOG_E_THROW("Unable to open file '" << filepath << "'.");
279  }
280 
281  constexpr const std::size_t buff_size = 4096;
282  std::vector<char> buffer(buff_size);
283 
284  while (f) {
285  f.read(buffer.data(), buff_size);
286  size_t bytes_read = size_t(f.gcount());
287 
288  hash.add(buffer.data(), bytes_read);
289  }
290 
291  return hash.getHash();
292 }
293 
300 inline std::string read_whole_file(const std::string& filepath) {
301  std::ifstream ifs{ filepath };
302  if (!ifs.is_open()) {
303  SHLOG_E_THROW("Error opening file: " << filepath);
304  }
305 
306  // Rad the whole file
307  ifs.seekg(0, std::ios::end);
308  std::streamsize size = ifs.tellg();
309 
310  std::string file_content(size, ' ');
311 
312  ifs.seekg(0);
313  ifs.read(&file_content[0], size);
314 
315  return file_content;
316 }
317 
324 inline std::string trim_left(const std::string& s) {
325  std::string res{ s };
326  res.erase(res.begin(),
327  std::find_if(res.begin(), res.end(), [](unsigned char ch) { return (std::isspace(ch) == 0); }));
328  return res;
329 }
330 
337 inline std::string trim_right(const std::string& s) {
338  std::string res{ s };
339  res.erase(std::find_if(res.rbegin(), res.rend(), [](unsigned char ch) { return (std::isspace(ch) == 0); }).base(),
340  res.end());
341  return res;
342 }
343 
350 inline std::string trim(const std::string& s) { return trim_right(trim_left(s)); }
351 
355 template <typename DType_>
356 void to_file(const std::vector<DType_>& vec, const std::string filepath) {
357  std::ofstream ofs(filepath, std::ios::out | std::ios::binary);
358  if (!ofs) {
359  SHLOG_E_THROW("Error openning file: " << filepath);
360  }
361 
362  for (auto&& d : vec) {
363  const char* p_d{ reinterpret_cast<const char*>(&d) };
364  ofs.write(p_d, sizeof(DType_));
365  }
366 }
367 
371 template <typename DType_>
372 void to_file(const std::vector<std::vector<DType_>>& mat, const std::string filepath) {
373  std::ofstream ofs(filepath, std::ios::out | std::ios::binary);
374  if (!ofs) {
375  SHLOG_E_THROW("Error openning file: " << filepath);
376  }
377 
378  for (auto&& vec : mat) {
379  for (auto&& d : vec) {
380  const char* p_d{ reinterpret_cast<const char*>(&d) };
381  ofs.write(p_d, sizeof(DType_));
382  }
383  }
384 }
385 
389 template <typename T_>
390 T_ ipow(T_ b, std::size_t p) {
391  T_ r = 1;
392  for (std::size_t i = 0; i < p; ++i) {
393  r = r * b;
394  }
395  return r;
396 }
397 
401 template <typename T_>
402 T_ round_decimal(T_ x, std::size_t places) {
403  std::size_t b = ipow(10, places);
404  return static_cast<T_>(std::round(b * x) / b);
405 }
406 
412 template <class T_>
413 constexpr std::string_view type_name() {
414  using namespace std;
415 #ifdef __clang__
416  string_view p = __PRETTY_FUNCTION__;
417  return string_view(p.data() + 34, p.size() - 34 - 1);
418 #elif defined(__GNUC__)
419  string_view p = __PRETTY_FUNCTION__;
420 # if __cplusplus < 201402
421  return string_view(p.data() + 36, p.size() - 36 - 1);
422 # else
423  return string_view(p.data() + 49, p.find(';', 49) - 49);
424 # endif
425 #elif defined(_MSC_VER)
426  string_view p = __FUNCSIG__;
427  return string_view(p.data() + 84, p.size() - 84 - 7);
428 #endif
429 }
430 
431 } // namespace utils
432 } // namespace sh
433 #endif // UTILS_H_
std::vector< std::string > split(const std::string &str, char delim)
Splits the string with the provided character delimiter.
Definition: utils.hpp:201
std::string trim_left(const std::string &s)
Left trim.
Definition: utils.hpp:324
int str_to_int(const std::string &str)
Tries to parse the integer from the string.
Definition: utils.hpp:123
std::string get_formated_timestamp(const std::string &fmt, UnixTimestamp ts=timestamp())
Returns string representing current time and date in formated string based on provided format.
Definition: utils.hpp:105
std::string trim(const std::string &s)
Trim.
Definition: utils.hpp:350
std::string to_lowercase(const std::string &old)
Returns a copy of old string but all lowercase.
Definition: utils.hpp:258
std::string read_whole_file(const std::string &filepath)
Reads the whole file into string that it will return.
Definition: utils.hpp:300
constexpr std::string_view type_name()
Returns a string view describing the type T_.
Definition: utils.hpp:413
std::string trim_right(const std::string &s)
Right trim.
Definition: utils.hpp:337
void print_matrix(const Container_ &mat)
Prints out any two-dimensional iterable container.
Definition: utils.hpp:232
void print_vector(const Container_ &row)
Prints out any one-dimensional iterable container.
Definition: utils.hpp:245
void to_file(const std::vector< DType_ > &vec, const std::string filepath)
Writes the given vector into the given file.
Definition: utils.hpp:356
void serialize_to_file(DataType_ data, const std::string filepath)
Serializes the given data into the file using cereal lib.
Definition: utils.hpp:54
DataType_ deserialize_from_file(const std::string filepath)
Deserializes the data from the provided file using cereal lib.
Definition: utils.hpp:70
T_ irand(T_ from, T_ to)
Returns a pseudorandom integral number sampled from the uniform distribution [from,...
Definition: utils.hpp:170
T_ round_decimal(T_ x, std::size_t places)
Rounds the number to the specified number of decimal places.
Definition: utils.hpp:402
T_ frand(T_ from, T_ to)
Returns a pseudorandom floating point number sampled from the uniform distribution [from,...
Definition: utils.hpp:186
std::string sha256_sum(const std::string &filepath)
Computes the SHA256 hash for the given file and returns it.
Definition: utils.hpp:272
int64_t timestamp()
Returns the actual UNIX timestamp (ms).
Definition: utils.hpp:87
T_ ipow(T_ b, std::size_t p)
Unsigned integer power function.
Definition: utils.hpp:390
bool is_set(T_ mask, size_t i)
Tests whether the i-th lowest significant bit is set.
Definition: utils.hpp:221
Definition: common-types.h:33
std::int64_t UnixTimestamp
Definition: common-types.h:54
#define SHLOG_E_THROW(x)
Definition: static-logger.hpp:158