-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathFileStream.h
150 lines (110 loc) · 4.37 KB
/
FileStream.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
//
// <author> damirlj@yahoo.com
// Copyright (c) 2021. All rights reserved!
//
#ifndef FILE_STREAMS_H_
#define FILE_STREAMS_H_
#include <errno.h>
#include <string.h>
#include <fstream>
#include <filesystem>
#include <string>
#include <vector>
namespace utils::file
{
/**
* RAII wrapper around the std::fstream
*/
class FileStream
{
public:
/**
* C-tor
* Create the file stream.
* Open the file.
*
* @param path The absolute file path
* @param mode Open mode, which specify the type of the file stream and the
* way how it should be created
*/
FileStream(const std::filesystem::path& path, std::ios_base::openmode mode) noexcept;
// Copy operation forbidden
FileStream(const FileStream& ) = delete;
FileStream& operator = (const FileStream& ) = delete;
bool isOpen() const;
std::size_t size() const;
/**
* D-tor
*
* Close the file stream
*/
virtual ~FileStream();
protected:
mutable std::fstream m_file;
};
template <class T>
class OutputFileStream : public FileStream
{
public:
explicit OutputFileStream(const std::filesystem::path& path) noexcept :
FileStream(path, std::ofstream::out)
{}
OutputFileStream(const std::filesystem::path& path, std::ios_base::openmode mode) noexcept :
FileStream(path, std::ofstream::out | mode)
{}
virtual ~OutputFileStream() override = default;
using data_t = T;
using chunk_t = std::vector<data_t>;
virtual void write(const chunk_t& data)
{
writeData(data);
}
virtual void write(chunk_t&& data)
{
writeData(std::move(data));
}
private:
template <class Data>
static constexpr bool compatible = std::is_same_v<std::decay_t<Data>, chunk_t> ||
std::is_constructible_v<chunk_t, Data> ||
std::is_convertible_v<Data, chunk_t>;
template<class Data, typename = std::enable_if_t<compatible>>
void writeData(Data&& data)
{
auto&& rdata = std::forward<Data>(data);//universal reference
m_file.write(reinterpret_cast<const char*>(&rdata[0]), rdata.size());
}
};//class OutputFileStream<T>
template <class T>
class InputFileStream: public FileStream
{
public:
explicit InputFileStream(const std::filesystem::path& path) noexcept:
FileStream(path, std::ifstream::in)
{}
InputFileStream(const std::filesystem::path& path, std::ios_base::openmode mode) noexcept :
FileStream(path, std::ifstream::in | mode)
{}
virtual ~InputFileStream() override = default;
using data_t = T;
using chunk_t = std::vector<data_t>;
/**
* Read entire file into memory
* @note It will throw std::runtime_error in case that operation on
* the input file stream (std::ifstream) is somehow failed
*/
virtual chunk_t readAll();
};//class InputFileStream<T>
template <class T>
inline typename InputFileStream<T>::chunk_t
InputFileStream<T>::readAll()
{
const auto file_size = size();
chunk_t buffer(file_size);
m_file.seekg(0);//rewind the position to the beginning of the stream
if (!m_file.read(reinterpret_cast<char*>(&buffer[0]), file_size) )
throw std::runtime_error(strerror(errno));
return buffer;
}
}//namespace:utils::file
#endif /*FILE_STREAMS_H_*/