4coder/test_data/lots_of_files/gjNetwork.h

228 lines
8.9 KiB
C
Raw Normal View History

2018-03-16 18:19:11 +00:00
///////////////////////////////////////////////////////////////////
//*-------------------------------------------------------------*//
//| Part of the Game Jolt API C++ Library (http://gamejolt.com) |//
//*-------------------------------------------------------------*//
//| Released under the zlib License |//
//| More information available in the readme file |//
//*-------------------------------------------------------------*//
///////////////////////////////////////////////////////////////////
#pragma once
#ifndef _GJ_GUARD_NETWORK_H_
#define _GJ_GUARD_NETWORK_H_
// ****************************************************************
/*! Main network interface class.\n
* Send requests, fetch data and download files with the cURL library.\n
* http://curl.haxx.se/
* \brief Network Interface */
class gjNetwork final
{
private:
// ****************************************************************
/*! Callback interface class for non-blocking cURL sessions.\n
* \brief Callback Interface */
class gjCall
{
protected:
CURL* m_pSession; //!< cURL session
std::string m_sInfo; //!< information about this callback
public:
gjCall(CURL* pSession, const std::string& sInfo)noexcept : m_pSession(pSession), m_sInfo(sInfo) {}
virtual ~gjCall() {}
/*! \name Finish Session */
//! @{
virtual void Finish(const bool& bOK) = 0;
//! @}
/*! \name Get Attributes */
//! @{
inline CURL* GetSession()const {return m_pSession;} //!< \copybrief m_pSession
inline const std::string& GetInfo()const {return m_sInfo;} //!< \copybrief m_sInfo
/*! */ //! @}
};
// ****************************************************************
/*! Template bridge for the callback interface class.\n
* T = type of output receiving object\n
* P = type of processing object\n
* D = output type\n
* \brief Template Bridge */
template <typename P, typename D> class gjCallTemplate : public gjCall
{
protected:
/*! \brief Output Interface Structure */
template <typename Ds> struct sOutput
{
virtual ~sOutput() {}
/*! \name Execute Output Callback */
//! @{
virtual void Execute(const Ds& pProcessedOutput) = 0;
//! @}
};
/*! \brief Specific Output Structure */
template <typename T, typename Ds> struct sOutputSpecific : public sOutput<Ds>
{
T* m_pOutputObj; //!< object with output callback function
void (T::*m_OutputCallback)(const Ds&, void*); //!< callback function to receive the data object when finished
void* m_pOutputData; //!< additional data for the output callback
/*! \name Execute Output Callback */
//! @{
void Execute(const Ds& pProcessedOutput)override {(m_pOutputObj->*(m_OutputCallback))(pProcessedOutput, m_pOutputData);}
//! @}
};
protected:
P* m_pProcessObj; //!< object with processing callback function
int (P::*m_ProcessCallback)(const std::string&, void*, D*); //!< callback function to convert the response string to a data object
void* m_pProcessData; //!< additional data for the processing callback
std::vector<sOutput<D>*> m_apOutput; //!< list of output structs
public:
gjCallTemplate(CURL* pSession, const std::string& sInfo, GJ_NETWORK_PROCESS)noexcept;
virtual ~gjCallTemplate();
/*! \name Add Output */
//! @{
template <typename T> void AddOutput(GJ_NETWORK_OUTPUT(D));
//! @}
};
// ****************************************************************
/*! Request callback sub-interface class for non-blocking cURL sessions.\n
* \brief Request Callback Sub-Interface */
template <typename P, typename D> class gjCallRequest final : public gjCallTemplate<P,D>
{
private:
std::string* m_psResponse; //!< response string of the request
curl_httppost* m_pPostList; //!< data for a POST request
public:
gjCallRequest(std::string* psResponse, curl_httppost* pPostList, CURL* pSession, const std::string& sInfo, GJ_NETWORK_PROCESS)noexcept
: gjCallTemplate<P,D>(pSession, sInfo, GJ_NETWORK_PROCESS_FW), m_psResponse(psResponse), m_pPostList(pPostList) {}
/*! \name Finish Session */
//! @{
void Finish(const bool& bOK)override;
//! @}
};
// ****************************************************************
/*! Download callback sub-interface class for non-blocking cURL sessions.\n
* \brief Download Callback Sub-Interface */
template <typename P, typename D> class gjCallDownload final : public gjCallTemplate<P,D>
{
private:
FILE* m_pFile; //!< file handle
std::string m_sPath; //!< local path of the file
public:
gjCallDownload(FILE* pFile, const std::string& sPath, CURL* pSession, const std::string& sInfo, GJ_NETWORK_PROCESS)noexcept
: gjCallTemplate<P,D>(pSession, sInfo, GJ_NETWORK_PROCESS_FW), m_pFile(pFile), m_sPath(sPath) {}
/*! \name Finish Session */
//! @{
void Finish(const bool& bOK)override;
//! @}
};
private:
CURLM* m_pMultiHandle; //!< handle for simultaneous cURL operations
int m_iNumSessions; //!< current number of active cURL sessions
std::vector<gjCall*> m_apCall; //!< list of callback objects
gjAPI* m_pAPI; //!< main interface access pointer
public:
gjNetwork(gjAPI* pAPI)noexcept;
~gjNetwork();
/*! \name Update */
//! @{
/*! Update all active non-blocking cURL sessions.\n
* Execute associated callback functions when a session is finished.
* \return TRUE when active, FALSE when idle */
bool Update();
//! @}
/*! \name Wait */
//! @{
/*! Finish all active sessions and return.
* \param iMaxWait Max waiting time in seconds (0 = until everything is finished) */
void Wait(const unsigned int& iMaxWait);
//! @}
/*! \name Send Request */
//! @{
/*! Send a direct or non-blocking request to the API.\n
* Retrieve a response string when finished.
* \note Creates a non-blocking session when output string is NULL\n
* Use "&POST<data>" at the end of the URL for a POST request
* \param sURL Relative API request string
* \return **GJ_OK** on success\n
* **GJ_REQUEST_FAILED** if request was unsuccessful\n
* **GJ_INVALID_INPUT** if URL string is empty\n
* **GJ_NETWORK_ERROR** if session cannot be established\n
* (see #GJ_ERROR) */
template <typename T, typename P, typename D> int SendRequest(const std::string& sURL, std::string* psOutput, GJ_NETWORK_PROCESS, GJ_NETWORK_OUTPUT(D))noexcept;
//! @}
/*! \name Download File */
//! @{
/*! Download a file direct or non-blocking from any URL.\n
* Retrieve the local path of the file when finished.
* \note Creates a non-blocking session when output string is NULL
* \param sURL Full path of the remote file
* \param sToFile Relative path of the download target
* \return **GJ_OK** on success\n
* **GJ_REQUEST_FAILED** if request was unsuccessful\n
* **GJ_INVALID_INPUT** if URL string or target file string is empty\n
* **GJ_NETWORK_ERROR** if session cannot be established\n
* **GJ_FILE_ERROR** if file cannot be written\n
* (see #GJ_ERROR) */
template <typename T, typename P, typename D> int DownloadFile(const std::string& sURL, const std::string& sToFile, std::string* psOutput, GJ_NETWORK_PROCESS, GJ_NETWORK_OUTPUT(D))noexcept;
//! @}
/*! \name Get Attributes */
//! @{
inline size_t GetNumSessions()const {return m_apCall.size();} //!< \copybrief m_iNumSessions
/*! */ //! @}
private:
DISABLE_COPY(gjNetwork)
/*! \name Management Functions */
//! @{
gjCall* __CheckCall(const std::string& sInfo);
void __KillCall(gjCall* pCall);
//! @}
};
// ****************************************************************
/*! Writing Callbacks */
size_t write_to_string(char* ptr, size_t size, size_t count, std::string* stream);
size_t write_to_file(void* ptr, size_t size, size_t count, FILE* stream);
// template implementation can be found in gjNetwork.hpp
#endif /* _GJ_GUARD_NETWORK_H_ */