// Copyright 2022, FOSS-VG Developers and Contributers // // Author(s): // BodgeMaster // // This program is free software: you can redistribute it and/or modify it // under the terms of the GNU Affero General Public License as published // by the Free Software Foundation, version 3. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied // warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // version 3 along with this program. // If not, see https://www.gnu.org/licenses/agpl-3.0.en.html #include #include #include #include #include "../lib/cli.hpp" #define EXIT_SUCCESS 0 #define EXIT_RUNTIME 1 #define EXIT_USAGE 2 int main(int argc, char* argv[]) { std::vector flags; flags.push_back(CLI::Flag('x', "hexadecimal", "base 16")); flags.push_back(CLI::Flag('o', "octal", "base 8")); flags.push_back(CLI::Flag('b', "binary", "base 2")); flags.push_back(CLI::Flag('d', "decimal", "base 10")); flags.push_back(CLI::Flag('h', "help", "print help and exit")); flags.push_back(CLI::Flag('l', "license", "print license information and exit")); std::vector options; std::vector arguments; arguments.push_back(CLI::Argument("NUMBER", "the number to convert")); CLI::ArgumentsParser cliParser = CLI::ArgumentsParser(argc, argv, flags, options, arguments, "Convert numbers between predefined bases", "This only works for unsigned numbers.\n\tBaseConvert understands the prefixes 0x, 0b, 0o, and 0 in input numbers."); if (cliParser.getFlag("help").value) { std::cout << cliParser.getUsage() << std::endl; return EXIT_SUCCESS; } if (cliParser.getFlag("license").value){ std::cout << "Copyright 2022, FOSS-VG Developers and Contributers\n" << "\n" << "BaseConvert is part of the FOSS-VG development tool suite.\n" << "\n" << "This program is free software: you can redistribute it and/or modify it\n" << "under the terms of the GNU Affero General Public License as published\n" << "by the Free Software Foundation, version 3.\n" << "\n" << "This program is distributed in the hope that it will be useful,\n" << "but WITHOUT ANY WARRANTY; without even the implied\n" << "warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n" << "See the GNU Affero General Public License for more details.\n" << "\n" << "You should have received a copy of the GNU Affero General Public License\n" << "version 3 along with this program.\n" << "If not, see https://www.gnu.org/licenses/agpl-3.0.en.html" << std::endl; return EXIT_SUCCESS; } if (cliParser.wrongUsage) { std::cout << cliParser.getUsage() << std::endl; return EXIT_USAGE; } std::string numberString = cliParser.getArgument(0).value; uint8_t base = 10; uint64_t* number = new uint64_t; if (numberString == "") { std::cerr << "Empty string is not a valid number." << std::endl; return EXIT_RUNTIME; } if (numberString[0] == '0') { if (numberString.substr(0, 2)=="0x" || numberString.substr(0, 2)=="0X") { base = 16; numberString = numberString.substr(2, numberString.length()-2); } else if (numberString.substr(0, 2)=="0b" || numberString.substr(0, 2)=="0B") { base = 2; numberString = numberString.substr(2, numberString.length()-2); } else if (numberString.substr(0, 2)=="0o" || numberString.substr(0, 2)=="0O") { base = 8; numberString = numberString.substr(2, numberString.length()-2); } else { base = 8; } } *number = std::stoull(numberString, nullptr, base); if (cliParser.getFlag("hexadecimal").value) { std::cout << "0x" << std::hex << *number << std::endl; } else if (cliParser.getFlag("octal").value) { *number==0? std::cout << "0" << std::endl : std::cout << "0" << std::oct << *number << std::endl; } else if (cliParser.getFlag("binary").value) { std::bitset<64> bitset = std::bitset<64>(*number); bool foundFirstBit = false; std::cout << "0b"; for (uint8_t i=0; i<64; i++) { if (bitset[63-i]) { std::cout << "1"; foundFirstBit = true; } else if (foundFirstBit) { std::cout << "0"; } } if (!foundFirstBit) { std::cout << "0"; } std::cout << std::endl; } else if (cliParser.getFlag("decimal").value) { std::cout << *number << std::endl; } else { std::cout << cliParser.getUsage() << std::endl; return EXIT_USAGE; } delete number; return EXIT_SUCCESS; }