[ox/fs] Add new Directory type

This commit is contained in:
2018-04-23 22:51:49 -05:00
parent aeee05be89
commit 59cc34b4e8
15 changed files with 306 additions and 26 deletions

View File

@@ -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

View File

@@ -32,7 +32,7 @@ struct __attribute__((packed)) FileStoreItem: public ptrarith::Item<size_t> {
return sizeof(*this) + this->size();
}
ox::ptrarith::Ptr<uint8_t, size_t> data() {
ptrarith::Ptr<uint8_t, size_t> data() {
return ptrarith::Ptr<uint8_t, size_t>(this, this->size(), sizeof(*this), this->size() - sizeof(*this));
}
};
@@ -42,8 +42,8 @@ template<typename size_t>
class FileStoreTemplate: public FileStore {
private:
using ItemPtr = typename ox::ptrarith::NodeBuffer<size_t, FileStoreItem<size_t>>::ItemPtr;
using Buffer = ox::ptrarith::NodeBuffer<size_t, FileStoreItem<size_t>>;
using ItemPtr = typename ptrarith::NodeBuffer<size_t, FileStoreItem<size_t>>::ItemPtr;
using Buffer = ptrarith::NodeBuffer<size_t, FileStoreItem<size_t>>;
struct __attribute__((packed)) FileStoreData {
ox::LittleEndian<size_t> rootNode = 0;
@@ -128,7 +128,7 @@ class FileStoreTemplate: public FileStore {
template<typename size_t>
FileStoreTemplate<size_t>::FileStoreTemplate(void *buff, size_t buffSize) {
m_buffSize = buffSize;
m_buffer = reinterpret_cast<ox::ptrarith::NodeBuffer<size_t, FileStoreItem<size_t>>*>(buff);
m_buffer = reinterpret_cast<ptrarith::NodeBuffer<size_t, FileStoreItem<size_t>>*>(buff);
if (!m_buffer->valid(buffSize)) {
m_buffSize = 0;
m_buffer = nullptr;

View File

@@ -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<std::size_t> 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);
}
}

View File

@@ -8,6 +8,7 @@
#pragma once
#include <ox/std/strops.hpp>
#include <ox/std/types.hpp>
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<std::size_t> nextSize() const;
bool hasNext() const;
PathIterator operator+(int i);
PathIterator operator-(int i);
};
}

View File

@@ -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<uint16_t>;
template class Directory<uint32_t>;
template struct DirectoryEntry<uint16_t>;
template struct DirectoryEntry<uint32_t>;
}

View File

@@ -6,20 +6,126 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <ox/fs/filesystem/pathiterator.hpp>
#include <ox/fs/filestore.hpp>
#include <ox/ptrarith/nodebuffer.hpp>
#include <ox/std/std.hpp>
namespace ox::fs {
struct DirectoryData {
template<typename InodeId_t>
struct __attribute__((packed)) DirectoryEntry {
// NodeBuffer fields
ox::LittleEndian<std::size_t> prev = 0;
ox::LittleEndian<std::size_t> next = 0;
// DirectoryEntry fields
ox::LittleEndian<InodeId_t> 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<uint8_t, InodeId_t> data() {
return ptrarith::Ptr<uint8_t, InodeId_t>(this, this->size(), sizeof(*this), this->size() - sizeof(*this));
}
};
template<typename InodeId_t>
class Directory {
Error add(const PathIterator &it, uint64_t inode);
private:
using Buffer = ptrarith::NodeBuffer<InodeId_t, DirectoryEntry<InodeId_t>>;
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<InodeId_t> find(PathIterator it) const noexcept;
};
template<typename InodeId_t>
Directory<InodeId_t>::Directory(uint8_t *buff, std::size_t size) {
m_size = size;
m_buff = reinterpret_cast<decltype(m_buff)>(buff);
}
template<typename InodeId_t>
Error Directory<InodeId_t>::init() noexcept {
if (m_size >= sizeof(Buffer)) {
new (m_buff) Buffer(m_size);
return 0;
}
return 1;
}
template<typename InodeId_t>
Error Directory<InodeId_t>::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<typename InodeId_t>
Error Directory<InodeId_t>::rm(PathIterator) noexcept {
return 1;
}
template<typename InodeId_t>
ValErr<InodeId_t> Directory<InodeId_t>::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<InodeId_t>(i->inode);
}
}
return {0, 1};
}
extern template class Directory<uint16_t>;
extern template class Directory<uint32_t>;
extern template struct DirectoryEntry<uint16_t>;
extern template struct DirectoryEntry<uint32_t>;
using Directory16 = Directory<uint16_t>;
using Directory32 = Directory<uint32_t>;
}

View File

@@ -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")

View File

@@ -11,6 +11,7 @@
#include <iostream>
#include <assert.h>
#include <array>
#include <map>
#include <vector>
#include <string>
@@ -382,6 +383,19 @@ map<string, int(*)(string)> tests = {
return 0;
}
},
{
"Directory",
[](string) {
std::array<uint8_t, 1000> 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;
}
},
},
};