[ox] Add file:line error tracing
This commit is contained in:
parent
956415a6a2
commit
ea7cf59ec7
125
deps/ox/src/ox/fs/filestore/filestoretemplate.hpp
vendored
125
deps/ox/src/ox/fs/filestore/filestoretemplate.hpp
vendored
@ -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>
|
||||
|
94
deps/ox/src/ox/fs/filesystem/pathiterator.cpp
vendored
94
deps/ox/src/ox/fs/filesystem/pathiterator.cpp
vendored
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
22
deps/ox/src/ox/fs/filesystem/pathiterator.hpp
vendored
22
deps/ox/src/ox/fs/filesystem/pathiterator.hpp
vendored
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
158
deps/ox/src/ox/fs/filesystem2/directory.hpp
vendored
158
deps/ox/src/ox/fs/filesystem2/directory.hpp
vendored
@ -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)};
|
||||
}
|
||||
|
||||
|
||||
|
1
deps/ox/src/ox/fs/test/CMakeLists.txt
vendored
1
deps/ox/src/ox/fs/test/CMakeLists.txt
vendored
@ -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)
|
||||
|
70
deps/ox/src/ox/fs/test/tests.cpp
vendored
70
deps/ox/src/ox/fs/test/tests.cpp
vendored
@ -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;
|
||||
}
|
||||
},
|
||||
|
2
deps/ox/src/ox/mc/optype.hpp
vendored
2
deps/ox/src/ox/mc/optype.hpp
vendored
@ -8,6 +8,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ox/std/error.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
enum class OpType {
|
||||
|
9
deps/ox/src/ox/ptrarith/nodebuffer.hpp
vendored
9
deps/ox/src/ox/ptrarith/nodebuffer.hpp
vendored
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
1
deps/ox/src/ox/std/CMakeLists.txt
vendored
1
deps/ox/src/ox/std/CMakeLists.txt
vendored
@ -21,6 +21,7 @@ install(
|
||||
assert.hpp
|
||||
bitops.hpp
|
||||
byteswap.hpp
|
||||
error.hpp
|
||||
math.hpp
|
||||
memops.hpp
|
||||
new.hpp
|
||||
|
6
deps/ox/src/ox/std/assert.cpp
vendored
6
deps/ox/src/ox/std/assert.cpp
vendored
@ -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
|
||||
|
2
deps/ox/src/ox/std/assert.hpp
vendored
2
deps/ox/src/ox/std/assert.hpp
vendored
@ -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
74
deps/ox/src/ox/std/error.hpp
vendored
Normal 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;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
6
deps/ox/src/ox/std/math.hpp
vendored
6
deps/ox/src/ox/std/math.hpp
vendored
@ -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;
|
||||
|
1
deps/ox/src/ox/std/std.hpp
vendored
1
deps/ox/src/ox/std/std.hpp
vendored
@ -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"
|
||||
|
62
deps/ox/src/ox/std/types.hpp
vendored
62
deps/ox/src/ox/std/types.hpp
vendored
@ -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);
|
||||
|
12
deps/ox/src/ox/trace/trace.cpp
vendored
12
deps/ox/src/ox/trace/trace.cpp
vendored
@ -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 << ')';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
8
deps/ox/src/ox/trace/trace.hpp
vendored
8
deps/ox/src/ox/trace/trace.hpp
vendored
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user