| @@ -0,0 +1,3 @@ | |||||
| [submodule "/home/bergmann/projects/dnpnode/projects/cppcurl/cmake/modules"] | |||||
| path = /home/bergmann/projects/dnpnode/projects/cppcurl/cmake/modules | |||||
| url = b3rgmann@git.bergmann89.de:cpp/CmakeModules.git | |||||
| @@ -0,0 +1,57 @@ | |||||
| # Initialize CMake ################################################################################ | |||||
| CMake_Minimum_Required ( VERSION 3.12.0 FATAL_ERROR ) | |||||
| # Set CMAKE_BUILD_TYPE | |||||
| If ( NOT CMAKE_BUILD_TYPE ) | |||||
| Set ( CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build!" FORCE ) | |||||
| EndIf ( NOT CMAKE_BUILD_TYPE ) | |||||
| Set_Property ( CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS Debug Release RelWithDebInfo MinSizeRel ) | |||||
| # Set CMAKE_MODULE_PATH | |||||
| If ( EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake/" ) | |||||
| Set ( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} | |||||
| "${CMAKE_CURRENT_SOURCE_DIR}/cmake/" ) | |||||
| EndIf ( ) | |||||
| If ( EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake/" ) | |||||
| Set ( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} | |||||
| "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules" ) | |||||
| EndIf ( ) | |||||
| # Project ######################################################################################### | |||||
| Include ( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/cppcurl-var.cmake ) | |||||
| Include ( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/cppcurl-options.cmake ) | |||||
| Project ( cppcurl | |||||
| DESCRIPTION "A simple library" | |||||
| VERSION "${CPPCURL_VERSION}" ) | |||||
| Include ( CTest ) | |||||
| Include ( GNUInstallDirs ) | |||||
| # Subdirectories | |||||
| Add_SubDirectory ( ${CMAKE_CURRENT_SOURCE_DIR}/src ) | |||||
| Add_SubDirectory ( ${CMAKE_CURRENT_SOURCE_DIR}/test ) | |||||
| # Install | |||||
| Include ( CMakePackageConfigHelpers ) | |||||
| Write_Basic_Package_Version_File ( "${CMAKE_CURRENT_BINARY_DIR}/cmake/cppcurl-config-version.cmake" | |||||
| VERSION ${CPPCURL_VERSION} | |||||
| COMPATIBILITY AnyNewerVersion ) | |||||
| Configure_File ( "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cppcurl-config.cmake" | |||||
| "${CMAKE_CURRENT_BINARY_DIR}/cmake/cppcurl-config.cmake" | |||||
| @ONLY ) | |||||
| Set ( ConfigPackageLocation "${CPPCURL_INSTALL_DIR_SHARE}/cmake" ) | |||||
| Install ( EXPORT | |||||
| cppcurl | |||||
| NAMESPACE | |||||
| cppcurl:: | |||||
| DESTINATION | |||||
| ${ConfigPackageLocation} ) | |||||
| Install ( FILES | |||||
| "${CMAKE_CURRENT_BINARY_DIR}/cmake/cppcurl-config.cmake" | |||||
| "${CMAKE_CURRENT_BINARY_DIR}/cmake/cppcurl-config-version.cmake" | |||||
| DESTINATION | |||||
| ${ConfigPackageLocation} | |||||
| COMPONENT | |||||
| Devel ) | |||||
| @@ -0,0 +1,3 @@ | |||||
| #pragma once | |||||
| #cmakedefine CPPCURL_HAS_CPPCORE | |||||
| @@ -0,0 +1,10 @@ | |||||
| # cppcurl-config.cmake - package configuration file | |||||
| Message ( WARNING "Please configure the dependencies of this package!" ) | |||||
| # Include ( CMakeFindDependencyMacro ) | |||||
| # Find_Dependency ( <dependency> ) | |||||
| Include ( FindPackageHandleStandardArgs ) | |||||
| Set ( ${CMAKE_FIND_PACKAGE_NAME}_CONFIG ${CMAKE_CURRENT_LIST_FILE} ) | |||||
| Find_Package_Handle_Standard_Args ( cppcurl CONFIG_MODE ) | |||||
| Include ( "${CMAKE_CURRENT_LIST_DIR}/cppcurl.cmake") | |||||
| @@ -0,0 +1,15 @@ | |||||
| Option ( CPPCURL_INSTALL_HEADER | |||||
| "Install headers of cppcurl." | |||||
| ON ) | |||||
| Option ( CPPCURL_INSTALL_STATIC | |||||
| "Install static library of cppcurl." | |||||
| ON ) | |||||
| Option ( CPPCURL_INSTALL_SHARED | |||||
| "Install shared library of cppcurl." | |||||
| ON ) | |||||
| Option ( CPPCURL_INSTALL_DEBUG | |||||
| "Install the stripped debug informations of cppcurl." | |||||
| OFF ) | |||||
| Option ( CPPCURL_NO_STRIP | |||||
| "Do not strip debug symbols from binary." | |||||
| OFF ) | |||||
| @@ -0,0 +1,31 @@ | |||||
| # Version | |||||
| Set ( CPPCURL_VERSION_MAJOR 1 ) | |||||
| Set ( CPPCURL_VERSION_MINOR 0 ) | |||||
| Set ( CPPCURL_VERSION_PATCH 0 ) | |||||
| Set ( CPPCURL_VERSION_BUILD 0 ) | |||||
| Set ( CPPCURL_VERSION_SHORT "${CPPCURL_VERSION_MAJOR}.${CPPCURL_VERSION_MINOR}" ) | |||||
| Set ( CPPCURL_VERSION "${CPPCURL_VERSION_SHORT}.${CPPCURL_VERSION_PATCH}.${CPPCURL_VERSION_BUILD}" ) | |||||
| Set ( CPPCURL_NAME "cppcurl-${CPPCURL_VERSION_SHORT}" ) | |||||
| Set ( CPPCURL_OUTPUTNAME "cppcurl" ) | |||||
| # Install directories | |||||
| Set ( CPPCURL_INSTALL_DIR_INCLUDE "include/${CPPCURL_NAME}" ) | |||||
| Set ( CPPCURL_INSTALL_DIR_LIB "lib" ) | |||||
| Set ( CPPCURL_INSTALL_DIR_SHARE "share/${CPPCURL_NAME}" ) | |||||
| # C Standard | |||||
| Set ( CMAKE_C_STANDARD 11 ) | |||||
| Set ( CMAKE_CXX_STANDARD 17 ) | |||||
| Set ( CMAKE_C_STANDARD_REQUIRED ON ) | |||||
| Set ( CMAKE_CXX_STANDARD_REQUIRED ON ) | |||||
| # Git Version | |||||
| Include ( git_helper OPTIONAL RESULT_VARIABLE HAS_GIT_HELPER ) | |||||
| If ( HAS_GIT_HELPER ) | |||||
| GitGetVersion ( ${CMAKE_CURRENT_LIST_DIR}/.. | |||||
| CPPCURL_VERSION_MAJOR | |||||
| CPPCURL_VERSION_MINOR | |||||
| CPPCURL_VERSION_PATCH | |||||
| CPPCURL_VERSION_BUILD | |||||
| CPPCURL_VERSION_HASH ) | |||||
| EndIf ( ) | |||||
| @@ -0,0 +1 @@ | |||||
| Subproject commit a50f6505f4989b1d96449ba7cd498f8bf2880427 | |||||
| @@ -0,0 +1,15 @@ | |||||
| #pragma once | |||||
| #include "cppcurl/easy.h" | |||||
| #include "cppcurl/exception.h" | |||||
| #include "cppcurl/global.h" | |||||
| #include "cppcurl/info.h" | |||||
| #include "cppcurl/multi.h" | |||||
| #include "cppcurl/option.h" | |||||
| #include "cppcurl/slist.h" | |||||
| #include "cppcurl/easy.inl" | |||||
| #include "cppcurl/exception.inl" | |||||
| #include "cppcurl/global.inl" | |||||
| #include "cppcurl/multi.inl" | |||||
| #include "cppcurl/slist.inl" | |||||
| @@ -0,0 +1,74 @@ | |||||
| #pragma once | |||||
| #include <memory> | |||||
| #include <curl/curl.h> | |||||
| #include "info.h" | |||||
| #include "slist.h" | |||||
| #include "option.h" | |||||
| namespace cppcurl | |||||
| { | |||||
| struct easy | |||||
| { | |||||
| private: | |||||
| using handle_ptr_u = std::unique_ptr<CURL, decltype(&curl_easy_cleanup)>; | |||||
| private: | |||||
| handle_ptr_u _handle; | |||||
| slist _header; | |||||
| public: | |||||
| /** | |||||
| * @brief Constructor. | |||||
| */ | |||||
| inline easy(); | |||||
| /** | |||||
| * @brief Get the internal curl easy handle. | |||||
| */ | |||||
| inline CURL* handle() const; | |||||
| /** | |||||
| * @brief Reset all options of the easy handle. | |||||
| */ | |||||
| inline void reset(); | |||||
| /** | |||||
| * @brief Perform the action configured in this easy handle. | |||||
| */ | |||||
| inline void perform(); | |||||
| /** | |||||
| * @brief Add header to easy handle. | |||||
| */ | |||||
| inline void add_header(const std::string& s); | |||||
| /** | |||||
| * @brief Add option to the easy handle. | |||||
| * | |||||
| * @param[in] opt Option to add to the handle. | |||||
| */ | |||||
| template<CURLoption T_option, typename T_value> | |||||
| inline void set_option(const __impl::option<T_option, T_value>& opt); | |||||
| /** | |||||
| * @brief Add option to the easy handle. | |||||
| * | |||||
| * @tparam T_option Option to add to the handle. | |||||
| * @param[in] val Value of option to add to the handle. | |||||
| */ | |||||
| template<CURLoption T_option> | |||||
| inline void set_option(const typename option<T_option>::value_type& val); | |||||
| /** | |||||
| * @brief Get an info from the easy handle. | |||||
| */ | |||||
| template<CURLINFO T_info> | |||||
| inline typename info<T_info>::value_type get_info() const; | |||||
| }; | |||||
| } | |||||
| #include "easy.inl" | |||||
| @@ -0,0 +1,190 @@ | |||||
| #pragma once | |||||
| #include "easy.h" | |||||
| #include "slist.inl" | |||||
| #include "global.inl" | |||||
| #include "exception.inl" | |||||
| namespace cppcurl | |||||
| { | |||||
| namespace __impl | |||||
| { | |||||
| /* opt_writer */ | |||||
| template<typename T_value, typename = void> | |||||
| struct opt_writer; | |||||
| template<typename T> | |||||
| struct opt_writer< | |||||
| T, | |||||
| std::enable_if_t< | |||||
| std::is_same_v<bool, std::decay_t<T>>>> | |||||
| { | |||||
| static inline void write(CURL* handle, CURLoption opt, bool val) | |||||
| { | |||||
| easy_exception::throw_error( | |||||
| curl_easy_setopt(handle, opt, static_cast<long>(val)), | |||||
| "Unable to set option on easy handle."); | |||||
| } | |||||
| }; | |||||
| template<typename T> | |||||
| struct opt_writer< | |||||
| T, | |||||
| std::enable_if_t< | |||||
| std::is_same_v<long, std::decay_t<T>>>> | |||||
| { | |||||
| static inline void write(CURL* handle, CURLoption opt, long val) | |||||
| { | |||||
| easy_exception::throw_error( | |||||
| curl_easy_setopt(handle, opt, val), | |||||
| "Unable to set option on easy handle."); | |||||
| } | |||||
| }; | |||||
| template<typename T> | |||||
| struct opt_writer< | |||||
| T, | |||||
| std::enable_if_t< | |||||
| std::is_same_v<void*, std::decay_t<T>>>> | |||||
| { | |||||
| static inline void write(CURL* handle, CURLoption opt, void* val) | |||||
| { | |||||
| easy_exception::throw_error( | |||||
| curl_easy_setopt(handle, opt, val), | |||||
| "Unable to set option on easy handle."); | |||||
| } | |||||
| }; | |||||
| template<typename T> | |||||
| struct opt_writer< | |||||
| T, | |||||
| std::enable_if_t< | |||||
| std::is_same_v<data_callback, std::decay_t<T>>>> | |||||
| { | |||||
| static inline void write(CURL* handle, CURLoption opt, data_callback val) | |||||
| { | |||||
| easy_exception::throw_error( | |||||
| curl_easy_setopt(handle, opt, val), | |||||
| "Unable to set option on easy handle."); | |||||
| } | |||||
| }; | |||||
| template<typename T> | |||||
| struct opt_writer< | |||||
| T, | |||||
| std::enable_if_t< | |||||
| std::is_same_v<std::string, std::decay_t<T>>>> | |||||
| { | |||||
| static inline void write(CURL* handle, CURLoption opt, const std::string& val) | |||||
| { | |||||
| easy_exception::throw_error( | |||||
| curl_easy_setopt(handle, opt, val.c_str()), | |||||
| "Unable to set option on easy handle."); | |||||
| } | |||||
| }; | |||||
| template<typename T> | |||||
| struct opt_writer< | |||||
| T, | |||||
| std::enable_if_t< | |||||
| std::is_same_v<slist, std::decay_t<T>>>> | |||||
| { | |||||
| static inline void write(CURL* handle, CURLoption opt, const slist& val) | |||||
| { | |||||
| easy_exception::throw_error( | |||||
| curl_easy_setopt(handle, opt, val.handle()), | |||||
| "Unable to set option on easy handle."); | |||||
| } | |||||
| }; | |||||
| /* info_reader */ | |||||
| template<typename T_value, typename = void> | |||||
| struct info_reader; | |||||
| template<typename T> | |||||
| struct info_reader< | |||||
| T, | |||||
| std::enable_if_t< | |||||
| std::is_same_v<long, std::decay_t<T>>>> | |||||
| { | |||||
| static inline long read(CURL* handle, CURLINFO info) | |||||
| { | |||||
| long ret; | |||||
| easy_exception::throw_error( | |||||
| curl_easy_getinfo(handle, info, &ret), | |||||
| "Unable to get info from easy handle."); | |||||
| return ret; | |||||
| } | |||||
| }; | |||||
| template<typename T> | |||||
| struct info_reader< | |||||
| T, | |||||
| std::enable_if_t< | |||||
| std::is_same_v<std::string, std::decay_t<T>>>> | |||||
| { | |||||
| static inline std::string read(CURL* handle, CURLINFO info) | |||||
| { | |||||
| const char * ret; | |||||
| easy_exception::throw_error( | |||||
| curl_easy_getinfo(handle, info, &ret), | |||||
| "Unable to get info from easy handle."); | |||||
| return std::string(ret ? ret : ""); | |||||
| } | |||||
| }; | |||||
| } | |||||
| /* easy */ | |||||
| easy::easy() | |||||
| : _handle(nullptr, &curl_easy_cleanup) | |||||
| { | |||||
| if (!global::is_initialized()) | |||||
| throw multi_exception(CURLM_BAD_HANDLE, "libcurl was not initialized!"); | |||||
| _handle.reset(curl_easy_init()); | |||||
| if (!_handle) | |||||
| throw multi_exception(CURLM_OUT_OF_MEMORY, "Unable to create easy handle"); | |||||
| } | |||||
| CURL* easy::handle() const | |||||
| { return _handle.get(); } | |||||
| void easy::reset() | |||||
| { curl_easy_reset(_handle.get()); } | |||||
| void easy::perform() | |||||
| { | |||||
| easy_exception::throw_error( | |||||
| curl_easy_perform(_handle.get()), | |||||
| "Unable to perform easy handle operations."); | |||||
| } | |||||
| void easy::add_header(const std::string& s) | |||||
| { | |||||
| _header.append(s); | |||||
| set_option<CURLOPT_HTTPHEADER>(_header); | |||||
| } | |||||
| template<CURLoption T_option, typename T_value> | |||||
| void easy::set_option(const __impl::option<T_option, T_value>& opt) | |||||
| { __impl::opt_writer<T_value>::write(handle(), T_option, opt.value); } | |||||
| template<CURLoption T_option> | |||||
| void easy::set_option(const typename option<T_option>::value_type& val) | |||||
| { set_option(option<T_option>(val)); } | |||||
| template<CURLINFO T_info> | |||||
| typename info<T_info>::value_type easy::get_info() const | |||||
| { | |||||
| using info_type = info<T_info>; | |||||
| using value_type = typename info_type::value_type; | |||||
| return __impl::info_reader<value_type>::read(handle(), T_info); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,65 @@ | |||||
| #pragma once | |||||
| #include <curl/curl.h> | |||||
| #include <cppcurl/config.h> | |||||
| #ifdef CPPCURL_HAS_CPPCORE | |||||
| #include <cppcore/misc/exception.h> | |||||
| #else | |||||
| #include <exception> | |||||
| #endif | |||||
| namespace cppcurl | |||||
| { | |||||
| /** | |||||
| * @brief Exception to represent curl errors. | |||||
| */ | |||||
| template<typename T_error> | |||||
| struct exception | |||||
| #ifdef CPPCURL_HAS_CPPCORE | |||||
| : public ::cppcore::exception | |||||
| #else | |||||
| : public std::exception | |||||
| #endif | |||||
| { | |||||
| public: | |||||
| /** | |||||
| * @brief Throw an exception if the passed error is not OK. | |||||
| */ | |||||
| static inline void throw_error(T_error err, const std::string& msg); | |||||
| public: | |||||
| T_error error; | |||||
| const std::string error_str; | |||||
| /** | |||||
| * @brief Constructor. | |||||
| */ | |||||
| inline exception(T_error err, const std::string& msg); | |||||
| #ifdef CPPCURL_HAS_CPPCORE | |||||
| protected: | |||||
| /** | |||||
| * @brief Print the message of the exception to the passed stream. | |||||
| * | |||||
| * @param[in] os Stream to print message of the exception to. | |||||
| */ | |||||
| inline void print_message(std::ostream& os) const override; | |||||
| #else | |||||
| private: | |||||
| const std::string _what; | |||||
| public: | |||||
| /** | |||||
| * @brief Get the exception message. | |||||
| */ | |||||
| inline const char* what() const throw() override; | |||||
| #endif | |||||
| }; | |||||
| using easy_exception = exception<CURLcode>; | |||||
| using multi_exception = exception<CURLMcode>; | |||||
| } | |||||
| @@ -0,0 +1,79 @@ | |||||
| #pragma once | |||||
| #include "exception.h" | |||||
| namespace cppcurl | |||||
| { | |||||
| namespace __impl | |||||
| { | |||||
| template<typename T_error> | |||||
| struct get_error_str | |||||
| { | |||||
| inline std::string operator()(T_error err) const = delete; | |||||
| }; | |||||
| template<> | |||||
| struct get_error_str<CURLcode> | |||||
| { | |||||
| inline std::string operator()(CURLcode err) const | |||||
| { return curl_easy_strerror(err); } | |||||
| }; | |||||
| template<> | |||||
| struct get_error_str<CURLMcode> | |||||
| { | |||||
| inline std::string operator()(CURLMcode err) const | |||||
| { return curl_multi_strerror(err); } | |||||
| }; | |||||
| } | |||||
| /* exception */ | |||||
| template<typename T_error> | |||||
| void exception<T_error> | |||||
| ::throw_error(T_error err, const std::string& msg) | |||||
| { | |||||
| if (static_cast<bool>(err)) | |||||
| throw exception(err, msg); | |||||
| } | |||||
| #ifdef CPPCURL_HAS_CPPCORE | |||||
| template<typename T_error> | |||||
| exception<T_error> | |||||
| ::exception(T_error err, const std::string& msg) | |||||
| : ::cppcore::exception (msg) | |||||
| , error (err) | |||||
| , error_str (__impl::get_error_str<T_error>()(err)) | |||||
| { } | |||||
| template<typename T_error> | |||||
| void exception<T_error> | |||||
| ::print_message(std::ostream& os) const | |||||
| { | |||||
| os << error_str | |||||
| << '(' | |||||
| << static_cast<int>(error) | |||||
| << "): " | |||||
| << message; | |||||
| } | |||||
| #else | |||||
| template<typename T_error> | |||||
| exception<T_error> | |||||
| ::exception(T_error err, const std::string& msg) | |||||
| : _what (__impl::get_error_str<T_error>()(err) + "(" + std::to_string(static_cast<int>(err)) + "): " + msg) | |||||
| , error (err) | |||||
| , error_str (get_error_str<T_error>()(err)) | |||||
| { } | |||||
| template<typename T_error> | |||||
| const char* exception<T_error> | |||||
| ::what() const throw() | |||||
| { | |||||
| return _what.c_str(); | |||||
| } | |||||
| #endif | |||||
| } | |||||
| @@ -0,0 +1,37 @@ | |||||
| #pragma once | |||||
| namespace cppcurl | |||||
| { | |||||
| /** | |||||
| * @brief Initializes libcurl. | |||||
| */ | |||||
| struct global | |||||
| { | |||||
| public: | |||||
| /** | |||||
| * @brief Constructor. | |||||
| */ | |||||
| inline global(); | |||||
| /** | |||||
| * @brief Destructor. | |||||
| */ | |||||
| inline ~global(); | |||||
| public: | |||||
| /** | |||||
| * @brief Get the initialization state of cppcurl. | |||||
| */ | |||||
| static inline bool is_initialized(); | |||||
| private: | |||||
| /** | |||||
| * @brief Get the counter of initialized instances. | |||||
| */ | |||||
| static inline int& counter(); | |||||
| }; | |||||
| } | |||||
| #include "global.inl" | |||||
| @@ -0,0 +1,41 @@ | |||||
| #pragma once | |||||
| #include <curl/curl.h> | |||||
| #include "global.h" | |||||
| #include "exception.inl" | |||||
| namespace cppcurl | |||||
| { | |||||
| /* global */ | |||||
| global::global() | |||||
| { | |||||
| if (counter()++ == 0) | |||||
| { | |||||
| auto err = curl_global_init(CURL_GLOBAL_DEFAULT); | |||||
| if (err != CURLE_OK) | |||||
| throw easy_exception(err, "Unable to initialize libcurl"); | |||||
| } | |||||
| } | |||||
| global::~global() | |||||
| { | |||||
| if (--counter() == 0) | |||||
| { | |||||
| // TODO logging? | |||||
| curl_global_cleanup(); | |||||
| } | |||||
| } | |||||
| bool global::is_initialized() | |||||
| { return static_cast<bool>(counter()); } | |||||
| int& global::counter() | |||||
| { | |||||
| static int value(0); | |||||
| return value; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,38 @@ | |||||
| #pragma once | |||||
| #include <curl/curl.h> | |||||
| namespace cppcurl | |||||
| { | |||||
| namespace __impl | |||||
| { | |||||
| template<CURLINFO T_info, typename T_value> | |||||
| struct info | |||||
| { | |||||
| public: | |||||
| using value_type = T_value; | |||||
| static constexpr CURLINFO id = T_info; | |||||
| public: | |||||
| value_type value; | |||||
| }; | |||||
| } | |||||
| template<CURLINFO T_info> | |||||
| struct info; | |||||
| #define cppcurl_define_info(nfo, type) \ | |||||
| template<> \ | |||||
| struct info<nfo> \ | |||||
| : public __impl::info<nfo, type> \ | |||||
| { } | |||||
| cppcurl_define_info(CURLINFO_CONTENT_TYPE, std::string); | |||||
| cppcurl_define_info(CURLINFO_RESPONSE_CODE, long); | |||||
| #undef cppcurl_define_info | |||||
| } | |||||
| @@ -0,0 +1,80 @@ | |||||
| #pragma once | |||||
| #include <memory> | |||||
| #include <curl/curl.h> | |||||
| namespace cppcurl | |||||
| { | |||||
| struct easy; | |||||
| struct multi | |||||
| { | |||||
| private: | |||||
| using handle_ptr_u = std::unique_ptr<CURLM, decltype(&curl_multi_cleanup)>; | |||||
| private: | |||||
| handle_ptr_u _handle; | |||||
| public: | |||||
| /** | |||||
| * @brief Constructor. | |||||
| */ | |||||
| inline multi(); | |||||
| /** | |||||
| * @brief Get the libcurl multi handle. | |||||
| */ | |||||
| inline CURLM * handle() const; | |||||
| /** | |||||
| * @brief Add a standard curl handle to the multi stack. | |||||
| */ | |||||
| inline void add_handle(const easy& e); | |||||
| /** | |||||
| * @brief Removes a curl handle from the multi stack again. | |||||
| */ | |||||
| inline void remove_handle(const easy& e); | |||||
| /** | |||||
| * @brief Write all file descriptors known by the object to the passed file descriptor sets. | |||||
| * | |||||
| * @param[in] read File descriptor set to listen for read operations. | |||||
| * @param[in] write File descriptor set to listen for write operations. | |||||
| * @param[in] except File descriptor set to listen for exceptional condition. | |||||
| * | |||||
| * @return Greatest file descriptor. | |||||
| */ | |||||
| inline int prepare_fdsets(fd_set& read, fd_set& write, fd_set& except) const; | |||||
| /** | |||||
| * @brief Perform any operations on the multi handle. | |||||
| * | |||||
| * @return Number of running easy handles. | |||||
| */ | |||||
| inline int perform(); | |||||
| /** | |||||
| * @brief Get the max timeout to wait for file descriptors. | |||||
| * | |||||
| * @return Timeout to wait for file descriptors or -1 if not relevant. | |||||
| */ | |||||
| inline long timeout() const; | |||||
| /** | |||||
| * @brief Read pending messages from the queue. | |||||
| */ | |||||
| inline CURLMsg * read_info() const; | |||||
| /** | |||||
| * @brief Read all pending messages from the queue. | |||||
| * Call the passed predicate one for each message. | |||||
| */ | |||||
| template<typename T_pred> | |||||
| inline void read_infos(const T_pred&& pred) const; | |||||
| }; | |||||
| } | |||||
| #include "multi.inl" | |||||
| @@ -0,0 +1,84 @@ | |||||
| #pragma once | |||||
| #include "multi.h" | |||||
| #include "easy.inl" | |||||
| #include "global.inl" | |||||
| #include "exception.inl" | |||||
| namespace cppcurl | |||||
| { | |||||
| /* multi */ | |||||
| multi::multi() | |||||
| : _handle(nullptr, &curl_multi_cleanup) | |||||
| { | |||||
| if (!global::is_initialized()) | |||||
| throw multi_exception(CURLM_BAD_HANDLE, "libcurl was not initialized!"); | |||||
| _handle.reset(curl_multi_init()); | |||||
| if (!_handle) | |||||
| throw multi_exception(CURLM_OUT_OF_MEMORY, "Unable to create multi handle"); | |||||
| } | |||||
| CURLM * multi::handle() const | |||||
| { return _handle.get(); } | |||||
| void multi::add_handle(const easy& e) | |||||
| { | |||||
| multi_exception::throw_error( | |||||
| curl_multi_add_handle(_handle.get(), e.handle()), | |||||
| "Unable to add easy handle to multi handle"); | |||||
| } | |||||
| void multi::remove_handle(const easy& e) | |||||
| { | |||||
| if (!e.handle()) | |||||
| return; | |||||
| multi_exception::throw_error( | |||||
| curl_multi_remove_handle(_handle.get(), e.handle()), | |||||
| "Unable to remove easy handle from multi handle"); | |||||
| } | |||||
| int multi::prepare_fdsets(fd_set& read, fd_set& write, fd_set& except) const | |||||
| { | |||||
| int ret = -1; | |||||
| multi_exception::throw_error( | |||||
| curl_multi_fdset(_handle.get(), &read, &write, &except, &ret), | |||||
| "Unable to get the file descriptor sets from multi handle"); | |||||
| return ret; | |||||
| } | |||||
| int multi::perform() | |||||
| { | |||||
| int ret = 0; | |||||
| multi_exception::throw_error( | |||||
| curl_multi_perform(_handle.get(), &ret), | |||||
| "Unable to perform the operations on the multi handle"); | |||||
| return ret; | |||||
| } | |||||
| long multi::timeout() const | |||||
| { | |||||
| long ret; | |||||
| multi_exception::throw_error( | |||||
| curl_multi_timeout(_handle.get(), &ret), | |||||
| "Unable to get timeout from multi handle"); | |||||
| return ret; | |||||
| } | |||||
| CURLMsg * multi::read_info() const | |||||
| { | |||||
| int i; | |||||
| return curl_multi_info_read(_handle.get(), &i); | |||||
| } | |||||
| template<typename T_pred> | |||||
| void multi::read_infos(const T_pred&& pred) const | |||||
| { | |||||
| CURLMsg * msg; | |||||
| while ((msg = read_info())) | |||||
| pred(*msg); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,56 @@ | |||||
| #pragma once | |||||
| #include <curl/curl.h> | |||||
| #include "slist.h" | |||||
| namespace cppcurl | |||||
| { | |||||
| namespace __impl | |||||
| { | |||||
| template<CURLoption T_option, typename T_value> | |||||
| struct option | |||||
| { | |||||
| public: | |||||
| using value_type = T_value; | |||||
| static constexpr CURLoption id = T_option; | |||||
| public: | |||||
| value_type value; | |||||
| public: | |||||
| inline option(const T_value& p_value) | |||||
| : value(p_value) | |||||
| { } | |||||
| }; | |||||
| } | |||||
| using data_callback = size_t (*) (char*, size_t, size_t, void*); | |||||
| template<CURLoption T_option> | |||||
| struct option; | |||||
| #define cppcurl_define_option(opt, type) \ | |||||
| template<> \ | |||||
| struct option<opt> \ | |||||
| : public __impl::option<opt, type> \ | |||||
| { using __impl::option<opt, type>::option; } | |||||
| cppcurl_define_option(CURLOPT_HTTPHEADER, const slist&); | |||||
| cppcurl_define_option(CURLOPT_PRIVATE, void*); | |||||
| cppcurl_define_option(CURLOPT_POST, bool); | |||||
| cppcurl_define_option(CURLOPT_READFUNCTION, data_callback); | |||||
| cppcurl_define_option(CURLOPT_READDATA, void*); | |||||
| cppcurl_define_option(CURLOPT_WRITEFUNCTION, data_callback); | |||||
| cppcurl_define_option(CURLOPT_WRITEDATA, void*); | |||||
| cppcurl_define_option(CURLOPT_URL, std::string); | |||||
| cppcurl_define_option(CURLOPT_POSTFIELDSIZE, long); | |||||
| cppcurl_define_option(CURLOPT_TIMEOUT, long); | |||||
| cppcurl_define_option(CURLOPT_FOLLOWLOCATION, bool); | |||||
| #undef cppcurl_define_option | |||||
| } | |||||
| @@ -0,0 +1,44 @@ | |||||
| #pragma once | |||||
| #include <string> | |||||
| #include <vector> | |||||
| #include <memory> | |||||
| #include <curl/curl.h> | |||||
| namespace cppcurl | |||||
| { | |||||
| struct slist | |||||
| { | |||||
| private: | |||||
| using handle_ptr_u = std::unique_ptr<curl_slist, decltype(&curl_slist_free_all)>; | |||||
| using string_vector = std::vector<std::string>; | |||||
| private: | |||||
| handle_ptr_u _handle; | |||||
| public: | |||||
| /** | |||||
| * @brief Constructor. | |||||
| */ | |||||
| inline slist(); | |||||
| /** | |||||
| * @brief Get the internal curl easy handle. | |||||
| */ | |||||
| inline curl_slist* handle() const; | |||||
| /** | |||||
| * @brief Add string to the list. | |||||
| */ | |||||
| inline void append(const std::string& s); | |||||
| /** | |||||
| * @brief clear the list. | |||||
| */ | |||||
| inline void reset(); | |||||
| }; | |||||
| } | |||||
| #include "slist.inl" | |||||
| @@ -0,0 +1,23 @@ | |||||
| #pragma once | |||||
| #include "slist.h" | |||||
| namespace cppcurl | |||||
| { | |||||
| /* slist */ | |||||
| slist::slist() | |||||
| : _handle(nullptr, &curl_slist_free_all) | |||||
| { } | |||||
| curl_slist* slist::handle() const | |||||
| { return _handle.get(); } | |||||
| void slist::append(const std::string& s) | |||||
| { _handle.reset(curl_slist_append(_handle.release(), s.c_str())); } | |||||
| void slist::reset() | |||||
| { _handle.reset(); } | |||||
| } | |||||
| @@ -0,0 +1,43 @@ | |||||
| # Initialize ###################################################################################### | |||||
| Include ( cotire OPTIONAL RESULT_VARIABLE HAS_COTIRE ) | |||||
| Include ( pedantic OPTIONAL RESULT_VARIABLE HAS_PEDANTIC ) | |||||
| Include ( strip_symbols OPTIONAL RESULT_VARIABLE HAS_STRIP_SYMBOLS ) | |||||
| Find_Package ( CURL REQUIRED) | |||||
| Find_Package ( cppcore QUIET ) | |||||
| If ( cppcore_FOUND ) | |||||
| Set ( CPPCURL_HAS_CPPCORE true ) | |||||
| EndIf ( ) | |||||
| # Interface Library ############################################################################### | |||||
| Set ( CPPCURL_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../include ) | |||||
| Set ( CPPCURL_GENERATED_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated/include ) | |||||
| Configure_File ( ${CMAKE_CURRENT_SOURCE_DIR}/../cmake/config.h.in | |||||
| ${CPPCURL_GENERATED_INCLUDE_DIR}/cppcurl/config.h ) | |||||
| Add_Library ( cppcurl INTERFACE ) | |||||
| Target_Include_Directories ( cppcurl | |||||
| INTERFACE | |||||
| $<BUILD_INTERFACE:${CPPCURL_INCLUDE_DIR}> | |||||
| $<BUILD_INTERFACE:${CPPCURL_GENERATED_INCLUDE_DIR}> | |||||
| $<INSTALL_INTERFACE:${CPPCURL_INSTALL_DIR_INCLUDE}> ) | |||||
| If ( CPPCURL_HAS_CPPCORE ) | |||||
| Target_Link_Libraries ( cppcurl | |||||
| INTERFACE | |||||
| cppcore | |||||
| CURL::libcurl ) | |||||
| EndIf ( ) | |||||
| # Install ######################################################################################### | |||||
| # Header | |||||
| Install ( FILES ${CPPCURL_INCLUDE_DIR}/cppcurl.h | |||||
| DESTINATION ${CPPCURL_INSTALL_DIR_INCLUDE} ) | |||||
| Install ( DIRECTORY ${CPPCURL_INCLUDE_DIR}/cppcurl | |||||
| DESTINATION ${CPPCURL_INSTALL_DIR_INCLUDE} ) | |||||
| Install ( DIRECTORY ${CPPCURL_GENERATED_INCLUDE_DIR}/cppcurl | |||||
| DESTINATION ${CPPCURL_INSTALL_DIR_INCLUDE} ) | |||||
| Install ( TARGETS cppcurl | |||||
| EXPORT cppcurl | |||||
| DESTINATION ${CPPCURL_INSTALL_DIR_INCLUDE} ) | |||||
| @@ -0,0 +1,43 @@ | |||||
| # Initialize ###################################################################################### | |||||
| Include ( cotire OPTIONAL RESULT_VARIABLE HAS_COTIRE ) | |||||
| Include ( pedantic OPTIONAL RESULT_VARIABLE HAS_PEDANTIC ) | |||||
| Include ( cmake_tests OPTIONAL RESULT_VARIABLE HAS_CMAKE_TESTS ) | |||||
| # Test ############################################################################################ | |||||
| Find_Package ( GTest ) | |||||
| If ( NOT "${GTest_FOUND}" ) | |||||
| Return ( ) | |||||
| EndIf ( ) | |||||
| File ( GLOB_RECURSE CPPCURL_TEST_HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h ) | |||||
| File ( GLOB_RECURSE CPPCURL_TEST_INLINE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.inl ) | |||||
| File ( GLOB_RECURSE CPPCURL_TEST_SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp ) | |||||
| Add_Executable ( cppcurl-test | |||||
| EXCLUDE_FROM_ALL | |||||
| ${CPPCURL_TEST_HEADER_FILES} | |||||
| ${CPPCURL_TEST_INLINE_FILES} | |||||
| ${CPPCURL_TEST_SOURCE_FILES} ) | |||||
| Target_Link_Libraries ( cppcurl-test | |||||
| PUBLIC | |||||
| cppcurl | |||||
| GTest::Main ) | |||||
| # pedantic | |||||
| If ( HAS_PEDANTIC ) | |||||
| Pedantic_Apply_Flags_Target ( cppcurl-test ALL ) | |||||
| EndIf ( ) | |||||
| # optimization | |||||
| If ( HAS_COTIRE ) | |||||
| Cotire ( cppcurl-test ) | |||||
| EndIf ( ) | |||||
| # test | |||||
| If ( HAS_CMAKE_TESTS ) | |||||
| Add_CMake_Test ( NAME cppcurl TARGET cppcurl-test ) | |||||
| Else ( ) | |||||
| Add_Test ( NAME cppcurl COMMAND cppcurl-test ) | |||||
| EndIf ( ) | |||||
| @@ -0,0 +1,10 @@ | |||||
| #include <gtest/gtest.h> | |||||
| #include <cppcurl.h> | |||||
| using namespace ::testing; | |||||
| using namespace ::cppcurl; | |||||
| TEST(cppcurl, dummy) | |||||
| { | |||||
| } | |||||