[ox] Add file:line error tracing

This commit is contained in:
Gary Talent 2018-05-31 22:45:57 -05:00
parent 956415a6a2
commit ea7cf59ec7
17 changed files with 438 additions and 215 deletions

View File

@ -87,7 +87,7 @@ class FileStoreTemplate: public FileStore {
* @return 0 if read is a success
*/
template<typename T>
int read(InodeId_t id, FsSize_t readStart,
Error read(InodeId_t id, FsSize_t readStart,
FsSize_t readSize, T *data,
FsSize_t *size);
@ -104,12 +104,24 @@ class FileStoreTemplate: public FileStore {
FileStoreData *fileStoreData();
/**
* Places the given Item at the given ID. If it already exists, the
* existing value will be overwritten.
*/
Error placeItem(ItemPtr item);
/**
* Places the given Item at the given ID. If it already exists, the
* existing value will be overwritten.
*/
Error placeItem(ItemPtr root, ItemPtr item, int depth = 0);
/**
* Removes the given Item at the given ID. If it already exists, the
* existing value will be overwritten.
*/
Error unplaceItem(ItemPtr root, ItemPtr item, int depth = 0);
/**
* Finds the parent an inode by its ID.
*/
@ -152,12 +164,12 @@ Error FileStoreTemplate<size_t>::format() {
auto data = m_buffer->template dataOf<FileStoreData>(fsData);
if (data.valid()) {
new (data) FileStoreData;
return 0;
return OxError(0);
} else {
oxTrace("ox::fs::FileStoreTemplate::format::fail") << "Could not read data section of FileStoreData";
}
}
return 1;
return OxError(1);
}
template<typename size_t>
@ -165,7 +177,7 @@ Error FileStoreTemplate<size_t>::setSize(InodeId_t size) {
if (m_buffSize >= size) {
return m_buffer->setSize(size);
}
return 1;
return OxError(1);
}
template<typename size_t>
@ -173,9 +185,9 @@ Error FileStoreTemplate<size_t>::incLinks(InodeId_t id) {
auto item = find(id);
if (item.valid()) {
item->links++;
return 0;
return OxError(0);
}
return 1;
return OxError(1);
}
template<typename size_t>
@ -183,9 +195,9 @@ Error FileStoreTemplate<size_t>::decLinks(InodeId_t id) {
auto item = find(id);
if (item.valid()) {
item->links--;
return 0;
return OxError(0);
}
return 1;
return OxError(1);
}
template<typename size_t>
@ -222,12 +234,12 @@ Error FileStoreTemplate<size_t>::write(InodeId_t id, void *data, FsSize_t dataSi
auto root = m_buffer->ptr(fsData->rootNode);
if (root.valid()) {
oxTrace("ox::fs::FileStoreTemplate::write") << "Placing" << dest->id << "on" << root->id << "at" << destData.offset();
return placeItem(root, dest);
return placeItem(dest);
} else {
oxTrace("ox::fs::FileStoreTemplate::write") << "Initializing root inode with offset of" << dest.offset()
<< "and data size of" << destData.size();
oxTrace("ox::fs::FileStoreTemplate::write") << "Initializing root inode ( offset:" << dest.offset()
<< ", data size:" << destData.size() << ")";
fsData->rootNode = dest.offset();
return 0;
return OxError(0);
}
} else {
oxTrace("ox::fs::FileStoreTemplate::write::fail") << "Could not place item due to absence of FileStore header.";
@ -236,7 +248,7 @@ Error FileStoreTemplate<size_t>::write(InodeId_t id, void *data, FsSize_t dataSi
}
m_buffer->free(dest);
}
return 1;
return OxError(1);
}
template<typename size_t>
@ -254,7 +266,7 @@ Error FileStoreTemplate<size_t>::read(InodeId_t id, void *data, FsSize_t dataSiz
if (size) {
*size = src.size();
}
return 0;
return OxError(0);
} else {
oxTrace("ox::fs::FileStoreTemplate::read::fail") << "Could not read data section of item:" << id;
oxTrace("ox::fs::FileStoreTemplate::read::fail") << "Item data section size:" << srcData.size();
@ -262,7 +274,7 @@ Error FileStoreTemplate<size_t>::read(InodeId_t id, void *data, FsSize_t dataSiz
} else {
oxTrace("ox::fs::FileStoreTemplate::read::fail") << "Could not find requested item:" << id;
}
return 1;
return OxError(1);
}
template<typename size_t>
@ -277,7 +289,7 @@ Error FileStoreTemplate<size_t>::read(InodeId_t id, FsSize_t readStart, FsSize_t
if (size) {
*size = sub.size();
}
return 0;
return OxError(0);
} else {
oxTrace("ox::fs::FileStoreTemplate::read::fail") << "Could not read requested data sub-section of item:" << id;
}
@ -287,12 +299,12 @@ Error FileStoreTemplate<size_t>::read(InodeId_t id, FsSize_t readStart, FsSize_t
} else {
oxTrace("ox::fs::FileStoreTemplate::read::fail") << "Could not find requested item:" << id;
}
return 1;
return OxError(1);
}
template<typename size_t>
template<typename T>
int FileStoreTemplate<size_t>::read(InodeId_t id, FsSize_t readStart,
Error FileStoreTemplate<size_t>::read(InodeId_t id, FsSize_t readStart,
FsSize_t readSize, T *data, FsSize_t *size) {
auto src = find(id);
if (src.valid()) {
@ -312,11 +324,11 @@ int FileStoreTemplate<size_t>::read(InodeId_t id, FsSize_t readStart,
if (size) {
*size = sub.size();
}
return 0;
return OxError(0);
}
}
}
return 1;
return OxError(1);
}
template<typename size_t>
@ -374,30 +386,93 @@ typename FileStoreTemplate<size_t>::FileStoreData *FileStoreTemplate<size_t>::fi
return nullptr;
}
template<typename size_t>
Error FileStoreTemplate<size_t>::placeItem(ItemPtr item) {
auto fsData = fileStoreData();
if (fsData) {
auto root = m_buffer->ptr(fsData->rootNode);
if (root.valid()) {
if (root->id == item->id) {
fsData->rootNode = item;
item->left = root->left;
item->right = root->right;
oxTrace("ox::fs::FileStoreTemplate::placeItem") << "Overwrote Root Item:" << item->id;
return 0;
} else {
return placeItem(root, item);
}
}
}
return OxError(1);
}
template<typename size_t>
Error FileStoreTemplate<size_t>::placeItem(ItemPtr root, ItemPtr item, int depth) {
if (depth < 5000) {
if (item->id > root->id) {
auto right = m_buffer->ptr(root->right);
if (!right.valid() || right->id == item->id) {
root->right = root.offset();
return 0;
root->right = item.offset();
if (right.valid()) {
item->left = right->left;
item->right = right->right;
}
oxTrace("ox::fs::FileStoreTemplate::placeItem") << "Placed Item:" << item->id;
return OxError(0);
} else {
return placeItem(right, item, depth + 1);
}
} else if (item->id < root->id) {
auto left = m_buffer->ptr(root->left);
if (!left.valid() || left->id == item->id) {
root->left = root.offset();
return 0;
root->left = item.offset();
if (left.valid()) {
item->left = left->left;
item->right = left->right;
}
oxTrace("ox::fs::FileStoreTemplate::placeItem") << "Placed Item:" << item->id;
return OxError(0);
} else {
return placeItem(left, item, depth + 1);
}
} else {
oxTrace("ox::fs::FileStoreTemplate::placeItem::fail") << "Cannot insert an item on itself.";
return OxError(1);
}
} else {
oxTrace("ox::fs::FileStoreTemplate::placeItem::fail") << "Excessive recursion depth, stopping before stack overflow.";
return OxError(2);
}
return 1;
}
template<typename size_t>
Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr root, ItemPtr item, int depth) {
if (depth < 5000) {
if (item->id > root->id) {
auto right = m_buffer->ptr(root->right);
if (!right.valid() || right->id == item->id) {
root->right = item.offset();
oxTrace("ox::fs::FileStoreTemplate::unplaceItem") << "Placed Item:" << item->id;
return OxError(0);
} else {
return unplaceItem(right, item, depth + 1);
}
} else if (item->id < root->id) {
auto left = m_buffer->ptr(root->left);
if (!left.valid() || left->id == item->id) {
root->left = item.offset();
oxTrace("ox::fs::FileStoreTemplate::unplaceItem") << "Placed Item:" << item->id;
return OxError(0);
} else {
return unplaceItem(left, item, depth + 1);
}
} else {
oxTrace("ox::fs::FileStoreTemplate::unplaceItem::fail") << "Item already exists.";
}
} else {
oxTrace("ox::fs::FileStoreTemplate::unplaceItem::fail") << "Excessive recursion depth, stopping before stack overflow.";
}
return OxError(1);
}
template<typename size_t>

