Allow binding commands to class instance
[lsnes.git] / include / library / command.hpp
blobb6612a193ff43862b528c79c992d2f71be78cb39
1 #ifndef _library_command__hpp__included__
2 #define _library_command__hpp__included__
4 #include <stdexcept>
5 #include <string>
6 #include <functional>
7 #include <set>
8 #include <map>
9 #include <list>
11 namespace command
13 class set;
14 class base;
15 class factory_base;
17 /**
18 * A set of commands.
20 class set
22 public:
23 /**
24 * Set add/drop listener.
26 class listener
28 public:
29 /**
30 * Dtor.
32 virtual ~listener();
33 /**
34 * New item in set.
36 virtual void create(set& s, const std::string& name, factory_base& cmd) = 0;
37 /**
38 * Deleted item from set.
40 virtual void destroy(set& s, const std::string& name) = 0;
41 /**
42 * Destroyed the entiere set.
44 virtual void kill(set& s) = 0;
46 /**
47 * Create a new set.
49 set() throw(std::bad_alloc);
50 /**
51 * Destroy a set.
53 ~set() throw();
54 /**
55 * Add a command to set.
57 void do_register(const std::string& name, factory_base& cmd) throw(std::bad_alloc);
58 /**
59 * Remove a command from set.
61 void do_unregister(const std::string& name, factory_base& cmd) throw(std::bad_alloc);
62 /**
63 * Add a notification callback and call ccb on all.
65 * Parameter listener: The listener to add.
67 void add_callback(listener& listener) throw(std::bad_alloc);
68 /**
69 * Drop a notification callback and call dcb on all.
71 * Parameter listener: The listener to drop.
73 void drop_callback(listener& listener) throw();
74 private:
75 char dummy;
78 /**
79 * A group of commands (with aliases).
81 class group
83 public:
84 /**
85 * Create a new command group. This also places some builtin commands in that new group.
87 group() throw(std::bad_alloc);
88 /**
89 * Destroy a group.
91 ~group() throw();
92 /**
93 * Look up and invoke a command. The command will undergo alias expansion and recursion checking.
95 * parameter cmd: Command to exeucte.
97 void invoke(const std::string& cmd) throw();
98 /**
99 * Get set of aliases.
101 std::set<std::string> get_aliases() throw(std::bad_alloc);
103 * Get alias
105 std::string get_alias_for(const std::string& aname) throw(std::bad_alloc);
107 * Set alias
109 void set_alias_for(const std::string& aname, const std::string& avalue) throw(std::bad_alloc);
111 * Is alias name valid.
113 bool valid_alias_name(const std::string& aname) throw(std::bad_alloc);
115 * Register a command.
117 void do_register(const std::string& name, base& cmd) throw(std::bad_alloc);
119 * Unregister a command.
121 void do_unregister(const std::string& name, base& cmd) throw(std::bad_alloc);
123 * Add all commands (including future ones) in given set.
125 void add_set(set& s) throw(std::bad_alloc);
127 * Drop a set of commands.
129 void drop_set(set& s) throw();
131 * Set the output stream.
133 void set_output(std::ostream& s);
135 * Set the OOM panic routine.
137 void set_oom_panic(void (*fn)());
138 private:
139 class listener : public set::listener
141 public:
142 listener(group& _grp);
143 ~listener();
144 void create(set& s, const std::string& name, factory_base& cmd);
145 void destroy(set& s, const std::string& name);
146 void kill(set& s);
147 private:
148 group& grp;
149 } _listener;
150 std::set<std::string> command_stack;
151 std::map<std::string, std::list<std::string>> aliases;
152 std::ostream* output;
153 void (*oom_panic_routine)();
154 base* builtin[1];
158 * A command.
160 class base
162 public:
164 * Register a new command.
166 * parameter group: The group command will be part of.
167 * parameter cmd: The command to register.
168 * parameter dynamic: Should the object be freed when its parent group dies?
169 * throws std::bad_alloc: Not enough memory.
171 base(group& group, const std::string& cmd, bool dynamic) throw(std::bad_alloc);
174 * Deregister a command.
176 virtual ~base() throw();
179 * Invoke a command.
181 * parameter arguments: Arguments to command.
182 * throws std::bad_alloc: Not enough memory.
183 * throws std::runtime_error: Command execution failed.
185 virtual void invoke(const std::string& arguments) throw(std::bad_alloc, std::runtime_error) = 0;
187 * Get short help for command.
189 virtual std::string get_short_help() throw(std::bad_alloc);
192 * Get long help for command.
194 virtual std::string get_long_help() throw(std::bad_alloc);
196 * Get name of command.
198 const std::string& get_name() { return commandname; }
200 * Notify that the parent group died.
202 * Note: Assumed to be called with global lock held.
204 void group_died() throw();
205 private:
206 base(const base&);
207 base& operator=(const base&);
208 std::string commandname;
209 group* in_group;
210 bool is_dynamic;
214 * A command factory.
216 class factory_base
218 public:
219 factory_base() throw() {}
221 * Register a new command.
223 * parameter _set: The set command will be part of.
224 * parameter cmd: The command to register.
225 * throws std::bad_alloc: Not enough memory.
227 void _factory_base(set& _set, const std::string& cmd) throw(std::bad_alloc);
229 * Destructor.
231 virtual ~factory_base() throw();
233 * Make a new command.
235 virtual base* make(group& grp) = 0;
237 * Notify that the parent set died.
239 * Note: Assumed to be called with global lock held.
241 void set_died() throw();
242 private:
243 factory_base(const factory_base&);
244 factory_base& operator=(const factory_base&);
245 std::string commandname;
246 set* in_set;
250 * Name, Description and help for command.
252 struct stub
255 * The command name.
257 const char* name;
259 * The short description.
261 const char* desc;
263 * The long help.
265 const char* help;
269 * Mandatory filename
271 struct arg_filename
274 * The filename itself.
276 std::string v;
278 * Return the filename.
280 * returns: The filename.
282 operator std::string() { return v; }
286 * Run command function helper.
288 * parameter fn: Function pointer to invoke.
289 * parameter a: The arguments to pass.
291 template<typename... args>
292 void invoke_fn(std::function<void(args... arguments)> fn, const std::string& a);
295 * Warp function pointer as command.
297 template<typename... args>
298 class _fnptr : public base
300 public:
302 * Create a new command.
304 * parameter group: The group command will be part of.
305 * parameter name: Name of the command
306 * parameter description Description for the command
307 * parameter help: Help for the command.
308 * parameter fn: Function to call on command.
309 * parameter dynamic: Should the object be freed when its parent group dies?
311 _fnptr(group& group, const std::string& name, const std::string& _description,
312 const std::string& _help, void (*_fn)(args... arguments), bool dynamic = false) throw(std::bad_alloc)
313 : base(group, name, dynamic)
315 shorthelp = _description;
316 help = _help;
317 fn = _fn;
320 * Create a new command.
322 * parameter _set: The set command will be part of.
323 * parameter name: Name of the command
324 * parameter fn: Function to call on command.
325 * parameter description Description&Help for the command
327 _fnptr(group& _group, stub _name, std::function<void(args... arguments)> _fn) throw(std::bad_alloc)
328 : base(_group, _name.name, false)
330 shorthelp = _name.desc;
331 help = _name.help;
332 fn = _fn;
335 * Destroy a commnad.
337 ~_fnptr() throw()
341 * Invoke a command.
343 * parameter a: Arguments to function.
345 void invoke(const std::string& a) throw(std::bad_alloc, std::runtime_error)
347 invoke_fn(fn, a);
350 * Get short description.
352 * returns: Description.
353 * throw std::bad_alloc: Not enough memory.
355 std::string get_short_help() throw(std::bad_alloc)
357 return shorthelp;
360 * Get long help.
362 * returns: help.
363 * throw std::bad_alloc: Not enough memory.
365 std::string get_long_help() throw(std::bad_alloc)
367 return help;
369 private:
370 std::function<void(args... arguments)> fn;
371 std::string shorthelp;
372 std::string help;
376 * Function pointer command factory.
378 template<typename... args>
379 class fnptr : public factory_base
381 public:
383 * Create a new command.
385 * parameter _set: The set command will be part of.
386 * parameter desc: Command descriptor.
387 * parameter fn: Function to call on command.
389 fnptr(set& _set, stub _name, void (*_fn)(args... arguments)) throw(std::bad_alloc)
391 shorthelp = _name.desc;
392 name = _name.name;
393 help = _name.help;
394 fn = _fn;
395 _factory_base(_set, name);
398 * Create a new command.
400 * parameter _set: The set command will be part of.
401 * parameter name: Name of the command
402 * parameter description Description for the command
403 * parameter help: Help for the command.
404 * parameter fn: Function to call on command.
406 fnptr(set& _set, const std::string& _name, const std::string& _description,
407 const std::string& _help, void (*_fn)(args... arguments)) throw(std::bad_alloc)
409 shorthelp = _description;
410 name = _name;
411 help = _help;
412 fn = _fn;
413 _factory_base(_set, name);
416 * Destroy a commnad.
418 ~fnptr() throw()
422 * Make a command.
424 base* make(group& grp) throw(std::bad_alloc)
426 return new _fnptr<args...>(grp, name, shorthelp, help, fn, true);
428 private:
429 void (*fn)(args... arguments);
430 std::string shorthelp;
431 std::string help;
432 std::string name;
436 * Generic byname factory.
438 template<typename T>
439 class byname_factory : public factory_base
441 public:
443 * Create a new factory.
445 byname_factory(set& s, const std::string& _name)
447 name = _name;
448 _factory_base(s, name);
451 * Destroy.
453 ~byname_factory() throw()
457 * Make a command.
459 base* make(group& grp) throw(std::bad_alloc)
461 return new T(grp, name);
463 private:
464 std::string name;
467 #endif