Mirror of :pserver:cvs@cvs.fefe.de:/cvs libowfat https://www.fefe.de/libowfat/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

56 lines
1.4 KiB

  1. #include "textcode.h"
  2. #include "haveinline.h"
  3. static inline int dec(unsigned char x) {
  4. if (x>='A' && x<='Z') return x-'A';
  5. if (x>='a' && x<='z') return x-'a'+26;
  6. if (x>='0' && x<='9') return x-'0'+26+26;
  7. switch (x) {
  8. case '+': return 62;
  9. case '/': return 63;
  10. default: return -1;
  11. }
  12. }
  13. size_t scan_base64(const char *src,char *dest,size_t *destlen) {
  14. unsigned short tmp=0,bits=0;
  15. register const unsigned char* s=(const unsigned char*) src;
  16. const char* orig=src;
  17. size_t i,j=0;
  18. for (i=0;;) {
  19. int a=dec(*s);
  20. if (a<0) {
  21. int equal=(*s=='=');
  22. while (*s=='=' && ((s-(const unsigned char*)src)&3)) ++s;
  23. tmp &= ((1<<bits)-1);
  24. if (!tmp || equal) { j=i; orig=(const char*)s; }
  25. break;
  26. }
  27. tmp=(tmp<<6)|a; bits+=6;
  28. ++s;
  29. if (bits>=8) {
  30. bits-=8;
  31. if (dest) dest[i]=(tmp>>bits);
  32. ++i;
  33. if (!bits) { j=i; orig=(const char*)s; }
  34. }
  35. }
  36. if (destlen) *destlen=j;
  37. return orig-src;
  38. }
  39. #ifdef UNITTEST
  40. #include <assert.h>
  41. #include <string.h>
  42. #include <stdio.h>
  43. int main() {
  44. char buf[100];
  45. size_t i,l;
  46. memset(buf,0,10); assert(scan_base64("Zm5vcmQ=",buf,&l)==8 && l==5 && !memcmp(buf,"fnord",6));
  47. memset(buf,0,10); assert(scan_base64("Zm5vcmQ",buf,&l)==7 && l==5 && !memcmp(buf,"fnord",6));
  48. memset(buf,0,10); assert(scan_base64("//8=",buf,&l)==4 && l==2 && !memcmp(buf,"\xff\xff",3));
  49. return 0;
  50. }
  51. #endif