Remove dynamic exceptions
[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 int calculateSize () { \
51       int ii = 0; \
52       while (literal [ii] != NULL) ii ++; \
53       return ii; \
54    } \
55    static _v asEnum (const char* str) { \
56       for (int ii = 0; literal [ii] != NULL; ii ++) { \
57          if (strcasecmp (str, literal [ii]) == 0) \
58             return (_v) ii; \
59       } \
60       return None; \
61    } \
62    static _v asEnumEx (const char* str) noexcept(false) { \
63       if (str == NULL) { \
64          std::string msg (#name); \
65          msg += "::asEnumEx | str can not be null"; \
66          throw anna::RuntimeException (msg, __FILE__,__LINE__); \
67       } \
68       _v result = asEnum (str); \
69       if (result == None) { \
70          std::string msg (#name); \
71          msg += " | Value: '"; \
72          msg += str; \
73          msg += "' is not valid | Valid values: "; \
74          msg += asList (); \
75          throw anna::RuntimeException (msg, __FILE__, __LINE__); \
76       } \
77       return result; \
78    } \
79    static _v asEnum (const std::string& str) { return asEnum (str.c_str ()); } \
80    static _v asEnumEx (const std::string& str) noexcept(false) { return asEnumEx (str.c_str ()); } \
81    static const char* asCString (const _v v) { return (v != None) ? literal [v]: NULL; } \
82    static const char* asNotNullCString (const _v v) { return (v != None) ? literal [v]: "<none>"; } \
83    static std::string asList () {\
84       std::string result;\
85       for (int ii = 0; literal [ii] != NULL; ii ++) { \
86          if (ii == 0 && strcmp (literal [ii], "None") == 0) continue; \
87          if (ii > 1) result += ' '; \
88          result += "'"; result += literal [ii]; result += "'"; \
89       } \
90       return result; \
91    }
92
93 /**
94  * \page assign_enum
95  *
96  * Establece los literales asociados a cada uno de los valores de la enumeración.
97  *
98  * Hay que completar el enumerado asignando los literales asociados a cada uno de los valores:
99  *
100  * \code
101  * anna_assign_enum (diameter::avp::DiameterURI::Transport) = { "tcp", "sctp", "udp", NULL };
102  * \endcode
103  *
104  * \ref declare_enum
105  * \warning Debe incluir el valor \em NULL para indicar el fin de la lista de valores.
106  */
107 #define anna_assign_enum(name) const char* name::literal []
108
109 /**
110  * \page item_enum
111  * Accede al literal definido por el Enumado y la posicion indicada como parámetro
112  */
113 #define anna_item_enum(name,ii) name::literal[ii]
114
115
116 #endif