f75902d5bdaa3a0b486803874eb26c899da9f834
[anna.git] / source / core / functions.cpp
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 #include <stdarg.h>
10 #include <ctype.h>
11 #include <poll.h>
12 #include <time.h>
13 #include <sys/time.h>
14 #include <pthread.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <sys/types.h>
18 #include <regex.h>
19 #include <sys/utsname.h>
20 #include <arpa/inet.h>
21 #include <sys/socket.h> // extraccion de IP del hostname
22 #include <netinet/in.h> // extraccion de IP del hostname
23 #include <netdb.h> // extraccion de IP del hostname
24 #include <unistd.h> // gethostname
25
26 #include <anna/core/functions.hpp>
27 #include <anna/core/DataBlock.hpp>
28 #include <anna/core/tracing/Logger.hpp>
29 #include <anna/core/util/Second.hpp>
30 #include <anna/core/util/Tokenizer.hpp>
31
32 #include <algorithm>
33
34
35 using namespace anna;
36 using namespace std;
37
38 #define PAGE_WIDTH_LENGTH      80
39
40 ExclusiveHash <std::string> functions::st_stringExclusiveHash;
41 ExclusiveHash <std::string, int> functions::st_string2intExclusiveHash;
42
43 string functions::getVersion() throw() {
44   static const int version = ANNA_VERSION;
45   string result;
46   int mainVersion = (version & 0xff00) >> 8;
47   int subVersion = (version & 0xff);
48   char aux [32];
49   sprintf(aux, "%d.%d", mainVersion, subVersion);
50   result = aux;
51   return result += getArchitecture();
52 }
53
54 /*
55 (1) Solo coge los dos primeros digitos del numero de release
56 */
57 string functions::getArchitecture() throw() {
58   string result;
59   WHEN_MULTITHREAD(result = "/MT");
60   WHEN_SINGLETHREAD(result = "/ST");
61 #ifdef _DEBUG
62   result += "/D";
63 #else
64   result += "/O";
65 #endif
66 #ifdef _PROFILE
67   result += 'P';
68 #endif
69   struct utsname un;
70   uname(&un);
71   result += '/';
72   result += un.sysname;
73   result += ' ';
74   char* release = anna_strchr(un.release, '.');               // (1)
75
76   if(release != NULL)
77     if((release = anna_strchr(release + 1, '.')) != NULL)
78       * release = 0;
79
80   result += un.release;
81   result += " (";
82   result += un.machine;
83   result += ")";
84   return result;
85 }
86
87 string functions::asString(const int number)
88 throw() {
89   char aux [16];
90   sprintf(aux, "%d", number);
91   return string(aux);
92 }
93
94 string functions::asString(const S64 number)
95 throw() {
96   char aux [24];
97   //sprintf(aux, "%lld", number);
98   #ifdef __anna64__
99      sprintf (aux, "%ld", number);
100   #else
101      sprintf (aux, "%lld", number);
102   #endif
103   return string(aux);
104 }
105
106 string functions::asString(const unsigned int number)
107 throw() {
108   char aux [16];
109   sprintf(aux, "%u", number);
110   return string(aux);
111 }
112
113 string functions::asString(const U64 number)
114 throw() {
115   char aux [16];
116   //sprintf(aux, "%llu", number);
117   #ifdef __anna64__
118      sprintf (aux, "%lu", number);
119   #else
120      sprintf (aux, "%llu", number);
121   #endif
122   return string(aux);
123 }
124
125 string functions::asString(const float number, const char* format)
126 throw() {
127   char aux [64];
128   sprintf(aux, format, number);
129   return string(aux);
130 }
131
132 string functions::asString(const double number, const char* format)
133 throw() {
134   char aux [64];
135   sprintf(aux, format, number);
136   return string(aux);
137 }
138
139 string functions::asDateTime(const Second &second)
140 throw() {
141   char aux [DateTimeSizeString];
142   return std::string(asDateTime(second, aux));
143 }
144
145 const char* functions::asDateTime(const Second &second, char* result)
146 throw() {
147   struct tm* tt = localtime((time_t*) & second);
148   sprintf(
149     result, "%02d/%02d/%4d %02d:%02d:%02d",
150     tt->tm_mday, tt->tm_mon + 1, tt->tm_year + 1900,
151     tt->tm_hour, tt->tm_min, tt->tm_sec
152   );
153   return result;
154 }
155
156 std::string functions::asString(const DataBlock& dataBlock, const int characterByLine)
157 throw() {
158   return dataBlock.asString(characterByLine);
159 }
160
161 string functions::asHexString(const int number)
162 throw() {
163   char aux [16];
164   sprintf(aux, "0x%x", number);
165   return string(aux);
166 }
167
168 string functions::asHexString(const S64 number)
169 throw() {
170   char aux [32];
171   //sprintf(aux, "0x%llx", number);
172   #ifdef __anna64__
173      sprintf (aux, "0x%lx", number);
174   #else
175      sprintf (aux, "0x%llx", number);
176   #endif
177   return string(aux);
178 }
179
180 // from a version by Allen Holub (see Andrew Binstock, "Hashing Revisited"
181 // Dr. Dobb's Journal, April 1996)
182 S64 functions::hash(const char* p)
183 throw() {
184   static const int long_bits = sizeof(S64) << 3;
185   static const int one_eighth = long_bits >> 3;
186   static const int three_fourths = long_bits * 3 / 4;
187   static const S64 high_bits = ((S64)(~0L)) << (long_bits - one_eighth);
188   S64 result = 0;
189   S64 temp;
190
191   while(*p != 0) {
192     result = (result << one_eighth) + *p ++;
193
194     if((temp = result & high_bits) != 0)
195       result = (result ^(temp >> three_fourths)) &~ high_bits;
196   }
197
198   return result;
199 }
200
201 //static
202 std::string functions::asHexString(const DataBlock& dataBlock)
203 throw() {
204   const char* buffer = dataBlock.getData();
205   const int size = dataBlock.getSize();
206   string result;
207   int byte;
208
209   for(int ii = 0; ii < size; ii ++) {
210     byte = (buffer [ii] & 0xf0) >> 4;
211     result += (byte >= 0 && byte <= 9) ? (byte + '0') : ((byte - 0xa) + 'a');
212     byte = (buffer [ii] & 0x0f);
213     result += (byte >= 0 && byte <= 9) ? (byte + '0') : ((byte - 0xa) + 'a');
214   }
215
216   return result;
217 }
218
219 /**
220  * Gets the original value obtained with #asHexString (const DataBlock&).
221  * \param hexString String which contains the buffer. The format is an hexadecimal octet sequence representation (i.e. 'af012fb3', with even number of digits).
222  * The input shall be preprocessed to comply with that format (e.g. colon or any other non-hex digit must be removed).
223  * \param target DataBlock for string decode.
224  * \return DataBlock corresponding to the provided string.
225  */
226 //static
227 DataBlock& functions::fromHexString(const std::string& hexString, DataBlock& target)
228 throw(RuntimeException) {
229
230   if((hexString.length() % 2) != 0)
231     throw RuntimeException("functions::fromHexString | Invalid string length", ANNA_FILE_LOCATION);
232
233   target.clear();
234   const char* src = hexString.data();
235   unsigned char hex;
236   int aux;
237   int j = 0;
238
239   for(int ii = 1, maxii = hexString.length(); ii < maxii; ii += 2) {
240     if(isxdigit(aux = src [ii - 1]) == 0)
241       throw RuntimeException("Invalid HexString", ANNA_FILE_LOCATION);
242
243     hex = ((aux >= '0' && aux <= '9') ? (aux - '0') : ((aux - 'a') + 0x0a)) << 4;
244
245     if(isxdigit(aux = src [ii]) == 0)
246       throw RuntimeException("Invalid HexString", ANNA_FILE_LOCATION);
247
248     hex |= (aux >= '0' && aux <= '9') ? (aux - '0') : ((aux - 'a') + 0x0a);
249     target += hex;
250   }
251
252   return target;
253 }
254
255 string functions::asString(const char* format, ...)
256 throw() {
257   va_list ap;
258   char aux [1024];
259   va_start(ap, format);
260   vsnprintf(aux, sizeof(aux), format, ap);
261   va_end(ap);
262   return string(aux);
263 }
264
265 void functions::sleep(const Millisecond &millisecond)
266 throw() {
267   timespec req;
268   timespec rem;
269   req.tv_sec = millisecond.getValue() / 1000;                          // segundos
270   req.tv_nsec = (millisecond.getValue() % 1000);                       // milisegundos
271   req.tv_nsec *= 1000000;                                   // mili = 10e-3, nano=10-9
272   int r;
273
274   while((r = nanosleep(&req, &rem)) != 0) {
275     if(errno == EINTR)
276       req = rem;
277     else {
278       string msg(asText("functions::sleep | timespec { sec: ", (int) req.tv_sec));
279       msg += functions::asText("| nsec: ", (int) req.tv_nsec);
280       msg += " }";
281       RuntimeException ex(msg, errno, ANNA_FILE_LOCATION);
282       ex.trace();
283       break;
284     }
285   }
286 }
287
288 bool functions::asBool(const char* str)
289 throw(RuntimeException) {
290   if(str == NULL)
291     return false;
292
293   if(strcasecmp(str, "true") == 0 || anna_strcmp(str, "1") == 0)
294     return true;
295
296   if(strcasecmp(str, "false") == 0 || anna_strcmp(str, "0") == 0)
297     return false;
298
299   string msg("anna::funcions::asBool | Cannot interpret '");
300   msg += str;
301   msg += "' as boolean";
302   throw RuntimeException(msg, ANNA_FILE_LOCATION);
303 }
304
305 S64 functions::asInteger64(const char* str)
306 throw() {
307   S64 number = 0;
308   //sscanf(str, "%lld", &number);
309   #ifdef __anna64__
310     sscanf (str, "%ld", &number);
311   #else
312      sscanf (str, "%lld", &number);
313   #endif
314   return number;
315 }
316
317 pthread_t functions::getCurrentThread()
318 throw() {
319   WHEN_MULTITHREAD(return pthread_self());
320   WHEN_SINGLETHREAD(return 0);
321 }
322
323 bool functions::isLike(const char* pattern, const std::string& _value)
324 throw(RuntimeException) {
325   const char* value = _value.c_str();
326   regex_t preg;
327   int ret;
328
329   if((ret = regcomp(&preg, pattern, REG_EXTENDED)) != 0) {
330     char err[256];
331     string msg("anna::functions::isLike | ");
332     msg += " | Pattern: ";
333     msg += pattern;
334     msg += " | Value: ";
335     msg += value;
336     msg += " | ";
337
338     if(regerror(ret, &preg, err, sizeof(err)))
339       msg += err;
340     else
341       msg += "Invalid pattern";
342
343     throw RuntimeException(msg, ANNA_FILE_LOCATION);
344   }
345
346   const bool result = (regexec(&preg, value, 0, NULL, 0) == 0) ? true : false;
347
348   regfree(&preg);
349   return result;
350 }
351
352 /*static*/
353 S64 functions::merge(const char* whatis, const int n1, const int n2, const int bitShift)
354 throw(RuntimeException) {
355   if(bitShift > intBitSize) {
356     string msg(functions::asString("%s | N1: 0x%x | N2: 0x%x | bitShift: %d | bitShift must be less than %d", whatis, n1, n2, bitShift, intBitSize));
357     throw RuntimeException(msg, ANNA_FILE_LOCATION);
358   }
359
360   if((bitsize(n1) + bitShift) > int64BitSize) {
361     string msg(functions::asString("%s | N1: 0x%x | N2: 0x%x | bitShift: %d | N1 overload", whatis, n1, n2, bitShift));
362     throw RuntimeException(msg, ANNA_FILE_LOCATION);
363   }
364
365   if(bitsize(n2) > bitShift) {
366     string msg(functions::asString("%s | N1: 0x%x | N2: 0x%x | bitShift: %d | N2 overload", whatis, n1, n2, bitShift));
367     throw RuntimeException(msg, ANNA_FILE_LOCATION);
368   }
369
370   S64 result = n1;
371   result <<= bitShift;
372   result |= n2;
373
374   if(bitShift == intBitSize) {
375     LOGINFORMATION(
376       string msg(functions::asString("%s | N1: 0x%x | N2: 0x%x | bitShift: %d | ", whatis, n1, n2, bitShift));
377       msg += functions::asHexString(result);
378       Logger::information(msg, ANNA_FILE_LOCATION);
379     );
380   }
381
382   return result;
383 }
384
385 /*static*/
386 /*
387  * Basado en el algoritmo de http://www-graphics.stanford.edu/~seander/bithacks.html#IntegerLogLookup
388  */
389 int functions::log2(const unsigned int v)
390 throw() {
391   static const char LogTable256[] = {
392     -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
393     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
394     5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
395     5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
396     6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
397     6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
398     6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
399     6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
400     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
401     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
402     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
403     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
404     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
405     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
406     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
407     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
408   };
409   int r = -1;     // r will be lg(v)
410   unsigned int t, tt; // temporaries
411
412   if((tt = v >> 16)) {
413     r = ((t = tt >> 8)) ? 24 + LogTable256[t] : 16 + LogTable256[tt];
414   } else {
415     r = (t = v >> 8) ? 8 + LogTable256[t] : LogTable256[v];
416   }
417
418   return r;
419 }
420
421 std::string functions::entriesAsString(int number, const char * wordForSingular, const char * wordForPlural) throw() {
422   std::string result;
423   std::string singular = (wordForSingular ? wordForSingular : "entry");
424   std::string plural = (wordForPlural ? wordForPlural : "entries");
425
426   if(wordForSingular && !wordForPlural)
427     plural = singular + "s";
428
429   result += ((number != 0) ? anna::functions::asString(number) : "no");
430   result += " ";
431   result += ((number != 1) ? plural : singular);
432   return result;
433 }
434
435
436 std::string functions::justify(const std::string & title, TextJustifyMode::_v mode, char filler) throw() {
437   std::string result;
438   int d_size = title.size();
439   int repeat = PAGE_WIDTH_LENGTH - d_size - 1;
440   bool adjust = false;
441
442   if(mode == TextJustifyMode::Center) {
443     repeat = (repeat - 1) / 2;
444     adjust = (2 * (repeat + 1) + d_size != PAGE_WIDTH_LENGTH);
445   }
446
447   if((mode == TextJustifyMode::Right) || (mode == TextJustifyMode::Center)) {
448     for(int k = 0; k < (repeat + (adjust ? 1 : 0)); k++) result += filler;
449
450     result += " ";
451   }
452
453   result += title;
454
455   if((mode == TextJustifyMode::Left) || (mode == TextJustifyMode::Center)) {
456     result += " ";
457
458     for(int k = 0; k < repeat; k++) result += filler;
459   }
460
461   return result;
462 }
463
464
465 std::string functions::highlight(const std::string & title, TextHighlightMode::_v mode, char filler, bool appendCR) throw() {
466   std::string result;
467   int ou_repeat = title.size();
468   int lr_repeat = PAGE_WIDTH_LENGTH - ou_repeat - 1;
469   bool adjust = false;
470
471   if(mode == TextHighlightMode::LeftAndRightline) {
472     lr_repeat = (lr_repeat - 1) / 2;
473     adjust = (2 * (lr_repeat + 1) + ou_repeat != PAGE_WIDTH_LENGTH);
474   }
475
476   if((mode == TextHighlightMode::Leftline) || (mode == TextHighlightMode::LeftAndRightline)) {
477     for(int k = 0; k < (lr_repeat + (adjust ? 1 : 0)); k++) result += filler;
478
479     result += " ";
480   }
481
482   if((mode == TextHighlightMode::Overline) || (mode == TextHighlightMode::OverAndUnderline)) {
483     for(int k = 0; k < ou_repeat; k++) result += filler;
484
485     result += "\n";
486   }
487
488   result += title;
489
490   if((mode == TextHighlightMode::Underline) || (mode == TextHighlightMode::OverAndUnderline)) {
491     result += "\n";
492
493     for(int k = 0; k < ou_repeat; k++) result += filler;
494   }
495
496   if((mode == TextHighlightMode::Rightline) || (mode == TextHighlightMode::LeftAndRightline)) {
497     result += " ";
498
499     for(int k = 0; k < lr_repeat; k++) result += filler;
500   }
501
502   if(appendCR) result += "\n";
503
504   return result;
505 }
506
507
508 std::string functions::tab(const std::string & text, int tabSpaces) throw() {
509   std::string result;
510   size_t pos, from = 0;
511   std::string tab, crTab = "\n";
512
513   for(int k = 0; k < tabSpaces; k++) tab += " ";
514
515   crTab += tab;
516   result = tab;
517   result += text;
518
519   while(((pos = result.find('\n', from)) != std::string::npos) && (pos != (result.size() - 1)/*exclude last CR if exists*/)) {
520     result.replace(pos, 1, crTab);
521     from = pos + 1;
522   }
523
524   return result;
525 }
526
527
528 bool functions::endsWith(const std::string & pattern, const std::string & suffix, std::string & preffix) throw() {
529   preffix = "";
530
531   if(pattern.size() < suffix.size()) return false;
532
533   size_t pos = pattern.rfind(suffix);
534
535   if(pos == std::string::npos) return false;
536
537   preffix.assign(pattern.c_str(), pos);
538   return (pos == (pattern.size() - suffix.size()));
539 }
540
541
542 bool functions::startsWith(const std::string & pattern, const std::string & preffix, std::string & suffix) throw() {
543   suffix = "";
544
545   if(pattern.size() < preffix.size()) return false;
546
547   if(pattern.find(preffix) != 0) return false;
548
549   suffix.assign(pattern.c_str(), preffix.size(), pattern.size() - preffix.size());
550   return true;
551 }
552
553
554 std::string functions::replace(const std::string & text, const char *item, const char *target, bool all) throw() {
555   std::string result = text;
556
557   if(!item || !target) return result;  // protection for NULL strings provided
558
559   size_t lengthReplaced = strlen(item);
560   size_t pos = result.find(item);
561
562   while(pos != std::string::npos) {
563     result.replace(pos, lengthReplaced, target);
564
565     if(!all) break;
566
567     pos = result.find(item);
568   }
569
570   return result;
571 }
572
573
574 std::string functions::addQuotationMarks(const std::string & str) throw() {
575   std::string result = "'";
576   result += str;
577   result += "'";
578   return (result);
579 }
580
581
582 std::string functions::addQuotationMarks(const char * str) throw() {
583   std::string result = "'";
584   result += (str ? str : "<null>");
585   result += "'";
586   return (result);
587 }
588
589
590 std::string functions::addQuotationMarks(const int & integer) throw() {
591   std::string result = "'";
592   result += anna::functions::asString(integer);
593   result += "'";
594   return (result);
595 }
596
597
598 std::string functions::vectorToStringRepresentation(const std::vector<int> & v, const char separator) throw() {
599   std::string result = "";
600
601   if(v.size() != 0) {
602     std::vector<int>::const_iterator iter;
603     std::vector<int>::const_iterator iter_min(v.begin());
604     std::vector<int>::const_iterator iter_max(v.end());
605
606     for(iter = iter_min; iter != iter_max; iter++) {
607       result += anna::functions::asString(*iter);
608       result += separator;
609     }
610
611     // Delete the last space: starts at 'size()-1', take 1 caracter:
612     result.erase(result.size() - 1, 1);
613   }
614
615   return (result);
616 }
617
618
619 std::string functions::vectorToStringRepresentation(const std::vector<std::string> & v, const char separator) throw() {
620   std::string result = "";
621
622   if(v.size() != 0) {
623     std::vector<std::string>::const_iterator iter;
624     std::vector<std::string>::const_iterator iter_min(v.begin());
625     std::vector<std::string>::const_iterator iter_max(v.end());
626
627     for(iter = iter_min; iter != iter_max; iter++) {
628       result += (*iter);
629       result += separator;
630     }
631
632     // Delete the last space: starts at 'size()-1', take 1 caracter:
633     result.erase(result.size() - 1, 1);
634   }
635
636   return (result);
637 }
638
639
640 std::string functions::socketLiteralAsString(const std::string & address, int port) throw() {
641   std::string result = address;
642   result += ":";
643   result += anna::functions::asString(port);
644   return result;
645 }
646
647
648 std::string functions::asAsciiString(const char * buffer, int size, bool & isFullyPrintable) throw() {
649   std::string result;
650   // Supposed printable by default:
651   isFullyPrintable = true;
652
653   if(size == 0 || !buffer) {
654     result = "<null>";
655     isFullyPrintable = false;
656     return result;
657   }
658
659   for(int k = 0; k < size; k ++) {
660     unsigned char c = (unsigned char) buffer [k];
661     int printable = isprint(c);
662     result += (printable ? (char) c : '.');
663
664     if(!printable) isFullyPrintable = false;
665   }
666
667   return result;
668 }
669
670
671 std::string functions::getHostname() throw() {
672   char aux[255];
673   std::string result = "<hostname>";
674
675   if(gethostname(aux, sizeof aux) == 0 /*success*/)
676     result = aux;
677
678   return result;
679 }
680
681 std::string functions::getDomainname() throw() {
682   char aux[256];
683   std::string result = "<domainname>";
684
685   if(getdomainname(aux, sizeof aux) == 0 /*success*/)
686     result = aux;
687
688   return result;
689 }
690
691 std::string functions::getFQDN(const char *hostname, const char *domainname) throw() {
692   std::string hn = hostname ? hostname : (functions::getHostname());
693   std::string dn = domainname ? domainname : (functions::getDomainname());
694   // FQDN is limited to 255 bytes, with aditional restriction: 63 bytes label within a domain name.
695
696   if(hn == "") return dn;
697
698   if(dn == "") return hn;
699
700   std::string label(hn, 0, 63);
701   std::string fqdn(label + "." + dn, 0, 255);
702   return fqdn;
703 }
704
705 std::string functions::getHostnameIP() throw() {
706   std::string result = "";
707   struct hostent *he;
708   struct in_addr **addr_list;
709   struct in_addr ipv4addr;
710   char hostname[128];
711   gethostname(hostname, sizeof hostname);
712
713   if((he = gethostbyname(hostname)) != NULL) {
714     // Official name: he->h_name
715     // IP addresses:
716     addr_list = (struct in_addr **)he->h_addr_list;
717
718     for(int i = 0; addr_list[i] != NULL; i++) {
719       //printf("%s ", inet_ntoa(*addr_list[i]));
720       result = inet_ntoa(*addr_list[i]);
721       return result;
722     }
723   }
724
725   return result;
726 }
727
728
729 anna::DataBlock functions::rawIpPresentationAsRaw(const std::string & rawPresentation) throw(anna::RuntimeException) {
730   int length = rawPresentation.size();
731
732   if(length != 8 && length != 32)
733     throw anna::RuntimeException("functions::rawIpPresentationAsRaw | Expected 8 or 32-sized raw IP presentation provided", ANNA_FILE_LOCATION);
734
735   anna::DataBlock result(true);
736   int byte;
737   char rByte[3]; // readable byte
738   rByte[2] = 0;
739
740   for(int k = 0; k < length; k += 2) {
741     rByte[0] =  rawPresentation[k];
742     rByte[1] = rawPresentation[k + 1];
743     sscanf(rByte, "%x", &byte);
744     result += byte;
745   }
746
747   return result;
748 }
749
750
751 std::string functions::rawIpAsRawIpPresentation(const anna::DataBlock & db) throw(anna::RuntimeException) {
752   int length = db.getSize();
753
754   if(length != 4 && length != 16)
755     throw anna::RuntimeException("functions::rawIpAsRawIpPresentation | Expected 4 or 16-sized raw IP DataBlock provided", ANNA_FILE_LOCATION);
756
757   std::string result = "";
758   int byte;
759   char rByte[3]; // readable byte
760   rByte[2] = 0;
761
762   for(int k = 0; k < length; k++) {
763     byte = (unsigned char)db[k];
764     sprintf(rByte, "%.2X", byte);
765     result += rByte;
766   }
767
768   return result;
769 }
770
771
772
773 ////////////////////
774 // Address Format //
775 ////////////////////
776 //   IPv6 addresses have two logical parts: a 64-bit network prefix, and a 64-bit host address part. (The host address is often automatically generated from the interface MAC address.[34]) An IPv6 address is represented by 8 groups of 16-bit hexadecimal values separated by colons (:) shown as follows:
777 //   A typical example of an IPv6 address is
778 //   2001:0db8:85a3:0000:0000:8a2e:0370:7334
779 //   The hexadecimal digits are case-insensitive.
780 //
781 //   The 128-bit IPv6 address can be abbreviated with the following rules:
782 //   -Rule one: Leading zeroes within a 16-bit value may be omitted. For example, the address fe80:0000:0000:0000:0202:b3ff:fe1e:8329 may be written as fe80:0:0:0:202:b3ff:fe1e:8329
783 //   -Rule two: A single occurrence of consecutive groups of zeroes within an address may be replaced by a double colon. For example, fe80:0:0:0:202:b3ff:fe1e:8329 becomes fe80::202:b3ff:fe1e:8329
784 //   A single IPv6 address can be represented in several different ways, such as 2001:db8::1:0:0:1 and 2001:0DB8:0:0:1::1. RFC 5952 recommends a canonical textual representation.
785
786 //      Si la dirección tiene más de una serie de grupos nulos consecutivos la compresión sólo se permite en uno de ellos.
787 //      Así, las siguientes son representaciones posibles de una misma dirección:
788 //
789 //      2001:0DB8:0000:0000:0000:0000:1428:57ab
790 //      2001:0DB8:0000:0000:0000::1428:57ab
791 //      2001:0DB8:0:0:0:0:1428:57ab
792 //      2001:0DB8:0::0:1428:57ab
793 //      2001:0DB8::1428:57ab
794 //      son todas válidas y significan lo mismo, pero
795 //      2001::25de::cade
796 //          --    --
797 //      no es válida porque no queda claro cuántos grupos nulos hay en cada lado.
798 //
799 //      Los ceros iniciales en un grupo también se pueden omitir:
800 //      2001:0DB8:02de::0e13
801 //      2001:DB8:2de::e13
802 //
803 //      Si la dirección es una dirección IPv4 empotrada (mapped), los Ãºltimos 32 bits pueden escribirse en base decimal, así:
804 //      ::ffff:192.168.89.9
805 //      ::ffff:c0a8:5909
806 //
807 //      No se debe confundir con:
808 //      ::192.168.89.9
809 //      ::c0a8:5909
810 //
811 //      El formato ::ffff:1.2.3.4 se denomina dirección IPv4 mapeada, y el formato ::1.2.3.4 dirección IPv4 compatible.
812 //      Las direcciones IPv4 pueden ser transformadas fácilmente al formato IPv6. Por ejemplo, si la dirección decimal IPv4 es 135.75.43.52
813 //       (en hexadecimal, 0x874B2B34), puede ser convertida a 0000:0000:0000:0000:0000:0000:874B:2B34 o ::874B:2B34. Entonces, uno puede usar
814 //       la notación mixta dirección IPv4 compatible, en cuyo caso la dirección debería ser ::135.75.43.52. Este tipo de dirección IPv4 compatible
815 //       casi no está siendo utilizada en la práctica, aunque los estándares no la han declarado obsoleta.
816 //
817 // http://tools.ietf.org/html/rfc5952: canonical text representation recommendation
818
819 bool functions::isIPv4(const std::string & ip, IPv4Type::_v ipv4Type) throw() {
820   if(ipv4Type == IPv4Type::Estrict) {
821     // La expresión regular no controla si hay mas de 3 puntos:
822     int n_dot = 0;
823
824     for(int k = 0; k < ip.length(); k++)
825       if(ip[k] == '.') n_dot++;
826
827     if(n_dot > 3)
828       return (false);
829
830     bool ipv4 = anna::functions::isLike(s_REGEXP_IPv4_ADDRESSES, ip);
831     bool colon = (ip.find(":") != std::string::npos);
832     return (ipv4 && !colon);
833   }
834
835   if(ipv4Type == IPv4Type::Compatible) {
836     std::string pureIPv4 = ip;
837     bool firstDoubleColon = (ip.find("::") == 0);
838
839     if(firstDoubleColon) {
840       pureIPv4.erase(0, 2);
841       bool anotherColon = (pureIPv4.find(":") != std::string::npos);
842
843       if(anotherColon) return (false);
844
845       return (anna::functions::isLike(s_REGEXP_IPv4_ADDRESSES, pureIPv4));
846     }
847   }
848
849   if(ipv4Type == IPv4Type::Mapped) {
850     size_t posLastColon = ip.rfind(":");
851
852     if(posLastColon == std::string::npos)
853       return (false);
854
855     if(!isIPv4(ip.substr(posLastColon + 1)))
856       return (false);
857
858     unsigned char buf[sizeof(struct in6_addr)];
859     int s = inet_pton(AF_INET6, ip.c_str(), buf);
860
861     if(s > 0)
862       return (true);
863   }
864
865   return false;
866 }
867
868
869 bool functions::isIPv6(const std::string & ip) throw() {
870   // Chequeo de digitos permitidos:
871   for(int k = 0; k < ip.length(); k++) {
872     bool digit = isdigit(ip[k]);
873     bool hex = ((ip[k] == 'a') ||
874                 (ip[k] == 'b') ||
875                 (ip[k] == 'c') ||
876                 (ip[k] == 'd') ||
877                 (ip[k] == 'e') ||
878                 (ip[k] == 'f') ||
879                 (ip[k] == 'A') ||
880                 (ip[k] == 'B') ||
881                 (ip[k] == 'C') ||
882                 (ip[k] == 'D') ||
883                 (ip[k] == 'E') ||
884                 (ip[k] == 'F'));
885     bool colon = (ip[k] == ':');
886
887     if(!digit && !hex && !colon)
888       return false;
889   }
890
891   return (anna::functions::isLike(s_REGEXP_IPv6_ADDRESSES, ip));
892 }
893
894
895 std::string functions::IPv4To6(const std::string & ip) throw(anna::RuntimeException) {
896   if(!isIPv4(ip, IPv4Type::Estrict) && !isIPv4(ip, IPv4Type::Compatible) && !isIPv4(ip, IPv4Type::Mapped))
897     throw anna::RuntimeException("functions::IPv4To6 | Expected IPv4, IPv4-compatible or IPv4-mapped address format", ANNA_FILE_LOCATION);
898
899   std::string result, pureIPv4;
900   bool firstDoubleColon = (ip.find("::") == 0);
901
902   if(firstDoubleColon) {
903     // Clean '::'
904     size_t ipv4_pos = ip.rfind(":") /* last ocurrence */ + 1;
905     pureIPv4 = ip.substr(ipv4_pos);
906   } else {
907     if(!isIPv4(ip)) {
908       size_t posColon = ip.find(":");
909
910       if(posColon == 0)  // first colon
911         throw anna::RuntimeException("functions::IPv4To6 | Invalid IPv4 address format", ANNA_FILE_LOCATION);
912
913       if(posColon != std::string::npos)  // any colon
914         return ip; // seems to be IPv6 already?
915
916       throw anna::RuntimeException("functions::IPv4To6 | Unreconized IPv4 address format", ANNA_FILE_LOCATION);
917     }
918
919     pureIPv4 = ip;
920   }
921
922   // Number of ocurrences for '.'
923   int n_dot = 0;
924
925   for(int k = 0; k < pureIPv4.length(); k++)
926     if(pureIPv4[k] == '.') n_dot++;
927
928   if(n_dot > 3)
929     throw anna::RuntimeException("functions::IPv4To6 | Wrong IPv4 address format (more than three dots!)", ANNA_FILE_LOCATION);
930
931   anna::Tokenizer tok;
932   anna::Tokenizer::const_iterator tok_it;
933   std::string token;
934   tok.apply(pureIPv4, ".");
935   int v[4];
936   int cnt = 0;
937
938   for(tok_it = tok.begin(); tok_it != tok.end(); tok_it ++) {
939     token = anna::Tokenizer::data(tok_it);
940     v[cnt] = atoi(anna::Tokenizer::data(tok_it));
941
942     if(v[cnt] < 0 || v[cnt] > 255)
943       throw anna::RuntimeException("functions::IPv4To6 | Wrong IPv4 address format (any value out of range 0-255)", ANNA_FILE_LOCATION);
944
945     cnt++;
946   }
947
948   if(isIPv4(ip, IPv4Type::Compatible))
949     result = anna::functions::asString("::%04x:%04x", v[0] * 256 + v[1], v[2] * 256 + v[3]);
950   else
951     result = anna::functions::asString("::ffff:%04x:%04x", v[0] * 256 + v[1], v[2] * 256 + v[3]);
952
953   return result;
954 }
955
956
957 std::string functions::normalizeIP(const std::string & ip) throw(anna::RuntimeException) {
958   std::string result = ip;
959 //   std::transform(result.begin(), result.end(), result.begin(), (int (*)(int))std::tolower);
960   std::transform(result.begin(), result.end(), result.begin(), ::tolower);
961
962   if(isIPv4(ip, IPv4Type::Estrict) || isIPv4(ip, IPv4Type::Compatible) || isIPv4(ip, IPv4Type::Mapped))
963     result = IPv4To6(result);
964
965   size_t pos = result.find("::"); // zeroes simplification group
966   size_t rpos = result.rfind("::"); // zeroes simplification group
967
968   if(pos != rpos)
969     throw anna::RuntimeException("functions::normalizeIP | Wrong IPv6 address format (more than one simplification group '::')", ANNA_FILE_LOCATION);
970
971   if(pos != std::string::npos) {  // zeroes exists
972     // string ( size_t n, char c ) -> content is initialized as a string formed by a repetition of character c, n times.
973     // Number of ocurrences for ':'
974     int n_colon = 0;
975
976     for(int k = 0; k < result.length(); k++)
977       if(result[k] == ':') n_colon++;
978
979     // Generate equivalent to '::'
980     std::string equiv_str;
981
982     for(int k = 0; k < (8 - n_colon); k++)
983       equiv_str += ":0";
984
985     equiv_str += ":";
986     // Replace with equivalent:
987     result.replace(pos, 2, equiv_str);
988
989     // Special case: IP began with '::'
990     if(result[0] == ':') {
991       result.insert(0, "0");
992     }
993
994     // Special case: IP was only '::'
995     if(result[result.length() - 1] == ':') {
996       result += "0";
997     }
998   }
999
1000   // Protection: it must be seven colons:
1001   int n_colon = 0;
1002
1003   for(int k = 0; k < result.length(); k++)
1004     if(result[k] == ':') n_colon++;
1005
1006   if(n_colon != 7)
1007     throw anna::RuntimeException("functions::normalizeIP | Wrong IPv6 address format (missing any 16-bit group)", ANNA_FILE_LOCATION);
1008
1009   // Padding with zeroes at left
1010   anna::Tokenizer ipStr;
1011   anna::Tokenizer::const_iterator ipStr_it;
1012   std::string token;
1013   ipStr.apply(result, ":");
1014   result = "";
1015
1016   for(ipStr_it = ipStr.begin(); ipStr_it != ipStr.end(); ipStr_it ++) {
1017     token = anna::Tokenizer::data(ipStr_it);
1018
1019     while(token.length() < 4) token.insert(0, "0");
1020
1021     result += token;
1022     result += ":";
1023   }
1024
1025   // Remove last ':'
1026   size_t lastPos = result.length() - 1;
1027   result.erase(lastPos, 1);
1028
1029   // Chequeo de digitos permitidos:
1030   for(int k = 0; k < result.length(); k++) {
1031     bool digit = isdigit(result[k]);
1032     bool hex = ((result[k] == 'a') ||
1033                 (result[k] == 'b') ||
1034                 (result[k] == 'c') ||
1035                 (result[k] == 'd') ||
1036                 (result[k] == 'e') ||
1037                 (result[k] == 'f'));
1038     bool colon = (result[k] == ':');
1039
1040     if(!digit && !hex && !colon) {
1041       throw anna::RuntimeException("functions::normalizeIP | Invalid address format (only digits (0-9) and hex digits are allowed)", ANNA_FILE_LOCATION);
1042     }
1043   }
1044
1045   return result;
1046 }
1047
1048
1049 bool functions::sameIP(const std::string & ip1, const std::string & ip2) throw(anna::RuntimeException) {
1050   //if (ip1 == ip2) return true; it should validate wrong-format addresses
1051   return (normalizeIP(ip1) == normalizeIP(ip2));
1052 }
1053
1054
1055 bool functions::matchIPv6(const std::string & _ipv6, const std::string & preffixedIpv6) throw(anna::RuntimeException) {
1056   size_t preffixPos = preffixedIpv6.find("/");
1057
1058   if(preffixPos == std::string::npos)
1059     return (sameIP(_ipv6, preffixedIpv6));
1060
1061   std::string ipv6 = _ipv6;
1062
1063   if(isIPv4(_ipv6, IPv4Type::Estrict) || isIPv4(_ipv6, IPv4Type::Compatible) || isIPv4(_ipv6, IPv4Type::Mapped)) ipv6 = IPv4To6(_ipv6);
1064
1065   std::string _ipv6_2 = preffixedIpv6.substr(0, preffixPos);
1066   std::string ipv6_2 = _ipv6_2;
1067
1068   if(isIPv4(_ipv6_2, IPv4Type::Estrict) || isIPv4(_ipv6_2, IPv4Type::Compatible) || isIPv4(_ipv6_2, IPv4Type::Mapped)) ipv6_2 = IPv4To6(_ipv6_2);
1069
1070   std::string preffix = preffixedIpv6.substr(preffixPos + 1);
1071   int ipv6_2_preffixLength = atoi(preffix.c_str());
1072
1073   if(ipv6_2_preffixLength < 0 || ipv6_2_preffixLength > 128)
1074     throw anna::RuntimeException("functions::matchIPv6 | Invalid Ipv6 preffix length: out of range [0,128]", ANNA_FILE_LOCATION);
1075
1076   // No restriction, all ipv6_2 ignored (special and not usual case)
1077   if(ipv6_2_preffixLength == 0) return true;
1078
1079   // Auxiliary data:
1080   int spare = ipv6_2_preffixLength /* bits */ % 8; // bytes
1081   int incompletedRestrictionBytes = ipv6_2_preffixLength / 8;
1082   int completedRestrictionBytes = incompletedRestrictionBytes + ((spare != 0) ? 1 : 0);
1083   char mask = 0xFF << (8 - spare);
1084   // Limit ipv6
1085   anna::DataBlock rawIP1 = ipAsRaw(ipv6);
1086   anna::DataBlock restrictedIP1(true);
1087   restrictedIP1.assign(rawIP1.getData(), incompletedRestrictionBytes);
1088
1089   if(spare != 0) restrictedIP1 += rawIP1[incompletedRestrictionBytes] & mask;
1090
1091   // Limit ipv6_2
1092   anna::DataBlock rawIP2 = ipAsRaw(ipv6_2);
1093   anna::DataBlock realIP2(true);
1094   realIP2.assign(rawIP2.getData(), incompletedRestrictionBytes);
1095
1096   if(spare != 0) realIP2 += rawIP2[incompletedRestrictionBytes] & mask;
1097
1098   // Comparison
1099   int n = memcmp(restrictedIP1.getData(), realIP2.getData(), completedRestrictionBytes);
1100   return (n == 0);
1101 }
1102
1103
1104 anna::DataBlock functions::ipAsRaw(const std::string & ip) throw(anna::RuntimeException) {
1105   anna::DataBlock result(true);
1106
1107   if(isIPv4(ip)) {
1108     unsigned char buf[sizeof(struct in6_addr)];
1109     int s = inet_pton(AF_INET, ip.c_str(), buf);
1110
1111     if(s > 0) {
1112       result += (S8)buf[0];
1113       result += (S8)buf[1];
1114       result += (S8)buf[2];
1115       result += (S8)buf[3];
1116     } else {
1117       if(s < 0) perror("inet_pton");
1118
1119       throw anna::RuntimeException("functions::ipAsRaw | Wrong IPv4 address format", ANNA_FILE_LOCATION);
1120     }
1121   } else {
1122     unsigned char buf[sizeof(struct in6_addr)];
1123     int s = inet_pton(AF_INET6, ip.c_str(), buf);
1124
1125     if(s > 0) {
1126       result += (S8)buf[0];
1127       result += (S8)buf[1];
1128       result += (S8)buf[2];
1129       result += (S8)buf[3];
1130       result += (S8)buf[4];
1131       result += (S8)buf[5];
1132       result += (S8)buf[6];
1133       result += (S8)buf[7];
1134       result += (S8)buf[8];
1135       result += (S8)buf[9];
1136       result += (S8)buf[10];
1137       result += (S8)buf[11];
1138       result += (S8)buf[12];
1139       result += (S8)buf[13];
1140       result += (S8)buf[14];
1141       result += (S8)buf[15];
1142     } else {
1143       if(s < 0) perror("inet_pton");
1144
1145       throw anna::RuntimeException("functions::ipAsRaw | Wrong IPv6 address format", ANNA_FILE_LOCATION);
1146     }
1147   }
1148
1149   return result;
1150   // Alternativa
1151   //   anna::DataBlock result(true);
1152   //
1153   //
1154   //   if (isIPv4(ip)) {
1155   //
1156   //      int dec1, dec2, dec3, dec4; // U32 type is valid, 'int' better: argument for %d must be 'int *' (http://www.cplusplus.com/reference/clibrary/cstdio/sscanf/)
1157   //      sscanf(ip.c_str(), "%d.%d.%d.%d", &dec1, &dec2, &dec3, &dec4);
1158   //      result += (S8)dec1;
1159   //      result += (S8)dec2;
1160   //      result += (S8)dec3;
1161   //      result += (S8)dec4;
1162   //   }
1163   //   else {
1164   //
1165   //      int hex1, hex2, hex3, hex4, hex5, hex6, hex7, hex8; // U16 type is not valid: argument for %X must be 'int *' (http://www.cplusplus.com/reference/clibrary/cstdio/sscanf/)
1166   //      sscanf(normalizeIP(ip).c_str(), "%X:%X:%X:%X:%X:%X:%X:%X", &hex1, &hex2, &hex3, &hex4, &hex5, &hex6, &hex7, &hex8);
1167   //      result += ((S8)(hex1 >> 8));
1168   //      result += ((S8)(hex1 & 0x00FF));
1169   //      result += ((S8)(hex2 >> 8));
1170   //      result += ((S8)(hex2 & 0x00FF));
1171   //      result += ((S8)(hex3 >> 8));
1172   //      result += ((S8)(hex3 & 0x00FF));
1173   //      result += ((S8)(hex4 >> 8));
1174   //      result += ((S8)(hex4 & 0x00FF));
1175   //      result += ((S8)(hex5 >> 8));
1176   //      result += ((S8)(hex5 & 0x00FF));
1177   //      result += ((S8)(hex6 >> 8));
1178   //      result += ((S8)(hex6 & 0x00FF));
1179   //      result += ((S8)(hex7 >> 8));
1180   //      result += ((S8)(hex7 & 0x00FF));
1181   //      result += ((S8)(hex8 >> 8));
1182   //      result += ((S8)(hex8 & 0x00FF));
1183   //   }
1184   //
1185   //
1186   //   return result;
1187 }
1188
1189
1190 std::string functions::rawIpAsString(const char *buffer, int bufferLength, bool normalize) throw(anna::RuntimeException) {
1191   std::string result = "";
1192   char str[INET6_ADDRSTRLEN];
1193
1194   if(bufferLength == 4) {
1195     if(inet_ntop(AF_INET, buffer, str, INET_ADDRSTRLEN) != NULL)
1196       result = str;
1197   } else if(bufferLength == 16) {
1198     if(inet_ntop(AF_INET6, buffer, str, INET6_ADDRSTRLEN) != NULL)
1199       result = str;
1200   } else
1201     throw anna::RuntimeException("functions::rawIpAsString | Unreconized IP address format (only 4-byte for IPv4, and 16-byte for IPv6 are allowed)", ANNA_FILE_LOCATION);
1202
1203   if(result == "")
1204     throw anna::RuntimeException("functions::rawIpAsString | Wrong IP address serialization (check range value)", ANNA_FILE_LOCATION);
1205
1206   return (normalize ? normalizeIP(result) : result);
1207   // Alternativa:
1208   //   std::string result;
1209   //
1210   //
1211   //   if (bufferLength == 4) { // IPv4
1212   //      result = anna::functions::asString("%d.%d.%d.%d", (U8)buffer[0], (U8)buffer[1], (U8)buffer[2], (U8)buffer[3]);
1213   //   }
1214   //   else if (bufferLength == 16) { // IPv6
1215   //      result = anna::functions::asString("%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
1216   //                       ((((U8)buffer[0]) << 8) & 0xFF00 /* same as (U16 cast)*/) +
1217   //                       (((U8)buffer[1])        & 0x00FF),
1218   //                       ((((U8)buffer[2]) << 8) & 0xFF00) +
1219   //                       (((U8)buffer[3])        & 0x00FF),
1220   //                       ((((U8)buffer[4]) << 8) & 0xFF00) +
1221   //                       (((U8)buffer[5])        & 0x00FF),
1222   //                       ((((U8)buffer[6]) << 8) & 0xFF00) +
1223   //                       (((U8)buffer[7])        & 0x00FF),
1224   //                       ((((U8)buffer[8]) << 8) & 0xFF00) +
1225   //                       (((U8)buffer[9])        & 0x00FF),
1226   //                       ((((U8)buffer[10]) << 8) & 0xFF00) +
1227   //                       (((U8)buffer[11])        & 0x00FF),
1228   //                       ((((U8)buffer[12]) << 8) & 0xFF00) +
1229   //                       (((U8)buffer[13])        & 0x00FF),
1230   //                       ((((U8)buffer[14]) << 8) & 0xFF00) +
1231   //                       (((U8)buffer[15])        & 0x00FF));
1232   //   }
1233   //   else
1234   //      throw anna::RuntimeException("functions::rawIpAsString | Unreconized IP address format (only 4-byte for IPv4, and 16-byte for IPv6 are allowed)", ANNA_FILE_LOCATION);
1235   //
1236   //
1237   //   return (normalize ? normalizeIP(result):result);
1238 }
1239
1240
1241 void functions::getAddressAndPortFromSocketLiteral(const std::string &literal, std::string &address, int &port) throw() {
1242   size_t pos = literal.find_last_of(":");
1243   size_t lastPos = literal.size() - 1;
1244   address = ""; port = -1; // assume error
1245
1246   if((pos != std::string::npos) && (pos != lastPos)) {
1247     address = literal.substr(0, pos);
1248     port = atoi(literal.substr(pos + 1, lastPos).c_str());
1249   }
1250 }
1251
1252
1253 socket_v functions::getSocketVectorFromString(const std::string & list) throw() {
1254   socket_v result;
1255   std::string address;
1256   int port;
1257   anna::Tokenizer lst;
1258   lst.apply(list, ",");
1259
1260   if(lst.size() < 1) return result;
1261
1262   anna::Tokenizer::const_iterator tok_min(lst.begin());
1263   anna::Tokenizer::const_iterator tok_max(lst.end());
1264   anna::Tokenizer::const_iterator tok_iter;
1265
1266   for(tok_iter = tok_min; tok_iter != tok_max; tok_iter++) {
1267     getAddressAndPortFromSocketLiteral(anna::Tokenizer::data(tok_iter), address, port);
1268
1269     if(port == -1) { result.clear(); return result; }
1270
1271     result.push_back(socket_t(address, port));
1272   }
1273
1274   return result;
1275 }
1276
1277 std::string functions::socketVectorAsString(const socket_v & socketVector) throw() {
1278   std::string result;
1279   socket_v_it it;
1280   socket_v_it it_min(socketVector.begin());
1281   socket_v_it it_max(socketVector.end());
1282
1283   for(it = it_min; it != it_max; it++) {
1284     result += anna::functions::asString("%s:%d,", (*it).first.c_str(), (*it).second);
1285   }
1286
1287   result.erase(result.size() - 1, 1);  // remove last comma
1288   return result;
1289 }
1290
1291 bool functions::littleEndian()
1292 throw() {
1293   int i = 1;
1294   char *p = (char *) &i;
1295   if (p[0] == 1) return true;
1296   return false;
1297 }
1298
1299 const char* functions::codeInteger(char* result, const int n)
1300 throw() {
1301   int aux(htonl(n));
1302   char* w((char*) &aux);
1303   *result = *w;
1304   *(result + 1) = *(w + 1);
1305   *(result + 2) = *(w + 2);
1306   *(result + 3) = *(w + 3);
1307   return result;
1308 }
1309
1310 const char* functions::codeShort(char* result, const short int n)
1311 throw() {
1312   short int aux(htons(n));
1313   char* w((char*) &aux);
1314   *result = *w;
1315   *(result + 1) = *(w + 1);
1316   return result;
1317 }
1318
1319 const char* functions::codeInteger64(char* result, const S64 n)
1320 throw() {
1321   S64 aux(0xffffffff);
1322   int n2;
1323   aux <<= 32;
1324   aux &= n;
1325   n2 = (aux >> 32) & 0xffffffff;
1326   codeInteger(result, n2);
1327   n2 = n & 0xffffffff;
1328   codeInteger(result + sizeof(int), n2);
1329   return result;
1330 }
1331
1332 /*static*/
1333 const char* functions::codeFloat(char* result, const float n)
1334 throw() {
1335   int ii;
1336   anna_memcpy(&ii, &n, sizeof(n));
1337   return functions::codeInteger(result, ii);
1338 }
1339
1340 /*static*/
1341 const char* functions::codeDouble(char* result, const double n)
1342 throw() {
1343   S64 ii;
1344   anna_memcpy(&ii, &n, sizeof(n));
1345   return functions::codeInteger64(result, ii);
1346 }
1347
1348 int functions::decodeInteger(const char* data)
1349 throw() {
1350   int result;
1351   char* w((char*) &result);
1352   *w  = *data;
1353   *(w + 1) = *(data + 1);
1354   *(w + 2) = *(data + 2);
1355   *(w + 3) = *(data + 3);
1356   return ntohl(result);
1357 }
1358
1359 short int functions::decodeShort(const char* data)
1360 throw() {
1361   short int result;
1362   char* w((char*) &result);
1363   *w  = *data;
1364   *(w + 1) = *(data + 1);
1365   return ntohs(result);
1366 }
1367
1368 S64 functions::decodeInteger64(const char* data)
1369 throw() {
1370   S64 result(decodeInteger(data));
1371   result <<= 32;
1372   return result |= (decodeInteger(data + sizeof(int)) & 0xffffffff);
1373 }
1374
1375 /*static*/
1376 float functions::decodeFloat(const char* data)
1377 throw() {
1378   float result;
1379   int ii = functions::decodeInteger(data);
1380   anna_memcpy(&result, &ii, sizeof(result));
1381   return result;
1382 }
1383
1384 /*static*/
1385 double functions::decodeDouble(const char* data)
1386 throw() {
1387   double result;
1388   S64 ii = functions::decodeInteger64(data);
1389   anna_memcpy(&result, &ii, sizeof(result));
1390   return result;
1391 }
1392
1393
1394
1395 void functions::decodeIsupNumber(const char *buffer, int length, isup_number_t & isupNumber, bool calledOrCalling) throw(anna::RuntimeException) {
1396 #define DECODE2BYTES_INDX_VALUETYPE(buffer,indx,value_type) ((((value_type)buffer[indx] << 8) & 0xFF00) + ((value_type)buffer[indx+1] & 0x00FF))
1397   isupNumber.reset();
1398   isupNumber.OddEven = (short)((buffer[0] >> 7) & 0x01);
1399   bool filler = isupNumber.OddEven;
1400
1401   if(filler && ((buffer [length - 1] & 0xf0) != 0x00))
1402     throw anna::RuntimeException("functions::decodeIsupNumber | Isup number filler must be '0000'", ANNA_FILE_LOCATION);
1403
1404   isupNumber.NatureOfAddress = (short)(buffer[0] & 0x7F);
1405   isupNumber.NumberingPlan = (short)((buffer[1] >> 4) & 0x07);
1406
1407   if(calledOrCalling) {
1408     isupNumber.InternalNetworkNumber = (short)((buffer[1] >> 7) & 0x01);
1409   } else {
1410     isupNumber.NumberIncomplete = (short)((buffer[1] >> 7) & 0x01);
1411     isupNumber.AddressPresentationRestricted = (short)((buffer[1] >> 2) & 0x03);
1412     isupNumber.Screening = (short)(buffer[1] & 0x03);
1413   }
1414
1415   // Digits:
1416   isupNumber.Digits = "";
1417   int byte;
1418
1419   for(int k = 2; k < length; k ++) {
1420     byte = (buffer [k] & 0x0f);
1421     isupNumber.Digits += (byte >= 0 && byte <= 9) ? (byte + '0') : ((byte - 0xa) + 'a');
1422     byte = (buffer [k] & 0xf0) >> 4;
1423     isupNumber.Digits += (byte >= 0 && byte <= 9) ? (byte + '0') : ((byte - 0xa) + 'a');
1424   }
1425
1426   if(filler) isupNumber.Digits.erase(isupNumber.Digits.size() - 1, 1);   // remove filler
1427 }
1428
1429
1430 void functions::codeIsupNumber(const isup_number_t & isupNumber, bool calledOrCalling, std::string & target) throw(anna::RuntimeException) {
1431   // Checkings:
1432   if(isupNumber.OddEven < 0 || isupNumber.OddEven > 1)
1433     throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'OddEven' field out of range [0,1]", ANNA_FILE_LOCATION);
1434
1435   bool odd = isupNumber.OddEven;
1436   bool oddDigits = (isupNumber.Digits.size() % 2);
1437
1438   if(odd != oddDigits)
1439     throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'OddEven' field doesn't correspond to the number of digits on 'Digits' field", ANNA_FILE_LOCATION);
1440
1441   if(isupNumber.NatureOfAddress < 0 || isupNumber.NatureOfAddress > 127)
1442     throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'NatureOfAddress' field out of range [0,127]", ANNA_FILE_LOCATION);
1443
1444   if(isupNumber.NumberingPlan < 0 || isupNumber.NumberingPlan > 7)
1445     throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'NumberingPlan' field out of range [0,7]", ANNA_FILE_LOCATION);
1446
1447   if(calledOrCalling) {
1448     if(isupNumber.NumberIncomplete != 0)
1449       throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'NumberIncomplete' field present on Called Party Number !", ANNA_FILE_LOCATION);
1450
1451     if(isupNumber.AddressPresentationRestricted != 0)
1452       throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'AddressPresentationRestricted' field present on Called Party Number !", ANNA_FILE_LOCATION);
1453
1454     if(isupNumber.Screening != 0)
1455       throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'Screening' field present on Called Party Number !", ANNA_FILE_LOCATION);
1456
1457     if(isupNumber.InternalNetworkNumber < 0 || isupNumber.InternalNetworkNumber > 1)
1458       throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'InternalNetworkNumber' field out of range [0,1]", ANNA_FILE_LOCATION);
1459   } else {
1460     if(isupNumber.InternalNetworkNumber != 0)
1461       throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'InternalNetworkNumber' field present on Calling Party Number !", ANNA_FILE_LOCATION);
1462
1463     if(isupNumber.NumberIncomplete < 0 || isupNumber.NumberIncomplete > 1)
1464       throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'NumberIncomplete' field out of range [0,1]", ANNA_FILE_LOCATION);
1465
1466     if(isupNumber.AddressPresentationRestricted < 0 || isupNumber.AddressPresentationRestricted > 3)
1467       throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'AddressPresentationRestricted' field out of range [0,3]", ANNA_FILE_LOCATION);
1468
1469     if(isupNumber.Screening < 0 || isupNumber.Screening > 3)
1470       throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'Screening' field out of range [0,3]", ANNA_FILE_LOCATION);
1471   }
1472
1473   char byte;
1474   target = "";
1475   bool filler = isupNumber.OddEven;
1476   bool hasDigits = (isupNumber.Digits.size() > 0);
1477   byte = filler ? 0x80 : 0x00;
1478   byte = byte |= isupNumber.NatureOfAddress;
1479   target += byte;
1480
1481   if(calledOrCalling) {
1482     byte = isupNumber.InternalNetworkNumber << 7;
1483     byte = byte |= (isupNumber.NumberingPlan << 4);
1484   } else {
1485     byte = isupNumber.NumberIncomplete << 7;
1486     byte = byte |= (isupNumber.NumberingPlan << 4);
1487     byte = byte |= (isupNumber.AddressPresentationRestricted << 2);
1488     byte = byte |= isupNumber.Screening;
1489   }
1490
1491   target += byte;
1492   //int byte;
1493   unsigned char hex;
1494   std::string dtlc = isupNumber.Digits; // digits to lower case
1495   //std::transform(dtlc.begin(), dtlc.end(), dtlc.begin(), std::tolower);
1496   const char *digits = dtlc.c_str();
1497
1498   for(int k = 1; k < isupNumber.Digits.size(); k += 2) {
1499     if(isxdigit(byte = digits [k - 1]) == 0)
1500       throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'Digits' field contains invalid digits (non hexadecimal)", ANNA_FILE_LOCATION);
1501
1502     hex = (byte >= '0' && byte <= '9') ? (byte - '0') : ((byte - 'a') + 0x0a);
1503
1504     if(isxdigit(byte = digits [k]) == 0)
1505       throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'Digits' field contains invalid digits (non hexadecimal)", ANNA_FILE_LOCATION);
1506
1507     hex |= ((byte >= '0' && byte <= '9') ? (byte - '0') : ((byte - 'a') + 0x0a)) << 4;
1508     target += hex;
1509   }
1510
1511   if(hasDigits && filler) {
1512     if(isxdigit(byte = digits [isupNumber.Digits.size() - 1]) == 0)
1513       throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'Digits' field contains invalid digits (non hexadecimal)", ANNA_FILE_LOCATION);
1514
1515     target += ((byte >= '0' && byte <= '9') ? (byte - '0') : ((byte - 'a') + 0x0a));
1516   }
1517 }
1518
1519
1520 void functions::codeIsupNumber(const isup_number_t & isupNumber, bool calledOrCalling, char * buffer, int & length) throw(anna::RuntimeException) {
1521   std::string target;
1522   codeIsupNumber(isupNumber, calledOrCalling, target);
1523   length = target.size();
1524   memcpy(buffer, target.c_str(), length);
1525 }
1526