/
waterstone
/
file_processor
Обзор
Документация
Войти
/
waterstone
/
file_processor
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/xor_file_processor.cpp
177 строк
5 KB
Peter Sakhno
Initial commit
19 янв 2026, 11:08
19 янв 2026, 11:08
1ffa16c
Код
Авторство
О чём код?
#include "xor_file_processor.h" #include <fstream> #include <iostream> #include <optional> #include <filesystem> namespace std_fs = std::filesystem; namespace XorFileProcessor { using Buffer = std::vector<char>; static void ProcessBuffer(uint64_t xor_key, Buffer::value_type* buffer, size_t size); static size_t CalcBufferSize(uintmax_t file_size); bool ProcessFile(const Context& context, IRunControl& ctrl) { Context ctx(context); try { // Check for input file existence if (!std_fs::exists(ctx.input_file_path)) { ctrl.SetErrorCode(ErrorCode::MissingInputFile); return false; } // Check that input file is just a file if (!std::filesystem::is_regular_file(ctx.input_file_path)) { ctrl.SetErrorCode(ErrorCode::InputIsNotFile); return false; } // Get size of input file const auto file_size = std_fs::file_size(ctx.input_file_path); // Open input file for reading in binary mode std::ifstream input_file(ctx.input_file_path, std::ios::binary); if (!input_file.is_open()) { ctrl.SetErrorCode(ErrorCode::CantOpenInputFile); return false; } // Open output file for writing in binary mode std::ofstream output_file(ctx.output_file_path, std::ios::binary); if (!output_file.is_open()) { ctrl.SetErrorCode(ErrorCode::CantOpenInputFile); return false; } // Calc good-enough buffer size const size_t buffer_size = CalcBufferSize(file_size); // Buffer XorFileProcessor::Buffer buffer(buffer_size); size_t total_processed = 0; while (input_file) { // Check if (ctrl.IsCanceled()) { ctrl.SetErrorCode(ErrorCode::Cancelled); return false; } // Ready data bytes from file to buffer input_file.read(buffer.data(), buffer.size()); // EOF? const auto bytes_read = input_file.gcount(); if (bytes_read <= 0) break; // Cals read bytes count const size_t process_bytes = std::min(buffer.size(), static_cast<size_t>(bytes_read)); // XOR data in buffer ProcessBuffer(ctx.xor_key, buffer.data(), process_bytes); // Write processed data to output output_file.write(buffer.data(), process_bytes); // Show progress total_processed += process_bytes; ctrl.SetProgress(total_processed, file_size); } // Check if all input data were processed if (total_processed != file_size) { ctrl.SetErrorCode(ErrorCode::NotFullyProcessed); return false; } // Delete input file if requeste if (ctx.delete_input_on_success) { try { input_file.close(); std_fs::remove(ctx.input_file_path); } catch (const std_fs::filesystem_error& e) { ctrl.SetErrorCode(ErrorCode::CantDeleteInputFile); ctrl.SetErrorText(e.what()); } catch (const std::exception& e) { ctrl.SetErrorCode(ErrorCode::CantDeleteInputFile); ctrl.SetErrorText(e.what()); } catch (...) { ctrl.SetErrorCode(ErrorCode::CantDeleteInputFile); } } return true; } catch (const std_fs::filesystem_error& e) { ctrl.SetErrorCode(ErrorCode::FileSystemError); ctrl.SetErrorText(e.what()); return false; } catch (const std::exception& e) { ctrl.SetErrorCode(ErrorCode::SystemError); ctrl.SetErrorText(e.what()); return false; } catch (...) { ctrl.SetErrorCode(ErrorCode::GeneralError); return false; } } static void ProcessBuffer(uint64_t xor_key, Buffer::value_type* buffer, size_t size) { if (buffer == nullptr || !size) return; if (!xor_key) return; // Process buffer by 8-byte blocks const size_t uint64_blocks = size / sizeof(uint64_t); uint64_t* data_as_uint64 = reinterpret_cast<uint64_t*>(buffer); for (size_t i = 0; i < uint64_blocks; ++i) data_as_uint64[i] ^= xor_key; // If buffer size is not a multiple of 8-byte block size const size_t remaining_bytes = size % sizeof(uint64_t); if (!remaining_bytes) return; // Treat xor key into a byte array const Buffer::value_type* key_bytes = reinterpret_cast<decltype(key_bytes)>(&xor_key); // Process remainig data auto remaining_data = buffer + (uint64_blocks * sizeof(uint64_t)); for (size_t i = 0; i < remaining_bytes; ++i) remaining_data[i] ^= key_bytes[i]; // It's safe, 'i' will always be less than key_bytes size } // Try to calc good-eneogh buffer size based on size of a file static size_t CalcBufferSize(uintmax_t file_size) { if (file_size <= 1024) { // <= 1KB return 1024; // 1KB } else if (file_size < 1024 * 1024) { // < 1MB return 64 * 1024; // 64KB } else if (file_size < 100 * 1024 * 1024) { // < 100MB return 256 * 1024; // 256KB } else if (file_size < 1024 * 1024 * 1024) { // < 1GB return 512 * 1024; // 512KB } else { // >= 1GB return 1024 * 1024; // 1MB } } }