Main Page · Modules · All Classes · Class Hierarchy
MCDefs.hpp
1 /*
2  * This file is part of the AiBO+ project
3  *
4  * Copyright (C) 2005-2016 Csaba Kertész (csaba.kertesz@gmail.com)
5  *
6  * AiBO+ is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * AiBO+ is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
19  *
20  */
21 
22 #pragma once
23 
24 #ifndef __AIBO_BUILD__
25 #include <QString>
26 #endif
27 
28 #include <boost/algorithm/string/case_conv.hpp>
29 #include <boost/algorithm/string/split.hpp>
30 #include <boost/random/mersenne_twister.hpp>
31 #include <boost/random/uniform_int.hpp>
32 #include <boost/random/variate_generator.hpp>
33 #include <boost/shared_ptr.hpp>
34 
35 // This hack is needed for testing
36 #if defined(protected)
37 #undef protected
38 #undef private
39 #include <sstream> // krazy:exclude=includes
40 #define protected public
41 #define private public
42 #else
43 #include <sstream>
44 #endif
45 #include <string>
46 
47 // These conditions are because of PVS Studio
48 #if defined(__unix__) || defined(__APPLE__) || defined(__MINGW32__) || defined(__MINGW64__)
49 #include <cxxabi.h>
50 #endif
51 #include <setjmp.h>
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <typeinfo>
55 #include <unistd.h>
56 
62 #define foreach_i(_i, _iter, _container) \
64  unsigned int _i = 0; \
65  \
66  for (auto _iter = _container.begin(); _iter != _container.end(); ++_i, ++_iter)
67 
74 template <typename T>
75 struct iterator_extractor { typedef typename T::iterator type; };
76 
83 template <typename T>
84 struct iterator_extractor<T const> { typedef typename T::const_iterator type; };
85 
92 template <typename T>
93 class Indexer {
94 public:
95  class iterator {
96  typedef typename iterator_extractor<T>::type inner_iterator;
97 
98  typedef typename std::iterator_traits<inner_iterator>::reference inner_reference;
99  public:
100  struct reference
101  {
102  reference (const size_t& _i, const inner_reference& _ref) : i(_i), ref(_ref) { }
103 
104  inner_reference operator*() const { return ref; }
105 
106  size_t i;
107  inner_reference ref;
108  };
109 
110  explicit iterator(inner_iterator it): _pos(0), _it(it) {}
111 
112  reference operator*() const { return reference(_pos, *_it); }
113 
114  iterator& operator++() { ++_pos; ++_it; return *this; }
115  iterator operator++(int) { iterator tmp(*this); ++*this; return tmp; }
116 
117  bool operator==(iterator const& it) const { return _it == it._it; }
118  bool operator!=(iterator const& it) const { return !(*this == it); }
119 
120  private:
121  size_t _pos;
122  inner_iterator _it;
123  };
124 
125  explicit Indexer(T& t): _container(t) {}
126 
127  iterator begin() const { return iterator(_container.begin()); }
128  iterator end() const { return iterator(_container.end()); }
129 
130 private:
131  T& _container;
132 };
133 
145 template <typename T>
146 Indexer<T> index(T& t) { return Indexer<T>(t); }
147 
148 // Macros to replace the broken exception handling on AIBO with a setjmp/longjmp hack
149 #if defined(__AIBO_BUILD__)
150 extern "C"
151 {
152 extern jmp_buf JumpPoint;
153 extern int JumpPointValid;
154 extern void RaiseCppException();
155 }
156 
157 #define MC_TRY_BEGIN MC_TRY_BEGIN_1(1)
158 #define MC_CATCH_BEGIN MC_CATCH_BEGIN_1(1)
159 #define MC_CATCH_END MC_CATCH_END_1(1)
160 
161 #define MC_TRY_BEGIN_1(_num) \
162  try { \
163  JumpPointValid = 1; \
164  if (setjmp(JumpPoint) != 0) \
165  { \
166  if (JumpPointValid) \
167  goto exception_happened##_num; \
168  } \
169  if (!JumpPointValid) \
170  goto finish##_num;
171 
172 #define MC_CATCH_BEGIN_1(_num) \
173  goto finish##_num; \
174  } catch(...) { } \
175 exception_happened##_num:
176 
177 #define MC_CATCH_END_1(_num) \
178 finish##_num: \
179  JumpPointValid = 0;
180 
181 #else
182 #define MC_TRY_BEGIN try {
183 #define MC_CATCH_BEGIN } catch(...) {
184 #define MC_CATCH_END }
185 #define MC_TRY_BEGIN_1(...) try {
186 #define MC_CATCH_BEGIN_1(...) } catch(...) {
187 #define MC_CATCH_END_1(...) }
188 #endif
189 
190 namespace MC
191 {
192 typedef boost::variate_generator<boost::mt19937&, boost::uniform_int<> > RandomGeneratorType;
193 }
194 
199 {
200  template<typename T>
201  friend T MCRandComplex(const T& min, const T& max);
202 
203 public:
204 
212  static void SetNewSeed(int seed = (int)time(nullptr));
213 
214 private:
216  static boost::mt19937 Algorithm;
217 };
218 
229 template <typename T>
230 T MCRandComplex(const T& min, const T& max)
231 {
232  MC::RandomGeneratorType Generator(MCRandomSeed::Algorithm, boost::uniform_int<>((int)min, (int)max));
233 
234  return (T)Generator();
235 }
236 
247 template <typename T>
248 T MCRand(const T& min, const T& max)
249 {
250  return rand() % (int)(max-min+1)+min;
251 }
252 
260 extern int MCRandSign();
261 
269 extern void MCSleep(unsigned int msecs);
270 
271 #if !defined(__AIBO_BUILD__) && defined(__unix__)
272 
279 extern int MCGetSystemMemorySize();
280 #endif
281 
289 extern float MCFloatInfinity();
290 
298 extern double MCDoubleInfinity();
299 
309 extern bool MCIsFloatInfinity(const float value);
310 
320 extern bool MCIsDoubleInfinity(const double value);
321 
333 extern float MCRound(float number);
334 
347 extern float MCScaleValue(float value, float min, float max, float new_max);
348 
359 template <typename T>
360 std::string MCToStr(const T value, bool hex_manipulator = false)
361 {
362  std::stringstream Tmp;
363 
364  if (hex_manipulator)
365  Tmp << std::hex;
366  Tmp << value;
367  return Tmp.str();
368 }
369 
379 template <typename T>
380 T MCStrConvert(const std::string& str)
381 {
382  std::stringstream Tmp(str);
383  T Value;
384 
385  Tmp >> Value;
386  return Value;
387 }
388 
398 template <typename T>
399 T MCAbs(const T& value)
400 {
401  return value >= 0 ? value : -value;
402 }
403 
418 extern int MCCompare(const std::string& item, const std::string& a, const std::string& b);
419 
432 template <typename T>
433 int MCCompare(const T& item, const T& a, const T& b)
434 {
435  T Diff1 = MCAbs(a-item);
436  T Diff2 = MCAbs(b-item);
437 
438  if (Diff1 == Diff2)
439  {
440  return 0;
441  }
442  return Diff1 < Diff2 ? -1 : 1;
443 }
444 
456 extern int MCCompare(const std::string& a, const std::string& b);
457 
469 template <typename T>
470 int MCCompare(const T& a, const T& b)
471 {
472  if (a == b)
473  return 0;
474 
475  return a > b ? -1 : 1;
476 }
477 
488 template <typename T>
489 const T& MCMin(const T& a, const T& b)
490 {
491  if (a < b)
492  return a;
493  return b;
494 }
495 
506 template <typename T>
507 const T& MCMax(const T& a, const T& b)
508 {
509  if (a < b)
510  return b;
511  return a;
512 }
513 
526 template <typename T>
527 const T& MCBound(const T& min, const T& value, const T& max)
528 {
529  return MCMax(min, MCMin(max, value));
530 }
531 
543 template <typename T>
544 bool MCRangeCheck(const T& value, const T& min, const T& max)
545 {
546  if (value < MCMin(min, max) || value > MCMax(min, max))
547  return false;
548 
549  return true;
550 }
551 
552 #if defined(__GNUC__) || defined(__clang__)
553 #define likely(x) __builtin_expect(!!(x), 1)
555 #define unlikely(x) __builtin_expect(!!(x), 0)
557 #else
558 #define likely(x) x
559 #define unlikely(x) x
560 #endif
561 
562 // Help clang's static analyzer to determinate functions that never return
563 #ifndef __has_feature
564 #define __has_feature(x) 0 // Compatibility with non-clang compilers.
565 #endif
566 #ifndef CLANG_ANALYZER_NORETURN
567 #if __has_feature(attribute_analyzer_noreturn)
568 #define CLANG_ANALYZER_NORETURN __attribute__((analyzer_noreturn))
569 #else
570 #define CLANG_ANALYZER_NORETURN
571 #endif
572 #endif
573 
575 #if defined(__MINGW32__) || defined(__MINGW64__)
576 #define MC_DIR_SEPARATOR "\\"
577 #else
578 #define MC_DIR_SEPARATOR "/"
579 #endif
580 
581 #if defined(__unix__)
582 #define MC_ANSI_RED "\033[1;31m"
584 #define MC_ANSI_BLACK "\033[1;30m"
586 #define MC_ANSI_PURPLE "\033[1;35m"
588 #define MC_ANSI_GREEN "\033[1;32m"
590 #define MC_ANSI_COLOR_END "\033[0;39m"
592 #else
593 #define MC_ANSI_RED ""
594 #define MC_ANSI_BLACK ""
595 #define MC_ANSI_PURPLE ""
596 #define MC_ANSI_GREEN ""
597 #define MC_ANSI_COLOR_END ""
598 #endif
599 
601 #define MC_UNUSED(a) (void)a;
602 
604 #define MC_DISABLE_COPY(class_name) \
605 private: \
606  class_name(const class_name&); \
607  class_name& operator=(const class_name&); \
608 public:
609 
611 #define MC_DISABLE_DEFAULT_CTOR(class_name) \
612 private: \
613  class_name(); \
614 public:
615 
626 template <typename T>
627 std::string MCGetClassName(T* instance = nullptr, const std::string& name_suffix = "")
628 {
629  // Note: The instance parameter is "fake" argument for easier use of the function
630  MC_UNUSED(instance)
631 
632  char* ClassName = nullptr;
633  std::string ClassNameStr = "";
634  int DemangleStatus = 0;
635 
636  ClassName = abi::__cxa_demangle(typeid(T).name(), 0, 0, &DemangleStatus);
637  if (ClassName)
638  {
639  ClassNameStr = ClassName;
640  ClassNameStr += name_suffix;
641  }
642  free(ClassName);
643  ClassName = nullptr;
644  return ClassNameStr;
645 }
646 
656 extern bool MCFileExists(const std::string& file_name);
657 
667 extern int MCGetFileSize(const std::string& file_name);
668 
669 #ifndef __AIBO_BUILD__
670 #if defined(__unix__) && !defined(__ANDROID__)
671 
676 extern void MCGenerateBacktrace();
677 #endif
678 
688 extern bool MCCreatePath(const QString& path_str);
689 
699 extern bool MCRemoveDirectory(const QString& dir_str);
700 
710 extern QString MCFixPath(const QString& path);
711 
719 extern void MCAddSearchPath(const QString& path);
720 
733 extern QString MCGetDataFile(const QString& file_name);
734 
747 extern QString MCGetDataSubdirectory(const QString& subdirectory);
748 #endif
749 
bool MCCreatePath(const QString &path_str)
Create a new path if it does not exist.
Definition: MCDefs.cpp:344
Random seed generation based on boost::mt19937.
Definition: MCDefs.hpp:198
int MCCompare(const std::string &item, const std::string &a, const std::string &b)
Decide whether a string is relative closer to other strings.
Definition: MCDefs.cpp:167
Iterator magic for for loops to get the index while iterating through.
Definition: MCDefs.hpp:75
bool MCRangeCheck(const T &value, const T &min, const T &max)
Range check of a value.
Definition: MCDefs.hpp:544
int MCGetFileSize(const std::string &file_name)
Get file size.
Definition: MCDefs.cpp:239
double MCDoubleInfinity()
Get double infinity.
Definition: MCDefs.cpp:116
bool MCIsDoubleInfinity(const double value)
Check a value for double infinity.
Definition: MCDefs.cpp:132
Iterator magic for for loops to get the index while iterating through.
Definition: MCDefs.hpp:93
std::string MCToStr(const T value, bool hex_manipulator=false)
Convert an other type to string with std::stringstream.
Definition: MCDefs.hpp:360
const T & MCBound(const T &min, const T &value, const T &max)
Check a value bound according to a range.
Definition: MCDefs.hpp:527
Indexer< T > index(T &t)
Iterator magic for for loops to get the index while iterating through.
Definition: MCDefs.hpp:146
T MCAbs(const T &value)
Calculate absolute value.
Definition: MCDefs.hpp:399
T MCRand(const T &min, const T &max)
Get a random number generated with standard calls.
Definition: MCDefs.hpp:248
std::string MCGetClassName(T *instance=nullptr, const std::string &name_suffix="")
Get a class name.
Definition: MCDefs.hpp:627
void MCSleep(unsigned int msecs)
Wait for some milliseconds.
Definition: MCDefs.cpp:89
QString MCGetDataFile(const QString &file_name)
Search a data file.
Definition: MCDefs.cpp:425
T MCRandComplex(const T &min, const T &max)
Get a random number generated with an advanced algorithm.
Definition: MCDefs.hpp:230
bool MCIsFloatInfinity(const float value)
Check a value for float infinity.
Definition: MCDefs.cpp:122
const T & MCMax(const T &a, const T &b)
Get the maximum of two values.
Definition: MCDefs.hpp:507
#define MC_UNUSED(a)
Helper macro to avoid compiler warning about unused function parameters.
Definition: MCDefs.hpp:601
const T & MCMin(const T &a, const T &b)
Get the minimum of two values.
Definition: MCDefs.hpp:489
bool MCFileExists(const std::string &file_name)
Check whether a file exists.
Definition: MCDefs.cpp:226
QString MCFixPath(const QString &path)
Fix the (back)slashes in a path according to the platform.
Definition: MCDefs.cpp:399
static boost::mt19937 Algorithm
Random number generation algorithm.
Definition: MCDefs.hpp:216
float MCRound(float number)
Round a float number.
Definition: MCDefs.cpp:142
float MCFloatInfinity()
Get float infinity.
Definition: MCDefs.cpp:110
bool MCRemoveDirectory(const QString &dir_str)
Remove a directory with its content.
Definition: MCDefs.cpp:370
float MCScaleValue(float value, float min, float max, float new_max)
Scale a value to a new range.
Definition: MCDefs.cpp:154
int MCRandSign()
Generate a random sign.
Definition: MCDefs.cpp:79
T MCStrConvert(const std::string &str)
Convert a string to an other type with std::stringstream.
Definition: MCDefs.hpp:380
QString MCGetDataSubdirectory(const QString &subdirectory)
Get a data subdirectory.
Definition: MCDefs.cpp:453
void MCAddSearchPath(const QString &path)
Add a location to the search path for data files.
Definition: MCDefs.cpp:414