crawlserv++  [under development]
Application for crawling and analyzing textual content of websites.
Curl.hpp
Go to the documentation of this file.
1 /*
2  *
3  * ---
4  *
5  * Copyright (C) 2022 Anselm Schmidt (ans[ät]ohai.su)
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version in addition to the terms of any
11  * licences already herein identified.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <https://www.gnu.org/licenses/>.
20  *
21  * ---
22  *
23  * Curl.hpp
24  *
25  * RAII wrapper for pointer to libcurl instance, also handles global instance if necessary.
26  * Does NOT have ownership of the pointer.
27  * The first instance has to be destructed last.
28  *
29  * Created on: Feb 7, 2019
30  * Author: ans
31  */
32 
33 #ifndef WRAPPER_CURL_HPP_
34 #define WRAPPER_CURL_HPP_
35 
36 #ifndef CRAWLSERVPP_TESTING
37 
38 #include <curl/curl.h>
39 
40 #else
41 
42 #include "FakeCurl/FakeCurl.hpp"
43 
44 #endif
45 
46 #include <atomic> // std::atomic
47 #include <stdexcept> // std::runtime_error
48 
49 namespace crawlservpp::Wrapper {
50 
51  /*
52  * DECLARATION
53  */
54 
56 
70  class Curl {
71  public:
74 
75  Curl();
76  virtual ~Curl();
77 
81 
82  [[nodiscard]] CURL * get() noexcept;
83  [[nodiscard]] CURL ** getPtr() noexcept;
84  [[nodiscard]] bool valid() const noexcept;
85 
89 
90  void init();
91  void clear() noexcept;
92 
94 
97 
100  Curl(Curl&) = delete;
101 
103  Curl& operator=(Curl&) = delete;
104 
105  Curl(Curl&& other) noexcept;
106  Curl& operator=(Curl&& other) noexcept;
107 
109 
110  private:
111  // underlying pointer to the libcurl API
112  CURL * ptr{nullptr};
113 
114  // global initialization state of the libcurl API
115  static std::atomic<unsigned int> globalInitCounter;
116  };
117 
118  /*
119  * IMPLEMENTATION
120  */
121 
122  /*
123  * CONSTRUCTION AND DESTRUCTION
124  */
125 
127 
136  inline Curl::Curl() {
137  // initialize global instance of libcurl if necessary
138  if(Curl::globalInitCounter.fetch_add(1) == 0) {
139  //NOLINTNEXTLINE(hicpp-signed-bitwise)
140  const auto curlCode{curl_global_init(CURL_GLOBAL_ALL)};
141 
142  if(curlCode != CURLE_OK) {
143  throw std::runtime_error(curl_easy_strerror(curlCode));
144  }
145  }
146 
147  // initialize local instance of libcurl
148  try {
149  this->init();
150  }
151  catch(...) {
152  if(Curl::globalInitCounter.fetch_sub(1) == 1) {
153  curl_global_cleanup();
154  }
155 
156  throw;
157  }
158  }
159 
161 
172  inline Curl::~Curl() {
173  // cleanup local handle if necessary
174  this->clear();
175 
176  // cleanup global instance if necessary
177  if(Curl::globalInitCounter.fetch_sub(1) == 1) {
178  curl_global_cleanup();
179  }
180  }
181 
182  /*
183  * GETTERS
184  */
185 
187 
193  inline CURL * Curl::get() noexcept {
194  return this->ptr;
195  }
196 
198 
205  inline CURL ** Curl::getPtr() noexcept {
206  return &(this->ptr);
207  }
208 
210 
214  inline bool Curl::valid() const noexcept {
215  return this->ptr != nullptr;
216  }
217 
218  /*
219  * INITIALIZATION AND CLEANUP
220  */
221 
223 
230  inline void Curl::init() {
231  this->clear();
232 
233  this->ptr = curl_easy_init();
234 
235  if(this->ptr == nullptr) {
236  throw std::runtime_error("curl_easy_init() failed");
237  }
238  }
239 
241 
255  inline void Curl::clear() noexcept {
256  if(this->ptr != nullptr) {
257  curl_easy_cleanup(this->ptr);
258 
259  this->ptr = nullptr;
260  }
261  }
262 
263  /*
264  * COPY AND MOVE
265  */
266 
268 
281  inline Curl::Curl(Curl&& other) noexcept {
282  this->ptr = other.ptr;
283 
284  other.ptr = nullptr;
285  }
286 
288 
312  inline Curl& Curl::operator=(Curl&& other) noexcept {
313  if(&other != this) {
314  this->clear();
315 
316  this->ptr = other.ptr;
317 
318  other.ptr = nullptr;
319  }
320 
321  return *this;
322  }
323 
324 } /* namespace crawlservpp::Wrapper */
325 
326 #endif /* WRAPPER_CURL_HPP_ */
void clear() noexcept
Clears the underlying libcurl handle.
Definition: Curl.hpp:255
CURL ** getPtr() noexcept
Gets a pointer to the pointer containing the address of the underlying libcurl handle.
Definition: Curl.hpp:205
void init()
Initializes the underlying libcurl handle.
Definition: Curl.hpp:230
bool valid() const noexcept
Checks whether the underlying libcurl handle is valid.
Definition: Curl.hpp:214
virtual ~Curl()
Destructor cleaning up the libcurl API locally and globally, if necessary.
Definition: Curl.hpp:172
RAII wrapper for handles of the libcurl API.
Definition: Curl.hpp:70
CURL * get() noexcept
Gets a pointer to the underlying libcurl handle.
Definition: Curl.hpp:193
Curl & operator=(Curl &)=delete
Deleted copy assignment operator.
Namespace for RAII wrappers and Wrapper::Database.
Definition: Database.hpp:109
Curl()
Constructor initializing the libcurl API locally and globally, if necessary.
Definition: Curl.hpp:136