Updated license
[anna.git] / include / anna / core / util / CommandLine.hpp
1 // ANNA - Anna is Not Nothingness Anymore
2 //
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
4 //
5 // https://bitbucket.org/testillano/anna
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
9 // are met:
10 //
11 //     * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 //     * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
16 // distribution.
17 //     * Neither the name of Google Inc. nor the names of its
18 // contributors may be used to endorse or promote products derived from
19 // this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 //
33 // Authors: eduardo.ramos.testillano@gmail.com
34 //          cisco.tierra@gmail.com
35
36
37 #ifndef anna_core_util_CommandLine_hpp
38 #define anna_core_util_CommandLine_hpp
39
40 #include <stdlib.h>
41
42 #include <vector>
43
44 #include <anna/core/functions.hpp>
45 #include <anna/core/Singleton.hpp>
46
47 namespace anna {
48
49 class RuntimeException;
50
51 namespace xml {
52 class Node;
53 }
54
55
56 /**
57    Facilita la recogida de parametros desde la linea de comandos. Tambien
58    verifica que todos los parametros necesarios han sido indicados por el
59    usuario.
60 */
61 class CommandLine : public Singleton <CommandLine> {
62 public:
63   /**
64      Define los tipos de argumento
65
66   */
67   struct Argument { enum Type { Mandatory = 0, Optional};  };
68
69   // Accesores
70   /**
71      @return la lista de cadenas indicadas en la linea de comandos al ejecutar este programa.
72      Mientras que no invoquemos al metodo #initialize devolvera NULL.
73   */
74   const char** getArgv() const throw() { return a_argv; }
75
76   /**
77      @return El numero de parametros indicados en la linea de comandos al ejecutar este programa.
78   */
79   int getArgc() const throw() { return a_argc; }
80
81   //
82   // Metodos
83   //
84   /**
85      Establece la informacion necesaria para analizar la linea de comandos
86      indicada por el usuario. Debe invocarse antes que cualquier otro metodo
87      relacionado con la obtencion/comprobacion de valor de la linea de comandos.
88
89      Recibe una copia de los parametros que los recibidos por el metodo 'main'.
90
91      @param argv Conjunto de cadenas que se reciben de la linea de comandos.
92      @param argc Numero de cadenas recibidas.
93   */
94   void initialize(const char** argv, const int argc) throw() {
95     a_argv = argv;
96     a_argc = argc;
97     a_wasParsed = false;
98   }
99
100   /**
101      Registra un argumentName que sera recocido por nuestra aplicacion.
102
103      Se pueden indicar tantos argumentNames como sea necesario.
104
105      @param argumentName Nombre del argumento.
106      @param type Tipo de argumento. Ver  Variable#Type.
107      @param comment Explicacion acerca de cometido de este argumento.
108      @param needValue Indica si el parametro que estamos definido debe tener un
109      valor adicional. Por ejemplo un parametro "usuario" deberia tener un valor adicional
110      que sea el valor que toma.
111    */
112   void add(const char* argumentName, Argument::Type type, const char* comment, const bool needValue = true) throw();
113
114   /**
115      Obtiene el valor asociado al argumento recibido como parametro.
116      El valor devuelto puede ser NULL en caso de que el argumento no sea
117      obligatorio y no este en la linea de comandos.
118      Si el argumento es obligatorio y no este en la linea de comandos o
119      no tiene valor asociado la ejecucion del programa TERMINA inmediatamente.
120
121      @param argumentName Nombre del argumento del que deseamos obtener el valor.
122      @param exitOnFault Indica el funcionamiento del metodo en caso de que el
123      argumento solicitado no halla sido indicado. Si el parametro no existe
124      si vale @em true la aplicacion terminara, si vale @em false devolvera NULL.
125
126      @return Valor asociadoal argumento recibido como parametro. Puede ser NULL.
127   */
128   const char* getValue(const char* argumentName, const bool exitOnFault = true) throw();
129
130   /**
131      Obtiene el valor asociado al argumento recibido, pero convirtiendo a
132      numero el valor obtenido por #getValue.
133
134      @param argumentName Nombre del argumento del que deseamos obtener el valor.
135
136      @return Valor numerico del valor devuelto por #getValue.
137   */
138   int getIntegerValue(const char* argumentName) throw() { return atoi(getValue(argumentName)); }
139
140   /**
141      Comprueba si el argumento recibido como parametro estña presente en la linea de
142      comandos.
143
144      @param argumentName Nombre del argumento del que deseamos obtener el valor.
145
146      @return true si el argumento esta en la linea de comandos y false en otro caso.
147    */
148   bool exists(const char* argumentName) throw() { return (getValue(argumentName, false) != NULL) ? true : false; }
149
150   /**
151     Comprueba la linea de comandos del programa para verificar que coincide con los argumentos
152     registrados por nuestra aplicacion:
153
154     @li Verifica que los parametros obligatorios estan en la linea de comandos.
155     @li Verifica que los valores de los argumento son correctos de forma que si un parametro
156     debe llevar un valor asociado este esta presente y que si no debe llevarlo no esta.
157     El orden en que aparezcan los argumento en la linea de comandos es indiferente a la hora de
158     hacer las comprobacion.
159
160     Si hay algun fallo en la linea de comandos establecida al ejecutar el programa visualiza un
161     resumen con los parametros soportados y la ejecucion del programa finaliza.
162   */
163   void verify() throw(RuntimeException);
164
165
166   /**
167      Class string representation
168      \return String with relevant information for this instance.
169   */
170   std::string asString() const throw();
171
172   /**
173      Class xml representation
174      \param parent Parent XML node on which hold this instance information.
175      \return XML document with relevant information for this instance.
176   */
177   xml::Node* asXML(xml::Node* parent) const throw();
178
179
180 private:
181   Mutex a_mutex;
182
183   class Variable {
184   public:
185     // Constructores
186     Variable(const char* name, const Argument::Type type, const char* comment, const bool needValue = true) :
187       a_name(name), a_type(type), a_comment(comment), a_needValue(needValue),
188       a_isOn(false), a_value(NULL) {
189     }
190     virtual ~Variable() { if(a_value) free(a_value); }
191
192     // Accesores
193     const std::string& getName() const throw() { return a_name; }
194     const char* getValue() const throw() { return a_value; }
195     const char* getComment() const throw() { return a_comment; }
196     bool getNeedValue() const throw() { return a_needValue; }
197     bool getIsOn() const throw() { return a_isOn; }
198     Argument::Type getType() const throw() { return a_type; }
199
200     // Modificadores
201     void setValue(const char* value) throw() { a_value = (value == NULL) ? NULL : strdup(value); }
202     void setIsOn(const bool isOn) throw() { a_isOn = isOn; }
203
204     // Metodos
205     std::string asString() const throw();
206
207   protected:
208     std::string a_name;
209     const char* a_comment;
210     char* a_value;
211     Argument::Type a_type;
212     bool a_needValue;
213     bool a_isOn;
214   };
215
216   const char **a_argv;
217   int a_argc;
218   bool a_wasParsed;
219   std::vector <Variable*> a_arguments;
220
221   CommandLine() : a_argv(NULL), a_argc(0)  {;}
222
223   bool analize() throw();
224   const Variable* search(const char *argumentName) const throw();
225   void printUsage() const throw();
226
227   friend class Singleton <CommandLine>;
228 };
229
230 }
231
232 #endif
233