#pragma once #include /** * @brief An abstract interface for persistent storage * * @note It is assumed that read operations are cached and therefore quick. */ class StorageSource { public: /** * @brief Write a byte to disk * * @note The data is only persisted if the function `commitData()` is called afterwards. * * @param byte The byte to write * @param index The index where to write the byte * @return true * @return false */ virtual bool writeByteAtIndex(uint8_t byte, uint16_t index) = 0; /** * @brief Ensure that enough storage is available for all data * * @param size * @return true The space was initialized an has sufficient size * @return false */ virtual bool canProvideStorageWithSize(uint16_t size) = 0; /** * @brief Write the data to persistent storage after a block of bytes was changed. * * @return true The data was persisted * @return false The data could not be saved */ virtual bool commitData() = 0; /** * @brief Read a single byte from persistent storage * * @param index The index of the byte in the data * @return uint8_t The byte at the given index */ virtual uint8_t readByteAtIndex(uint16_t index) = 0; /** * @brief Read a number of bytes from storage * * @param startIndex The index of the start byte * @param count The number of bytes to read * @param output The location to write the bytes * @return uint8_t The number of bytes read */ virtual uint16_t readBytes(uint16_t startIndex, uint16_t count, uint8_t* output) { uint16_t endIndex = startIndex + count; if (endIndex < startIndex) { return 0; // Overflow } for (uint16_t i = 0; i < endIndex; i += 1) { output[i] = readByteAtIndex(startIndex + i); } return count; } /** * @brief Write a number of bytes to storage * * @note The data is only persisted if the function `commitData()` is called afterwards. * * @param bytes The memory holding the bytes * @param count The number of bytes to write * @param startIndex The index where the bytes should be written * @return uint16_t The number of bytes written to storage */ virtual uint16_t writeBytes(uint8_t* bytes, uint16_t count, uint16_t startIndex) { uint16_t endIndex = startIndex + count; if (endIndex < startIndex) { return 0; // Overflow } for (uint16_t i = 0; i < endIndex; i += 1) { if (!writeByteAtIndex(bytes[i], startIndex + i)) { return i; // Failed to write byte } } return count; } };