-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.cpp
152 lines (143 loc) · 4.25 KB
/
main.cpp
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
#include <iostream>
#include <unordered_map> // for class TrieNode
#include <string> // for class TILDB.reader ifstream
#include <fstream>
class TrieNode {
public: // TODO make private with getter & setter
std::unordered_map<char, TrieNode*> children;
long disk_offset;
TrieNode() {
this->disk_offset = -1; // no file is pointed by this
}
};
class Trie {
private:
TrieNode *root;
public:
Trie() {
root = new TrieNode();
}
void insert(std::string key, long offset) {
TrieNode *current = root;
for (char c : key) {
if (current->children.count(c) == 0) {
// std::cout << "\t adding " << c << " to trie\n";
current->children[c] = new TrieNode(); // TODO make a pool / pre build the trie ?
}
current = current->children[c];
}
// std::cout << "\t adding offset " << offset << " to trienode at " << current << "\n" ;
current->disk_offset = offset;
}
long search(std::string key) { // returning -1 for missing key -> should we use exceptions?
TrieNode *current = root;
for (const char& c : key) {
if (current->children.count(c) == 0) {
// std::cout << "\t cannot find " << c << "\n";
return -1;
}
current = current->children[c];
}
// std::cout << "\t found offset " << current->disk_offset << " at trienode " << current << "\n" ;
return current->disk_offset;
}
};
class TILDB {
private:
Trie trie;
// TODO create read and write threads
// -> write thread must be single -> read can be multiple
std::ofstream writer;
std::ifstream reader;
public:
TILDB(std::string filename) {
writer.open("database/"+filename, std::ios_base::app);
reader.open("database/"+filename);
}
std::string getKey(std::string key) { // TODO should I take a reference of value instead ?
long file_offset = trie.search(key);
std::string value = "";
if (file_offset != -1) {
// std::cout << "\t offset:" << file_offset << "\n";
reader.seekg(file_offset, std::ios::beg);
std::getline(reader, value);
return value;
} else {
return ""; // TODO should I use an exception / warning instead
}
}
void setKey(std::string key, std::string value){
writer << key;
long file_offset = writer.tellp();
// std::cout << "\t offset:" << file_offset << "\n";
writer << value << std::endl;
trie.insert(key, file_offset);
}
~TILDB() {
writer.close();
reader.close();
}
};
class TILDBPool {
private:
static std::unordered_map<std::string, TILDB*> pool; // TODO make this static?
public:
TILDBPool() {} // CANNOT create instance
static TILDB* getTILDB(std::string filename) {
if (pool.count(filename) == 0) {
pool[filename] = new TILDB(filename);
}
return pool[filename];
}
};
class MenuCLI {
public:
static void show_menu(){
std::string filename = "default", key, value;
int selection;
TILDB *tildb = new TILDB(filename); // TODO make a pool for all different files
while (true) {
std::cout << "1. Change current filename/DB \n2. Write to DB:" << filename << " \n3. Read From DB" << filename << "\n Enter choice: ";
std::cin >> selection;
switch (selection) {
case 1:
std::cout << " Enter filename: ";
std::cin >> filename;
tildb = new TILDB(filename);
break;
case 2:
std::cout << " Enter Key: ";
std::cin >> key;
std::cout << " Enter Value: ";
std::cin >> value;
tildb->setKey(key, value);
// std::cout << " Stored in DB\n";
break;
case 3:
std::cout << " Enter Key: ";
std::cin >> key;
value = tildb->getKey(key);
std::cout << " Value: " << value << "\n";
break;
default:
std::cout << "Invalid choice!\n";
break;
}
}
}
};
extern "C" {
bool api_set_db(std::string filename, std::string key, std::string value) {
TILDB *tildb = TILDBPool::getTILDB(filename);
tildb->setKey(key, value);
}
std::string api_get_db(std::string filename, std::string key) {
TILDB *tildb = TILDBPool::getTILDB(filename);
tildb->getKey(key);
}
}
int main() {
std::cout << "Welcome to TrieIndexLogDB!\n\n";
MenuCLI::show_menu();
return 0;
}