對(duì)于C/C++實(shí)現(xiàn)Base64的Encode代碼的閱讀日記

首先了解了下Base64的實(shí)現(xiàn)原理:https://baijiahao.baidu.com/s?id=1644892102150918183&wfr=spider&for=pc
大概內(nèi)容就是嫡纠,base64基于一個(gè)含有64個(gè)字符的編碼表(A-Z,a-z,0-9,+忘朝,/)违孝,將原文進(jìn)行轉(zhuǎn)碼,其步驟就是將原文按每三個(gè)字節(jié)一組分割毛嫉,每三個(gè)字節(jié)又按六位一組分為四組,然后高位補(bǔ)零妇菱,所以輸出結(jié)果里每個(gè)字節(jié)最大值也就63承粤,也就是對(duì)應(yīng)了base64的編碼表。
接下來(lái)直接看base64.c文件的代碼

int base64_encode(unsigned char *dst, int *dlen, const unsigned char *src, int slen) {
    int i, n;
    int C1, C2, C3;
    unsigned char *p;

    if (slen == 0)
        return (0);

    /**
     * 首先計(jì)算傳入進(jìn)來(lái)的原文按六位一組闯团,可以分成多少組
     * 所以將slen * 8辛臊,然后再除6 (由于8是2的3次方,用乘法算太耗時(shí)房交,所以直接左移3位)
     */
    n = (slen << 3) / 6;

    /**
     * 由于原文長(zhǎng)度并不一定是3的倍數(shù)彻舰,可能多1或2個(gè)字節(jié),所以還需要計(jì)算是否多出字節(jié)
     * 由于是將3字節(jié)按4個(gè)6位分割候味,需要以24位一組的規(guī)則計(jì)算新數(shù)組空間
     * 按照8:6 和 16:12的比例淹遵,那么多出1個(gè)字節(jié),原文總位數(shù)除以6负溪,余2透揣;多出2個(gè)字節(jié),余4
     * 再結(jié)合每組24位的原則川抡,原文多1個(gè)字節(jié)辐真,在n的基礎(chǔ)上须尚,新數(shù)組還差18位即3字節(jié)空間,原文多2字節(jié)侍咱,新數(shù)組還差12位即2字節(jié)空間
     * 所以當(dāng)余2耐床,n需要自加3,當(dāng)余4楔脯,n需要自加2
     */
    switch ((slen << 3) - (n * 6)) {
        case 2:
            n += 3;
            break;
        case 4:
            n += 2;
            break;
        default:
            break;
    }

    /**
     * 按理說(shuō)按照以上計(jì)算撩轰,最終n的值就是新數(shù)組的長(zhǎng)度,所以dlen只要不小于n即可
     * 但我不明白為什么這里的判斷是dlen要大于n昧廷,不知道是不是為了字符串結(jié)尾\0留位置堪嫂,但也沒看代碼里結(jié)尾添加字符串的結(jié)尾標(biāo)識(shí)啊,啊木柬,不懂c啊
     */
    if (*dlen < n + 1) {
        *dlen = n + 1;
        return (POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL);
    }

    /**
     * 這里是將原文按3字節(jié)分組皆串,得到組數(shù),多余的1眉枕、2字節(jié)后面單獨(dú)計(jì)算
     */
    n = (slen / 3) * 3;

    /**
     * 按組數(shù)循環(huán)取原文里的字節(jié)恶复,每次取3個(gè),這里用了新指針p速挑,指向地址與傳參的dst一樣谤牡,聯(lián)系上下文针余,我個(gè)人理解是為了計(jì)算新數(shù)組實(shí)際長(zhǎng)度
     * 但是用strlen不也可以計(jì)算dst的長(zhǎng)度么葫男,不明白為什么這樣做
     * em....好像直接用dst運(yùn)算,最后指針已經(jīng)指向字符串末尾了河泳,不過也不是沒有辦法回到開頭伶授,這個(gè)p還是讓我很糾結(jié)
     */
    for (i = 0, p = dst; i < n; i += 3) {
        C1 = *src++;
        C2 = *src++;
        C3 = *src++;

        /**
         * 首先將第一字節(jié)右移2位,得到左6位流纹,與上0x3F糜烹,高2位置0,得到第一個(gè)6位
         * 然后在編碼表里進(jìn)行轉(zhuǎn)碼漱凝,得到新組的第一字節(jié)
         */
        *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
        /**
         * 接著將第一字節(jié)與3疮蹦,即00000011,得到低2位茸炒,然后左移4位愕乎,
         * 然后將第二字節(jié)右移4位,做加法運(yùn)算壁公,得到第二個(gè)6位感论,轉(zhuǎn)碼得到新組的第二字節(jié)
         */
        *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
        /**
         * 將第二字節(jié)與15,即00001111紊册,得到低4位比肄,然后左移2位,
         * 然后將第三字節(jié)右移6位,得到高2位芳绩,做加法運(yùn)算掀亥,得到第三個(gè)6位,轉(zhuǎn)碼得到新組的第三字節(jié)
         */
        *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
        /**
         * 最后將第三字節(jié)與上0x3F妥色,清除高2位搪花,得到低6位,即第四個(gè)6位嘹害,轉(zhuǎn)碼得到新組的第四字節(jié)
         */
        *p++ = base64_enc_map[C3 & 0x3F];
    }
    //以上將正好可以按3字節(jié)一組分割的內(nèi)容全部轉(zhuǎn)碼完畢

    /**
     * 接下來(lái)判斷原文按3字節(jié)分組后撮竿,是否還多出不夠一組的內(nèi)容
     */
    if (i < slen) {
        /**
         * 既然多出內(nèi)容,那么至少多一個(gè)吼拥,所以第一字節(jié)直接取
         * 對(duì)第二字節(jié)需要判斷
         */
        C1 = *src++;
        C2 = ((i + 1) < slen) ? *src++ : 0;

        /**
         * 新組第一二字節(jié)可直接取6位然后轉(zhuǎn)碼
         */
        *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
        *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];

        /**
         * 如果原文只多出1字節(jié)倚聚,那么新組第三字節(jié)肯定為0,那么按照規(guī)則凿可,空字符用 '=' 代替
         * 如果多出2字節(jié)惑折,則還繼續(xù)進(jìn)行取6位,轉(zhuǎn)碼的運(yùn)算
         */
        if ((i + 1) < slen)
            *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
        else *p++ = '=';
        /**
         * 由于最多多出2字節(jié)枯跑,所以新組第四字節(jié)肯定沒有值可以取惨驶,也就是空字符,所以直接轉(zhuǎn)換為 '='
         */
        *p++ = '=';
    }

    /**
     * 這里我的理解是計(jì)算字符數(shù)組dst(p)的長(zhǎng)度敛助,但還是那句話粗卜,為啥不用strlen(dst)計(jì)算
     */
    *dlen = p - dst;
    *p = 0;

    return (0);
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市纳击,隨后出現(xiàn)的幾起案子续扔,更是在濱河造成了極大的恐慌,老刑警劉巖焕数,帶你破解...
    沈念sama閱讀 219,039評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件纱昧,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡堡赔,警方通過查閱死者的電腦和手機(jī)识脆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)善已,“玉大人灼捂,你說(shuō)我怎么就攤上這事』煌牛” “怎么了悉稠?”我有些...
    開封第一講書人閱讀 165,417評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)艘包。 經(jīng)常有香客問我偎球,道長(zhǎng)洒扎,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,868評(píng)論 1 295
  • 正文 為了忘掉前任衰絮,我火速辦了婚禮袍冷,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘猫牡。我一直安慰自己胡诗,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評(píng)論 6 392
  • 文/花漫 我一把揭開白布淌友。 她就那樣靜靜地躺著煌恢,像睡著了一般。 火紅的嫁衣襯著肌膚如雪震庭。 梳的紋絲不亂的頭發(fā)上瑰抵,一...
    開封第一講書人閱讀 51,692評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音器联,去河邊找鬼二汛。 笑死,一個(gè)胖子當(dāng)著我的面吹牛拨拓,可吹牛的內(nèi)容都是我干的肴颊。 我是一名探鬼主播,決...
    沈念sama閱讀 40,416評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼渣磷,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼婿着!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起醋界,我...
    開封第一講書人閱讀 39,326評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤竟宋,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后形纺,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體丘侠,經(jīng)...
    沈念sama閱讀 45,782評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評(píng)論 3 337
  • 正文 我和宋清朗相戀三年挡篓,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片帚称。...
    茶點(diǎn)故事閱讀 40,102評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡官研,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出闯睹,到底是詐尸還是另有隱情戏羽,我是刑警寧澤,帶...
    沈念sama閱讀 35,790評(píng)論 5 346
  • 正文 年R本政府宣布楼吃,位于F島的核電站始花,受9級(jí)特大地震影響妄讯,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜酷宵,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評(píng)論 3 331
  • 文/蒙蒙 一亥贸、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧浇垦,春花似錦炕置、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至此虑,卻和暖如春甚纲,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背朦前。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工介杆, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人况既。 一個(gè)月前我還...
    沈念sama閱讀 48,332評(píng)論 3 373
  • 正文 我出身青樓这溅,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親棒仍。 傳聞我的和親對(duì)象是個(gè)殘疾皇子悲靴,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容