diff --git a/src/RagePhoto.cpp b/src/RagePhoto.cpp index 4aa0816..d38da1f 100644 --- a/src/RagePhoto.cpp +++ b/src/RagePhoto.cpp @@ -129,6 +129,10 @@ RagePhoto::RagePhoto() if (!m_data) throw std::runtime_error("RagePhotoData data struct can't be allocated"); std::memset(m_data, 0, sizeof(RagePhotoData)); + m_parser = static_cast(std::malloc(sizeof(RagePhotoFormatParser))); + if (!m_parser) + throw std::runtime_error("RagePhotoFormatParser parser struct can't be allocated"); + std::memset(m_parser, 0, sizeof(RagePhotoFormatParser)); setBufferDefault(); } @@ -140,6 +144,24 @@ RagePhoto::~RagePhoto() std::free(m_data->header); std::free(m_data->title); std::free(m_data); + std::free(m_parser); +} + +void RagePhoto::addParser(RagePhotoFormatParser *rp_parser) +{ + if (rp_parser) { + RagePhotoFormatParser n_parser[1]{}; + if (!std::memcmp(&n_parser[0], rp_parser, sizeof(RagePhotoFormatParser))) + return; + size_t length; + for (length = 0; std::memcmp(&n_parser[0], &m_parser[length], sizeof(RagePhotoFormatParser)); length++); + RagePhotoFormatParser *t_parser = static_cast(std::realloc(m_parser, (length + 2 * sizeof(RagePhotoFormatParser)))); + if (!t_parser) + throw std::runtime_error("RagePhotoFormatParser array can't be expanded"); + m_parser = t_parser; + std::memcpy(&m_parser[length], rp_parser, sizeof(RagePhotoFormatParser)); + std::memset(&m_parser[length+1], 0, sizeof(RagePhotoFormatParser)); + } } void RagePhoto::clear() @@ -521,6 +543,14 @@ bool RagePhoto::load(const char *data, size_t length) return false; #endif } + else if (m_parser) { + RagePhotoFormatParser n_parser[1]{}; + for (size_t i = 0; std::memcmp(&n_parser[0], &m_parser[i], sizeof(RagePhotoFormatParser)); i++) { + if (m_data->photoFormat == m_parser[i].photoFormat) + if (m_parser[i].funcLoad) + return (m_parser[i].funcLoad)(m_data, data, length); + } + } m_data->error = Error::IncompatibleFormat; // 2 return false; } @@ -813,6 +843,14 @@ bool RagePhoto::save(char *data, uint32_t photoFormat) return false; #endif } + else if (m_parser) { + RagePhotoFormatParser n_parser[1]{}; + for (size_t i = 0; std::memcmp(&n_parser[0], &m_parser[i], sizeof(RagePhotoFormatParser)); i++) { + if (photoFormat == m_parser[i].photoFormat) + if (m_parser[i].funcSave) + return (m_parser[i].funcSave)(m_data, data, photoFormat); + } + } m_data->error = Error::IncompatibleFormat; // 2 return false; @@ -868,24 +906,31 @@ bool RagePhoto::saveFile(const std::string &filename) return saveFile(filename, m_data->photoFormat); } -inline size_t RagePhoto::saveSize(RagePhotoData *ragePhotoData, uint32_t photoFormat) +inline size_t RagePhoto::saveSize(RagePhotoData *rp_data, RagePhotoFormatParser *rp_parser, uint32_t photoFormat) { if (photoFormat == PhotoFormat::GTA5) - return (ragePhotoData->jpegBuffer + ragePhotoData->jsonBuffer + ragePhotoData->titlBuffer + ragePhotoData->descBuffer + GTA5_HEADERSIZE + 56UL); + return (rp_data->jpegBuffer + rp_data->jsonBuffer + rp_data->titlBuffer + rp_data->descBuffer + GTA5_HEADERSIZE + 56UL); else if (photoFormat == PhotoFormat::RDR2) - return (ragePhotoData->jpegBuffer + ragePhotoData->jsonBuffer + ragePhotoData->titlBuffer + ragePhotoData->descBuffer + RDR2_HEADERSIZE + 56UL); - else - return 0; + return (rp_data->jpegBuffer + rp_data->jsonBuffer + rp_data->titlBuffer + rp_data->descBuffer + RDR2_HEADERSIZE + 56UL); + else if (rp_parser) { + RagePhotoFormatParser n_parser[1]{}; + for (size_t i = 0; std::memcmp(&n_parser[0], &rp_parser[i], sizeof(RagePhotoFormatParser)); i++) { + if (photoFormat == rp_parser[i].photoFormat) + if (rp_parser[i].funcSaveSz) + return (rp_parser[i].funcSaveSz)(rp_data, photoFormat); + } + } + return 0; } -inline size_t RagePhoto::saveSize(RagePhotoData *ragePhotoData) +inline size_t RagePhoto::saveSize(RagePhotoData *rp_data, RagePhotoFormatParser *rp_parser) { - return saveSize(ragePhotoData, ragePhotoData->photoFormat); + return saveSize(rp_data, rp_parser, rp_data->photoFormat); } inline size_t RagePhoto::saveSize(uint32_t photoFormat) { - return saveSize(m_data, photoFormat); + return saveSize(m_data, m_parser, photoFormat); } inline size_t RagePhoto::saveSize() @@ -898,12 +943,12 @@ inline void RagePhoto::setBufferDefault() setBufferDefault(m_data); } -inline void RagePhoto::setBufferDefault(RagePhotoData *ragePhotoData) +inline void RagePhoto::setBufferDefault(RagePhotoData *rp_data) { - ragePhotoData->descBuffer = DEFAULT_DESCBUFFER; - ragePhotoData->jsonBuffer = DEFAULT_JSONBUFFER; - ragePhotoData->titlBuffer = DEFAULT_TITLBUFFER; - setBufferOffsets(ragePhotoData); + rp_data->descBuffer = DEFAULT_DESCBUFFER; + rp_data->jsonBuffer = DEFAULT_JSONBUFFER; + rp_data->titlBuffer = DEFAULT_TITLBUFFER; + setBufferOffsets(rp_data); } inline void RagePhoto::setBufferOffsets() @@ -911,17 +956,17 @@ inline void RagePhoto::setBufferOffsets() setBufferOffsets(m_data); } -inline void RagePhoto::setBufferOffsets(RagePhotoData *ragePhotoData) +inline void RagePhoto::setBufferOffsets(RagePhotoData *rp_data) { - ragePhotoData->jsonOffset = ragePhotoData->jpegBuffer + 28; - ragePhotoData->titlOffset = ragePhotoData->jsonOffset + ragePhotoData->jsonBuffer + 8; - ragePhotoData->descOffset = ragePhotoData->titlOffset + ragePhotoData->titlBuffer + 8; - ragePhotoData->endOfFile = ragePhotoData->descOffset + ragePhotoData->descBuffer + 12; + rp_data->jsonOffset = rp_data->jpegBuffer + 28; + rp_data->titlOffset = rp_data->jsonOffset + rp_data->jsonBuffer + 8; + rp_data->descOffset = rp_data->titlOffset + rp_data->titlBuffer + 8; + rp_data->endOfFile = rp_data->descOffset + rp_data->descBuffer + 12; } -bool RagePhoto::setData(RagePhotoData *ragePhotoData, bool takeOwnership) +bool RagePhoto::setData(RagePhotoData *rp_data, bool takeOwnership) { - if (m_data == ragePhotoData) + if (m_data == rp_data) return true; if (takeOwnership) { @@ -932,60 +977,60 @@ bool RagePhoto::setData(RagePhotoData *ragePhotoData, bool takeOwnership) std::free(m_data->title); std::free(m_data); - m_data = ragePhotoData; + m_data = rp_data; } else { clear(); - m_data->photoFormat = ragePhotoData->photoFormat; + m_data->photoFormat = rp_data->photoFormat; - if (ragePhotoData->header) { - const size_t headerSize = strlen(ragePhotoData->header) + 1; + if (rp_data->header) { + const size_t headerSize = strlen(rp_data->header) + 1; m_data->header = static_cast(std::malloc(headerSize)); if (!m_data->header) return false; - std::memcpy(m_data->header, ragePhotoData->header, headerSize); - m_data->headerSum = ragePhotoData->headerSum; + std::memcpy(m_data->header, rp_data->header, headerSize); + m_data->headerSum = rp_data->headerSum; } - if (ragePhotoData->jpeg) { - m_data->jpeg = static_cast(std::malloc(ragePhotoData->jpegSize)); + if (rp_data->jpeg) { + m_data->jpeg = static_cast(std::malloc(rp_data->jpegSize)); if (!m_data->jpeg) return false; - std::memcpy(m_data->jpeg, ragePhotoData->jpeg, ragePhotoData->jpegSize); - m_data->jpegSize = ragePhotoData->jpegSize; - m_data->jpegBuffer = ragePhotoData->jpegBuffer; + std::memcpy(m_data->jpeg, rp_data->jpeg, rp_data->jpegSize); + m_data->jpegSize = rp_data->jpegSize; + m_data->jpegBuffer = rp_data->jpegBuffer; } - if (ragePhotoData->json) { - const size_t jsonSize = strlen(ragePhotoData->json) + 1; + if (rp_data->json) { + const size_t jsonSize = strlen(rp_data->json) + 1; m_data->json = static_cast(std::malloc(jsonSize)); if (!m_data->json) return false; - std::memcpy(m_data->json, ragePhotoData->json, jsonSize); - m_data->jsonBuffer = ragePhotoData->jsonBuffer; + std::memcpy(m_data->json, rp_data->json, jsonSize); + m_data->jsonBuffer = rp_data->jsonBuffer; } - if (ragePhotoData->title) { - const size_t titleSize = strlen(ragePhotoData->title) + 1; + if (rp_data->title) { + const size_t titleSize = strlen(rp_data->title) + 1; m_data->title = static_cast(std::malloc(titleSize)); if (!m_data->title) return false; - std::memcpy(m_data->title, ragePhotoData->title, titleSize); - m_data->titlBuffer = ragePhotoData->titlBuffer; + std::memcpy(m_data->title, rp_data->title, titleSize); + m_data->titlBuffer = rp_data->titlBuffer; } - if (ragePhotoData->description) { - const size_t descriptionSize = strlen(ragePhotoData->description) + 1; + if (rp_data->description) { + const size_t descriptionSize = strlen(rp_data->description) + 1; m_data->description = static_cast(std::malloc(descriptionSize)); if (!m_data->description) return false; - std::memcpy(m_data->description, ragePhotoData->description, descriptionSize); - m_data->descBuffer = ragePhotoData->descBuffer; + std::memcpy(m_data->description, rp_data->description, descriptionSize); + m_data->descBuffer = rp_data->descBuffer; } - m_data->unnamedSum1 = ragePhotoData->unnamedSum1; - m_data->unnamedSum2 = ragePhotoData->unnamedSum2; + m_data->unnamedSum1 = rp_data->unnamedSum1; + m_data->unnamedSum2 = rp_data->unnamedSum2; setBufferOffsets(); } @@ -1104,6 +1149,12 @@ ragephoto_t ragephoto_open() return static_cast(new RagePhoto); } +void ragephoto_addparser(ragephoto_t instance, RagePhotoFormatParser *rp_parser) +{ + RagePhoto *ragePhoto = static_cast(instance); + ragePhoto->addParser(rp_parser); +} + void ragephoto_clear(ragephoto_t instance) { RagePhoto *ragePhoto = static_cast(instance); @@ -1244,16 +1295,16 @@ void ragephoto_setbufferoffsets(ragephoto_t instance) ragePhoto->setBufferOffsets(); } -ragephoto_bool_t ragephoto_setphotodata(ragephoto_t instance, RagePhotoData *ragePhotoData) +ragephoto_bool_t ragephoto_setphotodata(ragephoto_t instance, RagePhotoData *rp_data) { RagePhoto *ragePhoto = static_cast(instance); - return ragePhoto->setData(ragePhotoData, true); + return ragePhoto->setData(rp_data, true); } -ragephoto_bool_t ragephoto_setphotodatac(ragephoto_t instance, RagePhotoData *ragePhotoData) +ragephoto_bool_t ragephoto_setphotodatac(ragephoto_t instance, RagePhotoData *rp_data) { RagePhoto *ragePhoto = static_cast(instance); - return ragePhoto->setData(ragePhotoData, false); + return ragePhoto->setData(rp_data, false); } void ragephoto_setphotodesc(ragephoto_t instance, const char *description, uint32_t bufferSize) diff --git a/src/RagePhoto.h b/src/RagePhoto.h index 7a6af18..cf01346 100644 --- a/src/RagePhoto.h +++ b/src/RagePhoto.h @@ -94,6 +94,7 @@ public: }; RagePhoto(); ~RagePhoto(); + void addParser(RagePhotoFormatParser *rp_parser); /**< Add a custom defined RagePhotoFormatParser. */ void clear(); /**< Resets the RagePhoto instance to default values. */ RagePhotoData* data(); /**< Returns the internal RagePhotoData object. */ /** Loads a Photo from a const char*. @@ -139,15 +140,15 @@ public: const std::string save(bool *ok = nullptr); bool saveFile(const std::string &filename, uint32_t photoFormat); /**< Saves a Photo to a file. */ bool saveFile(const std::string &filename); /**< Saves a Photo to a file. */ - static size_t saveSize(RagePhotoData *ragePhotoData, uint32_t photoFormat); /**< Returns the Photo save file size. */ - static size_t saveSize(RagePhotoData *ragePhotoData); /**< Returns the Photo save file size. */ + static size_t saveSize(RagePhotoData *rp_data, RagePhotoFormatParser *rp_parser, uint32_t photoFormat); /**< Returns the Photo save file size. */ + static size_t saveSize(RagePhotoData *rp_data, RagePhotoFormatParser *rp_parser); /**< Returns the Photo save file size. */ size_t saveSize(uint32_t photoFormat); /**< Returns the Photo save file size. */ size_t saveSize(); /**< Returns the Photo save file size. */ void setBufferDefault(); /**< Sets all cross-format Buffer to default size. */ - static void setBufferDefault(RagePhotoData *ragePhotoData); /**< Sets all cross-format Buffer to default size. */ + static void setBufferDefault(RagePhotoData *rp_data); /**< Sets all cross-format Buffer to default size. */ void setBufferOffsets(); /**< Moves all Buffer offsets to correct position. */ - static void setBufferOffsets(RagePhotoData *ragePhotoData); /**< Moves all Buffer offsets to correct position. */ - bool setData(RagePhotoData *ragePhotoData, bool takeOwnership = true); /**< Sets the internal RagePhotoData object. */ + static void setBufferOffsets(RagePhotoData *rp_data); /**< Moves all Buffer offsets to correct position. */ + bool setData(RagePhotoData *rp_data, bool takeOwnership = true); /**< Sets the internal RagePhotoData object. */ void setDescription(const char *description, uint32_t bufferSize = 0); /**< Sets the Photo description. */ void setFormat(uint32_t photoFormat); /**< Sets the Photo Format (GTA V or RDR 2). */ void setJson(const char *json, uint32_t bufferSize = 0); /**< Sets the Photo JSON data. */ @@ -167,6 +168,7 @@ public: private: RagePhotoData *m_data; + RagePhotoFormatParser *m_parser; }; #else #include "RagePhotoC.h" diff --git a/src/RagePhotoC.h b/src/RagePhotoC.h index 90608fe..0aae084 100644 --- a/src/RagePhotoC.h +++ b/src/RagePhotoC.h @@ -39,6 +39,12 @@ typedef void* ragephoto_t; /** Opens a \p ragephoto_t instance. */ LIBRAGEPHOTO_C_BINDING ragephoto_t ragephoto_open(); +/** Add a custom defined RagePhotoFormatParser. +* \param instance \p ragephoto_t instance +* \param rp_parser RagePhotoFormatParser parser to add +*/ +LIBRAGEPHOTO_C_BINDING void ragephoto_addparser(ragephoto_t instance, RagePhotoFormatParser *rp_parser); + /** Resets the \p ragephoto_t instance to default values. * \param instance \p ragephoto_t instance */ @@ -163,15 +169,15 @@ LIBRAGEPHOTO_C_BINDING void ragephoto_setbufferoffsets(ragephoto_t instance); /** Sets the internal RagePhotoData object. * \param instance \p ragephoto_t instance -* \param ragePhotoData RagePhotoData object being set +* \param rp_data RagePhotoData object being set */ -LIBRAGEPHOTO_C_BINDING ragephoto_bool_t ragephoto_setphotodata(ragephoto_t instance, RagePhotoData *ragePhotoData); +LIBRAGEPHOTO_C_BINDING ragephoto_bool_t ragephoto_setphotodata(ragephoto_t instance, RagePhotoData *rp_data); /** Copies RagePhotoData object to internal RagePhotoData object. * \param instance \p ragephoto_t instance -* \param ragePhotoData RagePhotoData object being copied +* \param rp_data RagePhotoData object being copied */ -LIBRAGEPHOTO_C_BINDING ragephoto_bool_t ragephoto_setphotodatac(ragephoto_t instance, RagePhotoData *ragePhotoData); +LIBRAGEPHOTO_C_BINDING ragephoto_bool_t ragephoto_setphotodatac(ragephoto_t instance, RagePhotoData *rp_data); /** Sets the Photo description. * \param instance \p ragephoto_t instance