/** * @file IObject.h * @brief Object system types and interfaces. * @copyright VisionLabs LLC * @date 25.06.2014 * */ #pragma once #include "IRefCounted.h" #include "Types.h" namespace fsdk { /** * @addtogroup CoreGroup SDK core interfaces * @brief Common interfaces and macros shared across all SDK objects. * @{ * */ struct ISettingsProvider; /** * @brief Archive interface. * @details Archives abstract data storage and IO operations. * * @note IArchive is not derived from IRefCounted and does not force any lifetime control. It is up to user to * implement it. * * @note SDK ojects that use IArchive for serialization purposes do call only write() (during saving) or only * read() (during loading) but never both during the same process unless otherwise is explicitly stated. * * @note During saving or loading SDK objects are free to write or read their data in chunks; e.g. there may be * several sequential calls to write() in scope of a single serialization request. Any IArchive implementation * should be aware of this. * */ struct IArchive { /** * @brief Write bytes to archive. * @param [in] data pointer to memory to write. * @param [in] size data size. * @return true if succeeded, false otherwise. * */ virtual bool write(const void* data, size_t size) = 0; /** * @brief Read bytes from archive. * @param [in] data pointer to memory to read to. * @param [in] size data size. * @return true if succeeded, false otherwise. * */ virtual bool read(void* data, size_t size) = 0; /** * @brief Set size hint. * @param [in] hint size hint. * */ virtual void setSizeHint(size_t hint) { ((void)hint); } virtual ~IArchive() = default; }; /** * @brief Serializable object interface. * @details Provides common functions for all serializable objects. * */ struct ISerializableObject : IRefCounted { /** * @brief Serialization nerror codes. * */ enum class Error : uint32_t { Ok, //!< Ok Size, //!< Not enough space Signature, //!< Invalid signature ArchiveRead, //!< Error during archive reading, InputArchive, //!< Input archive is nullptr ArchiveWrite, //!< Error during archive writing, }; /** * @brief Serialization flags. * @details These flags control advanced options and should not be set to anything else from Default in * normal conditions. * @note The same set of flags should be specified for both save() and load(). * */ enum Flags { /** @brief Default serialization mode. */ Default = 0, /** * @brief Omit object signature. * @details Helps to save space if there are several objects of the same type coming in a stream or * where type is known for sure. * @note This effectively disables signature check on loading. This may cause undefined results in * case of mismatched input data. * */ NoSignature = 1 }; /** * @brief Estimate size of this object binary data. * @param [inout] sizer sizer object to append result to. * @param [in] flags [optional] serialization flags @see Flags. * */ virtual void getSize(Sizer& sizer, uint32_t flags = Default) const noexcept = 0; /** * @brief Load object from archive. * @param [in] archive archive to read from. * @param [in] flags [optional] serialization flags @see Flags. * @return Result with error code specified by ISerializableObject::SerializationError. * @note This method pass exceptions from user defined IArchive, but doesnt throw its own * @see Result and ISerializableObject::SerializationError. * */ virtual Result load(IArchive* archive, uint32_t flags = Default) = 0; /** * @brief Save object to archive. * @param [in] archive archive to write to. * @param [in] flags [optional] serialization flags @see Flags. * @return Result with error code specified by ISerializableObject::SerializationError. * @note This method pass exceptions from user defined IArchive, but doesnt throw its own * @see Result and ISerializableObject::SerializationError. * */ virtual Result save(IArchive* archive, uint32_t flags = Default) const = 0; }; /** * @brief Specialized for ISerializableObject::SerializationError. * */ template<> struct ErrorTraits { static bool isOk(ISerializableObject::Error error) noexcept { return error == ISerializableObject::Error::Ok; } static const char* toString (ISerializableObject::Error error) noexcept { switch(error) { case ISerializableObject::Error::Ok : return "Ok"; case ISerializableObject::Error::Size: return "Size error"; case ISerializableObject::Error::Signature: return "Signature error"; case ISerializableObject::Error::ArchiveRead: return "Error during archive reading"; case ISerializableObject::Error::InputArchive: return "Input archive is nullptr"; case ISerializableObject::Error::ArchiveWrite: return "Error during archive writing"; default: return "Unknown error"; } } }; /** * @brief Data storage object interface helper. * */ struct IDataStorageObject : ISerializableObject { /** * @brief Clear object data. * @note This does not necessarily mean deallocation; it is defined by implementation how to manage * data memory. * */ virtual void clear() noexcept = 0; /** * @brief Get parent object (one that has created this). * @note Any returned interfaces will have their reference count incremented by one, so be sure to * call release() on the returned pointer(s) before they are freed or else you will have a memory * leak. * @return pointer to the parent object. * */ virtual IRefCounted* getParentObject() const noexcept = 0; }; /** @} */ }