1 #include "configuration_manager.hh"
4 #define MAX_LINE_LENGTH 80
9 * This constructor makes a new configuration_manager ready to use.
10 *\arg name Name of the application as mentioned in the
11 * "Use: <appname> ..." help message.
13 configuration_manager::configuration_manager(string name
){
19 *\brief Add a new configuration value to be searched for.
20 *\param shortname A character for the short form.
21 * For example the o in -o
22 *\param longname The double dash longname. For example
23 * output_file in --output_file=
24 *\param description A detailed description of the value.
25 *\param status Pointer to an integer. Will be set to 1 if arg found.
26 *\target Pointer to string to put the value in.
27 *\placeholder A placeholder for the documentation.
28 * For example <filename> in -f<filename>
30 void configuration_manager::add_option_value (const string
& shortname
,
31 const string
& longname
,
32 const string
& description
,
35 const string
& placeholder
,
36 const bool & allow_cmdline
,
37 const bool & allow_conffile
40 if(status
!=NULL
) if (target
!=NULL
)
41 option_values
.insert(option_values
.end(),
42 opt_value_t(shortname
,
57 *\brief Add a new configuration switch to be searched for.
58 *\param shortname A character for the short form.
59 * For example the h in -h
60 *\param longname The double dash longname. For example
62 *\param description A detailed description of the value.
63 *\param status Pointer to an integer. Will be set to 1 if arg found.
64 *\param allow_cmdline Specifies whether the switch is acceptable on the
66 *\param allow_conffile Specifies whether the switch is acceptable
67 * in a configuration file.
69 void configuration_manager::add_option_switch (const string
& shortname
,
70 const string
& longname
,
71 const string
& description
,
73 const bool & allow_cmdline
,
74 const bool & allow_conffile
78 option_switches
.insert(option_switches
.end(),
79 opt_switch_t(shortname
,
89 *\brief Add an accepted argument to the argument reader.
90 *\param placeholder Something like "<input-file>".
91 *\param description Text describing the argument.
92 *\param status A pointer to a status variable. Will be set to 0 by default.
93 * If the argument is filled in, it will be set to 1.
94 *\param target A pointer to a c++ string where the argument goes to.
96 *\note Arguments are filled in the order of adding them to the
98 * There would be no other way to determine the order.
100 void configuration_manager::add_argument(const string
& description
,
103 const string
& placeholder
){
107 if (target
!=NULL
) if(status
!=NULL
)
108 cmd_args
.insert(cmd_args
.end(),cmd_arg_t(placeholder
,
116 *\Read in the args passed to main().
117 *\returns empty vector on success or the error messages to be output.
119 vector
<string
> configuration_manager::read_args(int argc
, char ** args
){
121 vector
<string
> messages
;
124 // First we make a C++ string vector out of the **argv.
125 for (char ** akt
=args
+1; *akt
;akt
++) argv
.insert(argv
.end(),string(*akt
));
127 // Counter for the free command line parameters.
128 unsigned int free_parms_count
=0;
130 // Loop through the command line arguments
131 for (unsigned int arg_no
=0;arg_no
<argv
.size();arg_no
++){
135 // Look for long parameters.
136 if ((argv
[arg_no
].substr(0,2)=="--")&&(free_parms_count
==0)){
137 argstring
=argv
[arg_no
].substr(2);
139 // Look for long switches.
140 for (unsigned int switch_no
=0;switch_no
<option_switches
.size();switch_no
++){
141 string switch_name
=option_switches
[switch_no
].longname
;
142 if (argstring
.compare(0,switch_name
.length(),switch_name
,0,switch_name
.length())==0){
143 string value
=analyse_string(argstring
);
144 bool result
=analyse_bool(value
);
145 *(option_switches
[switch_no
].status
)=result
;
150 // Look for long values.
151 for (unsigned int value_no
=0;value_no
<option_values
.size();value_no
++){
152 string value_name
=option_values
[value_no
].longname
;
153 if (argstring
.compare(0,value_name
.length(),value_name
,0,value_name
.length())==0){
154 string value
=analyse_string(argstring
);
155 *(option_values
[value_no
].status
)=1;
156 *(option_values
[value_no
].target
)=value
;
161 messages
.insert(messages
.begin(),"Unknown option: --"+argstring
+"!");
166 // Look for short parameters
167 if ((argv
[arg_no
].substr(0,1)=="-")&&(free_parms_count
==0)&&(!found
)){ // Short parameters
169 argstring
=argv
[arg_no
].substr(1); // Reassign, with one more character now
170 for (unsigned int pos
=0;pos
< argstring
.length();pos
++){
171 bool short_found
=false;
173 // First, find short switches
174 for (unsigned int switch_no
=0;switch_no
<option_switches
.size();switch_no
++){
175 string short_name
=option_switches
[switch_no
].shortname
;
176 if (short_name
.compare(0,short_name
.length(),argstring
,pos
,short_name
.length())==0){
177 *(option_switches
[switch_no
].status
)=1;
179 pos
+=short_name
.length()-1;
183 // Now, find short values
185 for (unsigned int value_no
=0;value_no
<option_values
.size();value_no
++){
186 string short_name
=option_values
[value_no
].shortname
;
188 if (short_name
.compare(0,short_name
.length(),argstring
,pos
,short_name
.length())==0){
189 if (pos
==argstring
.length()-1){ // Last character, where's the value?
190 if (arg_no
<argv
.size()-1){ // Take next complete argument as value!
191 *(option_values
[value_no
].status
)=1;
192 *(option_values
[value_no
].target
)=argv
[arg_no
+1];
193 arg_no
+=1; // Consume the next argument
195 } else { // No argument left!
196 messages
.insert(messages
.begin(),"Missing value for -"+short_name
+"!");
200 *(option_values
[value_no
].status
)=1;
201 *(option_values
[value_no
].target
)=argstring
.substr(pos
+1);
202 pos
=argstring
.length(); // Do not analyse other characters.
208 if (!short_found
) messages
.insert(messages
.begin(),"Unknown Option: -"+argstring
.substr(pos
,1)+"!");
212 if (!found
) { // Must be a free form parameter...
213 if (free_parms_count
<cmd_args
.size()){ // Space available
214 *(cmd_args
[free_parms_count
].target
)=argv
[arg_no
];
215 *(cmd_args
[free_parms_count
].status
)=1;
217 } else { // No more space for free form parameters!
218 messages
.insert(messages
.begin(),"Too many arguments!");
222 if (!messages
.empty()){
223 messages
.insert(messages
.begin(),"Error!");
224 messages
.insert(messages
.begin(),"");
230 *\brief Extract a value from a configuration file line or
231 * a command line argument
233 string
configuration_manager::analyse_string(const string
& line
){
235 unsigned int pos
=line
.find("=");
236 if (pos
!=string::npos
) result
=line
.substr(pos
+1);
241 *\brief Extract a boolean value out of a string.
243 bool configuration_manager::analyse_bool(const string
& data
){
244 if ((data
=="false")||(data
=="0")||(data
=="no")) return false;
249 *\brief Generate help.
250 *\arg target Reference to a vector<string> to which lots of helpful
251 * strings are appended.
253 void configuration_manager::get_help(vector
<string
> & target
){
254 target
.insert(target
.end(),"");
255 string line
="Usage: "+app_name
;
257 for (vector
<opt_switch_t
>::iterator parm_p
=option_switches
.begin();parm_p
<option_switches
.end();parm_p
++){
258 string addstr
=" [-"+parm_p
->shortname
;
260 if (line
.length()+addstr
.length()>MAX_LINE_LENGTH
){
261 target
.insert(target
.end(),line
);
262 line
=string(7+app_name
.length(),' ');
267 for (vector
<opt_value_t
>::iterator parm_p
=option_values
.begin();parm_p
<option_values
.end();parm_p
++){
268 string addstr
=" [-"+parm_p
->shortname
;
269 addstr
+=parm_p
->placeholder
;
271 if (line
.length()+addstr
.length()>MAX_LINE_LENGTH
){
272 target
.insert(target
.end(),line
);
273 line
=string(7+app_name
.length(),' ');
278 for (vector
<cmd_arg_t
>::iterator parm_p
=cmd_args
.begin();parm_p
<cmd_args
.end();parm_p
++){
279 if (line
.length()+parm_p
->placeholder
.length()>MAX_LINE_LENGTH
){
280 target
.insert(target
.end(),line
);
281 line
=string(7+app_name
.length(),' ');
283 line
+=" ["+parm_p
->placeholder
+"]";
285 target
.insert(target
.end(),line
);
287 /* Here comes the documentation output. */
289 vector
<string
> left
,right
;
290 unsigned int max_width
;
292 /* Output switches? */
293 if (option_switches
.size()){
294 target
.insert(target
.end(),"");
295 target
.insert(target
.end(),"Switches:");
297 left
=vector
<string
>();
298 right
=vector
<string
>();
301 /* Now lets insert switches into left and right */
302 for (unsigned int sw
=0; sw
<option_switches
.size();sw
++){
303 opt_switch_t akt_sw
=option_switches
[sw
];
304 string rline
=akt_sw
.description
;
305 string lline
="-"+akt_sw
.shortname
+", --"+akt_sw
.longname
;
306 left
.insert(left
.end(),lline
);
307 right
.insert(right
.end(),rline
);
310 // Determine maximal width for left column
312 for (unsigned int c
=0; c
<left
.size();c
++)
313 if(left
[c
].length()>max_width
) max_width
=left
[c
].length();
315 /* output all the mess */
316 for (unsigned int c
=0; c
<left
.size();c
++){
317 string
nl(max_width
,' ');
318 nl
.replace(0,left
[c
].length(),left
[c
]);
320 while (nl
.length()>80){ // Too long???
321 int limit
=nl
.find_last_of(' ',MAX_LINE_LENGTH
+1);
322 target
.insert(target
.end(),nl
.substr(0,limit
));
323 nl
=string(max_width
+2,' ')+nl
.substr(limit
+1);
325 target
.insert(target
.end(),nl
);
330 if (option_values
.size()){
331 target
.insert(target
.end(),"");
332 target
.insert(target
.end(),"Option values:");
334 left
=vector
<string
>();
335 right
=vector
<string
>();
338 for (unsigned int val
=0; val
<option_values
.size();val
++){
339 opt_value_t akt_val
=option_values
[val
];
340 string rline
=akt_val
.description
;
341 string lline
=" -"+akt_val
.shortname
+akt_val
.placeholder
+", --"+
342 akt_val
.longname
+akt_val
.placeholder
;
343 left
.insert(left
.end(),lline
);
344 right
.insert(right
.end(),rline
);
347 // Determine maximal width for left column
348 for (unsigned int c
=0; c
<left
.size();c
++)
349 if(left
[c
].length()>max_width
) max_width
=left
[c
].length();
350 /* output all the mess */
351 for (unsigned int c
=0; c
<left
.size();c
++){
352 string
nl(max_width
,' ');
353 nl
.replace(0,left
[c
].length(),left
[c
]);
355 while (nl
.length()>80){ // Too long???
356 int limit
=nl
.find_last_of(' ',MAX_LINE_LENGTH
+1);
357 target
.insert(target
.end(),nl
.substr(0,limit
));
358 nl
=string(max_width
+2,' ')+nl
.substr(limit
+1);
360 target
.insert(target
.end(),nl
);
364 /* Output the Arguments */
365 if (cmd_args
.size()){
366 target
.insert(target
.end(),"");
367 target
.insert(target
.end(),"Arguments:");
369 left
=vector
<string
>();
370 right
=vector
<string
>();
373 for (unsigned int arg
=0; arg
<cmd_args
.size();arg
++){
374 cmd_arg_t akt_arg
=cmd_args
[arg
];
375 left
.insert(left
.end(),akt_arg
.placeholder
);
376 right
.insert(right
.end(),akt_arg
.description
);
379 // Determine maximal width for left column
381 for (unsigned int c
=0; c
<left
.size();c
++)
382 if(left
[c
].length()>max_width
) max_width
=left
[c
].length();
384 for (unsigned int c
=0; c
<left
.size();c
++){
385 string
nl(max_width
,' ');
386 nl
.replace(0,left
[c
].length(),left
[c
]);
388 while (nl
.length()>MAX_LINE_LENGTH
){ // Too long???
389 int limit
=nl
.find_last_of(' ',MAX_LINE_LENGTH
+1);
390 // printf("limit:%i\n",limit);
391 target
.insert(target
.end(),nl
.substr(0,limit
));
392 nl
=string(max_width
+2,' ')+nl
.substr(limit
+1);
394 target
.insert(target
.end(),nl
);
396 target
.insert(target
.end(),"");
401 *\brief Generate help.
402 *\return A vector containing many helpful strings for the user.
404 vector
<string
> configuration_manager::get_help(){
405 vector
<string
> result
;
411 /**************************************************/
414 configuration_manager::opt_value_t::opt_value_t(const string
& shortname
,
415 const string
& longname
,
416 const string
& description
,
419 const string
& placeholder
,
420 const bool & allow_conffile
,
421 const bool & allow_cmdline
423 this->shortname
=shortname
;
424 this->longname
=longname
;
425 this->description
=description
;
428 this->placeholder
=placeholder
;
429 this->allow_conffile
=allow_conffile
;
430 this->allow_cmdline
=allow_cmdline
;
431 if (status
) *status
=0;
435 configuration_manager::opt_switch_t::opt_switch_t(const string
& shortname
,
436 const string
& longname
,
437 const string
& description
,
439 const bool & allow_conffile
,
440 const bool & allow_cmdline
){
441 this->shortname
=shortname
;
442 this->longname
=longname
;
443 this->description
=description
;
446 this->placeholder
=placeholder
;
447 this->allow_conffile
=allow_conffile
;
448 this->allow_cmdline
=allow_cmdline
;
449 if (status
) *status
=0;
453 configuration_manager::cmd_arg_t::cmd_arg_t(const string
& placeholder
,
454 const string
& description
,
457 this->placeholder
=placeholder
;
458 this->description
=description
;
461 if (this->status
) *(this->status
)=0;