mijin2/source/mijin/net/curl_wrappers.hpp

135 lines
3.2 KiB
C++

#pragma once
#if !defined(MIJIN_NET_CURL_WRAPPERS_HPP_INCLUDED)
#define MIJIN_NET_CURL_WRAPPERS_HPP_INCLUDED 1
#include <curl/curl.h>
#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)