#include #include #include #include #include "QR.hpp" #define UNUSED(var) (void) var; // Version is injected through cmake constexpr const char* VERSION = "@qr_VERSION@"; void printHelp() { std::string helpText = R"EOF( (C) 2023, MikO – a tool for generating QR codes – Released under MIT license. Usage: -f --format output file format. can be one of "cli, png, svg, jpg, bmp" -h --help show this help -i --input take data from this argument instead of stdin -o --output output file name without extension -s --size desired output file size in pixels -t --type output QR code type. can be one of "small, medium, large" In pixel based renderers (i.e. PNG), the output size may not be exactly as specified but be the nearest multiple of the actual cell size for the QR code. )EOF"; std::cout << "qr " << VERSION; std::cout << helpText << std::endl; } int main(int argc, char* argv[]) { if (argc < 1) { printHelp(); exit(1); } const option options[] = { {"help", no_argument, nullptr, 'h'}, {"input", required_argument, nullptr, 'i'}, {"output", required_argument, nullptr, 'o'}, {"size", required_argument, nullptr, 's'}, {"type", required_argument, nullptr, 't'}, {"format", required_argument, nullptr, 'f'}, {nullptr} }; std::string outputFile; size_t segmentSize = 0; massivedynamic::Type type = massivedynamic::Type::MEDIUM; massivedynamic::Format format = massivedynamic::Format::CONSOLE; bool fromStdin = true; bool anyParameterSet = false; std::string paramData = ""; for(;;) { int index = -1; int result = getopt_long(argc, argv, "ho:s:t:f:i:", options, &index); if (result == -1) break; anyParameterSet = true; const option* opt = &options[index]; UNUSED(opt); switch(result) { case 'o': { if (strlen(optarg) > 0) outputFile = optarg; break; } case 's': { segmentSize = std::atoi(optarg); break; } case 't': { std::string value = optarg; if (value == "small") type = massivedynamic::Type::SMALL; else if (value == "medium") type = massivedynamic::Type::MEDIUM; else if (value == "large") type = massivedynamic::Type::LARGE; else { printHelp(); return 1; } break; } case 'f': { std::string value = optarg; static_assert(massivedynamic::FormatLength == 5, "exhaustive formats: did you miss to add something here?"); if (value == "cli") format = massivedynamic::Format::CONSOLE; else if (value == "svg") format = massivedynamic::Format::SVG; else if (value == "png") format = massivedynamic::Format::PNG; else if (value == "jpg") format = massivedynamic::Format::JPG; else if (value == "bmp") format = massivedynamic::Format::BMP; else { printHelp(); return 1; } break; } case 'i': { fromStdin = false; paramData = optarg; break; } case 'h': default: printHelp(); return 0; } } std::string line; std::stringstream data; if (fromStdin) { if (!isatty(fileno(stdin))) { while (std::getline(std::cin, line)) { if (std::cin.eof() || line.empty()) { std::cin.clear(); break; } data << line; } } if (isatty(fileno(stdin)) || data.str().empty()) { std::cerr << "ERROR: no data from stdinput." << std::endl; if(!anyParameterSet) printHelp(); exit(1); } } else data << paramData; if (data.str().empty()) { std::cerr << "ERROR: input data is empty" << std::endl; exit(1); } if ((format == massivedynamic::Format::PNG || format == massivedynamic::Format::SVG) && outputFile.empty()) { std::cerr << "ERROR: output file name (-o, --output) can not be empty" << std::endl; return 1; } std::unique_ptr qr = std::make_unique(data.str(), outputFile, segmentSize, type, format); return 0; }