#ifndef _MODULE_STORAGE_h
#define _MODULE_STORAGE_h
#include "watchos_consts.h"
#include "watchos_types.h"
#include "Task.h"
// We pre-allocate a table for tracking storage allocations. This defines how
// many entries that supports.
#define MODULE_STORAGE_MAX_ENTRIES 16
struct StorageEntry;
///
/// Module providing a coherent interface for persisting data
///
class Module_Storage : public Task
{
///
/// To validate that the storage we're reading is initialized, we store two bytes of magic
/// at the beginning.
///
uint16_t m_magic;
///
/// Storage tracks a version number to allow non-backward-compatible updates to be made
/// to the format in the future.
///
byte m_version;
///
/// One byte of storage is reserved to track top-level flags/options
///
byte m_options;
///
/// In-memory list of all storage allocations
///
StorageEntry* m_entry[MODULE_STORAGE_MAX_ENTRIES];
///
/// Convert a kernel well-known handle into a byte in the range 0-63
///
///
/// Well known handles are used as a bitmask, so each distinct handle
/// only sets a single bit. In order to save on storage, internally we map
/// those to a single byte in the range 0-63.
///
/// well known handle; one of the WATCHOS_MODULE_* consts
/// a byte with a number in the range 0-63
byte wellKnownHandleToByte(well_known_handle_t handle);
///
/// Get the offset of a specific module's data within storage
///
/// id of the module to get offset for
/// offset, in bytes, of the module's data
int getOffset(byte module);
public:
void initialize();
void start();
void suspend();
///
/// Check whether the underlying storage contains valid and initialized storage
///
/// true if valid; false if invalid
bool isValid();
///
/// Load the storage allocations from persistent storage
///
void load();
///
/// Commit the storage allocations to persistent storage
///
void commit();
///
/// Reset all storage allocations and write an empty allocation
/// table to persistent storage.
///
void reset();
///
/// Allocate storage for a module
///
/// module's handle
/// number of bytes of storage to allocate
///
/// true if an allocation was performed; false if an allocation already existed for the given module + size
bool allocate(well_known_handle_t module, uint16_t size, byte options = 0);
///
/// Write data to a module's storage
///
/// module to write for
/// offset, in bytes, within module's storage
/// value to write at offset
void write(well_known_handle_t module, uint16_t offset, byte value);
///
/// Fetch data from a module's storage
///
/// module to read for
/// offset, in bytes, within module's storage
/// the value previously stored at that address
byte read(well_known_handle_t module, uint16_t offset);
///
/// Allocate storage for a module
///
/// module's handle
/// number of bytes of storage to allocate
///
/// true if an allocation was performed; false if an allocation already existed for the given module + size
bool allocate(byte module, uint16_t size, byte options = 0);
///
/// Write data to a module's storage
///
/// module to write for
/// offset, in bytes, within module's storage
/// value to write at offset
void write(byte module, uint16_t offset, byte value);
///
/// Fetch data from a module's storage
///
/// module to read for
/// offset, in bytes, within module's storage
/// the value previously stored at that address
byte read(byte module, uint16_t offset);
};
#endif