Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
mpd
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Иван Мажукин
mpd
Commits
333d226e
Commit
333d226e
authored
Aug 29, 2012
by
Max Kellermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
SongFilter: convert to a C++ class
parent
04a9dec9
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
210 additions
and
241 deletions
+210
-241
Makefile.am
Makefile.am
+1
-2
DatabaseCommands.cxx
src/DatabaseCommands.cxx
+21
-51
DatabasePlaylist.cxx
src/DatabasePlaylist.cxx
+2
-2
DatabasePlaylist.hxx
src/DatabasePlaylist.hxx
+2
-2
DatabasePrint.cxx
src/DatabasePrint.cxx
+6
-6
DatabasePrint.hxx
src/DatabasePrint.hxx
+3
-3
DatabaseQueue.cxx
src/DatabaseQueue.cxx
+2
-2
DatabaseQueue.hxx
src/DatabaseQueue.hxx
+2
-2
DatabaseSelection.cxx
src/DatabaseSelection.cxx
+1
-1
DatabaseSelection.hxx
src/DatabaseSelection.hxx
+4
-4
Directory.cxx
src/Directory.cxx
+3
-4
PlaylistPrint.cxx
src/PlaylistPrint.cxx
+3
-3
PlaylistPrint.hxx
src/PlaylistPrint.hxx
+2
-2
QueueCommands.cxx
src/QueueCommands.cxx
+3
-8
QueuePrint.cxx
src/QueuePrint.cxx
+3
-3
QueuePrint.hxx
src/QueuePrint.hxx
+5
-5
SongFilter.cxx
src/SongFilter.cxx
+73
-118
SongFilter.hxx
src/SongFilter.hxx
+68
-20
SimpleDatabasePlugin.cxx
src/db/SimpleDatabasePlugin.cxx
+1
-1
directory.h
src/directory.h
+5
-2
No files found.
Makefile.am
View file @
333d226e
...
...
@@ -177,7 +177,6 @@ mpd_headers = \
src/riff.h
\
src/aiff.h
\
src/queue.h
\
src/queue_print.h
\
src/queue_save.h
\
src/refcount.h
\
src/replay_gain_config.h
\
...
...
@@ -333,7 +332,7 @@ src_mpd_SOURCES = \
src/playlist_vector.c
\
src/playlist_database.c
\
src/queue.c
\
src/QueuePrint.cxx
\
src/QueuePrint.cxx
src/QueuePrint.hxx
\
src/queue_save.c
\
src/replay_gain_config.c
\
src/replay_gain_info.c
\
...
...
src/DatabaseCommands.cxx
View file @
333d226e
...
...
@@ -59,25 +59,18 @@ handle_lsinfo2(struct client *client, int argc, char *argv[])
static
enum
command_return
handle_match
(
struct
client
*
client
,
int
argc
,
char
*
argv
[],
bool
fold_case
)
{
struct
locate_item_list
*
list
=
locate_item_list_parse
(
argv
+
1
,
argc
-
1
,
fold_case
);
if
(
list
==
NULL
)
{
SongFilter
filter
;
if
(
!
filter
.
Parse
(
argc
-
1
,
argv
+
1
,
fold_case
))
{
command_error
(
client
,
ACK_ERROR_ARG
,
"incorrect arguments"
);
return
COMMAND_RETURN_ERROR
;
}
const
DatabaseSelection
selection
(
""
,
true
,
list
);
const
DatabaseSelection
selection
(
""
,
true
,
&
filter
);
GError
*
error
=
NULL
;
enum
command_return
ret
=
db_selection_print
(
client
,
selection
,
true
,
&
error
)
return
db_selection_print
(
client
,
selection
,
true
,
&
error
)
?
COMMAND_RETURN_OK
:
print_error
(
client
,
error
);
locate_item_list_free
(
list
);
return
ret
;
}
enum
command_return
...
...
@@ -95,22 +88,16 @@ handle_search(struct client *client, int argc, char *argv[])
static
enum
command_return
handle_match_add
(
struct
client
*
client
,
int
argc
,
char
*
argv
[],
bool
fold_case
)
{
struct
locate_item_list
*
list
=
locate_item_list_parse
(
argv
+
1
,
argc
-
1
,
fold_case
);
if
(
list
==
NULL
)
{
SongFilter
filter
;
if
(
!
filter
.
Parse
(
argc
-
1
,
argv
+
1
,
fold_case
))
{
command_error
(
client
,
ACK_ERROR_ARG
,
"incorrect arguments"
);
return
COMMAND_RETURN_ERROR
;
}
GError
*
error
=
NULL
;
enum
command_return
ret
=
findAddIn
(
client
->
player_control
,
""
,
list
,
&
error
)
return
findAddIn
(
client
->
player_control
,
""
,
&
filter
,
&
error
)
?
COMMAND_RETURN_OK
:
print_error
(
client
,
error
);
locate_item_list_free
(
list
);
return
ret
;
}
enum
command_return
...
...
@@ -130,45 +117,31 @@ handle_searchaddpl(struct client *client, int argc, char *argv[])
{
const
char
*
playlist
=
argv
[
1
];
struct
locate_item_list
*
list
=
locate_item_list_parse
(
argv
+
2
,
argc
-
2
,
true
);
if
(
list
==
NULL
)
{
SongFilter
filter
;
if
(
!
filter
.
Parse
(
argc
-
2
,
argv
+
2
,
true
))
{
command_error
(
client
,
ACK_ERROR_ARG
,
"incorrect arguments"
);
return
COMMAND_RETURN_ERROR
;
}
GError
*
error
=
NULL
;
enum
command_return
ret
=
search_add_to_playlist
(
""
,
playlist
,
list
,
&
error
)
return
search_add_to_playlist
(
""
,
playlist
,
&
filter
,
&
error
)
?
COMMAND_RETURN_OK
:
print_error
(
client
,
error
);
locate_item_list_free
(
list
);
return
ret
;
}
enum
command_return
handle_count
(
struct
client
*
client
,
int
argc
,
char
*
argv
[])
{
struct
locate_item_list
*
list
=
locate_item_list_parse
(
argv
+
1
,
argc
-
1
,
false
);
if
(
list
==
NULL
)
{
SongFilter
filter
;
if
(
!
filter
.
Parse
(
argc
-
1
,
argv
+
1
,
false
))
{
command_error
(
client
,
ACK_ERROR_ARG
,
"incorrect arguments"
);
return
COMMAND_RETURN_ERROR
;
}
GError
*
error
=
NULL
;
enum
command_return
ret
=
searchStatsForSongsIn
(
client
,
""
,
list
,
&
error
)
return
searchStatsForSongsIn
(
client
,
""
,
&
filter
,
&
error
)
?
COMMAND_RETURN_OK
:
print_error
(
client
,
error
);
locate_item_list_free
(
list
);
return
ret
;
}
enum
command_return
...
...
@@ -188,7 +161,6 @@ handle_listall(struct client *client, G_GNUC_UNUSED int argc, char *argv[])
enum
command_return
handle_list
(
struct
client
*
client
,
int
argc
,
char
*
argv
[])
{
struct
locate_item_list
*
conditionals
;
unsigned
tagType
=
locate_parse_type
(
argv
[
1
]);
if
(
tagType
==
TAG_NUM_OF_ITEM_TYPES
)
{
...
...
@@ -203,6 +175,7 @@ handle_list(struct client *client, int argc, char *argv[])
}
/* for compatibility with < 0.12.0 */
SongFilter
*
filter
;
if
(
argc
==
3
)
{
if
(
tagType
!=
TAG_ALBUM
)
{
command_error
(
client
,
ACK_ERROR_ARG
,
...
...
@@ -211,28 +184,25 @@ handle_list(struct client *client, int argc, char *argv[])
return
COMMAND_RETURN_ERROR
;
}
conditionals
=
locate_item_list_new_single
((
unsigned
)
TAG_ARTIST
,
argv
[
2
]);
filter
=
new
SongFilter
((
unsigned
)
TAG_ARTIST
,
argv
[
2
]);
}
else
if
(
argc
>
2
)
{
conditionals
=
locate_item_list_parse
(
argv
+
2
,
argc
-
2
,
false
);
if
(
conditionals
==
NULL
)
{
filter
=
new
SongFilter
();
if
(
!
filter
->
Parse
(
argc
-
2
,
argv
+
2
,
false
))
{
delete
filter
;
command_error
(
client
,
ACK_ERROR_ARG
,
"not able to parse args"
);
return
COMMAND_RETURN_ERROR
;
}
}
else
conditionals
=
nullptr
;
filter
=
nullptr
;
GError
*
error
=
NULL
;
enum
command_return
ret
=
listAllUniqueTags
(
client
,
tagType
,
conditionals
,
&
error
)
listAllUniqueTags
(
client
,
tagType
,
filter
,
&
error
)
?
COMMAND_RETURN_OK
:
print_error
(
client
,
error
);
if
(
conditionals
!=
nullptr
)
locate_item_list_free
(
conditionals
);
delete
filter
;
return
ret
;
}
...
...
src/DatabasePlaylist.cxx
View file @
333d226e
...
...
@@ -39,14 +39,14 @@ AddSong(const char *playlist_path_utf8,
bool
search_add_to_playlist
(
const
char
*
uri
,
const
char
*
playlist_path_utf8
,
const
struct
locate_item_list
*
criteria
,
const
SongFilter
*
filter
,
GError
**
error_r
)
{
const
Database
*
db
=
GetDatabase
(
error_r
);
if
(
db
==
nullptr
)
return
false
;
const
DatabaseSelection
selection
(
uri
,
true
,
criteria
);
const
DatabaseSelection
selection
(
uri
,
true
,
filter
);
using
namespace
std
::
placeholders
;
const
auto
f
=
std
::
bind
(
AddSong
,
playlist_path_utf8
,
_1
,
_2
);
...
...
src/DatabasePlaylist.hxx
View file @
333d226e
...
...
@@ -23,12 +23,12 @@
#include "gcc.h"
#include "gerror.h"
struct
locate_item_list
;
class
SongFilter
;
gcc_nonnull
(
1
,
2
)
bool
search_add_to_playlist
(
const
char
*
uri
,
const
char
*
path_utf8
,
const
struct
locate_item_list
*
criteria
,
const
SongFilter
*
filter
,
GError
**
error_r
);
#endif
src/DatabasePrint.cxx
View file @
333d226e
...
...
@@ -120,12 +120,12 @@ db_selection_print(struct client *client, const DatabaseSelection &selection,
return
false
;
using
namespace
std
::
placeholders
;
const
auto
d
=
selection
.
match
==
nullptr
const
auto
d
=
selection
.
filter
==
nullptr
?
std
::
bind
(
PrintDirectory
,
client
,
_1
)
:
VisitDirectory
();
const
auto
s
=
std
::
bind
(
full
?
PrintSongFull
:
PrintSongBrief
,
client
,
_1
);
const
auto
p
=
selection
.
match
==
nullptr
const
auto
p
=
selection
.
filter
==
nullptr
?
std
::
bind
(
full
?
PrintPlaylistFull
:
PrintPlaylistBrief
,
client
,
_1
,
_2
)
:
VisitPlaylist
();
...
...
@@ -155,14 +155,14 @@ stats_visitor_song(SearchStats &stats, song &song)
bool
searchStatsForSongsIn
(
struct
client
*
client
,
const
char
*
name
,
const
struct
locate_item_list
*
criteria
,
const
SongFilter
*
filter
,
GError
**
error_r
)
{
const
Database
*
db
=
GetDatabase
(
error_r
);
if
(
db
==
nullptr
)
return
false
;
const
DatabaseSelection
selection
(
name
,
true
,
criteria
);
const
DatabaseSelection
selection
(
name
,
true
,
filter
);
SearchStats
stats
;
stats
.
numberOfSongs
=
0
;
...
...
@@ -211,14 +211,14 @@ PrintUniqueTag(struct client *client, enum tag_type tag_type,
bool
listAllUniqueTags
(
struct
client
*
client
,
int
type
,
const
struct
locate_item_list
*
criteria
,
const
SongFilter
*
filter
,
GError
**
error_r
)
{
const
Database
*
db
=
GetDatabase
(
error_r
);
if
(
db
==
nullptr
)
return
false
;
const
DatabaseSelection
selection
(
""
,
true
,
criteria
);
const
DatabaseSelection
selection
(
""
,
true
,
filter
);
if
(
type
==
LOCATE_TAG_FILE_TYPE
)
{
using
namespace
std
::
placeholders
;
...
...
src/DatabasePrint.hxx
View file @
333d226e
...
...
@@ -26,7 +26,7 @@
#include <stdbool.h>
struct
client
;
struct
locate_item_list
;
class
SongFilter
;
struct
DatabaseSelection
;
struct
db_visitor
;
...
...
@@ -47,13 +47,13 @@ printInfoForAllIn(struct client *client, const char *uri_utf8,
gcc_nonnull
(
1
,
2
)
bool
searchStatsForSongsIn
(
struct
client
*
client
,
const
char
*
name
,
const
struct
locate_item_list
*
criteria
,
const
SongFilter
*
filter
,
GError
**
error_r
);
gcc_nonnull
(
1
)
bool
listAllUniqueTags
(
struct
client
*
client
,
int
type
,
const
struct
locate_item_list
*
criteria
,
const
SongFilter
*
filter
,
GError
**
error_r
);
#endif
src/DatabaseQueue.cxx
View file @
333d226e
...
...
@@ -46,13 +46,13 @@ AddToQueue(struct player_control *pc, song &song, GError **error_r)
bool
findAddIn
(
struct
player_control
*
pc
,
const
char
*
uri
,
const
struct
locate_item_list
*
criteria
,
GError
**
error_r
)
const
SongFilter
*
filter
,
GError
**
error_r
)
{
const
Database
*
db
=
GetDatabase
(
error_r
);
if
(
db
==
nullptr
)
return
false
;
const
DatabaseSelection
selection
(
uri
,
true
,
criteria
);
const
DatabaseSelection
selection
(
uri
,
true
,
filter
);
using
namespace
std
::
placeholders
;
const
auto
f
=
std
::
bind
(
AddToQueue
,
pc
,
_1
,
_2
);
...
...
src/DatabaseQueue.hxx
View file @
333d226e
...
...
@@ -23,12 +23,12 @@
#include "gcc.h"
#include "gerror.h"
struct
locate_item_list
;
class
SongFilter
;
struct
player_control
;
gcc_nonnull
(
1
,
2
)
bool
findAddIn
(
struct
player_control
*
pc
,
const
char
*
name
,
const
struct
locate_item_list
*
criteria
,
GError
**
error_r
);
const
SongFilter
*
filter
,
GError
**
error_r
);
#endif
src/DatabaseSelection.cxx
View file @
333d226e
...
...
@@ -23,5 +23,5 @@
bool
DatabaseSelection
::
Match
(
const
song
&
song
)
const
{
return
match
==
nullptr
||
locate_list_song_match
(
&
song
,
match
);
return
filter
==
nullptr
||
filter
->
Match
(
song
);
}
src/DatabaseSelection.hxx
View file @
333d226e
...
...
@@ -25,7 +25,7 @@
#include <assert.h>
#include <stddef.h>
struct
locate_item_list
;
class
SongFilter
;
struct
song
;
struct
DatabaseSelection
{
...
...
@@ -41,11 +41,11 @@ struct DatabaseSelection {
*/
bool
recursive
;
const
locate_item_list
*
match
;
const
SongFilter
*
filter
;
DatabaseSelection
(
const
char
*
_uri
,
bool
_recursive
,
const
locate_item_list
*
_match
=
nullptr
)
:
uri
(
_uri
),
recursive
(
_recursive
),
match
(
_match
)
{
const
SongFilter
*
_filter
=
nullptr
)
:
uri
(
_uri
),
recursive
(
_recursive
),
filter
(
_filter
)
{
assert
(
uri
!=
NULL
);
}
...
...
src/Directory.cxx
View file @
333d226e
...
...
@@ -291,7 +291,7 @@ directory_sort(struct directory *directory)
}
bool
directory
::
Walk
(
bool
recursive
,
const
locate_item_list
*
match
,
directory
::
Walk
(
bool
recursive
,
const
SongFilter
*
filter
,
VisitDirectory
visit_directory
,
VisitSong
visit_song
,
VisitPlaylist
visit_playlist
,
GError
**
error_r
)
const
...
...
@@ -301,8 +301,7 @@ directory::Walk(bool recursive, const locate_item_list *match,
if
(
visit_song
)
{
struct
song
*
song
;
directory_for_each_song
(
song
,
this
)
if
((
match
==
NULL
||
locate_list_song_match
(
song
,
match
))
&&
if
((
filter
==
nullptr
||
filter
->
Match
(
*
song
))
&&
!
visit_song
(
*
song
,
error_r
))
return
false
;
}
...
...
@@ -321,7 +320,7 @@ directory::Walk(bool recursive, const locate_item_list *match,
return
false
;
if
(
recursive
&&
!
child
->
Walk
(
recursive
,
match
,
!
child
->
Walk
(
recursive
,
filter
,
visit_directory
,
visit_song
,
visit_playlist
,
error_r
))
return
false
;
...
...
src/PlaylistPrint.cxx
View file @
333d226e
...
...
@@ -19,6 +19,7 @@
#include "config.h"
#include "PlaylistPrint.hxx"
#include "QueuePrint.hxx"
extern
"C"
{
#include "playlist_list.h"
...
...
@@ -26,7 +27,6 @@ extern "C" {
#include "playlist_any.h"
#include "playlist_song.h"
#include "playlist.h"
#include "queue_print.h"
#include "stored_playlist.h"
#include "song_print.h"
#include "song.h"
...
...
@@ -91,9 +91,9 @@ playlist_print_current(struct client *client, const struct playlist *playlist)
void
playlist_print_find
(
struct
client
*
client
,
const
struct
playlist
*
playlist
,
const
struct
locate_item_list
*
list
)
const
SongFilter
&
filter
)
{
queue_find
(
client
,
&
playlist
->
queue
,
list
);
queue_find
(
client
,
&
playlist
->
queue
,
filter
);
}
void
...
...
src/PlaylistPrint.hxx
View file @
333d226e
...
...
@@ -26,7 +26,7 @@
struct
client
;
struct
playlist
;
struct
locate_item_list
;
class
SongFilter
;
/**
* Sends the whole playlist to the client, song URIs only.
...
...
@@ -66,7 +66,7 @@ playlist_print_current(struct client *client, const struct playlist *playlist);
*/
void
playlist_print_find
(
struct
client
*
client
,
const
struct
playlist
*
playlist
,
const
struct
locate_item_list
*
list
);
const
SongFilter
&
filter
);
/**
* Print detailed changes since the specified playlist version.
...
...
src/QueueCommands.cxx
View file @
333d226e
...
...
@@ -246,18 +246,13 @@ static enum command_return
handle_playlist_match
(
struct
client
*
client
,
int
argc
,
char
*
argv
[],
bool
fold_case
)
{
struct
locate_item_list
*
list
=
locate_item_list_parse
(
argv
+
1
,
argc
-
1
,
fold_case
);
if
(
list
==
NULL
)
{
SongFilter
filter
;
if
(
!
filter
.
Parse
(
argc
-
1
,
argv
+
1
,
fold_case
))
{
command_error
(
client
,
ACK_ERROR_ARG
,
"incorrect arguments"
);
return
COMMAND_RETURN_ERROR
;
}
playlist_print_find
(
client
,
&
g_playlist
,
list
);
locate_item_list_free
(
list
);
playlist_print_find
(
client
,
&
g_playlist
,
filter
);
return
COMMAND_RETURN_OK
;
}
...
...
src/QueuePrint.cxx
View file @
333d226e
...
...
@@ -18,10 +18,10 @@
*/
#include "config.h"
#include "QueuePrint.hxx"
#include "SongFilter.hxx"
extern
"C"
{
#include "queue_print.h"
#include "queue.h"
#include "song.h"
#include "song_print.h"
...
...
@@ -96,12 +96,12 @@ queue_print_changes_position(struct client *client, const struct queue *queue,
void
queue_find
(
struct
client
*
client
,
const
struct
queue
*
queue
,
const
struct
locate_item_list
*
criteria
)
const
SongFilter
&
filter
)
{
for
(
unsigned
i
=
0
;
i
<
queue_length
(
queue
);
i
++
)
{
const
struct
song
*
song
=
queue_get
(
queue
,
i
);
if
(
locate_list_song_match
(
song
,
criteria
))
if
(
filter
.
Match
(
*
song
))
queue_print_song_info
(
client
,
queue
,
i
);
}
}
src/
queue_print.h
→
src/
QueuePrint.hxx
View file @
333d226e
/*
* Copyright (C) 2003-201
1
The Music Player Daemon Project
* Copyright (C) 2003-201
2
The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
...
...
@@ -22,14 +22,14 @@
* client.
*/
#ifndef
QUEUE_PRINT_H
#define
QUEUE_PRINT_H
#ifndef
MPD_QUEUE_PRINT_HXX
#define
MPD_QUEUE_PRINT_HXX
#include <stdint.h>
struct
client
;
struct
queue
;
struct
locate_item_list
;
class
SongFilter
;
void
queue_print_info
(
struct
client
*
client
,
const
struct
queue
*
queue
,
...
...
@@ -49,6 +49,6 @@ queue_print_changes_position(struct client *client, const struct queue *queue,
void
queue_find
(
struct
client
*
client
,
const
struct
queue
*
queue
,
const
struct
locate_item_list
*
criteria
);
const
SongFilter
&
filter
);
#endif
src/SongFilter.cxx
View file @
333d226e
...
...
@@ -35,27 +35,6 @@ extern "C" {
#define LOCATE_TAG_FILE_KEY_OLD "filename"
#define LOCATE_TAG_ANY_KEY "any"
/* struct used for search, find, list queries */
struct
locate_item
{
uint8_t
tag
;
bool
fold_case
;
/* what we are looking for */
char
*
needle
;
};
/**
* An array of struct locate_item objects.
*/
struct
locate_item_list
{
/** number of items */
unsigned
length
;
/** this is a variable length array */
struct
locate_item
items
[
1
];
};
unsigned
locate_parse_type
(
const
char
*
str
)
{
...
...
@@ -69,107 +48,52 @@ locate_parse_type(const char *str)
return
tag_name_parse_i
(
str
);
}
static
bool
locate_item_init
(
struct
locate_item
*
item
,
const
char
*
type_string
,
const
char
*
needle
,
bool
fold_case
)
SongFilter
::
Item
::
Item
(
unsigned
_tag
,
const
char
*
_value
,
bool
_fold_case
)
:
tag
(
_tag
),
fold_case
(
_fold_case
),
value
(
fold_case
?
g_utf8_casefold
(
_value
,
-
1
)
:
g_strdup
(
_value
))
{
item
->
tag
=
locate_parse_type
(
type_string
);
if
(
item
->
tag
==
TAG_NUM_OF_ITEM_TYPES
)
return
false
;
item
->
fold_case
=
fold_case
;
item
->
needle
=
fold_case
?
g_utf8_casefold
(
needle
,
-
1
)
:
g_strdup
(
needle
);
return
true
;
}
void
locate_item_list_free
(
struct
locate_item_list
*
list
)
SongFilter
::
Item
::~
Item
()
{
for
(
unsigned
i
=
0
;
i
<
list
->
length
;
++
i
)
g_free
(
list
->
items
[
i
].
needle
);
g_free
(
list
);
g_free
(
value
);
}
static
struct
locate_item_list
*
locate_item_list_new
(
unsigned
length
)
{
struct
locate_item_list
*
list
=
(
struct
locate_item_list
*
)
g_malloc
(
sizeof
(
*
list
)
-
sizeof
(
list
->
items
[
0
])
+
length
*
sizeof
(
list
->
items
[
0
]));
list
->
length
=
length
;
return
list
;
}
struct
locate_item_list
*
locate_item_list_new_single
(
unsigned
tag
,
const
char
*
needle
)
{
struct
locate_item_list
*
list
=
locate_item_list_new
(
1
);
list
->
items
[
0
].
tag
=
tag
;
list
->
items
[
0
].
fold_case
=
false
;
list
->
items
[
0
].
needle
=
g_strdup
(
needle
);
return
list
;
}
struct
locate_item_list
*
locate_item_list_parse
(
char
*
argv
[],
unsigned
argc
,
bool
fold_case
)
{
if
(
argc
==
0
||
argc
%
2
!=
0
)
return
NULL
;
struct
locate_item_list
*
list
=
locate_item_list_new
(
argc
/
2
);
for
(
unsigned
i
=
0
;
i
<
list
->
length
;
++
i
)
{
if
(
!
locate_item_init
(
&
list
->
items
[
i
],
argv
[
i
*
2
],
argv
[
i
*
2
+
1
],
fold_case
))
{
locate_item_list_free
(
list
);
return
NULL
;
}
}
return
list
;
}
gcc_pure
static
bool
locate_string_match
(
const
struct
locate_item
*
item
,
const
char
*
value
)
bool
SongFilter
::
Item
::
StringMatch
(
const
char
*
s
)
const
{
assert
(
item
!=
NULL
);
assert
(
value
!=
NULL
);
assert
(
value
!=
nullptr
);
assert
(
s
!=
nullptr
);
if
(
item
->
fold_case
)
{
char
*
p
=
g_utf8_casefold
(
value
,
-
1
);
const
bool
result
=
strstr
(
p
,
item
->
needl
e
)
!=
NULL
;
if
(
fold_case
)
{
char
*
p
=
g_utf8_casefold
(
s
,
-
1
);
const
bool
result
=
strstr
(
p
,
valu
e
)
!=
NULL
;
g_free
(
p
);
return
result
;
}
else
{
return
strcmp
(
value
,
item
->
needl
e
)
==
0
;
return
strcmp
(
s
,
valu
e
)
==
0
;
}
}
gcc_pure
static
bool
locate_tag_match
(
const
struct
locate_item
*
item
,
const
struct
tag
*
tag
)
bool
SongFilter
::
Item
::
Match
(
const
tag_item
&
item
)
const
{
assert
(
item
!=
NULL
);
assert
(
tag
!=
NULL
);
return
(
tag
==
LOCATE_TAG_ANY_TYPE
||
(
unsigned
)
item
.
type
==
tag
)
&&
StringMatch
(
item
.
value
);
}
bool
SongFilter
::
Item
::
Match
(
const
struct
tag
&
_tag
)
const
{
bool
visited_types
[
TAG_NUM_OF_ITEM_TYPES
];
memset
(
visited_types
,
0
,
sizeof
(
visited_types
)
);
std
::
fill
(
visited_types
,
visited_types
+
TAG_NUM_OF_ITEM_TYPES
,
false
);
for
(
unsigned
i
=
0
;
i
<
tag
->
num_items
;
i
++
)
{
visited_types
[
tag
->
items
[
i
]
->
type
]
=
true
;
if
(
item
->
tag
!=
LOCATE_TAG_ANY_TYPE
&&
tag
->
items
[
i
]
->
type
!=
item
->
tag
)
continue
;
for
(
unsigned
i
=
0
;
i
<
_tag
.
num_items
;
i
++
)
{
visited_types
[
_tag
.
items
[
i
]
->
type
]
=
true
;
if
(
locate_string_match
(
item
,
tag
->
items
[
i
]
->
value
))
if
(
Match
(
*
_tag
.
items
[
i
]
))
return
true
;
}
...
...
@@ -179,36 +103,67 @@ locate_tag_match(const struct locate_item *item, const struct tag *tag)
* empty (first char is a \0), then it's a match as well and
* we should return true.
*/
if
(
*
item
->
needle
==
0
&&
item
->
tag
!=
LOCATE_TAG_ANY_TYPE
&&
!
visited_types
[
item
->
tag
])
if
(
*
value
==
0
&&
tag
<
TAG_NUM_OF_ITEM_TYPES
&&
!
visited_types
[
tag
])
return
true
;
return
false
;
}
gcc_pure
static
bool
locate_song_match
(
const
struct
locate_item
*
item
,
const
struct
song
*
song
)
bool
SongFilter
::
Item
::
Match
(
const
song
&
song
)
const
{
if
(
item
->
tag
==
LOCATE_TAG_FILE_TYPE
||
item
->
tag
==
LOCATE_TAG_ANY_TYPE
)
{
char
*
uri
=
song_get_uri
(
song
);
const
bool
result
=
locate_string_match
(
item
,
uri
);
if
(
tag
==
LOCATE_TAG_FILE_TYPE
||
tag
==
LOCATE_TAG_ANY_TYPE
)
{
char
*
uri
=
song_get_uri
(
&
song
);
const
bool
result
=
StringMatch
(
uri
);
g_free
(
uri
);
if
(
result
||
item
->
tag
==
LOCATE_TAG_FILE_TYPE
)
if
(
result
||
tag
==
LOCATE_TAG_FILE_TYPE
)
return
result
;
}
return
song
->
tag
!=
NULL
&&
locate_tag_match
(
item
,
song
->
tag
);
return
song
.
tag
!=
NULL
&&
Match
(
*
song
.
tag
);
}
SongFilter
::
SongFilter
(
unsigned
tag
,
const
char
*
value
,
bool
fold_case
)
{
items
.
push_back
(
Item
(
tag
,
value
,
fold_case
));
}
SongFilter
::~
SongFilter
()
{
/* this destructor exists here just so it won't get inlined */
}
bool
SongFilter
::
Parse
(
const
char
*
tag_string
,
const
char
*
value
,
bool
fold_case
)
{
unsigned
tag
=
locate_parse_type
(
tag_string
);
if
(
tag
==
TAG_NUM_OF_ITEM_TYPES
)
return
false
;
items
.
push_back
(
Item
(
tag
,
value
,
fold_case
));
return
true
;
}
bool
SongFilter
::
Parse
(
unsigned
argc
,
char
*
argv
[],
bool
fold_case
)
{
if
(
argc
==
0
||
argc
%
2
!=
0
)
return
false
;
for
(
unsigned
i
=
0
;
i
<
argc
;
i
+=
2
)
if
(
!
Parse
(
argv
[
i
],
argv
[
i
+
1
],
fold_case
))
return
false
;
return
true
;
}
bool
locate_list_song_match
(
const
struct
song
*
song
,
const
struct
locate_item_list
*
criteria
)
SongFilter
::
Match
(
const
song
&
song
)
const
{
for
(
unsigned
i
=
0
;
i
<
criteria
->
length
;
i
++
)
if
(
!
locate_song_match
(
&
criteria
->
items
[
i
],
song
))
for
(
const
auto
&
i
:
items
)
if
(
!
i
.
Match
(
song
))
return
false
;
return
true
;
...
...
src/SongFilter.hxx
View file @
333d226e
...
...
@@ -22,15 +22,82 @@
#include "gcc.h"
#include <list>
#include <stdint.h>
#include <stdbool.h>
#define LOCATE_TAG_FILE_TYPE TAG_NUM_OF_ITEM_TYPES+10
#define LOCATE_TAG_ANY_TYPE TAG_NUM_OF_ITEM_TYPES+20
struct
locate_item_list
;
struct
tag
;
struct
tag_item
;
struct
song
;
class
SongFilter
{
class
Item
{
uint8_t
tag
;
bool
fold_case
;
char
*
value
;
public
:
gcc_nonnull
(
3
)
Item
(
unsigned
tag
,
const
char
*
value
,
bool
fold_case
=
false
);
Item
(
const
Item
&
other
)
=
delete
;
Item
(
Item
&&
other
)
:
tag
(
other
.
tag
),
fold_case
(
other
.
fold_case
),
value
(
other
.
value
)
{
other
.
value
=
nullptr
;
}
~
Item
();
Item
&
operator
=
(
const
Item
&
other
)
=
delete
;
unsigned
GetTag
()
const
{
return
tag
;
}
gcc_pure
gcc_nonnull
(
2
)
bool
StringMatch
(
const
char
*
s
)
const
;
gcc_pure
bool
Match
(
const
tag_item
&
tag_item
)
const
;
gcc_pure
bool
Match
(
const
struct
tag
&
tag
)
const
;
gcc_pure
bool
Match
(
const
song
&
song
)
const
;
};
std
::
list
<
Item
>
items
;
public
:
SongFilter
()
=
default
;
gcc_nonnull
(
3
)
SongFilter
(
unsigned
tag
,
const
char
*
value
,
bool
fold_case
=
false
);
~
SongFilter
();
gcc_nonnull
(
2
,
3
)
bool
Parse
(
const
char
*
tag
,
const
char
*
value
,
bool
fold_case
=
false
);
gcc_nonnull
(
3
)
bool
Parse
(
unsigned
argc
,
char
*
argv
[],
bool
fold_case
=
false
);
gcc_pure
bool
Match
(
const
tag
&
tag
)
const
;
gcc_pure
bool
Match
(
const
song
&
song
)
const
;
};
/**
* @return #TAG_NUM_OF_ITEM_TYPES on error
*/
...
...
@@ -38,23 +105,4 @@ gcc_pure
unsigned
locate_parse_type
(
const
char
*
str
);
gcc_malloc
struct
locate_item_list
*
locate_item_list_new_single
(
unsigned
tag
,
const
char
*
needle
);
/* return number of items or -1 on error */
gcc_nonnull
(
1
)
struct
locate_item_list
*
locate_item_list_parse
(
char
*
argv
[],
unsigned
argc
,
bool
fold_case
);
gcc_nonnull
(
1
)
void
locate_item_list_free
(
struct
locate_item_list
*
list
);
gcc_pure
gcc_nonnull
(
1
,
2
)
bool
locate_list_song_match
(
const
struct
song
*
song
,
const
struct
locate_item_list
*
criteria
);
#endif
src/db/SimpleDatabasePlugin.cxx
View file @
333d226e
...
...
@@ -282,7 +282,7 @@ SimpleDatabase::Visit(const DatabaseSelection &selection,
return
false
;
db_lock
();
bool
ret
=
directory
->
Walk
(
selection
.
recursive
,
selection
.
match
,
bool
ret
=
directory
->
Walk
(
selection
.
recursive
,
selection
.
filter
,
visit_directory
,
visit_song
,
visit_playlist
,
error_r
);
db_unlock
();
...
...
src/directory.h
View file @
333d226e
...
...
@@ -55,7 +55,10 @@
struct
song
;
struct
db_visitor
;
struct
locate_item_list
;
#ifdef __cplusplus
class
SongFilter
;
#endif
struct
directory
{
/**
...
...
@@ -97,7 +100,7 @@ struct directory {
/**
* Caller must lock #db_mutex.
*/
bool
Walk
(
bool
recursive
,
const
locate_item_list
*
match
,
bool
Walk
(
bool
recursive
,
const
SongFilter
*
match
,
VisitDirectory
visit_directory
,
VisitSong
visit_song
,
VisitPlaylist
visit_playlist
,
GError
**
error_r
)
const
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment