mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
[ion] Storage delegate gets notified of storage changes
This commit is contained in:
@@ -11,6 +11,8 @@ namespace Ion {
|
||||
*
|
||||
* A record's fullName is baseName.extension. */
|
||||
|
||||
class StorageDelegate;
|
||||
|
||||
class Storage {
|
||||
public:
|
||||
typedef uint16_t record_size_t;
|
||||
@@ -76,6 +78,11 @@ public:
|
||||
Storage();
|
||||
size_t availableSize();
|
||||
uint32_t checksum();
|
||||
|
||||
// Delegate
|
||||
void setDelegate(StorageDelegate * delegate) { m_delegate = delegate; }
|
||||
void notifyChangeToDelegate() const;
|
||||
|
||||
int numberOfRecordsWithExtension(const char * extension);
|
||||
static bool FullNameHasExtension(const char * fullName, const char * extension, size_t extensionLength);
|
||||
|
||||
@@ -91,6 +98,7 @@ public:
|
||||
|
||||
// Record destruction
|
||||
void destroyRecordsWithExtension(const char * extension);
|
||||
|
||||
private:
|
||||
constexpr static uint32_t Magic = 0xEE0BDDBA;
|
||||
constexpr static size_t k_maxRecordSize = (1 << sizeof(record_size_t)*8);
|
||||
@@ -143,6 +151,18 @@ private:
|
||||
uint32_t m_magicHeader;
|
||||
char m_buffer[k_storageSize];
|
||||
uint32_t m_magicFooter;
|
||||
StorageDelegate * m_delegate;
|
||||
};
|
||||
|
||||
/* Some apps memoize records and need to be notified when a record might have
|
||||
* become invalid. We could have computed and compared the checksum of the
|
||||
* storage to detect storage invalidity, but profiling showed that this slows
|
||||
* down the execution (for example when scrolling the functions list).
|
||||
* We thus decided to notify a delegate when the storage changes. */
|
||||
|
||||
class StorageDelegate {
|
||||
public:
|
||||
virtual void storageDidChange(const Storage * storage) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -73,7 +73,8 @@ Storage::Record::Record(const char * basename, int basenameLength, const char *
|
||||
Storage::Storage() :
|
||||
m_magicHeader(Magic),
|
||||
m_buffer(),
|
||||
m_magicFooter(Magic)
|
||||
m_magicFooter(Magic),
|
||||
m_delegate(nullptr)
|
||||
{
|
||||
assert(m_magicHeader == Magic);
|
||||
assert(m_magicFooter == Magic);
|
||||
@@ -89,6 +90,12 @@ uint32_t Storage::checksum() {
|
||||
return Ion::crc32PaddedString(m_buffer, endBuffer()-m_buffer);
|
||||
}
|
||||
|
||||
void Storage::notifyChangeToDelegate() const {
|
||||
if (m_delegate != nullptr) {
|
||||
m_delegate->storageDidChange(this);
|
||||
}
|
||||
}
|
||||
|
||||
Storage::Record::ErrorStatus Storage::createRecordWithFullName(const char * fullName, const void * data, size_t size) {
|
||||
size_t recordSize = sizeOfRecordWithFullName(fullName, size);
|
||||
if (recordSize >= k_maxRecordSize || recordSize > availableSize()) {
|
||||
@@ -107,6 +114,7 @@ Storage::Record::ErrorStatus Storage::createRecordWithFullName(const char * full
|
||||
newRecord += overrideValueAtPosition(newRecord, data, size);
|
||||
// Next Record is null-sized
|
||||
overrideSizeAtPosition(newRecord, 0);
|
||||
notifyChangeToDelegate();
|
||||
return Record::ErrorStatus::None;
|
||||
}
|
||||
|
||||
@@ -128,6 +136,7 @@ Storage::Record::ErrorStatus Storage::createRecordWithExtension(const char * bas
|
||||
newRecord += overrideValueAtPosition(newRecord, data, size);
|
||||
// Next Record is null-sized
|
||||
overrideSizeAtPosition(newRecord, 0);
|
||||
notifyChangeToDelegate();
|
||||
return Record::ErrorStatus::None;
|
||||
}
|
||||
|
||||
@@ -201,15 +210,20 @@ Storage::Record Storage::recordBaseNamedWithExtensions(const char * baseName, co
|
||||
void Storage::destroyRecordsWithExtension(const char * extension) {
|
||||
size_t extensionLength = strlen(extension);
|
||||
char * currentRecordStart = (char *)m_buffer;
|
||||
bool didChange = false;
|
||||
while (currentRecordStart != nullptr && sizeOfRecordStarting(currentRecordStart) != 0) {
|
||||
const char * currentFullName = fullNameOfRecordStarting(currentRecordStart);
|
||||
if (FullNameHasExtension(currentFullName, extension, extensionLength)) {
|
||||
Record currentRecord(currentFullName);
|
||||
currentRecord.destroy();
|
||||
didChange = true;
|
||||
continue;
|
||||
}
|
||||
currentRecordStart = *(RecordIterator(currentRecordStart).operator++());
|
||||
}
|
||||
if (didChange) {
|
||||
notifyChangeToDelegate();
|
||||
}
|
||||
}
|
||||
|
||||
const char * Storage::fullNameOfRecord(const Record record) {
|
||||
@@ -241,6 +255,7 @@ Storage::Record::ErrorStatus Storage::setFullNameOfRecord(const Record record, c
|
||||
}
|
||||
overrideSizeAtPosition(p, newRecordSize);
|
||||
overrideFullNameAtPosition(p+sizeof(record_size_t), fullName);
|
||||
notifyChangeToDelegate();
|
||||
return Record::ErrorStatus::None;
|
||||
}
|
||||
}
|
||||
@@ -263,6 +278,7 @@ Storage::Record::ErrorStatus Storage::setBaseNameWithExtensionOfRecord(Record re
|
||||
}
|
||||
overrideSizeAtPosition(p, newRecordSize);
|
||||
overrideBaseNameWithExtensionAtPosition(p+sizeof(record_size_t), baseName, extension);
|
||||
notifyChangeToDelegate();
|
||||
return Record::ErrorStatus::None;
|
||||
}
|
||||
}
|
||||
@@ -295,6 +311,7 @@ Storage::Record::ErrorStatus Storage::setValueOfRecord(Record record, Record::Da
|
||||
record_size_t fullNameSize = strlen(fullName)+1;
|
||||
overrideSizeAtPosition(p, newRecordSize);
|
||||
overrideValueAtPosition(p+sizeof(record_size_t)+fullNameSize, data.buffer, data.size);
|
||||
notifyChangeToDelegate();
|
||||
return Record::ErrorStatus::None;
|
||||
}
|
||||
}
|
||||
@@ -310,6 +327,7 @@ void Storage::destroyRecord(Record record) {
|
||||
if (record == currentRecord) {
|
||||
record_size_t previousRecordSize = sizeOfRecordStarting(p);
|
||||
slideBuffer(p+previousRecordSize, -previousRecordSize);
|
||||
notifyChangeToDelegate();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user