Suuports clang compiler
[anna.git] / include / anna / core / define.autoenum.hpp
1 // ANNA - Anna is Not Nothingness Anymore
2 //
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
4 //
5 // http://redmine.teslayout.com/projects/anna-suite
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 the copyright holder 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_define_autoenum_hpp
38 #define anna_core_define_autoenum_hpp
39
40 #include <string.h>
41
42 #include <anna/core/RuntimeException.hpp>
43
44 /**
45  * \page declare_enum
46  *
47  * Facilita la declaración de enumerados y sus correspondientes métodos de conversión.
48  * Los valores de los enumerados debe incluir el valor \em None, que será usado en el método
49  * asEnum (const char*) incorporado por esta macro en caso de no encontrar ninguna correspondencia.
50  *
51  * El numerado desde el que se invoque esta macro incluirá de forma automática los siguiente métodos:
52  *
53  * \li _v Transport::asEnum (const char* str): que compara la cadena recibida con las cadenas establecidas al asignar los valores
54  * literales del enumerado y devuelve su valor enumerado. Si no hay coincidencia devolverá None.
55  * \li _v Transport::asEnum (const std::string& str): que compara la cadena recibida con las cadenas establecidas al asignar los valores
56  * literales del enumerado y devuelve su valor enumerado. Si no hay coincidencia devolverá None.
57  * \li _v Transport::asEnumEx (const char* str): que compara la cadena recibida con las cadenas establecidas al asignar los valores
58  * literales del enumerado y devuelve su valor enumerado. Si no hay coincidencia lanzará una excepción.
59  * \li _v Transport::asEnumEx (const std::string& str): que compara la cadena recibida con las cadenas establecidas al asignar los valores
60  * literales del enumerado y devuelve su valor enumerado. Si no hay coincidencia lanzará una excepción.
61  * \li const char* asCString (const _v) que devuelve el literal asociado al valor del enumerado recibido como parámetro. Puede devolver NULL.
62  * \li const char* asNotNullCString (const _v) que devuelve el literal asociado al valor del enumerado recibido como parámetro. Puede devolver "<none>".
63  * \li std::string asList () que devuelve el literal que la lista de valores válidos.
64  *
65  * Así quedaría la declaración del enumerado, que normalmente estará en un .h
66  * \code
67  * struct Transport {
68  *    enum _v { None = -1, TCP, SCTP, UDP };
69  *     anna_declare_enum (Transport);
70  * };
71  * \endcode
72  *
73  * \ref assign_enum
74  * \ref item_enum
75  */
76 #define anna_declare_enum(name) \
77    static const char* literal []; \
78    static _v asEnum (const char* str) throw () { \
79       for (int ii = 0; literal [ii] != NULL; ii ++) { \
80          if (strcasecmp (str, literal [ii]) == 0) \
81             return (_v) ii; \
82       } \
83       return None; \
84    } \
85    static _v asEnumEx (const char* str) throw (anna::RuntimeException) { \
86       if (str == NULL) { \
87          std::string msg (#name); \
88          msg += "::asEnumEx | str can not be null"; \
89          throw anna::RuntimeException (msg, __FILE__,__LINE__); \
90       } \
91       _v result = asEnum (str); \
92       if (result == None) { \
93          std::string msg (#name); \
94          msg += " | Value: '"; \
95          msg += str; \
96          msg += "' is not valid | Valid values: "; \
97          msg += asList (); \
98          throw anna::RuntimeException (msg, __FILE__, __LINE__); \
99       } \
100       return result; \
101    } \
102    static _v asEnum (const std::string& str) throw () { return asEnum (str.c_str ()); } \
103    static _v asEnumEx (const std::string& str) throw (anna::RuntimeException) { return asEnumEx (str.c_str ()); } \
104    static const char* asCString (const _v v) throw () { return (v != None) ? literal [v]: NULL; } \
105    static const char* asNotNullCString (const _v v) throw () { return (v != None) ? literal [v]: "<none>"; } \
106    static std::string asList () throw () {\
107       std::string result;\
108       for (int ii = 0; literal [ii] != NULL; ii ++) { \
109          if (ii == 0 && strcmp (literal [ii], "None") == 0) continue; \
110          if (ii > 1) result += ' '; \
111          result += "'"; result += literal [ii]; result += "'"; \
112       } \
113       return result; \
114    }
115
116 /**
117  * \page assign_enum
118  *
119  * Establece los literales asociados a cada uno de los valores de la enumeración.
120  *
121  * Hay que completar el enumerado asignando los literales asociados a cada uno de los valores:
122  *
123  * \code
124  * anna_assign_enum (diameter::avp::DiameterURI::Transport) = { "tcp", "sctp", "udp", NULL };
125  * \endcode
126  *
127  * \ref declare_enum
128  * \warning Debe incluir el valor \em NULL para indicar el fin de la lista de valores.
129  */
130 #define anna_assign_enum(name) const char* name::literal []
131
132 /**
133  * \page item_enum
134  * Accede al literal definido por el Enumado y la posicion indicada como parámetro
135  */
136 #define anna_item_enum(name,ii) name::literal[ii]
137
138
139 #endif