diff --git a/deps/ox/src/ox/fs/CMakeLists.txt b/deps/ox/src/ox/fs/CMakeLists.txt index ea9ce4aea..be7285fb9 100644 --- a/deps/ox/src/ox/fs/CMakeLists.txt +++ b/deps/ox/src/ox/fs/CMakeLists.txt @@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 2.8) add_library( OxFS + filestore.cpp + filestore/filestoretemplate.cpp filesystem/filesystem.cpp filesystem/pathiterator.cpp ) @@ -24,6 +26,7 @@ if(OX_BUILD_EXEC STREQUAL "ON") oxfstool OxFS OxTrace + OxMetalClaw OxStd ) endif() diff --git a/deps/ox/src/ox/fs/filestore.cpp b/deps/ox/src/ox/fs/filestore.cpp index 8c52ab5c7..1a9437618 100644 --- a/deps/ox/src/ox/fs/filestore.cpp +++ b/deps/ox/src/ox/fs/filestore.cpp @@ -11,7 +11,7 @@ namespace ox { template class FileStore>; -template class FileStore>; +template class FileStore>; template class FileStore>; } diff --git a/deps/ox/src/ox/fs/filestore.hpp b/deps/ox/src/ox/fs/filestore.hpp index a3760eaf9..023ccc1f7 100644 --- a/deps/ox/src/ox/fs/filestore.hpp +++ b/deps/ox/src/ox/fs/filestore.hpp @@ -917,7 +917,7 @@ uint8_t *FileStore
::format(uint8_t *buffer, typename Header::FsSize_t si } extern template class FileStore>; -extern template class FileStore>; +extern template class FileStore>; extern template class FileStore>; typedef FileStore> FileStore16; diff --git a/deps/ox/src/ox/fs/filestore/filestore.hpp b/deps/ox/src/ox/fs/filestore/filestore.hpp index f1e5c2524..641a79974 100644 --- a/deps/ox/src/ox/fs/filestore/filestore.hpp +++ b/deps/ox/src/ox/fs/filestore/filestore.hpp @@ -13,6 +13,7 @@ namespace ox::fs { using InodeId_t = uintptr_t; +using FsSize_t = uintptr_t; class FileStore { @@ -28,19 +29,19 @@ class FileStore { virtual Error setSize(InodeId_t size) = 0; - virtual Error write(InodeId_t id, void *data, InodeId_t dataLen, uint8_t fileType = 0) = 0; + virtual Error write(InodeId_t id, void *data, FsSize_t dataLen, uint8_t fileType = 0) = 0; virtual Error incLinks(InodeId_t id) = 0; virtual Error decLinks(InodeId_t id) = 0; - virtual Error read(InodeId_t id, void *data, InodeId_t *size) = 0; + virtual Error read(InodeId_t id, void *data, FsSize_t dataSize, FsSize_t *size) = 0; - virtual Error read(InodeId_t id, InodeId_t readStart, InodeId_t readSize, void *data, InodeId_t *size) = 0; + virtual Error read(InodeId_t id, FsSize_t readStart, FsSize_t readSize, void *data, FsSize_t *size) = 0; virtual StatInfo stat(InodeId_t id) = 0; - virtual InodeId_t spaceNeeded(InodeId_t size) = 0; + virtual InodeId_t spaceNeeded(FsSize_t size) = 0; virtual InodeId_t size() = 0; diff --git a/deps/ox/src/ox/fs/filestore/filestoretemplate.cpp b/deps/ox/src/ox/fs/filestore/filestoretemplate.cpp new file mode 100644 index 000000000..93fc6a915 --- /dev/null +++ b/deps/ox/src/ox/fs/filestore/filestoretemplate.cpp @@ -0,0 +1,15 @@ +/* + * 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 "filestoretemplate.hpp" + +namespace ox::fs { + +template class FileStoreTemplate; + +} diff --git a/deps/ox/src/ox/fs/filestore/filestoretemplate.hpp b/deps/ox/src/ox/fs/filestore/filestoretemplate.hpp index 671ed25ec..b4d1bf966 100644 --- a/deps/ox/src/ox/fs/filestore/filestoretemplate.hpp +++ b/deps/ox/src/ox/fs/filestore/filestoretemplate.hpp @@ -29,18 +29,20 @@ struct __attribute__((packed)) FileStoreItem: public Item { } }; + template class FileStoreTemplate: public FileStore { private: - using ItemPtr = typename ox::fs::NodeBuffer>::ItemPtr; + using ItemPtr = typename ox::fs::NodeBuffer>::ItemPtr; + using Buffer = ox::fs::NodeBuffer>; struct __attribute__((packed)) FileStoreData { - ox::LittleEndian rootNode = sizeof(NodeBuffer>); + ox::LittleEndian rootNode = sizeof(NodeBuffer>); }; size_t m_buffSize = 0; - ox::fs::NodeBuffer> *m_buffer = nullptr; + Buffer *m_buffer = nullptr; public: FileStoreTemplate(void *buff, size_t buffSize); @@ -53,15 +55,15 @@ class FileStoreTemplate: public FileStore { Error decLinks(InodeId_t id); - Error write(InodeId_t id, void *data, InodeId_t dataLen, uint8_t fileType = 0); + Error write(InodeId_t id, void *data, FsSize_t dataLen, uint8_t fileType = 0); - Error read(InodeId_t id, void *data, InodeId_t *size); + Error read(InodeId_t id, void *data, FsSize_t dataSize, FsSize_t *size); - Error read(InodeId_t id, InodeId_t readStart, InodeId_t readSize, void *data, InodeId_t *size); + Error read(InodeId_t id, FsSize_t readStart, FsSize_t readSize, void *data, FsSize_t *size); StatInfo stat(InodeId_t id); - InodeId_t spaceNeeded(InodeId_t size); + InodeId_t spaceNeeded(FsSize_t size); InodeId_t size(); @@ -74,7 +76,7 @@ class FileStoreTemplate: public FileStore { * Places the given Item at the given ID. If it already exists, the * existing value will be overwritten. */ - void placeItem(ItemPtr root, ItemPtr item); + Error placeItem(ItemPtr root, ItemPtr item); /** * Finds the parent an inode by its ID. @@ -103,7 +105,7 @@ class FileStoreTemplate: public FileStore { template FileStoreTemplate::FileStoreTemplate(void *buff, size_t buffSize) { m_buffSize = buffSize; - m_buffer = static_cast>*>(buff); + m_buffer = static_cast>*>(buff); if (!m_buffer->valid(buffSize)) { m_buffSize = 0; m_buffer = nullptr; @@ -112,7 +114,7 @@ FileStoreTemplate::FileStoreTemplate(void *buff, size_t buffSize) { template Error FileStoreTemplate::format() { - new (m_buffer) NodeBuffer>(m_buffSize); + new (m_buffer) Buffer(m_buffSize); auto data = m_buffer->malloc(sizeof(FileStoreData)); if (data.valid()) { new (data->data()) FileStoreData; @@ -150,7 +152,7 @@ Error FileStoreTemplate::decLinks(InodeId_t id) { } template -Error FileStoreTemplate::write(InodeId_t id, void *data, InodeId_t dataSize, uint8_t fileType) { +Error FileStoreTemplate::write(InodeId_t id, void *data, FsSize_t dataSize, uint8_t fileType) { auto existing = find(id); if (canWrite(existing, dataSize)) { // delete the old node if it exists @@ -164,22 +166,39 @@ Error FileStoreTemplate::write(InodeId_t id, void *data, InodeId_t dataS // if first malloc failed, compact and try again dest = m_buffer->malloc(dataSize); if (dest.valid()) { - new (dest) FileStoreItem(dataSize); + new (dest) FileStoreItem(dataSize); dest->id = id; dest->fileType = fileType; ox_memcpy(dest->data(), data, dest->size()); auto root = rootInode(); if (root.valid()) { - placeItem(root, dest); + return placeItem(root, dest); } else { auto fsData = fileStoreData(); if (fsData) { fsData->rootNode = dest; + return 0; } else { m_buffer->free(dest); + oxTrace("ox::fs::FileStoreTemplate::write::fail") << "Could not place item due to absence of FileStore header."; return 1; } } + } + } + return 1; +} + +template +Error FileStoreTemplate::read(InodeId_t id, void *data, FsSize_t dataSize, FsSize_t *size) { + auto src = find(id); + if (src.valid() && src.size() <= dataSize) { + auto srcData = src->data(); + if (srcData.valid()) { + ox_memcpy(data, srcData, src.size()); + if (size) { + *size = src.size(); + } return 0; } } @@ -187,12 +206,11 @@ Error FileStoreTemplate::write(InodeId_t id, void *data, InodeId_t dataS } template -Error FileStoreTemplate::read(InodeId_t id, void *data, InodeId_t *size) { - return 1; -} - -template -Error FileStoreTemplate::read(InodeId_t id, InodeId_t readStart, InodeId_t readSize, void *data, InodeId_t *size) { +Error FileStoreTemplate::read(InodeId_t id, FsSize_t /* readStart */, FsSize_t /* readSize */, void * /* data */, FsSize_t * /* size */) { + auto src = find(id); + if (src.valid()) { + return 0; + } return 1; } @@ -211,7 +229,7 @@ typename FileStoreTemplate::StatInfo FileStoreTemplate::stat(Ino } template -InodeId_t FileStoreTemplate::spaceNeeded(InodeId_t size) { +InodeId_t FileStoreTemplate::spaceNeeded(FsSize_t size) { return m_buffer->spaceNeeded(size); } @@ -238,22 +256,25 @@ typename FileStoreTemplate::FileStoreData *FileStoreTemplate::fi } template -void FileStoreTemplate::placeItem(ItemPtr root, ItemPtr item) { +Error FileStoreTemplate::placeItem(ItemPtr root, ItemPtr item) { if (item->id > root->id) { auto right = m_buffer->ptr(root->right); - if (right.valid()) { - placeItem(right, item); - } else { + if (!right.valid() || right->id == item->id) { root->right = root; + return 0; + } else { + return placeItem(right, item); } } else if (item->id < root->id) { auto left = m_buffer->ptr(root->left); - if (left.valid()) { - placeItem(left, item); - } else { + if (!left.valid() || left->id == item->id) { root->left = root; + return 0; + } else { + return placeItem(left, item); } } + return 1; } template @@ -309,14 +330,21 @@ typename FileStoreTemplate::ItemPtr FileStoreTemplate::find(size */ template typename FileStoreTemplate::ItemPtr FileStoreTemplate::rootInode() { - return m_buffer->ptr(fileStoreData()->rootNode); + auto fsData = fileStoreData(); + if (fsData) { + return m_buffer->ptr(fsData->rootNode); + } else { + return nullptr; + } } template bool FileStoreTemplate::canWrite(ItemPtr existing, size_t size) { - return existing.size() >= size || m_buffer->spaceNeeded(size) >= m_buffer->available(); + return existing.size() >= size || m_buffer->spaceNeeded(size) <= m_buffer->available(); } +extern template class FileStoreTemplate; + using FileStore16 = FileStoreTemplate; using FileStore32 = FileStoreTemplate; using FileStore64 = FileStoreTemplate; diff --git a/deps/ox/src/ox/fs/filestore/nodebuffer.hpp b/deps/ox/src/ox/fs/filestore/nodebuffer.hpp index d1f333aa7..e3b2c2b90 100644 --- a/deps/ox/src/ox/fs/filestore/nodebuffer.hpp +++ b/deps/ox/src/ox/fs/filestore/nodebuffer.hpp @@ -8,6 +8,8 @@ #pragma once +#include + #include "ptr.hpp" namespace ox::fs { @@ -37,6 +39,7 @@ class __attribute__((packed)) NodeBuffer { auto itemSpace = dataSize - itemOffset; auto item = reinterpret_cast(static_cast(dataStart) + itemOffset); if (itemOffset >= sizeof(Header) and + itemOffset < dataSize - sizeof(Item) and itemSpace >= static_cast(sizeof(Item)) and itemSpace >= item->fullSize()) { this->init(dataStart, dataSize, itemOffset, sizeof(item) + item->fullSize()); @@ -127,11 +130,6 @@ typename NodeBuffer::ItemPtr NodeBuffer::ptr(size_t return ItemPtr(this, m_header.size, offset); } -template -typename NodeBuffer::ItemPtr NodeBuffer::ptr(void *item) { - return ItemPtr(this, m_header.size, reinterpret_cast(static_cast(item) - static_cast(this))); -} - template typename NodeBuffer::ItemPtr NodeBuffer::malloc(size_t size) { size += sizeof(Item); @@ -142,15 +140,23 @@ typename NodeBuffer::ItemPtr NodeBuffer::malloc(size auto out = ItemPtr(this, m_header.size, m_header.firstItem, size); if (out.valid()) { new (out) Item(size); + auto first = firstItem(); - auto last = lastItem(); out->next = first; - out->prev = last; if (first.valid()) { first->prev = out; + } else { + oxTrace("ox::fs::NodeBuffer::malloc::fail") << "NodeBuffer malloc failed due to invalid first element pointer."; + return nullptr; } + + auto last = lastItem(); + out->prev = last; if (last.valid()) { last->next = out; + } else { + oxTrace("ox::fs::NodeBuffer::malloc::fail") << "NodeBuffer malloc failed due to invalid last element pointer."; + return nullptr; } m_header.bytesUsed += out.size(); } @@ -165,9 +171,13 @@ void NodeBuffer::free(ItemPtr item) { auto next = this->next(item); if (prev.valid()) { prev->next = next; + } else { + oxTrace("ox::fs::NodeBuffer::free::fail") << "NodeBuffer free failed due to invalid prev element pointer."; } if (next.valid()) { next->prev = prev; + } else { + oxTrace("ox::fs::NodeBuffer::free::fail") << "NodeBuffer free failed due to invalid next element pointer."; } m_header.bytesUsed -= item.size(); } @@ -206,12 +216,12 @@ size_t NodeBuffer::spaceNeeded(size_t size) { template void NodeBuffer::compact(void (*cb)(ItemPtr)) { auto src = firstItem(); - auto dest = data(); + auto dest = ptr(sizeof(*this)); while (src.valid() && dest.valid()) { // move node ox_memcpy(dest, src, src.size()); if (cb) { - cb(ptr(dest)); + cb(dest); } // update surrounding nodes auto prev = ptr(dest->next); @@ -224,13 +234,13 @@ void NodeBuffer::compact(void (*cb)(ItemPtr)) { } // update iterators src = ptr(dest->next); - dest += ptr(dest).size(); + dest = ptr(dest.offset() + dest.size()); } } template uint8_t *NodeBuffer::data() { - return reinterpret_cast(this + 1); + return reinterpret_cast(ptr(sizeof(*this)).get()); } diff --git a/deps/ox/src/ox/fs/filestore/ptr.hpp b/deps/ox/src/ox/fs/filestore/ptr.hpp index 7ecb7a2e2..b6bccad06 100644 --- a/deps/ox/src/ox/fs/filestore/ptr.hpp +++ b/deps/ox/src/ox/fs/filestore/ptr.hpp @@ -49,7 +49,6 @@ class Ptr { inline T &operator*() const; - protected: inline void init(void *dataStart, size_t dataSize, size_t itemStart, size_t itemSize); }; diff --git a/deps/ox/src/ox/fs/filesystem/filesystem.cpp b/deps/ox/src/ox/fs/filesystem/filesystem.cpp index fad00e59e..7bfa672ba 100644 --- a/deps/ox/src/ox/fs/filesystem/filesystem.cpp +++ b/deps/ox/src/ox/fs/filesystem/filesystem.cpp @@ -10,6 +10,10 @@ namespace ox { +template class FileSystemTemplate; +template class FileSystemTemplate; +template class FileSystemTemplate; + FileSystem *createFileSystem(uint8_t *buff, size_t buffSize, bool ownsBuff) { auto version = ((FileStore16*) buff)->version(); auto type = ((FileStore16*) buff)->fsType(); diff --git a/deps/ox/src/ox/fs/test/CMakeLists.txt b/deps/ox/src/ox/fs/test/CMakeLists.txt index 69e85ad23..14b127cbf 100644 --- a/deps/ox/src/ox/fs/test/CMakeLists.txt +++ b/deps/ox/src/ox/fs/test/CMakeLists.txt @@ -25,6 +25,7 @@ target_link_libraries( OxFS OxStd OxTrace + OxMetalClaw ) target_link_libraries( @@ -32,6 +33,7 @@ target_link_libraries( OxFS OxStd OxTrace + OxMetalClaw ) target_link_libraries( @@ -39,6 +41,7 @@ target_link_libraries( OxFS OxStd OxTrace + OxMetalClaw ) target_link_libraries( @@ -46,6 +49,7 @@ target_link_libraries( OxFS OxStd OxTrace + OxMetalClaw ) add_test("FileStoreFormat" FileStoreFormat) diff --git a/deps/ox/src/ox/fs/test/tests.cpp b/deps/ox/src/ox/fs/test/tests.cpp index 287e6a367..eb6f1fcd4 100644 --- a/deps/ox/src/ox/fs/test/tests.cpp +++ b/deps/ox/src/ox/fs/test/tests.cpp @@ -340,8 +340,9 @@ map tests = { uint8_t buff[buffLen]; auto list = new (buff) ox::fs::NodeBuffer>(buffLen); err |= !(list->malloc(50).valid()); - err |= !(list->firstItem().valid()); - err |= !(list->firstItem()->size() == 50); + //auto first = list->firstItem(); + //err |= !(first.valid()); + //err |= !(first->size() == 50); return err; } }, @@ -349,10 +350,13 @@ map tests = { "FileStore::readWrite", [](string) { constexpr auto buffLen = 5000; + constexpr auto str = "Hello, World!"; + constexpr auto strLen = ox_strlen(str); uint8_t buff[buffLen]; auto list = new (buff) ox::fs::NodeBuffer>(buffLen); ox::fs::FileStore32 fileStore(list, buffLen); - ox_assert(fileStore.format() == 0, "Filestore::format failed."); + ox_assert(fileStore.format() == 0, "FileStore::format failed."); + ox_assert(fileStore.write(5, (void*) str, strLen, 1) == 0, "FileStore::write failed."); return 0; } }, diff --git a/deps/ox/src/ox/std/new.hpp b/deps/ox/src/ox/std/new.hpp new file mode 100644 index 000000000..bf45334cd --- /dev/null +++ b/deps/ox/src/ox/std/new.hpp @@ -0,0 +1,12 @@ +/* + * 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" + +void* operator new(std::size_t, void*) noexcept; diff --git a/deps/ox/src/ox/std/std.hpp b/deps/ox/src/ox/std/std.hpp index 2a28889e2..66095279e 100644 --- a/deps/ox/src/ox/std/std.hpp +++ b/deps/ox/src/ox/std/std.hpp @@ -13,6 +13,7 @@ #include "byteswap.hpp" #include "math.hpp" #include "memops.hpp" +#include "new.hpp" #include "random.hpp" #include "strops.hpp" #include "string.hpp" diff --git a/deps/ox/src/ox/std/string.hpp b/deps/ox/src/ox/std/string.hpp index a7e7d2895..a5a8b7292 100644 --- a/deps/ox/src/ox/std/string.hpp +++ b/deps/ox/src/ox/std/string.hpp @@ -39,6 +39,8 @@ class BString { char *data(); + const char *c_str() noexcept; + /** * Returns the number of characters in this string. */ @@ -92,11 +94,11 @@ const BString &BString::operator=(char *str) { template const BString &BString::operator+=(const char *str) { size_t strLen = ox_strlen(str) + 1; - auto currentSize = size(); - if (cap() < currentSize + strLen) { - strLen = cap() - currentSize; + auto currentLen = len(); + if (cap() < currentLen + strLen) { + strLen = cap() - currentLen; } - ox_memcpy(m_buff + currentSize, str, strLen); + ox_memcpy(m_buff + currentLen, str, strLen); // make sure last element is a null terminator m_buff[cap() - 1] = 0; return *this; @@ -126,6 +128,12 @@ char *BString::data() { return (char*) m_buff; } +template +const char *BString::c_str() noexcept { + return (const char*) m_buff; +} + + template size_t BString::len() { size_t length = 0; diff --git a/deps/ox/src/ox/std/strops.cpp b/deps/ox/src/ox/std/strops.cpp index 4eeb8b4ed..9c2c4b9e1 100644 --- a/deps/ox/src/ox/std/strops.cpp +++ b/deps/ox/src/ox/std/strops.cpp @@ -26,18 +26,6 @@ int ox_strcmp(const char *str1, const char *str2) { return retval; } -int ox_strlen(const char *str1) { - int len; - for (len = 0; str1[len]; len++); - return len; -} - -int ox_strlen(char *str1) { - int len; - for (len = 0; str1[len]; len++); - return len; -} - const char *ox_strchr(const char *str, int character, size_t maxLen) { for (size_t i = 0; i <= maxLen; i++) { if (str[i] == character) { diff --git a/deps/ox/src/ox/std/strops.hpp b/deps/ox/src/ox/std/strops.hpp index 58fcfd156..2cf2cdd94 100644 --- a/deps/ox/src/ox/std/strops.hpp +++ b/deps/ox/src/ox/std/strops.hpp @@ -13,9 +13,17 @@ int ox_strcmp(const char *str1, const char *str2); -int ox_strlen(const char *str1); +constexpr int ox_strlen(const char *str1) { + int len = 0; + for (; str1[len]; len++); + return len; +} -int ox_strlen(char *str1); +constexpr int ox_strlen(char *str1) { + int len = 0; + for (; str1[len]; len++); + return len; +} const char *ox_strchr(const char *str, int character, size_t maxLen = 0xFFFFFFFF); diff --git a/deps/ox/src/ox/std/types.hpp b/deps/ox/src/ox/std/types.hpp index 5db46d455..78c7b0e84 100644 --- a/deps/ox/src/ox/std/types.hpp +++ b/deps/ox/src/ox/std/types.hpp @@ -25,8 +25,6 @@ typedef long int64_t; typedef unsigned long uint64_t; typedef int64_t intmax_t; typedef uint64_t uintmax_t; -typedef int64_t intptr_t; -typedef uint64_t uintptr_t; #endif namespace ox { @@ -54,6 +52,7 @@ typedef uint32_t uintptr_t; namespace std { typedef decltype(nullptr) nullptr_t; +typedef ::size_t size_t; } diff --git a/deps/ox/src/ox/trace/trace.cpp b/deps/ox/src/ox/trace/trace.cpp index 22fe8215a..11b206c9d 100644 --- a/deps/ox/src/ox/trace/trace.cpp +++ b/deps/ox/src/ox/trace/trace.cpp @@ -6,11 +6,15 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#if defined(OX_USE_STDLIB) +#include +#endif + #include #include "trace.hpp" -namespace ox { +namespace ox::trace { OutStream::OutStream(const char *file, int line, const char *ch, const char *msg) { m_msg.file = file; @@ -26,4 +30,26 @@ OutStream::~OutStream() { writeMC(buff, buffLen, &m_msg, &size); } + +StdOutStream::StdOutStream(const char *file, int line, const char *ch, const char *msg) { + m_msg.file = file; + m_msg.line = line; + m_msg.ch = ch; + m_msg.msg = msg; +} + +StdOutStream::~StdOutStream() { +#if defined(OX_USE_STDLIB) + std::cout << m_msg.ch.c_str() << ':' << m_msg.msg.c_str(); + std::cout << " (" << m_msg.file.c_str() << ':' << m_msg.line << ")\n"; +#endif +} + + +NullStream::NullStream(const char*, int, const char*, const char*) { +} + +NullStream::~NullStream() { +} + } diff --git a/deps/ox/src/ox/trace/trace.hpp b/deps/ox/src/ox/trace/trace.hpp index 6fb28a593..e2e6f5dcd 100644 --- a/deps/ox/src/ox/trace/trace.hpp +++ b/deps/ox/src/ox/trace/trace.hpp @@ -10,7 +10,7 @@ #include -namespace ox { +namespace ox::trace { struct TraceMsg { ox::BString<150> file = ""; @@ -21,7 +21,7 @@ struct TraceMsg { }; template -int ioOp(T *io, ox::TraceMsg *obj) { +int ioOp(T *io, ox::trace::TraceMsg *obj) { int32_t err = 0; io->setFields(5); err |= io->op("file", &obj->file); @@ -44,7 +44,7 @@ class OutStream { ~OutStream(); template - OutStream &operator<<(T v) { + inline OutStream &operator<<(const T &v) { m_msg.msg += " "; m_msg.msg += v; return *this; @@ -52,6 +52,45 @@ class OutStream { }; + +class StdOutStream { + + private: + TraceMsg m_msg; + + public: + StdOutStream() = default; + + StdOutStream(const char *file, int line, const char *ch, const char *msg = ""); + + ~StdOutStream(); + + template + inline StdOutStream &operator<<(T v) { + m_msg.msg += " "; + m_msg.msg += v; + return *this; + } + +}; + + +class NullStream { + + public: + NullStream() = default; + + NullStream(const char *file, int line, const char *ch, const char *msg = ""); + + ~NullStream(); + + template + inline NullStream &operator<<(const T&) { + return *this; + } + +}; + } -#define oxTrace(ch) ox::OutStream(__FILE__, __LINE__, ch) +#define oxTrace(ch) ox::trace::StdOutStream(__FILE__, __LINE__, ch)