-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathmapped_file.h
174 lines (147 loc) · 4.09 KB
/
mapped_file.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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
//
// Copyright RIME Developers
// Distributed under the BSD License
//
// 2011-06-27 GONG Chen <chen.sst@gmail.com>
//
#ifndef RIME_MAPPED_FILE_H_
#define RIME_MAPPED_FILE_H_
#include <stdint.h>
#include <cstring>
#include <boost/utility.hpp>
#include "common.h"
namespace rime {
// basic data structure
// Limitation: cannot point to itself (zero is used to represent NULL pointer)
template <class T = char, class Offset = int32_t>
class OffsetPtr {
public:
OffsetPtr() = default;
OffsetPtr(Offset offset) : offset_(offset) {}
OffsetPtr(const T* ptr) : OffsetPtr(to_offset(ptr)) {}
OffsetPtr(const OffsetPtr<T>& ptr) : OffsetPtr(ptr.get()) {}
OffsetPtr<T>& operator= (const OffsetPtr<T>& ptr) {
offset_ = to_offset(ptr.get());
return *this;
}
OffsetPtr<T>& operator= (const T* ptr) {
offset_ = to_offset(ptr);
return *this;
}
operator bool() const {
return !!offset_;
}
T* operator-> () const {
return get();
}
T& operator* () const {
return *get();
}
T& operator[] (size_t index) const {
return *(get() + index);
}
T* get() const {
if (!offset_) return NULL;
return reinterpret_cast<T*>((char*)&offset_ + offset_);
}
private:
Offset to_offset(const T* ptr) const {
return ptr ? (char*)ptr - (char*)(&offset_) : 0;
}
Offset offset_ = 0;
};
struct String {
OffsetPtr<char> data;
const char* c_str() const { return data.get(); }
size_t length() const { return c_str() ? strlen(c_str()) : 0; }
bool empty() const { return !data || !data[0]; }
};
template <class T, class Size = uint32_t>
struct Array {
Size size;
T at[1];
T* begin() { return &at[0]; }
T* end() { return &at[0] + size; }
const T* begin() const { return &at[0]; }
const T* end() const { return &at[0] + size; }
};
template <class T, class Size = uint32_t>
struct List {
Size size;
OffsetPtr<T> at;
T* begin() { return &at[0]; }
T* end() { return &at[0] + size; }
const T* begin() const { return &at[0]; }
const T* end() const { return &at[0] + size; }
};
// MappedFile class definition
class MappedFileImpl;
class MappedFile : boost::noncopyable {
protected:
explicit MappedFile(const string& file_name);
virtual ~MappedFile();
bool Create(size_t capacity);
bool OpenReadOnly();
bool OpenReadWrite();
bool Flush();
bool Resize(size_t capacity);
bool ShrinkToFit();
template <class T>
T* Allocate(size_t count = 1);
template <class T>
Array<T>* CreateArray(size_t array_size);
String* CreateString(const string& str);
bool CopyString(const string& src, String* dest);
size_t capacity() const;
char* address() const;
public:
bool Exists() const;
bool IsOpen() const;
void Close();
bool Remove();
template <class T>
T* Find(size_t offset);
const string& file_name() const { return file_name_; }
size_t file_size() const { return size_; }
private:
string file_name_;
size_t size_ = 0;
the<MappedFileImpl> file_;
};
// member function definitions
# define RIME_ALIGNED(size, T) ((size + alignof(T) - 1) & ~(alignof(T) - 1))
template <class T>
T* MappedFile::Allocate(size_t count) {
if (!IsOpen())
return NULL;
size_t used_space = RIME_ALIGNED(size_, T);
size_t required_space = sizeof(T) * count;
size_t file_size = capacity();
if (used_space + required_space > file_size) {
// not enough space; grow the file
size_t new_size = (std::max)(used_space + required_space, file_size * 2);
if(!Resize(new_size) || !OpenReadWrite())
return NULL;
}
T* ptr = reinterpret_cast<T*>(address() + used_space);
std::memset(ptr, 0, required_space);
size_ = used_space + required_space;
return ptr;
}
template <class T>
T* MappedFile::Find(size_t offset) {
if (!IsOpen() || offset > size_)
return NULL;
return reinterpret_cast<T*>(address() + offset);
}
template <class T>
Array<T>* MappedFile::CreateArray(size_t array_size) {
size_t num_bytes = sizeof(Array<T>) + sizeof(T) * (array_size - 1);
Array<T>* ret = reinterpret_cast<Array<T>*>(Allocate<char>(num_bytes));
if (!ret)
return NULL;
ret->size = array_size;
return ret;
}
} // namespace rime
#endif // RIME_MAPPED_FILE_H_