replace gnu regex wrapper with boost::regex
This commit is contained in:
@@ -29,7 +29,6 @@ ncmpcpp_SOURCES = \
|
||||
outputs.cpp \
|
||||
playlist.cpp \
|
||||
playlist_editor.cpp \
|
||||
regexes.cpp \
|
||||
screen.cpp \
|
||||
screen_type.cpp \
|
||||
scrollpad.cpp \
|
||||
@@ -86,7 +85,6 @@ noinst_HEADERS = \
|
||||
playlist_editor.h \
|
||||
proxy_song_list.h \
|
||||
regex_filter.h \
|
||||
regexes.h \
|
||||
screen.h \
|
||||
screen_switcher.h \
|
||||
screen_type.h \
|
||||
|
||||
@@ -61,7 +61,7 @@ std::set<std::string> SupportedExtensions;
|
||||
bool hasSupportedExtension(const std::string &file);
|
||||
|
||||
std::string ItemToString(const MPD::Item &item);
|
||||
bool BrowserEntryMatcher(const Regex &rx, const MPD::Item &item, bool filter);
|
||||
bool BrowserEntryMatcher(const boost::regex &rx, const MPD::Item &item, bool filter);
|
||||
|
||||
}
|
||||
|
||||
@@ -258,10 +258,15 @@ std::string Browser::currentFilter()
|
||||
|
||||
void Browser::applyFilter(const std::string &filter)
|
||||
{
|
||||
w.showAll();
|
||||
auto fun = std::bind(BrowserEntryMatcher, _1, _2, true);
|
||||
auto rx = RegexFilter<MPD::Item>(filter, Config.regex_type, fun);
|
||||
w.filter(w.begin(), w.end(), rx);
|
||||
try
|
||||
{
|
||||
w.showAll();
|
||||
auto fun = std::bind(BrowserEntryMatcher, _1, _2, true);
|
||||
auto rx = RegexFilter<MPD::Item>(
|
||||
boost::regex(filter, Config.regex_type), fun);
|
||||
w.filter(w.begin(), w.end(), rx);
|
||||
}
|
||||
catch (boost::bad_expression &) { }
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
@@ -273,9 +278,17 @@ bool Browser::allowsSearching()
|
||||
|
||||
bool Browser::search(const std::string &constraint)
|
||||
{
|
||||
auto fun = std::bind(BrowserEntryMatcher, _1, _2, false);
|
||||
auto rx = RegexFilter<MPD::Item>(constraint, Config.regex_type, fun);
|
||||
return w.search(w.begin(), w.end(), rx);
|
||||
try
|
||||
{
|
||||
auto fun = std::bind(BrowserEntryMatcher, _1, _2, false);
|
||||
auto rx = RegexFilter<MPD::Item>(
|
||||
boost::regex(constraint, Config.regex_type), fun);
|
||||
return w.search(w.begin(), w.end(), rx);
|
||||
}
|
||||
catch (boost::bad_expression &)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Browser::nextFound(bool wrap)
|
||||
@@ -614,11 +627,11 @@ std::string ItemToString(const MPD::Item &item)
|
||||
return result;
|
||||
}
|
||||
|
||||
bool BrowserEntryMatcher(const Regex &rx, const MPD::Item &item, bool filter)
|
||||
bool BrowserEntryMatcher(const boost::regex &rx, const MPD::Item &item, bool filter)
|
||||
{
|
||||
if (Browser::isParentDirectory(item))
|
||||
return filter;
|
||||
return rx.match(ItemToString(item));
|
||||
return boost::regex_search(ItemToString(item), rx);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -61,9 +61,9 @@ typedef MediaLibrary::AlbumEntry AlbumEntry;
|
||||
std::string AlbumToString(const AlbumEntry &ae);
|
||||
std::string SongToString(const MPD::Song &s);
|
||||
|
||||
bool TagEntryMatcher(const Regex &rx, const MediaLibrary::PrimaryTag &tagmtime);
|
||||
bool AlbumEntryMatcher(const Regex &rx, const NC::Menu<AlbumEntry>::Item &item, bool filter);
|
||||
bool SongEntryMatcher(const Regex &rx, const MPD::Song &s);
|
||||
bool TagEntryMatcher(const boost::regex &rx, const MediaLibrary::PrimaryTag &tagmtime);
|
||||
bool AlbumEntryMatcher(const boost::regex &rx, const NC::Menu<AlbumEntry>::Item &item, bool filter);
|
||||
bool SongEntryMatcher(const boost::regex &rx, const MPD::Song &s);
|
||||
|
||||
struct SortSongs {
|
||||
typedef NC::Menu<MPD::Song>::Item SongItem;
|
||||
@@ -563,25 +563,32 @@ std::string MediaLibrary::currentFilter()
|
||||
|
||||
void MediaLibrary::applyFilter(const std::string &filter)
|
||||
{
|
||||
if (isActiveWindow(Tags))
|
||||
try
|
||||
{
|
||||
Tags.showAll();
|
||||
auto rx = RegexFilter<PrimaryTag>(filter, Config.regex_type, TagEntryMatcher);
|
||||
Tags.filter(Tags.begin(), Tags.end(), rx);
|
||||
}
|
||||
else if (isActiveWindow(Albums))
|
||||
{
|
||||
Albums.showAll();
|
||||
auto fun = std::bind(AlbumEntryMatcher, _1, _2, true);
|
||||
auto rx = RegexItemFilter<AlbumEntry>(filter, Config.regex_type, fun);
|
||||
Albums.filter(Albums.begin(), Albums.end(), rx);
|
||||
}
|
||||
else if (isActiveWindow(Songs))
|
||||
{
|
||||
Songs.showAll();
|
||||
auto rx = RegexFilter<MPD::Song>(filter, Config.regex_type, SongEntryMatcher);
|
||||
Songs.filter(Songs.begin(), Songs.end(), rx);
|
||||
if (isActiveWindow(Tags))
|
||||
{
|
||||
Tags.showAll();
|
||||
auto rx = RegexFilter<PrimaryTag>(
|
||||
boost::regex(filter, Config.regex_type), TagEntryMatcher);
|
||||
Tags.filter(Tags.begin(), Tags.end(), rx);
|
||||
}
|
||||
else if (isActiveWindow(Albums))
|
||||
{
|
||||
Albums.showAll();
|
||||
auto fun = std::bind(AlbumEntryMatcher, _1, _2, true);
|
||||
auto rx = RegexItemFilter<AlbumEntry>(
|
||||
boost::regex(filter, Config.regex_type), fun);
|
||||
Albums.filter(Albums.begin(), Albums.end(), rx);
|
||||
}
|
||||
else if (isActiveWindow(Songs))
|
||||
{
|
||||
Songs.showAll();
|
||||
auto rx = RegexFilter<MPD::Song>(
|
||||
boost::regex(filter, Config.regex_type), SongEntryMatcher);
|
||||
Songs.filter(Songs.begin(), Songs.end(), rx);
|
||||
}
|
||||
}
|
||||
catch (boost::bad_expression &) { }
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
@@ -593,24 +600,34 @@ bool MediaLibrary::allowsSearching()
|
||||
|
||||
bool MediaLibrary::search(const std::string &constraint)
|
||||
{
|
||||
bool result = false;
|
||||
if (isActiveWindow(Tags))
|
||||
try
|
||||
{
|
||||
auto rx = RegexFilter<PrimaryTag>(constraint, Config.regex_type, TagEntryMatcher);
|
||||
result = Tags.search(Tags.begin(), Tags.end(), rx);
|
||||
bool result = false;
|
||||
if (isActiveWindow(Tags))
|
||||
{
|
||||
auto rx = RegexFilter<PrimaryTag>(
|
||||
boost::regex(constraint, Config.regex_type), TagEntryMatcher);
|
||||
result = Tags.search(Tags.begin(), Tags.end(), rx);
|
||||
}
|
||||
else if (isActiveWindow(Albums))
|
||||
{
|
||||
auto fun = std::bind(AlbumEntryMatcher, _1, _2, false);
|
||||
auto rx = RegexItemFilter<AlbumEntry>(
|
||||
boost::regex(constraint, Config.regex_type), fun);
|
||||
result = Albums.search(Albums.begin(), Albums.end(), rx);
|
||||
}
|
||||
else if (isActiveWindow(Songs))
|
||||
{
|
||||
auto rx = RegexFilter<MPD::Song>(
|
||||
boost::regex(constraint, Config.regex_type), SongEntryMatcher);
|
||||
result = Songs.search(Songs.begin(), Songs.end(), rx);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else if (isActiveWindow(Albums))
|
||||
catch (boost::bad_expression &)
|
||||
{
|
||||
auto fun = std::bind(AlbumEntryMatcher, _1, _2, false);
|
||||
auto rx = RegexItemFilter<AlbumEntry>(constraint, Config.regex_type, fun);
|
||||
result = Albums.search(Albums.begin(), Albums.end(), rx);
|
||||
return false;
|
||||
}
|
||||
else if (isActiveWindow(Songs))
|
||||
{
|
||||
auto rx = RegexFilter<MPD::Song>(constraint, Config.regex_type, SongEntryMatcher);
|
||||
result = Songs.search(Songs.begin(), Songs.end(), rx);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void MediaLibrary::nextFound(bool wrap)
|
||||
@@ -1010,21 +1027,21 @@ std::string SongToString(const MPD::Song &s)
|
||||
return s.toString(Config.song_library_format, Config.tags_separator);
|
||||
}
|
||||
|
||||
bool TagEntryMatcher(const Regex &rx, const MediaLibrary::PrimaryTag &pt)
|
||||
bool TagEntryMatcher(const boost::regex &rx, const MediaLibrary::PrimaryTag &pt)
|
||||
{
|
||||
return rx.match(pt.tag());
|
||||
return boost::regex_search(pt.tag(), rx);
|
||||
}
|
||||
|
||||
bool AlbumEntryMatcher(const Regex &rx, const NC::Menu<AlbumEntry>::Item &item, bool filter)
|
||||
bool AlbumEntryMatcher(const boost::regex &rx, const NC::Menu<AlbumEntry>::Item &item, bool filter)
|
||||
{
|
||||
if (item.isSeparator() || item.value().isAllTracksEntry())
|
||||
return filter;
|
||||
return rx.match(AlbumToString(item.value()));
|
||||
return boost::regex_search(AlbumToString(item.value()), rx);
|
||||
}
|
||||
|
||||
bool SongEntryMatcher(const Regex &rx, const MPD::Song &s)
|
||||
bool SongEntryMatcher(const boost::regex &rx, const MPD::Song &s)
|
||||
{
|
||||
return rx.match(SongToString(s));
|
||||
return boost::regex_search(SongToString(s), rx);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ bool Playlist::ReloadRemaining = false;
|
||||
namespace {//
|
||||
|
||||
std::string songToString(const MPD::Song &s);
|
||||
bool playlistEntryMatcher(const Regex &rx, const MPD::Song &s);
|
||||
bool playlistEntryMatcher(const boost::regex &rx, const MPD::Song &s);
|
||||
|
||||
}
|
||||
|
||||
@@ -141,9 +141,14 @@ std::string Playlist::currentFilter()
|
||||
|
||||
void Playlist::applyFilter(const std::string &filter)
|
||||
{
|
||||
w.showAll();
|
||||
auto rx = RegexFilter<MPD::Song>(filter, Config.regex_type, playlistEntryMatcher);
|
||||
w.filter(w.begin(), w.end(), rx);
|
||||
try
|
||||
{
|
||||
w.showAll();
|
||||
auto rx = RegexFilter<MPD::Song>(
|
||||
boost::regex(filter, Config.regex_type), playlistEntryMatcher);
|
||||
w.filter(w.begin(), w.end(), rx);
|
||||
}
|
||||
catch (boost::bad_expression &) { }
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
@@ -155,8 +160,16 @@ bool Playlist::allowsSearching()
|
||||
|
||||
bool Playlist::search(const std::string &constraint)
|
||||
{
|
||||
auto rx = RegexFilter<MPD::Song>(constraint, Config.regex_type, playlistEntryMatcher);
|
||||
return w.search(w.begin(), w.end(), rx);
|
||||
try
|
||||
{
|
||||
auto rx = RegexFilter<MPD::Song>(
|
||||
boost::regex(constraint, Config.regex_type), playlistEntryMatcher);
|
||||
return w.search(w.begin(), w.end(), rx);
|
||||
}
|
||||
catch (boost::bad_expression &)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Playlist::nextFound(bool wrap)
|
||||
@@ -343,9 +356,9 @@ std::string songToString(const MPD::Song &s)
|
||||
return result;
|
||||
}
|
||||
|
||||
bool playlistEntryMatcher(const Regex &rx, const MPD::Song &s)
|
||||
bool playlistEntryMatcher(const boost::regex &rx, const MPD::Song &s)
|
||||
{
|
||||
return rx.match(songToString(s));
|
||||
return boost::regex_search(songToString(s), rx);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -51,8 +51,8 @@ size_t RightColumnStartX;
|
||||
size_t RightColumnWidth;
|
||||
|
||||
std::string SongToString(const MPD::Song &s);
|
||||
bool PlaylistEntryMatcher(const Regex &rx, const std::string &playlist);
|
||||
bool SongEntryMatcher(const Regex &rx, const MPD::Song &s);
|
||||
bool PlaylistEntryMatcher(const boost::regex &rx, const std::string &playlist);
|
||||
bool SongEntryMatcher(const boost::regex &rx, const MPD::Song &s);
|
||||
|
||||
}
|
||||
|
||||
@@ -337,18 +337,24 @@ std::string PlaylistEditor::currentFilter()
|
||||
|
||||
void PlaylistEditor::applyFilter(const std::string &filter)
|
||||
{
|
||||
if (isActiveWindow(Playlists))
|
||||
try
|
||||
{
|
||||
Playlists.showAll();
|
||||
auto rx = RegexFilter<std::string>(filter, Config.regex_type, PlaylistEntryMatcher);
|
||||
Playlists.filter(Playlists.begin(), Playlists.end(), rx);
|
||||
}
|
||||
else if (isActiveWindow(Content))
|
||||
{
|
||||
Content.showAll();
|
||||
auto rx = RegexFilter<MPD::Song>(filter, Config.regex_type, SongEntryMatcher);
|
||||
Content.filter(Content.begin(), Content.end(), rx);
|
||||
if (isActiveWindow(Playlists))
|
||||
{
|
||||
Playlists.showAll();
|
||||
auto rx = RegexFilter<std::string>(
|
||||
boost::regex(filter, Config.regex_type), PlaylistEntryMatcher);
|
||||
Playlists.filter(Playlists.begin(), Playlists.end(), rx);
|
||||
}
|
||||
else if (isActiveWindow(Content))
|
||||
{
|
||||
Content.showAll();
|
||||
auto rx = RegexFilter<MPD::Song>(
|
||||
boost::regex(filter, Config.regex_type), SongEntryMatcher);
|
||||
Content.filter(Content.begin(), Content.end(), rx);
|
||||
}
|
||||
}
|
||||
catch (boost::bad_expression &) { }
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
@@ -360,18 +366,27 @@ bool PlaylistEditor::allowsSearching()
|
||||
|
||||
bool PlaylistEditor::search(const std::string &constraint)
|
||||
{
|
||||
bool result = false;
|
||||
if (isActiveWindow(Playlists))
|
||||
try
|
||||
{
|
||||
auto rx = RegexFilter<std::string>(constraint, Config.regex_type, PlaylistEntryMatcher);
|
||||
result = Playlists.search(Playlists.begin(), Playlists.end(), rx);
|
||||
bool result = false;
|
||||
if (isActiveWindow(Playlists))
|
||||
{
|
||||
auto rx = RegexFilter<std::string>(
|
||||
boost::regex(constraint, Config.regex_type), PlaylistEntryMatcher);
|
||||
result = Playlists.search(Playlists.begin(), Playlists.end(), rx);
|
||||
}
|
||||
else if (isActiveWindow(Content))
|
||||
{
|
||||
auto rx = RegexFilter<MPD::Song>(
|
||||
boost::regex(constraint, Config.regex_type), SongEntryMatcher);
|
||||
result = Content.search(Content.begin(), Content.end(), rx);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else if (isActiveWindow(Content))
|
||||
catch (boost::bad_expression &)
|
||||
{
|
||||
auto rx = RegexFilter<MPD::Song>(constraint, Config.regex_type, SongEntryMatcher);
|
||||
result = Content.search(Content.begin(), Content.end(), rx);
|
||||
return false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void PlaylistEditor::nextFound(bool wrap)
|
||||
@@ -523,14 +538,14 @@ std::string SongToString(const MPD::Song &s)
|
||||
return result;
|
||||
}
|
||||
|
||||
bool PlaylistEntryMatcher(const Regex &rx, const std::string &playlist)
|
||||
bool PlaylistEntryMatcher(const boost::regex &rx, const std::string &playlist)
|
||||
{
|
||||
return rx.match(playlist);
|
||||
return boost::regex_search(playlist, rx);
|
||||
}
|
||||
|
||||
bool SongEntryMatcher(const Regex &rx, const MPD::Song &s)
|
||||
bool SongEntryMatcher(const boost::regex &rx, const MPD::Song &s)
|
||||
{
|
||||
return rx.match(SongToString(s));
|
||||
return boost::regex_search(SongToString(s), rx);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,23 +21,19 @@
|
||||
#ifndef NCMPCPP_REGEX_FILTER_H
|
||||
#define NCMPCPP_REGEX_FILTER_H
|
||||
|
||||
#include <boost/regex.hpp>
|
||||
#include "menu.h"
|
||||
#include "regexes.h"
|
||||
|
||||
template <typename T> struct RegexFilter
|
||||
{
|
||||
typedef NC::Menu<T> MenuT;
|
||||
typedef typename NC::Menu<T>::Item Item;
|
||||
typedef std::function<bool(const Regex &, const T &)> FilterFunction;
|
||||
typedef std::function<bool(const boost::regex &, const T &)> FilterFunction;
|
||||
|
||||
RegexFilter(const std::string ®ex_, int cflags, FilterFunction filter)
|
||||
: m_rx(regex_, cflags), m_filter(filter) { }
|
||||
RegexFilter(boost::regex rx, FilterFunction filter)
|
||||
: m_rx(rx), m_filter(filter) { }
|
||||
|
||||
bool operator()(const Item &item) {
|
||||
if (m_rx.regex().empty())
|
||||
return true;
|
||||
if (!m_rx.compiled() || !m_rx.error().empty())
|
||||
return false;
|
||||
return m_filter(m_rx, item.value());
|
||||
}
|
||||
|
||||
@@ -46,12 +42,12 @@ template <typename T> struct RegexFilter
|
||||
std::string filter;
|
||||
auto rf = menu.getFilter().template target< RegexFilter<T> >();
|
||||
if (rf)
|
||||
filter = rf->m_rx.regex();
|
||||
filter = rf->m_rx.str();
|
||||
return filter;
|
||||
}
|
||||
|
||||
private:
|
||||
Regex m_rx;
|
||||
boost::regex m_rx;
|
||||
FilterFunction m_filter;
|
||||
};
|
||||
|
||||
@@ -59,16 +55,12 @@ template <typename T> struct RegexItemFilter
|
||||
{
|
||||
typedef NC::Menu<T> MenuT;
|
||||
typedef typename NC::Menu<T>::Item Item;
|
||||
typedef std::function<bool(const Regex &, const Item &)> FilterFunction;
|
||||
typedef std::function<bool(const boost::regex &, const Item &)> FilterFunction;
|
||||
|
||||
RegexItemFilter(const std::string ®ex_, int cflags, FilterFunction filter)
|
||||
: m_rx(regex_, cflags), m_filter(filter) { }
|
||||
RegexItemFilter(boost::regex rx, FilterFunction filter)
|
||||
: m_rx(rx), m_filter(filter) { }
|
||||
|
||||
bool operator()(const Item &item) {
|
||||
if (m_rx.regex().empty())
|
||||
return true;
|
||||
if (!m_rx.compiled() || !m_rx.error().empty())
|
||||
return false;
|
||||
return m_filter(m_rx, item);
|
||||
}
|
||||
|
||||
@@ -77,12 +69,12 @@ template <typename T> struct RegexItemFilter
|
||||
std::string filter;
|
||||
auto rf = menu.getFilter().template target< RegexItemFilter<T> >();
|
||||
if (rf)
|
||||
filter = rf->m_rx.regex();
|
||||
filter = rf->m_rx.str();
|
||||
return filter;
|
||||
}
|
||||
|
||||
private:
|
||||
Regex m_rx;
|
||||
boost::regex m_rx;
|
||||
FilterFunction m_filter;
|
||||
};
|
||||
|
||||
|
||||
102
src/regexes.cpp
102
src/regexes.cpp
@@ -1,102 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2008-2012 by Andrzej Rybczak *
|
||||
* electricityispower@gmail.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#include <cassert>
|
||||
#include "regexes.h"
|
||||
|
||||
Regex::Regex() : m_cflags(0), m_compiled(false) { }
|
||||
|
||||
Regex::Regex(const std::string ®ex_, int cflags)
|
||||
: m_regex(regex_), m_cflags(cflags), m_compiled(false)
|
||||
{
|
||||
compile();
|
||||
}
|
||||
|
||||
Regex::Regex (const Regex &rhs)
|
||||
: m_regex(rhs.m_regex), m_cflags(rhs.m_cflags), m_compiled(false)
|
||||
{
|
||||
if (rhs.m_compiled)
|
||||
compile();
|
||||
}
|
||||
|
||||
Regex::~Regex()
|
||||
{
|
||||
if (m_compiled)
|
||||
regfree(&m_rx);
|
||||
}
|
||||
|
||||
const std::string &Regex::regex() const
|
||||
{
|
||||
return m_regex;
|
||||
}
|
||||
|
||||
const std::string &Regex::error() const
|
||||
{
|
||||
return m_error;
|
||||
}
|
||||
|
||||
bool Regex::compiled() const
|
||||
{
|
||||
return m_compiled;
|
||||
}
|
||||
|
||||
bool Regex::compile()
|
||||
{
|
||||
if (m_compiled)
|
||||
{
|
||||
m_error.clear();
|
||||
regfree(&m_rx);
|
||||
}
|
||||
int comp_res = regcomp(&m_rx, m_regex.c_str(), m_cflags);
|
||||
bool result = true;
|
||||
if (comp_res != 0)
|
||||
{
|
||||
char buf[256];
|
||||
regerror(comp_res, &m_rx, buf, sizeof(buf));
|
||||
m_error = buf;
|
||||
result = false;
|
||||
}
|
||||
m_compiled = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Regex::compile(const std::string ®ex_, int cflags)
|
||||
{
|
||||
m_regex = regex_;
|
||||
m_cflags = cflags;
|
||||
return compile();
|
||||
}
|
||||
|
||||
bool Regex::match(const std::string &s) const
|
||||
{
|
||||
assert(m_compiled);
|
||||
return regexec(&m_rx, s.c_str(), 0, 0, 0) == 0;
|
||||
}
|
||||
|
||||
Regex &Regex::operator=(const Regex &rhs)
|
||||
{
|
||||
if (this == &rhs)
|
||||
return *this;
|
||||
m_regex = rhs.m_regex;
|
||||
m_cflags = rhs.m_cflags;
|
||||
if (rhs.m_compiled)
|
||||
compile();
|
||||
return *this;
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2008-2012 by Andrzej Rybczak *
|
||||
* electricityispower@gmail.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef NCMPCPP_REGEXES_H
|
||||
#define NCMPCPP_REGEXES_H
|
||||
|
||||
#include <regex.h>
|
||||
#include <string>
|
||||
|
||||
struct Regex
|
||||
{
|
||||
Regex();
|
||||
Regex(const std::string ®ex, int cflags);
|
||||
Regex(const Regex &rhs);
|
||||
virtual ~Regex();
|
||||
|
||||
/// @return regular expression
|
||||
const std::string ®ex() const;
|
||||
|
||||
/// @return compilation error (if there was any)
|
||||
const std::string &error() const;
|
||||
|
||||
/// @return true if regular expression is compiled, false otherwise
|
||||
bool compiled() const;
|
||||
|
||||
/// compiles regular expression
|
||||
/// @result true if compilation was successful, false otherwise
|
||||
bool compile();
|
||||
|
||||
/// compiles regular expression
|
||||
/// @result true if compilation was successful, false otherwise
|
||||
bool compile(const std::string ®ex, int cflags);
|
||||
|
||||
/// tries to match compiled regex with given string
|
||||
/// @return true if string was matched, false otherwise
|
||||
bool match(const std::string &s) const;
|
||||
|
||||
Regex &operator=(const Regex &rhs);
|
||||
|
||||
private:
|
||||
std::string m_regex;
|
||||
std::string m_error;
|
||||
regex_t m_rx;
|
||||
int m_cflags;
|
||||
bool m_compiled;
|
||||
};
|
||||
|
||||
#endif // NCMPCPP_REGEXES_H
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include <array>
|
||||
#include <iomanip>
|
||||
#include <regex.h>
|
||||
|
||||
#include "display.h"
|
||||
#include "global.h"
|
||||
@@ -71,7 +72,7 @@ namespace pos {//
|
||||
}*/
|
||||
|
||||
std::string SEItemToString(const SEItem &ei);
|
||||
bool SEItemEntryMatcher(const Regex &rx, const NC::Menu<SEItem>::Item &item, bool filter);
|
||||
bool SEItemEntryMatcher(const boost::regex &rx, const NC::Menu<SEItem>::Item &item, bool filter);
|
||||
|
||||
}
|
||||
|
||||
@@ -264,10 +265,15 @@ std::string SearchEngine::currentFilter()
|
||||
|
||||
void SearchEngine::applyFilter(const std::string &filter)
|
||||
{
|
||||
w.showAll();
|
||||
auto fun = std::bind(SEItemEntryMatcher, _1, _2, true);
|
||||
auto rx = RegexItemFilter<SEItem>(filter, Config.regex_type, fun);
|
||||
w.filter(w.begin(), w.end(), rx);
|
||||
try
|
||||
{
|
||||
w.showAll();
|
||||
auto fun = std::bind(SEItemEntryMatcher, _1, _2, true);
|
||||
auto rx = RegexItemFilter<SEItem>(
|
||||
boost::regex(filter, Config.regex_type), fun);
|
||||
w.filter(w.begin(), w.end(), rx);
|
||||
}
|
||||
catch (boost::bad_expression &) { }
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
@@ -279,9 +285,17 @@ bool SearchEngine::allowsSearching()
|
||||
|
||||
bool SearchEngine::search(const std::string &constraint)
|
||||
{
|
||||
auto fun = std::bind(SEItemEntryMatcher, _1, _2, false);
|
||||
auto rx = RegexItemFilter<SEItem>(constraint, Config.regex_type, fun);
|
||||
return w.search(w.begin(), w.end(), rx);
|
||||
try
|
||||
{
|
||||
auto fun = std::bind(SEItemEntryMatcher, _1, _2, false);
|
||||
auto rx = RegexItemFilter<SEItem>(
|
||||
boost::regex(constraint, Config.regex_type), fun);
|
||||
return w.search(w.begin(), w.end(), rx);
|
||||
}
|
||||
catch (boost::bad_expression &)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void SearchEngine::nextFound(bool wrap)
|
||||
@@ -574,11 +588,11 @@ std::string SEItemToString(const SEItem &ei)
|
||||
return result;
|
||||
}
|
||||
|
||||
bool SEItemEntryMatcher(const Regex &rx, const NC::Menu<SEItem>::Item &item, bool filter)
|
||||
bool SEItemEntryMatcher(const boost::regex &rx, const NC::Menu<SEItem>::Item &item, bool filter)
|
||||
{
|
||||
if (item.isSeparator() || !item.value().isSong())
|
||||
return filter;
|
||||
return rx.match(SEItemToString(item.value()));
|
||||
return boost::regex_search(SEItemToString(item.value()), rx);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -228,7 +228,7 @@ void Configuration::SetDefaults()
|
||||
playlist_disable_highlight_delay = 5;
|
||||
message_delay_time = 4;
|
||||
lyrics_db = 0;
|
||||
regex_type = REG_ICASE;
|
||||
regex_type = boost::regex::icase;
|
||||
lines_scrolled = 2;
|
||||
search_engine_default_search_mode = 0;
|
||||
visualizer_sync_interval = 30;
|
||||
@@ -782,8 +782,12 @@ void Configuration::Read()
|
||||
}
|
||||
else if (name == "regular_expressions")
|
||||
{
|
||||
if (v != "basic")
|
||||
regex_type |= REG_EXTENDED;
|
||||
if (v == "none")
|
||||
regex_type |= boost::regex::literal;
|
||||
else if (v == "basic")
|
||||
regex_type |= boost::regex::basic;
|
||||
else if (v == "extended")
|
||||
regex_type |= boost::regex::extended;
|
||||
}
|
||||
else if (name == "lines_scrolled")
|
||||
{
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#ifndef NCMPCPP_SETTINGS_H
|
||||
#define NCMPCPP_SETTINGS_H
|
||||
|
||||
#include <boost/regex.hpp>
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
#include <mpd/client.h>
|
||||
@@ -193,7 +194,8 @@ struct Configuration
|
||||
int playlist_disable_highlight_delay;
|
||||
int message_delay_time;
|
||||
int lyrics_db;
|
||||
int regex_type;
|
||||
|
||||
boost::regex::flag_type regex_type;
|
||||
|
||||
unsigned lines_scrolled;
|
||||
unsigned search_engine_default_search_mode;
|
||||
|
||||
@@ -81,8 +81,8 @@ std::string GenerateFilename(const MPD::MutableSong &s, const std::string &patte
|
||||
std::string ParseFilename(MPD::MutableSong &s, std::string mask, bool preview);
|
||||
|
||||
std::string SongToString(const MPD::MutableSong &s);
|
||||
bool DirEntryMatcher(const Regex &rx, const std::pair<std::string, std::string> &dir, bool filter);
|
||||
bool SongEntryMatcher(const Regex &rx, const MPD::MutableSong &s);
|
||||
bool DirEntryMatcher(const boost::regex &rx, const std::pair<std::string, std::string> &dir, bool filter);
|
||||
bool SongEntryMatcher(const boost::regex &rx, const MPD::MutableSong &s);
|
||||
|
||||
}
|
||||
|
||||
@@ -740,19 +740,25 @@ std::string TagEditor::currentFilter()
|
||||
|
||||
void TagEditor::applyFilter(const std::string &filter)
|
||||
{
|
||||
if (w == Dirs)
|
||||
try
|
||||
{
|
||||
Dirs->showAll();
|
||||
auto fun = std::bind(DirEntryMatcher, _1, _2, true);
|
||||
auto rx = RegexFilter< std::pair<std::string, std::string> >(filter, Config.regex_type, fun);
|
||||
Dirs->filter(Dirs->begin(), Dirs->end(), rx);
|
||||
}
|
||||
else if (w == Tags)
|
||||
{
|
||||
Tags->showAll();
|
||||
auto rx = RegexFilter<MPD::MutableSong>(filter, Config.regex_type, SongEntryMatcher);
|
||||
Tags->filter(Tags->begin(), Tags->end(), rx);
|
||||
if (w == Dirs)
|
||||
{
|
||||
Dirs->showAll();
|
||||
auto fun = std::bind(DirEntryMatcher, _1, _2, true);
|
||||
auto rx = RegexFilter< std::pair<std::string, std::string> >(
|
||||
boost::regex(filter, Config.regex_type), fun);
|
||||
Dirs->filter(Dirs->begin(), Dirs->end(), rx);
|
||||
}
|
||||
else if (w == Tags)
|
||||
{
|
||||
Tags->showAll();
|
||||
auto rx = RegexFilter<MPD::MutableSong>(
|
||||
boost::regex(filter, Config.regex_type), SongEntryMatcher);
|
||||
Tags->filter(Tags->begin(), Tags->end(), rx);
|
||||
}
|
||||
}
|
||||
catch (boost::bad_expression &) { }
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
@@ -764,19 +770,28 @@ bool TagEditor::allowsSearching()
|
||||
|
||||
bool TagEditor::search(const std::string &constraint)
|
||||
{
|
||||
bool result = false;
|
||||
if (w == Dirs)
|
||||
try
|
||||
{
|
||||
auto fun = std::bind(DirEntryMatcher, _1, _2, false);
|
||||
auto rx = RegexFilter< std::pair<std::string, std::string> >(constraint, Config.regex_type, fun);
|
||||
result = Dirs->search(Dirs->begin(), Dirs->end(), rx);
|
||||
bool result = false;
|
||||
if (w == Dirs)
|
||||
{
|
||||
auto fun = std::bind(DirEntryMatcher, _1, _2, false);
|
||||
auto rx = RegexFilter< std::pair<std::string, std::string> >(
|
||||
boost::regex(constraint, Config.regex_type), fun);
|
||||
result = Dirs->search(Dirs->begin(), Dirs->end(), rx);
|
||||
}
|
||||
else if (w == Tags)
|
||||
{
|
||||
auto rx = RegexFilter<MPD::MutableSong>(
|
||||
boost::regex(constraint, Config.regex_type), SongEntryMatcher);
|
||||
result = Tags->search(Tags->begin(), Tags->end(), rx);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else if (w == Tags)
|
||||
catch (boost::bad_expression &)
|
||||
{
|
||||
auto rx = RegexFilter<MPD::MutableSong>(constraint, Config.regex_type, SongEntryMatcher);
|
||||
result = Tags->search(Tags->begin(), Tags->end(), rx);
|
||||
return false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void TagEditor::nextFound(bool wrap)
|
||||
@@ -1169,16 +1184,16 @@ std::string SongToString(const MPD::MutableSong &s)
|
||||
return result.empty() ? Config.empty_tag : result;
|
||||
}
|
||||
|
||||
bool DirEntryMatcher(const Regex &rx, const std::pair<std::string, std::string> &dir, bool filter)
|
||||
bool DirEntryMatcher(const boost::regex &rx, const std::pair<std::string, std::string> &dir, bool filter)
|
||||
{
|
||||
if (dir.first == "." || dir.first == "..")
|
||||
return filter;
|
||||
return rx.match(dir.first);
|
||||
return boost::regex_search(dir.first, rx);
|
||||
}
|
||||
|
||||
bool SongEntryMatcher(const Regex &rx, const MPD::MutableSong &s)
|
||||
bool SongEntryMatcher(const boost::regex &rx, const MPD::MutableSong &s)
|
||||
{
|
||||
return rx.match(SongToString(s));
|
||||
return boost::regex_search(SongToString(s), rx);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user