#pragma once #if !defined(MIJIN_NET_CURL_WRAPPERS_HPP_INCLUDED) #define MIJIN_NET_CURL_WRAPPERS_HPP_INCLUDED 1 #include #include "./url.hpp" #include "../debug/assert.hpp" #include "../internal/common.hpp" #include "../types/result.hpp" namespace curl { #if !MIJIN_WITH_EXCEPTIONS struct [[nodiscard]] Error { CURLcode code = CURLE_OK; [[nodiscard]] bool isSuccess() const MIJIN_NOEXCEPT { return code == CURLE_OK; } }; #define MIJIN_CURL_VERIFY_RESULT(curlResult) \ do \ { \ if ((curlResult) != CURLE_OK) \ { \ return Error{curlResult}; \ } \ } while (0) #define MIJIN_CURL_RETURN_SUCCESS() return Error() #else using Error = void; [[nodiscard]] std::string curlCodeMessage(CURLcode code) { switch (code) { default: return "Unknown CURL error."; } } class CurlException : public std::runtime_error { private: CURLcode code_; public: explicit CurlException(CURLcode code) MIJIN_NOEXCEPT: std::runtime_error(curlCodeMessage(code)), code_(code) {} [[nodiscard]] constexpr CURLcode getCode() const MIJIN_NOEXCEPT { return code_; } }; #define MIJIN_CURL_VERIFY_RESULT(curlResult) \ do \ { \ if ((curlResult) != CURLE_OK) \ { \ throw CurlException((curlResult)); \ } \ } while (0) #define MIJIN_CURL_RETURN_SUCCESS() return #endif class CurlEasy { private: CURL* handle_ = nullptr; public: CurlEasy() MIJIN_NOEXCEPT = default; CurlEasy(const CurlEasy&) = delete; CurlEasy(CurlEasy&& other) MIJIN_NOEXCEPT : handle_(std::exchange(other.handle_, nullptr)) {} ~CurlEasy() MIJIN_NOEXCEPT { reset(); } CurlEasy& operator=(const CurlEasy&) = delete; CurlEasy& operator=(CurlEasy&& other) MIJIN_NOEXCEPT { if (this == &other) { return *this; } reset(); handle_ = std::exchange(other.handle_, nullptr); return *this; } MIJIN_ERROR_BOOL init() MIJIN_THROWS { reset(); handle_ = curl_easy_init(); if (handle_ != nullptr) { MIJIN_THROW_OR_RETURN_STD(false, "Error initializing CURL easy."); } MIJIN_RETURN_SUCCESS(true); } void reset() MIJIN_NOEXCEPT { if (handle_) { curl_easy_cleanup(handle_); handle_ = nullptr; } } Error setURL(const char* url) MIJIN_THROWS { const CURLcode result = curl_easy_setopt(handle_, CURLOPT_URL, url); MIJIN_CURL_VERIFY_RESULT(result); MIJIN_CURL_RETURN_SUCCESS(); } Error setURL(const std::string& url) MIJIN_NOEXCEPT { return setURL(url.c_str()); } Error setURL(const mijin::URL& url) MIJIN_NOEXCEPT { return setURL(url.getBase().c_str()); } }; } // namespace curl #endif // !defined(MIJIN_NET_CURL_WRAPPERS_HPP_INCLUDED)