diff --git a/deps/ox/CMakeLists.txt b/deps/ox/CMakeLists.txt index dc872d29..188227d7 100644 --- a/deps/ox/CMakeLists.txt +++ b/deps/ox/CMakeLists.txt @@ -15,6 +15,10 @@ if(OX_BUILD_EXEC STREQUAL "OFF" OR OX_USE_STDLIB STREQUAL "OFF") set(OX_RUN_TESTS "OFF") endif() +if(OX_USE_STDLIB STREQUAL "ON") + add_definitions(-DOX_USE_STDLIB) +endif() + if(NOT MSVC) add_definitions( -std=c++11 diff --git a/deps/ox/src/ox/fs/filestore/filestore.hpp b/deps/ox/src/ox/fs/filestore/filestore.hpp index a3c6d938..239dae97 100644 --- a/deps/ox/src/ox/fs/filestore/filestore.hpp +++ b/deps/ox/src/ox/fs/filestore/filestore.hpp @@ -24,9 +24,9 @@ class FileStore { uint8_t fileType; }; - virtual bool valid(InodeId_t size) = 0; + virtual Error format() = 0; - virtual void resize(InodeId_t size = 0) = 0; + virtual Error setSize(InodeId_t size) = 0; virtual Error write(InodeId_t id, void *data, InodeId_t dataLen, uint8_t fileType = 0) = 0; diff --git a/deps/ox/src/ox/fs/filestore/filestoretemplate.hpp b/deps/ox/src/ox/fs/filestore/filestoretemplate.hpp index edc53e19..aaacff51 100644 --- a/deps/ox/src/ox/fs/filestore/filestoretemplate.hpp +++ b/deps/ox/src/ox/fs/filestore/filestoretemplate.hpp @@ -17,14 +17,19 @@ template class FileStoreTemplate: public FileStore { private: + struct __attribute__((packed)) FileStoreData { + ox::LittleEndian rootNode = sizeof(LinkedList); + }; + + size_t m_buffSize = 0; ox::fs::LinkedList *m_linkedList = nullptr; public: - FileStoreTemplate(void *buff); + FileStoreTemplate(void *buff, size_t buffSize); - bool valid(InodeId_t size); + Error format(); - void resize(InodeId_t size = 0); + Error setSize(InodeId_t buffSize); Error write(InodeId_t id, void *data, InodeId_t dataLen, uint8_t fileType = 0); @@ -44,55 +49,96 @@ class FileStoreTemplate: public FileStore { InodeId_t available(); + private: + FileStoreData &fileStoreData(); + }; template -FileStoreTemplate::FileStoreTemplate(void *buff) { +FileStoreTemplate::FileStoreTemplate(void *buff, size_t buffSize) { + m_buffSize = buffSize; m_linkedList = static_cast*>(buff); + if (!m_linkedList->valid(buffSize)) { + m_buffSize = 0; + m_linkedList = nullptr; + } } template -bool FileStoreTemplate::valid(size_t size) { - return false; +Error FileStoreTemplate::format() { + Error err = 0; + auto data = m_linkedList->malloc(sizeof(FileStoreData)); + if (data.valid()) { + new (data->data()) FileStoreData; + } else { + err = 1; + } + return err; } -void FileStoreTemplate::resize(InodeId_t size = 0) { +template +Error FileStoreTemplate::setSize(InodeId_t size) { + Error err = 0; + if (m_buffSize >= size) { + err |= m_linkedList->setSize(size); + } else { + err = 1; + } + return err; } -Error FileStoreTemplate::write(InodeId_t id, void *data, InodeId_t dataLen, uint8_t fileType = 0) { +template +Error FileStoreTemplate::write(InodeId_t id, void *data, InodeId_t dataLen, uint8_t fileType) { return 1; } +template Error FileStoreTemplate::incLinks(InodeId_t id) { return 1; } +template Error FileStoreTemplate::decLinks(InodeId_t id) { return 1; } +template Error FileStoreTemplate::read(InodeId_t id, void *data, InodeId_t *size) { return 1; } +template Error FileStoreTemplate::read(InodeId_t id, InodeId_t readStart, InodeId_t readSize, void *data, InodeId_t *size) { return 1; } -StatInfo FileStoreTemplate::stat(InodeId_t id) { +template +typename FileStoreTemplate::StatInfo FileStoreTemplate::stat(InodeId_t id) { return {}; } +template InodeId_t FileStoreTemplate::spaceNeeded(InodeId_t size) { return 1; } +template InodeId_t FileStoreTemplate::size() { return 1; } +template InodeId_t FileStoreTemplate::available() { return 1; } +template +typename FileStoreTemplate::FileStoreData &FileStoreTemplate::fileStoreData() { + return *reinterpret_cast(m_linkedList->firstItem()); +} + +using FileStore16 = FileStoreTemplate; +using FileStore32 = FileStoreTemplate; +using FileStore64 = FileStoreTemplate; + } diff --git a/deps/ox/src/ox/fs/filestore/linkedlist.hpp b/deps/ox/src/ox/fs/filestore/linkedlist.hpp index 6dd4b1db..60c9abde 100644 --- a/deps/ox/src/ox/fs/filestore/linkedlist.hpp +++ b/deps/ox/src/ox/fs/filestore/linkedlist.hpp @@ -20,24 +20,36 @@ class __attribute__((packed)) LinkedList { friend LinkedList; public: - ox::LittleEndian size = sizeof(Item); + ox::LittleEndian m_size = sizeof(Item); protected: ox::LittleEndian prev = 0; ox::LittleEndian next = 0; + public: explicit Item(size_t size) { - this->size = size; + this->m_size = size; + } + + size_t size() const { + return m_size; + } + + ox::fs::Ptr data() { + return Ptr(this, m_size, sizeof(*this), m_size - sizeof(*this)); } }; private: struct __attribute__((packed)) Header { ox::LittleEndian size = sizeof(Header); + ox::LittleEndian bytesUsed = sizeof(Header); ox::LittleEndian firstItem = 0; }; struct ItemPtr: public ox::fs::Ptr { + inline ItemPtr() = default; + inline ItemPtr(void *dataStart, size_t dataSize, size_t itemOffset, size_t size): Ptr(dataStart, dataSize, itemOffset, size) { } @@ -46,8 +58,10 @@ class __attribute__((packed)) LinkedList { // make sure this can be read as an Item, and then use Item::size for the size auto itemSpace = dataSize - itemOffset; auto item = reinterpret_cast(static_cast(dataStart) + itemOffset); - if (itemSpace >= static_cast(sizeof(Item)) and itemSpace >= item->size) { - this->init(dataStart, dataSize, itemOffset, item->size); + if (itemOffset >= sizeof(Header) and + itemSpace >= static_cast(sizeof(Item)) and + itemSpace >= item->size()) { + this->init(dataStart, dataSize, itemOffset, item->size()); } else { this->init(dataStart, dataSize, 0, 0); } @@ -63,18 +77,31 @@ class __attribute__((packed)) LinkedList { ItemPtr firstItem(); + ItemPtr lastItem(); + ItemPtr prev(Item *item); ItemPtr next(Item *item); ItemPtr ptr(size_t offset); - ItemPtr ptr(uint8_t *item); + ItemPtr ptr(void *item); ItemPtr malloc(size_t size); void free(ItemPtr item); + bool valid(size_t maxSize); + + Error setSize(size_t size); + + size_t size(); + + /** + * @return the bytes still available in this LinkedList + */ + size_t available(); + private: void compact(void (*cb)(ItemPtr itemMoved)); @@ -92,6 +119,15 @@ typename LinkedList::ItemPtr LinkedList::firstItem() { return ptr(m_header.firstItem); } +template +typename LinkedList::ItemPtr LinkedList::lastItem() { + auto first = ptr(m_header.firstItem); + if (first.valid()) { + return prev(first); + } + return ItemPtr(); +} + template typename LinkedList::ItemPtr LinkedList::prev(Item *item) { return ptr(item->prev); @@ -108,20 +144,61 @@ typename LinkedList::ItemPtr LinkedList::ptr(size_t offset) { } template -typename LinkedList::ItemPtr LinkedList::ptr(uint8_t *item) { - return ItemPtr(this, m_header.size, reinterpret_cast(item - static_cast(this))); +typename LinkedList::ItemPtr LinkedList::ptr(void *item) { + return ItemPtr(this, m_header.size, reinterpret_cast(static_cast(item) - static_cast(this))); } template typename LinkedList::ItemPtr LinkedList::malloc(size_t size) { - if (!m_header.firstItem) { - m_header.firstItem = sizeof(m_header); + size += sizeof(Item); + if (m_header.size - m_header.bytesUsed >= size) { + if (!m_header.firstItem) { + m_header.firstItem = sizeof(m_header); + } + auto out = ItemPtr(this, m_header.size, m_header.firstItem, size); + if (out.valid()) { + new (out) Item(size); + auto first = firstItem(); + auto last = lastItem(); + out->next = first; + out->prev = last; + first->prev = out; + last->next = out; + m_header.bytesUsed += out.size(); + } + return out; } - auto out = ItemPtr(this, m_header.size, m_header.firstItem, size); - if (out.valid()) { - new (out) Item(size); + return ItemPtr(); +} + +template +void LinkedList::free(ItemPtr item) { + auto prev = this->prev(item); + auto next = this->next(item); + prev->next = next; + next->prev = prev; + m_header.bytesUsed -= item.size(); +} + +template +Error LinkedList::setSize(size_t size) { + auto last = lastItem(); + if ((last.valid() and last.end() >= size) or size < sizeof(m_header)) { + return 1; + } else { + m_header.size = size; + return 0; } - return out; +} + +template +bool LinkedList::valid(size_t maxSize) { + return m_header.size <= maxSize; +} + +template +size_t LinkedList::available() { + return m_header.size - m_header.bytesUsed; } template diff --git a/deps/ox/src/ox/fs/filestore/ptr.hpp b/deps/ox/src/ox/fs/filestore/ptr.hpp index 55bf1d27..24ca62d2 100644 --- a/deps/ox/src/ox/fs/filestore/ptr.hpp +++ b/deps/ox/src/ox/fs/filestore/ptr.hpp @@ -18,7 +18,7 @@ class Ptr { private: uint8_t *m_dataStart = nullptr; - size_t m_itemStart = 0; + size_t m_itemOffset = 0; size_t m_itemSize = 0; public: @@ -32,6 +32,8 @@ class Ptr { inline size_t offset() const; + inline size_t end(); + inline T *operator->() const; inline operator T*() const; @@ -40,10 +42,6 @@ class Ptr { inline T &operator*() const; - inline Ptr &operator=(size_t offset); - - inline Ptr &operator+=(size_t offset); - protected: void init(void *dataStart, size_t dataSize, size_t itemStart, size_t itemSize); @@ -56,7 +54,7 @@ inline Ptr::Ptr(void *dataStart, size_t dataSize, size_t itemStart, s template inline bool Ptr::valid() const { - return m_dataStart and m_itemStart; + return m_dataStart and m_itemOffset; } template @@ -66,24 +64,29 @@ inline size_t Ptr::size() const { template inline size_t Ptr::offset() const { - return m_itemStart; + return m_itemOffset; +} + +template +inline size_t Ptr::end() { + return m_itemOffset + m_itemSize; } template inline T *Ptr::operator->() const { ox_assert(valid(), "Invalid pointer access. (ox::fs::Ptr::operator->())"); - return reinterpret_cast(m_dataStart + m_itemStart); + return reinterpret_cast(m_dataStart + m_itemOffset); } template inline Ptr::operator T*() const { - return reinterpret_cast(m_dataStart + m_itemStart); + return reinterpret_cast(m_dataStart + m_itemOffset); } template inline Ptr::operator size_t() const { if (valid()) { - return m_itemStart; + return m_itemOffset; } return 0; } @@ -94,26 +97,14 @@ inline T &Ptr::operator*() const { return *static_cast(this); } -template -inline Ptr &Ptr::operator=(size_t offset) { - m_itemStart = offset; - return *this; -} - -template -inline Ptr &Ptr::operator+=(size_t offset) { - m_itemStart += offset; - return *this; -} - template void Ptr::init(void *dataStart, size_t dataSize, size_t itemStart, size_t itemSize) { // do some sanity checks before assuming this is valid + m_dataStart = static_cast(dataStart); if (itemSize >= sizeof(T) and dataStart and itemStart + itemSize <= dataSize) { - m_dataStart = static_cast(dataStart); - m_itemStart = itemStart; + m_itemOffset = itemStart; m_itemSize = itemSize; } } diff --git a/deps/ox/src/ox/fs/test/tests.cpp b/deps/ox/src/ox/fs/test/tests.cpp index 88d74fea..7991447f 100644 --- a/deps/ox/src/ox/fs/test/tests.cpp +++ b/deps/ox/src/ox/fs/test/tests.cpp @@ -6,6 +6,9 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +// make sure asserts are enabled for the test file +#undef NDEBUG + #include #include #include @@ -14,6 +17,8 @@ #include #include #include +#include + using namespace std; using namespace ox; @@ -330,12 +335,24 @@ map tests = { { "LinkedList::insert", [](string) { + int err = 0; constexpr auto buffLen = 5000; uint8_t buff[buffLen]; auto list = new (buff) ox::fs::LinkedList(buffLen); - assert(list->malloc(50).valid()); - assert(list->firstItem().valid()); - assert(list->firstItem()->size == 50); + err |= !(list->malloc(50).valid()); + err |= !(list->firstItem().valid()); + err |= !(list->firstItem()->size() == 50); + return err; + } + }, + { + "FileStore::readWrite", + [](string) { + constexpr auto buffLen = 5000; + uint8_t buff[buffLen]; + auto list = new (buff) ox::fs::LinkedList(buffLen); + ox::fs::FileStore32 fileStore(list, buffLen); + ox_assert(fileStore.format() == 0, "Filestore::format failed."); return 0; } }, diff --git a/deps/ox/src/ox/std/assert.hpp b/deps/ox/src/ox/std/assert.hpp index 6c0fe8b1..c55e0895 100644 --- a/deps/ox/src/ox/std/assert.hpp +++ b/deps/ox/src/ox/std/assert.hpp @@ -10,7 +10,7 @@ void oxAssert(const char *file, int line, bool pass, const char *msg); -#ifdef NDEBUG +#ifndef NDEBUG #define ox_assert(pass, msg) oxAssert(__FILE__, __LINE__, pass, msg) #else #define ox_assert(pass, msg) diff --git a/deps/ox/src/ox/std/byteswap.hpp b/deps/ox/src/ox/std/byteswap.hpp index 5d67b397..4a462ada 100644 --- a/deps/ox/src/ox/std/byteswap.hpp +++ b/deps/ox/src/ox/std/byteswap.hpp @@ -86,10 +86,19 @@ class __attribute__((packed)) LittleEndian { public: inline LittleEndian() = default; + inline LittleEndian(const LittleEndian &other) { + m_value = other.m_value; + } + inline LittleEndian(T value) { m_value = ox::bigEndianAdapt(value); } + inline const LittleEndian &operator=(const LittleEndian &other) { + m_value = other.m_value; + return *this; + } + inline T operator=(T value) { m_value = ox::bigEndianAdapt(value); return value; @@ -99,41 +108,29 @@ class __attribute__((packed)) LittleEndian { return ox::bigEndianAdapt(m_value); } - inline T operator+(T value) const { - return ox::bigEndianAdapt(m_value) + value; - } - - inline T operator+=(T other) { + template + inline T operator+=(I other) { auto newVal = *this + other; m_value = ox::bigEndianAdapt(newVal); return newVal; } - inline T operator-(T value) const { - return ox::bigEndianAdapt(m_value) - value; - } - - inline T operator-=(T other) { + template + inline T operator-=(I other) { auto newVal = *this - other; m_value = ox::bigEndianAdapt(newVal); return newVal; } - inline T operator*(T value) const { - return ox::bigEndianAdapt(m_value) * value; - } - - inline T operator*=(T other) { + template + inline T operator*=(I other) { auto newVal = *this * other; m_value = ox::bigEndianAdapt(newVal); return newVal; } - inline T operator/(T value) const { - return ox::bigEndianAdapt(m_value) / value; - } - - inline T operator/=(T other) { + template + inline T operator/=(I other) { auto newVal = *this / other; m_value = ox::bigEndianAdapt(newVal); return newVal;