Skip to content

Instantly share code, notes, and snippets.

@winks
Created March 17, 2018 23:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save winks/35492a4de4ca9cad6777919de223c427 to your computer and use it in GitHub Desktop.
Save winks/35492a4de4ca9cad6777919de223c427 to your computer and use it in GitHub Desktop.
ASCII85
#include <cmath>
#include <fstream>
#include <iostream>
#include <sys/stat.h>
#include <vector>
int32_t ascii_to_int(std::string c) {
int32_t rv;
for (size_t i=0; i<c.size(); ++i) {
rv <<= 8;
rv |= (int)c[i] & 0xFF;
}
return rv;
}
int32_t base85_to_int(std::string c) {
int32_t rv = 0;
for (int i=c.size()-1; i>=0; --i) {
int x = ((int) c[i]) - 33;
rv += x * (pow(85, (c.size()-i-1)));
}
return rv;
}
std::string int_to_base85(int32_t x) {
std::string rv;
int32_t rem = 0;
for (int i=4; i>=0; --i) {
rem = x % 85;
rv.insert(rv.begin(), (char) (rem + 33));
x = (x-rem) / 85;
}
return rv;
}
std::string int_to_ascii(int32_t x) {
std::string rv;
int32_t rem = 0;
for (int i=4; i>0; --i) {
rem = x & 127;
rv.insert(rv.begin(), (char) rem);
x >>= 8;
}
return rv;
}
int code(std::ifstream & in, int in_len, char pad_char, int32_t (*f1)(std::string), std::string (*f2)(int32_t))
{
std::string cx(" ");
int i = 0;
int j = 0;
int rv = 0;
std::string whole;
while (!in.eof()) {
j = 0;
for (i=0; i<in_len && !in.eof(); ++i) in.get(cx[i]);
if (in.eof() && i < in_len) {
for (j=i; j<in_len+1; ++j) cx[j-1] = pad_char;
j -= i;
}
i = 0;
whole.append(f2(f1(cx)));
}
if (j>0) whole.erase(whole.size()-j);
std::cout << whole << std::endl;
return rv;
}
int main(int argc, char *argv[])
{
if (argc < 3) {
std::cout << "Usage: " << argv[0] << "OPTION FILENAME" << std::endl;
std::cout << "\t-e\tencode to ASCII85" << std::endl;
std::cout << "\t-d\tdecode from ASCII85" << std::endl;
return 0;
}
std::string opt = argv[1];
if (opt != "-e" && opt != "-d") {
std::cout << "Wrong option: " << opt << std::endl;
return 0;
}
bool encodingMode = (opt == "-e");
char * filename;
filename = argv[2];
struct stat buf;
stat(filename, &buf);
std::cerr << "Reading " << filename << ", size: " << buf.st_size << std::endl;
std::ifstream in;
in.open(filename, std::ios::in | std::ios::binary);
if (!in || !in.is_open()) {
std::cerr << "Can't open input file " << filename << std::endl;
return 1;
}
int rv = 1;
if (encodingMode) {
rv = code(in, 4, '\0', ascii_to_int, int_to_base85);
} else {
rv = code(in, 5, 'u', base85_to_int, int_to_ascii);
}
if (in.is_open()) in.close();
return rv;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment