args.h 6.8 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 29 30 31 32
		arguments(int argc, char** const argv)
		{
			for(int i=0; i<argc; ++i)
			{
				std::string temp(argv[i]) ;
33
				std::string key, data ;
34 35 36 37

				if(temp.compare(0, 2, "--") == 0)
				{
					key = temp.substr(2, temp.size()-2) ;
38 39 40 41 42
#ifdef DEBUG_ARGS
					std::cout << "<<DEBUG>> (" << i << ")" << key << " -> [ ";
#endif
					int k = i+1;
					int j = k;
43
					while(j < argc) 
44
					{
45

46
						std::string next(argv[j]) ;
47
						if(next[0] == '[' || next[next.size()-1] == ']' || next.compare(0, 2, "--") != 0)
48
						{
49 50 51 52 53 54 55 56 57 58 59
							if(j != k)
							{
								data.append(" ");
#ifdef DEBUG_ARGS
								std::cout << " ";
#endif
							}
							data.append(next);
#ifdef DEBUG_ARGS
							std::cout << "(" << j << ")" << next;
#endif
60
						}
61 62 63 64 65
						else
						{
							break ;
						}
						++j;
66
						++i;
67
					}
68 69 70
#ifdef DEBUG_ARGS
					std::cout << "]" << std::endl;
#endif
71 72 73
				}
				_map.insert(std::pair<std::string, std::string>(key, data)) ;
			}
74 75 76 77
		}
		~arguments()
		{
		}
78

79
		//! \brief is the elements in the command line ?
80 81 82 83 84 85 86 87 88 89
		bool is_defined(const std::string& key) const
		{
			if(_map.count(key) > 0)
			{
				return true ;
			}
			else
			{
				return false ;
			}
90
        }
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107

        //! \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 ;
            }
        }

108
		//! \brief access the element stored value
109 110 111 112 113 114 115 116
		std::string operator[](const std::string& key) const
		{
			if(_map.count(key) > 0)
			{
				return _map.find(key)->second ;
			}
			else
			{
117
                //std::cerr << "Underfined request to key : \"" << key << "\"" << std::endl ;
118 119
				return std::string() ;
			}
120
        }
121 122 123 124 125
		//! \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.
126
		float get_float(const std::string& key, float default_value = 0.0f) const
127
		{
128
			if(_map.count(key) > 0)
Laurent Belcour's avatar
Laurent Belcour committed
129
				return atof(_map.find(key)->second.c_str()) ;
130
			else
131
				return default_value ;
Laurent Belcour's avatar
Laurent Belcour committed
132
		}
133 134 135 136 137
		//! \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.
138
		int get_int(const std::string& key, int default_value = 0) const
139
		{
140
			if(_map.count(key) > 0)
Laurent Belcour's avatar
Laurent Belcour committed
141
				return atoi(_map.find(key)->second.c_str()) ;
142
			else
143
				return default_value ;
Laurent Belcour's avatar
Laurent Belcour committed
144
		} 
145 146 147 148 149
		//! \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.
150
		vec get_vec(const std::string& key, int size, float default_value = 0.0f) const
Laurent Belcour's avatar
Laurent Belcour committed
151
		{
152
			vec res(size);
153 154 155
            for(int i=0; i<size; ++i)
                res[i] = default_value;

Laurent Belcour's avatar
Laurent Belcour committed
156 157
			if(_map.count(key) > 0)
			{
Laurent Belcour's avatar
Laurent Belcour committed
158
				std::string s = _map.find(key)->second;
159
				if(s[0] == '[') // Is an array of type [a, b, c]
Laurent Belcour's avatar
Laurent Belcour committed
160 161
				{
					int i = 0;
162
					size_t pos = 1;
163
					while(pos != std::string::npos && i<size)
Laurent Belcour's avatar
Laurent Belcour committed
164
					{
165
						size_t ppos = s.find(',', pos);
Laurent Belcour's avatar
Laurent Belcour committed
166 167 168

						if(ppos != std::string::npos)
						{
169
                            res[i] = atof(s.substr(pos, ppos-pos).c_str());
Laurent Belcour's avatar
Laurent Belcour committed
170 171 172
							pos = ppos+1;
							++i;
						}
173 174
						else
						{
175 176
                            std::string temp = s.substr(pos, std::string::npos);
                            res[i] = atof(temp.substr(0, temp.size()-1).c_str());
177 178 179
							pos = ppos;
							++i;
						}
Laurent Belcour's avatar
Laurent Belcour committed
180 181 182 183 184 185
					}
					return res;
				}
			}

			float val = get_float(key, default_value);
186 187 188 189
			for(int i=0; i<size; ++i)
			{
				res[i] = val;
			}
Laurent Belcour's avatar
Laurent Belcour committed
190 191
			return res;
		}
192

193 194 195 196 197 198
        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;
199

200 201 202 203 204 205 206 207 208
                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)
                        {
209 210
                            std::string temp = s.substr(pos, ppos-pos);
                            res.push_back(temp);
211 212 213 214 215
                            pos = ppos+1;
                        }
                        else
                        {
                            std::string temp = s.substr(pos, std::string::npos);
216 217
                            temp = temp.substr(0, temp.size()-1);
                            res.push_back(temp);
218 219 220 221 222 223 224 225 226
                            pos = ppos;
                        }
                    }
                }
            }

            return res;
        }

227 228 229 230 231 232 233 234 235
		  //! \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++)
			  {
236 237 238 239 240 241 242
				  if(!it->first.empty())
				  {
					  cmd.append(" --");
					  cmd.append(it->first);
					  cmd.append(" ");
					  cmd.append(it->second);
				  }
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
			  }

			  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();
			  char* argv[argc];
			  for(int i=0; i<argc; ++i)
			  {
				  argv[i] = &cmd_vec[i][0];
			  }

			  arguments current_args(argc, argv);
			  return current_args;
		  }


283 284 285 286 287
	private: // data

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

} ;