はじめに
独自実装した理由はとくにないです.以下のような変種が自由に作れるから?
s32 encodeBase64(FILE* file, s32 length, const u8* src); s32 decodeBase64(u8* dst, FILE* file);
共通処理
Base64の文字テーブルと, インデックス検索関数.
/*
This is free and unencumbered software released into the public domain.
*/
static const s8 Base64Chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const s8 Base64PadChar = '=';
s32 getIndexBase64Chars(s8 c)
{
if('A'<=c && c<='Z'){
return c-'A';
}else if('a'<=c && c<='z'){
return c-'a' + 26;
}else if('0'<=c && c<='9'){
return c-'0' + 52;
}
for(s32 i=62; i<64; ++i){
if(Base64Chars[i]==c){
return i;
}
}
return 0;
}
bool isBase64(s32 c)
{
return std::isalnum(c) || '+'==c || '/'==c;
}
s32 getLengthEncodedBase64(s32 l)
{
l = l<<3;
s32 n0 = l/6;
if(0<(l-n0*6)){
++n0;
}
s32 n1 = ((n0 + 3)>>2)<<2;
return n1;
}
s32 getLengthDecodedBase64(s32 l)
{
return (l*6 + 7)>>3;
}
Encode
s32 encodeBase64(s8* dst, s32 length, const u8* src)
{
ASSERT(NULL != dst);
ASSERT(0<=length);
ASSERT(NULL != src);
u8 tmp[3];
s32 d=0;
s32 l=0;
for(s32 i=0; i<length; ++i){
tmp[l] = src[i];
++l;
if(3<=l){
dst[d+0] = Base64Chars[tmp[0]>>2];
dst[d+1] = Base64Chars[((tmp[0]&0x03U)<<4) | (tmp[1]>>4)];
dst[d+2] = Base64Chars[((tmp[1]&0x0FU)<<2) | (tmp[2]>>6)];
dst[d+3] = Base64Chars[(tmp[2]&0x3FU)];
d += 4;
l = 0;
}
}
if(0<l){
for(s32 j=l; j<3; ++j){
tmp[j] = 0;
}
dst[d+0] = Base64Chars[tmp[0]>>2];
dst[d+1] = Base64Chars[((tmp[0]&0x03U)<<4) | (tmp[1]>>4)];
dst[d+2] = Base64Chars[((tmp[1]&0x0FU)<<2) | (tmp[2]>>6)];
dst[d+3] = Base64Chars[(tmp[2]&0x3FU)];
s32 n = l<<3;
s32 r = (l<<3)/6;
if(0<(n-r*6)){
++l;
}
for(s32 j=l; j<4; ++j){
dst[d+j] = Base64PadChar;
}
d+=4;
}
return d;
}
Decode
s32 decodeBase64(u8* dst, s32 length, const s8* src)
{
ASSERT(NULL != dst);
ASSERT(0<=length);
ASSERT(NULL != src);
s32 l=0;
s32 d=0;
u8 tmp[4];
for(s32 i=0;
i<length && isBase64(src[i]) && Base64PadChar != src[i];
++i)
{
tmp[l] = static_cast<u8>(getIndexBase64Chars(src[i]));
++l;
if(4<=l){
dst[d+0] = (tmp[0]<<2) | ((tmp[1]&0x30U)>>4);
dst[d+1] = (tmp[1]<<4) | ((tmp[2]&0x3CU)>>2);
dst[d+2] = (tmp[2]<<6) | tmp[3];
d += 3;
l=0;
}
}
if(0<l){
for(s32 i=l; i<4; ++i){
tmp[i] = 0;
}
dst[d+0] = (tmp[0]<<2) | ((tmp[1]&0x30U)>>4);
dst[d+1] = (tmp[1]<<4) | ((tmp[2]&0x3CU)>>2);
dst[d+2] = (tmp[2]<<6) | tmp[3];
d += (l*6)>>3;
}
return d;
}
0 件のコメント:
コメントを投稿