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

utilities.hxx
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
53namespace vigra {
54
55/** Convert a value to a string. Available for integral and floating point types
56 and void *.
57*/
58doxygen_overloaded_function(template <class T> std::string asString(T t))
59
60#define VIGRA_AS_STRING(T) \
61inline std::string asString(T t) \
62{ \
63 std::stringstream s; \
64 s << t; \
65 return s.str(); \
66}
67
68VIGRA_AS_STRING(bool)
69VIGRA_AS_STRING(signed char)
70VIGRA_AS_STRING(unsigned char)
71VIGRA_AS_STRING(signed short)
72VIGRA_AS_STRING(unsigned short)
73VIGRA_AS_STRING(signed long)
74VIGRA_AS_STRING(unsigned long)
75VIGRA_AS_STRING(signed long long)
76VIGRA_AS_STRING(unsigned long long)
77VIGRA_AS_STRING(signed int)
78VIGRA_AS_STRING(unsigned int)
79VIGRA_AS_STRING(float)
80VIGRA_AS_STRING(double)
81VIGRA_AS_STRING(long double)
82VIGRA_AS_STRING(void *)
83
84#undef VIGRA_AS_STRING
85
86template <class T>
87std::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 */
96inline 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
103inline 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 */
110inline 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
123inline std::string normalizeString(const char * s)
124{
125 return normalizeString(std::string(s));
126}
127
128namespace detail {
129
130template <class T>
131struct 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
210namespace std {
211
212template <class T1, class T2>
213ostream & operator<<(ostream & s, std::pair<T1, T2> const & p)
214{
215 s << "(" << p.first << ", " << p.second << ")";
216 return s;
217}
218
219}
220
221namespace vigra
222{
223namespace 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 */
281template <typename TPL, typename FUNCTOR>
282void 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
std::string normalizeString(std::string const &s)
Definition: utilities.hxx:110
doxygen_overloaded_function(template<... > void separableConvolveBlockwise) template< unsigned int N
Separated convolution on ChunkedArrays.
std::string asString(T t)(...)
void for_each_in_tuple(TPL &&t, FUNCTOR &&f)
Definition: utilities.hxx:282

© 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