args.h 8.69 KB
Newer Older
1 2 3
#pragma once

#include <string>
4
#include <sstream>
5 6 7 8
#include <map>
#include <cstdlib>
#include <iostream>

Laurent Belcour's avatar
Laurent Belcour committed
9 10
#include "common.h"

11 12
/*! \brief A useful class for storing the high-level arguments of a program
 *  or a function.
13 14
 *  \ingroup core
 *  \internal
15 16 17 18 19
 *
 *  The set of parameters are parsed from the command line using the 
 *  constructor. They are stored as std::string in a std::map.
 *  \todo add functionalities to provide new parameters values.
 */
20 21 22 23 24
class arguments
{
	public: // functions

		// Constructor and destructor
Laurent Belcour's avatar
Laurent Belcour committed
25 26
		arguments()
		{
27
		}
28
		arguments(int argc, char** const argv)
29 30 31 32
        {
            for(int i=0; i<argc; ++i)
            {
                std::string temp(argv[i]) ;
33 34
                std::string key;
                std::string data;
35

36 37 38 39
                if(temp.compare(0, 2, "--") == 0)
                {
//#define DEBUG_ARGS
                    key = temp.substr(2, temp.size()-2) ;
40
#ifdef DEBUG_ARGS
41
                    std::cout << "<<DEBUG>> (" << i << ")" << key << " -> [ ";
42
#endif
43 44 45 46
                    if(++i < argc)
                    {

                        std::string next(argv[i]) ;
47 48 49 50
                        if(next[0] == '-')
                        {
                            --i;
                        }
51
                        else if(next[0] == '[' && next[next.size()-1] != ']')
52 53
                        {
                            data.append(next);
54

55 56 57 58 59
                            ++i;
                            while(i < argc && next[next.size()-1] != ']')
                            {
                                next = argv[i] ;
                                data.append(" ");
60
#ifdef DEBUG_ARGS
61
                                std::cout << " ";
62
#endif
63
                                data.append(next);
64
#ifdef DEBUG_ARGS
65
                                std::cout << "(" << i << ")" << next;
66
#endif
67 68 69 70 71 72 73

                                ++i;
                            }
                            --i;
                        }
                        else
                        {
74
#ifdef DEBUG_ARGS
75
                            std::cout << next;
76
#endif
77 78 79 80 81 82
                            data.append(next);
                        }
                    }
#ifdef DEBUG_ARGS
                    std::cout << "]" << std::endl;
#endif
83
                    _map.insert(std::pair<std::string, std::string>(key, data)) ;
84
                }
85

86 87
            }
        }
88 89 90
		~arguments()
		{
		}
91

92
		//! \brief is the elements in the command line ?
93 94 95 96 97 98 99 100 101 102
		bool is_defined(const std::string& key) const
		{
			if(_map.count(key) > 0)
			{
				return true ;
			}
			else
			{
				return false ;
			}
103
        }
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120

