/****************************************************************************** * This program converts a file into Base64. Output is to the console. * * Copyright © 2021 Richard Lesh. All rights reserved. *****************************************************************************/ #undef NDEBUG #include "Utils.hpp" #include #include #include using namespace Utils; using namespace std; static string BASE64_CODES = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static int INPUT_COUNT = 0; static int OUTPUT_COUNT = 0; static bool HAS_LEFTOVER_BITS = false; static int LEFTOVER_BITS = 0; // Pass -1 to finish conversion void output_base64(int c) noexcept { int const WHICH_POSITION = INPUT_COUNT % 3; int six_bit_code = 0; if (c < 0) { switch (INPUT_COUNT % 3) { case 1: six_bit_code = (LEFTOVER_BITS << 4); cout << BASE64_CODES[six_bit_code]; cout << "=="; break; case 2: six_bit_code = (LEFTOVER_BITS << 2); cout << BASE64_CODES[six_bit_code]; cout << "="; break; default: // No padding needed break; } if (OUTPUT_COUNT % 76 != 0) { cout << endl; } return; } switch (WHICH_POSITION) { case 0: six_bit_code = (c >> 2) & 0x3F; LEFTOVER_BITS = c & 0x3; HAS_LEFTOVER_BITS = true; cout << BASE64_CODES[six_bit_code]; break; case 1: six_bit_code = (LEFTOVER_BITS << 4) | ((c >> 4) & 0xF); LEFTOVER_BITS = c & 0xF; HAS_LEFTOVER_BITS = true; cout << BASE64_CODES[six_bit_code]; break; case 2: six_bit_code = (LEFTOVER_BITS << 2) | ((c >> 6) & 0x3); LEFTOVER_BITS = c & 0x3F; cout << BASE64_CODES[six_bit_code]; cout << BASE64_CODES[LEFTOVER_BITS]; LEFTOVER_BITS = 0; HAS_LEFTOVER_BITS = false; ++OUTPUT_COUNT; break; } ++INPUT_COUNT; ++OUTPUT_COUNT; if (OUTPUT_COUNT % 76 == 0) { cout << endl; } } void convert_binary_file(string filespec) { ifstream ifh(filesystem::path(filespec).c_str(), ios_base::binary); if (!ifh.good()) { throw ios_base::failure("Problem opening input file!"); } unsigned char c; while (Utils::getbytes(ifh, c)) { output_base64(c); } output_base64(-1); ifh.close(); } int main(int argc, char **argv) { if (argc != 2) { cout << "Syntax: " << argv[0] << " {filename}" << endl; exit(1); } string filespec(argv[1]); try { convert_binary_file(filespec); } catch (ios_base::failure ex) { cout << "Error: " << Utils::exceptionMessage(ex) << endl; } return 0; }