• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Data Structures
  • Files
  • Directories
  • File List
  • Globals

basex.h

Go to the documentation of this file.
00001 /*
00002  * $Id$
00003  *
00004  * convert/decode to/from ascii using various bases
00005  *
00006  * Copyright (C) 2008 iptelorg GmbH
00007  *
00008  * Permission to use, copy, modify, and distribute this software for any
00009  * purpose with or without fee is hereby granted, provided that the above
00010  * copyright notice and this permission notice appear in all copies.
00011  *
00012  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
00013  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00014  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
00015  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00016  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00017  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
00018  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00019  */
00020 
00090 #ifndef _basex_h
00091 #define _basex_h
00092 
00093 #include "compiler_opt.h"
00094 
00095 /* defaults */
00096 #ifndef NO_BASE16_LOOKUP_TABLE
00097 #define BASE16_LOOKUP_TABLE
00098 #endif
00099 
00100 #ifndef NO_BASE64_LOOKUP_TABLE
00101 #define BASE64_LOOKUP_TABLE
00102 #endif
00103 
00104 #ifndef NO_BASE64_LOOKUP_8K
00105 #define BASE64_LOOKUP_8K
00106 #endif
00107 
00108 #ifndef NO_BASE16_LOOKUP_LARGE
00109 #define BASE16_LOOKUP_LARGE
00110 #endif
00111 
00112 #if !defined NO_BASE64_LOOKUP_LARGE && !defined BASE64_LOOKUP_8K
00113 #define BASE64_LOOKUP_LARGE
00114 #endif
00115 
00116 
00117 
00118 #if defined BASE16_READ_WHOLE_INTS || defined BASE64_READ_WHOLE_INTS || \
00119         defined BASE64_LOOKUP_8K
00120 #include "endianness.h"
00121 
00123 #define ALIGN_POINTER(p, type) \
00124         ((type*) ((long)((char*)(p)+sizeof(type)-1)&~(long)(sizeof(type)-1)))
00125 
00126 #define ALIGN_UINT_POINTER(p) ALIGN_POINTER(p, unsigned int)
00127 
00128 #endif
00129 
00130 
00131 #ifdef BASE16_LOOKUP_TABLE
00132 
00133 #ifdef BASE16_LOOKUP_LARGE
00134 
00136 extern unsigned char _bx_hexdig_hi[256];
00137 extern unsigned char _bx_hexdig_low[256];
00138 
00140 #define HEX_HI(h)       _bx_hexdig_hi[(unsigned char)(h)]
00141 
00142 #define HEX_LOW(h)      _bx_hexdig_low[(unsigned char)(h)]
00143 
00144 extern unsigned char _bx_unhexdig256[256];
00145 
00150 #define UNHEX(h)        _bx_unhexdig256[(h)]
00151 
00152 #else /* BASE16_LOOKUP_LARGE */
00153 
00155 extern unsigned char _bx_hexdig[16+1];
00156 
00157 #define HEX_4BITS(h) _bx_hexdig[(h)]
00158 #define HEX_HI(h)       HEX_4BITS(((unsigned char)(h))>>4)
00159 #define HEX_LOW(h)      HEX_4BITS((h)&0xf)
00160 
00161 extern unsigned char _bx_unhexdig32[32];
00162 #define UNHEX(h) _bx_unhexdig32[(((h))-'0')&0x1f]
00163 
00164 #endif /* BASE16_LOOKUP_LARGE */
00165 
00166 #else /* BASE16_LOOKUP_TABLE */
00167 /* no lookup tables */
00168 #if 0
00169 #define HEX_4BITS(h) (unsigned char)((unlikely((h)>=10))?((h)-10+'A'):(h)+'0')
00170 #define UNHEX(c) (unsigned char)((unlikely((c)>='A'))?(c)-'A'+10:(c)-'0')
00171 #else
00172 #define HEX_4BITS(hc) (unsigned char)( ((((hc)>=10)-1)&((hc)+'0')) | \
00173                                                                         ((((hc)<10)-1)&((hc)+'A')) )
00174 #define UNHEX(c) (unsigned char) ( ((((c)>'9')-1)& ((c)-'0')) | \
00175                                                                 ((((c)<='9')-1)&((c)-'A')) )
00176 #endif 
00177 
00178 #define HEX_HI(h)       HEX_4BITS(((unsigned char)(h))>>4)
00179 #define HEX_LOW(h)      HEX_4BITS((h)&0xf)
00180 
00181 #endif /* BASE16_LOOKUP_TABLE */
00182 
00183 
00184 #ifdef BASE64_LOOKUP_TABLE
00185 #ifdef BASE64_LOOKUP_LARGE
00186 /* large lookup tables, 2.5 k */
00187 
00188 extern unsigned char _bx_b64_first[256];
00189 extern unsigned char _bx_b64_second[4][256];
00190 extern unsigned char _bx_b64_third[4][256];
00191 extern unsigned char _bx_b64_fourth[256];
00192 
00193 #define BASE64_1(a) _bx_b64_first[(a)]
00194 #define BASE64_2(a,b) _bx_b64_second[(a)&0x3][(b)]
00195 #define BASE64_3(b,c) _bx_b64_third[(c)>>6][(b)]
00196 #define BASE64_4(c) _bx_b64_fourth[(c)]
00197 
00198 extern unsigned char _bx_ub64[256];
00199 #define UNBASE64(v) _bx_ub64[(v)]
00200 
00201 #elif defined BASE64_LOOKUP_8K
00202 /* even larger encode tables: 8k */
00203 extern unsigned short _bx_b64_12[4096];
00204 
00205 /* return a word (16 bits) */
00206 #define BASE64_12(a,b)  _bx_b64_12[((a)<<4)|((b)>>4)]
00207 #define BASE64_34(b,c)  _bx_b64_12[(((b)&0xf)<<8)|(c)]
00208 #ifdef __IS_LITTLE_ENDIAN
00209 #define FIRST_8B(s)     ((unsigned char)(s))
00210 #define LAST_8B(s)      ((s)>>8)
00211 #elif defined __IS_BIG_ENDIAN
00212 #define FIRST_8B(s)     ((s)>>8)
00213 #define LAST_8B(s)      ((unsigned char)(s))
00214 #else
00215 #error neither __IS_LITTLE_ENDIAN nor __IS_BIG_ENDIAN are defined
00216 #endif
00217 
00218 
00219 extern unsigned char _bx_ub64[256];
00220 #define UNBASE64(v) _bx_ub64[(v)]
00221 
00222 #else /* BASE64_LOOKUP_LARGE */
00223 /* small lookup tables */
00224 extern unsigned char _bx_b64[64+1];
00225 
00226 #define BASE64_DIG(v)   _bx_b64[(v)]
00227 
00228 #define BASE64_1(a)             BASE64_DIG((a)>>2)
00229 #define BASE64_2(a, b)  BASE64_DIG( (((a)<<4)&0x3f) | ((b)>>4))
00230 #define BASE64_3(b, c)  BASE64_DIG( (((b)<<2)&0x3f) | ((c)>>6))
00231 #define BASE64_4(c)             BASE64_DIG((c)&0x3f)
00232 
00233 extern unsigned char _bx_ub64[0x54+1];
00234 #define UNBASE64(v) _bx_ub64[(((v)&0x7f)-0x2b)]
00235 
00236 #endif /* BASE64_LOOKUP_LARGE */
00237 
00238 
00239 #else /* BASE64_LOOKUP_TABLE */
00240 
00241 #define BASE64_DIG(v) base64_enc_char(v)
00242 #define BASE64_1(a)             BASE64_DIG((a)>>2)
00243 #define BASE64_2(a, b)  BASE64_DIG( (((a)<<4)&0x3f) | ((b)>>4))
00244 #define BASE64_3(b, c)  BASE64_DIG( (((b)<<2)&0x3f) | ((c)>>6))
00245 #define BASE64_4(c)             BASE64_DIG((c)&0x3f)
00246 
00247 #define UNBASE64(v) base64_dec_char(v)
00248 
00249 #endif /* BASE64_LOOKUP_TABLE */
00250 
00251 
00252 
00254 #define base16_enc_len(l) (l*2)
00255 
00256 #define base16_max_dec_len(l) (l/2)
00257 
00258 #define base16_dec_len(b, l) base16_max_dec_len(l)
00259 
00260 #define base16_dec_min_len() 2
00261 
00262 #define base16_enc_min_len() 0
00263 
00265 #define base64_enc_len(l) (((l)+2)/3*4)
00266 
00267 #define base64_max_dec_len(l) ((l)/4*3)
00268 
00269 #define base64_dec_len(b, l) \
00270         (base64_max_dec_len(l)-((b)[(l)-2]=='=') -((b)[(l)-1]=='='))
00271 
00272 #define base64_dec_min_len() 4
00273 
00274 #define base64_enc_min_len() 0
00275 
00276 
00277 #ifdef BASE16_READ_WHOLE_INTS
00278 
00286 inline static int base16_enc(unsigned char* src, int slen, unsigned char*  dst, int dlen)
00287 {
00288         unsigned int* p;
00289         unsigned char* end;
00290         int osize;
00291         unsigned short us;
00292         
00293         osize=2*slen;
00294         if (unlikely(dlen<osize))
00295                 return -osize;
00296         end=src+slen;
00297         p=ALIGN_UINT_POINTER(src);
00298         if (likely((unsigned char*)p<end)){
00299                 switch((unsigned char)((unsigned char*)p-src)){
00300                         case 3:
00301                                 *dst=HEX_HI(*src);
00302                                 *(dst+1)=HEX_LOW(*src);
00303                                 dst+=2;
00304                                 src++;
00305                                 /* no break */
00306                         case 2:
00307                                 us=*(unsigned short*)(src);
00308 #if   defined __IS_LITTLE_ENDIAN
00309                                 *(dst+0)=HEX_HI(us);
00310                                 *(dst+1)=HEX_LOW(us);
00311                                 *(dst+2)=HEX_HI(us>>8);
00312                                 *(dst+3)=HEX_LOW(us>>8);
00313 #elif defined __IS_BIG_ENDIAN
00314                                 *(dst+2)=HEX_HI(us);
00315                                 *(dst+3)=HEX_LOW(us);
00316                                 *(dst+0)=HEX_HI(us>>8);
00317                                 *(dst+1)=HEX_LOW(us>>8);
00318 #endif
00319                                 dst+=4;
00320                                 /* no need to inc src */
00321                                 break;
00322                         case 1:
00323                                 *dst=HEX_HI(*src);
00324                                 *(dst+1)=HEX_LOW(*src);
00325                                 dst+=2;
00326                                 /* no need to inc src */
00327                         case 0:
00328                                 break;
00329                 }
00330                 for(;(unsigned char*)p<=(end-4);p++,dst+=8){
00331 #if   defined __IS_LITTLE_ENDIAN
00332                         *(dst+0)=HEX_HI(*p);
00333                         *(dst+1)=HEX_LOW(*p);
00334                         *(dst+2)=HEX_HI(((*p)>>8));
00335                         *(dst+3)=HEX_LOW(((*p)>>8));
00336                         *(dst+4)=HEX_HI(((*p)>>16));
00337                         *(dst+5)=HEX_LOW(((*p)>>16));
00338                         *(dst+6)=HEX_HI(((*p)>>24));
00339                         *(dst+7)=HEX_LOW(((*p)>>24));
00340 #elif defined __IS_BIG_ENDIAN
00341                         *(dst+6)=HEX_HI(*p);
00342                         *(dst+7)=HEX_LOW(*p);
00343                         *(dst+4)=HEX_HI(((*p)>>8));
00344                         *(dst+5)=HEX_LOW(((*p)>>8));
00345                         *(dst+2)=HEX_HI(((*p)>>16));
00346                         *(dst+3)=HEX_LOW(((*p)>>16));
00347                         *(dst+0)=HEX_HI(((*p)>>24));
00348                         *(dst+1)=HEX_LOW(((*p)>>24));
00349 #else
00350 #error neither BIG ro LITTLE endian defined
00351 #endif /* __IS_*_ENDIAN */
00352                 }
00353                 src=(unsigned char*)p;
00354                 /* src is 2-bytes aligned (short) */
00355                 switch((unsigned char)((unsigned char*)end-src)){
00356                         case 3:
00357                         case 2:
00358                                 us=*(unsigned short*)(src);
00359 #if   defined __IS_LITTLE_ENDIAN
00360                                 *(dst+0)=HEX_HI(us);
00361                                 *(dst+1)=HEX_LOW(us);
00362                                 *(dst+2)=HEX_HI(us>>8);
00363                                 *(dst+3)=HEX_LOW(us>>8);
00364 #elif defined __IS_BIG_ENDIAN
00365                                 *(dst+2)=HEX_HI(us);
00366                                 *(dst+3)=HEX_LOW(us);
00367                                 *(dst+0)=HEX_HI(us>>8);
00368                                 *(dst+1)=HEX_LOW(us>>8);
00369 #endif
00370                                 if ((end-src)==3){
00371                                         *(dst+4)=HEX_HI(*(src+2));
00372                                         *(dst+5)=HEX_LOW(*(src+2));
00373                                 }
00374                                 /* no need to inc anything */
00375                                 break;
00376                         case 1:
00377                                 *dst=HEX_HI(*src);
00378                                 *(dst+1)=HEX_LOW(*src);
00379                                 /* no need to inc anything */
00380                         case 0:
00381                                 break;
00382                 }
00383         }else if (unlikely((long)src&1)){
00384                 /* src is not 2-bytes (short) aligned */
00385                 switch((unsigned char)((unsigned char*)end-src)){
00386                         case 3:
00387                                 *dst=HEX_HI(*src);
00388                                 *(dst+1)=HEX_LOW(*src);
00389                                 dst+=2;
00390                                 src++;
00391                                 /* no break */
00392                         case 2:
00393                                 us=*(unsigned short*)(src);
00394 #if   defined __IS_LITTLE_ENDIAN
00395                                 *(dst+0)=HEX_HI(us);
00396                                 *(dst+1)=HEX_LOW(us);
00397                                 *(dst+2)=HEX_HI(us>>8);
00398                                 *(dst+3)=HEX_LOW(us>>8);
00399 #elif defined __IS_BIG_ENDIAN
00400                                 *(dst+2)=HEX_HI(us);
00401                                 *(dst+3)=HEX_LOW(us);
00402                                 *(dst+0)=HEX_HI(us>>8);
00403                                 *(dst+1)=HEX_LOW(us>>8);
00404 #endif
00405                                 /* no need to inc anything */
00406                                 break;
00407                         case 1:
00408                                 *dst=HEX_HI(*src);
00409                                 *(dst+1)=HEX_LOW(*src);
00410                                 /* no need to inc anything */
00411                         case 0:
00412                                 break;
00413                 }
00414         }else{
00415                 /* src is 2-bytes aligned (short) */
00416                 switch((unsigned char)((unsigned char*)end-src)){
00417                         case 3:
00418                         case 2:
00419                                 us=*(unsigned short*)(src);
00420 #if   defined __IS_LITTLE_ENDIAN
00421                                 *(dst+0)=HEX_HI(us);
00422                                 *(dst+1)=HEX_LOW(us);
00423                                 *(dst+2)=HEX_HI(us>>8);
00424                                 *(dst+3)=HEX_LOW(us>>8);
00425 #elif defined __IS_BIG_ENDIAN
00426                                 *(dst+2)=HEX_HI(us);
00427                                 *(dst+3)=HEX_LOW(us);
00428                                 *(dst+0)=HEX_HI(us>>8);
00429                                 *(dst+1)=HEX_LOW(us>>8);
00430 #endif
00431                                 if ((end-src)==3){
00432                                         *(dst+4)=HEX_HI(*(src+2));
00433                                         *(dst+5)=HEX_LOW(*(src+2));
00434                                 }
00435                                 /* no need to inc anything */
00436                                 break;
00437                         case 1:
00438                                 *dst=HEX_HI(*src);
00439                                 *(dst+1)=HEX_LOW(*src);
00440                                 /* no need to inc anything */
00441                         case 0:
00442                                 break;
00443                 }
00444         }
00445         
00446         return osize;
00447 }
00448 
00449 
00450 
00451 #else /* BASE16_READ_WHOLE_INTS */
00452 
00453 
00460 inline static int base16_enc(unsigned char* src, int slen,
00461                                                          unsigned char*  dst, int dlen)
00462 {
00463         unsigned char* end;
00464         int osize;
00465         
00466         osize=2*slen;
00467         if (unlikely(dlen<osize))
00468                 return -osize;
00469         end=src+slen;
00470         for (;src<end; src++,dst+=2){
00471                 *dst=HEX_HI(*src);
00472                 *(dst+1)=HEX_LOW(*src);
00473         }
00474         return osize;
00475 }
00476 
00477 
00478 #endif /* BASE16_READ_WHOLE_INTS */
00479 
00480 inline static int base16_dec(unsigned char* src, int slen, unsigned char* dst, int dlen)
00481 {
00482         unsigned char* end;
00483         int osize;
00484         
00485         osize=slen/2;
00486         if (unlikely(dlen<osize))
00487                 return -osize;
00488         end=src+2*osize;
00489         for (; src<end; src+=2, dst++)
00490                 *dst=(UNHEX(*src)<<4) | UNHEX(*(src+1));
00491         return osize;
00492 }
00493 
00494 
00495 
00496 
00497 
00501 inline static unsigned char base64_enc_char(unsigned char v)
00502 {
00503         switch(v){
00504                 case 0x3f:
00505                         return '/';
00506                 case 0x3e:
00507                         return '+';
00508                 default:
00509                         if (v<=25)
00510                                 return v+'A';
00511                         else if (v<=51)
00512                                 return v-26+'a';
00513                         else if (v<=61)
00514                                 return v-52+'0';
00515         }
00516         return 0xff;
00517 }
00518 
00521 inline static unsigned base64_dec_char(unsigned char v)
00522 {
00523         switch(v){
00524                 case '/':
00525                         return 0x3f;
00526                 case '+':
00527                         return 0x3e;
00528                 case ':':
00529                 case ';':
00530                 case '<':
00531                 case '=':
00532                 case '>':
00533                 case '?':
00534                 case '@':
00535                 case '[':
00536                 case '\\':
00537                 case ']':
00538                 case '^':
00539                 case '_':
00540                 case '`':
00541                         return 0xff;
00542                 default:
00543                         if ((v)<'0')
00544                                 return 0xff;
00545                         if ((v)<='9')
00546                                 return (v)-'0'+0x34;
00547                         else if ((v)<='Z')
00548                                 return (v)-'A';
00549                         else if ((v) <='z')
00550                                 return (v)-'a'+0x1a;
00551         }
00552         return 0xff;
00553 }
00554 
00555 
00556 #ifdef BASE64_LOOKUP_8K
00557 
00563 inline static int base64_enc(unsigned char* src, int slen,
00564                                                         unsigned char* dst,  int dlen)
00565 {
00566         unsigned char* end;
00567         int osize;
00568         
00569         osize=(slen+2)/3*4;
00570         if (unlikely(dlen<osize))
00571                 return -osize;
00572         end=src+slen/3*3;
00573         if (unlikely((long)dst%2)){
00574                 for (;src<end; src+=3,dst+=4){
00575                         dst[0]=FIRST_8B(BASE64_12(src[0], src[1]));
00576                         dst[1]=LAST_8B(BASE64_12(src[0], src[1]));
00577                         dst[2]=FIRST_8B(BASE64_34(src[1], src[2]));
00578                         dst[3]=LAST_8B(BASE64_34(src[1], src[2]));
00579                 }
00580                 switch(slen%3){
00581                         case 2:
00582                                 dst[0]=FIRST_8B(BASE64_12(src[0], src[1]));
00583                                 dst[1]=LAST_8B(BASE64_12(src[0], src[1]));
00584                                 dst[2]=FIRST_8B(BASE64_34(src[1], 0));
00585                                 dst[3]='=';
00586                                 break;
00587                         case 1:
00588                                 dst[0]=FIRST_8B(BASE64_12(src[0], 0));
00589                                 dst[1]=LAST_8B(BASE64_12(src[0], 0));
00590                                 dst[2]='=';
00591                                 dst[3]='=';
00592                                 break;
00593                 }
00594         }else{
00595                 for (;src<end; src+=3,dst+=4){
00596                         *(unsigned short*)(dst+0)=_bx_b64_12[(src[0]<<4)|(src[1]>>4)];
00597                         *(unsigned short*)(dst+2)=_bx_b64_12[((src[1]&0xf)<<8)|src[2]];
00598                 }
00599                 switch(slen%3){
00600                         case 2:
00601                                 *(unsigned short*)(dst+0)=_bx_b64_12[(src[0]<<4)|(src[1]>>4)];
00602                                 *(unsigned short*)(dst+2)=_bx_b64_12[((src[1]&0xf)<<8)|0];
00603                                 dst[3]='=';
00604                                 break;
00605                         case 1:
00606                                 *(unsigned short*)(dst+0)=_bx_b64_12[(src[0]<<4)|0];
00607                                 dst[2]='=';
00608                                 dst[3]='=';
00609                                 break;
00610                 }
00611         }
00612         return osize;
00613 }
00614 #else /*BASE64_LOOKUP_8K*/
00615 
00620 inline static int base64_enc(unsigned char* src, int slen,
00621                                                         unsigned char* dst,  int dlen)
00622 {
00623         unsigned char* end;
00624         int osize;
00625         
00626         osize=(slen+2)/3*4;
00627         if (unlikely(dlen<osize))
00628                 return -osize;
00629         end=src+slen/3*3;
00630         for (;src<end; src+=3,dst+=4){
00631                 dst[0]=BASE64_1(src[0]);
00632                 dst[1]=BASE64_2(src[0], src[1]);
00633                 dst[2]=BASE64_3(src[1], src[2]);
00634                 dst[3]=BASE64_4(src[2]);
00635         }
00636         switch(slen%3){
00637                 case 2:
00638                         dst[0]=BASE64_1(src[0]);
00639                         dst[1]=BASE64_2(src[0], src[1]);
00640                         dst[2]=BASE64_3(src[1], 0);
00641                         dst[3]='=';
00642                         break;
00643                 case 1:
00644                         dst[0]=BASE64_1(src[0]);
00645                         dst[1]=BASE64_2(src[0], 0);
00646                         dst[2]='=';
00647                         dst[3]='=';
00648                         break;
00649         }
00650         return osize;
00651 }
00652 #endif /*BASE64_LOOKUP_8K*/
00653 
00654 
00655 
00661 inline static int base64_dec(unsigned char* src, int slen,
00662                                                         unsigned char* dst,  int dlen)
00663 {
00664         
00665         unsigned char* end;
00666         int osize;
00667         register unsigned a, b, c, d; /* more registers used, but allows for
00668                                                                          paralles execution */
00669         
00670         if (unlikely((slen<4) || (slen%4) || 
00671                                 (src[slen-2]=='=' && src[slen-1]!='=')))
00672                 return 0; /* invalid base64 enc. */
00673         osize=(slen/4*3)-(src[slen-2]=='=')-(src[slen-1]=='=');
00674         if (unlikely(dlen<osize))
00675                 return -osize;
00676         end=src+slen-4;
00677         for (;src<end; src+=4,dst+=3){
00678 #if 0
00679                 u=      (UNBASE64(src[0])<<18) | (UNBASE64(src[1])<<12) | 
00680                         (UNBASE64(src[2])<<6)  |  UNBASE64(src[3]);
00681                 dst[0]=u>>16;
00682                 dst[1]=u>>8;
00683                 dst[3]=u;
00684 #endif
00685                 a=UNBASE64(src[0]);
00686                 b=UNBASE64(src[1]);
00687                 c=UNBASE64(src[2]);
00688                 d=UNBASE64(src[3]);
00689                 dst[0]=(a<<2) | (b>>4);
00690                 dst[1]=(b<<4) | (c>>2);
00691                 dst[2]=(c<<6) | d;
00692         }
00693         switch(osize%3){
00694                 case 0: /* no '=' => 3 output bytes at the end */
00695                         a=UNBASE64(src[0]);
00696                         b=UNBASE64(src[1]);
00697                         c=UNBASE64(src[2]);
00698                         d=UNBASE64(src[3]);
00699                         dst[0]=(a<<2) | (b>>4);
00700                         dst[1]=(b<<4) | (c>>2);
00701                         dst[2]=(c<<6) | d;
00702                         break;
00703                 case 2: /* 1  '=' => 2 output bytes at the end */
00704                         a=UNBASE64(src[0]);
00705                         b=UNBASE64(src[1]);
00706                         c=UNBASE64(src[2]);
00707                         dst[0]=(a<<2) | (b>>4);
00708                         dst[1]=(b<<4) | (c>>2);
00709                         break;
00710                 case 1: /* 2  '=' => 1 output byte at the end */
00711                         a=UNBASE64(src[0]);
00712                         b=UNBASE64(src[1]);
00713                         dst[0]=(a<<2) | (b>>4);
00714                         break;
00715         }
00716         return osize;
00717 }
00718 
00719 
00720 
00721 
00730 inline static int q_base64_enc(unsigned char* src, int slen,
00731                                                         unsigned char* dst,  int dlen)
00732 {
00733 #define q_b64_base      '0'
00734 #define q_b64_pad       'z'
00735 #define Q_BASE64(v)     (unsigned char)((v)+q_b64_base)
00736         unsigned char* end;
00737         int osize;
00738         
00739         osize=(slen+2)/3*4;
00740         if (unlikely(dlen<osize))
00741                 return -osize;
00742         end=src+slen/3*3;
00743         for (;src<end; src+=3,dst+=4){
00744                 dst[0]=Q_BASE64(src[0]>>2);
00745                 dst[1]=(Q_BASE64((src[0]<<4)&0x3f) | (src[1]>>4));
00746                 dst[2]=(Q_BASE64((src[1]<<2)&0x3f) | (src[2]>>6) );
00747                 dst[3]=Q_BASE64(src[2]&0x3f);
00748         }
00749         switch(slen%3){
00750                 case 2:
00751                         dst[0]=Q_BASE64(src[0]>>2);
00752                         dst[1]=(Q_BASE64((src[0]<<4)&0x3f) | (src[1]>>4));
00753                         dst[2]=Q_BASE64((src[1]<<2)&0x3f);
00754                         dst[3]=q_b64_pad;
00755                         break;
00756                 case 1:
00757                         dst[0]=Q_BASE64(src[0]>>2);
00758                         dst[1]=Q_BASE64((src[0]<<4)&0x3f);
00759                         dst[2]=q_b64_pad;
00760                         dst[3]=q_b64_pad;
00761                         break;
00762         }
00763         return osize;
00764 #undef Q_BASE64
00765 }
00766 
00767 
00768 
00777 inline static int q_base64_dec(unsigned char* src, int slen,
00778                                                         unsigned char* dst,  int dlen)
00779 {
00780 #define Q_UNBASE64(v) (unsigned char)((v)-q_b64_base)
00781         
00782         unsigned char* end;
00783         int osize;
00784 #ifdef SINGLE_REG
00785         register unsigned u;
00786 #else
00787         register unsigned a, b, c, d; /* more registers used, but allows for
00788                                                                          paralles execution */
00789 #endif
00790         
00791         if (unlikely((slen<4) || (slen%4) || 
00792                                 (src[slen-2]==q_b64_pad && src[slen-1]!=q_b64_pad)))
00793                 return 0; /* invalid base64 enc. */
00794         osize=(slen/4*3)-(src[slen-2]==q_b64_pad)-(src[slen-1]==q_b64_pad);
00795         if (unlikely(dlen<osize))
00796                 return -osize;
00797         end=src+slen-4;
00798         for (;src<end; src+=4,dst+=3){
00799 #ifdef SINGLE_REG
00800                 u=      (Q_UNBASE64(src[0])<<18) | (Q_UNBASE64(src[1])<<12) | 
00801                         (Q_UNBASE64(src[2])<<6)  |  Q_UNBASE64(src[3]);
00802                 dst[0]=u>>16;
00803                 dst[1]=u>>8;
00804                 dst[2]=u;
00805 #else
00806                 a=Q_UNBASE64(src[0]);
00807                 b=Q_UNBASE64(src[1]);
00808                 c=Q_UNBASE64(src[2]);
00809                 d=Q_UNBASE64(src[3]);
00810                 dst[0]=(a<<2) | (b>>4);
00811                 dst[1]=(b<<4) | (c>>2);
00812                 dst[2]=(c<<6) | d;
00813 #endif
00814         }
00815         switch(osize%3){
00816                 case 0: /* no '=' => 3 output bytes at the end */
00817 #ifdef SINGLE_REG
00818                         u=      (Q_UNBASE64(src[0])<<18) | (Q_UNBASE64(src[1])<<12) | 
00819                                 (Q_UNBASE64(src[2])<<6)  |  Q_UNBASE64(src[3]);
00820                         dst[0]=u>>16;
00821                         dst[1]=u>>8;
00822                         dst[2]=u;
00823 #else
00824                         a=Q_UNBASE64(src[0]);
00825                         b=Q_UNBASE64(src[1]);
00826                         c=Q_UNBASE64(src[2]);
00827                         d=Q_UNBASE64(src[3]);
00828                         dst[0]=(a<<2) | (b>>4);
00829                         dst[1]=(b<<4) | (c>>2);
00830                         dst[2]=(c<<6) | d;
00831 #endif
00832                         break;
00833                 case 2: /* 1  '=' => 2 output bytes at the end */
00834 #ifdef SINGLE_REG
00835                         u=      (Q_UNBASE64(src[0])<<12) | (Q_UNBASE64(src[1])<<6) | 
00836                                 (Q_UNBASE64(src[2]));
00837                         dst[0]=u>>10;
00838                         dst[1]=u>>2;
00839 #else
00840                         a=Q_UNBASE64(src[0]);
00841                         b=Q_UNBASE64(src[1]);
00842                         c=Q_UNBASE64(src[2]);
00843                         dst[0]=(a<<2) | (b>>4);
00844                         dst[1]=(b<<4) | (c>>2);
00845 #endif
00846                         break;
00847                 case 1: /* 2  '=' => 1 output byte at the end */
00848 #ifdef SINGLE_REG
00849                         dst[0]=(Q_UNBASE64(src[0])<<2) | (Q_UNBASE64(src[1])>>4); 
00850 #else
00851                         a=Q_UNBASE64(src[0]);
00852                         b=Q_UNBASE64(src[1]);
00853                         dst[0]=(a<<2) | (b>>4);
00854 #endif
00855                         break;
00856         }
00857         return osize;
00858 #undef q_b64_base
00859 #undef q_b64_pad
00860 }
00861 
00863 int init_basex(void);
00864 
00865 
00866 #endif /* _basex_h */

Generated on Tue May 22 2012 13:10:02 for SIP Router by  doxygen 1.7.1