Some non-instance variables cleanup
[lsnes.git] / src / core / actions.cpp
blobe37de2b4cf36ba1f80d1a08612eebd0c27d3fcc8
1 #include "core/command.hpp"
2 #include "core/messages.hpp"
3 #include "core/moviedata.hpp"
5 namespace
7 command::fnptr<const std::string&> CMD_action(lsnes_cmds, "action", "Execute core action",
8 "Syntax: action <name> [<params>...]\nExecutes core action.\n",
9 [](const std::string& _args) throw(std::bad_alloc, std::runtime_error) {
10 if(_args == "") {
11 messages << "Action name required." << std::endl;
12 return;
14 token_iterator<char> itr(_args, {" ", "\t"});
15 token_iterator<char> itre;
16 std::string sym = *itr++;
17 const interface_action* act = NULL;
18 for(auto i : our_rom.rtype->get_actions())
19 if(i->get_symbol() == sym) {
20 act = i;
21 break;
23 if(!act) {
24 messages << "No such action." << std::endl;
25 return;
27 if(!(our_rom.rtype->action_flags(act->id) & 1)) {
28 messages << "Action not enabled." << std::endl;
29 return;
31 std::vector<interface_action_paramval> params;
32 for(auto i : act->params) {
33 if(regex_match("toggle", i.model)) {
34 interface_action_paramval pv;
35 params.push_back(pv);
36 continue;
38 if(itr == itre) {
39 messages << "Action needs more parameters." << std::endl;
40 return;
42 std::string p = *itr++;
43 regex_results r;
44 interface_action_paramval pv;
45 if(r = regex("string(:(.*))?", i.model)) {
46 try {
47 if(r[2] != "" && !regex_match(r[2], p)) {
48 messages << "String does not satisfy constraints."
49 << std::endl;
50 return;
52 } catch(...) {
53 messages << "Internal error: Bad constraint in '" << i.model << "'."
54 << std::endl;
55 return;
57 pv.s = p;
58 } else if(r = regex("int:([0-9]+),([0-9]+)", i.model)) {
59 int64_t low, high, v;
60 try {
61 low = parse_value<int64_t>(r[1]);
62 high = parse_value<int64_t>(r[2]);
63 } catch(...) {
64 messages << "Internal error: Unknown limits in '" << i.model << "'."
65 << std::endl;
66 return;
68 try {
69 v = parse_value<int64_t>(p);
70 } catch(...) {
71 messages << "Can't parse parameter as integer." << std::endl;
72 return;
74 if(v < low || v > high) {
75 messages << "Parameter out of limits." << std::endl;
76 return;
78 pv.i = v;
79 } else if(r = regex("enum:(.*)", i.model)) {
80 try {
81 JSON::node e(r[1]);
82 unsigned num = 0;
83 for(auto i : e) {
84 std::string n;
85 if(i.type() == JSON::string)
86 n = i.as_string8();
87 else if(i.type() == JSON::array)
88 n = i.index(0).as_string8();
89 else
90 throw std::runtime_error("Choice not array nor "
91 "string");
92 if(n == p)
93 goto out;
94 num++;
96 messages << "Invalid choice for enumeration." << std::endl;
97 return;
98 out:
99 pv.i = num;
100 } catch(std::exception& e) {
101 messages << "JSON parse error parsing " << "model: "
102 << e.what() << std::endl;
103 return;
105 } else if(regex_match("bool", i.model)) {
106 int r = string_to_bool(p);
107 if(r < 0) {
108 messages << "Bad value for boolean parameter." << std::endl;
109 return;
111 pv.b = (r > 0);
112 } else if(regex_match("toggle", i.model)) {
113 } else {
114 messages << "Internal error: Unknown parameter model '" << i.model << "'."
115 << std::endl;
116 return;
118 params.push_back(pv);
120 if(itr != itre) {
121 messages << "Excess parameters for action." << std::endl;
122 return;
124 our_rom.rtype->execute_action(act->id, params);