bsnes: redump sprite/palette functions
[lsnes.git] / src / library / recentfiles.cpp
blob120e7122cddbdb729dabfa32587e198db04fec8b
1 #include "recentfiles.hpp"
2 #include "zip.hpp"
3 #include "eatarg.hpp"
4 #include "json.hpp"
5 #include "string.hpp"
6 #include <fstream>
8 recentfile_path::recentfile_path()
12 recentfile_path::recentfile_path(const std::string& p)
14 path = p;
17 std::string recentfile_path::serialize() const
19 return path;
22 recentfile_path recentfile_path::deserialize(const std::string& s)
24 recentfile_path p(s);
25 return p;
28 std::string recentfile_path::get_path() const
30 return path;
33 bool recentfile_path::check() const
35 if(path == "")
36 return false;
37 try {
38 return zip::file_exists(path);
39 return true;
40 } catch(...) {
41 return false;
45 std::string recentfile_path::display() const
47 return path;
50 bool recentfile_path::operator==(const recentfile_path& p) const
52 return p.path == path;
55 recentfile_multirom::recentfile_multirom()
57 //Nothing to do.
60 std::string recentfile_multirom::serialize() const
62 bool any = false;
63 JSON::node output(JSON::object);
64 if(packfile != "") {
65 output["pack"] = JSON::string(packfile);
66 } else if(singlefile != "") {
67 output["file"] = JSON::string(singlefile);
68 if(core != "") output["core"] = JSON::string(core);
69 if(system != "") output["system"] = JSON::string(system);
70 if(region != "") output["region"] = JSON::string(region);
71 } else {
72 output["files"] = JSON::array();
73 JSON::node& f = output["files"];
74 for(auto i : files) {
75 f.append(JSON::string(i));
76 if(i != "")
77 any = true;
79 if(core != "") output["core"] = JSON::string(core);
80 if(system != "") output["system"] = JSON::string(system);
81 if(region != "") output["region"] = JSON::string(region);
83 if(packfile != "" || singlefile != "" || core != "" || system != "" || region != "") any = true;
84 if(!any) return "";
85 return output.serialize();
88 recentfile_multirom recentfile_multirom::deserialize(const std::string& s)
90 recentfile_multirom r;
91 if(s.length() > 0 && s[0] == '{') {
92 //JSON.
93 try {
94 JSON::node d(s);
95 if(d.field_exists("pack")) r.packfile = d["pack"].as_string8();
96 if(d.field_exists("file")) r.singlefile = d["file"].as_string8();
97 if(d.field_exists("core")) r.core = d["core"].as_string8();
98 if(d.field_exists("system")) r.system = d["system"].as_string8();
99 if(d.field_exists("region")) r.region= d["region"].as_string8();
100 if(d.field_exists("files")) {
101 size_t cnt = d["files"].index_count();
102 r.files.resize(cnt);
103 for(unsigned i = 0; i < cnt; i++)
104 r.files[i] = d["files"].index(i).as_string8();
106 } catch(...) {
107 r.packfile = "";
108 r.singlefile = "";
109 r.core = "";
110 r.system = "";
111 r.region = "";
112 r.files.clear();
114 } else {
115 //Legacy form.
116 r.packfile = s;
118 return r;
121 bool recentfile_multirom::check() const
123 if(packfile == "" && singlefile == "" && core == "" && system == "" && region == "" && files.empty())
124 return false;
125 if(packfile != "" && !zip::file_exists(packfile))
126 return false;
127 if(singlefile != "" && !zip::file_exists(singlefile))
128 return false;
129 for(auto i : files)
130 if(i != "" && !zip::file_exists(i))
131 return false;
132 return true;
135 std::string recentfile_multirom::display() const
137 if(packfile != "")
138 return packfile;
139 if(singlefile != "") {
140 return singlefile + " <" + core + "/" + system + ">";
141 } else {
142 if(files.size() > 1 && files[1] != "")
143 return (stringfmt() << files[1] << " (+" << files.size() << ")").str();
144 else if(files.size() > 0)
145 return (stringfmt() << files[0] << " (+" << files.size() << ")").str();
146 else
147 return "(blank) <" + core + "/" + system + ">";
151 bool recentfile_multirom::operator==(const recentfile_multirom& p) const
153 if(packfile != p.packfile)
154 return false;
155 if(singlefile != p.singlefile)
156 return false;
157 if(core != p.core)
158 return false;
159 if(system != p.system)
160 return false;
161 if(region != p.region)
162 return false;
163 if(files.size() != p.files.size())
164 return false;
165 for(unsigned i = 0; i < files.size(); i++)
166 if(files[i] != p.files[i])
167 return false;
168 return true;
171 template<class T> recent_files<T>::recent_files(const std::string& _cfgfile, size_t _maxcount)
173 cfgfile = _cfgfile;
174 maxcount = _maxcount;
177 template<class T> void recent_files<T>::add(const T& file)
179 std::list<T> ents;
180 //Load the list.
182 std::ifstream in(cfgfile);
183 std::string f;
184 while(in) {
185 std::getline(in, f);
186 T g = T::deserialize(f);
187 if(g.check())
188 ents.push_back(g);
191 //Search for matches. If found, move to front, otherwise push to first.
192 auto itr = ents.begin();
193 for(; itr != ents.end(); itr++)
194 if(*itr == file)
195 break;
196 if(itr != ents.end())
197 ents.erase(itr);
198 ents.push_front(file);
199 //Write up to maxcount entries.
201 size_t i = 0;
202 std::ofstream out(cfgfile);
203 for(itr = ents.begin(); itr != ents.end() && i < maxcount; itr++, i++)
204 out << itr->serialize() << std::endl;
206 for(auto i : hooks)
207 (*i)();
210 template<class T> void recent_files<T>::add_hook(recent_files_hook& h)
212 hooks.push_back(&h);
215 template<class T> void recent_files<T>::remove_hook(recent_files_hook& h)
217 for(auto itr = hooks.begin(); itr != hooks.end(); itr++)
218 if(*itr == &h) {
219 hooks.erase(itr);
220 break;
224 template<class T> std::list<T> recent_files<T>::get()
226 size_t c = 0;
227 std::list<T> ents;
228 //Load the list.
230 std::ifstream in(cfgfile);
231 std::string f;
232 while(in) {
233 std::getline(in, f);
234 T g = T::deserialize(f);
235 if(c < maxcount && g.check()) {
236 ents.push_back(g);
237 c++;
241 return ents;
244 recent_files_hook::~recent_files_hook()
248 void _dummy_63263632747434353545()
250 recent_files<recentfile_path> x("", 0);
251 eat_argument(&recent_files<recentfile_path>::add);
252 eat_argument(&recent_files<recentfile_path>::add_hook);
253 eat_argument(&recent_files<recentfile_path>::remove_hook);
254 eat_argument(&recent_files<recentfile_path>::get);
255 recent_files<recentfile_multirom> y("", 0);
256 eat_argument(&recent_files<recentfile_multirom>::add);
257 eat_argument(&recent_files<recentfile_multirom>::add_hook);
258 eat_argument(&recent_files<recentfile_multirom>::remove_hook);
259 eat_argument(&recent_files<recentfile_multirom>::get);