8#include "libxr_def.hpp"
9#include "libxr_type.hpp"
14static constexpr uint16_t LIBXR_DATABASE_VERSION = 3;
47 template <
typename Data>
68 if (database.
Get(*
this) == ErrorCode::NOT_FOUND)
88 if (database.
Get(*
this) == ErrorCode::NOT_FOUND)
90 Memory::FastSet(&data_, 0, sizeof(Data));
247 KeyInfo() : raw_data(0xFFFFFFFF) {}
249 KeyInfo(
bool nextKey, uint8_t nameLength, uint32_t dataSize) : raw_data(0)
251 SetNextKeyExist(nextKey);
252 SetNameLength(nameLength);
253 SetDataSize(dataSize);
256 void SetNextKeyExist(
bool value)
258 raw_data = (raw_data & 0x7FFFFFFF) | (
static_cast<uint32_t
>(value & 0x1) << 31);
260 bool GetNextKeyExist()
const {
return (raw_data >> 31) & 0x1; }
262 void SetNameLength(uint8_t len)
264 raw_data = (raw_data & 0x80FFFFFF) | (
static_cast<uint32_t
>(len & 0x7F) << 24);
266 uint8_t GetNameLength()
const {
return (raw_data >> 24) & 0x7F; }
268 void SetDataSize(uint32_t size)
270 raw_data = (raw_data & 0xFF000000) | (size & 0x00FFFFFF);
272 uint32_t GetDataSize()
const {
return raw_data & 0x00FFFFFF; }
275 static_assert(
sizeof(
KeyInfo) == 4,
"KeyInfo size must be 4 bytes");
288 ErrorCode AddKey(
const char* name,
const void* data,
size_t size);
289 ErrorCode SetKey(
const char* name,
const void* data,
size_t size);
290 ErrorCode SetKey(
size_t offset,
const void* data,
size_t size);
291 ErrorCode GetKeyData(
size_t offset,
RawData data);
296 bool HasLastKey(
size_t offset);
297 size_t GetKeySize(
size_t offset);
298 size_t GetNextKey(
size_t offset);
300 void SetNestKeyExist(
size_t offset,
bool exist);
301 bool KeyDataCompare(
size_t offset,
const void* data,
size_t size);
302 bool KeyNameCompare(
size_t offset,
const char* name);
303 size_t SearchKey(
const char* name);
306 0x12345678 + LIBXR_DATABASE_VERSION;
327template <
size_t MinWriteSize>
331 0x12345678 + LIBXR_DATABASE_VERSION;
342 template <
size_t BlockSize>
345 uint8_t data[BlockSize];
349 template <
size_t BlockSize>
358 obj.data[BlockSize - 1] &= 0xF0;
364 uint8_t last_4bits = obj.data[BlockSize - 1] & 0x0F;
365 return last_4bits == 0x0F;
375 for (
size_t i = 0; i < BlockSize - 1; ++i)
377 if (obj.data[i] != 0xFF)
383 uint8_t last_byte = obj.data[BlockSize - 1];
384 if ((last_byte & 0xF0) != 0xF0)
389 uint8_t last_4bits = last_byte & 0x0F;
390 if (!(last_4bits == 0x0F || last_4bits == 0x00))
420 void SetNameLength(uint8_t len)
425 uint8_t GetNameLength()
const {
return (
raw_info >> 25) & 0x7F; }
427 void SetDataSize(uint32_t size)
432 uint32_t GetDataSize()
const {
return raw_info & 0x01FFFFFF; }
452 uint8_t padding[MinWriteSize];
474 ErrorCode AddKeyBody(
size_t name_len,
size_t size,
size_t& key_buf_offset)
476 bool recycle =
false;
494 return ErrorCode::FULL;
498 if (last_key_offset == 0)
500 FlashInfo flash_info;
502 KeyInfo& tmp_key = flash_info.key;
503 BlockBoolUtil<MinWriteSize>::SetFlag(tmp_key.no_next_key,
false);
504 BlockBoolUtil<MinWriteSize>::SetFlag(tmp_key.available_flag,
false);
505 BlockBoolUtil<MinWriteSize>::SetFlag(tmp_key.uninit,
false);
506 tmp_key.SetNameLength(0);
507 tmp_key.SetDataSize(0);
508 Write(0, flash_info);
509 key_buf_offset = GetNextKey(OFFSET_OF(FlashInfo, key));
513 key_buf_offset = GetNextKey(last_key_offset);
516 KeyInfo new_key = {};
517 BlockBoolUtil<MinWriteSize>::SetFlag(new_key.no_next_key,
true);
518 BlockBoolUtil<MinWriteSize>::SetFlag(new_key.available_flag,
true);
519 BlockBoolUtil<MinWriteSize>::SetFlag(new_key.uninit,
true);
520 new_key.SetNameLength(name_len);
521 new_key.SetDataSize(size);
523 Write(key_buf_offset, new_key);
524 BlockBoolUtil<MinWriteSize>::SetFlag(new_key.uninit,
false);
526 if (last_key_offset != 0)
530 KeyInfo new_last_key = {};
531 BlockBoolUtil<MinWriteSize>::SetFlag(new_last_key.no_next_key,
false);
532 BlockBoolUtil<MinWriteSize>::SetFlag(
533 new_last_key.available_flag,
534 BlockBoolUtil<MinWriteSize>::ReadFlag(last_key.available_flag));
535 BlockBoolUtil<MinWriteSize>::SetFlag(
536 new_last_key.uninit, BlockBoolUtil<MinWriteSize>::ReadFlag(last_key.uninit));
537 new_last_key.SetNameLength(last_key.GetNameLength());
538 new_last_key.SetDataSize(last_key.GetDataSize());
540 Write(last_key_offset, new_last_key);
543 Write(key_buf_offset, new_key);
545 return ErrorCode::OK;
548 ErrorCode AddKey(
size_t name_offset,
size_t name_len,
const void* data,
size_t size)
550 size_t key_buf_offset = 0;
551 ErrorCode ec = AddKeyBody(name_len, size, key_buf_offset);
552 if (ec != ErrorCode::OK)
556 CopyFlashData(GetKeyName(key_buf_offset), name_offset, name_len);
557 Write(GetKeyData(key_buf_offset), {
reinterpret_cast<const uint8_t*
>(data), size});
558 return ErrorCode::OK;
561 ErrorCode AddKey(
const char* name,
const void* data,
size_t size)
563 size_t name_len = strlen(name) + 1;
564 if (
auto ans = SearchKey(name))
566 return SetKey(name, data, size);
568 size_t key_buf_offset = 0;
569 ErrorCode ec = AddKeyBody(name_len, size, key_buf_offset);
570 if (ec != ErrorCode::OK)
574 Write(GetKeyName(key_buf_offset), {
reinterpret_cast<const uint8_t*
>(name), name_len});
575 Write(GetKeyData(key_buf_offset), {
reinterpret_cast<const uint8_t*
>(data), size});
576 return ErrorCode::OK;
579 ErrorCode SetKeyCommon(
size_t key_offset,
size_t name_len,
const void* data,
586 if (key.GetDataSize() == size)
588 if (KeyDataCompare(key_offset, data, size))
590 KeyInfo new_key = {};
591 BlockBoolUtil<MinWriteSize>::SetFlag(
593 BlockBoolUtil<MinWriteSize>::ReadFlag(key.no_next_key));
594 BlockBoolUtil<MinWriteSize>::SetFlag(new_key.available_flag,
false);
595 BlockBoolUtil<MinWriteSize>::SetFlag(
596 new_key.uninit, BlockBoolUtil<MinWriteSize>::ReadFlag(key.uninit));
597 new_key.SetNameLength(name_len);
598 new_key.SetDataSize(size);
599 Write(key_offset, new_key);
600 return AddKey(GetKeyName(key_offset), name_len, data, size);
602 return ErrorCode::OK;
605 return ErrorCode::FAILED;
608 ErrorCode SetKey(
size_t name_offset,
size_t name_length,
const void* data,
size_t size)
610 size_t key_offset = SearchKey(name_offset, name_length);
611 return SetKeyCommon(key_offset, name_length, data, size);
614 ErrorCode SetKey(
const char* name,
const void* data,
size_t size,
bool recycle =
true)
616 size_t key_offset = SearchKey(name);
621 if (key.GetDataSize() == size)
623 if (KeyDataCompare(key_offset, data, size))
631 return SetKey(name, data, size,
false);
636 return ErrorCode::FULL;
639 KeyInfo new_key = {};
640 BlockBoolUtil<MinWriteSize>::SetFlag(
642 BlockBoolUtil<MinWriteSize>::ReadFlag(key.no_next_key));
643 BlockBoolUtil<MinWriteSize>::SetFlag(new_key.available_flag,
false);
644 BlockBoolUtil<MinWriteSize>::SetFlag(
645 new_key.uninit, BlockBoolUtil<MinWriteSize>::ReadFlag(key.uninit));
646 new_key.SetNameLength(key.GetNameLength());
647 new_key.SetDataSize(size);
648 Write(key_offset, new_key);
649 return AddKey(GetKeyName(key_offset), key.GetNameLength(), data, size);
651 return ErrorCode::OK;
654 return ErrorCode::FAILED;
657 size_t GetKeyData(
size_t offset)
664 size_t GetKeyName(
size_t offset) {
return offset +
AlignSize(
sizeof(KeyInfo)); }
677 KeyInfo& tmp_key = info.key;
678 BlockBoolUtil<MinWriteSize>::SetFlag(tmp_key.no_next_key,
true);
679 BlockBoolUtil<MinWriteSize>::SetFlag(tmp_key.available_flag,
true);
680 BlockBoolUtil<MinWriteSize>::SetFlag(tmp_key.uninit,
false);
681 tmp_key.SetNameLength(0);
682 tmp_key.SetDataSize(0);
683 Write(offset, {
reinterpret_cast<uint8_t*
>(&info),
sizeof(FlashInfo)});
695 FlashInfo flash_data;
707 FlashInfo flash_data;
709 return BlockBoolUtil<MinWriteSize>::ReadFlag(flash_data.key.available_flag) ==
true;
719 uint32_t checksum = 0;
724 size_t GetKeySize(
size_t offset)
732 size_t GetNextKey(
size_t offset)
736 return offset + GetKeySize(offset);
741 if (IsBlockEmpty(block))
747 size_t key_offset = OFFSET_OF(FlashInfo, key);
753 while (!BlockBoolUtil<MinWriteSize>::ReadFlag(key.no_next_key))
755 key_offset = GetNextKey(key_offset);
761 bool KeyDataCompare(
size_t offset,
const void* data,
size_t size)
765 size_t key_data_offset = GetKeyData(offset);
766 uint8_t data_buffer = 0;
767 for (
size_t i = 0; i < size; i++)
769 flash_.
Read(key_data_offset + i, data_buffer);
770 if (data_buffer != (
reinterpret_cast<const uint8_t*
>(data))[i])
778 bool KeyNameCompare(
size_t offset,
const char* name)
782 for (
size_t i = 0; i < key.GetNameLength(); i++)
784 uint8_t data_buffer = 0;
786 if (data_buffer != name[i])
794 bool KeyNameCompare(
size_t offset_a,
size_t offset_b)
796 KeyInfo key_a, key_b;
799 if (key_a.GetNameLength() != key_b.GetNameLength())
803 for (
size_t i = 0; i < key_a.GetNameLength(); i++)
805 uint8_t data_buffer_a = 0, data_buffer_b = 0;
806 flash_.
Read(offset_a +
sizeof(KeyInfo) + i, data_buffer_a);
807 flash_.
Read(offset_b +
sizeof(KeyInfo) + i, data_buffer_b);
808 if (data_buffer_a != data_buffer_b)
816 void CopyFlashData(
size_t dst_offset,
size_t src_offset,
size_t size)
818 for (
size_t i = 0; i < size; i += MinWriteSize)
825 size_t SearchKey(
const char* name)
833 size_t key_offset = OFFSET_OF(FlashInfo, key);
836 size_t ans = 0, need_cycle = 0;
840 if (!BlockBoolUtil<MinWriteSize>::ReadFlag(key.available_flag))
842 key_offset = GetNextKey(key_offset);
848 if (!KeyNameCompare(key_offset, name))
854 if (BlockBoolUtil<MinWriteSize>::ReadFlag(key.no_next_key))
859 key_offset = GetNextKey(key_offset);
866 return SearchKey(name);
880 return static_cast<size_t>((size + MinWriteSize - 1) / MinWriteSize) * MinWriteSize;
894 return ErrorCode::OK;
897 if (data.
size_ % MinWriteSize == 0)
903 auto final_block_index = data.
size_ - data.
size_ % MinWriteSize;
904 if (final_block_index != 0)
911 data.
size_ % MinWriteSize);
927 auto ans = SearchKey(key.
name_);
930 return ErrorCode::NOT_FOUND;
938 return ErrorCode::FAILED;
943 return ErrorCode::OK;
1001 for (uint32_t i = 0; i <
block_size_; i += MinWriteSize)
1015 size_t key_offset = OFFSET_OF(
FlashInfo, key);
1017 size_t need_cycle = 0;
1020 key_offset = GetNextKey(key_offset);
1022 if (key_offset +
sizeof(key) >=
flash_.
Size())
1072 return ErrorCode::OK;
1076 size_t key_offset = OFFSET_OF(
FlashInfo, key);
1090 Write(write_buff_offset, new_key);
1092 write_buff_offset += GetKeySize(write_buff_offset);
1096 key_offset = GetNextKey(key_offset);
1104 Write(write_buff_offset, key);
1106 CopyFlashData(write_buff_offset, GetKeyName(key_offset), key.GetNameLength());
1107 write_buff_offset +=
AlignSize(key.GetNameLength());
1108 CopyFlashData(write_buff_offset, GetKeyData(key_offset), key.GetDataSize());
1109 write_buff_offset +=
AlignSize(key.GetDataSize());
1113 for (uint32_t i = 0; i <
block_size_; i += MinWriteSize)
1121 return ErrorCode::OK;
常量原始数据封装类。 A class for encapsulating constant raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
const void * addr_
数据存储地址(常量)。 The storage address of the data (constant).
键的基类,存储键名及其数据 (Base class for keys, storing key name and associated data).
RawData raw_data_
原始数据 (Raw data associated with the key).
KeyBase(const char *name, RawData raw_data)
构造函数,初始化键名和原始数据 (Constructor to initialize key name and raw data).
const char * name_
键名 (Key name).
模板类,表示数据库中的具体键 (Template class representing a specific key in the database).
Database & database_
关联的数据库对象 (Reference to the associated database).
ErrorCode Set(Data data)
设置键的值并更新数据库 (Set the key's value and update the database).
Key(Database &database, const char *name, Data init_value)
构造函数,初始化键并从数据库加载数据 (Constructor to initialize key and load data from the database).
Data data_
键存储的数据 (The data stored in the key).
ErrorCode operator=(Data data)
赋值运算符,设置键的值 (Assignment operator to set the key's value).
ErrorCode Load()
从数据库加载键的值 (Load the key's value from the database).
Key(Database &database, const char *name)
构造函数,初始化键,并在数据库不存在时赋默认值 (Constructor to initialize key, assigning default value if not found in the d...
数据库接口,提供键值存储和管理功能 (Database interface providing key-value storage and management).
virtual ErrorCode Add(KeyBase &key)=0
添加新键到数据库 (Add a new key to the database).
virtual ErrorCode Get(KeyBase &key)=0
从数据库获取键的值 (Retrieve the key's value from the database).
virtual ErrorCode Set(KeyBase &key, RawData data)=0
设置数据库中的键值 (Set the key's value in the database).
适用于最小写入单元受限的 Flash 存储的数据库实现 (Database implementation for Flash storage with minimum write unit restri...
size_t AvailableSize()
计算可用的存储空间大小 (Calculate the available storage size).
static constexpr uint32_t FLASH_HEADER
Flash 头部标识 (Flash header identifier).
@ BACKUP
备份块 (Backup block).
void Restore()
还原存储数据,清空 Flash 区域 (Restore storage data, clearing Flash memory area).
DatabaseRaw(Flash &flash, size_t recycle_threshold=128)
构造函数,初始化 Flash 存储和缓冲区 (Constructor to initialize Flash storage and buffer).
ErrorCode Add(KeyBase &key) override
添加新键到数据库 (Add a new key to the database).
ErrorCode Set(KeyBase &key, RawData data) override
设置数据库中的键值 (Set the key's value in the database).
ErrorCode Recycle()
回收 Flash 空间,整理数据 (Recycle Flash storage space and organize data).
uint32_t block_size_
Flash 块大小 (Flash block size).
static constexpr uint32_t CHECKSUM_BYTE
校验字节 (Checksum byte).
void Init()
初始化数据库存储区,确保主备块正确 (Initialize database storage, ensuring main and backup blocks are valid).
ErrorCode Write(size_t offset, ConstRawData data)
以最小写入单元对齐的方式写入数据 (Write data aligned to the minimum write unit).
ErrorCode Get(Database::KeyBase &key) override
获取数据库中的键值 (Retrieve the key's value from the database).
Flash & flash_
目标 Flash 存储设备 (Target Flash storage device).
uint8_t write_buffer_[MinWriteSize]
写入缓冲区 (Write buffer).
size_t AlignSize(size_t size)
计算对齐后的大小 (Calculate the aligned size).
size_t recycle_threshold_
回收阈值 (Recycle threshold).
适用于不支持逆序写入的 Flash 存储的数据库实现 (Database implementation for Flash storage that does not support reverse w...
void Save()
保存当前缓冲区内容到 Flash (Save the current buffer content to Flash).
static constexpr uint8_t CHECKSUM_BYTE
校验字节 (Checksum byte).
ErrorCode Set(KeyBase &key, RawData data) override
设置数据库中的键值 (Set the key's value in the database).
uint32_t max_buffer_size_
最大缓冲区大小 (Maximum buffer size).
ErrorCode Get(Database::KeyBase &key) override
获取数据库中的键值 (Retrieve the key's value from the database).
void Init()
初始化数据库存储区,确保主备块正确 (Initialize database storage, ensuring main and backup blocks are valid).
uint8_t * buffer_
数据缓冲区 (Data buffer).
static constexpr uint32_t FLASH_HEADER
Flash 头部标识 (Flash header identifier).
ErrorCode Add(KeyBase &key) override
添加新键到数据库 (Add a new key to the database).
void Restore()
还原存储数据,清空 Flash 区域 (Restore storage data, clearing Flash memory area).
bool IsBlockEmpty(BlockType block)
判断块是否为空 (Check if block is empty).
uint32_t block_size_
Flash 块大小 (Flash block size).
Flash & flash_
目标 Flash 存储设备 (Target Flash storage device).
void Load()
从 Flash 加载数据到缓冲区 (Load data from Flash into the buffer).
DatabaseRawSequential(Flash &flash, size_t max_buffer_size=256)
构造函数,初始化 Flash 存储和缓冲区 (Constructor initializing Flash storage and buffer).
bool IsBlockInited(BlockType block)
判断块是否已初始化 (Check if block is initialized).
@ BACKUP
备份块 (Backup block).
bool IsBlockError(BlockType block)
判断块是否损坏 (Check if block has an error).
Abstract base class representing a flash memory interface. 抽象基类,表示闪存接口。
size_t Size() const
Returns the size of the flash memory area. 获取闪存存储区域的大小。
size_t MinWriteSize() const
Returns the minimum writable block size in bytes. 获取最小可写块大小(字节)。
virtual ErrorCode Erase(size_t offset, size_t size)=0
Erases a section of the flash memory. 擦除闪存的指定区域。
virtual ErrorCode Write(size_t offset, ConstRawData data)=0
Writes data to the flash memory. 向闪存写入数据。
virtual ErrorCode Read(size_t offset, RawData data)
Reads data from the flash memory. 从闪存中读取数据。
size_t MinEraseSize() const
Returns the minimum erasable block size in bytes. 获取最小可擦除块大小(字节)。
static void FastSet(void *dst, uint8_t value, size_t size)
快速内存填充 / Fast memory fill
static void FastCopy(void *dst, const void *src, size_t size)
快速内存拷贝 / Fast memory copy
原始数据封装类。 A class for encapsulating raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
void * addr_
数据存储地址。 The storage address of the data.
Flash 存储的块信息结构 (Structure representing a Flash storage block).
KeyInfo key
Align KeyInfo to MinWriteSize.
uint32_t header
Flash block header.
键信息结构,存储键的元数据 (Structure containing key metadata).
BlockBoolData< MinWriteSize > no_next_key
是否是最后一个键
BlockBoolData< MinWriteSize > available_flag
该键是否有效
BlockBoolData< MinWriteSize > uninit
该键是否未初始化
uint32_t raw_info
高7位为 nameLength,低25位为 dataSize
Flash 存储的块信息结构 (Structure representing a Flash storage block).
KeyInfo key
该块的键信息 (Key metadata in this block).
uint32_t header
Flash 块头标识 (Flash block header identifier).
键信息结构,存储键的元数据 (Structure containing key metadata).