C++ Distributed Hash Table
utils.h
1 /*
2  * Copyright (C) 2014-2022 Savoir-faire Linux Inc.
3  * Author : Adrien BĂ©raud <adrien.beraud@savoirfairelinux.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <https://www.gnu.org/licenses/>.
17  */
18 
19 #pragma once
20 
21 #include "def.h"
22 
23 #include <msgpack.hpp>
24 
25 #include <chrono>
26 #include <random>
27 #include <functional>
28 #include <map>
29 
30 #include <cstdarg>
31 
32 #define WANT4 1
33 #define WANT6 2
34 
38 namespace dht {
39 
40 using NetId = uint32_t;
41 using want_t = int_fast8_t;
42 
43 OPENDHT_PUBLIC const char* version();
44 
45 // shortcut for std::shared_ptr
46 template<class T>
47 using Sp = std::shared_ptr<T>;
48 
49 template <typename Key, typename Item, typename Condition>
50 void erase_if(std::map<Key, Item>& map, const Condition& condition)
51 {
52  for (auto it = map.begin(); it != map.end(); ) {
53  if (condition(*it)) {
54  it = map.erase(it);
55  } else { ++it; }
56  }
57 }
58 
62 OPENDHT_PUBLIC std::pair<std::string, std::string>
63 splitPort(const std::string& s);
64 
65 class OPENDHT_PUBLIC DhtException : public std::runtime_error {
66 public:
67  DhtException(const std::string &str = "") :
68  std::runtime_error("DhtException occurred: " + str) {}
69 };
70 
71 class OPENDHT_PUBLIC SocketException : public DhtException {
72 public:
73  SocketException(int err) :
74  DhtException(strerror(err)) {}
75 };
76 
77 // Time related definitions and utility functions
78 
79 using clock = std::chrono::steady_clock;
80 using system_clock = std::chrono::system_clock;
81 using time_point = clock::time_point;
82 using duration = clock::duration;
83 
84 time_point from_time_t(std::time_t t);
85 std::time_t to_time_t(time_point t);
86 
87 inline std::string
88 to_str(double d) {
89  char buf[16];
90  auto ret = snprintf(buf, sizeof(buf), "%.3g", d);
91  return (ret < 0) ? std::to_string(d) : std::string(buf, ret);
92 }
93 
97 template <class DT>
98 static double
99 print_dt(DT d) {
100  return std::chrono::duration_cast<std::chrono::duration<double>>(d).count();
101 }
102 
103 template <class DT>
104 static std::string
105 print_duration(DT d) {
106  if (d < std::chrono::seconds(0)) {
107  return "-" + print_duration(-d);
108  } else if (d < std::chrono::milliseconds(1)) {
109  return to_str(std::chrono::duration_cast<std::chrono::duration<double, std::micro>>(d).count()) + " us";
110  } else if (d < std::chrono::seconds(1)) {
111  return to_str(std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(d).count()) + " ms";
112  } else if (d < std::chrono::minutes(1)) {
113  return to_str(std::chrono::duration_cast<std::chrono::duration<double>>(d).count()) + " s";
114  } else if (d < std::chrono::hours(1)) {
115  return to_str(std::chrono::duration_cast<std::chrono::duration<double, std::ratio<60>>>(d).count()) + " min";
116  } else {
117  return to_str(std::chrono::duration_cast<std::chrono::duration<double, std::ratio<3600>>>(d).count()) + " h";
118  }
119 }
120 
121 template <class TimePoint>
122 static std::string
123 print_time_relative(TimePoint now, TimePoint d) {
124  if (d == TimePoint::min()) return "never";
125  if (d == now) return "now";
126  return (d > now) ? std::string("in ") + print_duration(d - now)
127  : print_duration(now - d) + std::string(" ago");
128 }
129 
130 template <typename Duration = duration>
131 class uniform_duration_distribution : public std::uniform_int_distribution<typename Duration::rep> {
132  using Base = std::uniform_int_distribution<typename Duration::rep>;
133  using param_type = typename Base::param_type;
134 public:
135  uniform_duration_distribution(Duration min, Duration max) : Base(min.count(), max.count()) {}
136  template <class Generator>
137  Duration operator()(Generator && g) {
138  return Duration(Base::operator()(g));
139  }
140  template< class Generator >
141  Duration operator()( Generator && g, const param_type& params ) {
142  return Duration(Base::operator()(g, params));
143  }
144 };
145 
146 // Serialization related definitions and utility functions
147 
151 using Blob = std::vector<uint8_t>;
152 
156 OPENDHT_PUBLIC Blob unpackBlob(const msgpack::object& o);
157 
158 template <typename Type>
159 Blob
160 packMsg(const Type& t) {
161  msgpack::sbuffer buffer;
162  msgpack::packer<msgpack::sbuffer> pk(&buffer);
163  pk.pack(t);
164  return {buffer.data(), buffer.data()+buffer.size()};
165 }
166 
167 template <typename Type>
168 Type
169 unpackMsg(Blob b) {
170  msgpack::unpacked msg_res = msgpack::unpack((const char*)b.data(), b.size());
171  return msg_res.get().as<Type>();
172 }
173 
174 msgpack::unpacked unpackMsg(Blob b);
175 
176 msgpack::object* findMapValue(const msgpack::object& map, const char* key, size_t length);
177 
178 inline msgpack::object* findMapValue(const msgpack::object& map, const char* key) {
179  return findMapValue(map, key, strlen(key));
180 }
181 inline msgpack::object* findMapValue(const msgpack::object& map, std::string_view key) {
182  return findMapValue(map, key.data(), key.size());
183 }
184 
185 } // namespace dht
STL namespace.
OPENDHT_PUBLIC Blob unpackBlob(const msgpack::object &o)
static double print_dt(DT d)
Definition: utils.h:99
std::vector< uint8_t > Blob
Definition: utils.h:151
OPENDHT_PUBLIC std::pair< std::string, std::string > splitPort(const std::string &s)
Definition: callbacks.h:35