0
5
1
bin
bin
2
257
219
24
1 | 1 |
EXTRA_DIST += \ |
2 | 2 |
lemon/Makefile \ |
3 | 3 |
lemon/lemon.pc.in |
4 | 4 |
|
5 | 5 |
pkgconfig_DATA += lemon/lemon.pc |
6 | 6 |
|
7 | 7 |
lib_LTLIBRARIES += lemon/libemon.la |
8 | 8 |
|
9 | 9 |
lemon_libemon_la_SOURCES = \ |
10 | 10 |
lemon/arg_parser.cc \ |
11 | 11 |
lemon/base.cc \ |
12 | 12 |
lemon/random.cc |
13 | 13 |
|
14 | 14 |
|
15 | 15 |
lemon_libemon_la_CXXFLAGS = $(GLPK_CFLAGS) $(CPLEX_CFLAGS) $(SOPLEX_CXXFLAGS) |
16 | 16 |
lemon_libemon_la_LDFLAGS = $(GLPK_LIBS) $(CPLEX_LIBS) $(SOPLEX_LIBS) |
17 | 17 |
|
18 | 18 |
lemon_HEADERS += \ |
19 | 19 |
lemon/arg_parser.h \ |
20 |
lemon/assert.h \ |
|
20 | 21 |
lemon/bfs.h \ |
21 | 22 |
lemon/bin_heap.h \ |
22 | 23 |
lemon/dfs.h \ |
23 | 24 |
lemon/dijkstra.h \ |
24 | 25 |
lemon/dim2.h \ |
25 | 26 |
lemon/error.h \ |
26 | 27 |
lemon/graph_utils.h \ |
27 | 28 |
lemon/kruskal.h \ |
28 | 29 |
lemon/list_graph.h \ |
29 | 30 |
lemon/maps.h \ |
30 | 31 |
lemon/math.h \ |
31 | 32 |
lemon/path.h \ |
32 | 33 |
lemon/random.h \ |
33 | 34 |
lemon/tolerance.h \ |
34 | 35 |
lemon/unionfind.h |
35 | 36 |
|
36 | 37 |
bits_HEADERS += \ |
37 | 38 |
lemon/bits/alteration_notifier.h \ |
38 | 39 |
lemon/bits/array_map.h \ |
39 | 40 |
lemon/bits/base_extender.h \ |
40 | 41 |
lemon/bits/default_map.h \ |
41 | 42 |
lemon/bits/graph_extender.h \ |
42 | 43 |
lemon/bits/invalid.h \ |
43 | 44 |
lemon/bits/map_extender.h \ |
44 | 45 |
lemon/bits/path_dump.h \ |
45 | 46 |
lemon/bits/traits.h \ |
46 | 47 |
lemon/bits/utility.h \ |
47 | 48 |
lemon/bits/vector_map.h |
48 | 49 |
|
49 | 50 |
concept_HEADERS += \ |
50 | 51 |
lemon/concept_check.h \ |
51 | 52 |
lemon/concepts/digraph.h \ |
52 | 53 |
lemon/concepts/graph.h \ |
53 | 54 |
lemon/concepts/heap.h \ |
54 | 55 |
lemon/concepts/maps.h \ |
55 | 56 |
lemon/concepts/path.h \ |
56 | 57 |
lemon/concepts/graph_components.h |
1 | 1 |
/* -*- C++ -*- |
2 | 2 |
* |
3 | 3 |
* This file is a part of LEMON, a generic C++ optimization library |
4 | 4 |
* |
5 | 5 |
* Copyright (C) 2003-2008 |
6 | 6 |
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport |
7 | 7 |
* (Egervary Research Group on Combinatorial Optimization, EGRES). |
8 | 8 |
* |
9 | 9 |
* Permission to use, modify and distribute this software is granted |
10 | 10 |
* provided that this copyright notice appears in all copies. For |
11 | 11 |
* precise terms see the accompanying LICENSE file. |
12 | 12 |
* |
13 | 13 |
* This software is provided "AS IS" with no warranty of any kind, |
14 | 14 |
* express or implied, and with no claim as to its suitability for any |
15 | 15 |
* purpose. |
16 | 16 |
* |
17 | 17 |
*/ |
18 | 18 |
|
19 | 19 |
#ifndef LEMON_ARG_PARSER |
20 | 20 |
#define LEMON_ARG_PARSER |
21 | 21 |
|
22 | 22 |
#include <vector> |
23 | 23 |
#include <map> |
24 | 24 |
#include <list> |
25 | 25 |
#include <string> |
26 | 26 |
#include <iostream> |
27 | 27 |
#include <sstream> |
28 | 28 |
#include <algorithm> |
29 |
#include <lemon/ |
|
29 |
#include <lemon/assert.h> |
|
30 | 30 |
|
31 | 31 |
///\ingroup misc |
32 | 32 |
///\file |
33 | 33 |
///\brief A tool to parse command line arguments. |
34 | 34 |
|
35 | 35 |
namespace lemon { |
36 | 36 |
|
37 | 37 |
///Command line arguments parser |
38 | 38 |
|
39 | 39 |
///\ingroup misc |
40 | 40 |
///Command line arguments parser. |
41 | 41 |
/// |
42 | 42 |
///For a complete example see the \ref arg_parser_demo.cc demo file. |
43 | 43 |
class ArgParser { |
44 | 44 |
|
45 | 45 |
static void _showHelp(void *p); |
46 | 46 |
protected: |
47 | 47 |
|
48 | 48 |
int _argc; |
49 | 49 |
const char **_argv; |
50 | 50 |
|
51 | 51 |
enum OptType { UNKNOWN=0, BOOL=1, STRING=2, DOUBLE=3, INTEGER=4, FUNC=5 }; |
52 | 52 |
|
53 | 53 |
class ParData { |
54 | 54 |
public: |
55 | 55 |
union { |
56 | 56 |
bool *bool_p; |
57 | 57 |
int *int_p; |
58 | 58 |
double *double_p; |
59 | 59 |
std::string *string_p; |
60 | 60 |
struct { |
61 | 61 |
void (*p)(void *); |
62 | 62 |
void *data; |
63 | 63 |
} func_p; |
64 | 64 |
|
65 | 65 |
}; |
66 | 66 |
std::string help; |
67 | 67 |
bool mandatory; |
68 | 68 |
OptType type; |
69 | 69 |
bool set; |
70 | 70 |
bool ingroup; |
71 | 71 |
bool has_syn; |
72 | 72 |
bool syn; |
73 | 73 |
bool self_delete; |
74 | 74 |
ParData() : mandatory(false), type(UNKNOWN), set(false), ingroup(false), |
75 | 75 |
has_syn(false), syn(false), self_delete(false) {} |
76 | 76 |
}; |
77 | 77 |
|
78 | 78 |
typedef std::map<std::string,ParData> Opts; |
79 | 79 |
Opts _opts; |
80 | 80 |
|
81 | 81 |
class GroupData |
82 | 82 |
{ |
83 | 83 |
public: |
84 | 84 |
typedef std::list<std::string> Opts; |
85 | 85 |
Opts opts; |
86 | 86 |
bool only_one; |
87 | 87 |
bool mandatory; |
88 | 88 |
GroupData() :only_one(false), mandatory(false) {} |
89 | 89 |
}; |
90 | 90 |
|
91 | 91 |
typedef std::map<std::string,GroupData> Groups; |
92 | 92 |
Groups _groups; |
93 | 93 |
|
94 | 94 |
struct OtherArg |
95 | 95 |
{ |
96 | 96 |
std::string name; |
97 | 97 |
std::string help; |
98 | 98 |
OtherArg(std::string n, std::string h) :name(n), help(h) {} |
99 | 99 |
|
100 | 100 |
}; |
101 | 101 |
|
102 | 102 |
std::vector<OtherArg> _others_help; |
103 | 103 |
std::vector<std::string> _file_args; |
104 | 104 |
std::string _command_name; |
105 | 105 |
|
106 | 106 |
|
107 | 107 |
private: |
108 | 108 |
//Bind a function to an option. |
109 | 109 |
|
110 | 110 |
//\param name The name of the option. The leading '-' must be omitted. |
111 | 111 |
//\param help A help string. |
112 | 112 |
//\retval func The function to be called when the option is given. It |
113 | 113 |
// must be of type "void f(void *)" |
114 | 114 |
//\param data Data to be passed to \c func |
115 | 115 |
ArgParser &funcOption(const std::string &name, |
116 | 116 |
const std::string &help, |
117 | 117 |
void (*func)(void *),void *data); |
118 | 118 |
|
119 | 119 |
public: |
120 | 120 |
|
121 | 121 |
///\e |
122 | 122 |
ArgParser(int argc, const char **argv); |
123 | 123 |
|
124 | 124 |
~ArgParser(); |
125 | 125 |
|
126 | 126 |
///Add a new integer type option |
127 | 127 |
|
128 | 128 |
///\param name The name of the option. The leading '-' must be omitted. |
129 | 129 |
///\param help A help string. |
130 | 130 |
///\param value A default value for the option. |
131 | 131 |
///\param obl Indicate if the option is mandatory. |
132 | 132 |
ArgParser &intOption(const std::string &name, |
133 | 133 |
const std::string &help, |
134 | 134 |
int value=0, bool obl=false); |
135 | 135 |
|
136 | 136 |
///Add a new floating point type option |
137 | 137 |
|
138 | 138 |
///\param name The name of the option. The leading '-' must be omitted. |
139 | 139 |
///\param help A help string. |
140 | 140 |
///\param value A default value for the option. |
141 | 141 |
///\param obl Indicate if the option is mandatory. |
142 | 142 |
ArgParser &doubleOption(const std::string &name, |
143 | 143 |
const std::string &help, |
144 | 144 |
double value=0, bool obl=false); |
145 | 145 |
|
146 | 146 |
///Add a new bool type option |
147 | 147 |
|
148 | 148 |
///\param name The name of the option. The leading '-' must be omitted. |
149 | 149 |
///\param help A help string. |
150 | 150 |
///\param value A default value for the option. |
151 | 151 |
///\param obl Indicate if the option is mandatory. |
152 | 152 |
///\note A mandatory bool obtion is of very little use. |
153 | 153 |
ArgParser &boolOption(const std::string &name, |
154 | 154 |
const std::string &help, |
155 | 155 |
bool value=false, bool obl=false); |
156 | 156 |
|
157 | 157 |
///Add a new string type option |
158 | 158 |
|
159 | 159 |
///\param name The name of the option. The leading '-' must be omitted. |
160 | 160 |
///\param help A help string. |
161 | 161 |
///\param value A default value for the option. |
162 | 162 |
///\param obl Indicate if the option is mandatory. |
163 | 163 |
ArgParser &stringOption(const std::string &name, |
164 | 164 |
const std::string &help, |
165 | 165 |
std::string value="", bool obl=false); |
166 | 166 |
|
167 | 167 |
///\name Options with external storage |
168 | 168 |
///Using this functions, the value of the option will be directly written |
169 | 169 |
///into a variable once the option appears in the command line. |
170 | 170 |
|
171 | 171 |
///@{ |
172 | 172 |
|
173 | 173 |
///Add a new integer type option with a storage reference |
174 | 174 |
|
175 | 175 |
///\param name The name of the option. The leading '-' must be omitted. |
176 | 176 |
///\param help A help string. |
177 | 177 |
///\param obl Indicate if the option is mandatory. |
178 | 178 |
///\retval ref The value of the argument will be written to this variable. |
179 | 179 |
ArgParser &refOption(const std::string &name, |
180 | 180 |
const std::string &help, |
181 | 181 |
int &ref, bool obl=false); |
182 | 182 |
|
183 | 183 |
///Add a new floating type option with a storage reference |
184 | 184 |
|
185 | 185 |
///\param name The name of the option. The leading '-' must be omitted. |
186 | 186 |
///\param help A help string. |
187 | 187 |
///\param obl Indicate if the option is mandatory. |
188 | 188 |
///\retval ref The value of the argument will be written to this variable. |
189 | 189 |
ArgParser &refOption(const std::string &name, |
190 | 190 |
const std::string &help, |
191 | 191 |
double &ref, bool obl=false); |
192 | 192 |
|
193 | 193 |
///Add a new bool type option with a storage reference |
194 | 194 |
|
195 | 195 |
///\param name The name of the option. The leading '-' must be omitted. |
196 | 196 |
///\param help A help string. |
197 | 197 |
///\param obl Indicate if the option is mandatory. |
198 | 198 |
///\retval ref The value of the argument will be written to this variable. |
199 | 199 |
///\note A mandatory bool obtion is of very little use. |
200 | 200 |
ArgParser &refOption(const std::string &name, |
201 | 201 |
const std::string &help, |
202 | 202 |
bool &ref, bool obl=false); |
203 | 203 |
|
204 | 204 |
///Add a new string type option with a storage reference |
205 | 205 |
|
206 | 206 |
///\param name The name of the option. The leading '-' must be omitted. |
207 | 207 |
///\param help A help string. |
208 | 208 |
///\param obl Indicate if the option is mandatory. |
209 | 209 |
///\retval ref The value of the argument will be written to this variable. |
210 | 210 |
ArgParser &refOption(const std::string &name, |
211 | 211 |
const std::string &help, |
212 | 212 |
std::string &ref, bool obl=false); |
213 | 213 |
|
214 | 214 |
///@} |
215 | 215 |
|
216 | 216 |
///\name Option Groups and Synonyms |
217 | 217 |
/// |
218 | 218 |
|
219 | 219 |
///@{ |
220 | 220 |
|
221 | 221 |
///Boundle some options into a group |
222 | 222 |
|
223 | 223 |
/// You can group some option by calling this function repeatedly for each |
224 | 224 |
/// option to be grouped with the same groupname. |
225 | 225 |
///\param group The group name. |
226 | 226 |
///\param opt The option name. |
227 | 227 |
ArgParser &optionGroup(const std::string &group, |
228 | 228 |
const std::string &opt); |
229 | 229 |
|
230 | 230 |
///Make the members of a group exclusive |
231 | 231 |
|
232 | 232 |
///If you call this function for a group, than at most one of them can be |
233 | 233 |
///given at the same time |
234 | 234 |
ArgParser &onlyOneGroup(const std::string &group); |
235 | 235 |
|
236 | 236 |
///Make a group mandatory |
237 | 237 |
|
238 | 238 |
///Using this function, at least one of the members of \c group |
239 | 239 |
///must be given. |
240 | 240 |
ArgParser &mandatoryGroup(const std::string &group); |
241 | 241 |
|
242 | 242 |
///Create synonym to an option |
243 | 243 |
|
244 | 244 |
///With this function you can create a synonym \c syn of the |
245 | 245 |
///option \c opt. |
246 | 246 |
ArgParser &synonym(const std::string &syn, |
247 | 247 |
const std::string &opt); |
248 | 248 |
|
249 | 249 |
///@} |
250 | 250 |
|
251 | 251 |
///Give help string for non-parsed arguments. |
252 | 252 |
|
253 | 253 |
///With this function you can give help string for non-parsed arguments. |
254 | 254 |
///The parameter \c name will be printed in the short usage line, while |
255 | 255 |
///\c help gives a more detailed description. |
256 | 256 |
ArgParser &other(const std::string &name, |
257 | 257 |
const std::string &help=""); |
258 | 258 |
|
259 | 259 |
///Give back the non-option type arguments. |
260 | 260 |
|
261 | 261 |
///Give back a reference to a vector consisting of the program arguments |
262 | 262 |
///not starting with a '-' character. |
263 | 263 |
std::vector<std::string> &files() { return _file_args; } |
264 | 264 |
|
265 | 265 |
///Give back the command name (the 0th argument) |
266 | 266 |
const std::string &commandName() { return _command_name; } |
267 | 267 |
|
268 | 268 |
void show(std::ostream &os,Opts::iterator i); |
269 | 269 |
void show(std::ostream &os,Groups::iterator i); |
270 | 270 |
void showHelp(Opts::iterator i); |
271 | 271 |
void showHelp(std::vector<OtherArg>::iterator i); |
272 | 272 |
void shortHelp(); |
273 | 273 |
void showHelp(); |
274 | 274 |
|
275 | 275 |
void unknownOpt(std::string arg); |
276 | 276 |
|
277 | 277 |
void requiresValue(std::string arg, OptType t); |
278 | 278 |
void checkMandatories(); |
279 | 279 |
|
280 | 280 |
///Start the parsing process |
281 | 281 |
ArgParser &parse(); |
282 | 282 |
|
283 | 283 |
/// Synonym for parse() |
284 | 284 |
ArgParser &run() |
285 | 285 |
{ |
286 | 286 |
return parse(); |
287 | 287 |
} |
288 | 288 |
|
289 | 289 |
///Check if an opion has been given to the command. |
290 | 290 |
bool given(std::string op) |
291 | 291 |
{ |
292 | 292 |
Opts::iterator i = _opts.find(op); |
293 | 293 |
return i!=_opts.end()?i->second.set:false; |
294 | 294 |
} |
295 | 295 |
|
296 | 296 |
|
297 | 297 |
///Magic type for operator[] |
298 | 298 |
|
299 | 299 |
///This is the type of the return value of ArgParser::operator[](). |
300 | 300 |
///It automatically converts to \c int, \c double, \c bool or |
301 | 301 |
///\c std::string if the type of the option matches, otherwise it |
302 | 302 |
///throws an exception (i.e. it performs runtime type checking). |
303 | 303 |
class RefType |
304 | 304 |
{ |
305 | 305 |
ArgParser &_parser; |
306 | 306 |
std::string _name; |
307 | 307 |
public: |
308 | 308 |
///\e |
309 | 309 |
RefType(ArgParser &p,const std::string &n) :_parser(p),_name(n) {} |
310 | 310 |
///\e |
311 | 311 |
operator bool() |
312 | 312 |
{ |
313 | 313 |
Opts::iterator i = _parser._opts.find(_name); |
314 | 314 |
LEMON_ASSERT(i!=_parser._opts.end(), |
315 | 315 |
std::string()+"Unkown option: '"+_name+"'"); |
316 | 316 |
LEMON_ASSERT(i->second.type==ArgParser::BOOL, |
317 | 317 |
std::string()+"'"+_name+"' is a bool option"); |
318 | 318 |
return *(i->second.bool_p); |
319 | 319 |
} |
320 | 320 |
///\e |
321 | 321 |
operator std::string() |
322 | 322 |
{ |
323 | 323 |
Opts::iterator i = _parser._opts.find(_name); |
324 | 324 |
LEMON_ASSERT(i!=_parser._opts.end(), |
325 | 325 |
std::string()+"Unkown option: '"+_name+"'"); |
326 | 326 |
LEMON_ASSERT(i->second.type==ArgParser::STRING, |
327 | 327 |
std::string()+"'"+_name+"' is a string option"); |
328 | 328 |
return *(i->second.string_p); |
329 | 329 |
} |
330 | 330 |
///\e |
331 | 331 |
operator double() |
332 | 332 |
{ |
333 | 333 |
Opts::iterator i = _parser._opts.find(_name); |
334 | 334 |
LEMON_ASSERT(i!=_parser._opts.end(), |
335 | 335 |
std::string()+"Unkown option: '"+_name+"'"); |
336 | 336 |
LEMON_ASSERT(i->second.type==ArgParser::DOUBLE || |
337 | 337 |
i->second.type==ArgParser::INTEGER, |
338 | 338 |
std::string()+"'"+_name+"' is a floating point option"); |
339 | 339 |
return i->second.type==ArgParser::DOUBLE ? |
340 | 340 |
*(i->second.double_p) : *(i->second.int_p); |
341 | 341 |
} |
342 | 342 |
///\e |
343 | 343 |
operator int() |
344 | 344 |
{ |
345 | 345 |
Opts::iterator i = _parser._opts.find(_name); |
346 | 346 |
LEMON_ASSERT(i!=_parser._opts.end(), |
347 | 347 |
std::string()+"Unkown option: '"+_name+"'"); |
348 | 348 |
LEMON_ASSERT(i->second.type==ArgParser::INTEGER, |
349 | 349 |
std::string()+"'"+_name+"' is an integer option"); |
350 | 350 |
return *(i->second.int_p); |
351 | 351 |
} |
352 | 352 |
|
353 | 353 |
}; |
354 | 354 |
|
355 | 355 |
///Give back the value of an option |
356 | 356 |
|
357 | 357 |
///Give back the value of an option. |
358 | 358 |
///\sa RefType |
359 | 359 |
RefType operator[](const std::string &n) |
360 | 360 |
{ |
361 | 361 |
return RefType(*this, n); |
362 | 362 |
} |
363 | 363 |
|
364 | 364 |
}; |
365 | 365 |
} |
366 | 366 |
|
367 | 367 |
|
368 | 368 |
|
369 | 369 |
#endif // LEMON_MAIN_PARAMS |
1 | 1 |
/* -*- C++ -*- |
2 | 2 |
* |
3 | 3 |
* This file is a part of LEMON, a generic C++ optimization library |
4 | 4 |
* |
5 | 5 |
* Copyright (C) 2003-2008 |
6 | 6 |
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport |
7 | 7 |
* (Egervary Research Group on Combinatorial Optimization, EGRES). |
8 | 8 |
* |
9 | 9 |
* Permission to use, modify and distribute this software is granted |
10 | 10 |
* provided that this copyright notice appears in all copies. For |
11 | 11 |
* precise terms see the accompanying LICENSE file. |
12 | 12 |
* |
13 | 13 |
* This software is provided "AS IS" with no warranty of any kind, |
14 | 14 |
* express or implied, and with no claim as to its suitability for any |
15 | 15 |
* purpose. |
16 | 16 |
* |
17 | 17 |
*/ |
18 | 18 |
|
19 | 19 |
#ifndef LEMON_ERROR_H |
20 | 20 |
#define LEMON_ERROR_H |
21 | 21 |
|
22 | 22 |
/// \ingroup exceptions |
23 | 23 |
/// \file |
24 | 24 |
/// \brief Basic exception classes and error handling. |
25 | 25 |
|
26 | 26 |
#include <exception> |
27 | 27 |
#include <string> |
28 | 28 |
#include <sstream> |
29 | 29 |
#include <iostream> |
30 | 30 |
#include <cstdlib> |
31 | 31 |
#include <memory> |
32 | 32 |
|
33 | 33 |
namespace lemon { |
34 | 34 |
|
35 | 35 |
/// \addtogroup exceptions |
36 | 36 |
/// @{ |
37 | 37 |
|
38 | 38 |
/// \brief Exception safe wrapper class. |
39 | 39 |
/// |
40 | 40 |
/// Exception safe wrapper class to implement the members of exceptions. |
41 | 41 |
template <typename _Type> |
42 | 42 |
class ExceptionMember { |
43 | 43 |
public: |
44 | 44 |
typedef _Type Type; |
45 | 45 |
|
46 | 46 |
ExceptionMember() throw() { |
47 | 47 |
try { |
48 | 48 |
ptr.reset(new Type()); |
49 | 49 |
} catch (...) {} |
50 | 50 |
} |
51 | 51 |
|
52 | 52 |
ExceptionMember(const Type& type) throw() { |
53 | 53 |
try { |
54 | 54 |
ptr.reset(new Type()); |
55 | 55 |
if (ptr.get() == 0) return; |
56 | 56 |
*ptr = type; |
57 | 57 |
} catch (...) {} |
58 | 58 |
} |
59 | 59 |
|
60 | 60 |
ExceptionMember(const ExceptionMember& copy) throw() { |
61 | 61 |
try { |
62 | 62 |
if (!copy.valid()) return; |
63 | 63 |
ptr.reset(new Type()); |
64 | 64 |
if (ptr.get() == 0) return; |
65 | 65 |
*ptr = copy.get(); |
66 | 66 |
} catch (...) {} |
67 | 67 |
} |
68 | 68 |
|
69 | 69 |
ExceptionMember& operator=(const ExceptionMember& copy) throw() { |
70 | 70 |
if (ptr.get() == 0) return; |
71 | 71 |
try { |
72 | 72 |
if (!copy.valid()) return; |
73 | 73 |
*ptr = copy.get(); |
74 | 74 |
} catch (...) {} |
75 | 75 |
} |
76 | 76 |
|
77 | 77 |
void set(const Type& type) throw() { |
78 | 78 |
if (ptr.get() == 0) return; |
79 | 79 |
try { |
80 | 80 |
*ptr = type; |
81 | 81 |
} catch (...) {} |
82 | 82 |
} |
83 | 83 |
|
84 | 84 |
const Type& get() const { |
85 | 85 |
return *ptr; |
86 | 86 |
} |
87 | 87 |
|
88 | 88 |
bool valid() const throw() { |
89 | 89 |
return ptr.get() != 0; |
90 | 90 |
} |
91 | 91 |
|
92 | 92 |
private: |
93 | 93 |
std::auto_ptr<_Type> ptr; |
94 | 94 |
}; |
95 | 95 |
|
96 |
/// Exception-safe convenient |
|
96 |
/// Exception-safe convenient error message builder class. |
|
97 | 97 |
|
98 | 98 |
/// Helper class which provides a convenient ostream-like (operator << |
99 | 99 |
/// based) interface to create a string message. Mostly useful in |
100 | 100 |
/// exception classes (therefore the name). |
101 | 101 |
class ErrorMessage { |
102 | 102 |
protected: |
103 | 103 |
///\e |
104 | 104 |
|
105 | 105 |
///\todo The good solution is boost::shared_ptr... |
106 | 106 |
/// |
107 | 107 |
mutable std::auto_ptr<std::ostringstream> buf; |
108 | 108 |
|
109 | 109 |
///\e |
110 | 110 |
bool init() throw() { |
111 | 111 |
try { |
112 | 112 |
buf.reset(new std::ostringstream); |
113 | 113 |
} |
114 | 114 |
catch(...) { |
115 | 115 |
buf.reset(); |
116 | 116 |
} |
117 | 117 |
return buf.get(); |
118 | 118 |
} |
119 | 119 |
|
120 | 120 |
public: |
121 | 121 |
|
122 | 122 |
///\e |
123 | 123 |
ErrorMessage() throw() { init(); } |
124 | 124 |
|
125 | 125 |
ErrorMessage(const ErrorMessage& em) throw() : buf(em.buf) { } |
126 | 126 |
|
127 | 127 |
///\e |
128 | 128 |
ErrorMessage(const char *msg) throw() { |
129 | 129 |
init(); |
130 | 130 |
*this << msg; |
131 | 131 |
} |
132 | 132 |
|
133 | 133 |
///\e |
134 | 134 |
ErrorMessage(const std::string &msg) throw() { |
135 | 135 |
init(); |
136 | 136 |
*this << msg; |
137 | 137 |
} |
138 | 138 |
|
139 | 139 |
///\e |
140 | 140 |
template <typename T> |
141 | 141 |
ErrorMessage& operator<<(const T &t) throw() { |
142 | 142 |
if( ! buf.get() ) return *this; |
143 | 143 |
|
144 | 144 |
try { |
145 | 145 |
*buf << t; |
146 | 146 |
} |
147 | 147 |
catch(...) { |
148 | 148 |
buf.reset(); |
149 | 149 |
} |
150 | 150 |
return *this; |
151 | 151 |
} |
152 | 152 |
|
153 | 153 |
///\e |
154 | 154 |
const char* message() throw() { |
155 | 155 |
if( ! buf.get() ) return 0; |
156 | 156 |
|
157 | 157 |
const char* mes = 0; |
158 | 158 |
try { |
159 | 159 |
mes = buf->str().c_str(); |
160 | 160 |
} |
161 | 161 |
catch(...) {} |
162 | 162 |
return mes; |
163 | 163 |
} |
164 | 164 |
|
165 | 165 |
}; |
166 | 166 |
|
167 | 167 |
/// Generic exception class. |
168 | 168 |
|
169 | 169 |
/// Base class for exceptions used in LEMON. |
170 | 170 |
/// |
171 | 171 |
class Exception : public std::exception { |
172 | 172 |
public: |
173 | 173 |
///\e |
174 | 174 |
Exception() {} |
175 | 175 |
///\e |
176 | 176 |
virtual ~Exception() throw() {} |
177 | 177 |
///\e |
178 | 178 |
virtual const char* what() const throw() { |
179 | 179 |
return "lemon::Exception"; |
180 | 180 |
} |
181 | 181 |
}; |
182 | 182 |
|
183 | 183 |
/// One of the two main subclasses of \ref Exception. |
184 | 184 |
|
185 | 185 |
/// Logic errors represent problems in the internal logic of a program; |
186 | 186 |
/// in theory, these are preventable, and even detectable before the |
187 | 187 |
/// program runs (e.g. violations of class invariants). |
188 | 188 |
/// |
189 | 189 |
/// A typical example for this is \ref UninitializedParameter. |
190 | 190 |
class LogicError : public Exception { |
191 | 191 |
public: |
192 | 192 |
virtual const char* what() const throw() { |
193 | 193 |
return "lemon::LogicError"; |
194 | 194 |
} |
195 | 195 |
}; |
196 | 196 |
|
197 | 197 |
/// \ref Exception for uninitialized parameters. |
198 | 198 |
|
199 | 199 |
/// This error represents problems in the initialization |
200 | 200 |
/// of the parameters of the algorithms. |
201 | 201 |
class UninitializedParameter : public LogicError { |
202 | 202 |
public: |
203 | 203 |
virtual const char* what() const throw() { |
204 | 204 |
return "lemon::UninitializedParameter"; |
205 | 205 |
} |
206 | 206 |
}; |
207 | 207 |
|
208 | 208 |
|
209 | 209 |
/// One of the two main subclasses of \ref Exception. |
210 | 210 |
|
211 | 211 |
/// Runtime errors represent problems outside the scope of a program; |
212 | 212 |
/// they cannot be easily predicted and can generally only be caught |
213 | 213 |
/// as the program executes. |
214 | 214 |
class RuntimeError : public Exception { |
215 | 215 |
public: |
216 | 216 |
virtual const char* what() const throw() { |
217 | 217 |
return "lemon::RuntimeError"; |
218 | 218 |
} |
219 | 219 |
}; |
220 | 220 |
|
221 | 221 |
///\e |
222 | 222 |
class RangeError : public RuntimeError { |
223 | 223 |
public: |
224 | 224 |
virtual const char* what() const throw() { |
225 | 225 |
return "lemon::RangeError"; |
226 | 226 |
} |
227 | 227 |
}; |
228 | 228 |
|
229 | 229 |
///\e |
230 | 230 |
class IoError : public RuntimeError { |
231 | 231 |
public: |
232 | 232 |
virtual const char* what() const throw() { |
233 | 233 |
return "lemon::IoError"; |
234 | 234 |
} |
235 | 235 |
}; |
236 | 236 |
|
237 | 237 |
///\e |
238 | 238 |
class DataFormatError : public IoError { |
239 | 239 |
protected: |
240 | 240 |
ExceptionMember<std::string> _message; |
241 | 241 |
ExceptionMember<std::string> _file; |
242 | 242 |
int _line; |
243 | 243 |
|
244 | 244 |
mutable ExceptionMember<std::string> _message_holder; |
245 | 245 |
public: |
246 | 246 |
|
247 | 247 |
DataFormatError(const DataFormatError &dfe) : |
248 | 248 |
IoError(dfe), _message(dfe._message), _file(dfe._file), |
249 | 249 |
_line(dfe._line) {} |
250 | 250 |
|
251 | 251 |
///\e |
252 | 252 |
explicit DataFormatError(const char *the_message) |
253 | 253 |
: _message(the_message), _line(0) {} |
254 | 254 |
|
255 | 255 |
///\e |
256 | 256 |
DataFormatError(const std::string &file_name, int line_num, |
257 | 257 |
const char *the_message) |
258 | 258 |
: _message(the_message), _line(line_num) { file(file_name); } |
259 | 259 |
|
260 | 260 |
///\e |
261 | 261 |
void line(int ln) { _line = ln; } |
262 | 262 |
///\e |
263 | 263 |
void message(const std::string& msg) { _message.set(msg); } |
264 | 264 |
///\e |
265 | 265 |
void file(const std::string &fl) { _file.set(fl); } |
266 | 266 |
|
267 | 267 |
///\e |
268 | 268 |
int line() const { return _line; } |
269 | 269 |
///\e |
270 | 270 |
const char* message() const { |
271 | 271 |
if (_message.valid() && !_message.get().empty()) { |
272 | 272 |
return _message.get().c_str(); |
273 | 273 |
} else { |
274 | 274 |
return 0; |
275 | 275 |
} |
276 | 276 |
} |
277 | 277 |
|
278 | 278 |
/// \brief Returns the filename. |
279 | 279 |
/// |
280 | 280 |
/// Returns \e null if the filename was not specified. |
281 | 281 |
const char* file() const { |
282 | 282 |
if (_file.valid() && !_file.get().empty()) { |
283 | 283 |
return _file.get().c_str(); |
284 | 284 |
} else { |
285 | 285 |
return 0; |
286 | 286 |
} |
287 | 287 |
} |
288 | 288 |
|
289 | 289 |
///\e |
290 | 290 |
virtual const char* what() const throw() { |
291 | 291 |
try { |
292 | 292 |
std::ostringstream ostr; |
293 | 293 |
ostr << "lemon:DataFormatError" << ": "; |
294 | 294 |
if (message()) ostr << message(); |
295 | 295 |
if( file() || line() != 0 ) { |
296 | 296 |
ostr << " ("; |
297 | 297 |
if( file() ) ostr << "in file '" << file() << "'"; |
298 | 298 |
if( file() && line() != 0 ) ostr << " "; |
299 | 299 |
if( line() != 0 ) ostr << "at line " << line(); |
300 | 300 |
ostr << ")"; |
301 | 301 |
} |
302 | 302 |
_message_holder.set(ostr.str()); |
303 | 303 |
} |
304 | 304 |
catch (...) {} |
305 | 305 |
if( _message_holder.valid()) return _message_holder.get().c_str(); |
306 | 306 |
return "lemon:DataFormatError"; |
307 | 307 |
} |
308 | 308 |
|
309 | 309 |
virtual ~DataFormatError() throw() {} |
310 | 310 |
}; |
311 | 311 |
|
312 | 312 |
///\e |
313 | 313 |
class FileOpenError : public IoError { |
314 | 314 |
protected: |
315 | 315 |
ExceptionMember<std::string> _file; |
316 | 316 |
|
317 | 317 |
mutable ExceptionMember<std::string> _message_holder; |
318 | 318 |
public: |
319 | 319 |
|
320 | 320 |
FileOpenError(const FileOpenError &foe) : |
321 | 321 |
IoError(foe), _file(foe._file) {} |
322 | 322 |
|
323 | 323 |
///\e |
324 | 324 |
explicit FileOpenError(const std::string& fl) |
325 | 325 |
: _file(fl) {} |
326 | 326 |
|
327 | 327 |
|
328 | 328 |
///\e |
329 | 329 |
void file(const std::string &fl) { _file.set(fl); } |
330 | 330 |
|
331 | 331 |
/// \brief Returns the filename. |
332 | 332 |
/// |
333 | 333 |
/// Returns \e null if the filename was not specified. |
334 | 334 |
const char* file() const { |
335 | 335 |
if (_file.valid() && !_file.get().empty()) { |
336 | 336 |
return _file.get().c_str(); |
337 | 337 |
} else { |
338 | 338 |
return 0; |
339 | 339 |
} |
340 | 340 |
} |
341 | 341 |
|
342 | 342 |
///\e |
343 | 343 |
virtual const char* what() const throw() { |
344 | 344 |
try { |
345 | 345 |
std::ostringstream ostr; |
346 | 346 |
ostr << "lemon::FileOpenError" << ": "; |
347 | 347 |
ostr << "Cannot open file - " << file(); |
348 | 348 |
_message_holder.set(ostr.str()); |
349 | 349 |
} |
350 | 350 |
catch (...) {} |
351 | 351 |
if( _message_holder.valid()) return _message_holder.get().c_str(); |
352 | 352 |
return "lemon::FileOpenError"; |
353 | 353 |
} |
354 | 354 |
virtual ~FileOpenError() throw() {} |
355 | 355 |
}; |
356 | 356 |
|
357 | 357 |
class IoParameterError : public IoError { |
358 | 358 |
protected: |
359 | 359 |
ExceptionMember<std::string> _message; |
360 | 360 |
ExceptionMember<std::string> _file; |
361 | 361 |
|
362 | 362 |
mutable ExceptionMember<std::string> _message_holder; |
363 | 363 |
public: |
364 | 364 |
|
365 | 365 |
IoParameterError(const IoParameterError &ile) : |
366 | 366 |
IoError(ile), _message(ile._message), _file(ile._file) {} |
367 | 367 |
|
368 | 368 |
///\e |
369 | 369 |
explicit IoParameterError(const char *the_message) |
370 | 370 |
: _message(the_message) {} |
371 | 371 |
|
372 | 372 |
///\e |
373 | 373 |
IoParameterError(const char *file_name, const char *the_message) |
374 | 374 |
: _message(the_message), _file(file_name) {} |
375 | 375 |
|
376 | 376 |
///\e |
377 | 377 |
void message(const std::string& msg) { _message.set(msg); } |
378 | 378 |
///\e |
379 | 379 |
void file(const std::string &fl) { _file.set(fl); } |
380 | 380 |
|
381 | 381 |
///\e |
382 | 382 |
const char* message() const { |
383 | 383 |
if (_message.valid()) { |
384 | 384 |
return _message.get().c_str(); |
385 | 385 |
} else { |
386 | 386 |
return 0; |
387 | 387 |
} |
388 | 388 |
} |
389 | 389 |
|
390 | 390 |
/// \brief Returns the filename. |
391 | 391 |
/// |
392 | 392 |
/// Returns \c 0 if the filename was not specified. |
393 | 393 |
const char* file() const { |
394 | 394 |
if (_file.valid()) { |
395 | 395 |
return _file.get().c_str(); |
396 | 396 |
} else { |
397 | 397 |
return 0; |
398 | 398 |
} |
399 | 399 |
} |
400 | 400 |
|
401 | 401 |
///\e |
402 | 402 |
virtual const char* what() const throw() { |
403 | 403 |
try { |
404 | 404 |
std::ostringstream ostr; |
405 | 405 |
if (message()) ostr << message(); |
406 | 406 |
if (file()) ostr << "(when reading file '" << file() << "')"; |
407 | 407 |
_message_holder.set(ostr.str()); |
408 | 408 |
} |
409 | 409 |
catch (...) {} |
410 | 410 |
if( _message_holder.valid() ) return _message_holder.get().c_str(); |
411 | 411 |
return "lemon:IoParameterError"; |
412 | 412 |
} |
413 | 413 |
virtual ~IoParameterError() throw() {} |
414 | 414 |
}; |
415 | 415 |
|
416 |
|
|
417 |
///\e |
|
418 |
class AssertionFailedError : public LogicError { |
|
419 |
protected: |
|
420 |
const char *assertion; |
|
421 |
const char *file; |
|
422 |
int line; |
|
423 |
const char *function; |
|
424 |
const char *message; |
|
425 |
|
|
426 |
mutable ExceptionMember<std::string> _message_holder; |
|
427 |
public: |
|
428 |
///\e |
|
429 |
AssertionFailedError(const char *_file, int _line, const char *func, |
|
430 |
const char *msg, const char *_assertion = 0) : |
|
431 |
assertion(_assertion), file(_file), line(_line), function(func), |
|
432 |
message(msg) {} |
|
433 |
|
|
434 |
///\e |
|
435 |
const char* get_assertion() const { return assertion; } |
|
436 |
///\e |
|
437 |
const char* get_message() const { return message; } |
|
438 |
///\e |
|
439 |
const char* get_file() const { return file; } |
|
440 |
///\e |
|
441 |
const char* get_function() const { return function; } |
|
442 |
///\e |
|
443 |
int get_line() const { return line; } |
|
444 |
|
|
445 |
|
|
446 |
virtual const char* what() const throw() { |
|
447 |
try { |
|
448 |
std::ostringstream ostr; |
|
449 |
ostr << file << ":" << line << ": "; |
|
450 |
if( function ) |
|
451 |
ostr << function << ": "; |
|
452 |
ostr << message; |
|
453 |
if( assertion ) |
|
454 |
ostr << " (assertion '" << assertion << "' failed)"; |
|
455 |
_message_holder.set(ostr.str()); |
|
456 |
return ostr.str().c_str(); |
|
457 |
} |
|
458 |
catch(...) {} |
|
459 |
if( _message_holder.valid() ) return _message_holder.get().c_str(); |
|
460 |
return "lemon::AssertionFailedError"; |
|
461 |
} |
|
462 |
virtual ~AssertionFailedError() throw() {} |
|
463 |
}; |
|
464 |
|
|
465 |
|
|
466 |
/**************** Macros ****************/ |
|
467 |
|
|
468 |
|
|
469 |
template <typename Exception> |
|
470 |
inline void assert_fail(const char *file, int line, |
|
471 |
const char *func, |
|
472 |
Exception exception, |
|
473 |
const char *assertion = 0, |
|
474 |
bool do_abort=true) |
|
475 |
{ |
|
476 |
using namespace std; |
|
477 |
cerr << file << ":" << line << ": "; |
|
478 |
if (func) |
|
479 |
cerr << func << ": "; |
|
480 |
cerr << exception.what(); |
|
481 |
if (assertion) |
|
482 |
cerr << " (assertion '" << assertion << "' failed)"; |
|
483 |
cerr << endl; |
|
484 |
if (do_abort) |
|
485 |
abort(); |
|
486 |
} |
|
487 |
|
|
488 |
template <> |
|
489 |
inline void assert_fail<const char *>(const char *file, int line, |
|
490 |
const char *func, |
|
491 |
const char *message, |
|
492 |
const char *assertion, |
|
493 |
bool do_abort) |
|
494 |
{ |
|
495 |
using namespace std; |
|
496 |
cerr << file << ":" << line << ": "; |
|
497 |
if (func) |
|
498 |
cerr << func << ": "; |
|
499 |
cerr << message; |
|
500 |
if (assertion) |
|
501 |
cerr << " (assertion '" << assertion << "' failed)"; |
|
502 |
cerr << endl; |
|
503 |
if (do_abort) |
|
504 |
abort(); |
|
505 |
} |
|
506 |
|
|
507 |
template <> |
|
508 |
inline void assert_fail<std::string>(const char *file, int line, |
|
509 |
const char *func, |
|
510 |
std::string message, |
|
511 |
const char *assertion, |
|
512 |
bool do_abort) |
|
513 |
{ |
|
514 |
assert_fail(file, line, func, message.c_str(), assertion, do_abort); |
|
515 |
} |
|
516 |
|
|
517 |
template <typename Exception> |
|
518 |
inline void assert_fail_failure(const char *file, int line, const char *func, |
|
519 |
Exception exception, |
|
520 |
const char *assertion = 0, |
|
521 |
bool = true) |
|
522 |
{ |
|
523 |
throw AssertionFailedError(file, line, func, exception.what(), assertion); |
|
524 |
} |
|
525 |
|
|
526 |
template <> |
|
527 |
inline void assert_fail_failure<const char *>(const char *file, int line, |
|
528 |
const char *func, |
|
529 |
const char *message, |
|
530 |
const char *assertion, |
|
531 |
bool) |
|
532 |
{ |
|
533 |
throw AssertionFailedError(file, line, func, message, assertion); |
|
534 |
} |
|
535 |
|
|
536 |
template <> |
|
537 |
inline void assert_fail_failure<std::string>(const char *file, int line, |
|
538 |
const char *func, |
|
539 |
std::string message, |
|
540 |
const char *assertion, |
|
541 |
bool) |
|
542 |
{ |
|
543 |
assert_fail_failure(file, line, func, message.c_str(), assertion, true); |
|
544 |
} |
|
545 |
|
|
546 |
template <typename Exception> |
|
547 |
inline void assert_fail_exception(const char *file, int line, const char *func, |
|
548 |
Exception exception, |
|
549 |
const char *assertion = 0, bool = true) |
|
550 |
{ |
|
551 |
throw exception; |
|
552 |
} |
|
553 |
|
|
554 |
template <> |
|
555 |
inline void assert_fail_exception<const char *>(const char *file, int line, |
|
556 |
const char *func, |
|
557 |
const char *message, |
|
558 |
const char *assertion, |
|
559 |
bool) |
|
560 |
{ |
|
561 |
throw AssertionFailedError(file, line, func, message, assertion); |
|
562 |
} |
|
563 |
|
|
564 |
template <> |
|
565 |
inline void assert_fail_exception<std::string>(const char *file, int line, |
|
566 |
const char *func, |
|
567 |
std::string message, |
|
568 |
const char *assertion, |
|
569 |
bool) |
|
570 |
{ |
|
571 |
assert_fail_exception(file, line, func, message.c_str(), assertion, true); |
|
572 |
} |
|
573 |
|
|
574 | 416 |
/// @} |
575 | 417 |
|
576 | 418 |
} |
419 |
|
|
577 | 420 |
#endif // LEMON_ERROR_H |
578 |
|
|
579 |
#undef LEMON_ASSERT |
|
580 |
#undef LEMON_FIXME |
|
581 |
|
|
582 |
#ifdef LEMON_ENABLE_ASSERTS |
|
583 |
# define LEMON_ASSERT_ABORT |
|
584 |
#endif |
|
585 |
|
|
586 |
#ifndef LEMON_ASSERT_DO_ABORT |
|
587 |
# define LEMON_ASSERT_DO_ABORT 1 |
|
588 |
#endif |
|
589 |
|
|
590 |
#ifndef LEMON_ASSERT_HANDLER |
|
591 |
# if defined LEMON_ASSERT_EXCEPTION |
|
592 |
# define LEMON_ASSERT_HANDLER ::lemon::assert_fail_exception |
|
593 |
# elif defined LEMON_ASSERT_FAILURE |
|
594 |
# define LEMON_ASSERT_HANDLER ::lemon::assert_fail_failure |
|
595 |
# elif defined LEMON_ASSERT_ABORT |
|
596 |
# define LEMON_ASSERT_HANDLER ::lemon::assert_fail |
|
597 |
# else |
|
598 |
# define LEMON_DISABLE_ASSERTS |
|
599 |
# endif |
|
600 |
#endif |
|
601 |
|
|
602 |
#ifdef DOXYGEN |
|
603 |
|
|
604 |
/// \brief Macro for assertions with customizable message |
|
605 |
/// |
|
606 |
/// Macro for assertions with customizable message. |
|
607 |
/// |
|
608 |
/// The assertions are disabled in the default behaviour. You can |
|
609 |
/// enable the assertions with the |
|
610 |
/// \code |
|
611 |
/// #define LEMON_ENABLE_ASSERTS |
|
612 |
/// \endcode |
|
613 |
/// Then an assert |
|
614 |
/// provides a log on the standard error about the assertion and aborts |
|
615 |
/// the program if LEMON_ASSERT_DO_ABORT is also defined (otherwise the |
|
616 |
/// program keeps on running). |
|
617 |
/// By defining LEMON_ASSERT_FAILURE or |
|
618 |
/// LEMON_ASSERT_EXCEPTION, you can set other behaviour to the |
|
619 |
/// assertions. In case LEMON_ASSERT_FAILURE is given, LEMON_ASSERT |
|
620 |
/// will always throw an \c AssertionFailedError exception with |
|
621 |
/// the \c msg error message. By using |
|
622 |
/// LEMON_ASSERT_EXCEPTION, one can define an arbitrary exception to be thrown. |
|
623 |
/// |
|
624 |
/// The LEMON_ASSERT macro should be called with the \c exp parameter |
|
625 |
/// which should be an expression convertible to bool. If the given |
|
626 |
/// parameter is false the assertion is raised and one of the assertion |
|
627 |
/// behaviour will be activated. The \c msg should be either a const |
|
628 |
/// char* message or an exception. When the \c msg is an exception the |
|
629 |
/// \ref lemon::Exception::what() "what()" function is called to retrieve and |
|
630 |
/// display the error message. |
|
631 |
/// |
|
632 |
/// \todo We should provide some way to reset to the default behaviour, |
|
633 |
/// shouldn't we? |
|
634 |
/// |
|
635 |
/// \todo This whole 'assert' business should be placed in a separate |
|
636 |
/// include file. The boost assert is not guarded by header sentries |
|
637 |
/// which may help to change the behaviour of the assertions in |
|
638 |
/// the files. |
|
639 |
/// |
|
640 |
/// \todo __PRETTY_FUNCTION__ should be replaced by something |
|
641 |
/// compiler-independent, like BOOST_CURRENT_FUNCTION |
|
642 |
|
|
643 |
# define LEMON_ASSERT(exp, msg) \ |
|
644 |
(static_cast<void> (!!(exp) ? 0 : ( \ |
|
645 |
LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \ |
|
646 |
__PRETTY_FUNCTION__, \ |
|
647 |
msg, #exp, LEMON_ASSERT_DO_ABORT), 0))) |
|
648 |
|
|
649 |
#else |
|
650 |
# if defined LEMON_DISABLE_ASSERTS |
|
651 |
|
|
652 |
# define LEMON_ASSERT(exp, msg) (static_cast<void> (0)) |
|
653 |
|
|
654 |
# else |
|
655 |
# define LEMON_ASSERT(exp, msg) \ |
|
656 |
(static_cast<void> (!!(exp) ? 0 : ( \ |
|
657 |
LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \ |
|
658 |
__PRETTY_FUNCTION__, \ |
|
659 |
msg, #exp, LEMON_ASSERT_DO_ABORT), 0))) |
|
660 |
# endif |
|
661 |
#endif |
|
662 |
|
|
663 |
/** |
|
664 |
* \brief Macro for mark not yet implemented features. |
|
665 |
* |
|
666 |
* \todo Is this the right place for this? It should be used only in |
|
667 |
* modules under development. |
|
668 |
* |
|
669 |
* \todo __PRETTY_FUNCTION__ should be replaced by something |
|
670 |
* compiler-independent, like BOOST_CURRENT_FUNCTION |
|
671 |
*/ |
|
672 |
|
|
673 |
#define LEMON_FIXME(msg) \ |
|
674 |
(LEMON_ASSERT_HANDLER(__FILE__, __LINE__, __PRETTY_FUNCTION__, \ |
|
675 |
"FIXME: " msg)) |
1 | 1 |
EXTRA_DIST += \ |
2 | 2 |
test/Makefile |
3 | 3 |
|
4 | 4 |
noinst_HEADERS += \ |
5 | 5 |
test/digraph_test.h \ |
6 | 6 |
test/heap_test.h \ |
7 | 7 |
test/map_test.h \ |
8 | 8 |
test/test_tools.h |
9 | 9 |
|
10 | 10 |
check_PROGRAMS += \ |
11 | 11 |
test/bfs_test \ |
12 | 12 |
test/dfs_test \ |
13 | 13 |
test/digraph_test \ |
14 | 14 |
test/dim_test \ |
15 |
test/error_test \ |
|
15 | 16 |
test/graph_test \ |
16 | 17 |
test/kruskal_test \ |
17 | 18 |
test/maps_test \ |
18 | 19 |
test/random_test \ |
19 | 20 |
test/path_test \ |
20 | 21 |
test/test_tools_fail \ |
21 | 22 |
test/test_tools_pass \ |
22 | 23 |
test/unionfind_test |
23 | 24 |
|
24 | 25 |
TESTS += $(check_PROGRAMS) |
25 | 26 |
XFAIL_TESTS += test/test_tools_fail$(EXEEXT) |
26 | 27 |
|
27 | 28 |
test_bfs_test_SOURCES = test/bfs_test.cc |
28 | 29 |
test_dfs_test_SOURCES = test/dfs_test.cc |
29 | 30 |
test_digraph_test_SOURCES = test/digraph_test.cc |
30 | 31 |
test_dim_test_SOURCES = test/dim_test.cc |
31 |
|
|
32 |
test_error_test_SOURCES = test/error_test.cc |
|
32 | 33 |
test_graph_test_SOURCES = test/graph_test.cc |
33 | 34 |
# test_heap_test_SOURCES = test/heap_test.cc |
34 | 35 |
test_kruskal_test_SOURCES = test/kruskal_test.cc |
35 | 36 |
test_maps_test_SOURCES = test/maps_test.cc |
36 | 37 |
test_path_test_SOURCES = test/path_test.cc |
37 | 38 |
test_random_test_SOURCES = test/random_test.cc |
38 | 39 |
test_test_tools_fail_SOURCES = test/test_tools_fail.cc |
39 | 40 |
test_test_tools_pass_SOURCES = test/test_tools_pass.cc |
40 | 41 |
test_unionfind_test_SOURCES = test/unionfind_test.cc |
1 | 1 |
/* -*- C++ -*- |
2 | 2 |
* |
3 | 3 |
* This file is a part of LEMON, a generic C++ optimization library |
4 | 4 |
* |
5 | 5 |
* Copyright (C) 2003-2008 |
6 | 6 |
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport |
7 | 7 |
* (Egervary Research Group on Combinatorial Optimization, EGRES). |
8 | 8 |
* |
9 | 9 |
* Permission to use, modify and distribute this software is granted |
10 | 10 |
* provided that this copyright notice appears in all copies. For |
11 | 11 |
* precise terms see the accompanying LICENSE file. |
12 | 12 |
* |
13 | 13 |
* This software is provided "AS IS" with no warranty of any kind, |
14 | 14 |
* express or implied, and with no claim as to its suitability for any |
15 | 15 |
* purpose. |
16 | 16 |
* |
17 | 17 |
*/ |
18 | 18 |
|
19 | 19 |
#include <iostream> |
20 | 20 |
|
21 | 21 |
#include <lemon/error.h> |
22 | 22 |
#include "test_tools.h" |
23 | 23 |
|
24 | 24 |
using namespace lemon; |
25 |
using std::cout; |
|
26 |
using std::endl; |
|
27 | 25 |
|
28 |
void faulty_fn() { |
|
29 |
fault("This is a fault message"); |
|
26 |
#ifdef LEMON_ENABLE_ASSERTS |
|
27 |
#undef LEMON_ENABLE_ASSERTS |
|
28 |
#endif |
|
29 |
|
|
30 |
#ifdef LEMON_DISABLE_ASSERTS |
|
31 |
#undef LEMON_DISABLE_ASSERTS |
|
32 |
#endif |
|
33 |
|
|
34 |
//checking disabled asserts |
|
35 |
#define LEMON_DISABLE_ASSERTS |
|
36 |
#include <lemon/assert.h> |
|
37 |
|
|
38 |
void no_assertion_text_disable() { |
|
39 |
LEMON_ASSERT(true, "This is a fault message"); |
|
30 | 40 |
} |
31 | 41 |
|
32 |
void exception_fn() { |
|
33 |
throw Exception("This is a function throwing exception with some args: ") |
|
34 |
|
|
42 |
void no_assertion_exception_disable() { |
|
43 |
LEMON_ASSERT(true, Exception()); |
|
35 | 44 |
} |
36 | 45 |
|
37 |
void unfinished_fn() { |
|
38 |
LEMON_FIXME("unfinished_fn() is unfinished!"); |
|
46 |
void assertion_text_disable() { |
|
47 |
LEMON_ASSERT(false, "This is a fault message"); |
|
39 | 48 |
} |
40 | 49 |
|
50 |
void assertion_exception_disable() { |
|
51 |
LEMON_ASSERT(false, Exception()); |
|
52 |
} |
|
41 | 53 |
|
42 |
|
|
54 |
void fixme_disable() { |
|
55 |
LEMON_FIXME("fixme_disable() is fixme!"); |
|
56 |
} |
|
57 |
|
|
58 |
void check_assertion_disable() { |
|
59 |
no_assertion_text_disable(); |
|
60 |
no_assertion_exception_disable(); |
|
61 |
assertion_exception_disable(); |
|
62 |
assertion_text_disable(); |
|
63 |
fixme_disable(); |
|
64 |
} |
|
65 |
#undef LEMON_DISABLE_ASSERTS |
|
66 |
|
|
67 |
|
|
68 |
#define LEMON_ASSERT_ERROR |
|
69 |
#include <lemon/assert.h> |
|
70 |
|
|
71 |
void no_assertion_text_error() { |
|
72 |
LEMON_ASSERT(true, "This is a fault message"); |
|
73 |
} |
|
74 |
|
|
75 |
void no_assertion_exception_error() { |
|
76 |
LEMON_ASSERT(true, Exception()); |
|
77 |
} |
|
78 |
|
|
79 |
void assertion_text_error() { |
|
80 |
LEMON_ASSERT(false, "This is a fault message"); |
|
81 |
} |
|
82 |
|
|
83 |
void assertion_exception_error() { |
|
84 |
LEMON_ASSERT(false, Exception()); |
|
85 |
} |
|
86 |
|
|
87 |
void fixme_error() { |
|
88 |
LEMON_FIXME("fixme_error() is fixme!"); |
|
89 |
} |
|
90 |
|
|
91 |
void check_assertion_error() { |
|
92 |
no_assertion_text_error(); |
|
93 |
no_assertion_exception_error(); |
|
43 | 94 |
try { |
44 |
faulty_fn(); |
|
45 |
check(false, "A faulty function did not fail."); |
|
46 |
} |
|
47 |
catch(const Exception &e) { |
|
48 |
|
|
95 |
assertion_exception_error(); |
|
96 |
check(false, "Assertion error"); |
|
97 |
} catch (const AssertionFailedError& e) { |
|
49 | 98 |
} |
50 | 99 |
|
51 | 100 |
try { |
52 |
exception_fn(); |
|
53 |
check(false, "The function did not throw Exception."); |
|
54 |
} |
|
55 |
catch(const Exception &e) { |
|
56 |
|
|
101 |
assertion_text_error(); |
|
102 |
check(false, "Assertion error"); |
|
103 |
} catch (const AssertionFailedError& e) { |
|
57 | 104 |
} |
58 | 105 |
|
59 | 106 |
try { |
60 |
unfinished_fn(); |
|
61 |
check(false, "FIXME macro does not work."); |
|
107 |
fixme_error(); |
|
108 |
check(false, "Assertion error"); |
|
109 |
} catch (const AssertionFailedError& e) { |
|
62 | 110 |
} |
63 |
catch(const Exception &e) { |
|
64 |
cout << "Exeption = \"" << e.what() << "\" (Right behaviour)" << endl; |
|
65 | 111 |
} |
112 |
#undef LEMON_ASSERT_ERROR |
|
113 |
|
|
114 |
#define LEMON_ASSERT_EXCEPTION |
|
115 |
#include <lemon/assert.h> |
|
116 |
|
|
117 |
void no_assertion_text_exception() { |
|
118 |
LEMON_ASSERT(true, "This is a fault message"); |
|
119 |
} |
|
120 |
|
|
121 |
void no_assertion_exception_exception() { |
|
122 |
LEMON_ASSERT(true, Exception()); |
|
123 |
} |
|
124 |
|
|
125 |
void assertion_text_exception() { |
|
126 |
LEMON_ASSERT(false, "This is a fault message"); |
|
127 |
} |
|
128 |
|
|
129 |
void assertion_exception_exception() { |
|
130 |
LEMON_ASSERT(false, Exception()); |
|
131 |
} |
|
132 |
|
|
133 |
void fixme_exception() { |
|
134 |
LEMON_FIXME("fixme_exception() is fixme!"); |
|
135 |
} |
|
136 |
|
|
137 |
void check_assertion_exception() { |
|
138 |
no_assertion_text_exception(); |
|
139 |
no_assertion_exception_exception(); |
|
140 |
try { |
|
141 |
assertion_exception_exception(); |
|
142 |
check(false, "Assertion error"); |
|
143 |
} catch (const Exception& e) { |
|
144 |
} |
|
145 |
|
|
146 |
try { |
|
147 |
assertion_text_exception(); |
|
148 |
check(false, "Assertion error"); |
|
149 |
} catch (const AssertionFailedError& e) { |
|
150 |
} |
|
151 |
|
|
152 |
try { |
|
153 |
assertion_text_exception(); |
|
154 |
check(false, "Assertion error"); |
|
155 |
} catch (const AssertionFailedError& e) { |
|
156 |
} |
|
157 |
|
|
158 |
try { |
|
159 |
fixme_exception(); |
|
160 |
check(false, "Assertion error"); |
|
161 |
} catch (const AssertionFailedError& e) { |
|
162 |
} |
|
163 |
} |
|
164 |
#undef LEMON_ASSERT_EXCEPTION |
|
165 |
|
|
166 |
#define LEMON_ASSERT_LOG |
|
167 |
|
|
168 |
#include <lemon/assert.h> |
|
169 |
|
|
170 |
void no_assertion_text_log() { |
|
171 |
LEMON_ASSERT(true, "This is a fault message"); |
|
172 |
} |
|
173 |
|
|
174 |
void no_assertion_exception_log() { |
|
175 |
LEMON_ASSERT(true, Exception()); |
|
176 |
} |
|
177 |
|
|
178 |
void assertion_text_log() { |
|
179 |
LEMON_ASSERT(false, "This is a fault message"); |
|
180 |
} |
|
181 |
|
|
182 |
void assertion_exception_log() { |
|
183 |
LEMON_ASSERT(false, Exception()); |
|
184 |
} |
|
185 |
|
|
186 |
void fixme_log() { |
|
187 |
LEMON_FIXME("fixme_log() is fixme!"); |
|
188 |
} |
|
189 |
|
|
190 |
void check_assertion_log() { |
|
191 |
no_assertion_text_log(); |
|
192 |
no_assertion_exception_log(); |
|
193 |
std::cerr << "The next 3 failure messages are expected: " << std::endl; |
|
194 |
assertion_exception_log(); |
|
195 |
assertion_text_log(); |
|
196 |
fixme_log(); |
|
197 |
std::cerr << "End of expected error messages" << std::endl; |
|
198 |
} |
|
199 |
#undef LEMON_ASSERT_LOG |
|
200 |
|
|
201 |
#define LEMON_ASSERT_CUSTOM |
|
202 |
|
|
203 |
static int cnt = 0; |
|
204 |
void my_assert_handler(const char*, int, const char*, |
|
205 |
const char*, const char*) { |
|
206 |
++cnt; |
|
207 |
} |
|
208 |
|
|
209 |
void my_assert_handler(const char*, int, const char*, |
|
210 |
const std::exception&, const char*) { |
|
211 |
++cnt; |
|
212 |
} |
|
213 |
|
|
214 |
void my_assert_handler(const char*, int, const char*, |
|
215 |
const std::string&, const char*) { |
|
216 |
++cnt; |
|
217 |
} |
|
218 |
|
|
219 |
|
|
220 |
#define LEMON_CUSTOM_ASSERT_HANDLER my_assert_handler |
|
221 |
#include <lemon/assert.h> |
|
222 |
|
|
223 |
void no_assertion_text_custom() { |
|
224 |
LEMON_ASSERT(true, "This is a fault message"); |
|
225 |
} |
|
226 |
|
|
227 |
void no_assertion_exception_custom() { |
|
228 |
LEMON_ASSERT(true, Exception()); |
|
229 |
} |
|
230 |
|
|
231 |
void assertion_text_custom() { |
|
232 |
LEMON_ASSERT(false, "This is a fault message"); |
|
233 |
} |
|
234 |
|
|
235 |
void assertion_exception_custom() { |
|
236 |
LEMON_ASSERT(false, Exception()); |
|
237 |
} |
|
238 |
|
|
239 |
void fixme_custom() { |
|
240 |
LEMON_FIXME("fixme_custom() is fixme!"); |
|
241 |
} |
|
242 |
|
|
243 |
void check_assertion_custom() { |
|
244 |
no_assertion_text_custom(); |
|
245 |
no_assertion_exception_custom(); |
|
246 |
assertion_exception_custom(); |
|
247 |
assertion_text_custom(); |
|
248 |
fixme_custom(); |
|
249 |
check(cnt == 3, "The custom assert handler does not work"); |
|
250 |
} |
|
251 |
|
|
252 |
#undef LEMON_ASSERT_CUSTOM |
|
253 |
|
|
254 |
|
|
255 |
int main() { |
|
256 |
check_assertion_disable(); |
|
257 |
check_assertion_error(); |
|
258 |
check_assertion_exception(); |
|
259 |
check_assertion_log(); |
|
260 |
check_assertion_custom(); |
|
66 | 261 |
|
67 | 262 |
return 0; |
68 | 263 |
} |
0 comments (0 inline)