libvata2  [unstable] git snapshot
util.hh
Go to the documentation of this file.
1 /* util.hh -- various utilities
2  *
3  * Copyright (c) 2018 Ondrej Lengal <ondra.lengal@gmail.com>
4  *
5  * This file is a part of libvata2.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  */
17 
18 
19 #ifndef _VATA2_UTIL_HH_
20 #define _VATA2_UTIL_HH_
21 
22 #include <algorithm>
23 #include <functional>
24 #include <iostream>
25 #include <list>
26 #include <map>
27 #include <set>
28 #include <sstream>
29 #include <stack>
30 #include <unordered_map>
31 #include <vector>
32 
33 #define DEBUG_PRINT(x) { std::cerr << "debug: " << x << "\n"; }
34 #define DEBUG_PRINT_LN(x) { DEBUG_PRINT(__func__ << ":" << __LINE__ << ": " << x) }
35 #define WARN_PRINT(x) { std::cerr << "warning: " << x << "\n"; }
36 
37 namespace Vata2
38 {
39 namespace util
40 {
41 
42 /** Are two sets disjoint? */
43 template <class T>
44 bool are_disjoint(const std::set<T>& lhs, const std::set<T>& rhs)
45 { // {{{
46  auto itLhs = lhs.begin();
47  auto itRhs = rhs.begin();
48  while (itLhs != lhs.end() && itRhs != rhs.end())
49  {
50  if (*itLhs == *itRhs) { return false; }
51  else if (*itLhs < *itRhs) { ++itLhs; }
52  else {++itRhs; }
53  }
54 
55  return true;
56 } // }}}
57 
58 /**
59  * @brief Combine two hash values
60  *
61  * Values taken from
62  * http://www.boost.org/doc/libs/1_64_0/boost/functional/hash/hash.hpp
63  *
64  * TODO: fix to be more suitable for 64b
65  */
66 template <class T>
67 inline size_t hash_combine(size_t lhs, const T& rhs)
68 { // {{{
69  size_t rhs_hash = std::hash<T>{}(rhs);
70  lhs ^= rhs_hash + 0x9e3779b9 + (lhs<<6) + (lhs>>2);
71  return lhs;
72 } // hash_combine }}}
73 
74 
75 /**
76  * @brief Hashes a range
77  *
78  * Inspired by
79  * http://www.boost.org/doc/libs/1_64_0/boost/functional/hash/hash.hpp
80  */
81 template <typename It>
82 size_t hash_range(It first, It last)
83 { // {{{
84  size_t accum = 0;
85 
86  for (; first != last; ++first)
87  {
88  accum = hash_combine(accum, *first);
89  }
90 
91  return accum;
92 } // hash_range(It, It) }}}
93 
94 /// checks whether a container with @p find contains a key
95 template <class T, class K>
96 inline bool haskey(const T& cont, const K& key)
97 {
98  return cont.find(key) != cont.cend();
99 }
100 
101 /// inverts a map (should work for std::map and std::unordered_map)
102 template <template <class, class, class...> class Map, class T1, class T2, class... Args>
103 Map<T2, T1> invert_map(const Map<T1, T2>& mp)
104 { // {{{
105  Map<T2, T1> result;
106 
107  for (const auto& key_val_pair : mp)
108  {
109  auto it_ins_pair = result.insert({key_val_pair.second, key_val_pair.first});
110  if (!it_ins_pair.second)
111  {
112  throw std::runtime_error("duplicate key when inverting a map");
113  }
114  }
115 
116  return result;
117 } // invert_map }}}
118 
119 
120 template<class Tuple, std::size_t N>
122 
123 // CLOSING NAMESPACES AND GUARDS
124 } /* util */
125 } /* Vata2 */
126 
127 
128 // Some things that need to go to std
129 namespace std
130 { // {{{
131 
132 /**
133  * @brief A hasher for pairs
134  */
135 template <class A, class B>
136 struct hash<std::pair<A,B>>
137 {
138  inline size_t operator()(const std::pair<A,B>& k) const
139  { // {{{
140  size_t accum = std::hash<A>{}(k.first);
141  return Vata2::util::hash_combine(accum, k.second);
142  } // operator() }}}
143 };
144 
145 /**
146  * @brief A hasher for sets
147  */
148 template <class A>
149 struct hash<std::set<A>>
150 {
151  inline size_t operator()(const std::set<A>& cont) const
152  { // {{{
153  return Vata2::util::hash_range(cont.begin(), cont.end());
154  } // operator() }}}
155 };
156 
157 /**
158  * @brief A hasher for vectors
159  */
160 template <class A>
161 struct hash<std::vector<A>>
162 {
163  inline size_t operator()(const std::vector<A>& cont) const
164  { // {{{
165  return Vata2::util::hash_range(cont.begin(), cont.end());
166  } // operator() }}}
167 };
168 
169 /*#######################################################
170  # std::to_string(TYPE)
171  #######################################################*/
172 
173 /*======================================================
174  * DECLARATIONS
175  *========================================{{{*/
176 
177 template <class A> std::string to_string(const A& value);
178 template <class A> std::string to_string(const std::set<A>& st);
179 template <class A> std::string to_string(const std::vector<A>& vec);
180 template <class A> std::string to_string(const std::list<A>& vec);
181 template <class A> std::string to_string(const std::stack<A>& stck);
182 template <class A> std::string to_string(const std::function<A>& func);
183 template <class A, class B> std::string to_string(const std::pair<A, B>& p);
184 template <class A, class B> std::string to_string(const std::unordered_map<A, B>& unmap);
185 template <class A, class B> std::string to_string(const std::map<A, B>& mp);
186 
187 // }}}
188 
189 /*======================================================
190  * DEFINITIONS
191  *========================================{{{*/
192 
193 /** Character to string */
194 inline std::string to_string(char ch)
195 { // {{{
196  std::string str;
197  str += ch;
198  return str;
199 } // to_string(char) }}}
200 
201 /** String to string */
202 inline std::string to_string(const std::string& str) { return str; }
203 
204 /** Vector to string */
205 template <class A>
206 std::string to_string(const std::vector<A>& vec)
207 { // {{{
208  std::string result = "[";
209  bool first = true;
210  for (auto elem : vec)
211  {
212  if (!first) { result += ", "; }
213  first = false;
214  result += std::to_string(elem);
215  }
216  result += "]";
217 
218  return result;
219 } // to_string(std::vector) }}}
220 
221 /** List to string */
222 template <class A>
223 std::string to_string(const std::list<A>& vec)
224 { // {{{
225  std::string result = "[";
226  bool first = true;
227  for (auto elem : vec)
228  {
229  if (!first) { result += ", "; }
230  first = false;
231  result += std::to_string(elem);
232  }
233  result += "]";
234 
235  return result;
236 } // to_string(std::list) }}}
237 
238 /** unordered_map to string */
239 template <class A, class B>
240 std::string to_string(const std::unordered_map<A, B>& unmap)
241 { // {{{
242  std::string result = "{";
243  bool first = true;
244  for (auto key_val_pair : unmap)
245  {
246  if (!first) { result += ", "; }
247  first = false;
248  result +=
249  std::to_string(key_val_pair.first) +
250  " -> " +
251  std::to_string(key_val_pair.second);
252  }
253  result += "}";
254 
255  return result;
256 } // to_string(std::unordered_map) }}}
257 
258 /** map to string */
259 template <class A, class B>
260 std::string to_string(const std::map<A, B>& mp)
261 { // {{{
262  std::string result = "{";
263  bool first = true;
264  for (auto key_val_pair : mp)
265  {
266  if (!first) { result += ", "; }
267  first = false;
268  result +=
269  std::to_string(key_val_pair.first) +
270  " -> " +
271  std::to_string(key_val_pair.second);
272  }
273  result += "}";
274 
275  return result;
276 } // to_string(std::map) }}}
277 
278 /** set to string */
279 template <class A>
280 std::string to_string(const std::set<A>& st)
281 { // {{{
282  std::string result = "{";
283  bool first = true;
284  for (auto elem : st)
285  {
286  if (!first) { result += ", "; }
287  first = false;
288  result += std::to_string(elem);
289  }
290  result += "}";
291 
292  return result;
293 } // to_string(std::set) }}}
294 
295 /** stack to string */
296 template <class A>
297 std::string to_string(const std::stack<A>& stck)
298 { // {{{
299  std::stack<A> copy = stck;
300  std::vector<A> vec;
301  while (!copy.empty()) {
302  vec.push_back(copy.top());
303  copy.pop();
304  }
305  std::reverse(vec.begin(), vec.end());
306  return std::to_string(vec);
307 } // to_string(std::stack) }}}
308 
309 /** function to string */
310 template <class A>
311 std::string to_string(const std::function<A>& fun)
312 { // {{{
313  return std::to_string(static_cast<const void*>(&fun));
314 } // to_string(std::function) }}}
315 
316 /** tuple to string */
317 template <class... Ts>
318 std::string to_string(const std::tuple<Ts...>& tup)
319 { // {{{
320  std::string str = "<";
321  str += Vata2::util::TuplePrinter<decltype(tup), sizeof...(Ts)>::print(tup);
322  str += ">";
323 
324  return str;
325 } // to_string(std::tuple) }}}
326 
327 template <class A, class B>
328 std::string to_string(const std::pair<A, B>& p)
329 { // {{{
330  return std::to_string(std::tuple<A, B>(p.first, p.second));
331 } // to_string(std::pair) }}}
332 
333 /** arbitrary type with the << operator */
334 template <class A>
335 std::string to_string(const A& value)
336 { // {{{
337  std::ostringstream os;
338  os << value;
339  return os.str();
340 } // to_string(T) }}}
341 
342 // }}}
343 
344 } // namespace std }}}
345 
346 namespace Vata2
347 {
348 namespace util
349 {
350 
351 // Taken from
352 // http://en.cppreference.com/w/cpp/utility/tuple/tuple_cat
353 template<class Tuple, size_t N>
354 struct TuplePrinter
355 {
356  static std::string print(const Tuple& t)
357  {
358  std::string res = TuplePrinter<Tuple, N-1>::print(t);
359  return res + ", " + std::to_string(std::get<N-1>(t));
360  }
361 };
362 
363 template<class Tuple>
364 struct TuplePrinter<Tuple, 1> {
365  static std::string print(const Tuple& t)
366  {
367  return std::to_string(std::get<0>(t));
368  }
369 };
370 
371 }
372 }
373 #endif /* _VATA2_UTIL_HH_ */
bool haskey(const T &cont, const K &key)
checks whether a container with find contains a key
Definition: util.hh:96
bool are_disjoint(const std::set< T > &lhs, const std::set< T > &rhs)
Are two sets disjoint?
Definition: util.hh:44
size_t hash_combine(size_t lhs, const T &rhs)
Combine two hash values.
Definition: util.hh:67
Map< T2, T1 > invert_map(const Map< T1, T2 > &mp)
inverts a map (should work for std::map and std::unordered_map)
Definition: util.hh:103
static std::string print(const Tuple &t)
Definition: util.hh:356
size_t operator()(const std::pair< A, B > &k) const
Definition: util.hh:138
size_t hash_range(It first, It last)
Hashes a range.
Definition: util.hh:82
size_t operator()(const std::set< A > &cont) const
Definition: util.hh:151
size_t operator()(const std::vector< A > &cont) const
Definition: util.hh:163
static std::string print(const Tuple &t)
Definition: util.hh:365