Changed LICENSE. Now referenced to web site and file on project root directory
[anna.git] / include / anna / core / define.autoenum.hpp
1 // ANNA - Anna is Not Nothingness Anymore                                                         //
2 //                                                                                                //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo                         //
4 //                                                                                                //
5 // See project site at http://redmine.teslayout.com/projects/anna-suite                           //
6 // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
7
8
9 #ifndef anna_core_define_autoenum_hpp
10 #define anna_core_define_autoenum_hpp
11
12 #include <string.h>
13
14 #include <anna/core/RuntimeException.hpp>
15
16 /**
17  * \page declare_enum
18  *
19  * Facilita la declaración de enumerados y sus correspondientes métodos de conversión.
20  * Los valores de los enumerados debe incluir el valor \em None, que será usado en el método
21  * asEnum (const char*) incorporado por esta macro en caso de no encontrar ninguna correspondencia.
22  *
23  * El numerado desde el que se invoque esta macro incluirá de forma automática los siguiente métodos:
24  *
25  * \li _v Transport::asEnum (const char* str): que compara la cadena recibida con las cadenas establecidas al asignar los valores
26  * literales del enumerado y devuelve su valor enumerado. Si no hay coincidencia devolverá None.
27  * \li _v Transport::asEnum (const std::string& str): que compara la cadena recibida con las cadenas establecidas al asignar los valores
28  * literales del enumerado y devuelve su valor enumerado. Si no hay coincidencia devolverá None.
29  * \li _v Transport::asEnumEx (const char* str): que compara la cadena recibida con las cadenas establecidas al asignar los valores
30  * literales del enumerado y devuelve su valor enumerado. Si no hay coincidencia lanzará una excepción.
31  * \li _v Transport::asEnumEx (const std::string& str): que compara la cadena recibida con las cadenas establecidas al asignar los valores
32  * literales del enumerado y devuelve su valor enumerado. Si no hay coincidencia lanzará una excepción.
33  * \li const char* asCString (const _v) que devuelve el literal asociado al valor del enumerado recibido como parámetro. Puede devolver NULL.
34  * \li const char* asNotNullCString (const _v) que devuelve el literal asociado al valor del enumerado recibido como parámetro. Puede devolver "<none>".
35  * \li std::string asList () que devuelve el literal que la lista de valores válidos.
36  *
37  * Así quedaría la declaración del enumerado, que normalmente estará en un .h
38  * \code
39  * struct Transport {
40  *    enum _v { None = -1, TCP, SCTP, UDP };
41  *     anna_declare_enum (Transport);
42  * };
43  * \endcode
44  *
45  * \ref assign_enum
46  * \ref item_enum
47  */
48 #define anna_declare_enum(name) \
49    static const char* literal []; \
50    static _v asEnum (const char* str) throw () { \
51       for (int ii = 0; literal [ii] != NULL; ii ++) { \
52          if (strcasecmp (str, literal [ii]) == 0) \
53             return (_v) ii; \
54       } \
55       return None; \
56    } \
57    static _v asEnumEx (const char* str) throw (anna::RuntimeException) { \
58       if (str == NULL) { \
59          std::string msg (#name); \
60          msg += "::asEnumEx | str can not be null"; \
61          throw anna::RuntimeException (msg, __FILE__,__LINE__); \
62       } \
63       _v result = asEnum (str); \
64       if (result == None) { \
65          std::string msg (#name); \
66          msg += " | Value: '"; \
67          msg += str; \
68          msg += "' is not valid | Valid values: "; \
69          msg += asList (); \
70          throw anna::RuntimeException (msg, __FILE__, __LINE__); \
71       } \
72       return result; \
73    } \
74    static _v asEnum (const std::string& str) throw () { return asEnum (str.c_str ()); } \
75    static _v asEnumEx (const std::string& str) throw (anna::RuntimeException) { return asEnumEx (str.c_str ()); } \
76    static const char* asCString (const _v v) throw () { return (v != None) ? literal [v]: NULL; } \
77    static const char* asNotNullCString (const _v v) throw () { return (v != None) ? literal [v]: "<none>"; } \
78    static std::string asList () throw () {\
79       std::string result;\
80       for (int ii = 0; literal [ii] != NULL; ii ++) { \
81          if (ii == 0 && strcmp (literal [ii], "None") == 0) continue; \
82          if (ii > 1) result += ' '; \
83          result += "'"; result += literal [ii]; result += "'"; \
84       } \
85       return result; \
86    }
87
88 /**
89  * \page assign_enum
90  *
91  * Establece los literales asociados a cada uno de los valores de la enumeración.
92  *
93  * Hay que completar el enumerado asignando los literales asociados a cada uno de los valores:
94  *
95  * \code
96  * anna_assign_enum (diameter::avp::DiameterURI::Transport) = { "tcp", "sctp", "udp", NULL };
97  * \endcode
98  *
99  * \ref declare_enum
100  * \warning Debe incluir el valor \em NULL para indicar el fin de la lista de valores.
101  */
102 #define anna_assign_enum(name) const char* name::literal []
103
104 /**
105  * \page item_enum
106  * Accede al literal definido por el Enumado y la posicion indicada como parámetro
107  */
108 #define anna_item_enum(name,ii) name::literal[ii]
109
110
111 #endif