[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

utilities.hxx VIGRA

Go to the documentation of this file.

1 /************************************************************************/
2 /* */
3 /* Copyright 1998-2002 by Ullrich Koethe */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* The VIGRA Website is */
7 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
8 /* Please direct questions, bug reports, and contributions to */
9 /* ullrich.koethe@iwr.uni-heidelberg.de or */
10 /* vigra@informatik.uni-hamburg.de */
11 /* */
12 /* Permission is hereby granted, free of charge, to any person */
13 /* obtaining a copy of this software and associated documentation */
14 /* files (the "Software"), to deal in the Software without */
15 /* restriction, including without limitation the rights to use, */
16 /* copy, modify, merge, publish, distribute, sublicense, and/or */
17 /* sell copies of the Software, and to permit persons to whom the */
18 /* Software is furnished to do so, subject to the following */
19 /* conditions: */
20 /* */
21 /* The above copyright notice and this permission notice shall be */
22 /* included in all copies or substantial portions of the */
23 /* Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32 /* OTHER DEALINGS IN THE SOFTWARE. */
33 /* */
34 /************************************************************************/
35 
36 
37 #ifndef VIGRA_BASICS_HXX
38 #define VIGRA_BASICS_HXX
39 
40 #include "config.hxx"
41 #include "error.hxx"
42 #include "metaprogramming.hxx"
43 #include "tuple.hxx"
44 #include "diff2d.hxx"
45 #include "mathutil.hxx"
46 #include <string>
47 #include <sstream>
48 #include <cctype>
49 #include <tuple>
50 
51 /*! \file */
52 
53 namespace vigra {
54 
55 /** Convert a value to a string. Available for integral and floating point types
56  and void *.
57 */
58 doxygen_overloaded_function(template <class T> std::string asString(T t))
59 
60 #define VIGRA_AS_STRING(T) \
61 inline std::string asString(T t) \
62 { \
63  std::stringstream s; \
64  s << t; \
65  return s.str(); \
66 }
67 
68 VIGRA_AS_STRING(bool)
69 VIGRA_AS_STRING(signed char)
70 VIGRA_AS_STRING(unsigned char)
71 VIGRA_AS_STRING(signed short)
72 VIGRA_AS_STRING(unsigned short)
73 VIGRA_AS_STRING(signed long)
74 VIGRA_AS_STRING(unsigned long)
75 VIGRA_AS_STRING(signed long long)
76 VIGRA_AS_STRING(unsigned long long)
77 VIGRA_AS_STRING(signed int)
78 VIGRA_AS_STRING(unsigned int)
79 VIGRA_AS_STRING(float)
80 VIGRA_AS_STRING(double)
81 VIGRA_AS_STRING(long double)
82 VIGRA_AS_STRING(void *)
83 
84 #undef VIGRA_AS_STRING
85 
86 template <class T>
87 std::string operator<<(std::string const & s, T const & t)
88 {
89  std::stringstream ss;
90  ss << t;
91  return s + ss.str();
92 }
93 
94  /** Convert string to lower case.
95  */
96 inline std::string tolower(std::string s)
97 {
98  for(unsigned int k=0; k<s.size(); ++k)
99  s[k] = (std::string::value_type)std::tolower(s[k]);
100  return s;
101 }
102 
103 inline std::string tolower(const char * s)
104 {
105  return tolower(std::string(s));
106 }
107 
108  /** Convert string to lower case and remove any white space characters.
109  */
110 inline std::string normalizeString(std::string const & s)
111 {
112  std::string res;
113 
114  for(unsigned int k=0; k<s.size(); ++k)
115  {
116  if(std::isspace(s[k]))
117  continue;
118  res += (std::string::value_type)std::tolower(s[k]);
119  }
120  return res;
121 }
122 
123 inline std::string normalizeString(const char * s)
124 {
125  return normalizeString(std::string(s));
126 }
127 
128 namespace detail {
129 
130 template <class T>
131 struct FinallyImpl
132 {
133  T & destructor_;
134 
135  FinallyImpl(T & destructor)
136  : destructor_(destructor)
137  {}
138 
139  ~FinallyImpl()
140  {
141  destructor_();
142  }
143 };
144 
145 } // namespace detail
146 
147 } // namespace vigra
148 
149 #define VIGRA_TOKEN_PASTE_IMPL(x, y) x##y
150 #define VIGRA_TOKEN_PASTE(x, y) VIGRA_TOKEN_PASTE_IMPL(x, y)
151 
152 #define VIGRA_FINALLY_IMPL(destructor, counter) \
153  auto VIGRA_TOKEN_PASTE(_vigra_finally_impl_, counter) = [&]() { destructor; }; \
154  ::vigra::detail::FinallyImpl<decltype(VIGRA_TOKEN_PASTE(_vigra_finally_impl_, counter))> \
155  VIGRA_TOKEN_PASTE(_vigra_finally_, counter)(VIGRA_TOKEN_PASTE(_vigra_finally_impl_, counter))
156 
157  /** Emulate the 'finally' keyword as known from Python and other languages.
158 
159  This macro improves upon the famous
160  <a href="http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization">Resource Acquisition Is Initialization</a> idiom, where a resource (e.g. heap memory or a mutex) is automatically free'ed when program execution leaves the current scope. This is normally achieved by placing a call which releases the resource into the destructor of a dedicated helper class (e.g. <tt>std::unique_ptr</tt> or <tt>std::lock_guard<std::mutex></tt>).
161 
162  Traditionally, a separate helper class is needed for every type of resource to be handled. In contrast, the macro <tt>VIGRA_FINALLY</tt> creates such a class on the fly by means of an embedded lambda expression.
163 
164  <b>Usage:</b>
165 
166  <b>\#include</b> <vigra/utilities.hxx><br/>
167 
168  \code
169  std::mutex my_mutex;
170  ...
171  {
172  // the following two lines are equivalent to
173  // std::unique_ptr<std::string> my_string = new std::string("foo");
174  std::string * my_string = new std::string("foo");
175  VIGRA_FINALLY(delete my_string);
176 
177  // the following two lines are equivalent to
178  // std::lock_guard<std::mutex> lock(my_mutex);
179  my_mutex.lock();
180  VIGRA_FINALLY(my_mutex.unlock());
181 
182  ...
183  }
184  // the string has been deallocated and the mutex is unlocked
185  \endcode
186 
187  You can pass any code to this macro. Multiple statements must be enclosed in braces as usual. Arbitrary many calls to <tt>VIGRA_FINALLY</tt> can be placed in the same scope. Their actions will be executed in the reversed order of declaration:
188 
189  \code
190  int i = 0;
191  ...
192  {
193  VIGRA_FINALLY({ // execute multiple statements
194  i = i*i;
195  ++i;
196  });
197 
198  VIGRA_FINALLY( i += 2 ); // this executes first
199 
200  assert(i == 0); // as yet, nothing happend
201  }
202  assert(i == 5); // 'finally' code was executed in reversed order at end-of-scope
203  \endcode
204 
205  This idea was popularized by Marko Tintor in <a href="http://blog.memsql.com/c-error-handling-with-auto/">The Auto Macro: A Clean Approach to C++ Error Handling</a>.
206  */
207 #define VIGRA_FINALLY(destructor) \
208  VIGRA_FINALLY_IMPL(destructor, __COUNTER__)
209 
210 namespace std {
211 
212 template <class T1, class T2>
213 ostream & operator<<(ostream & s, std::pair<T1, T2> const & p)
214 {
215  s << "(" << p.first << ", " << p.second << ")";
216  return s;
217 }
218 
219 }
220 
221 namespace vigra
222 {
223 namespace detail
224 {
225  template <typename TPL, size_t N, typename FUNCTOR>
226  struct for_each_in_tuple_impl
227  {
228  typedef for_each_in_tuple_impl<TPL, N-1, FUNCTOR> ForEachRecursion;
229 
230  void operator()(TPL && t, FUNCTOR && f) const
231  {
232  ForEachRecursion()(std::forward<TPL>(t), std::forward<FUNCTOR>(f));
233  f(std::get<N-1>(std::forward<TPL>(t)));
234  }
235  };
236 
237  template <typename TPL, typename FUNCTOR>
238  struct for_each_in_tuple_impl<TPL, 0, FUNCTOR>
239  {
240  void operator()(TPL && t, FUNCTOR && f) const
241  {}
242  };
243 } // namespace detail
244 
245 /**
246  * The for_each_in_tuple function calls the functor f on all elements of the tuple t.
247  * For each element type in the tuple, the functor must have an appropriate overload of operator().
248  *
249  * Example:
250  * \code
251  * #include <iostream>
252  * #include <tuple>
253  * #include <vigra/utilities.hxx>
254  *
255  * struct print
256  * {
257  * template <typename T>
258  * void operator()(T const & t) const
259  * {
260  * std::cout << t << std::endl;
261  * }
262  * };
263  *
264  * struct add_one
265  * {
266  * template <typename T>
267  * void operator()(T & t) const
268  * {
269  * t += 1;
270  * }
271  * };
272  *
273  * int main()
274  * {
275  * std::tuple<int, double, size_t> tpl(-5, 0.4, 10);
276  * vigra::for_each_in_tuple(tpl, add_one());
277  * vigra::for_each_in_tuple(tpl, print());
278  * }
279  * \endcode
280  */
281 template <typename TPL, typename FUNCTOR>
282 void for_each_in_tuple(TPL && t, FUNCTOR && f)
283 {
284  typedef typename std::decay<TPL>::type UNQUALIFIED_TPL;
285  typedef detail::for_each_in_tuple_impl<TPL, std::tuple_size<UNQUALIFIED_TPL>::value, FUNCTOR> ForEachImpl;
286 
287  ForEachImpl()(std::forward<TPL>(t), std::forward<FUNCTOR>(f));
288 }
289 
290 } // namespace vigra
291 
292 /** \page Utilities Utilities
293  Basic helper functionality needed throughout.
294 
295  <UL style="list-style-image:url(documents/bullet.gif)">
296  <LI> \ref vigra::ArrayVector
297  <BR>&nbsp;&nbsp;&nbsp;<em>replacement for std::vector (always uses consecutive memory)</em>
298  <LI> \ref vigra::Any
299  <BR>&nbsp;&nbsp;&nbsp;<em>typesafe storage of arbitrary values</em>
300  <LI> \ref vigra::BucketQueue and \ref vigra::MappedBucketQueue
301  <BR>&nbsp;&nbsp;&nbsp;<em>efficient priority queues for integer priorities</em>
302  <LI> \ref RangesAndPoints
303  <BR>&nbsp;&nbsp;&nbsp;<em>2-D and N-D positions, extents, and boxes</em>
304  <LI> \ref PixelNeighborhood
305  <BR>&nbsp;&nbsp;&nbsp;<em>4- and 8-neighborhood definitions and circulators</em>
306  <LI> \ref VoxelNeighborhood
307  <BR>&nbsp;&nbsp;&nbsp;<em>6- and 26-neighborhood definitions and circulators</em>
308  <LI> \ref vigra::IteratorAdaptor
309  <BR>&nbsp;&nbsp;&nbsp;<em>Quickly create STL-compatible 1D iterator adaptors</em>
310  <LI> \ref TupleTypes
311  <BR>&nbsp;&nbsp;&nbsp;<em>pair, triple, tuple4, tuple5</em>
312  <LI> \ref MathConstants
313  <BR>&nbsp;&nbsp;&nbsp;<em>M_PI, M_SQRT2</em>
314  <LI> \ref TimingMacros
315  <BR>&nbsp;&nbsp;&nbsp;<em>Macros for taking execution speed measurements</em>
316  <LI> \ref VIGRA_FINALLY
317  <BR>&nbsp;&nbsp;&nbsp;<em>Emulation of the 'finally' keyword from Python</em>
318  </UL>
319 */
320 
321 #endif // VIGRA_BASICS_HXX
std::string tolower(std::string s)
Definition: utilities.hxx:96
void for_each_in_tuple(TPL &&t, FUNCTOR &&f)
Definition: utilities.hxx:282
std::string asString(T t)(...)
doxygen_overloaded_function(template<...> void separableConvolveBlockwise) template< unsigned int N
Separated convolution on ChunkedArrays.
std::string normalizeString(std::string const &s)
Definition: utilities.hxx:110

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.11.1 (Fri May 19 2017)