Repository navigation
Expand file tree
/
Copy pathstorage.cpp
More file actions
117 lines (100 loc) · 3.07 KB
/
Copy pathstorage.cpp
File metadata and controls
117 lines (100 loc) · 3.07 KB
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
#include "storage.h"
#include <fstream>
#include <algorithm>
#include <cctype>
Storage::Storage(const std::string& filename) : filename_(filename) {}
bool Storage::load() {
std::ifstream in(filename_, std::ios::binary);
if (!in.is_open()) {
// No file yet — start fresh
header_ = FileHeader();
contacts_.clear();
return true;
}
in.read(reinterpret_cast<char*>(&header_), sizeof(FileHeader));
if (!header_.is_valid()) {
in.close();
header_ = FileHeader();
contacts_.clear();
return false;
}
contacts_.resize(header_.count);
for (uint32_t i = 0; i < header_.count; i++) {
in.read(reinterpret_cast<char*>(&contacts_[i]), sizeof(Contact));
}
in.close();
return true;
}
bool Storage::write_all() {
std::ofstream out(filename_, std::ios::binary | std::ios::trunc);
if (!out.is_open()) return false;
header_.count = static_cast<uint32_t>(contacts_.size());
out.write(reinterpret_cast<const char*>(&header_), sizeof(FileHeader));
for (const auto& c : contacts_) {
out.write(reinterpret_cast<const char*>(&c), sizeof(Contact));
}
out.close();
return true;
}
bool Storage::save_contact(Contact& c) {
c.id = header_.next_id++;
c.created_at = time(nullptr);
c.modified_at = c.created_at;
c.deleted = 0;
contacts_.push_back(c);
return write_all();
}
bool Storage::update_contact(const Contact& c) {
for (auto& existing : contacts_) {
if (existing.id == c.id && !existing.deleted) {
existing = c;
existing.modified_at = time(nullptr);
return write_all();
}
}
return false;
}
bool Storage::delete_contact(uint32_t id) {
for (auto& c : contacts_) {
if (c.id == id && !c.deleted) {
c.deleted = 1;
c.modified_at = time(nullptr);
return write_all();
}
}
return false;
}
std::vector<Contact> Storage::get_all_active() {
std::vector<Contact> result;
for (const auto& c : contacts_) {
if (!c.deleted) result.push_back(c);
}
return result;
}
Contact* Storage::find_by_id(uint32_t id) {
for (auto& c : contacts_) {
if (c.id == id && !c.deleted) return &c;
}
return nullptr;
}
static std::string to_lower(const std::string& s) {
std::string result = s;
std::transform(result.begin(), result.end(), result.begin(),
[](unsigned char ch) { return std::tolower(ch); });
return result;
}
std::vector<Contact> Storage::search(const std::string& query) {
std::vector<Contact> result;
std::string q = to_lower(query);
for (const auto& c : contacts_) {
if (c.deleted) continue;
if (to_lower(c.name).find(q) != std::string::npos ||
to_lower(c.phone).find(q) != std::string::npos ||
to_lower(c.email).find(q) != std::string::npos ||
to_lower(c.company).find(q) != std::string::npos ||
to_lower(c.notes).find(q) != std::string::npos) {
result.push_back(c);
}
}
return result;
}