23 static Storage * storage =
nullptr;
24 if (storage ==
nullptr) {
31 if (
name ==
nullptr) {
36 size_t crc32InputSize = lenght*
sizeof(char)/
sizeof(
uint32_t)+1;
41 m_nameCRC32 =
Ion::crc32(crc32Input, crc32InputSize);
50 assert(m_magicHeader == Magic);
51 assert(m_magicFooter == Magic);
53 overrideSizeAtPosition(m_buffer, 0);
57 return k_storageSize-(endBuffer()-m_buffer)-
sizeof(
record_size_t);
61 if (!nameCompliant(name)) {
64 size_t recordSize = sizeOfRecord(name, size);
65 if (recordSize >= k_maxRecordSize || recordSize >
availableSize()) {
68 if (isNameTaken(name)) {
72 char * newRecord = endBuffer();
74 newRecord += overrideSizeAtPosition(newRecord, (
record_size_t)recordSize);
76 newRecord += overrideNameAtPosition(newRecord, name);
78 newRecord += overrideValueAtPosition(newRecord,
data, size);
80 overrideSizeAtPosition(newRecord, 0);
86 for (
char * p : *
this) {
87 const char * name = nameOfRecordStarting(p);
89 if (
strcmp(ext, extension) == 0) {
97 int currentIndex = -1;
98 const char * name =
nullptr;
99 for (
char * p : *
this) {
100 const char * currentName = nameOfRecordStarting(p);
101 const char * currentExtension = currentName+
strlen(currentName)-
strlen(extension);
102 if (
strcmp(currentExtension, extension) == 0) {
105 if (currentIndex == index) {
110 if (name ==
nullptr) {
117 for (
char * p : *
this) {
118 const char * currentName = nameOfRecordStarting(p);
119 if (
strcmp(currentName, name) == 0) {
126 const char * Storage::nameOfRecord(
const Record record) {
127 for (
char * p : *
this) {
128 Record currentRecord(nameOfRecordStarting(p));
129 if (record == currentRecord) {
130 return nameOfRecordStarting(p);
137 if (!nameCompliant(name)) {
140 if (isNameTaken(name, &record)) {
143 size_t nameSize =
strlen(name)+1;
144 for (
char * p : *
this) {
145 Record currentRecord(nameOfRecordStarting(p));
146 if (record == currentRecord) {
147 size_t previousNameSize =
strlen(nameOfRecordStarting(p))+1;
149 size_t newRecordSize = previousRecordSize-previousNameSize+nameSize;
150 if (newRecordSize >= k_maxRecordSize || !slideBuffer(p+
sizeof(
record_size_t)+previousNameSize, nameSize-previousNameSize)) {
153 overrideSizeAtPosition(p, newRecordSize);
161 Storage::Record::Data Storage::valueOfRecord(
const Record record) {
162 for (
char * p : *
this) {
163 Record currentRecord(nameOfRecordStarting(p));
164 if (record == currentRecord) {
165 const char * name = nameOfRecordStarting(p);
167 const void * value = valueOfRecordStarting(p);
171 return {.buffer=
nullptr, .size= 0};
175 for (
char * p : *
this) {
176 Record currentRecord(nameOfRecordStarting(p));
177 if (record == currentRecord) {
179 const char * name = nameOfRecordStarting(p);
180 size_t newRecordSize = sizeOfRecord(name,
data.size);
181 if (newRecordSize >= k_maxRecordSize || !slideBuffer(p+previousRecordSize, newRecordSize-previousRecordSize)) {
185 overrideSizeAtPosition(p, newRecordSize);
193 void Storage::destroyRecord(Record record) {
194 for (
char * p : *
this) {
195 Record currentRecord(nameOfRecordStarting(p));
196 if (record == currentRecord) {
198 slideBuffer(p+previousRecordSize, -previousRecordSize);
203 static inline uint16_t unalignedShort(
char * address) {
214 static inline void writeUnalignedShort(
uint16_t value,
char * address) {
224 return unalignedShort(
start);
227 const char * Storage::nameOfRecordStarting(
char *
start)
const {
231 const void * Storage::valueOfRecordStarting(
char *
start)
const {
233 while (*currentChar != 0) {
236 return currentChar+1;
239 size_t Storage::overrideSizeAtPosition(
char * position, record_size_t size) {
240 writeUnalignedShort(size, position);
244 size_t Storage::overrideNameAtPosition(
char * position,
const char * name) {
248 size_t Storage::overrideValueAtPosition(
char * position,
const void *
data, record_size_t size) {
253 bool Storage::isNameTaken(
const char * name, Record * recordToExclude) {
254 Record r = Record(name);
258 for (
char * p : *
this) {
259 Record s(nameOfRecordStarting(p));
260 if (recordToExclude && s == *recordToExclude) {
270 bool Storage::nameCompliant(
const char * name)
const {
273 const char * currentChar = name;
274 while (*currentChar != 0) {
275 if (*currentChar ==
'.') {
282 if ((*currentChar >=
'a' && *currentChar <=
'z') || *currentChar ==
'_' || (*currentChar >=
'0' && *currentChar <=
'9') || *currentChar ==
'.') {
288 return name != currentChar;
291 char * Storage::endBuffer() {
292 char * currentBuffer = m_buffer;
293 for (
char * p : *
this) {
294 currentBuffer += sizeOfRecordStarting(p);
296 return currentBuffer;
299 size_t Storage::sizeOfRecord(
const char * name,
size_t dataSize)
const {
300 size_t nameSize =
strlen(name)+1;
304 bool Storage::slideBuffer(
char * position,
int delta) {
312 Storage::RecordIterator & Storage::RecordIterator::operator++() {
313 record_size_t size = unalignedShort(m_recordStart);
314 char * nextRecord = m_recordStart+size;
315 record_size_t newRecordSize = unalignedShort(nextRecord);
316 m_recordStart = (newRecordSize == 0 ? nullptr : nextRecord);
Record recordWithExtensionAtIndex(const char *extension, int index)
void * memset(void *b, int c, size_t len)
Record::ErrorStatus createRecord(const char *name, const void *data, size_t size)
size_t strlcpy(char *dst, const char *src, size_t len)
int numberOfRecordsWithExtension(const char *extension)
Record recordNamed(const char *name)
static Storage * sharedStorage()
size_t strlen(const char *s)
void * memmove(void *dst, const void *src, size_t n)
Record(const char *name=nullptr)
const char * name() const
uint32_t crc32(const uint32_t *data, size_t length)
int strcmp(const char *s1, const char *s2)
void * memcpy(void *dst, const void *src, size_t n)