源码工程见: Gitee:Base64编码/解码
Base64.h:
#ifndef _BASE64_H
#define _BASE64_H
#include "Base64Define.h"
bool Base64_encode(char *codeSrc, int lenSrc, char *codeDes, int lenDes);
bool Base64_decode(char *codeSrc, int lenSrc, char *codeDes, int lenDes);
#endif
Base64.c:
#include "Base64.h"
#include <stdio.h>
// 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
// A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
// 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
// a b c d e f g h i j k l m n o p q r s t u v w x y z
// 52 53 54 55 56 57 58 59 60 61
// 0 1 2 3 4 5 6 7 8 9
// 62 63
// + /
//base64查询表
static char _encodetable[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
#define BASE64_CHAR_NULL 0xFF
///
// add by Wu Yin(lazy.fox.wu@gmail.com), 2022.10.19
//
// 必须保证 codeSrc+3 和 codeDes+4 不会内存越界
///
static bool _encodeOneSector(char *codeSrc, uchar lenSrc, char *codeDes) {
ifEqualsRetrunVal(codeSrc, NULL, false);
ifEqualsRetrunVal(codeDes, NULL, false);
if((lenSrc > 3) || (0 == lenSrc)) {
return false;
}
codeDes[0] = '=';
codeDes[1] = '=';
codeDes[2] = '=';
codeDes[3] = '=';
uchar idx = 0;
// =====================
// Base64 Sector 1
// =====================
idx = (codeSrc[0] & 0xFC) >> 2;
if(idx >= 64) {
return false;
}
codeDes[0] = _encodetable[idx];
// =====================
// Base64 Sector 2~4
// =====================
if(1 == lenSrc) {
idx = (codeSrc[0] & 0x03) << 4;
codeDes[1] = _encodetable[idx];
}
else if(2 == lenSrc) {
idx = ((codeSrc[0] & 0x03) << 4) | ((codeSrc[1] & 0xF0) >> 4);
codeDes[1] = _encodetable[idx];
idx = (codeSrc[1] & 0x0F) << 2;
codeDes[2] = _encodetable[idx];
}
else if(3 == lenSrc) {
idx = ((codeSrc[0] & 0x03) << 4) | ((codeSrc[1] & 0xF0) >> 4);
codeDes[1] = _encodetable[idx];
// printf("idx1=%d \n", idx);
idx = ((codeSrc[1] & 0x0F) << 2) | ((codeSrc[2] & 0xC0) >> 6);
codeDes[2] = _encodetable[idx];
// printf("idx2=%d \n", idx);
idx = codeSrc[2] & 0x3F;
codeDes[3] = _encodetable[idx];
// printf("idx3=%d \n", idx);
}
return true;
}
///
// add by Wu Yin(lazy.fox.wu@gmail.com), 2022.10.20
///
static uchar _base64CharToNum(char charBase64) {
if((charBase64 < '+') || (charBase64 > 'z')) {
return BASE64_CHAR_NULL;
}
if('=' == charBase64) {
return BASE64_CHAR_NULL;
}
if('+' == charBase64) {
return 62;
}
if('/' == charBase64) {
return 63;
}
if((charBase64 >= 'A') && (charBase64 <= 'Z')) {
return charBase64 - 'A';
}
if((charBase64 >= 'a') && (charBase64 <= 'z')) {
return charBase64 - 71;
}
if((charBase64 >= '0') && (charBase64 <= '9')) {
return charBase64 + 4;
}
return BASE64_CHAR_NULL;
}
///
// add by Wu Yin(lazy.fox.wu@gmail.com), 2022.10.20
//
// 必须保证 codeInput+4 和 codeDes+3 不会内存越界
///
static bool _decodeOneSector(char *codeInput, uchar lenSrc, char *codeDes) {
ifEqualsRetrunVal(codeInput, NULL, false);
ifEqualsRetrunVal(codeDes, NULL, false);
if((lenSrc > 4) || (0 == lenSrc)) {
return false;
}
codeDes[0] = 0;
codeDes[1] = 0;
codeDes[2] = 0;
// 不足4个的话,用“=”补齐
char codeSrc[4] = {'='};
for(int i = 0; i < lenSrc; i++) {
codeSrc[i] = codeInput[i];
}
// 前两个字符是“==”,是非法的Base64编码
if('=' == codeSrc[0]) {
return false;
}
if('=' == codeSrc[1]) {
return false;
}
uchar base64Num0 = _base64CharToNum(codeSrc[0]);
uchar base64Num1 = _base64CharToNum(codeSrc[1]);
uchar base64Num2 = _base64CharToNum(codeSrc[2]);
uchar base64Num3 = _base64CharToNum(codeSrc[3]);
// printf("%d-%d-%d-%d \n", base64Num0, base64Num1, base64Num2, base64Num3);
codeDes[0] = (base64Num0 << 2) | base64Num1 >> 4;
// "xx=="
if(BASE64_CHAR_NULL == base64Num2) {
codeDes[1] = base64Num1 << 4;
// printf("1: %c \n", codeDes[1]);
}
// "xxx="
else if(BASE64_CHAR_NULL == base64Num3) {
codeDes[1] = (base64Num1 << 4) | (base64Num2 >> 2);
// printf("2: %c \n", codeDes[1]);
}
// "xxxx"
else {
codeDes[1] = (base64Num1 << 4) | (base64Num2 >> 2);
codeDes[2] = (base64Num2 << 6) | base64Num3;
// printf("3: %c-%c \n", codeDes[1], codeDes[2]);
}
return true;
}
///
// add by Wu Yin(lazy.fox.wu@gmail.com), 2022.10.19
//
// 原码是每3字节一个Sector,可以转换成4个字节的Base64码
// Base64码是每4字节一个Sector,可以转换成3个原码
///
bool Base64_encode(char *codeSrc, int lenSrc, char *codeDes, int lenDes) {
ifEqualsRetrunVal(codeSrc, NULL, false);
ifEqualsRetrunVal(codeDes, NULL, false);
// 计算原码Sector个数
int srcCodeSectorCnt = (float)lenSrc / 3.0f + 0.9;
// 如果返回Base64码的数组太小,则返回错误
if(lenDes < srcCodeSectorCnt * 4) {
return false;
}
// ===============================
// 前部分,3的整数倍
// ===============================
int SectorCntHead = lenSrc / 3;
char *addrSrc = NULL;
char *addrDes = NULL;
int i = 0;
for(i = 0; i < SectorCntHead; i++) {
addrSrc = codeSrc + i * 3;
addrDes = codeDes + i * 4;
_encodeOneSector(addrSrc, 3, addrDes);
}
// ===============================
// 尾部分,3的余数
// ===============================
int SectorCntTail = lenSrc % 3;
if(0 == SectorCntTail) {
return true;
}
addrSrc = codeSrc + i * 3;
addrDes = codeDes + i * 4;
_encodeOneSector(addrSrc, SectorCntTail, addrDes);
return true;
}
///
// add by Wu Yin(lazy.fox.wu@gmail.com), 2022.10.20
///
bool Base64_decode(char *codeSrc, int lenSrc, char *codeDes, int lenDes) {
ifEqualsRetrunVal(codeSrc, NULL, false);
ifEqualsRetrunVal(codeDes, NULL, false);
// 计算原码Sector个数
int srcCodeSectorCnt = (float)lenSrc / 4.0f + 0.9;
// 如果返回Base64码的数组太小,则返回错误
if(lenDes < srcCodeSectorCnt * 3) {
return false;
}
// ====================================
// 前部分,4的整数倍
// ====================================
int SectorCntHead = lenSrc / 4;
char *addrSrc = NULL;
char *addrDes = NULL;
int i = 0;
for(i = 0; i < SectorCntHead; i++) {
addrSrc = codeSrc + i * 4;
addrDes = codeDes + i * 3;
// printf("addrSrc=%s \n", addrSrc);
_decodeOneSector(addrSrc, 4, addrDes);
}
// ====================================
// 尾部分,有可能不足4个,要用“=”补齐
// ====================================
int SectorCntTail = lenSrc % 4;
if(0 == SectorCntTail) {
return true;
}
addrSrc = codeSrc + i * 4;
addrDes = codeDes + i * 3;
_decodeOneSector(addrSrc, SectorCntTail, addrDes);
return true;
}