Updated license
[anna.git] / include / anna / core / util / Variable.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_Variable_hpp
38 #define anna_core_util_Variable_hpp
39
40 #include <anna/core/util/defines.hpp>
41 #include <anna/core/RuntimeException.hpp>
42 #include <anna/core/define.autoenum.hpp>
43 #include <anna/core/util/String.hpp>
44 #include <anna/core/DataBlock.hpp>
45
46 namespace anna {
47
48 /**
49    Recubrimiento de variables de usuario.
50
51    Establece un recubrimiento sobre los tipos de variables soportados por el nucleo
52 */
53 class Variable {
54 public:
55   /**
56      Enumeracion con los tipos de datos que podemos asociar a un mensaje interno.
57   */
58   struct Type {
59     enum _v {
60       None = -1,
61       Unused0,
62       String, /**< Cadena de type std::string. */
63       Integer, /**< Numero entero de type int. */
64       Unused1,
65       Integer64, /**< Numero entero de tipo enterno de 64 bits */
66       Boolean = 5, /**< Dato de tipo bool. */
67       Block = 6, /**< Objeto de tipo DataBlock. */
68       Float, /**< Número en coma flotante de 32 bits */
69       Double, /**< Número en coma flotante de 64 bits */
70       Custom /** Tipo particular definido por el usuario */
71     };
72     anna_declare_enum(Type)
73   };
74
75   // Constructores
76   /**
77      Constructor para inicializar una instancia de tipo cadena.
78
79     @param name Nombre logico que recibe este variable.
80     @param value Referencia a la variable que estamos recubriendo con esta instancia.
81   */
82   Variable(const char* name, std::string& value) :
83     a_name(name),
84     a_isNull(false),
85     a_type(Type::String),
86     a_isOwner(false) {
87     a_value.a_string = &value;
88   }
89
90
91   /**
92   * Constructor para inicializar una instancia de type entero.
93   *
94   * @param name Nombre logico que recibe este variable.
95   * @param value Referencia a la variable que estamos recubriendo con esta instancia.
96   */
97   Variable(const char* name, int& value) :
98     a_name(name),
99     a_isNull(false),
100     a_type(Type::Integer),
101     a_isOwner(false) {
102     value = 0;
103     a_value.a_integer = &value;
104   }
105
106   /**
107   * Constructor para inicializar una instancia de type long.
108   *
109   * @param name Nombre logico que recibe este variable.
110   * @param value Referencia a la variable que estamos recubriendo con esta instancia.
111   */
112   Variable(const char* name, S64& value) :
113     a_name(name),
114     a_isNull(false),
115     a_type(Type::Integer64),
116     a_isOwner(false) {
117     value = 0;
118     a_value.a_longInteger = &value;
119   }
120
121   /**
122   * Constructor para inicializar una instancia de type BOOLEAN.
123   *
124   * @param name Nombre logico que recibe este variable.
125   * @param value Referencia a la variable que estamos recubriendo con esta instancia.
126   */
127   Variable(const char* name, bool& value) :
128     a_name(name),
129     a_isNull(false),
130     a_type(Type::Boolean),
131     a_isOwner(false) {
132     value = false;
133     a_value.a_boolean = &value;
134   }
135
136   /**
137   * Constructor para inicializar una instancia de type BLOQUE_MEMORIA.
138   *
139   * @param name Nombre logico que recibe este variable.
140   * @param value Referencia a la variable que estamos recubriendo con esta instancia.
141   */
142   Variable(const char* name, DataBlock& value) :
143     a_name(name),
144     a_isNull(false),
145     a_type(Type::Block),
146     a_isOwner(false) {
147     a_value.a_dataBlock = &value;
148   }
149
150   /**
151   * Constructor para inicializar una instancia de type float.
152   *
153   * @param name Nombre logico que recibe este variable.
154   * @param value Referencia a la variable que estamos recubriendo con esta instancia.
155   */
156   Variable(const char* name, float& value) :
157     a_name(name),
158     a_isNull(false),
159     a_type(Type::Float),
160     a_isOwner(false) {
161     value = 0;
162     a_value.a_float = &value;
163   }
164
165   /**
166   * Constructor para inicializar una instancia de type double.
167   *
168   * @param name Nombre logico que recibe este variable.
169   * @param value Referencia a la variable que estamos recubriendo con esta instancia.
170   */
171   Variable(const char* name, double& value) :
172     a_name(name),
173     a_isNull(false),
174     a_type(Type::Double),
175     a_isOwner(false) {
176     value = 0;
177     a_value.a_double = &value;
178   }
179
180   /**
181   * Constructor para inicializar una instancia de un tipo definido por el usuario.
182   *
183   * @param name Nombre logico que recibe este variable.
184   * @param value Referencia a la variable que estamos recubriendo con esta instancia.
185   */
186   Variable(const char* name, void* value) :
187     a_name(name),
188     a_isNull(false),
189     a_type(Type::Custom),
190     a_isOwner(false) {
191     a_value.a_custom = value;
192   }
193
194   /**
195      Constructor.
196      @param name Nombre logico que recibe esta variable.
197      @param type Tipo de dato de esta variable.
198   */
199   Variable(const char* name, const Type::_v type);
200
201   /**
202      Destructor
203   */
204   virtual ~Variable();
205
206   // Accesores
207   /**
208      Devuelve el tipo del dato al que recubre esta variable.
209      @return El tipo del dato al que recubre esta variable.
210   */
211   Type::_v getType() const throw() { return a_type; }
212
213   /**
214      Devuelve el nombre logico asociado a esta variable.
215      \return Nombre logico asociado a esta variable.
216   */
217   const char* getName() const throw() { return a_name.c_str(); }
218
219   /**
220      Devuelve \em false si esta marcado como nulo o \em true en otro caso.
221      @return \em false si esta marcado como nulo o \em true en otro caso.
222   */
223   bool isNull() const throw() { return a_isNull; }
224
225   /**
226      Devuelve el valor alfabetico asociado a esta variable.
227      @return Si la variable indicada en el contructor de esta instancia puede interpretarse como
228      una string devolvera su contenido, en otro caso lanzara una excepcion para indicar el error.
229   */
230   const char* getStringValue() const throw(RuntimeException);
231
232   /**
233      Devuelve el valor numerico asociado a esta variable.
234      @return Si la variable indicada en el contructor de esta instancia puede interpretarse como
235      un entero de 32 bits devolvera su contenido, en otro caso lanzara una excepcion para indicar el error.
236   */
237   int getIntegerValue() const throw(RuntimeException);
238
239   /**
240      Devuelve el valor numerico asociado a esta variable.
241      @return Si la variable indicada en el contructor de esta instancia puede interpretarse como
242      un entero de 64 bits devolvera su contenido, en otro caso lanzara una excepcion para indicar el error.
243   */
244   S64 getInteger64Value() const throw(RuntimeException);
245
246   /**
247      Devuelve el valor booleano asociado a esta variable.
248      @return Si la variable indicada en el contructor de esta instancia puede interpretarse como
249      un booleano y este es distinto de cero devolvera true en otro caso devolvera false.
250      indicar el error.
251   */
252   bool getBooleanValue() const throw(RuntimeException) ;
253
254   /**
255      Devuelve el bloque de memoria asociado a esta variable.
256      @return Si la variable indicada en el contructor de esta instancia era de type  DataBlock
257      devolvera el contenido de esta, en otro caso lanzara una excepcion.
258   */
259   const DataBlock& getDataBlockValue() const throw(RuntimeException) ;
260
261   /**
262      Devuelve el valor numerico asociado a esta variable.
263      @return Si la variable indicada en el contructor de esta instancia puede interpretarse como
264      un entero en coma flotante devolvera su contenido, en otro caso lanzara una excepcion para indicar el error.
265   */
266   float getFloatValue() const throw(RuntimeException);
267
268   /**
269      Devuelve el valor numerico asociado a esta variable.
270      @return Si la variable indicada en el contructor de esta instancia puede interpretarse como
271      un entero en coma flotante devolvera su contenido, en otro caso lanzara una excepcion para indicar el error.
272   */
273   double getDoubleValue() const throw(RuntimeException);
274
275   /**
276    * Devuelve el valor de un elemento definido por el usuario.
277    */
278   void* getCustom() throw(RuntimeException) {
279     verifyMatchType(Type::Custom, ANNA_FILE_LOCATION);
280     return a_value.a_custom;
281   }
282
283   /**
284    * Devuelve el valor de un elemento definido por el usuario.
285    */
286   const void* getCustom() const throw(RuntimeException) {
287     verifyMatchType(Type::Custom, ANNA_FILE_LOCATION);
288     return a_value.a_custom;
289   }
290
291   /**
292    * Devuelve el valor de un elemento definido por el usuario.
293    */
294   void setCustom(void* value) throw(RuntimeException) {
295     verifyMatchType(Type::Custom, ANNA_FILE_LOCATION);
296     a_isNull = (value == NULL);
297     a_value.a_custom = value;
298   }
299
300   /**
301      Interpreta el valor asociado a esta variable como un valor entero.
302      \warning No se realiza ninguna comprobacion semantica.
303   */
304   int getInteger() const throw() { return *a_value.a_integer; }
305
306   /**
307      Interpreta el valor asociado a esta variable como un valor entero largo.
308      \warning No se realiza ninguna comprobacion semantica.
309   */
310   S64 getInteger64() const throw() { return *a_value.a_longInteger; }
311
312   /**
313      Interpreta el valor asociado a esta variable como un valor booleano.
314      \warning No se realiza ninguna comprobacion semantica.
315   */
316   bool getBoolean() const throw() { return *a_value.a_boolean; }
317
318   /**
319      Interpreta el valor asociado a esta variable como un valor bloque de datos.
320      \warning No se realiza ninguna comprobacion semantica.
321   */
322   const DataBlock& getDataBlock() const throw() { return *a_value.a_dataBlock; }
323
324   /**
325      Interpreta el valor asociado a esta variable como un valor en coma flotante de 32 bits
326      \warning No se realiza ninguna comprobacion semantica.
327   */
328   float getFloat() const throw() { return *a_value.a_float; }
329
330   /**
331      Interpreta el valor asociado a esta variable como un valor en coma flotante de 64 bits
332      \warning No se realiza ninguna comprobacion semantica.
333   */
334   double getDouble() const throw() { return *a_value.a_double; }
335
336   // Modificadores
337   /**
338   * Establece el valor de la variable a la que recubre. Si la variable estaba marcada como nula la desmarca.
339   * Si el type de dato que deseamos establecer no coincide con el type de dato indicado al crear esta
340   * variable devolvera una excepcion de ejecucion indicado la anomalia.
341   *
342   * @param value Valor que tomara la variable a la que recubre este variable.
343   */
344   void setValue(const char* value) throw(RuntimeException);
345
346   /**
347   * Establece el valor de la variable a la que recubre. Si la variable estaba marcada como nula la desmarca.
348   * Si el type de dato que deseamos establecer no coincide con el type de dato indicado al crear esta
349   * variable devolvera una excepcion de ejecucion indicado la anomalia.
350   *
351   * @param value Valor que tomara la variable a la que recubre este variable.
352   */
353   void setCharPointer(const char* value) throw(RuntimeException);
354
355   /**
356   * Establece el valor de la variable a la que recubre. Si la variable estaba marcada como nula la desmarca.
357   * Si el type de dato que deseamos establecer no coincide con el type de dato indicado al crear esta
358   * variable devolvera una excepcion de ejecucion indicado la anomalia.
359   *
360   * @param value Valor que tomara la variable a la que recubre este variable.
361   */
362   void setValue(const int value) throw(RuntimeException);
363
364   /**
365   * Establece el valor de la variable a la que recubre. Si la variable estaba marcada como nula la desmarca.
366   * Si el type de dato que deseamos establecer no coincide con el type de dato indicado al crear esta
367   * variable devolvera una excepcion de ejecucion indicado la anomalia.
368   *
369   * @param value Valor que tomara la variable a la que recubre este variable.
370   */
371   void setValue(const S64 value) throw(RuntimeException) ;
372
373   /**
374   * Establece el valor de la variable a la que recubre. Si la variable estaba marcada como nula la desmarca.
375   * Si el type de dato que deseamos establecer no coincide con el type de dato indicado al crear esta
376   * variable devolvera una excepcion de ejecucion indicado la anomalia.
377   *
378   * @param value Valor que tomara la variable a la que recubre este variable.
379   */
380   void setValue(const bool value) throw(RuntimeException);
381
382   /**
383   * Establece el valor de la variable a la que recubre. Si la variable estaba marcada como nula la desmarca.
384   * Si el type de dato que deseamos establecer no coincide con el type de dato indicado al crear esta
385   * variable devolvera una excepcion de ejecucion indicado la anomalia.
386   *
387   * @param value Valor que tomara la variable a la que recubre este variable.
388   */
389   void setValue(const DataBlock& value) throw(RuntimeException) ;
390
391   /**
392   * Establece el valor de la variable a la que recubre. Si la variable estaba marcada como nula la desmarca.
393   * Si el type de dato que deseamos establecer no coincide con el type de dato indicado al crear esta
394   * variable devolvera una excepcion de ejecucion indicado la anomalia.
395   *
396   * @param value Valor que tomara la variable a la que recubre este variable.
397   */
398   void setValue(const float value) throw(RuntimeException) ;
399
400   /**
401   * Establece el valor de la variable a la que recubre. Si la variable estaba marcada como nula la desmarca.
402   * Si el type de dato que deseamos establecer no coincide con el type de dato indicado al crear esta
403   * variable devolvera una excepcion de ejecucion indicado la anomalia.
404   *
405   * @param value Valor que tomara la variable a la que recubre este variable.
406   */
407   void setValue(const double value) throw(RuntimeException) ;
408
409   /**
410      Marca/Desmarca la variable como nula.
411      @param isNull Indica la nueva marca de la variable.
412   */
413   void setNull(const bool isNull = true) throw() { a_isNull = isNull; }
414
415   /**
416      Establece el valor asociado a esta variable como un valor entero.
417      \warning No se realiza ninguna comprobacion semantica.
418   */
419   void setInteger(const int value) throw() { *a_value.a_integer = value; a_isNull = false; }
420
421   /**
422      Establece el valor asociado a esta variable como un valor entero largo.
423      \warning No se realiza ninguna comprobacion semantica.
424   */
425   void setLong(const S64 value) throw() { *a_value.a_longInteger = value; a_isNull = false; }
426
427   /**
428      Establece el valor asociado a esta variable como un valor booleano.
429      \warning No se realiza ninguna comprobacion semantica.
430   */
431   void setBoolean(const bool value) throw() { *a_value.a_boolean = value; a_isNull = false; }
432
433   /**
434      Interpreta el valor asociado a esta variable como un valor bloque de datos.
435      \warning No se realiza ninguna comprobacion semantica.
436   */
437   void setDataBlock(const DataBlock& value) throw() { *a_value.a_dataBlock = value; a_isNull = false; }
438
439   /**
440      Interpreta el valor asociado a esta variable como número en coma flotante.
441      \warning No se realiza ninguna comprobacion semantica.
442   */
443   void setFloat(const float value) throw() { *a_value.a_float = value; a_isNull = false; }
444
445   /**
446      Interpreta el valor asociado a esta variable como número en coma flotante.
447      \warning No se realiza ninguna comprobacion semantica.
448   */
449   void setDouble(const double value) throw() { *a_value.a_double = value; a_isNull = false; }
450
451   /**
452      @return \em true si la variable recibida tiene el mismo nombre que esta instancia o \em false
453      en otro caso.
454   */
455   bool isEqual(const Variable& right) const throw() { return a_name == right.a_name; }
456
457   /**
458      Devuelve una cadena con informacion relevante de esta instancia.
459      \return Una cadena con informacion relevante de esta instancia.
460   */
461   virtual String asString() const throw();
462
463 protected:
464   /**
465      Devuelve la direccion de memoria de la variable C++ a sociada a esta variable logica.
466      \return La direccion de memoria de la variable C++ a sociada a esta variable logica.
467      \warning La forma de interpretar este valor dependera del tipo de dato (ver #Type) asociado
468      Devuelve la referencia a memoria de esta variable.
469      \internal
470   */
471   void* getReference() const throw();
472
473   /**
474      Devuelve el area de memoria de la variable C++ a sociada a esta variable logica.
475      \return La area de memoria de la variable C++ a sociada a esta variable logica.
476      \warning La forma de interpretar este valor dependera del tipo de dato (ver #Type) asociado
477      a esta variable.
478   */
479   void* buffer() const throw();
480
481   /**
482      Devuelve la referencia a la variable que controla el indicador de nulo de esta variable.
483      \return La referencia a la variable que controla el indicador de nulo de esta variable.
484   */
485   bool* getNullIndicator() throw() { return &a_isNull; }
486
487 private:
488   std::string a_name;
489   union {
490     std::string* a_string;
491     int* a_integer;
492     S64* a_longInteger;
493     bool* a_boolean;
494     DataBlock* a_dataBlock;
495     float* a_float;
496     double* a_double;
497     void* a_custom;
498   } a_value;
499   struct {
500     int integer;
501     S64 longInteger;
502     bool boolean;
503     float theFloat;
504     double theDouble;
505   } a_aux;
506   const Type::_v a_type;
507   const bool a_isOwner;
508   bool a_isNull;
509
510   Variable(const Variable&);
511   Variable& operator = (const Variable&);
512   void verifyIsNotNull(const char* file, const int lineno) const throw(RuntimeException);
513   void verifyMatchSomeType(const Type::_v firstType, const Type::_v secondType, const char* file, const int lineno) const throw(RuntimeException);
514   void verifyMatchType(const Type::_v, const char* file, const int lineno) const throw(RuntimeException);
515
516 };
517
518 }
519
520 #endif