MarlinMT  0.1.0
Utils.h
Go to the documentation of this file.
1 #ifndef MARLINMT_UTILS_h
2 #define MARLINMT_UTILS_h 1
3 
4 // -- std headers
5 #include <map>
6 #include <cmath>
7 #include <string>
8 #include <sstream>
9 #include <typeinfo>
10 #include <chrono>
11 #include <vector>
12 #include <algorithm>
13 #include <unordered_map>
14 #include <thread>
15 
16 // -- marlinmt headers
17 #include <marlinmt/Exceptions.h>
19 
20 namespace marlinmt {
21 
28  class clock {
29  public:
30  using clock_type = std::chrono::steady_clock ;
31  using time_point = clock_type::time_point ;
32  using duration_rep = float ;
33  using pair = std::pair<duration_rep, duration_rep> ;
34  // helper definitions
35  using nanoseconds = std::chrono::duration<duration_rep, std::nano> ;
36  using microseconds = std::chrono::duration<duration_rep, std::micro> ;
37  using milliseconds = std::chrono::duration<duration_rep, std::milli> ;
38  using seconds = std::chrono::duration<duration_rep> ;
39  using minutes = std::chrono::duration<duration_rep, std::ratio<60>> ;
40 
41  public:
42  // static API only
43  clock() = delete ;
44  ~clock() = delete ;
45 
46  public:
50  static time_point now() {
51  return clock_type::now() ;
52  }
53 
63  template <class unit = seconds>
64  static duration_rep elapsed_since( const time_point &since ) {
65  auto current = now() ;
66  return std::chrono::duration_cast<unit>( current - since ).count() ;
67  }
68 
87  template <class unit = seconds>
88  static duration_rep time_difference( const time_point &older, const time_point &ealier ) {
89  return std::chrono::duration_cast<unit>( ealier - older ).count() ;
90  }
91 
98  template <class unit = seconds>
99  static void crunchFor( duration_rep crunchTime ) {
100  auto start = clock::now() ;
101  auto now = start ;
102  clock::duration_rep timediff = 0 ;
103  while ( timediff < crunchTime ) {
104  (void)std::sqrt(2) ;
105  now = clock::now() ;
106  timediff = clock::time_difference<unit>(start, now) ;
107  }
108  }
109  };
110 
111  //--------------------------------------------------------------------------
112  //--------------------------------------------------------------------------
113 
118  class HashHelper {
119  private:
121  static const unsigned long long int hashinit = 14695981039346656037ull ;
122 
123  public:
124  static constexpr unsigned long long int doByte(unsigned long long int hash, unsigned char val) {
125  return (hash ^ val) * 1099511628211ull ;
126  }
127 
133  static unsigned long long int hash64( const char *key ) {
134  unsigned char* str = (unsigned char*)key ;
135  unsigned long long int hash = hashinit ;
136  for ( ; *str; ++str) hash = doByte(hash, *str) ;
137  return hash ;
138  }
139 
143  template <typename T>
144  static unsigned long long int typeHash64() {
145  static unsigned long long int code = hash64(typeid(T).name()) ;
146  return code ;
147  }
148  };
149 
150  //--------------------------------------------------------------------------
151  //--------------------------------------------------------------------------
152 
157  class StringUtil {
158  public:
164  template <typename T>
165  static std::string typeToString( const T &var ) ;
166 
172  template <typename T>
173  static std::vector<std::string> typeToString( const std::vector<T> &vars ) ;
174 
180  template <typename T>
181  static T stringToType( const std::string &str ) ;
182 
188  template <typename T>
189  static std::vector<T> stringToType( const std::vector<std::string> &strs ) ;
190 
197  template <typename T>
198  static std::vector<T> split( const std::string &inputString, const std::string &delimiter = " " ) ;
199 
208  template <typename T>
209  static std::string join( const T &input, const std::string &delimiter = " " ) ;
210 
218  template <typename T>
219  static std::string join( const std::vector<T> &input, const std::string &delimiter = " " ) ;
220  };
221 
222  //--------------------------------------------------------------------------
223  //--------------------------------------------------------------------------
224 
225  template <typename T>
226  inline std::string StringUtil::typeToString( const T &var ) {
227  std::ostringstream oss ;
228  if ((oss << var).fail()) {
229  throw Exception( "Couldn't convert value to string" ) ;
230  }
231  return oss.str() ;
232  }
233 
234  //--------------------------------------------------------------------------
235 
236  template <>
237  inline std::string StringUtil::typeToString( const std::string &var ) {
238  return var ;
239  }
240 
241  //--------------------------------------------------------------------------
242 
243  template <>
244  inline std::string StringUtil::typeToString( const bool &var ) {
245  return (var ? "true" : "false") ;
246  }
247 
248  //--------------------------------------------------------------------------
249 
250  template <typename T>
251  inline std::vector<std::string> StringUtil::typeToString( const std::vector<T> &vars ) {
252  std::vector<std::string> result ;
253  result.reserve( vars.size() ) ;
254  for( auto var : vars ) {
255  result.push_back( typeToString<T>( var ) ) ;
256  }
257  return result ;
258  }
259 
260  //--------------------------------------------------------------------------
261 
262  template <typename T>
263  inline T StringUtil::stringToType( const std::string &str ) {
264  T t ;
265  std::istringstream iss(str) ;
266  if ((iss >> t).fail()) {
267  throw Exception( "Couldn't convert string to value" ) ;
268  }
269  return t ;
270  }
271 
272  //--------------------------------------------------------------------------
273 
274  template <>
275  inline std::string StringUtil::stringToType( const std::string &str ) {
276  return str;
277  }
278 
279  //--------------------------------------------------------------------------
280 
281  template <>
282  inline bool StringUtil::stringToType( const std::string &str ) {
283  if ( str == "true" || str == "1" || str == "on" ) return true ;
284  if ( str == "false" || str == "0" || str == "off" ) return false ;
285  throw Exception( "Couldn't convert value to string" ) ;
286  }
287 
288  //--------------------------------------------------------------------------
289 
290  template <typename T>
291  inline std::vector<T> StringUtil::stringToType( const std::vector<std::string> &strs ) {
292  std::vector<T> result ;
293  result.reserve( strs.size() ) ;
294  for( auto str : strs ) {
295  result.push_back( stringToType<T>( str ) ) ;
296  }
297  return result ;
298  }
299 
300  //--------------------------------------------------------------------------
301 
302  template <typename T>
303  inline std::vector<T> StringUtil::split(const std::string &inputString, const std::string &delimiter) {
304  std::string::size_type lastPos = inputString.find_first_not_of(delimiter, 0);
305  std::string::size_type pos = inputString.find_first_of(delimiter, lastPos);
306  typename std::vector<T> tokens ;
307  while ((std::string::npos != pos) || (std::string::npos != lastPos)) {
308  T value = stringToType<T>(inputString.substr(lastPos, pos - lastPos)) ;
309  tokens.push_back(value) ;
310  lastPos = inputString.find_first_not_of(delimiter, pos) ;
311  pos = inputString.find_first_of(delimiter, lastPos) ;
312  }
313  return tokens ;
314  }
315 
316  //--------------------------------------------------------------------------
317 
318  // weird overloading function that just converts the value to string ...
319  template <typename T>
320  inline std::string StringUtil::join( const T &input, const std::string &/*delimiter*/ ) {
321  return typeToString( input ) ;
322  }
323 
324  //--------------------------------------------------------------------------
325 
326  template <typename T>
327  inline std::string StringUtil::join( const std::vector<T> &input, const std::string &delimiter ) {
328  std::stringstream ss ;
329  for( auto iter = input.begin() ; iter != input.end() ; ++iter ) {
330  ss << typeToString( *iter ) ;
331  if( std::next(iter) != input.end() ) {
332  ss << delimiter ;
333  }
334  }
335  return ss.str() ;
336  }
337 
338  namespace details {
339 
340  template <typename T>
341  struct type_info {
342  static const char* type ;
343  };
344 
345  template <typename T> const char* type_info<T>::type = typeid(T).name();
346 
347  // dirty C++ specializations ... See Utils.cc file
348  template <> struct type_info<std::nullptr_t> { static const char* type ; };
349  template <> struct type_info<bool> { static const char* type ; };
350  template <> struct type_info<short> { static const char* type ; };
351  template <> struct type_info<int> { static const char* type ; };
352  template <> struct type_info<unsigned int> { static const char* type ; };
353  template <> struct type_info<float> { static const char* type ; };
354  template <> struct type_info<double> { static const char* type ; };
355  template <> struct type_info<char> { static const char* type ; };
356  template <> struct type_info<std::string> { static const char* type ; };
357  template <> struct type_info<std::vector<short>> { static const char* type ; };
358  template <> struct type_info<std::vector<int>> { static const char* type ; };
359  template <> struct type_info<std::vector<unsigned int>> { static const char* type ; };
360  template <> struct type_info<std::vector<float>> { static const char* type ; };
361  template <> struct type_info<std::vector<double>> { static const char* type ; };
362  template <> struct type_info<std::vector<char>> { static const char* type ; };
363  template <> struct type_info<std::vector<std::string>> { static const char* type ; };
364  template <> struct type_info<std::vector<bool>> { static const char* type ; };
365 
366  //--------------------------------------------------------------------------
367 
368  template <typename T>
369  struct convert {
370  static inline std::string to_string( const T &value ) {
371  std::ostringstream oss ;
372  if ((oss << value).fail()) {
373  MARLINMT_THROW( "to_string failure: " + std::string(details::type_info<T>::type) ) ;
374  }
375  return oss.str() ;
376  }
377 
378  static inline T from_string( const std::string &str ) {
379  T t ;
380  std::istringstream iss(str) ;
381  if ((iss >> t).fail()) {
382  MARLINMT_THROW( "from_string failure: " + std::string(details::type_info<T>::type) ) ;
383  }
384  return t ;
385  }
386  };
387 
388  //--------------------------------------------------------------------------
389 
390  template <>
391  struct convert<std::string> {
392  static inline std::string to_string( const std::string &value ) {
393  return value ;
394  }
395 
396  static inline std::string from_string( const std::string &str ) {
397  return str ;
398  }
399  };
400 
401  //--------------------------------------------------------------------------
402 
403 
404  template <>
405  struct convert<bool> {
406  static inline std::string to_string( const bool &value ) {
407  return value ? "true" : "false" ;
408  }
409 
410  static inline bool from_string( const std::string &str ) {
411  static const auto true_list = { "true", "1", "on" } ;
412  static const auto false_list = { "false", "0", "off" } ;
413  auto strcp = str ;
414  std::transform(str.begin(), str.end(), strcp.begin(),
415  [](unsigned char c){ return std::tolower(c); } ) ;
416  if( std::find( std::begin(true_list), std::end(true_list), strcp ) != std::end(true_list) ) {
417  return true ;
418  }
419  if( std::find( std::begin(false_list), std::end(false_list), strcp ) != std::end(false_list) ) {
420  return false ;
421  }
422  MARLINMT_THROW( "from_string failure: bool" ) ;
423  }
424  };
425 
426  //--------------------------------------------------------------------------
427 
428  template <typename T>
429  struct convert<std::vector<T>> {
430  static inline std::string to_string( const std::vector<T> &value ) {
431  std::stringstream ss ;
432  for( auto iter = value.begin() ; iter != value.end() ; ++iter ) {
433  ss << details::convert<T>::to_string( *iter ) ;
434  if( std::next(iter) != value.end() ) {
435  ss << " " ;
436  }
437  }
438  return ss.str() ;
439  }
440 
441  static inline std::vector<T> from_string( const std::string &str ) {
442  std::string::size_type lastPos = str.find_first_not_of(" ", 0);
443  std::string::size_type pos = str.find_first_of(" ", lastPos);
444  typename std::vector<T> tokens ;
445  while ((std::string::npos != pos) || (std::string::npos != lastPos)) {
446  tokens.emplace_back(
447  details::convert<T>::from_string(str.substr(lastPos, pos - lastPos))
448  );
449  lastPos = str.find_first_not_of(" ", pos) ;
450  pos = str.find_first_of(" ", lastPos) ;
451  }
452  return tokens ;
453  }
454  };
455 
456  //--------------------------------------------------------------------------
457 
458  template <>
459  struct convert<std::vector<std::string>> {
460  static inline std::string to_string( const std::vector<std::string> &value ) {
461  std::stringstream ss ;
462  for( auto iter = value.begin() ; iter != value.end() ; ++iter ) {
463  ss << *iter ;
464  if( std::next(iter) != value.end() ) {
465  ss << " " ;
466  }
467  }
468  return ss.str() ;
469  }
470 
471  static inline std::vector<std::string> from_string( const std::string &str ) {
472  std::string::size_type lastPos = str.find_first_not_of(" ", 0);
473  std::string::size_type pos = str.find_first_of(" ", lastPos);
474  std::vector<std::string> tokens ;
475  while ((std::string::npos != pos) || (std::string::npos != lastPos)) {
476  tokens.emplace_back( str.substr(lastPos, pos - lastPos) ) ;
477  lastPos = str.find_first_not_of(" ", pos) ;
478  pos = str.find_first_of(" ", lastPos) ;
479  }
480  return tokens ;
481  }
482  };
483 
484  //--------------------------------------------------------------------------
485 
486  template <typename T>
487  inline std::vector<T> split_string(const std::string &str, const std::string &delimiter, size_t maxTokens = std::numeric_limits<std::size_t>::max()) {
488  if( 0 == maxTokens ) {
489  MARLINMT_THROW( "maxTokens can't be 0" ) ;
490  }
491  std::string::size_type lastPos = str.find_first_not_of(delimiter, 0) ;
492  std::string::size_type pos = str.find_first_of(delimiter, lastPos) ;
493  typename std::vector<T> tokens ;
494  while ((std::string::npos != pos) || (std::string::npos != lastPos)) {
495  if( tokens.size()+1 >= maxTokens ) {
496  tokens.emplace_back(
497  details::convert<T>::from_string(str.substr(lastPos))
498  );
499  break ;
500  }
501  tokens.emplace_back(
502  details::convert<T>::from_string(str.substr(lastPos, pos - lastPos))
503  );
504  lastPos = str.find_first_not_of(delimiter, pos) ;
505  pos = str.find_first_of(delimiter, lastPos) ;
506  }
507  return tokens ;
508  }
509 
510  //--------------------------------------------------------------------------
511 
512  template <>
513  inline std::vector<std::string> split_string(const std::string &str, const std::string &delimiter, size_t maxTokens) {
514  if( 0 == maxTokens ) {
515  MARLINMT_THROW( "maxTokens can't be 0" ) ;
516  }
517  std::string::size_type lastPos = str.find_first_not_of(delimiter, 0) ;
518  std::string::size_type pos = str.find_first_of(delimiter, lastPos) ;
519  std::vector<std::string> tokens ;
520  while ((std::string::npos != pos) || (std::string::npos != lastPos)) {
521  if( tokens.size()+1 >= maxTokens ) {
522  tokens.emplace_back(
523  str.substr(lastPos)
524  );
525  break ;
526  }
527  tokens.emplace_back(
528  str.substr(lastPos, pos - lastPos)
529  );
530  lastPos = str.find_first_not_of(delimiter, pos) ;
531  pos = str.find_first_of(delimiter, lastPos) ;
532  }
533  return tokens ;
534  }
535 
536  //--------------------------------------------------------------------------
537 
538  template <typename K, typename V>
539  inline std::vector<K> keys( const std::map<K,V> &m ) {
540  typename std::vector<K> keyRet {} ;
541  keyRet.reserve( m.size() ) ;
542  for( auto &kv : m ) {
543  keyRet.push_back( kv.first ) ;
544  }
545  return keyRet ;
546  }
547 
548  //--------------------------------------------------------------------------
549 
550  template <typename K, typename V>
551  inline std::vector<K> keys( const std::unordered_map<K,V> &m ) {
552  typename std::vector<K> keyRet {} ;
553  keyRet.reserve( m.size() ) ;
554  for( auto &kv : m ) {
555  keyRet.push_back( kv.first ) ;
556  }
557  return keyRet ;
558  }
559 
560  //--------------------------------------------------------------------------
561 
562  template <typename K, typename V>
563  inline std::vector<K> keys( const std::vector<std::pair<K,V>> &m ) {
564  typename std::vector<K> keyRet {} ;
565  keyRet.reserve( m.size() ) ;
566  for( auto &kv : m ) {
567  keyRet.push_back( kv.first ) ;
568  }
569  return keyRet ;
570  }
571 
572  //--------------------------------------------------------------------------
573 
574  inline bool is_number( const std::string &str ) {
575  return !str.empty() && std::find_if(str.begin(), str.end(), [](unsigned char c) { return !std::isdigit(c); }) == str.end() ;
576  }
577 
578  //--------------------------------------------------------------------------
579 
580  inline unsigned int nthreads( const std::string &str ) {
581  if( details::is_number(str) ) {
583  }
584  if( str == "auto" ) {
585  return std::thread::hardware_concurrency() ;
586  }
587  MARLINMT_THROW( "Invalid conversion to n threads" ) ;
588  }
589 
590  //--------------------------------------------------------------------------
591 
592  inline void to_lower( std::string &str ) {
593  std::transform( str.begin(), str.end(), str.begin(), [](unsigned char c) { return std::tolower( c ) ; } ) ;
594  }
595 
596  //--------------------------------------------------------------------------
597 
598  template <typename T>
599  inline T getenv( const std::string &var ) {
600  auto env = ::getenv( var.c_str() ) ;
601  if( nullptr == env ) {
602  MARLINMT_THROW( var + " env variable is not set" ) ;
603  }
604  return details::convert<T>::from_string( env ) ;
605  }
606 
607  //--------------------------------------------------------------------------
608 
609  template <typename T>
610  inline T getenv( const std::string &var, const T &defVal ) {
611  auto env = ::getenv( var.c_str() ) ;
612  if( nullptr == env ) {
613  return defVal ;
614  }
615  return details::convert<T>::from_string( env ) ;
616  }
617 
618  //--------------------------------------------------------------------------
619 
620  inline void print_banner( std::ostream &out ) {
621  out << std::endl ;
622  out << " __ __ _ _ __ __ _______ " << std::endl ;
623  out << " | \\/ | | (_) | \\/ |__ __|" << std::endl ;
624  out << " | \\ / | __ _ _ __| |_ _ __ | \\ / | | | " << std::endl ;
625  out << " | |\\/| |/ _` | '__| | | '_ \\| |\\/| | | | " << std::endl ;
626  out << " | | | | (_| | | | | | | | | | | | | | " << std::endl ;
627  out << " |_| |_|\\__,_|_| |_|_|_| |_|_| |_| |_| " << std::endl ;
628  out << std::endl ;
629  out << " Version: " << MARLINMT_RELEASE << std::endl ;
630  out << std::endl ;
631  out << " LICENCE: GPLv3 " << std::endl ;
632  out << " Copyright (C), Marlin/MarlinMT Authors" << std::endl ;
633  out << std::endl ;
634  }
635 
636  }
637 
638 } // end namespace marlinmt
639 
640 #endif
static std::string to_string(const std::string &value)
Definition: Utils.h:392
bool is_number(const std::string &str)
Definition: Utils.h:574
static std::string to_string(const std::vector< std::string > &value)
Definition: Utils.h:460
static std::vector< T > from_string(const std::string &str)
Definition: Utils.h:441
unsigned int nthreads(const std::string &str)
Definition: Utils.h:580
static const char * type
Definition: Utils.h:351
static std::string join(const T &input, const std::string &delimiter=" ")
Weird overload for scalar types.
Definition: Utils.h:320
static const char * type
Definition: Utils.h:349
static std::string typeToString(const T &var)
Convert a type to string.
Definition: Utils.h:226
static std::string to_string(const std::vector< T > &value)
Definition: Utils.h:430
std::chrono::duration< duration_rep, std::micro > microseconds
Definition: Utils.h:36
Definition: EntryData.h:93
T getenv(const std::string &var, const T &defVal)
Definition: Utils.h:610
constexpr unsigned long long value(const Flag_t &flag)
Definition: Flags.h:106
static const char * type
Definition: Utils.h:353
static std::string to_string(const bool &value)
Definition: Utils.h:406
static std::vector< std::string > from_string(const std::string &str)
Definition: Utils.h:471
static duration_rep time_difference(const time_point &older, const time_point &ealier)
Get the time difference between two time points.
Definition: Utils.h:88
static const char * type
Definition: Utils.h:355
static const char * type
Definition: Utils.h:350
static unsigned long long int typeHash64()
Generate a hash 64 from the typeid name.
Definition: Utils.h:144
std::chrono::duration< duration_rep, std::nano > nanoseconds
Definition: Utils.h:35
static bool from_string(const std::string &str)
Definition: Utils.h:410
static time_point now()
Get the current time.
Definition: Utils.h:50
std::chrono::duration< duration_rep, std::ratio< 60 > > minutes
Definition: Utils.h:39
clock class Provide a wrapper around a certain clock type in std to perform safe clock measurement in...
Definition: Utils.h:28
#define MARLINMT_THROW(message)
Definition: Exceptions.h:8
static T from_string(const std::string &str)
Definition: Utils.h:378
static T stringToType(const std::string &str)
Convert a variable to string.
Definition: Utils.h:263
std::chrono::duration< duration_rep > seconds
Definition: Utils.h:38
clock_type::time_point time_point
Definition: Utils.h:31
float duration_rep
Definition: Utils.h:32
void to_lower(std::string &str)
Definition: Utils.h:592
static std::string to_string(const T &value)
Definition: Utils.h:370
static std::vector< T > split(const std::string &inputString, const std::string &delimiter=" ")
Split the string with the corresponding delimiter.
Definition: Utils.h:303
StringUtil class Simple utility class for string operations.
Definition: Utils.h:157
std::vector< K > keys(const std::vector< std::pair< K, V >> &m)
Definition: Utils.h:563
HashHelper class Helper class to generate hash 64 id.
Definition: Utils.h:118
std::chrono::steady_clock clock_type
Definition: Utils.h:30
std::vector< std::string > split_string(const std::string &str, const std::string &delimiter, size_t maxTokens)
Definition: Utils.h:513
#define MARLINMT_RELEASE
Exception class.
Definition: Exceptions.h:60
std::pair< duration_rep, duration_rep > pair
Definition: Utils.h:33
static void crunchFor(duration_rep crunchTime)
Crunch numbers for some time.
Definition: Utils.h:99
static const char * type
Definition: Utils.h:342
std::chrono::duration< duration_rep, std::milli > milliseconds
Definition: Utils.h:37
static duration_rep elapsed_since(const time_point &since)
Get the elapsed time since a previous time point.
Definition: Utils.h:64
static constexpr unsigned long long int doByte(unsigned long long int hash, unsigned char val)
Definition: Utils.h:124
void print_banner(std::ostream &out)
Definition: Utils.h:620
static unsigned long long int hash64(const char *key)
Generate a hash 64 from a string.
Definition: Utils.h:133
static std::string from_string(const std::string &str)
Definition: Utils.h:396