diff --git a/deps/ox/src/ox/fs/filesystem/directory.hpp b/deps/ox/src/ox/fs/filesystem/directory.hpp index 5548fdd9..da89322a 100644 --- a/deps/ox/src/ox/fs/filesystem/directory.hpp +++ b/deps/ox/src/ox/fs/filesystem/directory.hpp @@ -43,13 +43,14 @@ struct OX_PACKED DirectoryEntry { public: constexpr DirectoryEntry() noexcept = default; - Error init(InodeId_t inode, const char *name, InodeId_t bufferSize) noexcept { - m_bufferSize = bufferSize; + Error init(InodeId_t inode, ox::CRStringView name, size_t bufferSize) noexcept { + m_bufferSize = static_cast(bufferSize); auto d = data(); if (d.valid()) { d->inode = inode; - ox::strncpy(d->name, name, ox::min(bufferSize, static_cast(MaxFileNameLength))); - return OxError(0); + auto const maxStrSz = bufferSize - 1 - sizeof(*this); + ox::strncpy(d->name, name.data(), ox::min(maxStrSz, name.len())); + return {}; } return OxError(1); } @@ -103,23 +104,23 @@ class Directory { */ Error init() noexcept; - Error mkdir(PathIterator path, bool parents, FileName *nameBuff = nullptr); + Error mkdir(PathIterator path, bool parents); /** * @param parents indicates the operation should create non-existent directories in the path, like mkdir -p */ - Error write(PathIterator path, uint64_t inode64, FileName *nameBuff = nullptr) noexcept; + Error write(PathIterator path, uint64_t inode64) noexcept; - Error remove(PathIterator path, FileName *nameBuff = nullptr) noexcept; + Error remove(PathIterator path) noexcept; template Error ls(F cb) noexcept; [[nodiscard]] - Result findEntry(const FileName &name) const noexcept; + Result findEntry(const StringView &name) const noexcept; [[nodiscard]] - Result find(PathIterator name, FileName *nameBuff = nullptr) const noexcept; + Result find(PathIterator path) const noexcept; }; @@ -145,22 +146,17 @@ Error Directory::init() noexcept { } new (buff) Buffer(Size); m_size = Size; - return OxError(0); + return {}; } template -Error Directory::mkdir(PathIterator path, bool parents, FileName *nameBuff) { +Error Directory::mkdir(PathIterator path, bool parents) { if (path.valid()) { oxTrace("ox.fs.Directory.mkdir", path.fullPath()); - // reuse nameBuff if it has already been allocated, as it is a rather large variable - if (nameBuff == nullptr) { - nameBuff = new (ox_alloca(sizeof(FileName))) FileName; - } - // determine if already exists - auto name = nameBuff; - oxReturnError(path.get(*name)); - auto childInode = find(PathIterator(*name)); + ox::StringView name; + oxReturnError(path.get(name)); + auto childInode = find(PathIterator(name)); if (!childInode.ok()) { // if this is not the last item in the path and parents is disabled, // return an error @@ -171,12 +167,10 @@ Error Directory::mkdir(PathIterator path, bool parents, Fi oxTracef("ox.fs.Directory.mkdir", "Generated Inode ID: {}", childInode.value); oxLogError(childInode.error); oxReturnError(childInode.error); - // initialize the directory Directory child(m_fs, childInode.value); oxReturnError(child.init()); - - auto err = write(PathIterator(*name), childInode.value); + auto err = write(PathIterator(name), childInode.value); if (err) { oxLogError(err); // could not index the directory, delete it @@ -184,46 +178,34 @@ Error Directory::mkdir(PathIterator path, bool parents, Fi return err; } } - Directory child(m_fs, childInode.value); if (path.hasNext()) { - oxReturnError(child.mkdir(path.next(), parents, nameBuff)); + oxReturnError(child.mkdir(path.next(), parents)); } } - return OxError(0); + return {}; } template -Error Directory::write(PathIterator path, uint64_t inode64, FileName *nameBuff) noexcept { +Error Directory::write(PathIterator path, uint64_t inode64) noexcept { const auto inode = static_cast(inode64); - // reuse nameBuff if it has already been allocated, as it is a rather large variable - if (nameBuff == nullptr) { - nameBuff = new (ox_alloca(sizeof(FileName))) FileName; - } - auto name = nameBuff; - + ox::StringView name; + oxReturnError(path.next(name)); if (path.next().hasNext()) { // not yet at target directory, recurse to next one - oxReturnError(path.get(*name)); oxTracef("ox.fs.Directory.write", "Attempting to write to next sub-Directory: {} of {}", - *name, path.fullPath()); - oxRequire(nextChild, findEntry(*name)); - oxTracef("ox.fs.Directory.write", "{}: {}", *name, nextChild); + name, path.fullPath()); + oxRequire(nextChild, findEntry(name)); + oxTracef("ox.fs.Directory.write", "{}: {}", name, nextChild); if (nextChild) { - // reuse name because it is a rather large variable and will not be used again - // be attentive that this remains true - name = nullptr; - return Directory(m_fs, nextChild).write(path.next(), inode, nameBuff); + return Directory(m_fs, nextChild).write(path.next(), inode); } else { - oxTracef("ox.fs.Directory.write", "{} not found and not allowed to create it.", *name); + oxTracef("ox.fs.Directory.write", "{} not found and not allowed to create it.", name); return OxError(1, "File not found and not allowed to create it."); } } else { oxTrace("ox.fs.Directory.write", path.fullPath()); // insert the new entry on this directory - // get the name - oxReturnError(path.next(*name)); - // find existing version of directory oxTracef("ox.fs.Directory.write", "Searching for directory inode {}", m_inodeId); oxRequire(oldStat, m_fs.stat(m_inodeId)); @@ -233,8 +215,7 @@ Error Directory::write(PathIterator path, uint64_t inode64 oxTrace("ox.fs.Directory.write.fail", "Could not read existing version of Directory"); return OxError(1, "Could not read existing version of Directory"); } - - const auto pathSize = name->len() + 1; + const auto pathSize = name.len() + 1; const auto entryDataSize = DirectoryEntry::DirectoryEntryData::spaceNeeded(pathSize); const auto newSize = oldStat.size + Buffer::spaceNeeded(entryDataSize); auto cpy = ox_malloca(newSize, Buffer, *old, oldStat.size); @@ -242,29 +223,22 @@ Error Directory::write(PathIterator path, uint64_t inode64 oxTrace("ox.fs.Directory.write.fail", "Could not allocate memory for copy of Directory"); return OxError(1, "Could not allocate memory for copy of Directory"); } - oxReturnError(cpy->setSize(newSize)); auto val = cpy->malloc(entryDataSize).value; if (!val.valid()) { oxTrace("ox.fs.Directory.write.fail", "Could not allocate memory for new directory entry"); return OxError(1, "Could not allocate memory for new directory entry"); } - - oxTracef("ox.fs.Directory.write", "Attempting to write Directory entry: {}", name->data()); - oxReturnError(val->init(inode, name->data(), val.size())); + oxTracef("ox.fs.Directory.write", "Attempting to write Directory entry: {}", name); + oxReturnError(val->init(inode, name, val.size())); return m_fs.write(m_inodeId, cpy.get(), cpy->size(), static_cast(FileType::Directory)); } } template -Error Directory::remove(PathIterator path, FileName *nameBuff) noexcept { - // reuse nameBuff if it has already been allocated, as it is a rather large variable - if (nameBuff == nullptr) { - nameBuff = new (ox_alloca(sizeof(FileName))) FileName; - } - auto &name = *nameBuff; +Error Directory::remove(PathIterator path) noexcept { + ox::StringView name; oxReturnError(path.get(name)); - oxTrace("ox.fs.Directory.remove", name); auto buff = m_fs.read(m_inodeId).template to(); if (buff.valid()) { @@ -283,7 +257,7 @@ Error Directory::remove(PathIterator path, FileName *nameB oxTrace("ox.fs.Directory.remove.fail", "Could not find directory buffer"); return OxError(1, "Could not find directory buffer"); } - return OxError(0); + return {}; } template @@ -295,7 +269,6 @@ Error Directory::ls(F cb) noexcept { oxTrace("ox.fs.Directory.ls.fail", "Could not directory buffer"); return OxError(1, "Could not directory buffer"); } - oxTrace("ox.fs.Directory.ls", "Found directory buffer."); for (auto i = buff->iterator(); i.valid(); i.next()) { auto data = i->data(); @@ -305,12 +278,11 @@ Error Directory::ls(F cb) noexcept { oxTrace("ox.fs.Directory.ls", "INVALID DIRECTORY ENTRY"); } } - - return OxError(0); + return {}; } template -Result Directory::findEntry(const FileName &name) const noexcept { +Result Directory::findEntry(CRStringView name) const noexcept { oxTrace("ox.fs.Directory.findEntry", name); auto buff = m_fs.read(m_inodeId).template to(); if (!buff.valid()) { @@ -327,7 +299,7 @@ Result Directory::findEntry return static_cast(data->inode); } } else { - oxTrace("ox.fs.Directory.findEntry") << "INVALID DIRECTORY ENTRY"; + oxTrace("ox.fs.Directory.findEntry", "INVALID DIRECTORY ENTRY"); } } oxTrace("ox.fs.Directory.findEntry.fail", "Entry not present"); @@ -335,22 +307,15 @@ Result Directory::findEntry } template -Result Directory::find(PathIterator path, FileName *nameBuff) const noexcept { - // reuse nameBuff if it has already been allocated, as it is a rather large variable - if (nameBuff == nullptr) { - nameBuff = new (ox_alloca(sizeof(FileName))) FileName; - } - +Result Directory::find(PathIterator path) const noexcept { // determine if already exists - auto name = nameBuff; - oxReturnError(path.get(*name)); - - oxRequire(v, findEntry(*name)); + ox::StringView name; + oxReturnError(path.get(name)); + oxRequire(v, findEntry(name)); // recurse if not at end of path if (auto p = path.next(); p.valid()) { Directory dir(m_fs, v); - name = nullptr; - return dir.find(p, nameBuff); + return dir.find(p); } return v; } diff --git a/deps/ox/src/ox/fs/filesystem/pathiterator.cpp b/deps/ox/src/ox/fs/filesystem/pathiterator.cpp index 716d481e..581b2901 100644 --- a/deps/ox/src/ox/fs/filesystem/pathiterator.cpp +++ b/deps/ox/src/ox/fs/filesystem/pathiterator.cpp @@ -40,30 +40,9 @@ Error PathIterator::dirPath(char *out, std::size_t outSize) { } } -/** - * @return 0 if no error - */ -Error PathIterator::fileName(char *out, std::size_t outSize) { - auto idx = ox::lastIndexOf(m_path, '/', m_maxSize); - if (idx >= 0) { - idx++; // pass up the preceding / - std::size_t fileNameSize = static_cast(ox::strlen(&m_path[idx])); - if (fileNameSize < outSize) { - ox::memcpy(out, &m_path[idx], fileNameSize); - out[fileNameSize] = 0; - return OxError(0); - } else { - return OxError(1); - } - } else { - return OxError(2); - } -} - // Gets the get item in the path -Error PathIterator::get(IString &fileName) { +Error PathIterator::get(StringView &fileName) { std::size_t size = 0; - std::ignore = fileName.resize(MaxFileNameLength); if (m_iterator >= m_maxSize) { oxTracef("ox.fs.PathIterator.get", "m_iterator ({}) >= m_maxSize ({})", m_iterator, m_maxSize); return OxError(1); @@ -88,22 +67,21 @@ Error PathIterator::get(IString &fileName) { if (size >= MaxFileNameLength || size == 0) { return OxError(1); } - ox::memcpy(fileName.data(), &m_path[start], size); + fileName = ox::substr(m_path, start, start + size); // truncate trailing / if (size && fileName[size - 1] == '/') { - size--; + fileName = ox::substr(m_path, start, start + size - 1); } - oxReturnError(fileName.resize(size)); + oxAssert(fileName[fileName.len()-1] != '/', "name ends in /"); return {}; } /** * @return 0 if no error */ -Error PathIterator::next(IString &fileName) { +Error PathIterator::next(StringView &fileName) { std::size_t size = 0; auto retval = OxError(1); - std::ignore = fileName.resize(MaxFileNameLength); if (m_iterator < m_maxSize && ox::strlen(&m_path[m_iterator])) { retval = OxError(0); if (m_path[m_iterator] == '/') { @@ -122,15 +100,14 @@ Error PathIterator::next(IString &fileName) { if (size >= MaxFileNameLength) { return OxError(1); } - ox::memcpy(fileName.data(), &m_path[start], size); + fileName = ox::substr(m_path, start, start + size); + // truncate trailing / + while (fileName.len() && fileName[fileName.len() - 1] == '/') { + fileName = ox::substr(m_path, start, start + size); + } + m_iterator += size; + oxAssert(fileName.len() == 0 || fileName[fileName.len()-1] != '/', "name ends in /"); } - // truncate trailing / - if (size && fileName[size - 1] == '/') { - size--; - } - fileName[size] = 0; // end with null terminator - oxReturnError(fileName.resize(size)); - m_iterator += size; return retval; } diff --git a/deps/ox/src/ox/fs/filesystem/pathiterator.hpp b/deps/ox/src/ox/fs/filesystem/pathiterator.hpp index b3cbeda2..2c7c88ad 100644 --- a/deps/ox/src/ox/fs/filesystem/pathiterator.hpp +++ b/deps/ox/src/ox/fs/filesystem/pathiterator.hpp @@ -13,7 +13,6 @@ namespace ox { constexpr std::size_t MaxFileNameLength = 255; -using FileName = IString; class PathIterator { private: @@ -28,29 +27,14 @@ class PathIterator { PathIterator(CRStringView path); - /** - * @return 0 if no error - */ Error dirPath(char *pathOut, std::size_t pathOutSize); - /** - * @return 0 if no error - */ Error fileName(char *out, std::size_t outSize); - /** - * @return 0 if no error - */ - Error next(FileName &fileName); + Error next(StringView &fileName); - /** - * @return 0 if no error - */ - Error get(FileName &fileName); + Error get(StringView &fileName); - /** - * @return 0 if no error - */ Result nextSize() const; [[nodiscard]] diff --git a/deps/ox/src/ox/fs/test/CMakeLists.txt b/deps/ox/src/ox/fs/test/CMakeLists.txt index d2ecc00f..44eaf770 100644 --- a/deps/ox/src/ox/fs/test/CMakeLists.txt +++ b/deps/ox/src/ox/fs/test/CMakeLists.txt @@ -19,7 +19,6 @@ add_test("[ox/fs] PathIterator::next5" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests add_test("[ox/fs] PathIterator::hasNext" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests PathIterator::hasNext) add_test("[ox/fs] PathIterator::dirPath" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests PathIterator::dirPath) -add_test("[ox/fs] PathIterator::fileName" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests PathIterator::fileName) add_test("[ox/fs] NodeBuffer::insert" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests "NodeBuffer::insert") add_test("[ox/fs] FileStore::readWrite" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests "FileStore::readWrite") diff --git a/deps/ox/src/ox/fs/test/tests.cpp b/deps/ox/src/ox/fs/test/tests.cpp index 25e5cb2a..68199eae 100644 --- a/deps/ox/src/ox/fs/test/tests.cpp +++ b/deps/ox/src/ox/fs/test/tests.cpp @@ -58,9 +58,9 @@ const std::map> tests = { "PathIterator::next1", [](ox::StringView) { - auto const path = ox::String("/usr/share/charset.gbag"); + auto constexpr path = ox::StringLiteral("/usr/share/charset.gbag"); ox::PathIterator it(path.c_str(), path.len()); - ox::FileName buff; + ox::StringView buff; oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next"); oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next"); oxAssert(it.next(buff) == 0 && buff == "charset.gbag", "PathIterator shows wrong next"); @@ -70,11 +70,13 @@ const std::map> tests = { "PathIterator::next2", [](ox::StringView) { - auto const path = ox::String("/usr/share/"); - ox::PathIterator it(path.c_str(), path.len()); - ox::FileName buff; - oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "usr") == 0, "PathIterator shows wrong next"); - oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "share") == 0, "PathIterator shows wrong next"); + auto constexpr path = ox::StringView("/usr/share/"); + ox::PathIterator it(path); + ox::StringView buff; + oxAssert(it.next(buff), "PathIterator::next returned error"); + oxExpect(buff, "usr"); + oxAssert(it.next(buff), "PathIterator::next returned error"); + oxExpect(buff, "share"); return OxError(0); } }, @@ -83,20 +85,20 @@ const std::map> tests = [](ox::StringView) { auto const path = ox::String("/"); ox::PathIterator it(path.c_str(), path.len()); - ox::FileName buff; - oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "\0") == 0, "PathIterator shows wrong next"); + ox::StringView buff; + oxAssert(it.next(buff) == 0 && buff == "\0", "PathIterator shows wrong next"); return OxError(0); } }, { "PathIterator::next4", [](ox::StringView) { - auto const path = ox::String("usr/share/charset.gbag"); - ox::PathIterator it(path.c_str(), path.len()); - ox::FileName buff; - oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "usr") == 0, "PathIterator shows wrong next"); - oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "share") == 0, "PathIterator shows wrong next"); - oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "charset.gbag") == 0, "PathIterator shows wrong next"); + auto constexpr path = ox::StringLiteral("usr/share/charset.gbag"); + ox::PathIterator it(path); + ox::StringView buff; + oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next"); + oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next"); + oxAssert(it.next(buff) == 0 && buff == "charset.gbag", "PathIterator shows wrong next"); return OxError(0); } }, @@ -105,32 +107,22 @@ const std::map> tests = [](ox::StringView) { auto const path = ox::String("usr/share/"); ox::PathIterator it(path.c_str(), path.len()); - ox::FileName buff; - oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "usr") == 0, "PathIterator shows wrong next"); - oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "share") == 0, "PathIterator shows wrong next"); + ox::StringView buff; + oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next"); + oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next"); return OxError(0); } }, { "PathIterator::dirPath", [] (ox::StringView) { - auto const path = ox::String("/usr/share/charset.gbag"); + auto constexpr path = ox::StringLiteral("/usr/share/charset.gbag"); ox::PathIterator it(path.c_str(), path.len()); auto buff = static_cast(ox_alloca(path.len() + 1)); oxAssert(it.dirPath(buff, path.len()) == 0 && ox::strcmp(buff, "/usr/share/") == 0, "PathIterator shows incorrect dir path"); return OxError(0); } }, - { - "PathIterator::fileName", - [](ox::StringView) { - auto const path = ox::String("/usr/share/charset.gbag"); - ox::PathIterator it(path.c_str(), path.len()); - auto buff = static_cast(ox_alloca(path.len() + 1)); - oxAssert(it.fileName(buff, path.len()) == 0 && ox::strcmp(buff, "charset.gbag") == 0, "PathIterator shows incorrect file name"); - return OxError(0); - } - }, { "PathIterator::hasNext", [](ox::StringView) { @@ -221,7 +213,6 @@ const std::map> tests = oxTrace("ox.fs.test.FileSystem") << "format"; oxAssert(ox::FileSystem32::format(fsBuff.data(), fsBuff.size()), "FileSystem format failed"); ox::FileSystem32 fs(ox::FileStore32(fsBuff.data(), fsBuff.size())); - oxTrace("ox.fs.test.FileSystem") << "mkdir"; oxAssert(fs.mkdir("/dir", true), "mkdir failed"); oxAssert(fs.stat("/dir").error, "mkdir failed"); @@ -229,7 +220,6 @@ const std::map> tests = oxAssert(fs.stat("/l1d1/l2d1/l3d1").error, "mkdir failed"); oxAssert(fs.mkdir("/l1d1/l2d2", true), "mkdir failed"); oxAssert(fs.stat("/l1d1/l2d2").error, "mkdir failed"); - return OxError(0); } },