Enigma 3.2.2
A Simple, Reliable and Efficient Encryption Tool
Loading...
Searching...
No Matches
FileUtils.hpp
Go to the documentation of this file.
1#pragma once
2#ifndef ENIGMA_FILE_UTILS_H
3#define ENIGMA_FILE_UTILS_H
4
5#include <Core/Core.hpp>
6#include <Logger/Logger.hpp>
7#include <version> // version include has yvals_core.h include so we can use __cpp_lib_filesystem & __cpp_lib_experimental_filesystem defines
8
9#include <fstream>
10#if defined(__cpp_lib_filesystem)
11#include <filesystem>
12namespace fs = std::filesystem;
13#elif defined(__cpp_lib_experimental_filesystem)
14#include <experimental/filesystem>
15namespace fs = std::experimental::filesystem;
16#else
17#error compiler does not support std::filesystem
18#endif
19#include "FinalAction.hpp"
20
22class FileUtils final {
24
25 public:
26 static bool Read(const fs::path& filename, std::vector<byte>& buffer) {
27 if (std::ifstream ifs{filename, std::ios::binary | std::ios::ate}) // ate: open at the end
28 {
29 const std::size_t file_size = static_cast<std::size_t>(ifs.tellg());
30 buffer.resize(file_size, '\000');
31 ifs.seekg(0, std::ios::beg);
32 ifs.read(reinterpret_cast<char *>(buffer.data()), file_size);
33 ifs.close();
34 return true;
35 } else {
36 ENIGMA_ERROR("Failed to read file {}", filename.string());
37 return false;
38 }
39 }
40
41 static bool ReadString(const fs::path& filename, std::string& buffer) {
42 if (std::ifstream ifs{filename, std::ios::binary | std::ios::ate}) // ate: open at the end
43 {
44 const std::size_t file_size = static_cast<std::size_t>(ifs.tellg());
45 buffer.resize(file_size, '\000');
46 ifs.seekg(0, std::ios::beg);
47 ifs.read(reinterpret_cast<char *>(buffer.data()), file_size);
48 ifs.close();
49 return true;
50 } else {
51 ENIGMA_ERROR("Failed to read file {}", filename.string());
52 return false;
53 }
54 }
55
56 static bool Write(const fs::path& filename, const std::vector<byte>& buffer) {
57 if (std::ofstream ofs{filename, std::ios::binary}) {
58 ofs.write(reinterpret_cast<const char *>(buffer.data()), buffer.size());
59 ofs.close();
60 return true;
61 } else {
62 ENIGMA_ERROR("Failed to write file {}", filename.string());
63 return false;
64 }
65 }
66
67 static bool WriteString(const fs::path& filename, const std::string& buffer) {
68 if (std::ofstream ofs{filename, std::ios::binary}) {
69 ofs.write(reinterpret_cast<const char *>(buffer.data()), buffer.size());
70 ofs.close();
71 return true;
72 } else {
73 ENIGMA_ERROR("Failed to write file {}", filename.string());
74 return false;
75 }
76 }
77
78 /*
79 * Reads a file chunk by chunk
80 */
81 static void ReadChunksFstream(const fs::path& filename, const std::size_t max_chunk_size, const std::function<bool(std::vector<byte>&&)>& callback) {
82 if (std::ifstream ifs{filename, std::ios::binary}) {
83 while (!ifs.eof()) {
84 std::vector<Enigma::byte> chunk(max_chunk_size, '\000');
85 ifs.read(reinterpret_cast<char *>(chunk.data()), chunk.size());
86
87 // resize chunk if we read bytes less than max_chunk_size
88 const auto bytes_read = static_cast<std::size_t>(ifs.gcount());
89 if (bytes_read < max_chunk_size)
90 chunk.resize(bytes_read);
91
92 // serve chunk and see if false was returned from callback to stop reading loop.
93 if (!callback(std::move(chunk))) break;
94 }
95 ifs.close();
96 } else {
97 ENIGMA_ERROR("Failed to read file chunks {}", filename.string());
98 }
99 }
100
101 /*
102 * Reads a file chunk by chunk
103 */
104 static void ReadChunks(const fs::path& filename, const std::size_t max_chunk_size, const std::function<bool(std::vector<byte>&&)>& callback) {
105 // Open file to read from
106 std::FILE *file = std::fopen(filename.string().c_str(), "rb");
107 if (!file) {
108 ENIGMA_ERROR("Failed to read file chunks {}", filename.string());
109 return;
110 }
111 FinalAction fileCloser([&file] {
112 std::fclose(file);
113 });
114
115 // While end of file not reached...
116 while (!std::feof(file)) {
117 // Make some memory for chunk
118 std::vector<Enigma::byte> chunk(max_chunk_size, '\000');
119
120 // Read chunk and get back how many bytes were read
121 const std::size_t bytes_read = std::fread(chunk.data(), sizeof(Enigma::byte), max_chunk_size, file);
122 // resize chunk if we read bytes less than max_chunk_size
123 if (bytes_read < max_chunk_size)
124 chunk.resize(bytes_read);
125
126 // Serve chunk
127 if (!callback(std::move(chunk))) break;
128 }
129 }
130};
132
133#endif // !ENIGMA_FILE_UTILS_H
#define ENIGMA_ERROR(...)
Definition Logger.hpp:43
#define NS_ENIGMA_BEGIN
Enable/Disable Assertions.
Definition Macros.hpp:13
#define NS_ENIGMA_END
Definition Macros.hpp:14
#define ENIGMA_STATIC_CLASS(Class)
Makes a class static, which will prevent creating instances from it and only use it as Class::Func()....
Definition Macros.hpp:120
static bool WriteString(const fs::path &filename, const std::string &buffer)
Definition FileUtils.hpp:67
static bool Write(const fs::path &filename, const std::vector< byte > &buffer)
Definition FileUtils.hpp:56
static void ReadChunks(const fs::path &filename, const std::size_t max_chunk_size, const std::function< bool(std::vector< byte > &&)> &callback)
static bool ReadString(const fs::path &filename, std::string &buffer)
Definition FileUtils.hpp:41
static void ReadChunksFstream(const fs::path &filename, const std::size_t max_chunk_size, const std::function< bool(std::vector< byte > &&)> &callback)
Definition FileUtils.hpp:81
static bool Read(const fs::path &filename, std::vector< byte > &buffer)
Definition FileUtils.hpp:26
Executes a function at the end of the scope (deferred) using RAII gsl libs.
std::uint8_t byte
Definition Types.hpp:12