forked from tetl/Frozlunky
-
Notifications
You must be signed in to change notification settings - Fork 0
/
patch_group.cpp
102 lines (88 loc) · 2.32 KB
/
patch_group.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
#include "patch_group.h"
bool PatchGroup::_perform() {
for(std::pair<std::string, std::shared_ptr<Patch>> patch : patches) {
patch.second->perform();
if(patch.second->valid() && !patch.second->is_active()) {
#ifdef DEBUG_MODE
std::cout << "Warning: patch \"" << patch.first << "\" failed to be activated." << std::endl;
#endif
return false;
}
}
return true;
}
bool PatchGroup::_undo() {
for(std::pair<std::string, std::shared_ptr<Patch>> patch : patches) {
patch.second->undo();
if(patch.second->valid() && patch.second->is_active()) {
#ifdef DEBUG_MODE
std::cout << "Warning: patch \"" << patch.first << "\" failed to be reversed." << std::endl;
#endif
return false;
}
}
return true;
}
bool PatchGroup::valid() {
for(std::pair<std::string, std::shared_ptr<Patch>> patch : patches) {
if(patch.second->valid())
return true;
}
return true;
}
void PatchGroup::lock() {
Patch::lock();
for(auto iter = patches.begin(), end = patches.end(); iter != end; iter++) {
iter->second->lock();
}
}
void PatchGroup::unlock() {
Patch::unlock();
for(auto iter = patches.begin(), end = patches.end(); iter != end; iter++) {
iter->second->unlock();
}
}
PatchGroup* PatchGroup::add(const std::string& name, std::shared_ptr<Patch> patch) {
if(patches.find(name) == patches.end()) {
patches[name] = patch;
}
return this;
}
std::shared_ptr<Patch> PatchGroup::get(const std::string& name) {
auto iter = patches.find(name);
if(iter == patches.end())
return nullptr;
else
return iter->second;
}
void PatchGroup::push_state() {
std::map<std::string, bool> state;
for(std::pair<std::string, std::shared_ptr<Patch>> patch : patches) {
state[patch.first] = patch.second->is_active();
}
patch_states.push_back(state);
}
void PatchGroup::pop_state() {
if(patch_states.size() > 0) {
std::map<std::string, bool>& state = patch_states.back();
for(auto iter = state.begin(); iter != state.end(); iter++) {
auto physical = patches.find(iter->first);
if(physical != patches.end()) {
if(iter->second) {
if(!physical->second->is_active()) {
physical->second->perform();
}
}
else if(physical->second->is_active()) {
physical->second->undo();
}
}
}
patch_states.pop_back();
}
}
void PatchGroup::pop_noload_state() {
if(patch_states.size() > 0) {
patch_states.pop_back();
}
}