pianod2
multisource multiuser scriptable networked music player
filter.h
Go to the documentation of this file.
1 
16 #pragma once
17 
18 #include <config.h>
19 
20 #include <cstdlib>
21 
22 #include <string>
23 #include <vector>
24 #include <memory>
25 
26 #include "enumeratedarray.h"
27 #include "musictypes.h"
28 
29 namespace Query {
30  class Constraints;
31  class Details;
32  class List;
33 };
34 
38 class Filter {
39  friend class Constraints;
40  friend class Query::Details;
41  friend class Query::List;
42 public:
44  enum class Field {
45  Invalid = 0,
46  Id,
47  Artist,
48  Album,
49  Type,
50  Genre,
51  Playlist,
52  Title,
53  Search,
54  Name,
55  Year,
56  Duration,
57  Lastplay,
58  Track,
59  Rating,
60  Played,
61  Heard,
62  Rated,
63  UserRating,
64  False,
66  Count
67  };
68  static const unsigned FieldCount = static_cast <unsigned> (Field::Count);
69 
72  enum class Action {
73  Noop,
74  And,
75  Or,
76  LessThan,
77  LessEqual,
78  Equal,
79  NotEqual,
82  Match
83  };
84 
86  using FilterRating = float;
87 
88 protected:
90  class ParseError : public std::exception {
91  public:
92  std::string reason;
93  const char *point;
94  ParseError (const std::string &_reason, const char *where)
95  : reason (_reason), point (where) {};
96  };
98  class InvalidValue : public std::exception {
99  public:
100  std::string field;
101  std::string value;
102  InvalidValue (const std::string &_field, const std::string &_value)
103  : field (_field), value (_value) {};
104  };
106  class DisallowedOperator : public std::exception {
107  public:
108  std::string field;
109  std::string op;
110  DisallowedOperator (const std::string &_field, const std::string &_operator)
111  : field (_field), op (_operator) {};
112  };
113 
114  class Operation;
116  using Op = std::unique_ptr<Operation>;
117  inline const char *skipWhitespace (const char **const command) {
118  while (isspace (**command)) {
119  (*command)++;
120  }
121  return *command;
122  }
123 
124  std::string gatherString (const char **const command, const char *error_reason);
125  Op parseParenthesis (const char **const command);
126  Op parseComparison (const char **const command);
127  Op parseSearch (const char **const command);
128  Op parseNegation (const char **const command);
129  Op parseOr (const char **const command);
130  Op parseAnd (const char **const command);
131 
133  class Operation {
134  friend class Query::List;
135  friend Op Filter::parseNegation (const char **const command);
136  private:
139  bool invert = false;
140  union value_t {
141  long numeric;
144  struct rating_t {
145  float value;
146  const User *user;
149  struct string_t {
150  char *value;
151  size_t match_length;
154  struct subnodes_t {
157  } nodes;
158  } value;
159  void clear ();
160  public:
161  inline Operation () {
162  memset (&value, '\0', sizeof (value));
163  };
164  inline ~Operation () {
165  clear ();
166  };
167 
168  std::string toString ();
172  inline Operation (const Action _action, const Field _field)
173  : Operation () {
174  action = _action;
175  field = _field;
176  };
177  Operation (const Action action, std::unique_ptr<Filter::Operation> &&left, std::unique_ptr<Filter::Operation> &&right);
178  Operation (const Action action, const Field field, const std::string &_value, const bool wildcard = false);
179  Operation (const Action action, const Field field, const long value);
180  Operation (const Action action, const Field field, const FilterRating value, const User *user);
181  Operation (const Action action, const Field field, const MusicThingie::Type type);
182 
183  // Copy and move operations.
184  Operation (const Operation &) = delete;
185  Operation &operator =(const Operation &) = delete;
186  Operation (Operation &&from);
187  Operation &operator =(Operation &&from);
188 
189 
190  // Operation execution methods
191  template<typename DiffType>
192  bool applyOperation (DiffType diff) const;
193 
197  inline bool numericCheck (long compare_to) const {
198  return compare_to == 0 ? false : applyOperation (compare_to - value.numeric);
199  };
200  bool stringCheck (const std::string &compare_to) const;
201 
202  bool genreCheck (const std::string &list) const;
203 
204  bool evaluate (const PianodPlaylist *playlist) const;
205  bool evaluate (const PianodArtist *artist) const;
206  bool evaluate (const PianodAlbum *album) const;
207  bool evaluate (const PianodSong *track) const;
208 
209  // Static functions
210  static bool isNumericOperator (Action action);
211  static bool isStringOperator (Action action);
212  static bool isStringField (Field field);
214  };
215 
216  std::shared_ptr<Operation> parsetree;
217  bool persistable = true;
218 
219 public:
220  const static Filter All;
221  const static Filter None;
222 
223  Filter (void) {};
224  Filter (const Filter &) = default;
225  Filter (Filter &&from_filter) = default;
226  Filter (const std::string &expression);
227  Filter (const MusicThingie *thing,
228  const MusicThingie::Type type = MusicThingie::Type (0),
229  const DuplicationFlags &manner = DuplicationFlags (true));
230 
231  Filter &operator=(const std::string &expression);
232  Filter &operator=(const Filter &filter) = default;
233  Filter &operator=(Filter &&from_filter) = default;
234 
235 
236  virtual ~Filter ();
237 
241  template<typename MusicThing> inline bool matches (const MusicThing *thing) const {
242  if (!parsetree) return true;
243  return (parsetree->evaluate (thing));
244  };
245 
246  inline bool canPersist (void) const {
247  return persistable;
248  }
249  std::string toString () const;
250 };
251 
252 template<> bool Filter::matches<MusicThingie> (const MusicThingie *thing) const;
253 
254 
255 
258 class PermutedFilter: public Filter {
259  friend class Query::List;
260 private:
261  std::vector<std::string> phrases;
263 public:
264  PermutedFilter (const std::string &phrase, Field search_target = Field::Search);
265  PermutedFilter (const std::vector<std::string> &phrases, Field search_target = Field::Search);
266 };
267 
268 
269 
272 class ListFilter: public Filter {
273 public:
274  ListFilter (const std::vector<std::string> &items, Field search_target = Field::Search);
275 };
276 
An array indexed by an enumeration rather than an integer of some sort.
Definition: enumeratedarray.h:33
Error for filter expressions trying to use a relational operation incorrectly.
Definition: filter.h:106
std::string field
Definition: filter.h:108
DisallowedOperator(const std::string &_field, const std::string &_operator)
Definition: filter.h:110
std::string op
Definition: filter.h:109
Error for filter expression containing an invalid value.
Definition: filter.h:98
std::string value
Definition: filter.h:101
std::string field
Definition: filter.h:100
InvalidValue(const std::string &_field, const std::string &_value)
Definition: filter.h:102
Nodes for the filter parse tree.
Definition: filter.h:133
bool evaluate(const PianodPlaylist *playlist) const
Determine if a playlist matches a filter.
Definition: filter.cpp:717
static MusicThingie::Type getTypeFromField(const Filter::Field field)
Get the music thingie type corresponding to a field name.
Definition: filter.cpp:194
std::string toString()
Definition: filter.cpp:56
static bool isStringOperator(Action action)
Check if an operation applies to strings.
Definition: filter.cpp:185
bool invert
Apply not operator to result of action.
Definition: filter.h:139
static bool isStringField(Field field)
Check if a field contains string values.
Definition: filter.cpp:159
union Filter::Operation::value_t value
bool numericCheck(long compare_to) const
Perform a numeric comparision.
Definition: filter.h:197
bool applyOperation(DiffType diff) const
Apply operation to difference, yielding truth.
Definition: filter.cpp:324
Operation()
Definition: filter.h:161
Action action
The operation: and/or, comparison type, etc.
Definition: filter.h:138
~Operation()
Definition: filter.h:164
Operation(const Action _action, const Field _field)
Construct a check or comparision.
Definition: filter.h:172
Operation(const Action action, std::unique_ptr< Filter::Operation > &&left, std::unique_ptr< Filter::Operation > &&right)
void clear()
Release value in an operation node.
Definition: filter.cpp:213
bool genreCheck(const std::string &list) const
Check if a genre/genre list matches the filter comparison.
Definition: filter.cpp:668
Operation(const Operation &)=delete
bool stringCheck(const std::string &compare_to) const
Check if string value matches filter comparison.
Definition: filter.cpp:692
Operation & operator=(const Operation &)=delete
Field field
For comparison operations, the field to match.
Definition: filter.h:137
static bool isNumericOperator(Action action)
Check if an operation applies to numeric values.
Definition: filter.cpp:173
Error for generic filter syntax/parse errors.
Definition: filter.h:90
std::string reason
Definition: filter.h:92
ParseError(const std::string &_reason, const char *where)
Definition: filter.h:94
const char * point
Definition: filter.h:93
Track data filter.
Definition: filter.h:38
std::string gatherString(const char **const command, const char *error_reason)
Gather a string, either quoted or not, processing quote characters.
Definition: filter.cpp:350
std::unique_ptr< Operation > Op
Container for Operation, to ensure instances are cleaned up.
Definition: filter.h:116
Filter & operator=(const Filter &filter)=default
const char * skipWhitespace(const char **const command)
Definition: filter.h:117
std::shared_ptr< Operation > parsetree
Definition: filter.h:216
static const unsigned FieldCount
Definition: filter.h:68
static const Filter All
Selects all tracks.
Definition: filter.h:220
virtual ~Filter()
Destroy a filter.
Definition: filter.cpp:1062
Field
Fields on which comparisons can be done by the filter.
Definition: filter.h:44
@ Track
Track number.
@ Title
Song name.
float FilterRating
Definition: filter.h:86
friend class Constraints
Definition: filter.h:39
std::string toString() const
Get a filter's expression.
Definition: filter.cpp:957
Filter(const Filter &)=default
Op parseComparison(const char **const command)
Handle comparison or other base operator in expression.
Definition: filter.cpp:429
static const Filter None
Selects nothing.
Definition: filter.h:221
bool matches(const MusicThing *thing) const
Check if a filter matches a song, album, artist or playlist.
Definition: filter.h:241
bool canPersist(void) const
Definition: filter.h:246
Filter & operator=(Filter &&from_filter)=default
Filter & operator=(const std::string &expression)
Assign a new expression to a filter.
Definition: filter.cpp:1054
Action
Filter operations; each node in the parse tree has one action indicating how to proceed.
Definition: filter.h:72
Op parseOr(const char **const command)
Handle binary OR, either as | or ||.
Definition: filter.cpp:638
Op parseNegation(const char **const command)
Handle negation operator, then choose parenthesis or a comparison.
Definition: filter.cpp:611
Op parseAnd(const char **const command)
Handle binary AND, either as & or &&.
Definition: filter.cpp:654
bool persistable
Not true if user referenced or other problematic expressions.
Definition: filter.h:217
Filter(void)
Definition: filter.h:223
Op parseParenthesis(const char **const command)
Handle (parenthesis in an expression).
Definition: filter.cpp:398
Filter(Filter &&from_filter)=default
Op parseSearch(const char **const command)
Handle bare search term in expression.
Definition: filter.cpp:416
Permuted filter, like Filter but constructed from a list of strings.
Definition: filter.h:272
ListFilter(const std::vector< std::string > &items, Field search_target=Field::Search)
Create a new list filter.
Definition: filter.cpp:1127
Base class for songs, albums, artists, playlists, genres, etc.
Definition: musictypes.h:77
Type
Definition: musictypes.h:86
Permuted filter, like Filter but constructed from a string.
Definition: filter.h:258
PermutedFilter(const std::string &phrase, Field search_target=Field::Search)
Create a new permuted filter from a single phrase.
Definition: filter.cpp:1073
const Field target_field
Definition: filter.h:262
std::vector< std::string > phrases
Definition: filter.h:261
Base class for albums, these are also MusicThingies and artists.
Definition: musictypes.h:307
Base class for artists, derived from MusicThingies.
Definition: musictypes.h:272
Base class for playlists, but still a MusicThingie.
Definition: musictypes.h:416
Base class for songs, these are also MusicThingies, artists and albums.
Definition: musictypes.h:339
Media sources mark the available fields (array index) to true to indicate they are capable of searchi...
Definition: querylist.h:44
Information about how a query should be performed by a source.
Definition: querylist.h:64
A adapter to convert filters into a list of queries for a source.
Definition: querylist.h:97
Data about each user.
Definition: user.h:53
Enumerated array type.
Playlist / Artist / Album / Song data types.
Filter-to-query converter.
Definition: filter.h:29
For ratings and user-specific operations.
Definition: filter.h:144
float value
Rating value, when applicable.
Definition: filter.h:145
const User * user
A user, for applicable actions.
Definition: filter.h:146
For string operations.
Definition: filter.h:149
size_t match_length
Portion of string to match; selects exact vs wildcard match.
Definition: filter.h:151
char * value
String comparison value, when applicable.
Definition: filter.h:150
For and/or operations.
Definition: filter.h:154
Operation * l_eval
Definition: filter.h:155
Operation * r_eval
Left side of AND/OR.
Definition: filter.h:156
Definition: filter.h:140
struct Filter::Operation::value_t::rating_t rating
MusicThingie::Type type
Type of results, when applicable.
Definition: filter.h:142
long numeric
Numeric comparison value, when applicable.
Definition: filter.h:141
struct Filter::Operation::value_t::subnodes_t nodes
struct Filter::Operation::value_t::string_t string