kamailio.cfg: removed sample db_mode parameter for domain module
[sip-router] / basex.h
1 /*
2  * $Id$
3  *
4  * convert/decode to/from ascii using various bases
5  *
6  * Copyright (C) 2008 iptelorg GmbH
7  *
8  * Permission to use, copy, modify, and distribute this software for any
9  * purpose with or without fee is hereby granted, provided that the above
10  * copyright notice and this permission notice appear in all copies.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19  */
20
21 /*!
22  * \file
23  * \brief SIP-router core :: convert/decode to/from ascii using various bases
24  *
25  * \ingroup core
26  *
27  * Module: \ref core
28  *
29  *
30  * Functions:
31  *  - base16_enc(src, src_len, dst, dst_len)    : encode to standard hex
32  *  - base16_dec(src, src_len, dst, dst_len)    : decode from standard hex
33  *  - base16_enc_len(len)                       : length needed to encode len bytes (macro)
34  *  - base16_max_dec_len(len)                   : length needed to decode a string of size len
35  *
36  *  - base64_enc(src, src_len, dst, dst_len)    : encode to base64, standard alphabet
37  *  - base64_dec(src, src_len, dst, dst_len)    : decode from base64, standard  alphabet
38  *  - base64_enc_len(len)                       : length needed to encode len bytes (macro)
39  *  - base64_max_dec_len(len)                   : maximum length needed to decode len bytes (macro)
40  *  - base64_dec_len(str, len)                  : size of the decoded str 
41  *  - q_base64_enc(src, src_len, dst, dst_len)  : encode to special base64 alphabet (non standard)
42  *  - q_base64_dec(src, src_len, dst, dst_len)  - decode from special non-standard base64 alphabet
43  *
44  *  All the above functions return the size used (in dst) on success and
45  *   0 or a negative number (which is -1*size_needed) on error.
46  *
47  * There are close to no checks for validity, an unexpected char will lead
48  * to a corrupted result, but the functions won't return error.
49  *
50  * Notes:
51  *  on a core2 duo the versions with lookup tables are way faster (see
52  *  http://www.experts-exchange.com/Programming/Languages/CPP/Q_21988706.html
53  *  for some interesting tests and ideeas).
54  *
55  *  Test results for 40 bytes  (typical ser nounce) in average cpu cycles:
56 \verbatim
57  *                    lookup   lookup_large lookup8k no-lookup
58  *  base16_enc           211/231  218/199      -       1331
59  *  base16_dec           252/251  236          -       1226
60  *  base64_enc           209      186         156      1005
61  *  base64_dec           208      207         207      1242
62  *  q_base64_enc         -                              288
63  *  q_base64_dec         -                              281
64  *  (see test/basex.txt for more results)
65 \endverbatim
66  *
67  * Defines:
68  *  - BASE64_LOOKUP_TABLE/NO_BASE64_LOOKUP_TABLE : use (default)/don't use
69  *     small lookup tables for conversions (faster in general).
70  *  - BASE64_LOOKUP_LARGE    : use large lookup tables (2560 bytes for 
71  *    encoding and 256 bytes for decoding; without it 64 bytes are used for
72  *    encoding and 85 bytes for decoding.
73  *  - BASE64_LOOKUP_8K : use even larger lookup tables (8K for encoding and
74  *    256 for decoding); also try to write 2 bytes at a time (short) if
75  *    the destination is 2 byte aligned
76  *
77  *  - BASE16_LOOKUP_TABLE/NO_BASE16_LOOKUP_TABLE : use (default)/don't use
78  *     small lookup tables for conversions (faster in general).
79  *  - BASE16_LOOKUP_LARGE  : use large lookup tables (512 bytes for 
80  *    encoding and 256 bytes for decoding
81  *  - BASE16_READ_WHOLE_INTS : read an int at a time
82  *
83  * History:
84  * --------
85  *  2008-06-11  created by andrei
86  */
87  
88
89
90 #ifndef _basex_h
91 #define _basex_h
92
93 #include "compiler_opt.h"
94
95 /* defaults */
96 #ifndef NO_BASE16_LOOKUP_TABLE
97 #define BASE16_LOOKUP_TABLE
98 #endif
99
100 #ifndef NO_BASE64_LOOKUP_TABLE
101 #define BASE64_LOOKUP_TABLE
102 #endif
103
104 #ifndef NO_BASE64_LOOKUP_8K
105 #define BASE64_LOOKUP_8K
106 #endif
107
108 #ifndef NO_BASE16_LOOKUP_LARGE
109 #define BASE16_LOOKUP_LARGE
110 #endif
111
112 #if !defined NO_BASE64_LOOKUP_LARGE && !defined BASE64_LOOKUP_8K
113 #define BASE64_LOOKUP_LARGE
114 #endif
115
116
117
118 #if defined BASE16_READ_WHOLE_INTS || defined BASE64_READ_WHOLE_INTS || \
119         defined BASE64_LOOKUP_8K
120 #include "endianness.h"
121
122 /*! \brief aligns p to a type* pointer, type must have a 2^k size */
123 #define ALIGN_POINTER(p, type) \
124         ((type*) ((long)((char*)(p)+sizeof(type)-1)&~(long)(sizeof(type)-1)))
125
126 #define ALIGN_UINT_POINTER(p) ALIGN_POINTER(p, unsigned int)
127
128 #endif
129
130
131 #ifdef BASE16_LOOKUP_TABLE
132
133 #ifdef BASE16_LOOKUP_LARGE
134 /*! \brief use large tables: 512 for lookup and 256 for decode */
135
136 extern unsigned char _bx_hexdig_hi[256];
137 extern unsigned char _bx_hexdig_low[256];
138
139 /*! \brief returns the first 4 bits of c converted to a hex digit */
140 #define HEX_HI(h)       _bx_hexdig_hi[(unsigned char)(h)]
141 /*! \brief returns the low 4 bits of converted to a hex digit */
142 #define HEX_LOW(h)      _bx_hexdig_low[(unsigned char)(h)]
143
144 extern unsigned char _bx_unhexdig256[256];
145
146 /*! \brief  converts hex_digit to a number (0..15); it might
147  *      \return 0xff for invalid digit (but with some compile
148  *      option it won't check)
149  */
150 #define UNHEX(h)        _bx_unhexdig256[(h)]
151
152 #else /* BASE16_LOOKUP_LARGE */
153 /*! \brief use small tabes: 16 bytes for lookup and 32 for decode */
154
155 extern unsigned char _bx_hexdig[16+1];
156
157 #define HEX_4BITS(h) _bx_hexdig[(h)]
158 #define HEX_HI(h)       HEX_4BITS(((unsigned char)(h))>>4)
159 #define HEX_LOW(h)      HEX_4BITS((h)&0xf)
160
161 extern unsigned char _bx_unhexdig32[32];
162 #define UNHEX(h) _bx_unhexdig32[(((h))-'0')&0x1f]
163
164 #endif /* BASE16_LOOKUP_LARGE */
165
166 #else /* BASE16_LOOKUP_TABLE */
167 /* no lookup tables */
168 #if 0
169 #define HEX_4BITS(h) (unsigned char)((unlikely((h)>=10))?((h)-10+'A'):(h)+'0')
170 #define UNHEX(c) (unsigned char)((unlikely((c)>='A'))?(c)-'A'+10:(c)-'0')
171 #else
172 #define HEX_4BITS(hc) (unsigned char)( ((((hc)>=10)-1)&((hc)+'0')) | \
173                                                                         ((((hc)<10)-1)&((hc)+'A')) )
174 #define UNHEX(c) (unsigned char) ( ((((c)>'9')-1)& ((c)-'0')) | \
175                                                                 ((((c)<='9')-1)&((c)-'A')) )
176 #endif 
177
178 #define HEX_HI(h)       HEX_4BITS(((unsigned char)(h))>>4)
179 #define HEX_LOW(h)      HEX_4BITS((h)&0xf)
180
181 #endif /* BASE16_LOOKUP_TABLE */
182
183
184 #ifdef BASE64_LOOKUP_TABLE
185 #ifdef BASE64_LOOKUP_LARGE
186 /* large lookup tables, 2.5 k */
187
188 extern unsigned char _bx_b64_first[256];
189 extern unsigned char _bx_b64_second[4][256];
190 extern unsigned char _bx_b64_third[4][256];
191 extern unsigned char _bx_b64_fourth[256];
192
193 #define BASE64_1(a) _bx_b64_first[(a)]
194 #define BASE64_2(a,b) _bx_b64_second[(a)&0x3][(b)]
195 #define BASE64_3(b,c) _bx_b64_third[(c)>>6][(b)]
196 #define BASE64_4(c) _bx_b64_fourth[(c)]
197
198 extern unsigned char _bx_ub64[256];
199 #define UNBASE64(v) _bx_ub64[(v)]
200
201 #elif defined BASE64_LOOKUP_8K
202 /* even larger encode tables: 8k */
203 extern unsigned short _bx_b64_12[4096];
204
205 /* return a word (16 bits) */
206 #define BASE64_12(a,b)  _bx_b64_12[((a)<<4)|((b)>>4)]
207 #define BASE64_34(b,c)  _bx_b64_12[(((b)&0xf)<<8)|(c)]
208 #ifdef __IS_LITTLE_ENDIAN
209 #define FIRST_8B(s)     ((unsigned char)(s))
210 #define LAST_8B(s)      ((s)>>8)
211 #elif defined __IS_BIG_ENDIAN
212 #define FIRST_8B(s)     ((s)>>8)
213 #define LAST_8B(s)      ((unsigned char)(s))
214 #else
215 #error neither __IS_LITTLE_ENDIAN nor __IS_BIG_ENDIAN are defined
216 #endif
217
218
219 extern unsigned char _bx_ub64[256];
220 #define UNBASE64(v) _bx_ub64[(v)]
221
222 #else /* BASE64_LOOKUP_LARGE */
223 /* small lookup tables */
224 extern unsigned char _bx_b64[64+1];
225
226 #define BASE64_DIG(v)   _bx_b64[(v)]
227
228 #define BASE64_1(a)             BASE64_DIG((a)>>2)
229 #define BASE64_2(a, b)  BASE64_DIG( (((a)<<4)&0x3f) | ((b)>>4))
230 #define BASE64_3(b, c)  BASE64_DIG( (((b)<<2)&0x3f) | ((c)>>6))
231 #define BASE64_4(c)             BASE64_DIG((c)&0x3f)
232
233 extern unsigned char _bx_ub64[0x54+1];
234 #define UNBASE64(v) _bx_ub64[(((v)&0x7f)-0x2b)]
235
236 #endif /* BASE64_LOOKUP_LARGE */
237
238
239 #else /* BASE64_LOOKUP_TABLE */
240
241 #define BASE64_DIG(v) base64_enc_char(v)
242 #define BASE64_1(a)             BASE64_DIG((a)>>2)
243 #define BASE64_2(a, b)  BASE64_DIG( (((a)<<4)&0x3f) | ((b)>>4))
244 #define BASE64_3(b, c)  BASE64_DIG( (((b)<<2)&0x3f) | ((c)>>6))
245 #define BASE64_4(c)             BASE64_DIG((c)&0x3f)
246
247 #define UNBASE64(v) base64_dec_char(v)
248
249 #endif /* BASE64_LOOKUP_TABLE */
250
251
252
253 /*! \brief lenght needed for encoding l bytes */
254 #define base16_enc_len(l) (l*2)
255 /*! \brief maximum lenght needed for decoding l bytes */
256 #define base16_max_dec_len(l) (l/2)
257 /*! \brief actual space needed for decoding a string b of size l */
258 #define base16_dec_len(b, l) base16_max_dec_len(l)
259 /*! \brief minimum valid source len for decoding */
260 #define base16_dec_min_len() 2
261 /*! \brief minimum valid source len for encoding */
262 #define base16_enc_min_len() 0
263
264 /*! \brief space needed for encoding l bytes */
265 #define base64_enc_len(l) (((l)+2)/3*4)
266 /*! \brief maximum space needed for encoding l bytes */
267 #define base64_max_dec_len(l) ((l)/4*3)
268 /*! \brief actual space needed for decoding a string b of size l, l>=4 */
269 #define base64_dec_len(b, l) \
270         (base64_max_dec_len(l)-((b)[(l)-2]=='=') -((b)[(l)-1]=='='))
271 /*! \brief minimum valid source len for decoding */
272 #define base64_dec_min_len() 4
273 /*! \brief minimum valid source len for encoding */
274 #define base64_enc_min_len() 0
275
276
277 #ifdef BASE16_READ_WHOLE_INTS
278
279 /*! 
280  * \params: 
281  * \return: size used from the output buffer (dst) on success,
282  *          -size_needed on error
283  *
284  * WARNING: the output string is not 0-term
285  */
286 inline static int base16_enc(unsigned char* src, int slen, unsigned char*  dst, int dlen)
287 {
288         unsigned int* p;
289         unsigned char* end;
290         int osize;
291         unsigned short us;
292         
293         osize=2*slen;
294         if (unlikely(dlen<osize))
295                 return -osize;
296         end=src+slen;
297         p=ALIGN_UINT_POINTER(src);
298         if (likely((unsigned char*)p<end)){
299                 switch((unsigned char)((unsigned char*)p-src)){
300                         case 3:
301                                 *dst=HEX_HI(*src);
302                                 *(dst+1)=HEX_LOW(*src);
303                                 dst+=2;
304                                 src++;
305                                 /* no break */
306                         case 2:
307                                 us=*(unsigned short*)(src);
308 #if   defined __IS_LITTLE_ENDIAN
309                                 *(dst+0)=HEX_HI(us);
310                                 *(dst+1)=HEX_LOW(us);
311                                 *(dst+2)=HEX_HI(us>>8);
312                                 *(dst+3)=HEX_LOW(us>>8);
313 #elif defined __IS_BIG_ENDIAN
314                                 *(dst+2)=HEX_HI(us);
315                                 *(dst+3)=HEX_LOW(us);
316                                 *(dst+0)=HEX_HI(us>>8);
317                                 *(dst+1)=HEX_LOW(us>>8);
318 #endif
319                                 dst+=4;
320                                 /* no need to inc src */
321                                 break;
322                         case 1:
323                                 *dst=HEX_HI(*src);
324                                 *(dst+1)=HEX_LOW(*src);
325                                 dst+=2;
326                                 /* no need to inc src */
327                         case 0:
328                                 break;
329                 }
330                 for(;(unsigned char*)p<=(end-4);p++,dst+=8){
331 #if   defined __IS_LITTLE_ENDIAN
332                         *(dst+0)=HEX_HI(*p);
333                         *(dst+1)=HEX_LOW(*p);
334                         *(dst+2)=HEX_HI(((*p)>>8));
335                         *(dst+3)=HEX_LOW(((*p)>>8));
336                         *(dst+4)=HEX_HI(((*p)>>16));
337                         *(dst+5)=HEX_LOW(((*p)>>16));
338                         *(dst+6)=HEX_HI(((*p)>>24));
339                         *(dst+7)=HEX_LOW(((*p)>>24));
340 #elif defined __IS_BIG_ENDIAN
341                         *(dst+6)=HEX_HI(*p);
342                         *(dst+7)=HEX_LOW(*p);
343                         *(dst+4)=HEX_HI(((*p)>>8));
344                         *(dst+5)=HEX_LOW(((*p)>>8));
345                         *(dst+2)=HEX_HI(((*p)>>16));
346                         *(dst+3)=HEX_LOW(((*p)>>16));
347                         *(dst+0)=HEX_HI(((*p)>>24));
348                         *(dst+1)=HEX_LOW(((*p)>>24));
349 #else
350 #error neither BIG ro LITTLE endian defined
351 #endif /* __IS_*_ENDIAN */
352                 }
353                 src=(unsigned char*)p;
354                 /* src is 2-bytes aligned (short) */
355                 switch((unsigned char)((unsigned char*)end-src)){
356                         case 3:
357                         case 2:
358                                 us=*(unsigned short*)(src);
359 #if   defined __IS_LITTLE_ENDIAN
360                                 *(dst+0)=HEX_HI(us);
361                                 *(dst+1)=HEX_LOW(us);
362                                 *(dst+2)=HEX_HI(us>>8);
363                                 *(dst+3)=HEX_LOW(us>>8);
364 #elif defined __IS_BIG_ENDIAN
365                                 *(dst+2)=HEX_HI(us);
366                                 *(dst+3)=HEX_LOW(us);
367                                 *(dst+0)=HEX_HI(us>>8);
368                                 *(dst+1)=HEX_LOW(us>>8);
369 #endif
370                                 if ((end-src)==3){
371                                         *(dst+4)=HEX_HI(*(src+2));
372                                         *(dst+5)=HEX_LOW(*(src+2));
373                                 }
374                                 /* no need to inc anything */
375                                 break;
376                         case 1:
377                                 *dst=HEX_HI(*src);
378                                 *(dst+1)=HEX_LOW(*src);
379                                 /* no need to inc anything */
380                         case 0:
381                                 break;
382                 }
383         }else if (unlikely((long)src&1)){
384                 /* src is not 2-bytes (short) aligned */
385                 switch((unsigned char)((unsigned char*)end-src)){
386                         case 3:
387                                 *dst=HEX_HI(*src);
388                                 *(dst+1)=HEX_LOW(*src);
389                                 dst+=2;
390                                 src++;
391                                 /* no break */
392                         case 2:
393                                 us=*(unsigned short*)(src);
394 #if   defined __IS_LITTLE_ENDIAN
395                                 *(dst+0)=HEX_HI(us);
396                                 *(dst+1)=HEX_LOW(us);
397                                 *(dst+2)=HEX_HI(us>>8);
398                                 *(dst+3)=HEX_LOW(us>>8);
399 #elif defined __IS_BIG_ENDIAN
400                                 *(dst+2)=HEX_HI(us);
401                                 *(dst+3)=HEX_LOW(us);
402                                 *(dst+0)=HEX_HI(us>>8);
403                                 *(dst+1)=HEX_LOW(us>>8);
404 #endif
405                                 /* no need to inc anything */
406                                 break;
407                         case 1:
408                                 *dst=HEX_HI(*src);
409                                 *(dst+1)=HEX_LOW(*src);
410                                 /* no need to inc anything */
411                         case 0:
412                                 break;
413                 }
414         }else{
415                 /* src is 2-bytes aligned (short) */
416                 switch((unsigned char)((unsigned char*)end-src)){
417                         case 3:
418                         case 2:
419                                 us=*(unsigned short*)(src);
420 #if   defined __IS_LITTLE_ENDIAN
421                                 *(dst+0)=HEX_HI(us);
422                                 *(dst+1)=HEX_LOW(us);
423                                 *(dst+2)=HEX_HI(us>>8);
424                                 *(dst+3)=HEX_LOW(us>>8);
425 #elif defined __IS_BIG_ENDIAN
426                                 *(dst+2)=HEX_HI(us);
427                                 *(dst+3)=HEX_LOW(us);
428                                 *(dst+0)=HEX_HI(us>>8);
429                                 *(dst+1)=HEX_LOW(us>>8);
430 #endif
431                                 if ((end-src)==3){
432                                         *(dst+4)=HEX_HI(*(src+2));
433                                         *(dst+5)=HEX_LOW(*(src+2));
434                                 }
435                                 /* no need to inc anything */
436                                 break;
437                         case 1:
438                                 *dst=HEX_HI(*src);
439                                 *(dst+1)=HEX_LOW(*src);
440                                 /* no need to inc anything */
441                         case 0:
442                                 break;
443                 }
444         }
445         
446         return osize;
447 }
448
449
450
451 #else /* BASE16_READ_WHOLE_INTS */
452
453
454 /*!
455  * \return : size used from the output buffer (dst) on success,
456  *          -size_needed on error
457  *
458  * \note WARNING: the output string is not 0-term
459  */
460 inline static int base16_enc(unsigned char* src, int slen,
461                                                          unsigned char*  dst, int dlen)
462 {
463         unsigned char* end;
464         int osize;
465         
466         osize=2*slen;
467         if (unlikely(dlen<osize))
468                 return -osize;
469         end=src+slen;
470         for (;src<end; src++,dst+=2){
471                 *dst=HEX_HI(*src);
472                 *(dst+1)=HEX_LOW(*src);
473         }
474         return osize;
475 }
476
477
478 #endif /* BASE16_READ_WHOLE_INTS */
479
480 inline static int base16_dec(unsigned char* src, int slen, unsigned char* dst, int dlen)
481 {
482         unsigned char* end;
483         int osize;
484         
485         osize=slen/2;
486         if (unlikely(dlen<osize))
487                 return -osize;
488         end=src+2*osize;
489         for (; src<end; src+=2, dst++)
490                 *dst=(UNHEX(*src)<<4) | UNHEX(*(src+1));
491         return osize;
492 }
493
494
495
496
497
498 /*! \brief helper internal function: encodes v (6 bits value)
499  * \return char ascii encoding on success and 0xff on error
500  * (value out of range) */
501 inline static unsigned char base64_enc_char(unsigned char v)
502 {
503         switch(v){
504                 case 0x3f:
505                         return '/';
506                 case 0x3e:
507                         return '+';
508                 default:
509                         if (v<=25)
510                                 return v+'A';
511                         else if (v<=51)
512                                 return v-26+'a';
513                         else if (v<=61)
514                                 return v-52+'0';
515         }
516         return 0xff;
517 }
518
519 /*! \brief helper internal function: decodes a base64 "digit",
520  * \return value on success (0-63) and 0xff on error (invalid)*/
521 inline static unsigned base64_dec_char(unsigned char v)
522 {
523         switch(v){
524                 case '/':
525                         return 0x3f;
526                 case '+':
527                         return 0x3e;
528                 case ':':
529                 case ';':
530                 case '<':
531                 case '=':
532                 case '>':
533                 case '?':
534                 case '@':
535                 case '[':
536                 case '\\':
537                 case ']':
538                 case '^':
539                 case '_':
540                 case '`':
541                         return 0xff;
542                 default:
543                         if ((v)<'0')
544                                 return 0xff;
545                         if ((v)<='9')
546                                 return (v)-'0'+0x34;
547                         else if ((v)<='Z')
548                                 return (v)-'A';
549                         else if ((v) <='z')
550                                 return (v)-'a'+0x1a;
551         }
552         return 0xff;
553 }
554
555
556 #ifdef BASE64_LOOKUP_8K
557 /*!
558  * \return : size used from the output buffer (dst) on success ((slen+2)/3*4)
559  *          -size_needed on error
560  *
561  * \note WARNING: the output string is not 0-term
562  */
563 inline static int base64_enc(unsigned char* src, int slen,
564                                                         unsigned char* dst,  int dlen)
565 {
566         unsigned char* end;
567         int osize;
568         
569         osize=(slen+2)/3*4;
570         if (unlikely(dlen<osize))
571                 return -osize;
572         end=src+slen/3*3;
573         if (unlikely((long)dst%2)){
574                 for (;src<end; src+=3,dst+=4){
575                         dst[0]=FIRST_8B(BASE64_12(src[0], src[1]));
576                         dst[1]=LAST_8B(BASE64_12(src[0], src[1]));
577                         dst[2]=FIRST_8B(BASE64_34(src[1], src[2]));
578                         dst[3]=LAST_8B(BASE64_34(src[1], src[2]));
579                 }
580                 switch(slen%3){
581                         case 2:
582                                 dst[0]=FIRST_8B(BASE64_12(src[0], src[1]));
583                                 dst[1]=LAST_8B(BASE64_12(src[0], src[1]));
584                                 dst[2]=FIRST_8B(BASE64_34(src[1], 0));
585                                 dst[3]='=';
586                                 break;
587                         case 1:
588                                 dst[0]=FIRST_8B(BASE64_12(src[0], 0));
589                                 dst[1]=LAST_8B(BASE64_12(src[0], 0));
590                                 dst[2]='=';
591                                 dst[3]='=';
592                                 break;
593                 }
594         }else{
595                 for (;src<end; src+=3,dst+=4){
596                         *(unsigned short*)(dst+0)=_bx_b64_12[(src[0]<<4)|(src[1]>>4)];
597                         *(unsigned short*)(dst+2)=_bx_b64_12[((src[1]&0xf)<<8)|src[2]];
598                 }
599                 switch(slen%3){
600                         case 2:
601                                 *(unsigned short*)(dst+0)=_bx_b64_12[(src[0]<<4)|(src[1]>>4)];
602                                 *(unsigned short*)(dst+2)=_bx_b64_12[((src[1]&0xf)<<8)|0];
603                                 dst[3]='=';
604                                 break;
605                         case 1:
606                                 *(unsigned short*)(dst+0)=_bx_b64_12[(src[0]<<4)|0];
607                                 dst[2]='=';
608                                 dst[3]='=';
609                                 break;
610                 }
611         }
612         return osize;
613 }
614 #else /*BASE64_LOOKUP_8K*/
615 /*! \brief Convert to base64
616  * \return size used from the output buffer (dst) on success ((slen+2)/3*4)
617  *          -size_needed on error
618  * \note WARNING: the output string is not 0-term
619  */
620 inline static int base64_enc(unsigned char* src, int slen,
621                                                         unsigned char* dst,  int dlen)
622 {
623         unsigned char* end;
624         int osize;
625         
626         osize=(slen+2)/3*4;
627         if (unlikely(dlen<osize))
628                 return -osize;
629         end=src+slen/3*3;
630         for (;src<end; src+=3,dst+=4){
631                 dst[0]=BASE64_1(src[0]);
632                 dst[1]=BASE64_2(src[0], src[1]);
633                 dst[2]=BASE64_3(src[1], src[2]);
634                 dst[3]=BASE64_4(src[2]);
635         }
636         switch(slen%3){
637                 case 2:
638                         dst[0]=BASE64_1(src[0]);
639                         dst[1]=BASE64_2(src[0], src[1]);
640                         dst[2]=BASE64_3(src[1], 0);
641                         dst[3]='=';
642                         break;
643                 case 1:
644                         dst[0]=BASE64_1(src[0]);
645                         dst[1]=BASE64_2(src[0], 0);
646                         dst[2]='=';
647                         dst[3]='=';
648                         break;
649         }
650         return osize;
651 }
652 #endif /*BASE64_LOOKUP_8K*/
653
654
655
656 /*! \brief
657  * \return size used from the output buffer (dst) on success (max: slen/4*3)
658  *          -size_needed on error or 0 on bad base64 encoded string
659  * \note WARNING: the output string is not 0-term
660  */
661 inline static int base64_dec(unsigned char* src, int slen,
662                                                         unsigned char* dst,  int dlen)
663 {
664         
665         unsigned char* end;
666         int osize;
667         register unsigned a, b, c, d; /* more registers used, but allows for
668                                                                          paralles execution */
669         
670         if (unlikely((slen<4) || (slen%4) || 
671                                 (src[slen-2]=='=' && src[slen-1]!='=')))
672                 return 0; /* invalid base64 enc. */
673         osize=(slen/4*3)-(src[slen-2]=='=')-(src[slen-1]=='=');
674         if (unlikely(dlen<osize))
675                 return -osize;
676         end=src+slen-4;
677         for (;src<end; src+=4,dst+=3){
678 #if 0
679                 u=      (UNBASE64(src[0])<<18) | (UNBASE64(src[1])<<12) | 
680                         (UNBASE64(src[2])<<6)  |  UNBASE64(src[3]);
681                 dst[0]=u>>16;
682                 dst[1]=u>>8;
683                 dst[3]=u;
684 #endif
685                 a=UNBASE64(src[0]);
686                 b=UNBASE64(src[1]);
687                 c=UNBASE64(src[2]);
688                 d=UNBASE64(src[3]);
689                 dst[0]=(a<<2) | (b>>4);
690                 dst[1]=(b<<4) | (c>>2);
691                 dst[2]=(c<<6) | d;
692         }
693         switch(osize%3){
694                 case 0: /* no '=' => 3 output bytes at the end */
695                         a=UNBASE64(src[0]);
696                         b=UNBASE64(src[1]);
697                         c=UNBASE64(src[2]);
698                         d=UNBASE64(src[3]);
699                         dst[0]=(a<<2) | (b>>4);
700                         dst[1]=(b<<4) | (c>>2);
701                         dst[2]=(c<<6) | d;
702                         break;
703                 case 2: /* 1  '=' => 2 output bytes at the end */
704                         a=UNBASE64(src[0]);
705                         b=UNBASE64(src[1]);
706                         c=UNBASE64(src[2]);
707                         dst[0]=(a<<2) | (b>>4);
708                         dst[1]=(b<<4) | (c>>2);
709                         break;
710                 case 1: /* 2  '=' => 1 output byte at the end */
711                         a=UNBASE64(src[0]);
712                         b=UNBASE64(src[1]);
713                         dst[0]=(a<<2) | (b>>4);
714                         break;
715         }
716         return osize;
717 }
718
719
720
721
722 /*! \brief
723  * same as \ref base64_enc() but with a different alphabet, that allows simpler and
724  *  faster enc/dec
725  * \return size used from the output buffer (dst) on success ((slen+2)/3*4)
726  *          -size_needed on error
727  * \note WARNING: the alphabet includes ":;<>?@[]\`", so it might not be suited
728  *  in all cases (e.g. encoding something in a sip uri).
729  */
730 inline static int q_base64_enc(unsigned char* src, int slen,
731                                                         unsigned char* dst,  int dlen)
732 {
733 #define q_b64_base      '0'
734 #define q_b64_pad       'z'
735 #define Q_BASE64(v)     (unsigned char)((v)+q_b64_base)
736         unsigned char* end;
737         int osize;
738         
739         osize=(slen+2)/3*4;
740         if (unlikely(dlen<osize))
741                 return -osize;
742         end=src+slen/3*3;
743         for (;src<end; src+=3,dst+=4){
744                 dst[0]=Q_BASE64(src[0]>>2);
745                 dst[1]=(Q_BASE64((src[0]<<4)&0x3f) | (src[1]>>4));
746                 dst[2]=(Q_BASE64((src[1]<<2)&0x3f) | (src[2]>>6) );
747                 dst[3]=Q_BASE64(src[2]&0x3f);
748         }
749         switch(slen%3){
750                 case 2:
751                         dst[0]=Q_BASE64(src[0]>>2);
752                         dst[1]=(Q_BASE64((src[0]<<4)&0x3f) | (src[1]>>4));
753                         dst[2]=Q_BASE64((src[1]<<2)&0x3f);
754                         dst[3]=q_b64_pad;
755                         break;
756                 case 1:
757                         dst[0]=Q_BASE64(src[0]>>2);
758                         dst[1]=Q_BASE64((src[0]<<4)&0x3f);
759                         dst[2]=q_b64_pad;
760                         dst[3]=q_b64_pad;
761                         break;
762         }
763         return osize;
764 #undef Q_BASE64
765 }
766
767
768
769 /*! \brief
770  * same as \ref base64_enc() but with a different alphabet, that allows simpler and
771  *  faster enc/dec
772  *
773  * \return size used from the output buffer (dst) on success (max: slen/4*3)
774  *          -size_needed on error or 0 on bad base64 encoded string
775  * \note WARNING: the output string is not 0-term
776  */
777 inline static int q_base64_dec(unsigned char* src, int slen,
778                                                         unsigned char* dst,  int dlen)
779 {
780 #define Q_UNBASE64(v) (unsigned char)((v)-q_b64_base)
781         
782         unsigned char* end;
783         int osize;
784 #ifdef SINGLE_REG
785         register unsigned u;
786 #else
787         register unsigned a, b, c, d; /* more registers used, but allows for
788                                                                          paralles execution */
789 #endif
790         
791         if (unlikely((slen<4) || (slen%4) || 
792                                 (src[slen-2]==q_b64_pad && src[slen-1]!=q_b64_pad)))
793                 return 0; /* invalid base64 enc. */
794         osize=(slen/4*3)-(src[slen-2]==q_b64_pad)-(src[slen-1]==q_b64_pad);
795         if (unlikely(dlen<osize))
796                 return -osize;
797         end=src+slen-4;
798         for (;src<end; src+=4,dst+=3){
799 #ifdef SINGLE_REG
800                 u=      (Q_UNBASE64(src[0])<<18) | (Q_UNBASE64(src[1])<<12) | 
801                         (Q_UNBASE64(src[2])<<6)  |  Q_UNBASE64(src[3]);
802                 dst[0]=u>>16;
803                 dst[1]=u>>8;
804                 dst[2]=u;
805 #else
806                 a=Q_UNBASE64(src[0]);
807                 b=Q_UNBASE64(src[1]);
808                 c=Q_UNBASE64(src[2]);
809                 d=Q_UNBASE64(src[3]);
810                 dst[0]=(a<<2) | (b>>4);
811                 dst[1]=(b<<4) | (c>>2);
812                 dst[2]=(c<<6) | d;
813 #endif
814         }
815         switch(osize%3){
816                 case 0: /* no '=' => 3 output bytes at the end */
817 #ifdef SINGLE_REG
818                         u=      (Q_UNBASE64(src[0])<<18) | (Q_UNBASE64(src[1])<<12) | 
819                                 (Q_UNBASE64(src[2])<<6)  |  Q_UNBASE64(src[3]);
820                         dst[0]=u>>16;
821                         dst[1]=u>>8;
822                         dst[2]=u;
823 #else
824                         a=Q_UNBASE64(src[0]);
825                         b=Q_UNBASE64(src[1]);
826                         c=Q_UNBASE64(src[2]);
827                         d=Q_UNBASE64(src[3]);
828                         dst[0]=(a<<2) | (b>>4);
829                         dst[1]=(b<<4) | (c>>2);
830                         dst[2]=(c<<6) | d;
831 #endif
832                         break;
833                 case 2: /* 1  '=' => 2 output bytes at the end */
834 #ifdef SINGLE_REG
835                         u=      (Q_UNBASE64(src[0])<<12) | (Q_UNBASE64(src[1])<<6) | 
836                                 (Q_UNBASE64(src[2]));
837                         dst[0]=u>>10;
838                         dst[1]=u>>2;
839 #else
840                         a=Q_UNBASE64(src[0]);
841                         b=Q_UNBASE64(src[1]);
842                         c=Q_UNBASE64(src[2]);
843                         dst[0]=(a<<2) | (b>>4);
844                         dst[1]=(b<<4) | (c>>2);
845 #endif
846                         break;
847                 case 1: /* 2  '=' => 1 output byte at the end */
848 #ifdef SINGLE_REG
849                         dst[0]=(Q_UNBASE64(src[0])<<2) | (Q_UNBASE64(src[1])>>4); 
850 #else
851                         a=Q_UNBASE64(src[0]);
852                         b=Q_UNBASE64(src[1]);
853                         dst[0]=(a<<2) | (b>>4);
854 #endif
855                         break;
856         }
857         return osize;
858 #undef q_b64_base
859 #undef q_b64_pad
860 }
861
862 /*! \brief inits internal lookup tables */
863 int init_basex(void);
864
865
866 #endif /* _basex_h */