4coder/test_data/lots_of_files/gjDataItem.h

299 lines
14 KiB
C++

///////////////////////////////////////////////////////////////////
//*-------------------------------------------------------------*//
//| 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_DATAITEM_H_
#define _GJ_GUARD_DATAITEM_H_
// ****************************************************************
/*! Data store item class.\n
* http://gamejolt.com/api/doc/game/data-store/
* \brief Data Store Item Object
* \bug Data store items are not UTF-8 compatible (server-side),\n
* if you have problems with string data, use Base64 instead */
class gjDataItem final
{
private:
std::string m_sKey; //!< unique key of this item
std::string m_sData; //!< semi-cached data
int m_iType; //!< type of this item (0 = global, 1 = user)
std::string m_sVerify; //!< temporary verification data (helper)
void* m_pTarget; //!< last target for binary data (helper)
gjAPI* m_pAPI; //!< main interface access pointer
public:
gjDataItem(const gjData& aDataItemData, const int& iType, gjAPI* pAPI)noexcept;
/*! \name Set Data Request */
//! @{
/*! Set data of this data store item through an API request.\n
* May does nothing, if this is an user item and the same data was already sent.
* \pre Login maybe required
* \note \b -Now blocks, \b -Call uses non-blocking callbacks
* \param sData Data to send
* \return **GJ_OK** on success\n
* **GJ_REQUEST_FAILED** if request was unsuccessful\n
* **GJ_REQUEST_CANCELED** if this is an user item and the same data was already sent\n
* **GJ_NOT_CONNECTED** if connection/login is missing\n
* (see #GJ_ERROR) */
inline int SetDataNow(const std::string& sData) {return this->__SetData(sData, true, GJ_NETWORK_NULL_API(gjDataItemPtr));}
inline int SetDataCall(const std::string& sData) {return this->__SetData(sData, false, GJ_NETWORK_NULL_API(gjDataItemPtr));}
template <typename T> inline int SetDataCall(const std::string& sData, GJ_NETWORK_OUTPUT(gjDataItemPtr)) {return this->__SetData(sData, false, GJ_NETWORK_OUTPUT_FW);}
//! @}
/*! \name Set Data Request Base64 */
//! @{
/*! Like \link SetDataNow SetData\endlink\n
* Allows to send data in binary form.
* \pre Login maybe required
* \note \b -Now blocks, \b -Call uses non-blocking callbacks
* \param pData Data in binary form to send
* \param iSize Size of the data
* \return **GJ_OK** on success\n
* **GJ_REQUEST_FAILED** if request was unsuccessful\n
* **GJ_REQUEST_CANCELED** if this is an user item and the same data was already sent\n
* **GJ_NOT_CONNECTED** if connection/login is missing\n
* (see #GJ_ERROR) */
inline int SetDataBase64Now(void* pData, const size_t& iSize) {return this->__SetDataBase64(pData, iSize, true, GJ_NETWORK_NULL_API(gjDataItemPtr));}
inline int SetDataBase64Call(void* pData, const size_t& iSize) {return this->__SetDataBase64(pData, iSize, false, GJ_NETWORK_NULL_API(gjDataItemPtr));}
template <typename T> inline int SetDataBase64Call(void* pData, const size_t& iSize, GJ_NETWORK_OUTPUT(gjDataItemPtr)) {return this->__SetDataBase64(pData, iSize, false, GJ_NETWORK_OUTPUT_FW);}
//! @}
/*! \name Get Data Request */
//! @{
/*! Get data of this data store item through an API request.
* \pre Login maybe required
* \note \b -Now blocks, \b -Call uses non-blocking callbacks
* \return **GJ_OK** on success\n
* **GJ_REQUEST_FAILED** if request was unsuccessful\n
* **GJ_NOT_CONNECTED** if connection/login is missing\n
* (see #GJ_ERROR) */
inline int GetDataNow(std::string* psOutput) {if(!psOutput) return GJ_INVALID_INPUT; return this->__GetData(psOutput, GJ_NETWORK_NULL_API(std::string));}
template <typename T> inline int GetDataCall(GJ_NETWORK_OUTPUT(std::string)) {return this->__GetData(NULL, GJ_NETWORK_OUTPUT_FW);}
//! @}
/*! \name Get Data Request Base64 */
//! @{
/*! Like \link GetDataNow GetData\endlink\n
* Allows to get data in binary form.
* \pre Login maybe required
* \note \b -Now blocks, \b -Call uses non-blocking callbacks
* \param pTarget Pointer to the target
* \param iSize Size of the target
* \return **GJ_OK** on success\n
* **GJ_REQUEST_FAILED** if request was unsuccessful\n
* **GJ_NOT_CONNECTED** if connection/login is missing\n
* (see #GJ_ERROR) */
inline int GetDataBase64Now(void* pTarget, const size_t& iSize) {if(!pTarget || iSize <= 0) return GJ_INVALID_INPUT; return this->__GetDataBase64(pTarget, iSize, true, GJ_NETWORK_NULL_API(gjVoidPtr));}
inline int GetDataBase64Call(void* pTarget, const size_t& iSize) {if(!pTarget || iSize <= 0) return GJ_INVALID_INPUT; return this->__GetDataBase64(pTarget, iSize, false, GJ_NETWORK_NULL_API(gjVoidPtr));}
template <typename T> inline int GetDataBase64Call(void* pTarget, const size_t& iSize, GJ_NETWORK_OUTPUT(gjVoidPtr)) {if(!pTarget || iSize <= 0) return GJ_INVALID_INPUT; return this->__GetDataBase64(pTarget, iSize, false, GJ_NETWORK_OUTPUT_FW);}
//! @}
/*! \name Remove Request */
//! @{
/*! Clears/Removes the data store item through an API request.\n
* \pre Login maybe required
* \note \b -Now blocks, \b -Call uses non-blocking callbacks
* \return **GJ_OK** on success\n
* **GJ_REQUEST_FAILED** if request was unsuccessful\n
* **GJ_NOT_CONNECTED** if connection/login is missing\n
* (see #GJ_ERROR) */
inline int RemoveNow() {return this->__Remove(true, GJ_NETWORK_NULL_API(gjDataItemPtr));}
inline int RemoveCall() {return this->__Remove(false, GJ_NETWORK_NULL_API(gjDataItemPtr));}
template <typename T> inline int RemoveCall(GJ_NETWORK_OUTPUT(gjDataItemPtr)) {return this->__Remove(false, GJ_NETWORK_OUTPUT_FW);}
//! @}
/*! \name Get Attributes */
//! @{
inline const std::string& GetKey()const {return m_sKey;} //!< \copybrief m_sKey
inline const int& GetType()const {return m_iType;} //!< \copybrief m_iType
/*! */ //! @}
private:
DISABLE_COPY(gjDataItem)
/*! \name Superior Request Functions */
//! @{
template <typename T> int __SetData(const std::string& sData, const bool& bNow, GJ_NETWORK_OUTPUT(gjDataItemPtr));
template <typename T> int __SetDataBase64(void* pData, const size_t& iSize, const bool& bNow, GJ_NETWORK_OUTPUT(gjDataItemPtr));
template <typename T> int __GetData(std::string* psOutput, GJ_NETWORK_OUTPUT(std::string));
template <typename T> int __GetDataBase64(void* pTarget, const size_t& iSize, const bool& bNow, GJ_NETWORK_OUTPUT(gjVoidPtr));
template <typename T> int __Remove(const bool& bNow, GJ_NETWORK_OUTPUT(gjDataItemPtr));
//! @}
/*! \name Callback Functions */
//! @{
int __SetDataCallback(const std::string& sData, void* pAdd, gjDataItemPtr* ppOutput);
int __GetDataCallback(const std::string& sData, void* pAdd, std::string* psOutput);
int __GetDataBase64Callback(const std::string& sData, void* pAdd, gjVoidPtr* ppOutput);
int __RemoveCallback(const std::string& sData, void* pAdd, gjDataItemPtr* ppOutput);
//! @}
};
// ****************************************************************
/* set data of this data store item */
template <typename T> int gjDataItem::__SetData(const std::string& sData, const bool& bNow, GJ_NETWORK_OUTPUT(gjDataItemPtr))
{
if(!m_pAPI->IsUserConnected() && m_iType) return GJ_NOT_CONNECTED;
// cancel request if data was already sent
if(sData == m_sData && m_iType) return GJ_REQUEST_CANCELED;
// set verification data
m_sVerify = sData;
// access user or global data store item
const std::string sUserData = m_iType ?
"&username=" + m_pAPI->GetProcUserName() +
"&user_token=" + m_pAPI->GetProcUserToken() :
"";
// send set data store request
std::string sResponse;
if(m_pAPI->SendRequest("/data-store/set/"
"?game_id=" + m_pAPI->GetProcGameID() +
"&key=" + gjAPI::UtilEscapeString(m_sKey) +
sUserData + "&POST" + sData, bNow ? &sResponse : NULL, this, &gjDataItem::__SetDataCallback, &m_sVerify, GJ_NETWORK_OUTPUT_FW)) return GJ_REQUEST_FAILED;
if(bNow) return this->__SetDataCallback(sResponse, &m_sVerify, NULL);
return GJ_OK;
}
// ****************************************************************
/* set Base64 data of this data store item */
template <typename T> int gjDataItem::__SetDataBase64(void* pData, const size_t& iSize, const bool& bNow, GJ_NETWORK_OUTPUT(gjDataItemPtr))
{
if(!m_pAPI->IsUserConnected() && m_iType) return GJ_NOT_CONNECTED;
if(!pData || iSize <= 0) return GJ_INVALID_INPUT;
const size_t iNeed = base64_needed(iSize);
// convert binary data to Base64 string
char* pcBase64 = new char[iNeed];
base64_encode((unsigned char*)pData, iSize, pcBase64, iNeed);
// execute set data function with Base64 string
const int iReturn = this->__SetData(pcBase64, bNow, GJ_NETWORK_OUTPUT_FW);
SAFE_DELETE_ARRAY(pcBase64)
return iReturn;
}
// ****************************************************************
/* get data of this data store item */
template <typename T> int gjDataItem::__GetData(std::string* psOutput, GJ_NETWORK_OUTPUT(std::string))
{
if(!m_pAPI->IsUserConnected() && m_iType) return GJ_NOT_CONNECTED;
const bool bNow = psOutput ? true : false;
// check for cached data
if(m_iType)
{
if(m_sData.length())
{
if(bNow) (*psOutput) = m_sData;
else (pOutputObj->*OutputCallback)(m_sData, pOutputData);
return GJ_OK;
}
}
// access user or global data store item
const std::string sUserData = m_iType ?
"&username=" + m_pAPI->GetProcUserName() +
"&user_token=" + m_pAPI->GetProcUserToken() :
"";
// send get data store request
std::string sResponse;
if(m_pAPI->SendRequest("/data-store/"
"?game_id=" + m_pAPI->GetProcGameID() +
"&key=" + gjAPI::UtilEscapeString(m_sKey) +
"&format=" + "dump" +
sUserData, bNow ? &sResponse : NULL, this, &gjDataItem::__GetDataCallback, NULL, GJ_NETWORK_OUTPUT_FW)) return GJ_REQUEST_FAILED;
if(bNow) return this->__GetDataCallback(sResponse, NULL, psOutput);
return GJ_OK;
}
// ****************************************************************
/* get Base64 data of this data store item */
template <typename T> int gjDataItem::__GetDataBase64(void* pTarget, const size_t& iSize, const bool& bNow, GJ_NETWORK_OUTPUT(gjVoidPtr))
{
if(!m_pAPI->IsUserConnected() && m_iType) return GJ_NOT_CONNECTED;
if(!pTarget || iSize <= 0) return GJ_INVALID_INPUT;
// save last target
m_pTarget = pTarget;
// check for cached data
if(m_iType)
{
if(m_sData.length())
{
// convert Base64 string to binary data
base64_decode(m_sData.c_str(), (unsigned char*)m_pTarget, iSize);
if(!bNow) (pOutputObj->*OutputCallback)(m_pTarget, pOutputData);
return GJ_OK;
}
}
// access user or global data store item
const std::string sUserData = m_iType ?
"&username=" + m_pAPI->GetProcUserName() +
"&user_token=" + m_pAPI->GetProcUserToken() :
"";
// send get data store request
std::string sResponse;
if(m_pAPI->SendRequest("/data-store/"
"?game_id=" + m_pAPI->GetProcGameID() +
"&key=" + gjAPI::UtilEscapeString(m_sKey) +
"&format=" + "dump" +
sUserData, bNow ? &sResponse : NULL, this, &gjDataItem::__GetDataBase64Callback, I_TO_P(iSize), GJ_NETWORK_OUTPUT_FW)) return GJ_REQUEST_FAILED;
if(bNow) return this->__GetDataBase64Callback(sResponse, I_TO_P(iSize), NULL);
return GJ_OK;
}
// ****************************************************************
/* clear/remove this data store item */
template <typename T> int gjDataItem::__Remove(const bool& bNow, GJ_NETWORK_OUTPUT(gjDataItemPtr))
{
if(!m_pAPI->IsUserConnected() && m_iType) return GJ_NOT_CONNECTED;
// access user or global data store item
const std::string sUserData = m_iType ?
"&username=" + m_pAPI->GetProcUserName() +
"&user_token=" + m_pAPI->GetProcUserToken() :
"";
// send remove data store request
std::string sResponse;
if(m_pAPI->SendRequest("/data-store/remove/"
"?game_id=" + m_pAPI->GetProcGameID() +
"&key=" + gjAPI::UtilEscapeString(m_sKey) +
sUserData, bNow ? &sResponse : NULL, this, &gjDataItem::__RemoveCallback, NULL, GJ_NETWORK_OUTPUT_FW)) return GJ_REQUEST_FAILED;
if(bNow) return this->__RemoveCallback(sResponse, NULL, NULL);
return GJ_OK;
}
#endif /* _GJ_GUARD_DATAITEM_H_ */