diff options
author | Andrzej Rybczak <electricityispower@gmail.com> | 2015-04-13 01:43:07 +0200 |
---|---|---|
committer | Andrzej Rybczak <electricityispower@gmail.com> | 2015-04-18 17:41:10 +0200 |
commit | a21d9ca4250d93d12fb70bdf5a01169ec753e4b9 (patch) | |
tree | e7ceee4c4b39fed8bae8273f408d484962adf70e /src | |
parent | 4a372c0fbb130e8cb5b5a4bb200132c6928b4472 (diff) |
format: split into two headers
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/display.cpp | 1 | ||||
-rw-r--r-- | src/format.cpp | 2 | ||||
-rw-r--r-- | src/format.h | 223 | ||||
-rw-r--r-- | src/format_impl.h | 263 | ||||
-rw-r--r-- | src/lyrics.cpp | 1 | ||||
-rw-r--r-- | src/settings.cpp | 1 | ||||
-rw-r--r-- | src/status.cpp | 1 | ||||
-rw-r--r-- | src/utility/comparators.cpp | 1 |
9 files changed, 274 insertions, 220 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 4e4530b7..aa945017 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -73,6 +73,7 @@ noinst_HEADERS = \ display.h \ enums.h \ format.h \ + format_impl.h \ global.h \ help.h \ helpers.h \ diff --git a/src/display.cpp b/src/display.cpp index 83a1b3bf..6241068e 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -23,6 +23,7 @@ #include "browser.h" #include "charset.h" #include "display.h" +#include "format_impl.h" #include "helpers.h" #include "song_info.h" #include "playlist.h" diff --git a/src/format.cpp b/src/format.cpp index 329df462..b1924fce 100644 --- a/src/format.cpp +++ b/src/format.cpp @@ -20,7 +20,7 @@ #include <stdexcept> -#include "format.h" +#include "format_impl.h" #include "utility/type_conversions.h" namespace { diff --git a/src/format.h b/src/format.h index 378943e4..17cf23e0 100644 --- a/src/format.h +++ b/src/format.h @@ -25,9 +25,6 @@ #include "menu.h" #include "song.h" -#include "strbuffer.h" -#include "utility/functional.h" -#include "utility/wide_string.h" namespace Format { @@ -65,39 +62,6 @@ private: enum class Result { Empty, Missing, Ok }; -// Commutative binary operation such that: -// - Empty + Empty = Empty -// - Empty + Missing = Missing -// - Empty + Ok = Ok -// - Missing + Missing = Missing -// - Missing + Ok = Missing -// - Ok + Ok = Ok -inline Result &operator+=(Result &base, Result result) -{ - if (base == Result::Missing || result == Result::Missing) - base = Result::Missing; - else if (base == Result::Ok || result == Result::Ok) - base = Result::Ok; - return base; -} - -/*inline std::ostream &operator<<(std::ostream &os, Result r) -{ - switch (r) - { - case Result::Empty: - os << "empty"; - break; - case Result::Missing: - os << "missing"; - break; - case Result::Ok: - os << "ok"; - break; - } - return os; -}*/ - template <typename CharT> using Expression = boost::variant< std::basic_string<CharT>, @@ -126,198 +90,19 @@ private: Base m_base; }; -template <typename CharT, typename OutputT, typename SecondOutputT = OutputT> -struct Printer: boost::static_visitor<Result> -{ - typedef std::basic_string<CharT> StringT; - - Printer(OutputT &os, const MPD::Song *song, SecondOutputT *second_os, const unsigned flags) - : m_output(os) - , m_song(song) - , m_output_switched(false) - , m_second_os(second_os) - , m_no_output(0) - , m_flags(flags) - { } - - Result operator()(const StringT &s) - { - if (!s.empty()) - { - output(s); - return Result::Ok; - } - else - return Result::Empty; - } - - Result operator()(const NC::Color &c) - { - if (m_flags & Flags::Color) - output(c); - return Result::Empty; - } - - Result operator()(NC::Format fmt) - { - if (m_flags & Flags::Format) - output(fmt); - return Result::Empty; - } - - Result operator()(OutputSwitch) - { - if (!m_no_output) - m_output_switched = true; - return Result::Ok; - } - - Result operator()(const SongTag &st) - { - StringT tags; - if (m_flags & Flags::Tag && m_song != nullptr) - { - tags = convertString<CharT, char>::apply( - m_song->getTags(st.function()) - ); - } - if (!tags.empty()) - { - if (st.delimiter() > 0) - { - // shorten length by chopping off the tail - if (st.function() == &MPD::Song::getLength) - tags.resize(st.delimiter()); - else - tags = wideShorten(tags, st.delimiter()); - } - output(tags); - return Result::Ok; - } - else - return Result::Missing; - } - - // If all Empty -> Empty, if any Ok -> continue with Ok, if any Missing -> stop with Empty. - Result operator()(const Group<CharT> &group) - { - auto visit = [this, &group] { - Result result = Result::Empty; - for (const auto &ex : group.base()) - { - result += boost::apply_visitor(*this, ex); - if (result == Result::Missing) - { - result = Result::Empty; - break; - } - } - return result; - }; - - ++m_no_output; - Result result = visit(); - --m_no_output; - if (!m_no_output && result == Result::Ok) - visit(); - return result; - } - - // If all Empty or Missing -> Empty, if any Ok -> stop with Ok. - Result operator()(const FirstOf<CharT> &first_of) - { - for (const auto &ex : first_of.base()) - { - if (boost::apply_visitor(*this, ex) == Result::Ok) - return Result::Ok; - } - return Result::Empty; - } - -private: - // generic version for streams (buffers, menus) - template <typename ValueT, typename OutputStreamT> - struct output_ { - static void exec(OutputStreamT &os, const ValueT &value) { - os << value; - } - }; - // specialization for strings (input/output) - template <typename SomeCharT, typename OtherCharT> - struct output_<std::basic_string<SomeCharT>, std::basic_string<OtherCharT>> { - typedef std::basic_string<SomeCharT> SomeString; - typedef std::basic_string<OtherCharT> OtherString; - - // compile only if string types are the same - static typename std::enable_if< - std::is_same<SomeString, OtherString>::value, - void - >::type exec(SomeString &result, const OtherString &s) { - result += s; - } - }; - // when writing to a string, we should ignore all other - // properties. if this code is reached, throw an exception. - template <typename ValueT, typename SomeCharT> - struct output_<ValueT, std::basic_string<SomeCharT>> { - static void exec(std::basic_string<CharT> &, const ValueT &) { - throw std::logic_error("non-string property can't be appended to the string"); - } - }; - - template <typename ValueT> - void output(const ValueT &value) const - { - if (!m_no_output) - { - if (m_output_switched && m_second_os != nullptr) - output_<ValueT, SecondOutputT>::exec(*m_second_os, value); - else - output_<ValueT, OutputT>::exec(m_output, value); - } - } - - OutputT &m_output; - const MPD::Song *m_song; - - bool m_output_switched; - SecondOutputT *m_second_os; - - unsigned m_no_output; - const unsigned m_flags; -}; - template <typename CharT, typename VisitorT> -void visit(VisitorT &visitor, const AST<CharT> &ast) -{ - for (const auto &ex : ast.base()) - boost::apply_visitor(visitor, ex); -} +void visit(VisitorT &visitor, const AST<CharT> &ast); template <typename CharT, typename ItemT> void print(const AST<CharT> &ast, NC::Menu<ItemT> &menu, const MPD::Song *song, - NC::BasicBuffer<CharT> *buffer, const unsigned flags = Flags::All) -{ - Printer<CharT, NC::Menu<ItemT>, NC::Buffer> printer(menu, song, buffer, flags); - visit(printer, ast); -} + NC::BasicBuffer<CharT> *buffer, const unsigned flags = Flags::All); template <typename CharT> void print(const AST<CharT> &ast, NC::BasicBuffer<CharT> &buffer, - const MPD::Song *song, const unsigned flags = Flags::All) -{ - Printer<CharT, NC::BasicBuffer<CharT>> printer(buffer, song, &buffer, flags); - visit(printer, ast); -} + const MPD::Song *song, const unsigned flags = Flags::All); template <typename CharT> -std::basic_string<CharT> stringify(const AST<CharT> &ast, const MPD::Song *song) -{ - std::basic_string<CharT> result; - Printer<CharT, std::basic_string<CharT>> printer(result, song, &result, Flags::Tag); - visit(printer, ast); - return result; -} +std::basic_string<CharT> stringify(const AST<CharT> &ast, const MPD::Song *song); AST<char> parse(const std::string &s, const unsigned flags = Flags::All); AST<wchar_t> parse(const std::wstring &ws, const unsigned flags = Flags::All); diff --git a/src/format_impl.h b/src/format_impl.h new file mode 100644 index 00000000..ec9ad973 --- /dev/null +++ b/src/format_impl.h @@ -0,0 +1,263 @@ +/*************************************************************************** + * Copyright (C) 2008-2014 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_HAVE_FORMAT_IMPL_H +#define NCMPCPP_HAVE_FORMAT_IMPL_H + +#include <boost/variant.hpp> + +#include "format.h" +#include "menu.h" +#include "song.h" +#include "strbuffer.h" +#include "utility/functional.h" +#include "utility/wide_string.h" + +namespace Format { + +// Commutative binary operation such that: +// - Empty + Empty = Empty +// - Empty + Missing = Missing +// - Empty + Ok = Ok +// - Missing + Missing = Missing +// - Missing + Ok = Missing +// - Ok + Ok = Ok +inline Result &operator+=(Result &base, Result result) +{ + if (base == Result::Missing || result == Result::Missing) + base = Result::Missing; + else if (base == Result::Ok || result == Result::Ok) + base = Result::Ok; + return base; +} + +/*inline std::ostream &operator<<(std::ostream &os, Result r) +{ + switch (r) + { + case Result::Empty: + os << "empty"; + break; + case Result::Missing: + os << "missing"; + break; + case Result::Ok: + os << "ok"; + break; + } + return os; +}*/ + +template <typename CharT, typename OutputT, typename SecondOutputT = OutputT> +struct Printer: boost::static_visitor<Result> +{ + typedef std::basic_string<CharT> StringT; + + Printer(OutputT &os, const MPD::Song *song, SecondOutputT *second_os, const unsigned flags) + : m_output(os) + , m_song(song) + , m_output_switched(false) + , m_second_os(second_os) + , m_no_output(0) + , m_flags(flags) + { } + + Result operator()(const StringT &s) + { + if (!s.empty()) + { + output(s); + return Result::Ok; + } + else + return Result::Empty; + } + + Result operator()(const NC::Color &c) + { + if (m_flags & Flags::Color) + output(c); + return Result::Empty; + } + + Result operator()(NC::Format fmt) + { + if (m_flags & Flags::Format) + output(fmt); + return Result::Empty; + } + + Result operator()(OutputSwitch) + { + if (!m_no_output) + m_output_switched = true; + return Result::Ok; + } + + Result operator()(const SongTag &st) + { + StringT tags; + if (m_flags & Flags::Tag && m_song != nullptr) + { + tags = convertString<CharT, char>::apply( + m_song->getTags(st.function()) + ); + } + if (!tags.empty()) + { + if (st.delimiter() > 0) + { + // shorten length by chopping off the tail + if (st.function() == &MPD::Song::getLength) + tags.resize(st.delimiter()); + else + tags = wideShorten(tags, st.delimiter()); + } + output(tags); + return Result::Ok; + } + else + return Result::Missing; + } + + // If all Empty -> Empty, if any Ok -> continue with Ok, if any Missing -> stop with Empty. + Result operator()(const Group<CharT> &group) + { + auto visit = [this, &group] { + Result result = Result::Empty; + for (const auto &ex : group.base()) + { + result += boost::apply_visitor(*this, ex); + if (result == Result::Missing) + { + result = Result::Empty; + break; + } + } + return result; + }; + + ++m_no_output; + Result result = visit(); + --m_no_output; + if (!m_no_output && result == Result::Ok) + visit(); + return result; + } + + // If all Empty or Missing -> Empty, if any Ok -> stop with Ok. + Result operator()(const FirstOf<CharT> &first_of) + { + for (const auto &ex : first_of.base()) + { + if (boost::apply_visitor(*this, ex) == Result::Ok) + return Result::Ok; + } + return Result::Empty; + } + +private: + // generic version for streams (buffers, menus) + template <typename ValueT, typename OutputStreamT> + struct output_ { + static void exec(OutputStreamT &os, const ValueT &value) { + os << value; + } + }; + // specialization for strings (input/output) + template <typename SomeCharT, typename OtherCharT> + struct output_<std::basic_string<SomeCharT>, std::basic_string<OtherCharT>> { + typedef std::basic_string<SomeCharT> SomeString; + typedef std::basic_string<OtherCharT> OtherString; + + // compile only if string types are the same + static typename std::enable_if< + std::is_same<SomeString, OtherString>::value, + void + >::type exec(SomeString &result, const OtherString &s) { + result += s; + } + }; + // when writing to a string, we should ignore all other + // properties. if this code is reached, throw an exception. + template <typename ValueT, typename SomeCharT> + struct output_<ValueT, std::basic_string<SomeCharT>> { + static void exec(std::basic_string<CharT> &, const ValueT &) { + throw std::logic_error("non-string property can't be appended to the string"); + } + }; + + template <typename ValueT> + void output(const ValueT &value) const + { + if (!m_no_output) + { + if (m_output_switched && m_second_os != nullptr) + output_<ValueT, SecondOutputT>::exec(*m_second_os, value); + else + output_<ValueT, OutputT>::exec(m_output, value); + } + } + + OutputT &m_output; + const MPD::Song *m_song; + + bool m_output_switched; + SecondOutputT *m_second_os; + + unsigned m_no_output; + const unsigned m_flags; +}; + +template <typename CharT, typename VisitorT> +void visit(VisitorT &visitor, const AST<CharT> &ast) +{ + for (const auto &ex : ast.base()) + boost::apply_visitor(visitor, ex); +} + +template <typename CharT, typename ItemT> +void print(const AST<CharT> &ast, NC::Menu<ItemT> &menu, const MPD::Song *song, + NC::BasicBuffer<CharT> *buffer, const unsigned flags) +{ + Printer<CharT, NC::Menu<ItemT>, NC::Buffer> printer(menu, song, buffer, flags); + visit(printer, ast); +} + +template <typename CharT> +void print(const AST<CharT> &ast, NC::BasicBuffer<CharT> &buffer, + const MPD::Song *song, const unsigned flags) +{ + Printer<CharT, NC::BasicBuffer<CharT>> printer(buffer, song, &buffer, flags); + visit(printer, ast); +} + +template <typename CharT> +std::basic_string<CharT> stringify(const AST<CharT> &ast, const MPD::Song *song) +{ + std::basic_string<CharT> result; + Printer<CharT, std::basic_string<CharT>> printer(result, song, &result, Flags::Tag); + visit(printer, ast); + return result; +} + +} + +#endif // NCMPCPP_HAVE_FORMAT__IMPL_H diff --git a/src/lyrics.cpp b/src/lyrics.cpp index b8db4287..7f470c13 100644 --- a/src/lyrics.cpp +++ b/src/lyrics.cpp @@ -26,6 +26,7 @@ #include "browser.h" #include "charset.h" #include "curl_handle.h" +#include "format_impl.h" #include "global.h" #include "helpers.h" #include "lyrics.h" diff --git a/src/settings.cpp b/src/settings.cpp index a42dbc35..77c2e31f 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -23,6 +23,7 @@ #include <stdexcept> #include "configuration.h" +#include "format_impl.h" #include "helpers.h" #include "settings.h" #include "utility/conversion.h" diff --git a/src/status.cpp b/src/status.cpp index 51ede82e..8db7a6d6 100644 --- a/src/status.cpp +++ b/src/status.cpp @@ -24,6 +24,7 @@ #include "browser.h" #include "charset.h" +#include "format_impl.h" #include "global.h" #include "helpers.h" #include "lyrics.h" diff --git a/src/utility/comparators.cpp b/src/utility/comparators.cpp index 85ada86f..533cd389 100644 --- a/src/utility/comparators.cpp +++ b/src/utility/comparators.cpp @@ -20,6 +20,7 @@ #include <locale> #include "comparators.h" +#include "format_impl.h" #include "utility/string.h" namespace { |