0ceb35856ec93ec1c5cc6664a3644d6259e70517
[anna.git] / include / anna / core / functions.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_functions_hpp
10 #define anna_core_functions_hpp
11
12 #include <stdlib.h>
13
14 #include <anna/core/util/ComponentManager.hpp>
15 #include <anna/core/util/defines.hpp>
16 #include <anna/core/RuntimeException.hpp>
17
18 #include <anna/core/util/ExclusiveHash.hpp>
19 #include <anna/core/util/Second.hpp>
20 #include <anna/core/util/Millisecond.hpp>
21 #include <anna/core/util/Microsecond.hpp>
22
23 #include <anna/core/DataBlock.hpp>
24
25
26 #include <time.h>
27 #include <sys/time.h>
28 #include <string>
29 #include <vector>
30
31
32 //------------------------------------------------------------------------------
33 //---------------------------------------------------------------------- #define
34 //------------------------------------------------------------------------------
35 #define s_REGEXP_IPv4_ADDRESSES "\\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b"
36 //#define s_REGEXP_IPv6_ADDRESSES "s*((([0-9A-Fa-f]{1,4}:){7}(([0-9A-Fa-f]{1,4})|:))|(([0-9A-Fa-f]{1,4}:){6}(:|((25[0-5]|2[0-4]\\d|[01]?\\d{1,2})(\\.(25[0-5]|2[0-4]\\d|[01]?\\d{1,2})){3})|(:[0-9A-Fa-f]{1,4})))|(([0-9A-Fa-f]{1,4}:){5}((:((25[0-5]|2[0-4]\\d|[01]?\\d{1,2})(\\.(25[0-5]|2[0-4]\\d|[01]?\\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){4}(:[0-9A-Fa-f]{1,4}){0,1}((:((25[0-5]|2[0-4]\\d|[01]?\\d{1,2})(\\.(25[0-5]|2[0-4]\\d|[01]?\\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){3}(:[0-9A-Fa-f]{1,4}){0,2}((:((25[0-5]|2[0-4]\\d|[01]?\\d{1,2})(\\.(25[0-5]|2[0-4]\\d|[01]?\\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){2}(:[0-9A-Fa-f]{1,4}){0,3}((:((25[0-5]|2[0-4]\\d|[01]?\\d{1,2})(\\.(25[0-5]|2[0-4]\\d|[01]?\\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:)(:[0-9A-Fa-f]{1,4}){0,4}((:((25[0-5]|2[0-4]\\d|[01]?\\d{1,2})(\\.(25[0-5]|2[0-4]\\d|[01]?\\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(:(:[0-9A-Fa-f]{1,4}){0,5}((:((25[0-5]|2[0-4]\\d|[01]?\\d{1,2})(\\.(25[0-5]|2[0-4]\\d|[01]?\\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(((25[0-5]|2[0-4]\\d|[01]?\\d{1,2})(\\.(25[0-5]|2[0-4]\\d|[01]?\\d{1,2})){3})))(%.+)?\\s*"
37 #define s_REGEXP_IPv6_ADDRESSES "s*((([0-9A-Fa-f]{1,4}:){7}(([0-9A-Fa-f]{1,4})|:))|(([0-9A-Fa-f]{1,4}:){6}(:|((25[0-5]|2[0-4]\\d|[01]?\\d{1,2})\
38 (\\.(25[0-5]|2[0-4]\\d|[01]?\\d{1,2})){3})|(:[0-9A-Fa-f]{1,4})))|(([0-9A-Fa-f]{1,4}:){5}((:((25[0-5]|2[0-4]\\d|[01]?\\d{1,2})(\\.(25[0-5]|2[0-4]\
39 \\d|[01]?\\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){4}(:[0-9A-Fa-f]{1,4}){0,1}((:((25[0-5]|2[0-4]\\d|[01]?\\d{1,2})(\\.(\
40 25[0-5]|2[0-4]\\d|[01]?\\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){3}(:[0-9A-Fa-f]{1,4}){0,2}((:((25[0-5]|2[0-4]\\d|[01]?\
41 \\d{1,2})(\\.(25[0-5]|2[0-4]\\d|[01]?\\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){2}(:[0-9A-Fa-f]{1,4}){0,3}((:((25[0-5]|2\
42 [0-4]\\d|[01]?\\d{1,2})(\\.(25[0-5]|2[0-4]\\d|[01]?\\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:)(:[0-9A-Fa-f]{1,4}){0,4}((:\
43 ((25[0-5]|2[0-4]\\d|[01]?\\d{1,2})(\\.(25[0-5]|2[0-4]\\d|[01]?\\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(:(:[0-9A-Fa-f]{1,4}){0,5}((:((25[0-\
44 5]|2[0-4]\\d|[01]?\\d{1,2})(\\.(25[0-5]|2[0-4]\\d|[01]?\\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(((25[0-5]|2[0-4]\\d|[01]?\\d{1,2})(\\.(25[\
45 0-5]|2[0-4]\\d|[01]?\\d{1,2})){3})))(%.+)?\\s*"
46
47 // Helpers for alarm parsing parameters:
48 #define STRING_WITH_QUOTATION_MARKS__C_STR(x)   ((anna::functions::addQuotationMarks(x)).c_str())
49 #define ANNA_AS_STRING__C_STR(x)             ((anna::functions::asString(x)).c_str())
50
51
52
53 namespace anna {
54
55 class DataBlock;
56
57 #ifdef __CYGWIN__
58 #define CLOCK_PROCESS_CPUTIME_ID CLOCK_PROCESS_CPUTIME
59 #endif
60
61
62 /**
63    functions - Métodos y variables
64 */
65 struct functions {
66   /**
67      Tamao de la memoria reservada que debe tener la variable usada para guardar
68      el resultado de convertir el 'time' en texto.
69
70      @see asString
71   */
72   static const int DateTimeSizeString = 21;
73
74   /**
75      @return La versin de functions con la que hemos linkado nuestra aplicacion.
76   */
77   static std::string getVersion() throw();
78
79   /**
80      @return Un literal con la arquitectura sobre la que hemos compilado nuestra aplicacion.
81   */
82   static std::string getArchitecture() throw();
83
84   /**
85      Indica el número de bits de un entero.
86   */
87   static const int intBitSize = sizeof(int) * 8;
88
89   /*
90    * Indica el número de bits de un entero largo.
91    */
92   static const int int64BitSize = sizeof(S64) * 8;
93
94   /**
95      \param number Numero a convertir.
96      @return Un literal con el numero convertido a cadena decimal.
97   */
98   static std::string asString(const int number) throw();
99
100   /**
101      \param number Numero a convertir.
102      @return Un literal con el numero sin signo convertido a cadena decimal.
103   */
104   static std::string asString(const unsigned int number) throw();
105
106   /**
107      \param number Numero a convertir.
108      @return Un literal con el numero sin signo convertido a cadena decimal.
109   */
110   static std::string asString(const unsigned long long int number) throw() {
111     return asString((U64)number);
112   }
113
114   /**
115      \param number Numero a convertir.
116      @return Un literal con el numero sin signo convertido a cadena decimal.
117   */
118   static std::string asString(const long long int number) throw() {
119     return asString((S64)number);
120   }
121
122   /**
123      Devuelve un literal con tel numero convertido a cadena decimal
124      @return Un literal con el numero signo convertido a cadena decimal.
125   */
126   static std::string asString(const S64 number) throw();
127
128   /**
129      Devuelve un literal con tel numero convertido a cadena decimal
130      @return Un literal con el numero signo convertido a cadena decimal.
131   */
132   static std::string asString(const U64 number) throw();
133
134   /**
135      \param _bool Booleano a convertir.
136      \return Un literal con el boolean convertido a cadena.
137   */
138   static const char* asString(const bool _bool) throw() { return (_bool == true) ? "true" : "false"; }
139
140   /**
141      Devuelve una cadena con el bloque de datos decodificado en grupos de 16 bytes.
142      @param dataBlock Bloque de datos a interpretar.
143      \param characterByLine Número de caracteres en cada línea.
144      @return Devuelve una cadena con el bloque de datos decodificado en grupos de 16 bytes.
145   */
146   static std::string asString(const DataBlock& dataBlock, const int characterByLine = 16) throw();
147
148   /**
149      Devuelve una cadena con el numero en coma flotante.
150      \param v Numero a tratar.
151      \param format Formato aplicado para convertir el numero a cadena. Ver \em man printf.
152      \return una cadena con el numero en coma flotante.
153   */
154   static std::string asString(const double v, const char* format = "%e") throw();
155
156   /**
157      Devuelve una cadena con el numero en coma flotante.
158      \param v Numero a tratar.
159      \param format Formato aplicado para convertir el numero a cadena. Ver \em man printf.
160      \return una cadena con el numero en coma flotante.
161   */
162   static std::string asString(const float v, const char* format = "%f") throw();
163
164   /**
165      \param comment Comentario que precede al valor.
166      \param number Numero a convertir.
167      @return Un literal con el numero convertido a cadena decimal.
168   */
169   static std::string asText(const char* comment, const int number)
170   throw() {
171     std::string result(comment);
172     return result += asString(number);
173   }
174
175   /**
176      \param comment Comentario que precede al valor.
177      \param number Numero a convertir.
178      @return Un literal con el numero convertido a cadena decimal.
179   */
180   static std::string asText(const char* comment, const S64 number)
181   throw() {
182     std::string result(comment);
183     return result += asString(number);
184   }
185
186   /**
187       \param comment Comentario que precede al valor.
188       \param _bool Booleano a convertir.
189       @return Un literal con el numero convertido a cadena decimal.
190    */
191   static std::string asText(const char* comment, const bool _bool)
192   throw() {
193     std::string result(comment);
194     return result += asString(_bool);
195   }
196
197   /**
198      \param comment Comentario que precede al valor.
199      \param dataBlock Bloque de datos a interpretar.
200      \param characterByLine Número de caracteres en cada línea.
201      @return Un literal con el numero convertido a cadena decimal.
202   */
203   static std::string asText(const char* comment, const DataBlock& dataBlock, const int characterByLine = 16)
204   throw() {
205     std::string result(comment);
206     return result += asString(dataBlock, characterByLine);
207   }
208
209   /**
210      \param comment Comentario que precede al valor.
211      \param value Numero a tratar.
212      \param format Formato aplicado para convertir el numero a cadena. Ver \em man printf.
213      \return Un literal con el numero convertido a cadena.
214   */
215   static std::string asText(const char* comment, const float value, const char* format = "%f")
216   throw() {
217     std::string result(comment);
218     return result += asString(value, format);
219   }
220
221   /**
222      \param comment Comentario que precede al valor.
223      \param value Numero a tratar.
224      \param format Formato aplicado para convertir el numero a cadena. Ver \em man printf.
225      \return Un literal con el numero convertido a cadena.
226   */
227   static std::string asText(const char* comment, const double value, const char* format = "%e")
228   throw() {
229     std::string result(comment);
230     return result += asString(value, format);
231   }
232
233   /**
234      \param number Numero a convertir.
235      @return Un literal con el numero convertido a cadena hexadecimal.
236   */
237   static std::string asHexString(const int number) throw();
238
239   /**
240      \param number Numero a convertir.
241      @return Un literal con el numero convertido a cadena hexadecimal.
242   */
243   static std::string asHexString(const S64 number) throw();
244
245   /**
246      \param number Numero a convertir.
247      @return Un literal con el numero convertido a cadena hexadecimal.
248   */
249   static std::string asHexString(const U64 number) throw() { return asHexString((S64) number); }
250
251   /**
252      \param comment Comentario que precede al valor.
253      \param number Numero a convertir.
254      @return Un literal con el numero convertido a cadena decimal.
255   */
256   static std::string asHexText(const char* comment, const int number)
257   throw() {
258     std::string result(comment);
259     return result += asHexString(number);
260   }
261
262   /**
263      \param comment Comentario que precede al valor.
264      \param number Numero a convertir.
265      @return Un literal con el numero convertido a cadena decimal.
266   */
267   static std::string asHexText(const char* comment, const S64 number)
268   throw() {
269     std::string result(comment);
270     return result += asHexString(number);
271   }
272
273   /**
274     * Devuelve un cadena con el contenido del bloque de datos interpretado como BCD, pero pasa
275     * cada valor binario a su correspondiente carácter. Por ejemplo, el buffer aa210c quedará como una cadena "AA210C".
276     *
277     * \param dataBlock Bloque a codificar.
278     * \return La cadena que contiene el valor literal del buffer de datos.
279     */
280   static std::string asHexString(const DataBlock& dataBlock) throw();
281
282   /**
283    * Obtiene el valor original de una cadena obtenido con #asHexString (const DataBlock&).
284    * \param hexString Cadena que contiene el búfer.
285    * \param target Bloque de datos sobre el que decodificar la cadena.
286    * \return El bloque de datos original correspondiente a la cadena recibida.
287    */
288   static DataBlock& fromHexString(const std::string& hexString, DataBlock& target) throw(RuntimeException);
289
290   /**
291      Devuelve una cadena con la hora en formato 'dd/mm/yyyy hh:mm:ss'.
292
293      @param second Hora que deseamos traducir.
294
295      @return Un literal con la hora en el formato 'dd/mm/yyyy hh:mm:ss'.
296   */
297   static std::string asDateTime(const Second &second) throw();
298
299   /**
300       Devuelve una cadena con la hora en formato 'dd/mm/yyyy hh:mm:ss'.
301
302       @param second Hora que deseamos traducir.
303       @param result Puntero donde vamos a guardar el resultado de la conversin.
304       Debe tener espacio reservado para contener #TimeSizeAsString caracteres.
305
306       @return El puntero recibido como parametro conteniendo el literal con la hora
307       en el formato 'dd/mm/yyyy hh:mm:ss'.
308    */
309   static const char* asDateTime(const Second &second, char* result) throw();
310
311   /**
312      Calcula la funcion hash de la cadena recibida como parametro.
313      \param str Cadena a la que aplicar la funcion hash.
314   */
315   static S64 hash(const char* str) throw();
316
317   /**
318      Calcula la funcion hash de la cadena recibida como parametro.
319      \param str Cadena a la que aplicar la funcion hash.
320   */
321   static S64 hash(const std::string& str) throw() { return hash(str.c_str()); }
322
323   /**
324      Calcula la funcion hash exclusive de la cadena recibida como parametro.
325      \param str Cadena a la que aplicar la funcion hash exclusiva.
326   */
327   static unsigned long exclusiveHash(const std::string& str) throw() { return st_stringExclusiveHash.calcule(str); }
328
329   /**
330      Calcula la funcion hash exclusive de la cadena recibida como parametro.
331      \param str Cadena a la que aplicar la funcion hash exclusiva.
332   */
333   static unsigned long exclusiveHash(const char* str) throw() { return st_stringExclusiveHash.calcule(std::string(str)); }
334
335   /**
336      Devuelve la cadena que contiene el resultado de aplicar la especificacion \em format
337      sobre el resto de los parametros.
338
339      \param format especificacion de formato similiar al empleado en las funciones \em printf,
340      \em scanf, etc.
341
342      \return la cadena que contiene el resultado de aplicar la especificacion \em format
343      sobre el resto de los parametros.
344   */
345   static std::string asString(const char* format, ...) throw();
346
347   /**
348      Devuelve el resultado de invocar a metodo asString de la clase recibida como parametro.
349      Si t es NULL devolvera el texto indicando la sitacion.
350      \param t Instancia de la clase a usar. Puede ser NULL.
351      \return el resultado de invoca a T::asString () si t es distinto de NULL.
352      \warning La clase T debe tener un metodo estatico con la signatura:
353      \code
354         static const char* className () throw ();
355      \endcode
356   */
357   template <typename T> static std::string asString(const T* t)
358   throw() {
359     if(t == NULL) {
360       std::string result(T::className());
361       result += " { <null> }";
362       return result;
363     }
364
365     return t->asString();
366   }
367
368   /**
369      Metodo identididad. Facilita la implementacion de patrones donde no se conoce el tipo de dato recibido.
370
371      \param str Instancia de la cadena.
372      \return La misma instancia recibida como parametro.
373   */
374   static const std::string& asString(const std::string& str) throw() { return str; }
375
376   /**
377      Detiene la ejecucion del thread durante el numero de milisegundos indicados.
378
379      \param millisecond Numero de milisegundos que vamos a detener la ejecucion de este thread.
380   */
381   static void sleep(const Millisecond &millisecond) throw();
382
383   /**
384      Obtiene el numero de segundos transcurridos desde el 1 del 1 de 1970.
385      \return El numero de segundos transcurridos desde el 1 del 1 de 1970.
386   */
387   static Second second() throw() {
388     Second result(::time(NULL));
389     return result;
390   }
391
392   /**
393      Obtiene el numero de microsegundos transcurridos desde el 1 del 1 de 1970.
394      \return El numero de microsegundos transcurridos desde el 1 del 1 de 1970.
395   */
396   static Microsecond microsecond() throw() {
397     struct timeval tv;
398     gettimeofday(&tv, NULL);
399     Microsecond result((Microsecond::type_t)1000000 * tv.tv_sec + tv.tv_usec);
400     return result;
401   }
402
403   /**
404      Obtiene el numero de milisegundos transcurridos desde el 1 del 1 de 1970.
405      \return El numero de milisegundos transcurridos desde el 1 del 1 de 1970.
406   */
407   static Millisecond millisecond() throw() {
408     struct timeval tv;
409     gettimeofday(&tv, NULL);
410     Millisecond result((Millisecond::type_t)1000 * tv.tv_sec + tv.tv_usec / 1000);
411     return result;
412   }
413
414   /**
415      Devuelve la referencia interna de los microsegundos transcurrido en el procesador.
416      \return la referencia interna de los microsegundos transcurrido en el procesador.
417   */
418   static Microsecond hardwareClock() throw() {
419     timespec ts;
420     //clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts); // DONT works (original)
421     //clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts); // DONT works
422     //clock_gettime(CLOCK_MONOTONIC, &ts); // works
423       // Note that CLOCK_MONOTONIC is subject to discontinuities from system time
424       //  adjustment in Linux. CLOCK_MONOTONIC_RAW was defined to get around this
425       //  (gets hardware time not adjusted by NTP).
426     clock_gettime(CLOCK_MONOTONIC_RAW, &ts); // works
427
428     Microsecond result((Microsecond::type_t)1000000 * ts.tv_sec + ts.tv_nsec / 1000);
429     return result;
430   }
431
432   /**
433      Interpreta la cadena recibida como parametro como un dato de tipo boolean.
434
435      Si la cadena vale NULL, o contiene los literales "false" o "0" devolvera \em false,
436      si contiene los literales "true" o "1" devolvera \em true, en otro caso devolvera un excepcion.
437
438      \param str Cadena a interpretar.
439
440      \return El valor booleano correspondiente a la cadena recibida.
441   */
442   static bool asBool(const char* str) throw(RuntimeException);
443
444   /**
445      Interpreta la cadena recibida como parametro como un entero de 32 bits.
446      \return
447    */
448   static int asInteger(const char* str) throw() { return atoi(str); }
449
450   /**
451      Interpreta la cadena recibida como parametro como un entero de 32 bits.
452      \return
453    */
454   static S64 asInteger64(const char* str) throw();
455
456   /**
457      Devuelve el identificador de thread desde el que es invocado este metodo.
458      Si el programa no tuviera soporta para MT siempre devolvera 0.
459      \return el identificador de thread desde el que es invocado este metodo.
460   */
461   static pthread_t getCurrentThread() throw();
462
463   /**
464      Devuelve \em true si la version de nucleo que estamos ejecutado soporta multithread o \em false en otro
465      caso.
466      \return \em true si la version de nucleo que estamos ejecutado soporta multithread o \em false en otro
467   */
468   static bool supportMultithread() throw() {
469     WHEN_SINGLETHREAD(return false);
470     WHEN_MULTITHREAD(return true);
471   }
472
473   /**
474      Devuelve \em true si el valor recibido cumple el patron establecido o \em false en otro caso.
475      \param pattern Expresion regular que describe el patron a cumplir.
476      \param value Cadena a comparar con el patron.
477      \return \em true si el valor recibido cumple el patron establecido o \em false en otro caso.
478
479      \see regexec para mas informacion sobre las expresiones regulares.
480   */
481   static bool isLike(const char* pattern, const std::string& value) throw(RuntimeException);
482
483   /**
484    * Devuelve el número de bits necesarios para representar el valor recibido como parámetro.
485    * \param n Valor a estudiar.
486    * \return el número de bits necesarios para representar el valor recibido como parámetro.
487    */
488   static int bitsize(const int n) throw() {  return (n == 0) ? 1 : functions::log2(n) + 1; }
489
490   /**
491    * Devuelve el número de bits necesarios para representar el valor recibido como parámetro.
492    * \param n Valor a estudiar.
493    * \return el número de bits necesarios para representar el valor recibido como parámetro.
494    */
495   static int bitsize(const S64 n) throw() {
496     int aux = n >> intBitSize;
497     return (aux != 0) ? (bitsize(aux) + intBitSize) : bitsize((int) n);
498   }
499
500   /**
501    * Calcula la operación (n1 << bitShit) | n2. Establece las comprobaciones necesarias para verificar
502    * que la operación se realiza correctamente, teniendo especial cuidado de que no se puedan solapar
503    * ninguno de los valores.
504    *
505    * \param whatis Literal que debería identificar el punto de invocación en caso de que haya algún error.
506    * \param n1 Número a desplazar el nº de bits indicado por \em bitShift.
507    * \param bitShift Número de bits a desplazar.
508    * \param n2 Número a combinar con el resultado de la operación (n1 << bitShift).
509    */
510   static S64 merge(const char* whatis, const int n1, const int n2, const int bitShift) throw(RuntimeException);
511
512   /**
513    * Calcula el logaritmo en base 2 del número recibo como parámetro.
514    * \param v Valor a calcular.
515    * \return El algoritmo en base 2 del número recibido como parámetro o -1 si el parámetro recibido es 0.
516    */
517   static int log2(const unsigned int v) throw();
518
519
520
521
522   //////////////////////////////////////////////////////////////////////////////////////////////////
523   // Text format resources /////////////////////////////////////////////////////////////////////////
524   //////////////////////////////////////////////////////////////////////////////////////////////////
525   struct TextHighlightMode {
526     enum _v {
527       None = -1, // Initialized
528       Overline,
529       Underline,
530       OverAndUnderline,
531       Leftline,
532       Rightline,
533       LeftAndRightline
534     };
535   };
536
537   struct TextJustifyMode {
538     enum _v {
539       None = -1, // Initialized
540       Left,
541       Center,
542       Right
543     };
544   };
545
546   /**
547      Solve singular/plural literal expression for any number.
548      <pre>
549      Provide (0): returns "no entries"
550      Provide (1): returns "1 entry"
551      Provide (2): returns "2 entries"
552
553      Provide (0, 'table'): returns "no tables"
554      Provide (1, 'table'): returns "1 table"
555      Provide (2, 'table'): returns "2 tables"
556
557      Provide (0, 'query', 'queries'): returns "no queries"
558      Provide (1, 'query', 'queries'): returns "1 query"
559      Provide (2, 'query', 'queries'): returns "2 queries"
560      </pre>
561
562      @param number Amount processed
563      @param wordForSingular Word used as singular, 'entry' by default.
564      @param wordForPlural Word used as plural, 'entries' by default.
565
566      @return Coherent literal as '%d <singular word/plural word>'
567   */
568   static std::string entriesAsString(int number, const char * wordForSingular = NULL, const char * wordForPlural = NULL) throw();
569
570   /**
571      Justify text (traces and output improvement)
572
573      @param title Title processed
574      @param mode Justify mode: Left (default), Center, Right
575      @param filler Filler character used (space by default)
576
577      @return Processed text
578   */
579   static std::string justify(const std::string & title, TextJustifyMode::_v mode = TextJustifyMode::Left, char filler = ' ') throw();
580
581   /**
582      Highligth text (traces and output improvement)
583
584      @param title Title processed
585      @param mode Highlight mode: Overline, Underline(default), OverAndUnderline, Leftline, Rightline, LeftAndRightline
586      @param filler Filler character used (dash by default)
587      @param appendCR Carriage return inclusion (true by default)
588
589      @return Processed text
590   */
591   static std::string highlight(const std::string & title, TextHighlightMode::_v mode = TextHighlightMode::Underline, char filler = '-', bool appendCR = true) throw();
592
593   /**
594      Highligth and justify text (traces and output improvement)
595
596      @param title Title processed
597      @param hMode Highlight mode: Overline, Underline(default), OverAndUnderline, Leftline, Rightline, LeftAndRightline
598      @param jMode Justify mode: Left (default), Center, Right
599      @param highlightFiller Filler character used (double dash ('=') by default)
600      @param justifyFiller Filler character used when justify (space by default)
601      @param appendCR Carriage return inclusion (true by default)
602
603      @return Processed text
604   */
605   static std::string highlightJustify(const std::string & title, TextHighlightMode::_v hMode = TextHighlightMode::OverAndUnderline, TextJustifyMode::_v jMode = TextJustifyMode::Center, char highlightFiller = '=', char justifyFiller = ' ', bool appendCR = true) throw() {
606     return(highlight(justify(title, jMode, justifyFiller), hMode, highlightFiller, appendCR));
607   }
608
609   /**
610      Tabulate text (traces and output improvement)
611
612      @param text Text processed
613      @param tabSpaces Tab spaces (three by default)
614   */
615   static std::string tab(const std::string & text, int tabSpaces = 3) throw();
616
617
618   //////////////////////////////////////////////////////////////////////////////////////////////////
619   // Conversions and helpers ///////////////////////////////////////////////////////////////////////
620   //////////////////////////////////////////////////////////////////////////////////////////////////
621
622   /**
623      Pattern to obtain a multi named component instance easily.
624      Parameters are usually replaced by the macro C <b>FILE_LOCATION</b>.
625
626      \param className Component class name
627      \param fromFile File which called the method
628      \param fromLine Line number within the file from where the method is called.
629
630      \return Component instance for the class provided at the pattern
631      \see Component
632   */
633   template <typename T> static T* componentByName(const char *className, const char* fromFile, const int fromLine)
634   throw(RuntimeException) {
635     ComponentManager &cm = ComponentManager::instantiate();
636     T* result = static_cast <T*>(cm.find(className));
637
638     if(result == NULL) {
639       std::string msg(className);
640       msg += " | Unregistered component";
641       throw RuntimeException(msg, fromFile, fromLine);
642     }
643
644     return result;
645   }
646
647   /**
648      Pattern to obtain a single named component instance easily.
649      Parameters are usually replaced by the macro C <b>FILE_LOCATION</b>.
650
651      \param fromFile File which called the method
652      \param fromLine Line number within the file from where the method is called.
653
654      \return Component instance for the class provided at the pattern
655      \warning T class must implement a method in the form:
656      \code
657          static const char* getClassName () throw ();
658      \endcode
659      \see Component
660   */
661   template <typename T> static T* component(const char* fromFile, const int fromLine)
662   throw(RuntimeException) {
663     return functions::componentByName<T> (T::getClassName(), fromFile, fromLine);
664   }
665
666
667   /**
668    * Gets exclusive hash for string provided on integer range
669    *
670    * @param str String hashed
671    *
672    * @return Hash unique value
673    */
674   static int exclusiveHashInt(const std::string& str) throw() { return st_string2intExclusiveHash.calcule(str); }
675
676   /**
677    * Gets exclusive hash for string (char pointer) provided on integer range
678    *
679    * @param str String hashed
680    *
681    * @return Hash unique value
682    */
683   static int exclusiveHashInt(const char* str) throw() { return st_string2intExclusiveHash.calcule(std::string(str)); }
684
685   /**
686      Finds string at the end of another
687
688      @param pattern String where we find
689      @param suffix Searched string
690
691      @return Boolean about ocurrency
692   */
693   static bool endsWith(const std::string & pattern, const std::string & suffix) throw() {
694     std::string dummy;
695     return endsWith(pattern, suffix, dummy);
696   }
697
698   /**
699      Similar to #endsWith but returning additional preffix string by reference (pattern without suffix)
700   */
701   static bool endsWith(const std::string & pattern, const std::string & suffix, std::string & preffix) throw();
702
703   /**
704      Finds string at the begining of another
705
706      @param pattern String where we find
707      @param preffix Searched string
708
709      @return Boolean about ocurrency
710   */
711   static bool startsWith(const std::string & pattern, const std::string & preffix) throw() {
712     std::string dummy;
713     return startsWith(pattern, preffix, dummy);
714   }
715
716   /**
717      Similar to #startsWith but returning additional suffix string by reference (pattern without preffix)
718   */
719   static bool startsWith(const std::string & pattern, const std::string & preffix, std::string & suffix) throw();
720
721   /**
722      Finds 'item' and replaces it with 'target' within the string provided ('text').
723      The result is returned.
724
725      @param text Original string
726      @param item Searched string
727      @param target String which replaces the item
728      @param all Boolean about replace all items or only the first found. True by default.
729
730      @return Modified string
731   */
732   static std::string replace(const std::string & text, const char *item, const char *target, bool all = true) throw();
733
734   /**
735   * Coverts original string without quotation into quoted one: '\%s'
736   */
737   static std::string addQuotationMarks(const std::string & str) throw();
738   static std::string addQuotationMarks(const char * str) throw();
739   static std::string addQuotationMarks(const int & integer) throw();
740
741   /**
742   * Generates space-separated string lists based on integer elements
743   * Also, another separator could be used.
744   */
745   static std::string vectorToStringRepresentation(const std::vector<int> & v, const char separator = ' ') throw();
746
747   /**
748   * Generates space-separated string lists based on string elements.
749   * Also, another separator could be used.
750   */
751   static std::string vectorToStringRepresentation(const std::vector<std::string> & v, const char separator = ' ') throw();
752
753   /**
754      Returns socket notation 'Address:Port'
755   */
756   static std::string socketLiteralAsString(const std::string & address, int port) throw();
757
758   /**
759      Ascii string for buffer/size data block
760
761      @param buffer Octet string buffer
762      @param size Buffer size
763      @param isFullyPrintable Returned by reference
764
765      @return Ascii string representation, and dots for non-printable cheracters
766   */
767   static std::string asAsciiString(const char * buffer, int size, bool & isFullyPrintable) throw();
768
769   /**
770      Same as #asAsciiString but without interest about if is printable or not
771   */
772   static std::string asAsciiString(const char * buffer, int size) throw() {
773     bool isFullyPrintable;
774     return asAsciiString(buffer, size, isFullyPrintable);
775   }
776
777   /**
778      Same as #asAsciiString providing anna::DataBlock
779   */
780   static std::string asAsciiString(const DataBlock & db, bool & isFullyPrintable) throw() {
781     return asAsciiString(db.getData(), db.getSize(), isFullyPrintable);
782   }
783
784   /**
785      Same as #asAsciiString providing DataBlock and without interest about if is printable or not
786   */
787   static std::string asAsciiString(const DataBlock & db) throw() {
788     bool isFullyPrintable;
789     return asAsciiString(db.getData(), db.getSize(), isFullyPrintable);
790   }
791
792
793   /**
794    * IP Address enconding based on common database 'human-readable raw presentation':
795    * <pre>
796    *    Example for IPv4: 'AABBCCDD' will be DataBlock for '170.187.204.221'
797    *    Example for IPv6: '20010DB885A3000000008A2E03707334' will be DataBlock for '2001:0db8:85a3:0000:0000:8a2e:0370:7334'
798    *
799    *    '000000000000000000000000AABBCCDD' will be encoded as 16-sized Datablock, not IPv4 (4 bytes). Is not recommended to
800    *    put IPv4 on this way because of ambiguity regarding IPv4-compatible format. It is application responsability to trim
801    *    leading zeros in order to use this method for IPv4 source.
802    * </pre>
803    *
804    * @param rawPresentation Input IP address as raw presentation. Must be 8 or 32 sized for IPv4 and IPv6 respectively.
805    *
806    * @return Encoded DataBlock
807    */
808   static DataBlock rawIpPresentationAsRaw(const std::string & rawPresentation) throw(RuntimeException);
809
810
811   /**
812    * IP Address decoding from raw presentation:
813    * <pre>
814    *    Example for IPv4: 'AABBCCDD' will be '170.187.204.221'
815    *    Example for IPv6: '20010DB885A3000000008A2E03707334' will be '2001:0db8:85a3:0000:0000:8a2e:0370:7334'
816    *
817    *    '000000000000000000000000AABBCCDD' will be internally encoded as 16-sized Datablock, not IPv4 (4 bytes).
818    *    Is not recommended to put IPv4 on this way because of ambiguity regarding IPv4-compatible format. It is
819    *    application responsability to trim leading zeros in order to use this method for IPv4 source.
820    * </pre>
821    *
822    * @param rawPresentation Input IP address as raw presentation. Must be 8 or 32 sized for IPv4 and IPv6 respectively.
823    * @param normalize Normalize returned address representation, 'false' by default (to avoid IPv4 to IPv6 conversion)
824    *
825    * @return Decoded IP address
826    */
827   static std::string rawIpPresentationToIpAsString(const std::string & rawPresentation, bool normalize = false) throw(RuntimeException) {
828     return rawIpAsString(rawIpPresentationAsRaw(rawPresentation), normalize);
829   }
830
831
832   /**
833    * IP Address decoding to 'human-readable raw presentation':
834    * <pre>
835    *    Example for IPv4: DataBlock for '170.187.204.221' will be 'AABBCCDD' (a pure IPv4 will never contain leading zeros outside of its scope (i.e., 24 zeros on a 32-character presentation)
836    *    Example for IPv6: DataBlock for '2001:0db8:85a3:0000:0000:8a2e:0370:7334' will be '20010DB885A3000000008A2E03707334'
837    *
838    *    DataBlock for '::170.187.204.221' will be represented as IPv4 compatible: '000000000000000000000000AABBCCDD'
839    * </pre>
840    *
841    * @param db Encoded DataBlock with 4 or 16 bytes to represent Ipv4 or Ipv6.
842    *
843    * @return Human-readable raw IP presentation
844    */
845   static std::string rawIpAsRawIpPresentation(const DataBlock & db) throw(RuntimeException);
846
847
848   /**
849    * Gets the host name (system name)
850    *
851    * @return Hostname
852    */
853   static std::string getHostname() throw();
854
855   /**
856    * Gets the domain name
857    *
858    * @return Domainname
859    */
860   static std::string getDomainname() throw();
861
862   /**
863    * Gets the FQDN (Fully Qualified Domain Name)
864    *
865    * @param hostname Specific provided hostname. Automatically solved if missing. Empty string implies exclusion from FQDN.
866    * @param domainname Specific provided domainname. Automatically solved if missing. Empty string implies exclusion from FQDN.
867    *
868    * @return FQDN (<hostname>.<domainname>)
869    */
870   static std::string getFQDN(const char *hostname = NULL, const char  *domainname = NULL) throw();
871
872   /**
873    * Gets the IP based on hostname (#getHostname)
874    *
875    * @return Hostname-based IP
876    */
877   static std::string getHostnameIP() throw();
878
879
880
881   //////////////////////////////////////////////////////////////////////////////////////////////////
882   // IP Address resources //////////////////////////////////////////////////////////////////////////
883   //////////////////////////////////////////////////////////////////////////////////////////////////
884
885   /**
886   * IPv4 subtype (Estrict/Compatible)
887   */
888   struct IPv4Type {
889     enum _v {
890       Estrict = -1, // Initialized,
891       Compatible,
892       Mapped
893     };
894   };
895
896   /**
897   * IPv4 address family detection
898   *
899   * @param ip IP address
900   * @param ipv4Type Check for IPv4-compatible (i.e. '::192.168.0.1'), IPv4-mapped (i.e. '2001:0db8:85a3:0000:0000:8a2e:192.168.0.1') or estrict IPv4 format.
901   *
902   * @return Boolean for IPv4 nature
903   */
904   static bool isIPv4(const std::string & ip, IPv4Type::_v ipv4Type = IPv4Type::Estrict) throw();
905
906   /**
907   * IPv6 address family detection
908   *
909   * @param ip IP address
910   *
911   * @return Boolean for IPv6 nature
912   */
913   static bool isIPv6(const std::string & ip) throw();
914
915   /**
916    * Convert an IPv4 address to IPv6. Also removes dots from IPv4-mapped format.
917    *
918    * @param ipv4 IP Address in dot notation (192.168.1.100)
919    *
920    * @return string IPv6 formatted address or launch exception if invalid input
921    */
922   static std::string IPv4To6(const std::string & ipv4) throw(RuntimeException);
923
924   /**
925    * Normalizes an IP address to long notation. Specially used for IPv6, but valid for IPv4 (via IPv4To6 conversion).
926    *
927    * Examples:
928    *  ::1 ->                          0000:0000:0000:0000:0000:0000:0000:0001
929    *  2001:db8:85a3::8a2e:370:7334 -> 2001:0db8:85a3:0000:0000:8a2e:0370:7334
930    *
931    * @param ip Input IP address
932    *
933    * @return Normalized IP address
934    */
935   static std::string normalizeIP(const std::string & ip) throw(RuntimeException);
936
937   /**
938    * Compare two IP addresses by mean normalization
939    *
940    * @param ip1 First IP address compared
941    * @param ip2 Second IP address compared
942    *
943    * @return Boolean about IP's comparison
944    */
945   static bool sameIP(const std::string & ip1, const std::string & ip2) throw(RuntimeException);
946
947   /**
948    * Compare two IP addresses by mean internal comparison after ipv6 preffix restriction
949    *
950    * @param ipv6 IPv6 address matched
951    * @param preffixedIpv6 Preffixed IPv6 address (<ipv6>/<preffix length>: only values from 0 (always match) to 128 (maximum restriction) are allowed).
952    *
953    * @return Boolean about subnet matching
954    */
955   static bool matchIPv6(const std::string & ipv6, const std::string & preffixedIpv6) throw(RuntimeException);
956
957   /**
958    * IP Address serialization
959    *
960    * @param ip Input IP address
961    *
962    * @return Encoded DataBlock
963    */
964   static DataBlock ipAsRaw(const std::string & ip) throw(RuntimeException);
965
966   /**
967    * IP Address decoding
968    *
969    * @param db Encoded DataBlock with 4 or 16 bytes to represent Ipv4 or Ipv6.
970    * @param normalize Normalize returned address representation, 'false' by default (to avoid IPv4 to IPv6 conversion)
971    *
972    * @return Decoded IP address
973    */
974   static std::string rawIpAsString(const DataBlock & db, bool normalize = false) throw(RuntimeException) {
975     return (rawIpAsString(db.getData(), db.getSize(), normalize));
976   }
977
978   /**
979    * IP Address decoding
980    *
981    * @param buffer Encoded buffer with 4 or 16 bytes to represent Ipv4 or Ipv6.
982    * @param bufferLength Encoded buffer length with 4 or 16 bytes to represent Ipv4 or Ipv6.
983    * @param normalize Normalize returned address representation, 'false' by default (to avoid IPv4 to IPv6 conversion)
984    *
985    * @return Decoded IP address
986    */
987   static std::string rawIpAsString(const char *buffer, int bufferLength, bool normalize = false) throw(RuntimeException);
988
989   /**
990    * Abbreviates an IP address. Specially used for IPv6, but valid for IPv4.
991    *
992    * Examples:
993    *  0000:0000:0000:0000:0000:0000:0000:0001 -> ::1
994    *  2001:0db8:85a3:0000:0000:8a2e:0370:7334 -> 2001:db8:85a3::8a2e:370:7334
995    *
996    * @param ip Input IP address
997    *
998    * @return Abbreviated IP address
999    */
1000   static std::string abbreviateIP(const std::string & ip) throw(RuntimeException) {
1001     return (rawIpAsString(ipAsRaw(ip)));
1002   }
1003
1004
1005
1006
1007   // socket literal description typedef, vectors and conversion tools
1008
1009   /**
1010   * Extract ADDRESS (ip or hostname ro resolve) and PORT from socket literal description ('<ip|hostname>:<port>').
1011   *
1012   * @param literal Socket literal in format '<ip|hostname>:<port>'
1013   * @param address Address extracted by reference
1014   * @param port Port extracted by reference
1015   */
1016   static void getAddressAndPortFromSocketLiteral(const std::string &literal, std::string &address, int &port) throw();
1017
1018   /**
1019   * Translate pipe-separated socket literal list into Address/Port vector.
1020   *
1021   * @param list Comma-separated Address/Port list. I.e.: '10.95.10.25:4000,10.95.10.25:4001', or 'fed1:4000,fed2:4001'
1022   * @return Address/Port socket items vector
1023   */
1024   static socket_v getSocketVectorFromString(const std::string & list) throw();
1025
1026   /**
1027   * Translate Address/Port vector into comma-separated Address/Port list.
1028   *
1029   * @param socketVector Address/Port vector
1030   *
1031   * @return Comma-separated Address/Port list. I.e.: '10.95.10.25:4000,10.95.10.25:4001', or 'fed1:4000,fed2:4001'
1032   */
1033   static std::string socketVectorAsString(const socket_v & socketVector) throw();
1034
1035
1036   /**
1037     Endianess of the system
1038
1039     @result Returns true when the system is little endian, false if big endian
1040   */
1041   static bool littleEndian() throw();
1042
1043   /**
1044      Encodes an integer number with 32 bits over a buffer with at least 4 bytes of length.
1045      @param result Buffer where the number is encoded.
1046      @param n Number to encode.
1047      \return Buffer with the encoded number.
1048    */
1049   static const char* codeInteger(char* result, const int n) throw();
1050
1051   /**
1052      Encodes an integer number with 16 bits over a buffer with at least 2 bytes of length.
1053      @param result Buffer where the number is encoded.
1054      @param n Number to encode.
1055      \return Buffer with the encoded number.
1056   */
1057   static const char* codeShort(char* result, const short int n) throw();
1058
1059   /**
1060      Encodes an integer number with 64 bits over a buffer with at least 8 bytes of length.
1061      @param result Buffer where the number is encoded.
1062      @param n Number to encode.
1063      \return Buffer with the encoded number.
1064    */
1065   static const char* codeInteger64(char* result, const S64 n) throw();
1066
1067   /**
1068      Encodes a floating number with 32 bits (according to the standard IEEE-754) over a buffer with at least 4 bytes of length.
1069      @param result Buffer where the number is encoded.
1070      @param n Number to encode.
1071      \return Buffer with the encoded number.
1072    */
1073   static const char* codeFloat(char* result, const float n) throw();
1074
1075   /**
1076      Encodes a floating number with 64 bits (according to the standard IEEE-754) over a buffer with at least 8 bytes of length.
1077      @param result Buffer where the number is encoded.
1078      @param n Number to encode.
1079      \return Buffer with the encoded number.
1080    */
1081   static const char* codeDouble(char* result, const double n) throw();
1082
1083   /**
1084      Decodes an 32 bits integer number contained in a 4-bytes buffer.
1085      @param data Buffer with the encoded number.
1086      @return Value for the number contained in the buffer.
1087   */
1088   static int decodeInteger(const char* data)  throw();
1089
1090   /**
1091      Decodes an 16 bits integer number contained in a 2-bytes buffer.
1092      @param data Buffer with the encoded number.
1093      @return Value for the number contained in the buffer.
1094   */
1095   static short int decodeShort(const char* data)  throw();
1096
1097   /**
1098      Decodes an 64 bits integer number contained in a 8-bytes buffer.
1099      @param data Buffer with the encoded number.
1100      @return Value for the number contained in the buffer.
1101   */
1102   static S64 decodeInteger64(const char* data)  throw();
1103
1104   /**
1105      Decodes an 32 bits floating number (according to the standard IEEE-754) contained in a 4-bytes buffer.
1106      @param data Buffer with the encoded number.
1107      @return Value for the number contained in the buffer.
1108   */
1109   static float decodeFloat(const char* data)  throw();
1110
1111   /**
1112      Decodes an 64 bits floating number (according to the standard IEEE-754) contained in a 8-bytes buffer.
1113      @param data Buffer with the encoded number.
1114      @return Value for the number contained in the buffer.
1115   */
1116   static double decodeDouble(const char* data)  throw();
1117
1118
1119   /**
1120   * Decodes an ISUP Number (called or calling party number).
1121   *
1122   * @param buffer Isup number content buffer.
1123   * @param length Isup number content length.
1124   * @param isupNumber Isup number decoded by reference.
1125   * @param calledOrCalling True for called party number, false for calling
1126   */
1127   static void decodeIsupNumber(const char *buffer, int length, isup_number_t & isupNumber, bool calledOrCalling) throw(RuntimeException);
1128
1129   /**
1130   * Encodes an ISUP Number (called or calling party number).
1131   *
1132   * @param isupNumber Isup number.
1133   * @param calledOrCalling True for called party number, false for calling
1134   * @param buffer Isup number content encoded buffer.
1135   * @param length Isup number content encoded length.
1136   */
1137   static void codeIsupNumber(const isup_number_t & isupNumber, bool calledOrCalling, char * buffer, int & length) throw(RuntimeException);
1138
1139   /**
1140   * Encodes an ISUP Number (called or calling party number).
1141   *
1142   * @param isupNumber Isup number.
1143   * @param calledOrCalling True for called party number, false for calling
1144   * @param target Isup number octet string.
1145   */
1146   static void codeIsupNumber(const isup_number_t & isupNumber, bool calledOrCalling, std::string & target) throw(RuntimeException);
1147
1148 private:
1149   static ExclusiveHash <std::string> st_stringExclusiveHash;
1150   static ExclusiveHash <std::string, int> st_string2intExclusiveHash;
1151 };
1152
1153 }
1154
1155 #endif
1156