Add <functional> to files that use std::function
[lsnes.git] / src / library / memorywatch.cpp
blob74801d9c7ef09fcd4ea60f9f1373635b13fac90b
1 #include "framebuffer-font2.hpp"
2 #include "memorywatch.hpp"
3 #include "memoryspace.hpp"
4 #include "int24.hpp"
5 #include "mathexpr-error.hpp"
6 #include "mathexpr.hpp"
7 #include <functional>
8 #include <sstream>
9 #include "string.hpp"
11 namespace memorywatch
13 namespace
15 template<typename T> T* pointer_cast(char* ptr)
17 return reinterpret_cast<T*>(ptr);
21 memread_oper::memread_oper()
22 : operinfo("(readmemory)")
26 memread_oper::~memread_oper() {}
28 void memread_oper::evaluate(mathexpr::value target, std::vector<std::function<mathexpr::value()>> promises)
30 if(promises.size() != 1)
31 throw mathexpr::error(mathexpr::error::ARGCOUNT, "Memory read operator takes 1 argument");
32 static const int system_endian = memory_space::get_system_endian();
33 uint64_t addr;
34 mathexpr::value val;
35 try {
36 val = promises[0]();
37 void* res = val._value;
38 addr = val.type->tounsigned(res);
39 if(addr_size)
40 addr %= addr_size;
41 addr += addr_base;
42 } catch(std::exception& e) {
43 throw mathexpr::error(mathexpr::error::ADDR, e.what());
45 if(bytes > 8)
46 throw mathexpr::error(mathexpr::error::SIZE, "Memory read size out of range");
47 char buf[8];
48 mspace->read_range(addr, buf, bytes);
49 //Endian swap if needed.
50 if(endianess && system_endian != endianess)
51 for(unsigned i = 0; i < bytes / 2; i++)
52 std::swap(buf[i], buf[bytes - i - 1]);
53 switch(bytes) {
54 case 1:
55 if(float_flag)
56 throw mathexpr::error(mathexpr::error::SIZE, "1 byte floats not supported");
57 else if(signed_flag)
58 target.type->parse_s(target._value, *(const int8_t*)buf);
59 else
60 target.type->parse_u(target._value, *(const uint8_t*)buf);
61 break;
62 case 2:
63 if(float_flag)
64 throw mathexpr::error(mathexpr::error::SIZE, "2 byte floats not supported");
65 else if(signed_flag)
66 target.type->parse_s(target._value, *pointer_cast<int16_t>(buf));
67 else
68 target.type->parse_u(target._value, *pointer_cast<uint16_t>(buf));
69 break;
70 case 3:
71 if(float_flag)
72 throw mathexpr::error(mathexpr::error::SIZE, "3 byte floats not supported");
73 else if(signed_flag)
74 target.type->parse_s(target._value, *pointer_cast<ss_int24_t>(buf));
75 else
76 target.type->parse_u(target._value, *pointer_cast<ss_uint24_t>(buf));
77 break;
78 case 4:
79 if(float_flag)
80 target.type->parse_f(target._value, *pointer_cast<float>(buf));
81 else if(signed_flag)
82 target.type->parse_s(target._value, *pointer_cast<int32_t>(buf));
83 else
84 target.type->parse_u(target._value, *pointer_cast<uint32_t>(buf));
85 break;
86 case 8:
87 if(float_flag)
88 target.type->parse_f(target._value, *pointer_cast<double>(buf));
89 else if(signed_flag)
90 target.type->parse_s(target._value, *pointer_cast<int64_t>(buf));
91 else
92 target.type->parse_u(target._value, *pointer_cast<uint64_t>(buf));
93 break;
94 default:
95 throw mathexpr::error(mathexpr::error::SIZE, "Memory address size not supported");
97 if(scale_div > 1)
98 target.type->scale(target._value, scale_div);
101 namespace
103 bool is_terminal(char ch)
105 if(ch == '%') return true;
106 if(ch == 'b') return true;
107 if(ch == 'B') return true;
108 if(ch == 'd') return true;
109 if(ch == 'i') return true;
110 if(ch == 'o') return true;
111 if(ch == 's') return true;
112 if(ch == 'u') return true;
113 if(ch == 'x') return true;
114 if(ch == 'X') return true;
115 return false;
118 std::string get_placeholder(const std::string& str, size_t idx)
120 std::ostringstream p;
121 for(size_t i = idx; i < str.length(); i++) {
122 p << str[i];
123 if(is_terminal(str[idx]))
124 break;
126 return p.str();
130 bool showsign;
131 bool fillzeros;
132 int width;
133 int precision;
134 bool uppercasehex;
137 item_printer::~item_printer()
141 void item_printer::trace()
145 std::string item::get_value()
147 if(format == "") {
148 //Default.
149 mathexpr::_format fmt;
150 fmt.type = mathexpr::_format::DEFAULT;
151 mathexpr::value v = expr->evaluate();
152 return v.type->format(v._value, fmt);
154 std::ostringstream out;
155 for(size_t i = 0; i < format.length(); i++) {
156 if(format[i] != '%')
157 out << format[i];
158 else {
159 //Format placeholder.
160 std::string p = get_placeholder(format, i + 1);
161 if(p == "")
162 continue;
163 i += p.length();
164 if(p[p.length() - 1] == '%') {
165 out << '%';
166 continue;
168 mathexpr::_format fmt;
169 fmt.showsign = false;
170 fmt.fillzeros = false;
171 fmt.width = -1;
172 fmt.precision = -1;
173 fmt.uppercasehex = false;
174 auto r = regex("([+0]*)([1-9][0-9]*)?(\\.(0|[1-9][0-9]*))?([bBdiosuxX])", p);
175 if(!r) {
176 throw mathexpr::error(mathexpr::error::FORMAT, "Bad format placeholder");
177 continue;
179 std::string flags = r[1];
180 size_t i;
181 for(i = 0; i < flags.length(); i++) {
182 if(flags[i] == '+')
183 fmt.showsign = true;
184 if(flags[i] == '0')
185 fmt.fillzeros = true;
187 //The remaining part is width.precision.
188 if(r[2] != "")
189 try {
190 fmt.width = parse_value<int>(r[2]);
191 } catch(...) {}
192 if(r[4] != "")
193 try {
194 fmt.precision = parse_value<int>(r[4]);
195 } catch(...) {}
196 switch(r[5][0]) {
197 case 'b': fmt.type = mathexpr::_format::BINARY; break;
198 case 'B': fmt.type = mathexpr::_format::BOOLEAN; break;
199 case 'd': fmt.type = mathexpr::_format::DECIMAL; break;
200 case 'i': fmt.type = mathexpr::_format::DECIMAL; break;
201 case 'o': fmt.type = mathexpr::_format::OCTAL; break;
202 case 's': fmt.type = mathexpr::_format::STRING; break;
203 case 'u': fmt.type = mathexpr::_format::DECIMAL; break;
204 case 'x': fmt.type = mathexpr::_format::HEXADECIMAL; break;
205 case 'X': fmt.type = mathexpr::_format::HEXADECIMAL; fmt.uppercasehex = true; break;
207 mathexpr::value v = expr->evaluate();
208 out << v.type->format(v._value, fmt);
211 return out.str();
214 void item::show(const std::string& n)
216 std::string x;
217 try {
218 x = get_value();
219 } catch(std::bad_alloc& e) {
220 throw;
221 } catch(mathexpr::error& e) {
222 x = e.get_short_error();
223 } catch(std::runtime_error& e) {
224 x = e.what();
226 if(printer)
227 printer->show(n, x);
231 set::~set()
233 roots.clear();
234 GC::item::do_gc();
237 void set::reset()
239 for(auto& i : roots) {
240 if(i.second.printer)
241 i.second.printer->reset();
242 i.second.expr->reset();
246 void set::refresh()
248 for(auto& i : roots)
249 i.second.expr->reset();
250 for(auto& i : roots)
251 i.second.show(i.first);
254 std::set<std::string> set::names_set()
256 std::set<std::string> r;
257 for(auto i : roots)
258 r.insert(i.first);
259 return r;
262 item& set::get(const std::string& name)
264 auto i = get_soft(name);
265 if(!i)
266 throw std::runtime_error("No such watch '" + name + "'");
267 return *i;
270 item* set::get_soft(const std::string& name)
272 if(!roots.count(name))
273 return NULL;
274 return &(roots.find(name)->second);
277 item* set::create(const std::string& name, item& item)
279 roots.insert(std::make_pair(name, item));
280 return &(roots.find(name)->second);
283 void set::destroy(const std::string& name)
285 if(!roots.count(name))
286 return;
287 roots.erase(name);
288 GC::item::do_gc();
291 const std::string& set::get_longest_name(std::function<size_t(const std::string& n)> rate)
293 static std::string empty;
294 size_t best_len = 0;
295 const std::string* best = &empty;
296 for(auto& i : roots) {
297 size_t r = rate(i.first);
298 if(r > best_len) {
299 best = &i.first;
300 best_len = r;
303 return *best;
306 size_t set::utflength_rate(const std::string& n)
308 return utf8::strlen(n);
311 void set::foreach(std::function<void(item& item)> cb)
313 for(auto& i : roots)
314 cb(i.second);
317 void set::swap(set& s) throw()
319 std::swap(roots, s.roots);