/** * @file cnvrt2txt.cpp * @brief Program to prime numbers from binary format to text format. * * This program converts a file containing 64-bit little-endian long * integers in to a text file with one long integer per line. * * Syntax: cnvrt2txt --if=primes.bin --of=primes.txt * * 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 cnvrt2txt.cpp -o cnvrt2txt * * @author Richard Lesh * @date 2025-02-05 * @version 1.0 */ #include #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 std::endian::native == std::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 std::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 } std::ifstream inputFileStream; std::ofstream outputFileStream; std::istream* openInputStream(const std::string& filename) { if (!filename.empty()) { inputFileStream.open(filename, std::ios::binary); if (!inputFileStream) { return nullptr; } return &inputFileStream; } // Ensure stdin is in binary mode on Windows #ifdef _WIN32 _setmode(_fileno(stdin), _O_BINARY); #endif return &std::cin; } std::ostream* openOutputStream(const std::string& filename) { if (!filename.empty()) { outputFileStream.open(filename); if (!outputFileStream) { return nullptr; } return &outputFileStream; } return &std::cout; } int main(int argc, char** argv) { std::string inputFile, outputFile; for (int i = 1; i < argc; ++i) { std::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.bin] [--of=outfile.txt]" << endl; return 1; } else { std::cerr << "Unknown argument: " << arg << std::endl; return 1; } } std::istream* inputStream = openInputStream(inputFile); if (!inputStream || !*inputStream) { std::cerr << "Error: Cannot open input file " << inputFile << std::endl; return 1; } std::ostream* outputStream = openOutputStream(outputFile); if (!outputStream || !*outputStream) { std::cerr << "Error: Cannot open output file " << outputFile << std::endl; return 1; } int64_t number; if (!isLittleEndian()) { while (inputStream->read(reinterpret_cast(&number), sizeof(int64_t))) { *outputStream << swapEndian(number) << endl; } } else { while (inputStream->read(reinterpret_cast(&number), sizeof(int64_t))) { *outputStream << number << endl; } } return 0; }