/** * @file cnvrt2bin.cpp * @brief Program to prime numbers from text format to binary format. * * This program converts a text file containing long integers, one * long integer per line, into a binary file of 64-bit little-endian * long integers. * * Syntax: cnvrt2bin --if=primes.txt --of=primes.bin * * If --if is not supplied, then STDIN is used. * If --of is not suplied, then STDOUT is used. * * Compile with command: g++ --std=c++23 cnvrt2bin.cpp -o cnvrt2bin * * @author Richard Lesh * @date 2025-02-05 * @version 1.0 */ #include #include #include #include #if __cplusplus >= 202302L #include #elif defined(_MSC_VER) #include #endif using namespace std; // Macro to convert a value to a string #define STRINGIFY(x) #x #define TO_STRING(x) STRINGIFY(x) //#pragma message("Compiling with C++ standard: " TO_STRING(__cplusplus)) bool isLittleEndian() { #if __cplusplus >= 202002L return endian::native == endian::little; #else uint64_t num = 0x1234567890abcdef; return *(reinterpret_cast(&num)) == 0xef; #endif } // Function to swap endianness of a 64-bit integer inline uint64_t swapEndian(uint64_t value) { #if __cplusplus >= 202302L return byteswap(value); #elif defined(__GNUC__) || defined(__clang__) return __builtin_bswap64(value); #elif defined(_MSC_VER) return _byteswap_uint64(value); #else // Portable fallback (slower) constexpr uint64_t swapEndian(uint64_t value) { return ((value >> 56) & 0x00000000000000FFULL) | ((value >> 40) & 0x000000000000FF00ULL) | ((value >> 24) & 0x0000000000FF0000ULL) | ((value >> 8) & 0x00000000FF000000ULL) | ((value << 8) & 0x000000FF00000000ULL) | ((value << 24) & 0x0000FF0000000000ULL) | ((value << 40) & 0x00FF000000000000ULL) | ((value << 56) & 0xFF00000000000000ULL); } #endif } ifstream inputFileStream; ofstream outputFileStream; istream* openInputStream(const string& filename) { if (!filename.empty()) { inputFileStream.open(filename); if (!inputFileStream) { return nullptr; } return &inputFileStream; } return &cin; } ostream* openOutputStream(const string& filename) { if (!filename.empty()) { outputFileStream.open(filename, ios::binary); if (!outputFileStream) { return nullptr; } return &outputFileStream; } // Ensure stdout is in binary mode on Windows #ifdef _WIN32 _setmode(_fileno(stdout), _O_BINARY); #endif return &cout; } int main(int argc, char** argv) { string inputFile, outputFile; for (int i = 1; i < argc; ++i) { string arg = argv[i]; if (arg.rfind("--if=", 0) == 0) { inputFile = arg.substr(5); } else if (arg.rfind("--of=", 0) == 0) { outputFile = arg.substr(5); } else if (arg == "--help" || arg == "-h") { cout << "Syntax: " << argv[0] << " [--if=infile.txt] [--of=outfile.bin]" << endl; return 1; } else { cerr << "Unknown argument: " << arg << endl; return 1; } } istream* inputStream = openInputStream(inputFile); if (!inputStream || !*inputStream) { cerr << "Error: Cannot open input file " << inputFile << endl; return 1; } ostream* outputStream = openOutputStream(outputFile); if (!outputStream || !*outputStream) { cerr << "Error: Cannot open output file " << outputFile << endl; return 1; } int64_t number; if (!isLittleEndian()) { while (*inputStream >> number) { uint64_t swapped = swapEndian(number); outputStream->write(reinterpret_cast(&swapped), sizeof(int64_t)); } } else { while (*inputStream >> number) { outputStream->write(reinterpret_cast(&number), sizeof(int64_t)); } } return 0; }