From 4a47bbd8166a573bf96f175d1135f1f64a599f56 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 9 Aug 2019 15:03:07 +0200 Subject: [PATCH] IcyMetadataParser: implement charset conversion --- src/IcyMetaDataParser.cxx | 47 +++++++++++++++++++++++++++++++++++---- src/IcyMetaDataParser.hxx | 13 +++++++++++ test/meson.build | 1 + test/test_icy_parser.cxx | 6 ++++- 4 files changed, 62 insertions(+), 5 deletions(-) diff --git a/src/IcyMetaDataParser.cxx b/src/IcyMetaDataParser.cxx index 580cdfa81..2c8f1c9db 100644 --- a/src/IcyMetaDataParser.cxx +++ b/src/IcyMetaDataParser.cxx @@ -19,6 +19,7 @@ #include "IcyMetaDataParser.hxx" #include "tag/Builder.hxx" +#include "util/AllocatedString.hxx" #include "util/StringView.hxx" #include @@ -26,6 +27,16 @@ #include #include +#ifdef HAVE_ICU_CONVERTER + +void +IcyMetaDataParser::SetCharset(const char *charset) +{ + icu_converter.reset(IcuConverter::Create(charset)); +} + +#endif + void IcyMetaDataParser::Reset() noexcept { @@ -76,10 +87,26 @@ icy_add_item(TagBuilder &tag, TagType type, StringView value) noexcept static void icy_parse_tag_item(TagBuilder &tag, +#ifdef HAVE_ICU_CONVERTER + const IcuConverter *icu_converter, +#endif const char *name, const char *value) noexcept { - if (strcmp(name, "StreamTitle") == 0) + if (strcmp(name, "StreamTitle") == 0) { +#ifdef HAVE_ICU_CONVERTER + if (icu_converter != nullptr) { + try { + icy_add_item(tag, TAG_TITLE, + icu_converter->ToUTF8(value).c_str()); + } catch (...) { + } + + return; + } +#endif + icy_add_item(tag, TAG_TITLE, value); + } } /** @@ -108,7 +135,11 @@ find_end_quote(char *p, char *const end) noexcept } static std::unique_ptr -icy_parse_tag(char *p, char *const end) noexcept +icy_parse_tag( +#ifdef HAVE_ICU_CONVERTER + const IcuConverter *icu_converter, +#endif + char *p, char *const end) noexcept { assert(p != nullptr); assert(end != nullptr); @@ -145,7 +176,11 @@ icy_parse_tag(char *p, char *const end) noexcept *quote = 0; p = quote + 1; - icy_parse_tag_item(tag, name, value); + icy_parse_tag_item(tag, +#ifdef HAVE_ICU_CONVERTER + icu_converter, +#endif + name, value); char *semicolon = std::find(p, end, ';'); if (semicolon == end) @@ -200,7 +235,11 @@ IcyMetaDataParser::Meta(const void *data, size_t length) noexcept if (meta_position == meta_size) { /* parse */ - tag = icy_parse_tag(meta_data, meta_data + meta_size); + tag = icy_parse_tag( +#ifdef HAVE_ICU_CONVERTER + icu_converter.get(), +#endif + meta_data, meta_data + meta_size); delete[] meta_data; /* change back to normal data mode */ diff --git a/src/IcyMetaDataParser.hxx b/src/IcyMetaDataParser.hxx index b490f9782..1bcf1ec6f 100644 --- a/src/IcyMetaDataParser.hxx +++ b/src/IcyMetaDataParser.hxx @@ -20,7 +20,9 @@ #ifndef MPD_ICY_META_DATA_PARSER_HXX #define MPD_ICY_META_DATA_PARSER_HXX +#include "lib/icu/Converter.hxx" #include "tag/Tag.hxx" +#include "config.h" #include @@ -32,6 +34,10 @@ class IcyMetaDataParser { size_t meta_size, meta_position; char *meta_data; +#ifdef HAVE_ICU_CONVERTER + std::unique_ptr icu_converter; +#endif + std::unique_ptr tag; public: @@ -39,6 +45,13 @@ public: Reset(); } +#ifdef HAVE_ICU_CONVERTER + /** + * Throws on error. + */ + void SetCharset(const char *charset); +#endif + /** * Initialize an enabled icy_metadata object with the specified * data_size (from the icy-metaint HTTP response header). diff --git a/test/meson.build b/test/meson.build index 66f7e88d0..247a2b5d4 100644 --- a/test/meson.build +++ b/test/meson.build @@ -335,6 +335,7 @@ if curl_dep.found() '../src/LogBackend.cxx', include_directories: inc, dependencies: [ + icu_dep, tag_dep, gtest_dep, ], diff --git a/test/test_icy_parser.cxx b/test/test_icy_parser.cxx index 867c38eb8..a9e73e16e 100644 --- a/test/test_icy_parser.cxx +++ b/test/test_icy_parser.cxx @@ -18,7 +18,11 @@ icy_parse_tag(const char *p) { char *q = strdup(p); AtScopeExit(q) { free(q); }; - return icy_parse_tag(q, q + strlen(q)); + return icy_parse_tag( +#ifdef HAVE_ICU_CONVERTER + nullptr, +#endif + q, q + strlen(q)); } static void