diff --git a/CMakeLists.txt b/CMakeLists.txt index 0cd24e3..a139646 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,6 +83,11 @@ install(TARGETS ragephoto DESTINATION ${CMAKE_INSTALL_LIBDIR}) install(FILES ${RAGEPHOTO_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pkgconfig/ragephoto.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) +option(WITH_DOCUMENTATION "Build libragephoto with documentation" OFF) +if (WITH_DOCUMENTATION) + add_subdirectory(doc) +endif() + option(WITH_GTK_EXAMPLE "Build libragephoto with GTK Photo Viewer" OFF) if (WITH_GTK_EXAMPLE) add_subdirectory(examples/ragephoto-gtkviewer) diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt new file mode 100644 index 0000000..23054fd --- /dev/null +++ b/doc/CMakeLists.txt @@ -0,0 +1,35 @@ +#[[************************************************************************** +* libragephoto RAGE Photo Parser +* Copyright (C) 2021 Syping +* +* Redistribution and use in source and binary forms, with or without modification, +* are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* This software is provided as-is, no warranties are given to you, we are not +* responsible for anything with use of the software, you are self responsible. +****************************************************************************]] + +cmake_minimum_required(VERSION 3.7) +find_package(Doxygen REQUIRED) +include(GNUInstallDirs) + +if (NOT DOXYGEN_FOUND) + message(FATAL_ERROR "Doxygen is needed to build the documentation.") +endif() + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY) +add_custom_target( + doc ALL + COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + COMMENT "Generate API documentation with Doxygen" + VERBATIM +) +install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html DESTINATION ${CMAKE_INSTALL_DOCDIR}) diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in new file mode 100644 index 0000000..ecc5b53 --- /dev/null +++ b/doc/Doxyfile.in @@ -0,0 +1,10 @@ +PROJECT_NAME = "libragephoto" +PROJECT_NUMBER = "Version: @PROJECT_VERSION@" +INPUT = "@CMAKE_CURRENT_SOURCE_DIR@/index.doc" \ + "src" +OUTPUT_DIRECTORY = "@CMAKE_CURRENT_BINARY_DIR@" +EXTRACT_PRIVATE = NO +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = YES +EXPAND_ONLY_PREDEF = YES +PREDEFINED = protected=private diff --git a/src/RagePhoto.cpp b/src/RagePhoto.cpp index daf5f74..670bdc8 100644 --- a/src/RagePhoto.cpp +++ b/src/RagePhoto.cpp @@ -402,6 +402,96 @@ const std::string RagePhoto::title() return p_titleString; } +void RagePhoto::setDescription(const std::string &description, uint32_t bufferSize) +{ + p_descriptionString = description; + if (bufferSize != 0) { + p_descBuffer = bufferSize; + moveOffsets(); + } +} + +void RagePhoto::setJson(const std::string &json, uint32_t bufferSize) +{ + p_jsonString = json; + if (bufferSize != 0) { + p_jsonBuffer = bufferSize; + moveOffsets(); + } +} + +void RagePhoto::setHeader(const std::string &header) +{ + p_photoString = header; +} + +bool RagePhoto::setPhotoData(const char *data, uint32_t size, uint32_t bufferSize) +{ + if (p_photoLoaded) { + if (p_photoSize > size) { + char *t_photoData = static_cast(realloc(p_photoData, size)); + if (!t_photoData) { + p_error = Error::PhotoMallocError; // 15 + return false; + } + p_photoData = t_photoData; + memcpy(p_photoData, data, size); + } + else if (p_photoSize < size) { + free(p_photoData); + p_photoData = static_cast(malloc(size)); + if (!p_photoData) { + p_error = Error::PhotoMallocError; // 15 + p_photoLoaded = false; + return false; + } + memcpy(p_photoData, data, size); + } + else { + memcpy(p_photoData, data, size); + } + } + else { + p_photoData = static_cast(malloc(size)); + if (!p_photoData) { + p_error = Error::PhotoMallocError; // 15 + return false; + } + memcpy(p_photoData, data, size); + p_photoLoaded = true; + } + + if (bufferSize != 0) { + p_photoBuffer = bufferSize; + moveOffsets(); + } + + p_error = Error::NoError; // 255 + return true; +} + +bool RagePhoto::setPhotoData(const std::string &data, uint32_t bufferSize) +{ + return setPhotoData(data.data(), data.size(), bufferSize); +} + +void RagePhoto::setTitle(const std::string &title, uint32_t bufferSize) +{ + p_titleString = title; + if (bufferSize != 0) { + p_titlBuffer = bufferSize; + moveOffsets(); + } +} + +void RagePhoto::moveOffsets() +{ + p_jsonOffset = p_photoBuffer + 28; + p_titlOffset = p_jsonOffset + p_jsonBuffer + 8; + p_descOffset = p_titlOffset + p_titlBuffer + 8; + p_endOfFile = p_descOffset + p_descBuffer + 12; +} + size_t RagePhoto::readBuffer(const char *input, char *output, size_t *pos, size_t len, size_t inputLen) { size_t readLen = 0; diff --git a/src/RagePhoto.h b/src/RagePhoto.h index 6d6108a..0ccbf00 100644 --- a/src/RagePhoto.h +++ b/src/RagePhoto.h @@ -27,6 +27,7 @@ class LIBRAGEPHOTO_EXPORT RagePhoto { public: + /** Parsing and set errors */ enum class Error : uint8_t { DescMallocError = 30, DescReadError = 31, @@ -64,26 +65,41 @@ public: UnicodeInitError = 4, Uninitialised = 0, }; + /** Photo Formats */ enum class PhotoFormat : uint32_t { - GTA5 = 0x01000000U, - RDR2 = 0x04000000U, - Undefined = 0, + GTA5 = 0x01000000U, /**< GTA V Photo Format */ + RDR2 = 0x04000000U, /**< RDR 2 Photo Format */ + Undefined = 0, /**< Undefined Format */ }; RagePhoto(); ~RagePhoto(); - void clear(); - bool load(const char *data, size_t length); - bool load(const std::string &data); - Error error(); - PhotoFormat format(); - const char *photoData(); - const uint32_t photoSize(); - const std::string description(); - const std::string json(); - const std::string header(); - const std::string title(); + void clear(); /**< Resets the RagePhoto instance to default values. */ + bool load(const char *data, size_t length); /**< Loads a Photo stored inside a const char*. */ + bool load(const std::string &data); /**< Loads a Photo stored inside a std::string. */ + Error error(); /**< Returns the last error occurred. */ + PhotoFormat format(); /**< Returns the Photo Format (GTA V or RDR 2). */ + const char *photoData(); /**< Returns the Photo JPEG data. */ + const uint32_t photoSize(); /**< Returns the Photo JPEG data size. */ + const std::string description(); /**< Returns the Photo description. */ + const std::string json(); /**< Returns the Photo JSON data. */ + const std::string header(); /**< Returns the Photo header. */ + const std::string title(); /**< Returns the Photo title. */ + void setDescription(const std::string &description, uint32_t bufferSize = 0); /**< Sets the Photo description. */ + void setJson(const std::string &json, uint32_t bufferSize = 0); /**< Sets the Photo JSON data. */ + void setHeader(const std::string &header); /**< Sets the Photo header. (expert only) */ + /** Sets the Photo JPEG data. + * @param data JPEG data + * @param size JPEG data size + */ + bool setPhotoData(const char *data, uint32_t size, uint32_t bufferSize = 0); + /** Sets the Photo JPEG data. + * @param data JPEG data + */ + bool setPhotoData(const std::string &data, uint32_t bufferSize = 0); + void setTitle(const std::string &title, uint32_t bufferSize = 0); /**< Sets the Photo title. */ protected: + inline void moveOffsets(); inline size_t readBuffer(const char *input, char *output, size_t *pos, size_t len, size_t inputLen); inline uint32_t charToUInt32BE(char *x); inline uint32_t charToUInt32LE(char *x);