View File

@ -24,22 +24,22 @@ PathIterator::PathIterator(const char *path): PathIterator(path, ox_strlen(path)
/**
* @return 0 if no error
*/
int PathIterator::dirPath(char *out, std::size_t outSize) {
Error PathIterator::dirPath(char *out, std::size_t outSize) {
int idx = ox_lastIndexOf(m_path, '/', m_maxSize);
std::size_t size = idx + 1;
if (idx >= 0 && size < outSize) {
ox_memcpy(out, m_path, size);
out[size] = 0;
return 0;
return OxError(0);
} else {
return 1;
return OxError(1);
}
}
/**
* @return 0 if no error
*/
int PathIterator::fileName(char *out, std::size_t outSize) {
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 /
@ -47,19 +47,51 @@ int PathIterator::fileName(char *out, std::size_t outSize) {
if (fileNameSize < outSize) {
ox_memcpy(out, &m_path[idx], fileNameSize);
out[fileNameSize] = 0;
return 0;
return OxError(0);
} else {
return 1;
return OxError(1);
}
} else {
return 2;
return OxError(2);
}
}
// Gets the next item in the path
int PathIterator::next(char *pathOut, std::size_t pathOutSize) {
// Gets the get item in the path
Error PathIterator::get(char *pathOut, std::size_t pathOutSize) {
std::size_t size = 0;
int retval = 1;
Error retval = 1;
if (m_iterator < m_maxSize && ox_strlen(&m_path[m_iterator])) {
retval = 0;
auto start = m_iterator;
if (m_path[start] == '/') {
start++;
}
// 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;
// cannot fit the output in the output parameter
if (size >= pathOutSize) {
return OxError(1);
}
ox_memcpy(pathOut, &m_path[start], size);
}
// truncate trailing /
if (size && pathOut[size - 1] == '/') {
size--;
}
pathOut[size] = 0; // end with null terminator
return OxError(retval);
}
// Gets the get item in the path
Error PathIterator::next(char *pathOut, std::size_t pathOutSize) {
std::size_t size = 0;
Error retval = 1;
if (m_iterator < m_maxSize && ox_strlen(&m_path[m_iterator])) {
retval = 0;
if (m_path[m_iterator] == '/') {
@ -76,7 +108,7 @@ int PathIterator::next(char *pathOut, std::size_t pathOutSize) {
size = end - start;
// cannot fit the output in the output parameter
if (size >= pathOutSize) {
return -1;
return OxError(1);
}
ox_memcpy(pathOut, &m_path[start], size);
}
@ -86,13 +118,20 @@ int PathIterator::next(char *pathOut, std::size_t pathOutSize) {
}
pathOut[size] = 0; // end with null terminator
m_iterator += size;
return retval;
return OxError(retval);
}
/**
* @return 0 if no error
*/
int PathIterator::next(BString<MaxFileNameLength> *fileName) {
Error PathIterator::get(BString<MaxFileNameLength> *fileName) {
return get(fileName->data(), fileName->cap());
}
/**
* @return 0 if no error
*/
Error PathIterator::next(BString<MaxFileNameLength> *fileName) {
return next(fileName->data(), fileName->cap());
}
@ -116,7 +155,7 @@ ValErr<std::size_t> PathIterator::nextSize() const {
size = end - start;
}
it += size;
return {size, retval};
return {size, OxError(retval)};
}
bool PathIterator::hasNext() const {
@ -138,12 +177,31 @@ bool PathIterator::hasNext() const {
return size > 0;
}
PathIterator PathIterator::operator+(int i) {
return PathIterator(m_path, m_maxSize, m_iterator + i);
bool PathIterator::valid() const {
return m_path[m_iterator] != 0;
}
PathIterator PathIterator::operator-(int i) {
return PathIterator(m_path, m_maxSize, m_iterator - i);
PathIterator PathIterator::operator+(int i) const {
std::size_t size = 0;
Error retval = 1;
auto iterator = m_iterator;
if (iterator < m_maxSize && ox_strlen(&m_path[iterator])) {
retval = 0;
if (m_path[iterator] == '/') {
iterator++;
}
std::size_t start = iterator;
// 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;
}
iterator += size;
return PathIterator(m_path, m_maxSize, iterator + i);
}
}

View File

@ -28,22 +28,32 @@ class PathIterator {
/**
* @return 0 if no error
*/
int dirPath(char *pathOut, std::size_t pathOutSize);
Error dirPath(char *pathOut, std::size_t pathOutSize);
/**
* @return 0 if no error
*/
int fileName(char *out, std::size_t outSize);
Error fileName(char *out, std::size_t outSize);
/**
* @return 0 if no error
*/
int next(char *pathOut, std::size_t pathOutSize);
Error next(char *pathOut, std::size_t pathOutSize);
/**
* @return 0 if no error
*/
int next(BString<MaxFileNameLength> *fileName);
Error get(char *pathOut, std::size_t pathOutSize);
/**
* @return 0 if no error
*/
Error next(BString<MaxFileNameLength> *fileName);
/**
* @return 0 if no error
*/
Error get(BString<MaxFileNameLength> *fileName);
/**
* @return 0 if no error
@ -52,9 +62,9 @@ class PathIterator {
bool hasNext() const;
PathIterator operator+(int i);
bool valid() const;
PathIterator operator-(int i);
PathIterator operator+(int i) const;
};

View File

@ -18,52 +18,55 @@ namespace ox::fs {
template<typename InodeId_t>
struct __attribute__((packed)) DirectoryEntry {
struct __attribute__((packed)) DirectoryEntryData {
// DirectoryEntry fields
LittleEndian<InodeId_t> inode = 0;
char name[MaxFileNameLength];
};
public:
struct __attribute__((packed)) DirectoryEntryData {
// DirectoryEntry fields
LittleEndian<InodeId_t> inode = 0;
char name[MaxFileNameLength];
};
// NodeBuffer fields
LittleEndian<InodeId_t> prev = 0;
LittleEndian<InodeId_t> next = 0;
// NodeBuffer fields
LittleEndian<InodeId_t> prev = 0;
LittleEndian<InodeId_t> next = 0;
DirectoryEntry() = default;
DirectoryEntry(InodeId_t inode, const char *name) {
auto d = data();
if (d.valid()) {
d->inode = inode;
ox_strncpy(d->name, name, MaxFileNameLength);
private:
LittleEndian<InodeId_t> m_bufferSize = sizeof(DirectoryEntry);
public:
DirectoryEntry() = default;
DirectoryEntry(InodeId_t inode, const char *name, InodeId_t bufferSize) {
auto d = data();
if (d.valid()) {
d->inode = inode;
ox_strncpy(d->name, name, MaxFileNameLength);
m_bufferSize = bufferSize;
}
}
}
ptrarith::Ptr<DirectoryEntryData, InodeId_t> data() {
return ptrarith::Ptr<DirectoryEntryData, InodeId_t>(this, this->fullSize(), sizeof(*this), this->size());
}
/**
* @return the size of the data + the size of the Item type
*/
InodeId_t fullSize() const {
const auto d = const_cast<DirectoryEntry*>(this)->data();
if (d.valid()) {
return sizeof(*this) + offsetof(DirectoryEntryData, name) + ox_strnlen(d->name, MaxFileNameLength);
ptrarith::Ptr<DirectoryEntryData, InodeId_t> data() {
return ptrarith::Ptr<DirectoryEntryData, InodeId_t>(this, this->fullSize(), sizeof(*this), this->size());
}
return 0;
}
InodeId_t size() const {
return fullSize() - offsetof(DirectoryEntryData, inode);
}
/**
* @return the size of the data + the size of the Item type
*/
InodeId_t fullSize() const {
return m_bufferSize;
}
void setSize(InodeId_t) {
// ignore set value
}
InodeId_t size() const {
return fullSize() - offsetof(DirectoryEntryData, inode);
}
static std::size_t spaceNeeded(std::size_t chars) {
return sizeof(DirectoryEntry) + chars;
}
void setSize(InodeId_t) {
// ignore set value
}
static std::size_t spaceNeeded(std::size_t chars) {
return sizeof(DirectoryEntry) + offsetof(DirectoryEntryData, name) + chars;
}
};
@ -76,7 +79,6 @@ class Directory {
InodeId_t m_inodeId = 0;
std::size_t m_size = 0;
Buffer *m_buff = nullptr;
FileStore *m_fs = nullptr;
public:
@ -91,18 +93,17 @@ class Directory {
Error rm(PathIterator it) noexcept;
ValErr<InodeId_t> find(const char *name) const noexcept;
ValErr<InodeId_t> find(const BString<MaxFileNameLength> &name) const noexcept;
};
template<typename InodeId_t>
Directory<InodeId_t>::Directory(FileStore *fs, InodeId_t id) {
Directory<InodeId_t>::Directory(FileStore *fs, InodeId_t inodeId) {
m_fs = fs;
m_inodeId = id;
auto buff = fs->read(id).template to<Buffer>();
m_inodeId = inodeId;
auto buff = fs->read(inodeId).template to<Buffer>();
if (buff.valid()) {
m_size = buff.size();
m_buff = buff;
}
}
@ -113,17 +114,37 @@ Error Directory<InodeId_t>::init() noexcept {
auto buff = m_fs->read(m_inodeId);
if (buff.valid()) {
new (buff) Buffer(Size);
return 0;
m_size = Size;
return OxError(0);
}
return 1;
m_size = 0;
return OxError(1);
}
template<typename InodeId_t>
Error Directory<InodeId_t>::write(PathIterator path, InodeId_t inode) noexcept {
// find existing entry and update if exists
InodeId_t nextChild = 0;
if ((path + 1).hasNext()) {
oxTrace("ox::fs::Directory::write") << "Attempting to write to next sub-Directory";
if (!path.hasNext()) {
Error err = 1;
// read the name and pop it off the stack as soon as possible to help
// avoid a stack overflow in the recursive calls
{
BString<MaxFileNameLength> name;
path.get(&name);
nextChild = find(name);
}
// It's important for the recursive call to be outside the block where name
// lived. This avoids allocation several BString<MaxFileNameLength>s on the
// stack at once, while also avoiding the use of heap memory.
if (nextChild) {
return Directory(m_fs, nextChild).write(path + 1, inode);
}
} else {
// insert the new entry on this directory
// get the name
BString<MaxFileNameLength> name;
path.next(&name);
@ -133,37 +154,50 @@ Error Directory<InodeId_t>::write(PathIterator path, InodeId_t inode) noexcept {
const auto newSize = m_size + DirectoryEntry<InodeId_t>::spaceNeeded(name.size());
auto cpy = ox_malloca(newSize, Buffer, old);
if (cpy != nullptr) {
// TODO: look for old version of this entry and delete it
cpy->setSize(newSize);
auto val = cpy->malloc(name.size());
if (val.valid()) {
new (val) DirectoryEntry<InodeId_t>(inode, name.data());
err = m_fs->write(m_inodeId, cpy, cpy->size());
oxTrace("ox::fs::Directory::write") << "Attempting to write Directory to FileStore";
new (val) DirectoryEntry<InodeId_t>(inode, name.data(), newSize);
return m_fs->write(m_inodeId, cpy, cpy->size());
} else {
oxTrace("ox::fs::Directory::write::fail") << "Could not allocate memory for new directory entry";
}
} else {
oxTrace("ox::fs::Directory::write::fail") << "Could not allocate memory for copy of Directory";
}
} else {
oxTrace("ox::fs::Directory::write::fail") << "Could not read existing version of Directory";
}
return err;
}
// TODO: get sub directory and call its write instead of recursing on this directory
return write(path + 1, inode);
return OxError(1);
}
template<typename InodeId_t>
Error Directory<InodeId_t>::rm(PathIterator) noexcept {
return 1;
return OxError(1);
}
template<typename InodeId_t>
ValErr<InodeId_t> Directory<InodeId_t>::find(const char *name) const noexcept {
ValErr<InodeId_t> retval = {0, 1};
ValErr<InodeId_t> Directory<InodeId_t>::find(const BString<MaxFileNameLength> &name) const noexcept {
oxTrace("ox::fs::Directory::find") << name.c_str();
auto buff = m_fs->read(m_inodeId).template to<Buffer>();
for (auto i = buff->iterator(); i.hasNext(); i.next()) {
auto data = i->data();
if (data.valid() && data->name == name) {
retval = static_cast<InodeId_t>(data->inode);
if (buff.valid()) {
oxTrace("ox::fs::Directory::find") << "Found directory buffer.";
for (auto i = buff->iterator(); i.valid(); i.next()) {
auto data = i->data();
oxTrace("ox::fs::Directory::find::name") << name.c_str();
if (data.valid() && data->name == name.c_str()) {
return static_cast<InodeId_t>(data->inode);
}
}
oxTrace("ox::fs::Directory::find::fail");
} else {
oxTrace("ox::fs::Directory::find::fail") << "Could not find directory buffer";
}
return retval;
return {0, OxError(1)};
}

View File

@ -60,6 +60,7 @@ add_test("Test\\ PathIterator::next2" FSTests PathIterator::next2)
add_test("Test\\ PathIterator::next3" FSTests PathIterator::next3)
add_test("Test\\ PathIterator::next4" FSTests PathIterator::next4)
add_test("Test\\ PathIterator::next5" FSTests PathIterator::next5)
add_test("Test\\ PathIterator::hasNext" FSTests PathIterator::hasNext)
add_test("Test\\ PathIterator::dirPath" FSTests PathIterator::dirPath)
add_test("Test\\ PathIterator::fileName" FSTests PathIterator::fileName)

View File

@ -32,9 +32,7 @@ map<string, int(*)(string)> tests = {
int retval = 0;
string path = "/usr/share/charset.gbag";
PathIterator it(path.c_str(), path.size());
const auto buffSize = 1024;
char buff[buffSize];
assert(buffSize >= path.size());
auto buff = static_cast<char*>(ox_alloca(path.size() + 1));
retval |= !(it.next(buff, path.size()) == 0 && ox_strcmp(buff, "usr") == 0);
retval |= !(it.next(buff, path.size()) == 0 && ox_strcmp(buff, "share") == 0);
retval |= !(it.next(buff, path.size()) == 0 && ox_strcmp(buff, "charset.gbag") == 0);
@ -47,9 +45,7 @@ map<string, int(*)(string)> tests = {
int retval = 0;
string path = "/usr/share/";
PathIterator it(path.c_str(), path.size());
const auto buffSize = 1024;
char buff[buffSize];
assert(buffSize >= path.size());
auto buff = static_cast<char*>(ox_alloca(path.size() + 1));
retval |= !(it.next(buff, path.size()) == 0 && ox_strcmp(buff, "usr") == 0);
retval |= !(it.next(buff, path.size()) == 0 && ox_strcmp(buff, "share") == 0);
return retval;
@ -61,9 +57,7 @@ map<string, int(*)(string)> tests = {
int retval = 0;
string path = "/";
PathIterator it(path.c_str(), path.size());
const auto buffSize = 1024;
char buff[buffSize];
assert(buffSize >= path.size());
auto buff = static_cast<char*>(ox_alloca(path.size() + 1));
retval |= !(it.next(buff, path.size()) == 0 && ox_strcmp(buff, "\0") == 0);
return retval;
}
@ -74,9 +68,7 @@ map<string, int(*)(string)> tests = {
int retval = 0;
string path = "usr/share/charset.gbag";
PathIterator it(path.c_str(), path.size());
const auto buffSize = 1024;
char buff[buffSize];
assert(buffSize >= path.size());
auto buff = static_cast<char*>(ox_alloca(path.size() + 1));
retval |= !(it.next(buff, path.size()) == 0 && ox_strcmp(buff, "usr") == 0);
retval |= !(it.next(buff, path.size()) == 0 && ox_strcmp(buff, "share") == 0);
retval |= !(it.next(buff, path.size()) == 0 && ox_strcmp(buff, "charset.gbag") == 0);
@ -89,9 +81,7 @@ map<string, int(*)(string)> tests = {
int retval = 0;
string path = "usr/share/";
PathIterator it(path.c_str(), path.size());
const auto buffSize = 1024;
char buff[buffSize];
assert(buffSize >= path.size());
auto buff = static_cast<char*>(ox_alloca(path.size() + 1));
retval |= !(it.next(buff, path.size()) == 0 && ox_strcmp(buff, "usr") == 0);
retval |= !(it.next(buff, path.size()) == 0 && ox_strcmp(buff, "share") == 0);
return retval;
@ -103,9 +93,7 @@ map<string, int(*)(string)> tests = {
int retval = 0;
string path = "/usr/share/charset.gbag";
PathIterator it(path.c_str(), path.size());
const auto buffSize = 1024;
char buff[buffSize];
assert(buffSize >= path.size());
auto buff = static_cast<char*>(ox_alloca(path.size() + 1));
retval |= !(it.dirPath(buff, path.size()) == 0 && ox_strcmp(buff, "/usr/share/") == 0);
return retval;
}
@ -116,13 +104,22 @@ map<string, int(*)(string)> tests = {
int retval = 0;
string path = "/usr/share/charset.gbag";
PathIterator it(path.c_str(), path.size());
const auto buffSize = 1024;
char buff[buffSize];
assert(buffSize >= path.size());
auto buff = static_cast<char*>(ox_alloca(path.size() + 1));
retval |= !(it.fileName(buff, path.size()) == 0 && ox_strcmp(buff, "charset.gbag") == 0);
return retval;
}
},
{
"PathIterator::hasNext",
[](string) {
int retval = 0;
const auto path = "/file1";
PathIterator it(path, ox_strlen(path));
oxAssert(it.hasNext(), "PathIterator shows incorrect hasNext");
oxAssert(!(it + 1).hasNext(), "PathIterator shows incorrect hasNext");
return retval;
}
},
{
"FileSystem32::findInodeOf /",
[](string) {
@ -383,16 +380,27 @@ map<string, int(*)(string)> tests = {
{
"Directory",
[](string) {
//std::array<uint8_t, 5000> fsBuff;
//std::array<uint8_t, 1000> dirBuff;
//ox::fs::FileStore32 fileStore(fsBuff.data(), fsBuff.size());
//fileStore.format();
//ox::fs::Directory32 dir(&fileStore, dirBuff.data(), dirBuff.size());
//dir.init();
//dir.write("/file1", 1);
//oxAssert(dir.find("/file1") == 1, "Could not find /file1");
//dir.write("/file3", 3);
//dir.write("/file2", 2);
std::array<uint8_t, 5000> fsBuff;
ox::fs::FileStore32 fileStore(fsBuff.data(), fsBuff.size());
fileStore.format();
auto dir = ox_malloca(1000, ox::fs::Directory32, &fileStore, 100);
oxTrace("ox::fs::test::Directory") << "Init";
oxAssert(dir->init(), "Init failed");
oxTrace("ox::fs::test::Directory") << "write 1";
oxAssert(dir->write("/file1", 1), "Directory write of file1 failed");
oxTrace("ox::fs::test::Directory") << "find";
oxAssert(dir->find("file1").error, "Could not find file1");
oxAssert(dir->find("file1") == 1, "Could not find file1");
//oxTrace("ox::fs::test::Directory") << "write 2";
//oxAssert(dir->write("/file3", 3) == 0, "Directory write of file3 failed");
//oxTrace("ox::fs::test::Directory") << "write 3";
//oxAssert(dir->write("/file2", 2) == 0, "Directory write of file2 failed");
return 0;
}
},

View File

@ -8,6 +8,8 @@
#pragma once
#include "ox/std/error.hpp"
namespace ox {
enum class OpType {

View File

@ -55,6 +55,10 @@ class __attribute__((packed)) NodeBuffer {
return m_current;
}
bool valid() {
return m_current.valid();
}
bool hasNext() {
if (m_current.valid()) {
oxTrace("ox::ptrarith::NodeBuffer::Iterator::hasNext::current") << m_current.offset();
@ -190,7 +194,6 @@ typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::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<Item*>(reinterpret_cast<uint8_t*>(this) + itemOffset);
oxTrace("ox::ptrarith::NodeBuffer::ptr::itemOffset") << itemOffset << m_header.size - sizeof(Item);
if (itemOffset >= sizeof(Header) &&
itemOffset < m_header.size - sizeof(Item) &&
itemSpace >= static_cast<size_t>(sizeof(Item)) &&
@ -271,10 +274,10 @@ template<typename size_t, typename Item>
Error NodeBuffer<size_t, Item>::setSize(size_t size) {
auto last = lastItem();
if ((last.valid() && last.end() >= size) || size < sizeof(m_header)) {
return 1;
return OxError(1);
} else {
m_header.size = size;
return 0;
return OxError(0);
}
}

View File

@ -21,6 +21,7 @@ install(
assert.hpp
bitops.hpp
byteswap.hpp
error.hpp
math.hpp
memops.hpp
new.hpp

View File

@ -33,11 +33,11 @@ void _assert<Error>([[maybe_unused]]const char *file, [[maybe_unused]]int line,
if (err) {
auto ei = ErrorInfo(err);
std::cerr << "\033[31;1;1mASSERT FAILURE:\033[0m (" << file << ':' << line << "): " << msg << '\n';
std::cerr << "\tError Info: " << ei.errCode;
std::cerr << "\tError Code:\t" << ei.errCode << '\n';
if (ei.file != nullptr) {
std::cerr << " (" << reinterpret_cast<const char*>(ei.file) << ':' << ei.line << ')';
std::cerr << "\tError Location:\t" << reinterpret_cast<const char*>(ei.file) << ':' << ei.line << '\n';
}
std::cerr << std::endl;
std::cerr << std::flush;
std::abort();
}
#endif

View File

@ -14,7 +14,7 @@
#include <ox/__buildinfo/defines.hpp>
#include "types.hpp"
#include "error.hpp"
namespace ox {

74
deps/ox/src/ox/std/error.hpp vendored Normal file
View File

@ -0,0 +1,74 @@
/*
* 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
#include "types.hpp"
#ifdef DEBUG
#define OxError(x) x ? reinterpret_cast<uint64_t>(__FILE__) | _errorTags(__LINE__, x) : 0
#else
#define OxError(x) x
#endif
namespace ox {
using Error = uint64_t;
constexpr Error errCode(Error err) {
return (err >> 58) & onMask<Error>(5);
}
struct ErrorInfo {
const char *file = nullptr;
int line = -1;
Error errCode = 0;
ErrorInfo() = default;
ErrorInfo(Error err) {
this->file = reinterpret_cast<const char*>(err & onMask<Error>(48));
this->line = static_cast<int>((err >> 48) & onMask<Error>(11));
this->errCode = ox::errCode(err);
}
};
static constexpr Error _errorTags(Error line, Error errCode) {
line &= onMask<Error>(11);
line <<= 48;
errCode &= onMask<Error>(5);
errCode <<= 59;
return errCode | line;
}
template<typename T>
struct ValErr {
T value;
Error error;
inline constexpr ValErr() = default;
inline constexpr ValErr(T value, Error error = 0): value(value), error(error) {
}
inline constexpr operator const T&() const {
return value;
}
inline constexpr operator T&() {
return value;
}
inline constexpr bool ok() const {
return error == 0;
}
};
}

View File

@ -13,17 +13,17 @@
namespace ox {
template<typename T>
inline const T &min(const T &a, const T &b) {
inline constexpr const T &min(const T &a, const T &b) {
return a < b ? a : b;
}
template<typename T>
inline const T &max(const T &a, const T &b) {
inline constexpr const T &max(const T &a, const T &b) {
return a > b ? a : b;
}
template<typename I>
inline I pow(I v, int e) {
inline constexpr I pow(I v, int e) {
I out = 1;
for (I i = 0; i < e; i++) {
out *= v;

View File

@ -11,6 +11,7 @@
#include "assert.hpp"
#include "bitops.hpp"
#include "byteswap.hpp"
#include "error.hpp"
#include "math.hpp"
#include "memops.hpp"
#include "new.hpp"

View File

@ -52,68 +52,6 @@ typedef uint32_t uintptr_t;
namespace ox {
using Error = uint64_t;
struct ErrorInfo {
const char *file = nullptr;
int line = -1;
Error errCode = 0;
ErrorInfo() = default;
ErrorInfo(Error err) {
this->file = reinterpret_cast<const char*>(err & onMask<Error>(48));
this->line = static_cast<int>((err >> 48) & onMask<Error>(11));
this->errCode = (err >> 58) & onMask<Error>(5);
}
};
constexpr Error ErrorTags(Error line, Error errCode) {
line &= onMask<Error>(11);
line <<= 48;
errCode &= onMask<Error>(5);
errCode <<= 59;
return errCode | line;
}
}
#ifdef DEBUG
#define OxError(x) x ? reinterpret_cast<uint64_t>(__FILE__) | ErrorTags(__LINE__, x) : 0
#else
#define OxError(x) x
#endif
namespace ox {
template<typename T>
struct ValErr {
T value;
Error error;
inline constexpr ValErr() = default;
inline constexpr ValErr(T value, Error error = 0): value(value), error(error) {
}
inline constexpr operator const T&() const {
return value;
}
inline constexpr operator T&() {
return value;
}
inline constexpr bool ok() const {
return error == 0;
}
};
}
namespace std {
using nullptr_t = decltype(nullptr);

View File

@ -54,4 +54,16 @@ NullStream::NullStream(const char*, int, const char*, const char*) {
NullStream::~NullStream() {
}
void logError(const char *file, int line, Error err) {
if (err) {
ErrorInfo ei(err);
TraceStream trc(file, line, "ox::error");
trc << "\tError:\t" << ei.errCode;
if (ei.file != nullptr) {
trc << " (" << reinterpret_cast<const char*>(ei.file) << ':' << ei.line << ')';
}
}
}
}

View File

@ -91,6 +91,12 @@ class NullStream {
};
using TraceStream = StdOutStream;
void logError(const char *file, int line, Error err);
}
#define oxTrace(ch) ox::trace::StdOutStream(__FILE__, __LINE__, ch)
#define oxLogError(err) ox::trace::logError(__FILE__, __LINE__, err)
#define oxTrace(ch) ox::trace::TraceStream(__FILE__, __LINE__, ch)