diff options
author | Max Kellermann <max@musicpd.org> | 2018-01-21 20:31:59 +0100 |
---|---|---|
committer | Max Kellermann <max@musicpd.org> | 2018-01-23 16:48:43 +0100 |
commit | 1da64fb79c8aa327fd62b3eedf832efbf3d420d0 (patch) | |
tree | 848ab50d230af0d5c063ed8bb505611ddd8d12d4 /src | |
parent | 8b42fd0a2876b44c6c68f874495693b9466cb5b7 (diff) |
lib/curl/Delegate: helper class for response body parsers
Eliminate duplicate code.
Diffstat (limited to 'src')
-rw-r--r-- | src/input/plugins/TidalErrorParser.cxx | 12 | ||||
-rw-r--r-- | src/input/plugins/TidalErrorParser.hxx | 20 | ||||
-rw-r--r-- | src/input/plugins/TidalLoginRequest.cxx | 76 | ||||
-rw-r--r-- | src/input/plugins/TidalLoginRequest.hxx | 42 | ||||
-rw-r--r-- | src/input/plugins/TidalTrackRequest.cxx | 74 | ||||
-rw-r--r-- | src/input/plugins/TidalTrackRequest.hxx | 42 | ||||
-rw-r--r-- | src/lib/curl/Delegate.cxx | 54 | ||||
-rw-r--r-- | src/lib/curl/Delegate.hxx | 73 | ||||
-rw-r--r-- | src/lib/curl/Parser.hxx | 42 | ||||
-rw-r--r-- | src/lib/yajl/ResponseParser.cxx | 43 | ||||
-rw-r--r-- | src/lib/yajl/ResponseParser.hxx | 52 |
11 files changed, 370 insertions, 160 deletions
diff --git a/src/input/plugins/TidalErrorParser.cxx b/src/input/plugins/TidalErrorParser.cxx index 71d523660..149037786 100644 --- a/src/input/plugins/TidalErrorParser.cxx +++ b/src/input/plugins/TidalErrorParser.cxx @@ -40,8 +40,8 @@ static constexpr yajl_callbacks tidal_error_parser_callbacks = { TidalErrorParser::TidalErrorParser(unsigned _status, const std::multimap<std::string, std::string> &headers) - :status(_status), - parser(&tidal_error_parser_callbacks, nullptr, this) + :YajlResponseParser(&tidal_error_parser_callbacks, nullptr, this), + status(_status) { auto i = headers.find("content-type"); if (i == headers.end() || i->second.find("/json") == i->second.npos) @@ -49,15 +49,9 @@ TidalErrorParser::TidalErrorParser(unsigned _status, } void -TidalErrorParser::OnData(ConstBuffer<void> data) -{ - parser.Parse((const unsigned char *)data.data, data.size); -} - -void TidalErrorParser::OnEnd() { - parser.CompleteParse(); + YajlResponseParser::OnEnd(); if (!message.empty()) throw FormatRuntimeError("Error from Tidal: %s", diff --git a/src/input/plugins/TidalErrorParser.hxx b/src/input/plugins/TidalErrorParser.hxx index 0ccf2fe8a..969ec0cf9 100644 --- a/src/input/plugins/TidalErrorParser.hxx +++ b/src/input/plugins/TidalErrorParser.hxx @@ -21,9 +21,8 @@ #define TIDAL_ERROR_PARSER_HXX #include "check.h" -#include "lib/yajl/Handle.hxx" +#include "lib/yajl/ResponseParser.hxx" -#include <exception> #include <string> #include <map> @@ -33,11 +32,9 @@ struct StringView; /** * Parse an error JSON response. */ -class TidalErrorParser { +class TidalErrorParser final : public YajlResponseParser { const unsigned status; - Yajl::Handle parser; - enum class State { NONE, USER_MESSAGE, @@ -53,16 +50,9 @@ public: TidalErrorParser(unsigned status, const std::multimap<std::string, std::string> &headers); - /** - * Feed response body data into the JSON parser. - */ - void OnData(ConstBuffer<void> data); - - /** - * Throw an exception describing the error condition. Call - * this at the end of the response body. - */ - void OnEnd(); +protected: + /* virtual methods from CurlResponseParser */ + void OnEnd() override; public: /* yajl callbacks */ diff --git a/src/input/plugins/TidalLoginRequest.cxx b/src/input/plugins/TidalLoginRequest.cxx index e378ef9ad..71c04112f 100644 --- a/src/input/plugins/TidalLoginRequest.cxx +++ b/src/input/plugins/TidalLoginRequest.cxx @@ -21,10 +21,12 @@ #include "TidalLoginRequest.hxx" #include "TidalErrorParser.hxx" #include "lib/curl/Form.hxx" +#include "lib/yajl/Handle.hxx" #include "lib/yajl/Callbacks.hxx" +#include "lib/yajl/ResponseParser.hxx" #include "util/RuntimeError.hxx" -using Wrapper = Yajl::CallbacksWrapper<TidalLoginRequest>; +using Wrapper = Yajl::CallbacksWrapper<TidalLoginRequest::ResponseParser>; static constexpr yajl_callbacks parse_callbacks = { nullptr, nullptr, @@ -39,6 +41,31 @@ static constexpr yajl_callbacks parse_callbacks = { nullptr, }; +class TidalLoginRequest::ResponseParser final : public YajlResponseParser { + enum class State { + NONE, + SESSION_ID, + } state = State::NONE; + + std::string session; + +public: + explicit ResponseParser() noexcept + :YajlResponseParser(&parse_callbacks, nullptr, this) {} + + std::string &&GetSession() { + if (session.empty()) + throw std::runtime_error("No sessionId in login response"); + + return std::move(session); + } + + /* yajl callbacks */ + bool String(StringView value) noexcept; + bool MapKey(StringView value) noexcept; + bool EndMap() noexcept; +}; + static std::string MakeLoginUrl(const char *base_url) { @@ -66,47 +93,26 @@ TidalLoginRequest::~TidalLoginRequest() noexcept request.StopIndirect(); } -void -TidalLoginRequest::OnHeaders(unsigned status, - std::multimap<std::string, std::string> &&headers) +std::unique_ptr<CurlResponseParser> +TidalLoginRequest::MakeParser(unsigned status, + std::multimap<std::string, std::string> &&headers) { - if (status != 200) { - error_parser = std::make_unique<TidalErrorParser>(status, headers); - return; - } + if (status != 200) + return std::make_unique<TidalErrorParser>(status, headers); auto i = headers.find("content-type"); if (i == headers.end() || i->second.find("/json") == i->second.npos) throw std::runtime_error("Not a JSON response from Tidal"); - parser = {&parse_callbacks, nullptr, this}; + return std::make_unique<ResponseParser>(); } void -TidalLoginRequest::OnData(ConstBuffer<void> data) +TidalLoginRequest::FinishParser(std::unique_ptr<CurlResponseParser> p) { - if (error_parser) { - error_parser->OnData(data); - return; - } - - parser.Parse((const unsigned char *)data.data, data.size); -} - -void -TidalLoginRequest::OnEnd() -{ - if (error_parser) { - error_parser->OnEnd(); - return; - } - - parser.CompleteParse(); - - if (session.empty()) - throw std::runtime_error("No sessionId in login response"); - - handler.OnTidalLoginSuccess(std::move(session)); + assert(dynamic_cast<ResponseParser *>(p.get()) != nullptr); + auto &rp = (ResponseParser &)*p; + handler.OnTidalLoginSuccess(rp.GetSession()); } void @@ -116,7 +122,7 @@ TidalLoginRequest::OnError(std::exception_ptr e) noexcept } inline bool -TidalLoginRequest::String(StringView value) noexcept +TidalLoginRequest::ResponseParser::String(StringView value) noexcept { switch (state) { case State::NONE: @@ -131,7 +137,7 @@ TidalLoginRequest::String(StringView value) noexcept } inline bool -TidalLoginRequest::MapKey(StringView value) noexcept +TidalLoginRequest::ResponseParser::MapKey(StringView value) noexcept { if (value.Equals("sessionId")) state = State::SESSION_ID; @@ -142,7 +148,7 @@ TidalLoginRequest::MapKey(StringView value) noexcept } inline bool -TidalLoginRequest::EndMap() noexcept +TidalLoginRequest::ResponseParser::EndMap() noexcept { state = State::NONE; diff --git a/src/input/plugins/TidalLoginRequest.hxx b/src/input/plugins/TidalLoginRequest.hxx index e5d17d6df..51b4fde53 100644 --- a/src/input/plugins/TidalLoginRequest.hxx +++ b/src/input/plugins/TidalLoginRequest.hxx @@ -21,17 +21,9 @@ #define TIDAL_LOGIN_REQUEST_HXX #include "check.h" -#include "lib/curl/Handler.hxx" +#include "lib/curl/Delegate.hxx" #include "lib/curl/Slist.hxx" #include "lib/curl/Request.hxx" -#include "lib/yajl/Handle.hxx" - -#include <exception> -#include <memory> -#include <string> - -class CurlRequest; -class TidalErrorParser; /** * Callback class for #TidalLoginRequest. @@ -49,27 +41,16 @@ public: * * After construction, call Start() to initiate the request. */ -class TidalLoginRequest final : CurlResponseHandler { +class TidalLoginRequest final : DelegateCurlResponseHandler { CurlSlist request_headers; CurlRequest request; - std::unique_ptr<TidalErrorParser> error_parser; - - Yajl::Handle parser; - - enum class State { - NONE, - SESSION_ID, - } state = State::NONE; - - std::string session; - - std::exception_ptr error; - TidalLoginHandler &handler; public: + class ResponseParser; + TidalLoginRequest(CurlGlobal &curl, const char *base_url, const char *token, const char *username, const char *password, @@ -82,18 +63,13 @@ public: } private: + /* virtual methods from DelegateCurlResponseHandler */ + std::unique_ptr<CurlResponseParser> MakeParser(unsigned status, + std::multimap<std::string, std::string> &&headers) override; + void FinishParser(std::unique_ptr<CurlResponseParser> p) override; + /* virtual methods from CurlResponseHandler */ - void OnHeaders(unsigned status, - std::multimap<std::string, std::string> &&headers) override; - void OnData(ConstBuffer<void> data) override; - void OnEnd() override; void OnError(std::exception_ptr e) noexcept override; - -public: - /* yajl callbacks */ - bool String(StringView value) noexcept; - bool MapKey(StringView value) noexcept; - bool EndMap() noexcept; }; #endif diff --git a/src/input/plugins/TidalTrackRequest.cxx b/src/input/plugins/TidalTrackRequest.cxx index e8f27ae7a..34ce48a3c 100644 --- a/src/input/plugins/TidalTrackRequest.cxx +++ b/src/input/plugins/TidalTrackRequest.cxx @@ -23,7 +23,7 @@ #include "lib/yajl/Callbacks.hxx" #include "util/RuntimeError.hxx" -using Wrapper = Yajl::CallbacksWrapper<TidalTrackRequest>; +using Wrapper = Yajl::CallbacksWrapper<TidalTrackRequest::ResponseParser>; static constexpr yajl_callbacks parse_callbacks = { nullptr, nullptr, @@ -38,6 +38,31 @@ static constexpr yajl_callbacks parse_callbacks = { nullptr, }; +class TidalTrackRequest::ResponseParser final : public YajlResponseParser { + enum class State { + NONE, + URLS, + } state = State::NONE; + + std::string url; + +public: + explicit ResponseParser() noexcept + :YajlResponseParser(&parse_callbacks, nullptr, this) {} + + std::string &&GetUrl() { + if (url.empty()) + throw std::runtime_error("No url in track response"); + + return std::move(url); + } + + /* yajl callbacks */ + bool String(StringView value) noexcept; + bool MapKey(StringView value) noexcept; + bool EndMap() noexcept; +}; + static std::string MakeTrackUrl(const char *base_url, const char *track_id) { @@ -68,47 +93,26 @@ TidalTrackRequest::~TidalTrackRequest() noexcept request.StopIndirect(); } -void -TidalTrackRequest::OnHeaders(unsigned status, - std::multimap<std::string, std::string> &&headers) +std::unique_ptr<CurlResponseParser> +TidalTrackRequest::MakeParser(unsigned status, + std::multimap<std::string, std::string> &&headers) { - if (status != 200) { - error_parser = std::make_unique<TidalErrorParser>(status, headers); - return; - } + if (status != 200) + return std::make_unique<TidalErrorParser>(status, headers); auto i = headers.find("content-type"); if (i == headers.end() || i->second.find("/json") == i->second.npos) throw std::runtime_error("Not a JSON response from Tidal"); - parser = {&parse_callbacks, nullptr, this}; + return std::make_unique<ResponseParser>(); } void -TidalTrackRequest::OnData(ConstBuffer<void> data) +TidalTrackRequest::FinishParser(std::unique_ptr<CurlResponseParser> p) { - if (error_parser) { - error_parser->OnData(data); - return; - } - - parser.Parse((const unsigned char *)data.data, data.size); -} - -void -TidalTrackRequest::OnEnd() -{ - if (error_parser) { - error_parser->OnEnd(); - return; - } - - parser.CompleteParse(); - - if (url.empty()) - throw std::runtime_error("No url in track response"); - - handler.OnTidalTrackSuccess(std::move(url)); + assert(dynamic_cast<ResponseParser *>(p.get()) != nullptr); + auto &rp = (ResponseParser &)*p; + handler.OnTidalTrackSuccess(rp.GetUrl()); } void @@ -118,7 +122,7 @@ TidalTrackRequest::OnError(std::exception_ptr e) noexcept } inline bool -TidalTrackRequest::String(StringView value) noexcept +TidalTrackRequest::ResponseParser::String(StringView value) noexcept { switch (state) { case State::NONE: @@ -134,7 +138,7 @@ TidalTrackRequest::String(StringView value) noexcept } inline bool -TidalTrackRequest::MapKey(StringView value) noexcept +TidalTrackRequest::ResponseParser::MapKey(StringView value) noexcept { if (value.Equals("urls")) state = State::URLS; @@ -145,7 +149,7 @@ TidalTrackRequest::MapKey(StringView value) noexcept } inline bool -TidalTrackRequest::EndMap() noexcept +TidalTrackRequest::ResponseParser::EndMap() noexcept { state = State::NONE; diff --git a/src/input/plugins/TidalTrackRequest.hxx b/src/input/plugins/TidalTrackRequest.hxx index 829cd053e..f51877c8a 100644 --- a/src/input/plugins/TidalTrackRequest.hxx +++ b/src/input/plugins/TidalTrackRequest.hxx @@ -21,17 +21,9 @@ #define TIDAL_TRACK_REQUEST_HXX #include "check.h" -#include "lib/curl/Handler.hxx" +#include "lib/curl/Delegate.hxx" #include "lib/curl/Slist.hxx" #include "lib/curl/Request.hxx" -#include "lib/yajl/Handle.hxx" - -#include <exception> -#include <memory> -#include <string> - -class CurlRequest; -class TidalErrorParser; /** * Callback class for #TidalTrackRequest. @@ -51,27 +43,16 @@ public: * * After construction, call Start() to initiate the request. */ -class TidalTrackRequest final : CurlResponseHandler { +class TidalTrackRequest final : DelegateCurlResponseHandler { CurlSlist request_headers; CurlRequest request; - std::unique_ptr<TidalErrorParser> error_parser; - - Yajl::Handle parser; - - enum class State { - NONE, - URLS, - } state = State::NONE; - - std::string url; - - std::exception_ptr error; - TidalTrackHandler &handler; public: + class ResponseParser; + TidalTrackRequest(CurlGlobal &curl, const char *base_url, const char *token, const char *session, @@ -85,18 +66,13 @@ public: } private: + /* virtual methods from DelegateCurlResponseHandler */ + std::unique_ptr<CurlResponseParser> MakeParser(unsigned status, + std::multimap<std::string, std::string> &&headers) override; + void FinishParser(std::unique_ptr<CurlResponseParser> p) override; + /* virtual methods from CurlResponseHandler */ - void OnHeaders(unsigned status, - std::multimap<std::string, std::string> &&headers) override; - void OnData(ConstBuffer<void> data) override; - void OnEnd() override; void OnError(std::exception_ptr e) noexcept override; - -public: - /* yajl callbacks */ - bool String(StringView value) noexcept; - bool MapKey(StringView value) noexcept; - bool EndMap() noexcept; }; #endif diff --git a/src/lib/curl/Delegate.cxx b/src/lib/curl/Delegate.cxx new file mode 100644 index 000000000..a2511d2d5 --- /dev/null +++ b/src/lib/curl/Delegate.cxx @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2008-2018 Max Kellermann <max.kellermann@gmail.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "Delegate.hxx" +#include "Parser.hxx" + +#include <assert.h> + +void +DelegateCurlResponseHandler::OnHeaders(unsigned status, + std::multimap<std::string, std::string> &&headers) +{ + parser = MakeParser(status, std::move(headers)); + assert(parser); +} + +void +DelegateCurlResponseHandler::OnData(ConstBuffer<void> data) +{ + parser->OnData(data); +} + +void +DelegateCurlResponseHandler::OnEnd() +{ + parser->OnEnd(); + FinishParser(std::move(parser)); +} diff --git a/src/lib/curl/Delegate.hxx b/src/lib/curl/Delegate.hxx new file mode 100644 index 000000000..fe6a65f35 --- /dev/null +++ b/src/lib/curl/Delegate.hxx @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2008-2018 Max Kellermann <max.kellermann@gmail.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CURL_DELEGATE_HXX +#define CURL_DELEGATE_HXX + +#include "Handler.hxx" + +#include <memory> + +class CurlResponseParser; + +/** + * A #CurlResponseHandler implementation which delegates response body + * parsing to another object which is created dynamically. This is + * useful when a different parser needs to be used under certain + * runtime conditions (e.g. depending on the status or content type). + */ +class DelegateCurlResponseHandler : public CurlResponseHandler { + std::unique_ptr<CurlResponseParser> parser; + +protected: + /** + * HTTP response headers have been received, and we now need a + * parser. This method constructs one and returns it (or + * throws an exception which will be passed to + * CurlResponseParser::OnError()). + */ + virtual std::unique_ptr<CurlResponseParser> MakeParser(unsigned status, + std::multimap<std::string, std::string> &&headers) = 0; + + /** + * The parser has finished parsing the response body. This + * method can be used to evaluate the result. Exceptions + * thrown by this method will be passed to + * CurlResponseParser::OnError(). + */ + virtual void FinishParser(std::unique_ptr<CurlResponseParser> p) = 0; + +public: + void OnHeaders(unsigned status, + std::multimap<std::string, std::string> &&headers) final; + void OnData(ConstBuffer<void> data) final; + void OnEnd() final; +}; + +#endif diff --git a/src/lib/curl/Parser.hxx b/src/lib/curl/Parser.hxx new file mode 100644 index 000000000..709b4937f --- /dev/null +++ b/src/lib/curl/Parser.hxx @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2008-2018 Max Kellermann <max.kellermann@gmail.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CURL_PARSER_HXX +#define CURL_PARSER_HXX + +template<typename T> struct ConstBuffer; + +class CurlResponseParser { +public: + virtual ~CurlResponseParser() = default; + virtual void OnData(ConstBuffer<void> data) = 0; + virtual void OnEnd() = 0; +}; + +#endif diff --git a/src/lib/yajl/ResponseParser.cxx b/src/lib/yajl/ResponseParser.cxx new file mode 100644 index 000000000..f8c0b3727 --- /dev/null +++ b/src/lib/yajl/ResponseParser.cxx @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2008-2018 Max Kellermann <max.kellermann@gmail.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ResponseParser.hxx" +#include "util/ConstBuffer.hxx" + +void +YajlResponseParser::OnData(ConstBuffer<void> data) +{ + handle.Parse((const unsigned char *)data.data, data.size); +} + +void +YajlResponseParser::OnEnd() +{ + handle.CompleteParse(); +} diff --git a/src/lib/yajl/ResponseParser.hxx b/src/lib/yajl/ResponseParser.hxx new file mode 100644 index 000000000..be08dd3d5 --- /dev/null +++ b/src/lib/yajl/ResponseParser.hxx @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2008-2018 Max Kellermann <max.kellermann@gmail.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef YAJL_RESPONSE_PARSER_HXX +#define YAJL_RESPONSE_PARSER_HXX + +#include "Handle.hxx" +#include "lib/curl/Parser.hxx" + +/** + * A helper class which parses the response body as JSON. + */ +class YajlResponseParser : public CurlResponseParser { + Yajl::Handle handle; + +public: + template<typename... Args> + YajlResponseParser(Args... args) noexcept + :handle(std::forward<Args>(args)...) {} + + /* virtual methods fro CurlResponseParser */ + void OnData(ConstBuffer<void> data) final; + void OnEnd() override; +}; + +#endif |