-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFSVector.h
123 lines (105 loc) · 2.99 KB
/
FSVector.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
#pragma once
#include <fstream>
#include <memory>
#include <cstddef>
#include <string>
#include <experimental/filesystem>
template<typename T>
class FSVector final
{
public:
using size_type = uint64_t;
using value_type = T;
class Reference
{
friend FSVector;
Reference(const std::string& path, size_type n)
: file_(path)
, n_(n)
{
}
public:
Reference& operator=(const Reference& value)
{
return operator=((T)value);
}
Reference& operator=(const T& value)
{
file_.seekp(sizeof(size_type) + n_ * sizeof(T));
file_.write(reinterpret_cast<const char*>(&value), sizeof(T));
return *this;
}
operator T() const
{
std::unique_ptr<std::byte[]> data = std::make_unique<std::byte[]>(sizeof(T));
file_.seekg(sizeof(size_type) + n_ * sizeof(T));
file_.read(reinterpret_cast<char*>(data.get()), sizeof(T));
return *reinterpret_cast<T*>(data.get());
}
private:
mutable std::fstream file_;
size_type n_;
};
explicit FSVector(const std::string& path)
: path_(path)
{
if (!std::experimental::filesystem::exists(path)) {
size_type size = 0;
std::ofstream ofs(path, std::ifstream::out | std::ifstream::app | std::ifstream::binary);
ofs.write(reinterpret_cast<char *>(&size), sizeof(size));
}
file_.open(path, std::ifstream::out | std::ifstream::in | std::ifstream::binary);
}
T operator[](size_type n) const
{
std::unique_ptr<std::byte[]> data = std::make_unique<std::byte[]>(sizeof(T));
file_.seekg(sizeof(size_type) + n * sizeof(T));
file_.read(reinterpret_cast<char*>(data.get()), sizeof(T));
return *reinterpret_cast<T*>(data.get());
}
Reference operator[](size_type n)
{
file_.flush();
return Reference(path_, n);
}
void push_back(const T& value)
{
size_type size = this->size();
file_.seekp(sizeof(size_type) + size * sizeof(T));
file_.write(reinterpret_cast<const char*>(&value), sizeof(T));
++size;
file_.seekp(0);
file_.write(reinterpret_cast<char*>(&size), sizeof(size));
}
size_type size() const
{
size_type size = 0;
file_.seekg(0);
file_.read(reinterpret_cast<char*>(&size), sizeof(size));
return size;
}
void resize(size_type n)
{
file_.seekp(0);
file_.write(reinterpret_cast<char*>(&n), sizeof(n));
}
void clear()
{
resize(0);
}
bool empty() const
{
return size() == 0;
}
void erase(size_type n)
{
const size_type size = this->size();
for (size_type i = n; i + 1 < size; i++) {
operator[](i) = operator[](i + 1);
}
resize(size - 1);
}
private:
mutable std::fstream file_;
std::string path_;
};