From 59cc34b4e8b10341a1c9d784d049c4301e9b9e6e Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Mon, 23 Apr 2018 22:51:49 -0500 Subject: [PATCH] [ox/fs] Add new Directory type --- deps/ox/CMakeLists.txt | 2 +- deps/ox/src/ox/fs/CMakeLists.txt | 9 +- .../src/ox/fs/filestore/filestoretemplate.hpp | 8 +- deps/ox/src/ox/fs/filesystem/pathiterator.cpp | 39 +++++- deps/ox/src/ox/fs/filesystem/pathiterator.hpp | 17 ++- deps/ox/src/ox/fs/filesystem2/directory.cpp | 19 +++ deps/ox/src/ox/fs/filesystem2/directory.hpp | 112 +++++++++++++++++- deps/ox/src/ox/fs/test/CMakeLists.txt | 2 + deps/ox/src/ox/fs/test/tests.cpp | 14 +++ deps/ox/src/ox/ptrarith/nodebuffer.hpp | 66 ++++++++++- deps/ox/src/ox/ptrarith/ptr.hpp | 18 +++ deps/ox/src/ox/std/std.hpp | 1 + deps/ox/src/ox/std/stddef.hpp | 13 ++ deps/ox/src/ox/std/types.hpp | 6 +- deps/ox/src/ox/trace/trace.hpp | 6 +- 15 files changed, 306 insertions(+), 26 deletions(-) create mode 100644 deps/ox/src/ox/fs/filesystem2/directory.cpp create mode 100644 deps/ox/src/ox/std/stddef.hpp diff --git a/deps/ox/CMakeLists.txt b/deps/ox/CMakeLists.txt index 0e59b294..1ff4fd57 100644 --- a/deps/ox/CMakeLists.txt +++ b/deps/ox/CMakeLists.txt @@ -36,7 +36,7 @@ if(NOT MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsign-compare") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wunused-variable") - + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wmissing-field-initializers") if (CMAKE_BUILD_TYPE STREQUAL "Release") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") diff --git a/deps/ox/src/ox/fs/CMakeLists.txt b/deps/ox/src/ox/fs/CMakeLists.txt index be7285fb..f4dd4c3f 100644 --- a/deps/ox/src/ox/fs/CMakeLists.txt +++ b/deps/ox/src/ox/fs/CMakeLists.txt @@ -6,6 +6,7 @@ add_library( filestore/filestoretemplate.cpp filesystem/filesystem.cpp filesystem/pathiterator.cpp + filesystem2/directory.cpp ) set_property( @@ -38,14 +39,6 @@ install( include/ox/fs ) -install( - FILES - filestore/nodebuffer.hpp - filestore/ptr.hpp - DESTINATION - include/ox/fs/filestore -) - install( FILES filesystem/filesystem.hpp diff --git a/deps/ox/src/ox/fs/filestore/filestoretemplate.hpp b/deps/ox/src/ox/fs/filestore/filestoretemplate.hpp index 561de63f..667faaa0 100644 --- a/deps/ox/src/ox/fs/filestore/filestoretemplate.hpp +++ b/deps/ox/src/ox/fs/filestore/filestoretemplate.hpp @@ -32,7 +32,7 @@ struct __attribute__((packed)) FileStoreItem: public ptrarith::Item { return sizeof(*this) + this->size(); } - ox::ptrarith::Ptr data() { + ptrarith::Ptr data() { return ptrarith::Ptr(this, this->size(), sizeof(*this), this->size() - sizeof(*this)); } }; @@ -42,8 +42,8 @@ template class FileStoreTemplate: public FileStore { private: - using ItemPtr = typename ox::ptrarith::NodeBuffer>::ItemPtr; - using Buffer = ox::ptrarith::NodeBuffer>; + using ItemPtr = typename ptrarith::NodeBuffer>::ItemPtr; + using Buffer = ptrarith::NodeBuffer>; struct __attribute__((packed)) FileStoreData { ox::LittleEndian rootNode = 0; @@ -128,7 +128,7 @@ class FileStoreTemplate: public FileStore { template FileStoreTemplate::FileStoreTemplate(void *buff, size_t buffSize) { m_buffSize = buffSize; - m_buffer = reinterpret_cast>*>(buff); + m_buffer = reinterpret_cast>*>(buff); if (!m_buffer->valid(buffSize)) { m_buffSize = 0; m_buffer = nullptr; diff --git a/deps/ox/src/ox/fs/filesystem/pathiterator.cpp b/deps/ox/src/ox/fs/filesystem/pathiterator.cpp index 06ce55fb..f5d070e4 100644 --- a/deps/ox/src/ox/fs/filesystem/pathiterator.cpp +++ b/deps/ox/src/ox/fs/filesystem/pathiterator.cpp @@ -12,9 +12,13 @@ namespace ox { -PathIterator::PathIterator(const char *path, std::size_t maxSize) { +PathIterator::PathIterator(const char *path, std::size_t maxSize, std::size_t iterator) { m_path = path; m_maxSize = maxSize; + m_iterator = iterator; +} + +PathIterator::PathIterator(const char *path): PathIterator(path, ox_strlen(path)) { } /** @@ -85,7 +89,30 @@ int PathIterator::next(char *pathOut, std::size_t pathOutSize) { return retval; } -bool PathIterator::hasNext() { +ValErr PathIterator::nextSize() const { + std::size_t size = 0; + Error retval = 1; + auto it = m_iterator; + if (it < m_maxSize && ox_strlen(&m_path[it])) { + retval = 0; + if (m_path[it] == '/') { + it++; + } + std::size_t start = it; + // end is at the next / + const char *substr = ox_strchr(&m_path[start], '/', m_maxSize - start); + // correct end if it is invalid, which happens if there is no next / + if (!substr) { + substr = ox_strchr(&m_path[start], 0, m_maxSize - start); + } + std::size_t end = substr - m_path; + size = end - start; + } + it += size; + return {size, retval}; +} + +bool PathIterator::hasNext() const { std::size_t size = 0; if (m_iterator < m_maxSize && ox_strlen(&m_path[m_iterator])) { std::size_t start = m_iterator; @@ -104,4 +131,12 @@ bool PathIterator::hasNext() { return size > 0; } +PathIterator PathIterator::operator+(int i) { + return PathIterator(m_path, m_maxSize, m_iterator + i); +} + +PathIterator PathIterator::operator-(int i) { + return PathIterator(m_path, m_maxSize, m_iterator - i); +} + } diff --git a/deps/ox/src/ox/fs/filesystem/pathiterator.hpp b/deps/ox/src/ox/fs/filesystem/pathiterator.hpp index f64d3717..8ca6523e 100644 --- a/deps/ox/src/ox/fs/filesystem/pathiterator.hpp +++ b/deps/ox/src/ox/fs/filesystem/pathiterator.hpp @@ -8,6 +8,7 @@ #pragma once +#include #include namespace ox { @@ -19,7 +20,9 @@ class PathIterator { std::size_t m_maxSize = 0; public: - PathIterator(const char *path, std::size_t maxSize); + PathIterator(const char *path, std::size_t maxSize, std::size_t iterator = 0); + + PathIterator(const char *path); /** * @return 0 if no error @@ -36,7 +39,17 @@ class PathIterator { */ int next(char *pathOut, std::size_t pathOutSize); - bool hasNext(); + /** + * @return 0 if no error + */ + ValErr nextSize() const; + + bool hasNext() const; + + PathIterator operator+(int i); + + PathIterator operator-(int i); + }; } diff --git a/deps/ox/src/ox/fs/filesystem2/directory.cpp b/deps/ox/src/ox/fs/filesystem2/directory.cpp new file mode 100644 index 00000000..3281fea4 --- /dev/null +++ b/deps/ox/src/ox/fs/filesystem2/directory.cpp @@ -0,0 +1,19 @@ +/* + * Copyright 2015 - 2018 gtalent2@gmail.com + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "directory.hpp" + +namespace ox::fs { + +template class Directory; +template class Directory; + +template struct DirectoryEntry; +template struct DirectoryEntry; + +} diff --git a/deps/ox/src/ox/fs/filesystem2/directory.hpp b/deps/ox/src/ox/fs/filesystem2/directory.hpp index d3dc3bc9..b285ac8c 100644 --- a/deps/ox/src/ox/fs/filesystem2/directory.hpp +++ b/deps/ox/src/ox/fs/filesystem2/directory.hpp @@ -6,20 +6,126 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#pragma once + #include #include +#include +#include namespace ox::fs { -struct DirectoryData { +template +struct __attribute__((packed)) DirectoryEntry { + + // NodeBuffer fields + ox::LittleEndian prev = 0; + ox::LittleEndian next = 0; + + // DirectoryEntry fields + ox::LittleEndian inode = 0; + BString<255> name; + + explicit DirectoryEntry(const char *name) { + this->name = name; + } + + /** + * @return the size of the data + the size of the Item type + */ + InodeId_t fullSize() const { + return offsetof(DirectoryEntry, name) + name.size(); + } + + InodeId_t size() const { + return fullSize() - offsetof(DirectoryEntry, inode); + } + + ptrarith::Ptr data() { + return ptrarith::Ptr(this, this->size(), sizeof(*this), this->size() - sizeof(*this)); + } + }; + +template class Directory { - Error add(const PathIterator &it, uint64_t inode); + private: + using Buffer = ptrarith::NodeBuffer>; + std::size_t m_size = 0; + Buffer *m_buff = nullptr; - Error rm(PathIterator &it); + public: + Directory(uint8_t *buff, std::size_t size); + + /** + * Initializes Directory. + */ + Error init() noexcept; + + Error write(PathIterator it, InodeId_t inode) noexcept; + + Error rm(PathIterator it) noexcept; + + ValErr find(PathIterator it) const noexcept; }; +template +Directory::Directory(uint8_t *buff, std::size_t size) { + m_size = size; + m_buff = reinterpret_cast(buff); +} + +template +Error Directory::init() noexcept { + if (m_size >= sizeof(Buffer)) { + new (m_buff) Buffer(m_size); + return 0; + } + return 1; +} + +template +Error Directory::write(PathIterator it, InodeId_t inode) noexcept { + if (it.hasNext()) { + return write(it + 1, inode); + } else { + auto current = find(it); + if (current.ok()) { + } else { + } + } + return 1; +} + +template +Error Directory::rm(PathIterator) noexcept { + return 1; +} + +template +ValErr Directory::find(PathIterator it) const noexcept { + auto size = it.nextSize(); + char name[size + 1]; + it.next(name, size); + for (auto i = m_buff->iterator(); i.hasNext(); i.next()) { + if (i->name == name) { + return static_cast(i->inode); + } + } + return {0, 1}; +} + + +extern template class Directory; +extern template class Directory; + +extern template struct DirectoryEntry; +extern template struct DirectoryEntry; + +using Directory16 = Directory; +using Directory32 = Directory; + } diff --git a/deps/ox/src/ox/fs/test/CMakeLists.txt b/deps/ox/src/ox/fs/test/CMakeLists.txt index 667cfc89..c0c9308b 100644 --- a/deps/ox/src/ox/fs/test/CMakeLists.txt +++ b/deps/ox/src/ox/fs/test/CMakeLists.txt @@ -74,3 +74,5 @@ add_test("Test\\ FileSystem32::stripDirectories" FSTests "FileSystem32::stripDir add_test("Test\\ NodeBuffer::insert" FSTests "NodeBuffer::insert") add_test("Test\\ FileStore::readWrite" FSTests "FileStore::readWrite") + +add_test("Test\\ Directory" FSTests "Directory") diff --git a/deps/ox/src/ox/fs/test/tests.cpp b/deps/ox/src/ox/fs/test/tests.cpp index a501462e..d6646909 100644 --- a/deps/ox/src/ox/fs/test/tests.cpp +++ b/deps/ox/src/ox/fs/test/tests.cpp @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -382,6 +383,19 @@ map tests = { return 0; } }, + { + "Directory", + [](string) { + std::array buff; + ox::fs::Directory32 dir(buff.data(), buff.size()); + dir.init(); + dir.write("/file1", 1); + //oxAssert(dir.find("/file1") == 1, "Could not find /file1"); + dir.write("/file3", 3); + dir.write("/file2", 2); + return 0; + } + }, }, }; diff --git a/deps/ox/src/ox/ptrarith/nodebuffer.hpp b/deps/ox/src/ox/ptrarith/nodebuffer.hpp index 5da808b0..8ce43138 100644 --- a/deps/ox/src/ox/ptrarith/nodebuffer.hpp +++ b/deps/ox/src/ox/ptrarith/nodebuffer.hpp @@ -24,7 +24,51 @@ class __attribute__((packed)) NodeBuffer { ox::LittleEndian firstItem = 0; }; - using ItemPtr = ox::ptrarith::Ptr; + using ItemPtr = Ptr; + + class Iterator { + private: + NodeBuffer *m_buffer = nullptr; + ItemPtr m_current; + size_t m_it = 0; + + public: + Iterator(NodeBuffer *buffer, ItemPtr current) { + m_buffer = buffer; + m_current = current; + oxTrace("ox::ptrarith::Iterator::start") << current.offset(); + } + + operator const Item*() const { + return m_current; + } + + operator Item*() { + return m_current; + } + + const Item *operator->() const { + return m_current; + } + + Item *operator->() { + return m_current; + } + + bool hasNext() { + if (m_current.valid()) { + oxTrace("ox::ptrarith::NodeBuffer::Iterator::hasNext::current") << m_current.offset(); + auto next = m_buffer->next(m_current); + return next.valid() && m_buffer->firstItem() != next; + } + return false; + } + + void next() { + oxTrace("ox::ptrarith::NodeBuffer::Iterator::next") << m_it++; + m_current = m_buffer->next(m_current); + } + }; Header m_header; @@ -33,6 +77,10 @@ class __attribute__((packed)) NodeBuffer { explicit NodeBuffer(size_t size); + const Iterator iterator() const; + + Iterator iterator(); + ItemPtr firstItem(); ItemPtr lastItem(); @@ -84,8 +132,20 @@ NodeBuffer::NodeBuffer(size_t size) { m_header.size = size; } +template +const typename NodeBuffer::Iterator NodeBuffer::iterator() const { + return Iterator(this, firstItem()); +} + +template +typename NodeBuffer::Iterator NodeBuffer::iterator() { + oxTrace("ox::ptrarith::NodeBuffer::iterator::size") << m_header.size; + return Iterator(this, firstItem()); +} + template typename NodeBuffer::ItemPtr NodeBuffer::firstItem() { + oxTrace("ox::ptrarith::NodeBuffer::firstItem") << m_header.firstItem; return ptr(m_header.firstItem); } @@ -121,12 +181,14 @@ typename NodeBuffer::ItemPtr NodeBuffer::ptr(size_t // make sure this can be read as an Item, and then use Item::size for the size auto itemSpace = m_header.size - itemOffset; auto item = reinterpret_cast(reinterpret_cast(this) + itemOffset); + oxTrace("ox::ptrarith::NodeBuffer::ptr::itemOffset") << itemOffset << m_header.size - sizeof(Item); if (itemOffset >= sizeof(Header) and itemOffset < m_header.size - sizeof(Item) and itemSpace >= static_cast(sizeof(Item)) and itemSpace >= item->fullSize()) { return ItemPtr(this, m_header.size, itemOffset, item->fullSize()); } else { + oxTrace("ox::ptrarith::NodeBuffer::ptr::null") << itemOffset; return ItemPtr(this, m_header.size, 0, 0); } } @@ -271,7 +333,7 @@ struct __attribute__((packed)) Item { this->m_size = size; } - size_t size() const { + virtual size_t size() const { return m_size; } }; diff --git a/deps/ox/src/ox/ptrarith/ptr.hpp b/deps/ox/src/ox/ptrarith/ptr.hpp index 7952edfc..0746d628 100644 --- a/deps/ox/src/ox/ptrarith/ptr.hpp +++ b/deps/ox/src/ox/ptrarith/ptr.hpp @@ -56,6 +56,10 @@ class Ptr { inline operator size_t() const; + inline bool operator==(const Ptr &other) const; + + inline bool operator!=(const Ptr &other) const; + template inline const Ptr subPtr(size_t offset, size_t size) const; @@ -168,6 +172,20 @@ inline Ptr::operator size_t() const { return 0; } +template +inline bool Ptr::operator==(const Ptr &other) const { + return m_dataStart == other.m_dataStart && + m_itemOffset == other.m_itemOffset && + m_itemSize == other.m_itemSize; +} + +template +inline bool Ptr::operator!=(const Ptr &other) const { + return m_dataStart != other.m_dataStart || + m_itemOffset != other.m_itemOffset || + m_itemSize != other.m_itemSize; +} + template template inline const Ptr Ptr::subPtr(size_t offset, size_t size) const { diff --git a/deps/ox/src/ox/std/std.hpp b/deps/ox/src/ox/std/std.hpp index 66095279..e4accc46 100644 --- a/deps/ox/src/ox/std/std.hpp +++ b/deps/ox/src/ox/std/std.hpp @@ -15,6 +15,7 @@ #include "memops.hpp" #include "new.hpp" #include "random.hpp" +#include "stddef.hpp" #include "strops.hpp" #include "string.hpp" #include "types.hpp" diff --git a/deps/ox/src/ox/std/stddef.hpp b/deps/ox/src/ox/std/stddef.hpp new file mode 100644 index 00000000..15272c45 --- /dev/null +++ b/deps/ox/src/ox/std/stddef.hpp @@ -0,0 +1,13 @@ +/* + * Copyright 2015 - 2018 gtalent2@gmail.com + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#if !defined(offsetof) +#define offsetof(type, member) __builtin_offsetof(type, member) +#endif diff --git a/deps/ox/src/ox/std/types.hpp b/deps/ox/src/ox/std/types.hpp index 377f054e..301fff2c 100644 --- a/deps/ox/src/ox/std/types.hpp +++ b/deps/ox/src/ox/std/types.hpp @@ -66,11 +66,15 @@ struct ValErr { this->error = error; } + inline constexpr operator const T&() const { + return value; + } + inline constexpr operator T&() { return value; } - inline constexpr bool ok() { + inline constexpr bool ok() const { return error == 0; } diff --git a/deps/ox/src/ox/trace/trace.hpp b/deps/ox/src/ox/trace/trace.hpp index ff89279b..d55434fe 100644 --- a/deps/ox/src/ox/trace/trace.hpp +++ b/deps/ox/src/ox/trace/trace.hpp @@ -13,10 +13,10 @@ namespace ox::trace { struct TraceMsg { - ox::BString<150> file = ""; + ox::BString<255> file = ""; int line = 0; uint64_t time = 0; - ox::BString<50> ch = ""; + ox::BString<75> ch = ""; ox::BString<100> msg; }; @@ -93,4 +93,4 @@ class NullStream { } -#define oxTrace(ch) ox::trace::NullStream(__FILE__, __LINE__, ch) +#define oxTrace(ch) ox::trace::StdOutStream(__FILE__, __LINE__, ch)