        //! \brief is the data at the given key in a vector format?
        //! No matter the type of the data, this function will test is the
        //! mapped string is of type "[ .... ]".
        //! It returns false if there is no associated entry.
        bool is_vec(const std::string& key) const
        {
            if(_map.count(key) > 0)
            {
                return _map.find(key)->second[0] == '[' ;
            }
            else
            {
                return false ;
            }
        }

121
		//! \brief access the element stored value
122 123 124 125 126 127 128 129
		std::string operator[](const std::string& key) const
		{
			if(_map.count(key) > 0)
			{
				return _map.find(key)->second ;
			}
			else
			{
130
                //std::cerr << "Underfined request to key : \"" << key << "\"" << std::endl ;
131 132
				return std::string() ;
			}
133 134
        }
        //! \brief update the value \a val stored under key \a key
135
        void update(const std::string& key, const std::string& val)
136 137
        {
            _map[key] = val;
138
        }
139 140 141 142 143 144 145 146 147 148 149 150
		//! \brief acces to the string value associated with the parameter
		//! \a key.
		//!
		//! The \a default_value argument will be returned if the \a key
		//! has no associated value.
		std::string get_string(const std::string& key, std::string default_value = "") const
		{
			if(_map.count(key) > 0)
				return _map.find(key)->second.c_str() ;
			else
				return default_value ;
		}
151 152 153 154 155
		//! \brief acces to the float value associated with the parameter
		//! \a key.
		//!
		//! The \a default_value argument will be returned if the \a key
		//! has no associated value.
156
		float get_float(const std::string& key, float default_value = 0.0f) const
157
		{
158
			if(_map.count(key) > 0)
Laurent Belcour's avatar
Laurent Belcour committed
159
				return (float)atof(_map.find(key)->second.c_str()) ;
160
			else
161
				return default_value ;
Laurent Belcour's avatar
Laurent Belcour committed
162
		}
163 164 165 166 167
		//! \brief acces to the integer value associated with the parameter
		//! \a key.
		//!
		//! The \a default_value argument will be returned if the \a key
		//! has no associated value.
168
		int get_int(const std::string& key, int default_value = 0) const
169
		{
170
			if(_map.count(key) > 0)
Laurent Belcour's avatar
Laurent Belcour committed
171
				return atoi(_map.find(key)->second.c_str()) ;
172
			else
173
				return default_value ;
Laurent Belcour's avatar
Laurent Belcour committed
174
		} 
175 176 177 178 179
		//! \brief acces to a vector of float of size \a size associated with
		//! the parameter \a key.
		//!
		//! The \a default_value argument will be returned if the \a key
		//! has no associated value.
180
		vec get_vec(const std::string& key, int size, float default_value = 0.0f) const
Laurent Belcour's avatar
Laurent Belcour committed
181
		{
182
			vec res(size);
183 184 185
            for(int i=0; i<size; ++i)
                res[i] = default_value;

Laurent Belcour's avatar
Laurent Belcour committed
186 187
			if(_map.count(key) > 0)
			{
Laurent Belcour's avatar
Laurent Belcour committed
188
				std::string s = _map.find(key)->second;
189
				if(s[0] == '[') // Is an array of type [a, b, c]
Laurent Belcour's avatar
Laurent Belcour committed
190 191
				{
					int i = 0;
192
					size_t pos = 1;
193
					while(pos != std::string::npos && i<size)
Laurent Belcour's avatar
Laurent Belcour committed
194
					{
195
						size_t ppos = s.find(',', pos);
Laurent Belcour's avatar
Laurent Belcour committed
196 197 198

						if(ppos != std::string::npos)
						{
199
                            res[i] = atof(s.substr(pos, ppos-pos).c_str());
Laurent Belcour's avatar
Laurent Belcour committed
200 201 202
							pos = ppos+1;
							++i;
						}
203 204
						else
						{
205 206
                            std::string temp = s.substr(pos, std::string::npos);
                            res[i] = atof(temp.substr(0, temp.size()-1).c_str());
207 208 209
							pos = ppos;
							++i;
						}
Laurent Belcour's avatar
Laurent Belcour committed
210 211 212 213 214 215
					}
					return res;
				}
			}

			float val = get_float(key, default_value);
216 217 218 219
			for(int i=0; i<size; ++i)
			{
				res[i] = val;
			}
Laurent Belcour's avatar
Laurent Belcour committed
220 221
			return res;
		}
222

223 224 225 226 227 228
        std::vector<std::string> get_vec(const std::string& key) const
        {
            std::vector<std::string> res;
            if(_map.count(key) > 0)
            {
                std::string s = _map.find(key)->second;
229

230 231 232 233 234 235 236 237 238
                if(s[0] == '[') // Is an array of type [a, b, c]
                {
                    size_t pos = 1;
                    while(pos != std::string::npos)
                    {
                        size_t ppos = s.find(',', pos);

                        if(ppos != std::string::npos)
                        {
239 240
                            std::string temp = s.substr(pos, ppos-pos);
                            res.push_back(temp);
241 242 243 244 245
                            pos = ppos+1;
                        }
                        else
                        {
                            std::string temp = s.substr(pos, std::string::npos);
246 247
                            temp = temp.substr(0, temp.size()-1);
                            res.push_back(temp);
248 249 250 251 252 253 254 255 256
                            pos = ppos;
                        }
                    }
                }
            }

            return res;
        }

257 258 259 260 261 262 263 264 265
		  //! \brief get the reconstructed command line arguments (without
		  //! the executable name
		  std::string get_cmd() const
		  {
			  std::string cmd;

			  std::map<std::string, std::string>::const_iterator it = _map.begin();
			  for(;it != _map.end(); it++)
			  {
266 267 268 269 270 271 272
				  if(!it->first.empty())
				  {
					  cmd.append(" --");
					  cmd.append(it->first);
					  cmd.append(" ");
					  cmd.append(it->second);
				  }
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
			  }

			  return cmd;
		  }

		  //! \brief Create an argument object from a string describing a command
		  //! line.
		  static arguments create_arguments(const std::string& n)
		  {
			  std::vector<std::string> cmd_vec;
			  std::stringstream stream(n);
#ifdef DEBUG_ARGS
			  std::cout << "<<DEBUG>> create argument vector: [";
#endif
			  while(stream.good())
			  {
				  std::string temp;
				  stream >> temp;
#ifdef DEBUG_ARGS
				  std::cout << temp << ", ";
#endif

				  cmd_vec.push_back(temp);
			  }
#ifdef DEBUG_ARGS
			  std::cout << "]" << std::endl;
#endif

			  int argc = cmd_vec.size();
302 303
			  char** argv;
			  argv = new char*[argc];
304 305 306 307 308 309
			  for(int i=0; i<argc; ++i)
			  {
				  argv[i] = &cmd_vec[i][0];
			  }

			  arguments current_args(argc, argv);
310
			  delete[] argv;
311 312 313
			  return current_args;
		  }

314 315 316 317 318 319 320 321 322 323
          friend std::ostream& operator<<(std::ostream& out, const arguments& args)
          {
              std::map<std::string, std::string>::const_iterator it;
              for(it=args._map.begin(); it!=args._map.end(); ++it)
              {
                  out<< "[" << it->first << "] -> " << it->second << std::endl;
              }
              return out;
          }

324

325 326 327 328 329
	private: // data

		std::map<std::string, std::string> _map ;

} ;