Skip to content

Instantly share code, notes, and snippets.

@ACUVE
Created March 8, 2011 06:44
Show Gist options
  • Save ACUVE/859952 to your computer and use it in GitHub Desktop.
Save ACUVE/859952 to your computer and use it in GitHub Desktop.
base64プログラム
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <fstream>
//#include <iostream>
#include <string>
#include <exception>
#include <stdexcept>
#include "scope_exit.hpp"
bool base64decode(char const * const base64, unsigned int const plen, void ** const ret, unsigned int * const psize){
static char const list[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0,
0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0,
0, 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, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
unsigned int const len = plen ? plen : std::strlen(base64);
if(len & 0x3){
return false;
}
bool const haspadding = base64[len - 1] == '=', hastwopadding = base64[len - 2] == '=';
unsigned int const fulllen = (len >> 2) - haspadding;
unsigned char *retdata = new(std::nothrow) unsigned char[*psize = fulllen * 3 + (haspadding ? hastwopadding ? 1 : 2 : 0)];
*ret = retdata;
unsigned char const *basedata = reinterpret_cast<unsigned char const*>(base64);
for(unsigned int i = fulllen; ~(--i); basedata += 4, retdata += 3){
unsigned char const ddata[] = {list[basedata[0]], list[basedata[1]], list[basedata[2]], list[basedata[3]]};
retdata[0] = (ddata[0] << 2) | (ddata[1] >> 4);
retdata[1] = (ddata[1] << 4) | (ddata[2] >> 2);
retdata[2] = (ddata[2] << 6) | ddata[3];
}
if(haspadding){
if(hastwopadding){
retdata[0] = (list[basedata[0]] << 2) | (list[basedata[1]] >> 4);
}else{
unsigned char const ddata[] = {list[basedata[0]], list[basedata[1]], list[basedata[2]]};
retdata[0] = (ddata[0] << 2) | (ddata[1] >> 4);
retdata[1] = (ddata[1] << 4) | (ddata[2] >> 2);
}
}
return true;
}
bool base64encode(void const * const data, unsigned int const size, char ** const ret){
static char const * const list = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
unsigned int const fullsize = size / 3, rest = size % 3;
unsigned char *retp = new(std::nothrow) unsigned char[(fullsize + (rest ? 1 : 0)) * 4 + 1];
*ret = reinterpret_cast<char*>(retp);
unsigned char const *datap = static_cast<unsigned char const*>(data);
if(retp == NULL){
return false;
}
for(unsigned int i = fullsize; ~(--i); datap += 3, retp += 4){
retp[0] = list[datap[0] >> 2];
retp[1] = list[(datap[0] & 0x3) << 4 | datap[1] >> 4];
retp[2] = list[(datap[1] & 0xF) << 2 | datap[2] >> 6];
retp[3] = list[datap[2] & 0x3F];
}
switch(rest){
case 1:{
retp[0] = list[datap[0] >> 2];
retp[1] = list[(datap[0] & 0x3) << 4];
retp[2] = retp[3] = '=';
retp += 4;
break;
}
case 2:{
retp[0] = list[datap[0] >> 2];
retp[1] = list[(datap[0] & 0x3) << 4 | datap[1] >> 4];
retp[2] = list[(datap[1] & 0xF) << 2];
retp[3] = '=';
retp += 4;
break;
}
}
retp[0] = '\0';
return true;
}
void base64free(void *base64){
delete[] static_cast<unsigned char*>(base64);
}
int main(int argc, char **argv){
try{
if(argc < 2) throw std::runtime_error("引数が足りません");
if(argc == 2){
FILE *file = std::fopen(argv[1], "rb");
if(!file) throw std::runtime_error("fopenエラー");
scope_exit{std::fclose(file);};
if(std::fseek(file, 0, SEEK_END)) throw std::runtime_error("fseekエラー1");
long size = std::ftell(file);
if(size == -1) throw std::runtime_error("ftellエラー");
if(std::fseek(file, 0, SEEK_SET)) throw std::runtime_error("fseekエラー2");
char *data = static_cast<char*>(std::malloc(size * sizeof(char)));
if(!data) throw std::runtime_error("mallocエラー");
scope_exit{std::free(data);};
if(!std::fread(data, size, 1, file)) throw std::runtime_error("freadエラー");
char *ret;
if(!base64encode(data, size, &ret)) throw std::runtime_error("base64encodeエラー");
scope_exit{base64free(ret);};
std::puts(ret);
}else if(argc == 3){
std::ifstream file(argv[1]);
if(!file) throw std::runtime_error("ifstreamエラー");
FILE *ofile = std::fopen(argv[2], "wb");
if(!ofile) throw std::runtime_error("fopenエラー");
std::string str;
std::getline(file, str);
if(!file) throw std::runtime_error("getlineエラー");
void *p;
unsigned int size;
if(!base64decode(str.c_str(), str.length(), &p, &size)) throw std::runtime_error("base64decodeエラー");
scope_exit{base64free(p);};
if(!std::fwrite(p, size, 1, ofile)) throw std::runtime_error("fwriteエラー");
}else{
throw std::runtime_error("引数が多すぎます");
}
}catch(std::exception &e){
std::fprintf(stderr, "Exception is thrown. what:%s\n", e.what());
return -1;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment