curl-cpp
static c++17 wrapper for curl with -fno-exceptions support
curl.cc
1 #include "curl.hpp"
2 #include <curl/curl.h>
3 
4 #include <err.h>
5 #include <cstring>
6 #include <cinttypes>
7 #include <limits>
8 
9 namespace curl {
10 constexpr auto curl_t::Version::from(std::uint8_t major, std::uint8_t minor, std::uint8_t patch) noexcept ->
11  Version
12 {
13  return {static_cast<std::uint32_t>(major << 16) |
14  static_cast<std::uint32_t>(minor << 8) |
15  static_cast<std::uint32_t>(patch)};
16 }
17 
18 static constexpr const auto mask = std::numeric_limits<std::uint8_t>::max();
19 constexpr std::uint8_t curl_t::Version::get_major() const noexcept
20 {
21  return (num >> 16) & mask;
22 }
23 constexpr std::uint8_t curl_t::Version::get_minor() const noexcept
24 {
25  return (num >> 8) & mask;
26 }
27 constexpr std::uint8_t curl_t::Version::get_patch() const noexcept
28 {
29  return num & mask;
30 }
31 
32 constexpr bool operator < (const curl_t::Version &x, const curl_t::Version &y) noexcept
33 {
34  return x.num < y.num;
35 }
36 constexpr bool operator <= (const curl_t::Version &x, const curl_t::Version &y) noexcept
37 {
38  return x.num <= y.num;
39 }
40 constexpr bool operator > (const curl_t::Version &x, const curl_t::Version &y) noexcept
41 {
42  return x.num > y.num;
43 }
44 constexpr bool operator >= (const curl_t::Version &x, const curl_t::Version &y) noexcept
45 {
46  return x.num >= y.num;
47 }
48 constexpr bool operator == (const curl_t::Version &x, const curl_t::Version &y) noexcept
49 {
50  return x.num == y.num;
51 }
52 constexpr bool operator != (const curl_t::Version &x, const curl_t::Version &y) noexcept
53 {
54  return x.num != y.num;
55 }
56 
57 std::size_t curl_t::Version::to_string(char buffer[12]) const noexcept
58 {
59  return std::snprintf(buffer, 12, "%" PRIu8 ".%" PRIu8 ".%" PRIu8, get_major(), get_minor(), get_patch());
60 }
61 
62 static auto initialize_and_return_arg(FILE *stderr_stream_arg) noexcept
63 {
64  auto code = curl_global_init(CURL_GLOBAL_ALL);
65  if (code != CURLE_OK)
66  errx(1, "curl_global_init(CURL_GLOBAL_ALL) failed with %s", curl_easy_strerror(code));
67 
68  return stderr_stream_arg;
69 }
70 curl_t::curl_t(FILE *stderr_stream_arg) noexcept:
71  stderr_stream{initialize_and_return_arg(stderr_stream_arg)},
72  version_info {curl_version_info(CURLVERSION_NOW)},
73  version {static_cast<const curl_version_info_data*>(version_info)->version_num},
74  version_str {static_cast<const curl_version_info_data*>(version_info)->version}
75 {
76  if (version < Version::from(7, 4, 1))
77  errx(1, "CURLINFO_RESPONSE_CODE isn't supported in this version: %s, %" PRIu32,
78  version_str, version.num);
79 }
80 
81 static auto initialize_and_return_last_arg(curl_t::malloc_callback_t malloc_callback,
82  curl_t::free_callback_t free_callback,
83  curl_t::realloc_callback_t realloc_callback,
84  curl_t::strdup_callback_t strdup_callback,
85  curl_t::calloc_callback_t calloc_callback,
86  FILE *stderr_stream_arg) noexcept
87 {
88  auto code = curl_global_init_mem(CURL_GLOBAL_ALL,
89  malloc_callback,
90  free_callback,
91  realloc_callback,
92  strdup_callback,
93  calloc_callback);
94  if (code != CURLE_OK)
95  errx(1, "curl_global_init_mem(CURL_GLOBAL_ALL, %p, %p, %p, %p, %p) failed with %s",
96  malloc_callback,
97  free_callback,
98  realloc_callback,
99  strdup_callback,
100  calloc_callback,
101  curl_easy_strerror(code));
102 
103  return stderr_stream_arg;
104 }
105 curl_t::curl_t(FILE *stderr_stream_arg,
106  malloc_callback_t malloc_callback,
107  free_callback_t free_callback,
108  realloc_callback_t realloc_callback,
109  strdup_callback_t strdup_callback,
110  calloc_callback_t calloc_callback) noexcept:
111  stderr_stream{initialize_and_return_last_arg(malloc_callback,
112  free_callback,
113  realloc_callback,
114  strdup_callback,
115  calloc_callback,
116  stderr_stream_arg)},
117  version_info {curl_version_info(CURLVERSION_NOW)},
118  version {static_cast<const curl_version_info_data*>(version_info)->version_num},
119  version_str {static_cast<const curl_version_info_data*>(version_info)->version}
120 {
121  if (version < Version::from(7, 4, 1))
122  errx(1, "CURLINFO_RESPONSE_CODE isn't supported in this version: %s, %" PRIu32,
123  version_str, version.num);
124 }
125 
126 bool curl_t::has_compression_support() const noexcept
127 {
128  auto *info = static_cast<const curl_version_info_data*>(version_info);
129  return info->features & CURL_VERSION_LIBZ;
130 }
131 bool curl_t::has_largefile_support() const noexcept
132 {
133  auto *info = static_cast<const curl_version_info_data*>(version_info);
134  return info->features & CURL_VERSION_LARGEFILE;
135 }
136 bool curl_t::has_protocol(const char *protocol) const noexcept
137 {
138  auto *info = static_cast<const curl_version_info_data*>(version_info);
139  auto *protocols = info->protocols;
140 
141  for (std::size_t i = 0; protocols[i]; ++i)
142  if (std::strcmp(protocols[i], protocol) == 0)
143  return true;
144 
145  return false;
146 }
147 bool curl_t::has_ssl_support() const noexcept
148 {
149  auto *info = static_cast<const curl_version_info_data*>(version_info);
150  return info->features & CURL_VERSION_SSL;
151 }
152 bool curl_t::has_ipv6_support() const noexcept
153 {
154  auto *info = static_cast<const curl_version_info_data*>(version_info);
155  return info->features & CURL_VERSION_IPV6;
156 }
157 
158 bool curl_t::has_erase_all_cookies_in_mem_support() const noexcept
159 {
160  return version >= Version::from(7, 14, 1);
161 }
162 bool curl_t::has_erase_all_session_cookies_in_mem_support() const noexcept
163 {
164  return version >= Version::from(7, 15, 4);
165 }
166 bool curl_t::has_flush_cookies_to_jar() const noexcept
167 {
168  return version >= Version::from(7, 17, 1);
169 }
170 bool curl_t::has_reload_cookies_from_file() const noexcept
171 {
172  return version >= Version::from(7, 39, 0);
173 }
174 
175 bool curl_t::has_disable_signal_handling_support() const noexcept
176 {
177  return version >= Version::from(7, 10, 0);
178 }
179 
180 bool curl_t::has_private_ptr_support() const noexcept
181 {
182  return version >= Version::from(7, 10, 3);
183 }
184 
185 bool curl_t::has_readfunc_abort_support() const noexcept
186 {
187  return version >= Version::from(7, 12, 1);
188 }
189 bool curl_t::has_pause_support() const noexcept
190 {
191  return version >= Version::from(7, 18, 0);
192 }
193 
194 bool curl_t::has_header_option_support() const noexcept
195 {
196  return version >= Version::from(7, 37, 0);
197 }
198 bool curl_t::has_set_ip_addr_only_support() const noexcept
199 {
200  return version >= Version::from(7, 24, 0);
201 }
202 
203 bool curl_t::has_redirect_url_support() const noexcept
204 {
205  return version >= Version::from(7, 18, 2);
206 }
207 
208 bool curl_t::has_getinfo_cookie_list_support() const noexcept
209 {
210  return version >= Version::from(7, 14, 1);
211 }
212 
213 bool curl_t::has_buffer_size_tuning_support() const noexcept
214 {
215  return version >= Version::from(7, 10, 0);
216 }
217 bool curl_t::has_buffer_size_growing_support() const noexcept
218 {
219  return version >= Version::from(7, 53, 0);
220 }
221 
222 bool curl_t::has_get_active_socket_support() const noexcept
223 {
224  return version >= Version::from(7, 45, 0);
225 }
226 
227 bool curl_t::has_CURLU() const noexcept
228 {
229  return version >= Version::from(7, 63, 0);
230 }
231 
232 bool curl_t::has_multi_poll_support() const noexcept
233 {
234  return version >= Version::from(7, 66, 0);
235 }
236 bool curl_t::has_multi_socket_support() const noexcept
237 {
238  return version >= Version::from(7, 16, 0);
239 }
240 
241 bool curl_t::has_http2_multiplex_support() const noexcept
242 {
243  return version >= Version::from(7, 43, 0);
244 }
245 bool curl_t::has_max_concurrent_stream_support() const noexcept
246 {
247  return version >= Version::from(7, 67, 0);
248 }
249 
250 
251 bool curl_t::has_ssl_session_sharing_support() const noexcept
252 {
253  return version >= Version::from(7, 23, 0) && has_ssl_support();
254 }
255 bool curl_t::has_connection_cache_sharing_support() const noexcept
256 {
257  return version >= Version::from(7, 57, 0);
258 }
259 bool curl_t::has_psl_sharing_support() const noexcept
260 {
261  auto *info = static_cast<const curl_version_info_data*>(version_info);
262  return version >= Version::from(7, 61, 0) && info->features & CURL_VERSION_PSL;
263 }
264 
266 {
267  curl_global_cleanup();
268 }
269 } /* namespace curl */
curl::curl_t::Version::operator>
constexpr friend bool operator>(const Version &x, const Version &y) noexcept
Definition: curl.cc:40
curl::curl_t::version_str
const char *const version_str
Definition: curl.hpp:152
curl::curl_t::Version::operator!=
constexpr friend bool operator!=(const Version &x, const Version &y) noexcept
Definition: curl.cc:52
curl::curl_t::~curl_t
~curl_t()
Definition: curl.cc:265
curl::curl_t::Version::operator==
constexpr friend bool operator==(const Version &x, const Version &y) noexcept
Definition: curl.cc:48
curl::curl_t::has_CURLU
bool has_CURLU() const noexcept
Definition: curl.cc:227
curl::curl_t::Version::to_string
std::size_t to_string(char buffer[12]) const noexcept
Definition: curl.cc:57
curl::curl_t::version_info
const void *const version_info
Definition: curl.hpp:121
curl::curl_t::curl_t
curl_t(FILE *stderr_stream_arg) noexcept
Definition: curl.cc:70
curl::curl_t::stderr_stream
FILE * stderr_stream
Definition: curl.hpp:115
curl::curl_t
Definition: curl.hpp:62
curl::curl_t::version
const Version version
Definition: curl.hpp:125
curl::curl_t::curl_t
curl_t(FILE *stderr_stream_arg, malloc_callback_t malloc_callback, free_callback_t free_callback, realloc_callback_t realloc_callback, strdup_callback_t strdup_callback, calloc_callback_t calloc_callback) noexcept
Definition: curl.cc:105
curl::curl_t::has_http2_multiplex_support
bool has_http2_multiplex_support() const noexcept
Definition: curl.cc:241
curl::curl_t::has_protocol
bool has_protocol(const char *protocol) const noexcept
Definition: curl.cc:136
curl::curl_t::Version::operator<=
constexpr friend bool operator<=(const Version &x, const Version &y) noexcept
Definition: curl.cc:36
curl::curl_t::Version::operator<
constexpr friend bool operator<(const Version &x, const Version &y) noexcept
Definition: curl.cc:32
curl::curl_t::Version
Definition: curl.hpp:69
curl::curl_t::Version::operator>=
constexpr friend bool operator>=(const Version &x, const Version &y) noexcept
Definition: curl.cc:44