basex.h 22 KB

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