pianod2
multisource multiuser scriptable networked music player
interpreter.h
Go to the documentation of this file.
1 
9 #pragma once
10 
11 #include <vector>
12 #include <set>
13 #include <string>
14 #include <unordered_map>
15 #include <map>
16 #include <memory>
17 
19 
20 #include "fundamentals.h"
21 #include "response.h"
22 
23 #define KEY_AUDIOOPTIONS "audioOptions"
24 #define KEY_WAITOPTIONS "waitOptions"
25 #define KEY_TUNEROPTIONS "tunerOptions"
26 #define KEY_LIBRARYOPTIONS "libraryOptions"
27 #define KEY_PANDORAOPTIONS "pandoraOptions"
28 #define KEY_PLAYBACKSELECTION "playbackOptions"
29 
30 #define KEY_OPTIONS "options"
31 #define KEY_COMMAND "command"
32 #define KEY_REQUEST "request"
33 
34 #define KEY_ASUSER "asUser"
35 #define KEY_WITHSOURCE "withSource"
36 #define KEY_INROOM "inRoom"
37 #define REQUEST_ASUSER "asUserExecute"
38 #define REQUEST_WITHSOURCE "withSourceExecute"
39 #define REQUEST_INROOM "inRoomExecute"
40 
41 #define PARSER_SOURCEIDENTITY "sourceId"
42 #define KEY_SOURCE "source"
43 #define SOURCEIDENTITY " {" KEY_SOURCE ":" PARSER_SOURCEIDENTITY "}"
44 
45 class PianodConnection;
46 
48 class PianodParser : public Parsnip::Parser {
49  friend class PianodDispatcher;
50  std::unordered_map <std::string, const Parsnip::OptionParser::Definitions> option_definitions;
51 public:
52  void addOptionParser (const std::string &name, Parsnip::OptionParser::Definitions defs);
53 };
54 
55 
56 
58 public:
59  using CommandIds = std::map <std::string, CommandId>;
60  using SchemaList = std::vector<std::string>;
61 private:
63 public:
64  using RequestPair = std::pair <CommandId, const Parsnip::Data *>;
65  using SchemaSet::SchemaSet;
66  using SchemaSet::validate;
67 
68  CommandId getCommandId (const std::string &name) const;
69  void addRequestNames (const CommandIds &mappings);
70  void validate (const std::string &command, const Parsnip::Data &request);
71  std::ostream &dump (const std::string &command, std::ostream &target = std::clog) const;
72  std::ostream &dumpAll (std::ostream &target = std::clog) const;
74 };
75 using PianodSchemaRef = std::shared_ptr <PianodSchema>;
76 
77 
78 
80 class PianodDispatcher : public Parsnip::Dispatcher <ResponseCollector, PianodConnection &> {
83  std::vector <class PianodInterpreter *> interpreters;
84 public:
85  using HelpList = std::vector<std::string>;
86  using base_type::operator();
87 
89  void addHandler (const Parsnip::Parser::Definitions &defs, class PianodInterpreter *interpreter);
90  void rewriteJsonRequest (Parsnip::Data &request) const;
91  ResponseCollector jsonRequest (const Parsnip::Data &request, PianodConnection &context) const;
92  ResponseCollector redispatch (const Parsnip::Data &options, PianodConnection &context) const;
93 
94  const HelpList getHelp (std::vector <std::string> search);
95 };
96 
97 
98 
101 class PianodInterpreter : public Parsnip::Interpreter <ResponseCollector , PianodConnection &> {
103  virtual ResponseCollector interpret (Parsnip::Parser::CommandId command_id, const Parsnip::Data &parameters, PianodConnection & context) override final;
104 protected:
105  using StringVector = std::vector <std::string>;
108 
113  virtual bool authorizedCommand (Parsnip::Parser::CommandId command_id, PianodConnection &context) = 0;
114 
121  virtual ResponseCollector handleCommand (Parsnip::Parser::CommandId command_id, const Parsnip::Data &parameters, PianodConnection &context) = 0;
122 
126 
127 public:
128  static bool optionIs (const Parsnip::Data &options, const char *name, const char *expected);
136  template <typename ValueType, typename LookupType>
137  static inline ValueType optionalValue (const Parsnip::Data &options, const char *name, const LookupType &lookup, const ValueType default_value) {
138  return (options.contains (name) ? lookup [options [name].asString()] : default_value);
139  }
141  virtual void registerInterpreter (PianodDispatcher &dispatcher);
142  const HelpList getHelp (const std::vector <std::string> &search, std::set <std::string> *option_parsers);
143 };
144 
145 
146 
Generic data type.
Definition: parsnip.h:81
bool contains(const std::string &word) const
Check if a key exists in a dictionary.
Definition: parsnip_types.cpp:328
const StringType & asString() const
Retrieve string value.
Definition: parsnip_types.cpp:133
Definition: parsnip_command.h:148
const ParserRef parser
Definition: parsnip_command.h:150
Definition: parsnip_command.h:141
std::vector< const char * > Definitions
Definition: parsnip_command.h:90
A class for parsing command lines.
Definition: parsnip_command.h:100
std::vector< Definition > Definitions
Definition: parsnip_command.h:117
int CommandId
Definition: parsnip_command.h:109
A schema built to validate JSON messages based on command line patterns.
Definition: parsnip_command.h:171
int CommandId
Definition: parsnip_command.h:173
Connection to a pianod client, along with context and state of that connection.
Definition: connection.h:54
Dispatcher based on Parsnip template, customized for pianod by adding help support.
Definition: interpreter.h:80
std::vector< class PianodInterpreter * > interpreters
List of all associated interpreters.
Definition: interpreter.h:83
void rewriteJsonRequest(Parsnip::Data &request) const
Rewrite the JSON request, wrapping the actual command in any as-user, in-room, and with-source specif...
Definition: interpreter.cpp:209
std::vector< std::string > HelpList
Definition: interpreter.h:85
ResponseCollector jsonRequest(const Parsnip::Data &request, PianodConnection &context) const
Dispatch a JSON request for execution.
Definition: interpreter.cpp:228
PianodSchemaRef schema
Definition: interpreter.h:82
const HelpList getHelp(std::vector< std::string > search)
Request help for all interpreters which a dispatcher handles.
Definition: interpreter.cpp:251
ResponseCollector redispatch(const Parsnip::Data &options, PianodConnection &context) const
Dispatch a command or request embedded within another command.
Definition: interpreter.cpp:240
void addHandler(const Parsnip::Parser::Definitions &defs, class PianodInterpreter *interpreter)
Add a handler to/for which commands will be dispatched.
Definition: interpreter.cpp:186
PianodDispatcher(const Parsnip::ParserRef &parser, const PianodSchemaRef &schema)
Construct a dispatcher for Pianod.
Definition: interpreter.cpp:179
Interpreter class based on Parsnip template, customized base for pianod interpreters with the additio...
Definition: interpreter.h:101
const HelpList getHelp(const std::vector< std::string > &search, std::set< std::string > *option_parsers)
Search the interpreter's definitions for any definitions matching search criteria.
Definition: interpreter.cpp:338
static const StringVector EmptyStringVector
An empty string vector, often used as a default with Parsnip::Data::getOr.
Definition: interpreter.h:107
static ValueType optionalValue(const Parsnip::Data &options, const char *name, const LookupType &lookup, const ValueType default_value)
Retrieve the ID of a string value.
Definition: interpreter.h:137
virtual void registerInterpreter(PianodDispatcher &dispatcher)
Register the interpreter with a dispatcher.
Definition: interpreter.cpp:330
virtual bool authorizedCommand(Parsnip::Parser::CommandId command_id, PianodConnection &context)=0
Check whether a command is authorized.
static bool optionIs(const Parsnip::Data &options, const char *name, const char *expected)
Check if a string value exists and is case-blind equal to a particular value.
Definition: interpreter.cpp:309
friend PianodDispatcher
Definition: interpreter.h:102
PianodDispatcher::HelpList HelpList
Definition: interpreter.h:140
std::vector< std::string > StringVector
Definition: interpreter.h:105
virtual const Parsnip::Parser::Definitions & getParserDefinitions()=0
Retrieve the parser definitions handled by the interpreter.
virtual ResponseCollector handleCommand(Parsnip::Parser::CommandId command_id, const Parsnip::Data &parameters, PianodConnection &context)=0
Command handler.
virtual ResponseCollector interpret(Parsnip::Parser::CommandId command_id, const Parsnip::Data &parameters, PianodConnection &context) override final
Authorize and execute a command.
Definition: interpreter.cpp:319
static const Parsnip::Data EmptyDictionary
An empty dictionary, often used as a default with Parsnip::Data::getOr.
Definition: interpreter.h:106
Command line parser based on Parsnip, but with some help support added for pianod.
Definition: interpreter.h:48
std::unordered_map< std::string, const Parsnip::OptionParser::Definitions > option_definitions
Definition: interpreter.h:50
void addOptionParser(const std::string &name, Parsnip::OptionParser::Definitions defs)
Construct and register an option parser.
Definition: interpreter.cpp:87
Definition: interpreter.h:57
std::pair< CommandId, const Parsnip::Data * > RequestPair
Definition: interpreter.h:64
std::vector< std::string > SchemaList
Definition: interpreter.h:60
std::ostream & dump(const std::string &command, std::ostream &target=std::clog) const
Definition: interpreter.cpp:124
std::map< std::string, CommandId > CommandIds
Definition: interpreter.h:59
CommandId getCommandId(const std::string &name) const
Retrieve a request's ID by name.
Definition: interpreter.cpp:100
CommandIds command_ids
Definition: interpreter.h:62
void addRequestNames(const CommandIds &mappings)
Register additional name/ID mappings for requests.
Definition: interpreter.cpp:110
void validate(const std::string &command, const Parsnip::Data &request)
Verify a request complies with its schema.
Definition: interpreter.cpp:119
SchemaList allRequestNames() const
Definition: interpreter.cpp:136
std::ostream & dumpAll(std::ostream &target=std::clog) const
Definition: interpreter.cpp:129
A response collector/aggregator.
Definition: response.h:197
Essential data structures and support.
std::shared_ptr< PianodSchema > PianodSchemaRef
Definition: interpreter.h:75
void validate(const AudioSettings settings)
Validate audio settings.
Definition: audiooptionsparser.cpp:33
std::shared_ptr< Parser > ParserRef
Definition: parsnip_command.h:138
Parsnip command-line parsing.
Send messages of various kinds to clients.