From 50c859d70834c6b58116a2f9a15f168b9b94f9d8 Mon Sep 17 00:00:00 2001 From: bergmann Date: Sat, 17 Feb 2018 12:37:32 +0100 Subject: [PATCH] * implemented mp::pair * code styling --- src/CMakeLists.txt | 3 +- src/LoggerImpl.cpp | 257 ----- src/cpputils/Exception.h | 167 --- src/cpputils/HandleManager.h | 1004 ---------------- src/cpputils/Logger.h | 187 --- src/cpputils/LoggerImpl.h | 189 ---- src/cpputils/Misc.h | 237 ---- src/cpputils/container.h | 5 + src/cpputils/container/handle_manager.h | 1005 +++++++++++++++++ .../{Nullable.h => container/nullable.h} | 83 +- .../{SmartPtr.h => container/smart_ptr.h} | 46 +- src/cpputils/container/wrapper.h | 104 ++ src/cpputils/logging.h | 0 src/cpputils/logging/consumer.h | 4 + src/cpputils/logging/consumer/consumer.h | 24 + .../logging/consumer/consumer_stream.h | 25 + src/cpputils/logging/global.h | 42 + src/cpputils/logging/log_message.h | 42 + src/cpputils/logging/logger.h | 98 ++ src/cpputils/logging/logger_impl.h | 51 + src/cpputils/logging/matcher.h | 6 + src/cpputils/logging/matcher/matcher.h | 20 + src/cpputils/logging/matcher/matcher_all.h | 15 + .../logging/matcher/matcher_default.h | 20 + src/cpputils/logging/matcher/matcher_regex.h | 23 + src/cpputils/logging/rule.h | 63 ++ src/cpputils/logging/types.h | 31 + src/cpputils/misc.h | 14 + src/cpputils/misc/convert.h | 63 ++ .../{EnumConversion.h => misc/enum.h} | 54 +- src/cpputils/misc/exception.h | 168 +++ src/cpputils/{Flags.h => misc/flags.h} | 42 +- src/cpputils/misc/indent.h | 39 + src/cpputils/{Linq.h => misc/linq.h} | 77 +- src/cpputils/misc/misc.h | 35 + .../{StreamHelper.h => misc/stream.h} | 42 +- .../{StringHelper.h => misc/string.h} | 66 +- src/cpputils/{Time.h => misc/time.h} | 4 +- .../transform_iterator.h} | 34 +- src/cpputils/misc/type_helper.h | 20 + src/cpputils/mp.h | 7 + src/cpputils/mp/MetaProgramming.h.old | 980 ---------------- src/cpputils/mp/container.h | 3 + src/cpputils/mp/container/pair.h | 238 ++++ src/cpputils/mp/core.h | 173 +-- src/cpputils/mp/core/checker.h | 51 + src/cpputils/mp/core/conditionals.h | 53 + src/cpputils/mp/core/const.h | 30 + src/cpputils/mp/core/modifier.h | 78 ++ src/cpputils/mp/core/types.h | 10 + src/cpputils/mp/intern.h | 3 + src/cpputils/mp/intern/comparable_equal.h | 39 + src/cpputils/mp/intern/comparable_less.h | 36 + src/cpputils/mp/intern/ebo.h | 83 ++ src/cpputils/mp/intern/has_value.h | 16 + src/cpputils/mp/intern/operators_comparable.h | 36 + src/cpputils/mp/intern/operators_orderable.h | 50 + src/cpputils/mp/operations.h | 6 + src/cpputils/mp/operations/compare.h | 4 + src/cpputils/mp/operations/compare/equal.h | 73 ++ src/cpputils/mp/operations/compare/greater.h | 51 + .../mp/operations/compare/greater_equal.h | 51 + src/cpputils/mp/operations/compare/less.h | 73 ++ .../mp/operations/compare/less_equal.h | 51 + .../mp/operations/compare/not_equal.h | 51 + src/cpputils/mp/operations/eval.h | 59 + src/cpputils/mp/operations/eval_if.h | 80 ++ src/cpputils/mp/operations/first.h | 46 + src/cpputils/mp/operations/if.fwd.h | 18 + src/cpputils/mp/operations/if.h | 52 + src/cpputils/mp/operations/logical.h | 4 + src/cpputils/mp/operations/logical/and.h | 63 ++ src/cpputils/mp/operations/logical/not.h | 55 + src/cpputils/mp/operations/logical/or.h | 63 ++ src/cpputils/mp/operations/second.h | 46 + src/cpputils/mp/operations/value.h | 54 + src/cpputils/mp/util.h | 159 +-- src/cpputils/mp/util/default.h | 33 + src/cpputils/mp/util/is_a.h | 38 + src/cpputils/mp/util/make.h | 55 + src/cpputils/mp/util/tag_of.h | 35 + src/cpputils/mp/{convert.h => util/to.h} | 37 +- src/cpputils/mp/util/when.h | 32 + src/impl/logging/LoggerImpl.cpp.old | 119 ++ src/impl/logging/consumer/consumer.cpp | 14 + src/impl/logging/consumer/consumer_stream.cpp | 66 ++ src/impl/logging/global.cpp | 129 +++ src/impl/logging/logger.cpp | 15 + src/impl/logging/logger_impl.cpp | 23 + src/impl/logging/matcher.cpp | 41 + test/CMakeLists.txt | 1 + test/EnumConversionTests.cpp | 61 - test/FlagsTests.cpp | 76 -- test/HandleManagerTests.cpp | 120 -- test/LoggingTests.cpp | 135 --- test/MiscTests.cpp | 22 - test/StringHelperTests.cpp | 97 -- test/container/handle_manager.cpp | 120 ++ .../nullable.cpp} | 74 +- test/logging/logging_tests.cpp | 124 ++ test/misc/enum.cpp | 65 ++ test/misc/flags.cpp | 72 ++ test/{LinqTests.cpp => misc/linq.cpp} | 6 +- test/misc/misc.cpp | 18 + .../stream.cpp} | 29 +- test/misc/string.cpp | 59 + test/{TimeTests.cpp => misc/time.cpp} | 8 +- .../transform_iterator.cpp} | 27 +- test/mp/MetaProgrammingTests.cpp.old | 341 ------ test/mp/container/pair.cpp | 61 + test/mp/core.cpp | 2 +- test/mp/intern/comparable_equal.cpp | 8 + test/mp/intern/ebo.cpp | 9 + test/mp/intern/has_value.cpp | 10 + test/mp/mp.cpp | 1 + test/mp/operations/compare/equal.cpp | 9 + test/mp/operations/compare/less.cpp | 9 + test/mp/util.cpp | 36 - test/mp/util/default.cpp | 14 + test/mp/util/is_a.cpp | 18 + test/mp/util/make.cpp | 9 + test/mp/util/tag_of.cpp | 27 + test/mp/{convert.cpp => util/to.cpp} | 4 +- 123 files changed, 5130 insertions(+), 4533 deletions(-) delete mode 100644 src/LoggerImpl.cpp delete mode 100644 src/cpputils/Exception.h delete mode 100644 src/cpputils/HandleManager.h delete mode 100644 src/cpputils/Logger.h delete mode 100644 src/cpputils/LoggerImpl.h delete mode 100644 src/cpputils/Misc.h create mode 100644 src/cpputils/container.h create mode 100644 src/cpputils/container/handle_manager.h rename src/cpputils/{Nullable.h => container/nullable.h} (52%) rename src/cpputils/{SmartPtr.h => container/smart_ptr.h} (79%) create mode 100644 src/cpputils/container/wrapper.h create mode 100644 src/cpputils/logging.h create mode 100644 src/cpputils/logging/consumer.h create mode 100644 src/cpputils/logging/consumer/consumer.h create mode 100644 src/cpputils/logging/consumer/consumer_stream.h create mode 100644 src/cpputils/logging/global.h create mode 100644 src/cpputils/logging/log_message.h create mode 100644 src/cpputils/logging/logger.h create mode 100644 src/cpputils/logging/logger_impl.h create mode 100644 src/cpputils/logging/matcher.h create mode 100644 src/cpputils/logging/matcher/matcher.h create mode 100644 src/cpputils/logging/matcher/matcher_all.h create mode 100644 src/cpputils/logging/matcher/matcher_default.h create mode 100644 src/cpputils/logging/matcher/matcher_regex.h create mode 100644 src/cpputils/logging/rule.h create mode 100644 src/cpputils/logging/types.h create mode 100644 src/cpputils/misc.h create mode 100644 src/cpputils/misc/convert.h rename src/cpputils/{EnumConversion.h => misc/enum.h} (67%) create mode 100644 src/cpputils/misc/exception.h rename src/cpputils/{Flags.h => misc/flags.h} (60%) create mode 100644 src/cpputils/misc/indent.h rename src/cpputils/{Linq.h => misc/linq.h} (95%) create mode 100644 src/cpputils/misc/misc.h rename src/cpputils/{StreamHelper.h => misc/stream.h} (71%) rename src/cpputils/{StringHelper.h => misc/string.h} (61%) rename src/cpputils/{Time.h => misc/time.h} (97%) rename src/cpputils/{TransformIterator.h => misc/transform_iterator.h} (84%) create mode 100644 src/cpputils/misc/type_helper.h create mode 100644 src/cpputils/mp.h delete mode 100644 src/cpputils/mp/MetaProgramming.h.old create mode 100644 src/cpputils/mp/container.h create mode 100644 src/cpputils/mp/container/pair.h create mode 100644 src/cpputils/mp/core/checker.h create mode 100644 src/cpputils/mp/core/conditionals.h create mode 100644 src/cpputils/mp/core/const.h create mode 100644 src/cpputils/mp/core/modifier.h create mode 100644 src/cpputils/mp/core/types.h create mode 100644 src/cpputils/mp/intern.h create mode 100644 src/cpputils/mp/intern/comparable_equal.h create mode 100644 src/cpputils/mp/intern/comparable_less.h create mode 100644 src/cpputils/mp/intern/ebo.h create mode 100644 src/cpputils/mp/intern/has_value.h create mode 100644 src/cpputils/mp/intern/operators_comparable.h create mode 100644 src/cpputils/mp/intern/operators_orderable.h create mode 100644 src/cpputils/mp/operations.h create mode 100644 src/cpputils/mp/operations/compare.h create mode 100644 src/cpputils/mp/operations/compare/equal.h create mode 100644 src/cpputils/mp/operations/compare/greater.h create mode 100644 src/cpputils/mp/operations/compare/greater_equal.h create mode 100644 src/cpputils/mp/operations/compare/less.h create mode 100644 src/cpputils/mp/operations/compare/less_equal.h create mode 100644 src/cpputils/mp/operations/compare/not_equal.h create mode 100644 src/cpputils/mp/operations/eval.h create mode 100644 src/cpputils/mp/operations/eval_if.h create mode 100644 src/cpputils/mp/operations/first.h create mode 100644 src/cpputils/mp/operations/if.fwd.h create mode 100644 src/cpputils/mp/operations/if.h create mode 100644 src/cpputils/mp/operations/logical.h create mode 100644 src/cpputils/mp/operations/logical/and.h create mode 100644 src/cpputils/mp/operations/logical/not.h create mode 100644 src/cpputils/mp/operations/logical/or.h create mode 100644 src/cpputils/mp/operations/second.h create mode 100644 src/cpputils/mp/operations/value.h create mode 100644 src/cpputils/mp/util/default.h create mode 100644 src/cpputils/mp/util/is_a.h create mode 100644 src/cpputils/mp/util/make.h create mode 100644 src/cpputils/mp/util/tag_of.h rename src/cpputils/mp/{convert.h => util/to.h} (91%) create mode 100644 src/cpputils/mp/util/when.h create mode 100644 src/impl/logging/LoggerImpl.cpp.old create mode 100644 src/impl/logging/consumer/consumer.cpp create mode 100644 src/impl/logging/consumer/consumer_stream.cpp create mode 100644 src/impl/logging/global.cpp create mode 100644 src/impl/logging/logger.cpp create mode 100644 src/impl/logging/logger_impl.cpp create mode 100644 src/impl/logging/matcher.cpp delete mode 100644 test/EnumConversionTests.cpp delete mode 100644 test/FlagsTests.cpp delete mode 100644 test/HandleManagerTests.cpp delete mode 100644 test/LoggingTests.cpp delete mode 100644 test/MiscTests.cpp delete mode 100644 test/StringHelperTests.cpp create mode 100644 test/container/handle_manager.cpp rename test/{NullableTests.cpp => container/nullable.cpp} (65%) create mode 100644 test/logging/logging_tests.cpp create mode 100644 test/misc/enum.cpp create mode 100644 test/misc/flags.cpp rename test/{LinqTests.cpp => misc/linq.cpp} (99%) create mode 100644 test/misc/misc.cpp rename test/{StreamHelperTests.cpp => misc/stream.cpp} (69%) create mode 100644 test/misc/string.cpp rename test/{TimeTests.cpp => misc/time.cpp} (88%) rename test/{TransformIteratorTests.cpp => misc/transform_iterator.cpp} (78%) delete mode 100644 test/mp/MetaProgrammingTests.cpp.old create mode 100644 test/mp/container/pair.cpp create mode 100644 test/mp/intern/comparable_equal.cpp create mode 100644 test/mp/intern/ebo.cpp create mode 100644 test/mp/intern/has_value.cpp create mode 100644 test/mp/mp.cpp create mode 100644 test/mp/operations/compare/equal.cpp create mode 100644 test/mp/operations/compare/less.cpp delete mode 100644 test/mp/util.cpp create mode 100644 test/mp/util/default.cpp create mode 100644 test/mp/util/is_a.cpp create mode 100644 test/mp/util/make.cpp create mode 100644 test/mp/util/tag_of.cpp rename test/mp/{convert.cpp => util/to.cpp} (96%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c8a6c99..829cf6c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,8 +1,9 @@ # Project: cpputils ############################################################################### Project ( cpputils ) -File ( GLOB_RECURSE SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp ) +File ( GLOB_RECURSE SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/impl/*.cpp ) Add_Library ( cpputils STATIC ${SOURCE_FILES} ) +Include_Directories ( ${CMAKE_CURRENT_SOURCE_DIR} ) Target_Include_Directories ( cpputils INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} diff --git a/src/LoggerImpl.cpp b/src/LoggerImpl.cpp deleted file mode 100644 index 2a31cbf..0000000 --- a/src/LoggerImpl.cpp +++ /dev/null @@ -1,257 +0,0 @@ -#include -#include - -#include "cpputils/LoggerImpl.h" - -using namespace logging; - -struct StreamFormatSaver -{ - std::ios state; - std::ostream& stream; - - StreamFormatSaver(std::ostream& s) : - state (nullptr), - stream (s) - { state.copyfmt(stream); } - - ~StreamFormatSaver() - { stream.copyfmt(state); } -}; - - -struct Manager -{ -private: - using LoggerImplPtrU = std::unique_ptr; - - LoggerImpl _defaultLogger; - std::map _logger; - std::list _rules; - std::set _consumer; - - LoggerImpl& initLogger(LoggerImpl& logger) - { - for (auto& rule : _rules) - { - if (rule.loggerMatcher->match(logger)) - logger.registerRule(rule); - } - return logger; - } - -public: - inline Logger& getLogger(const std::string& name) - { - if (name.empty()) - return _defaultLogger; - auto it = _logger.find(name); - return (it != _logger.end() - ? *it->second - : initLogger(*_logger.emplace(name, LoggerImplPtrU(new LoggerImpl(name))).first->second)); - } - - void registerConsumer(Consumer& consumer) - { - _consumer.insert(&consumer); - for (auto& rule : _rules) - { - if (rule.consumerMatcher->match(consumer)) - rule.registerConsumer(consumer); - } - } - - void unregisterConsumer(Consumer& consumer) - { - for (auto& rule : _rules) - rule.unregisterConsumer(consumer); - } - - RuleHandle defineRule(MatcherPtrU loggerMatcher, MatcherPtrU consumerMatcher, Level minLevel, Level maxLevel) - { - _rules.emplace_back(std::move(loggerMatcher), std::move(consumerMatcher), minLevel, maxLevel); - auto& rule = _rules.back(); - for (auto& c : _consumer) - { - if (rule.consumerMatcher->match(*c)) - rule.registerConsumer(*c); - } - if (rule.loggerMatcher->match(_defaultLogger)) - _defaultLogger.registerRule(rule); - for (auto& l : _logger) - { - if (rule.loggerMatcher->match(*l.second)) - l.second->registerRule(rule); - } - return &rule; - } - - void undefineRule(RuleHandle rule) - { - auto r = static_cast(rule); - auto it = _rules.begin(); - while (&*it != r && it != _rules.end()) - ++it; - if (it == _rules.end()) - return; - _defaultLogger.unregisterRule(*it); - for (auto& l : _logger) - l.second->unregisterRule(*it); - _rules.erase(it); - } - - inline void reset() - { - _logger.clear(); - _rules.clear(); - _consumer.clear(); - } - - Manager() : - _defaultLogger(std::string()) - { } -}; - -Manager& manager() -{ - static Manager value; - return value; -} - -std::string EmptyString; - -Consumer::Consumer(const std::string& n, bool autoRegister) : - _name(n) -{ - if (autoRegister) - registerConsumer(*this); -} - -Consumer::~Consumer() - { unregisterConsumer(*this); } - -void StreamConsumer::log(DataPtrS data) -{ - std::lock_guard lk(_mutex); - - using namespace std; - if (!data) - return; - auto& d = *data; - auto t = std::chrono::duration_cast>>(d.time.time_since_epoch()).count(); - auto f = d.file; - if (f) - { - auto tmp = strrchr(f, '/'); - if (tmp) - f = tmp + 1; - } - else - f = "unknown"; - - StreamFormatSaver formatSaver(*_stream); - if (t >= 0) *_stream << "[" << fixed << setfill(' ') << setw(17) << setprecision(6) << t << "] "; - switch(d.level) - { - case Level::Debug: *_stream << "DEBUG "; break; - case Level::Info: *_stream << "INFO "; break; - case Level::Warn: *_stream << "WARN "; break; - case Level::Error: *_stream << "ERROR "; break; - } - - if (d.sender) *_stream << "0x" << hex << setw(2 * sizeof(void*)) << setfill('0') << d.sender; - else *_stream << " "; - if (d.thread != std::thread::id()) *_stream << "@" << hex << setw(2 * sizeof(void*)) << setfill('0') << d.thread; - else *_stream << " "; - if (!d.name.empty()) *_stream << " '" << d.name << "'"; - if (d.line) *_stream << " - " << setw(25) << setfill(' ') << f << ":" << setw(5) << setfill(' ') << dec << d.line; - if (!d.message.empty()) - { - *_stream << ": " << d.message; - if (d.message.back() != '\n') - *_stream << std::endl; - } - else - *_stream << std::endl; -} - - - -bool AllMatcher::match(const Logger& logger) const - { return true; } - -bool AllMatcher::match(const Consumer& consumer) const - { return true; } - -bool RegexMatcher::match(const Logger& logger) const - { return !logger.name().empty() && std::regex_match(logger.name(), _regex) != _invert; } - -bool RegexMatcher::match(const Consumer& consumer) const - { return !consumer.name().empty() && std::regex_match(consumer.name(), _regex) != _invert; } - -bool DefaultLoggerMatcher::match(const Logger& logger) const - { return &_defaultLogger == &logger; } - - - -LogHelper::LogHelper(Logger& logger, DataPtrS data) : - _logger (logger), - _data (data) - { } - -LogHelper::~LogHelper() - { _logger.log(_data); } - - - -const std::string& Logger::name() const - { return EmptyString; } - -bool Logger::isEnabled(Level level) const - { return false; } - -void Logger::log(DataPtrS data) const - { /* no op */ } - - - -const std::string& LoggerImpl::name() const - { return _name; } - -bool LoggerImpl::isEnabled(Level level) const -{ - for (auto& rule : _rules) - { - if (rule->isEnabled(level)) - return true; - } - return false; -} - -void LoggerImpl::log(DataPtrS data) const -{ - std::lock_guard lk(_mutex); - for (auto& r : _rules) - r->log(data); -} - -namespace logging -{ - Logger& getLogger(const std::string& name) - { return manager().getLogger(name); } - - void registerConsumer(Consumer& consumer) - { return manager().registerConsumer(consumer); } - - void unregisterConsumer(Consumer& consumer) - { return manager().unregisterConsumer(consumer); } - - RuleHandle defineRule(MatcherPtrU loggerMatcher, MatcherPtrU consumerMatcher, Level minLevel, Level maxLevel) - { return manager().defineRule(std::move(loggerMatcher), std::move(consumerMatcher), minLevel, maxLevel); } - - void undefineRule(RuleHandle rule) - { return manager().undefineRule(rule); } - - void resetLogging() - { manager().reset(); } -} \ No newline at end of file diff --git a/src/cpputils/Exception.h b/src/cpputils/Exception.h deleted file mode 100644 index 295c252..0000000 --- a/src/cpputils/Exception.h +++ /dev/null @@ -1,167 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -#include "Flags.h" - -namespace utl -{ - - struct Exception : public std::exception - { - public: - enum class PrintFlag - { - ResolveAddress, - }; - using PrintFlags = ShiftedFlags; - - public: - static constexpr size_t StackSize = 15; - static const PrintFlags& defaultPrintFlags() - { - static const PrintFlags value({ PrintFlag::ResolveAddress }); - return value; - }; - - private: - mutable bool _msgCacheEmpty; - mutable std::string _msgCache; - - protected: - virtual void printMessage(std::ostream& os) const - { - os << message; - } - - public: - std::string message; - void* stack[StackSize]; - int stackSize; - - public: - void print(std::ostream& os, const PrintFlags& flags = defaultPrintFlags()) const - { - printMessage(os); - os << std::endl; - char** lines = nullptr; - if (flags.isSet(PrintFlag::ResolveAddress)) - lines = backtrace_symbols(stack, stackSize); - for (int i = 0; i < stackSize; ++i) - { - os << " [0x" << std::setw(2 * sizeof(void*)) << std::setfill('0') << std::hex << reinterpret_cast(stack[i]) << "]"; - if (lines && lines[i]) - os << " " << lines[i]; - os << std::endl; - } - } - - std::string print(const PrintFlags& flags = defaultPrintFlags()) const - { - std::ostringstream os; - print(os, flags); - return os.str(); - } - - const char* what() const throw() override - { - if (_msgCacheEmpty) - { - _msgCache = print(); - _msgCacheEmpty = false; - } - return _msgCache.c_str(); - } - - inline friend std::ostream& operator <<(std::ostream& os, const Exception& ex) - { - ex.print(os); - return os; - } - - public: - Exception() : - Exception("") - { } - - Exception(std::string msg) : - message (msg), - _msgCacheEmpty (true) - { - stackSize = backtrace(stack, StackSize); - } - }; - - struct ErrorException : public Exception - { - public: - int error; - - ErrorException(int e) : - Exception(std::to_string(e) + " - " + strerror(e)), - error(e) - { } - - ErrorException(const std::string& msg, int e) : - Exception(msg + ": " + std::to_string(e) + " - " + strerror(e)), - error(e) - { } - }; - - struct EOutOfRange : public Exception - { - protected: - void printMessage(std::ostream& os) const override - { - os << "index out of range (min=" << min << "; max=" << max << "; index=" << index << ")"; - if (!message.empty()) - os << " - " << message; - } - - public: - size_t min; - size_t max; - size_t index; - - EOutOfRange(size_t mi, size_t ma, size_t idx, std::string msg = "") : - Exception (msg), - min (mi), - max (ma), - index (idx) - { } - }; - - struct EArgument : public Exception - { - protected: - void printMessage(std::ostream& os) const override - { - os << "invalid argument"; - if (!argument.empty()) - os << "(" << argument << ")"; - if (!message.empty()) - os << " - " << message; - } - - public: - std::string argument; - - EArgument(std::string arg, std::string msg) : - Exception (message), - argument (arg) - { } - }; - - struct EInvalidOperation : public Exception - { - public: - EInvalidOperation(std::string msg) : - Exception(msg) - { } - }; - -} \ No newline at end of file diff --git a/src/cpputils/HandleManager.h b/src/cpputils/HandleManager.h deleted file mode 100644 index 21ea255..0000000 --- a/src/cpputils/HandleManager.h +++ /dev/null @@ -1,1004 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#include "./Misc.h" -#include "./Exception.h" - -namespace utl -{ - struct Handle - { - uint64_t value; - - inline explicit operator bool () const; - inline operator uint64_t() const; - inline Handle& operator = (uint64_t); - inline Handle& operator = (const Handle&); - - inline bool operator == (const Handle&) const; - inline bool operator != (const Handle&) const; - inline bool operator <= (const Handle&) const; - inline bool operator >= (const Handle&) const; - inline bool operator < (const Handle&) const; - inline bool operator > (const Handle&) const; - - inline bool operator == (const uint64_t&) const; - inline bool operator != (const uint64_t&) const; - inline bool operator <= (const uint64_t&) const; - inline bool operator >= (const uint64_t&) const; - inline bool operator < (const uint64_t&) const; - inline bool operator > (const uint64_t&) const; - - inline std::string toString () const; - - inline Handle(); - inline Handle(const uint64_t&); - inline Handle(const Handle&); - - static inline bool fromString(const std::string& str, Handle& handle); - static inline const Handle& empty(); - }; - - using TypeId = uint8_t; - using SystemId = uint8_t; - - namespace __impl - { - using Index = size_t; - using InternIndex = ssize_t; - - static constexpr InternIndex INVALID_INDEX = -1; - static constexpr size_t GROW_SIZE = 100; - - enum class EntryStatus - { - Unknown, - Used, - Free, - }; - - #pragma pack(push, 1) - struct HandleData - { - SystemId systemId; // 0..7 system id (to manage handles for multiple (dedicated) subsystems) - TypeId typeId; // 8..15 type id (defined by user) - uint16_t counter; // 16..31 reusage counter - uint32_t entryIndex; // 32..64 index in data array (unique for each system) - }; - #pragma pack(pop) - static_assert(sizeof(Handle) == sizeof(HandleData), "mismatching size of Handle and HandleData"); - static_assert(sizeof(Handle) == 8, "size of Handle is not equal 64"); - - inline HandleData makeHandleData(const Handle& handle); - inline Handle makeHandle (HandleData hd); - - template - struct System; - - template - struct Entry - { - public: - using value_type = TValue; - using this_type = Entry; - using wrapper_type = wrapper; - - private: - InternIndex _next; - InternIndex _prev; - uint16_t _counter; - EntryStatus _status; - TypeId _typeId; - wrapper_type _data; - - public: - inline InternIndex next () const; - inline void next (InternIndex value); - inline InternIndex prev () const; - inline void prev (InternIndex value); - inline EntryStatus status () const; - inline void link (InternIndex prev, InternIndex next, EntryStatus status); - inline void unlink (); - inline uint16_t counter () const; - inline void assign (value_type value, const TypeId& tId, const uint16_t cntr = 0); - inline value_type data (); - inline void data (value_type v); - - inline Entry(); - inline Entry(Entry&&); - inline Entry(const Entry&); - }; - - template - struct System - { - public: - using entry_type = TEntry; - using this_type = System; - using entry_vector_type = std::vector; - - private: - InternIndex _firstFree; - InternIndex _lastFree; - InternIndex _firstUsed; - InternIndex _lastUsed; - entry_vector_type _entries; - - inline void pushFront (Index index, InternIndex& first, InternIndex& last, EntryStatus status); - inline void pushBack (Index index, InternIndex& first, InternIndex& last, EntryStatus status); - inline Index popFront (bool canGrow, InternIndex& first, InternIndex& last, EntryStatus status); - inline Index popBack (bool canGrow, InternIndex& first, InternIndex& last, EntryStatus status); - inline void remove (Index index, InternIndex& first, InternIndex& last, EntryStatus status); - - public: - inline void grow (size_t size = 0); - inline void pushFrontFree (Index index); - inline void pushFrontUsed (Index index); - inline void pushBackFree (Index index); - inline void pushBackUsed (Index index); - inline Index popFrontFree (); - inline Index popFrontUsed (); - inline Index popBackFree (); - inline Index popBackUsed (); - inline void removeFree (Index index); - inline void removeUsed (Index index); - inline size_t size () const; - - inline entry_type& operator[] (const Index& index); - inline const entry_type& operator[] (const Index& index) const; - - inline System(); - inline System(System&&); - inline System(const System&&); - }; - - template - struct Systems - { - public: - using entry_type = TEntry; - using this_type = System; - using system_type = System; - using system_vector_type = std::vector; - - private: - system_vector_type _systems; - - public: - inline system_type& operator[] (const Index& index); - inline const system_type& operator[] (const Index& index) const; - inline size_t size () const; - inline void clear (); - }; - } - - inline TypeId getTypeId(const Handle& handle) - { return __impl::makeHandleData(handle).typeId; } - - inline SystemId getSystemId(const Handle& handle) - { return __impl::makeHandleData(handle).systemId; } - - template - class HandleManager - { - public: - using value_type = T; - using this_type = HandleManager; - using entry_type = __impl::Entry; - using systems_type = __impl::Systems; - - private: - systems_type _systems; - - public: - /** check if an given handle is valid - * @param handle handle to check - * @return TRUE if handle is valid, FALSE otherwise */ - inline bool isValid(const Handle& handle) const; - - /** try to get the value for a given handle - * @param handle handle to get value for - * @param value parameter to store value at - * @return TRUE on success, FALSE otherwise */ - inline bool tryGet(const Handle& handle, value_type& value); - - /** get the value for a given handle - * @param handle handle to get value for - * @return valid stored for handle */ - inline value_type get(const Handle& handle); - - /** update the value of a given handle (only valid handles are accepted) - * @param handle handle to update value for - * @param value new value to store - * @return TRUE on success, FALSE otherwise (invalid handle) */ - inline bool update(const Handle& handle, value_type value); - - /** set the value for a given handle (this will add the item to the manager if the handle is unknown) - * @param handle handle to set value for - * @param value value to store - * @return TRUE on success, FALSE otherwise (the storage entry is used by an other value) */ - inline bool set(const Handle& handle, value_type value); - - /** insert a new value to the manager - * @param tId type id of the value - * @param sId system id of the value - * @param value value to add - * @return Handle of the stored value */ - inline Handle insert(const TypeId& tId, const SystemId& sId, value_type value); - - /** remove the value of a given handle - * @param handle handle to remove value for - * @return TRUE on success, FALSE otherwise (handle is invalid) */ - inline bool remove(const Handle& handle); - - /** access values by a given handle - * @param handle handle to get value for - * @return reference to the value */ - inline value_type& operator[](const Handle& handle); - - /** remove all stored valus and reset the handle manager completely */ - inline void clear(); - }; -} - -/* HELPER ****************************************************************************************/ - -inline -utl::Handle::operator bool() const - { return static_cast(value); } - -inline -utl::Handle::operator uint64_t() const - { return value; } - -inline utl::Handle& -utl::Handle::operator =(uint64_t v) -{ - value = v; - return *this; -} - -inline utl::Handle& -utl::Handle::operator =(const Handle& other) -{ - value = other.value; - return *this; -} - -inline bool -utl::Handle::operator ==(const Handle& other) const - { return value == other.value; } - -inline bool -utl::Handle::operator !=(const Handle& other) const - { return value != other.value; } - -inline bool -utl::Handle::operator <=(const Handle& other) const - { return value <= other.value; } - -inline bool -utl::Handle::operator >=(const Handle& other) const - { return value >= other.value; } - -inline bool -utl::Handle::operator <(const Handle& other) const - { return value < other.value; } - -inline bool -utl::Handle::operator >(const Handle& other) const - { return value > other.value; } - -inline bool -utl::Handle::operator ==(const uint64_t& other) const - { return value == other; } - -inline bool -utl::Handle::operator !=(const uint64_t& other) const - { return value != other; } - -inline bool -utl::Handle::operator <=(const uint64_t& other) const - { return value <= other; } - -inline bool -utl::Handle::operator >=(const uint64_t& other) const - { return value >= other; } - -inline bool -utl::Handle::operator <(const uint64_t& other) const - { return value < other; } - -inline bool -utl::Handle::operator >(const uint64_t& other) const - { return value > other; } - -inline std::string -utl::Handle::toString() const -{ - char buffer[2*sizeof(*this)+3]; - memset(&buffer[0], 0, sizeof(buffer)); - const uint8_t *p = reinterpret_cast(this); - int x = 0; - for (size_t i = 0; i < sizeof(*this); ++i) - { - if (i == 1 || i == 2 || i == 4) - { - buffer[2*i+x] = '-'; - ++x; - } - buffer[2*i+x] = static_cast((p[i] >> 4) & 0x0F); - buffer[2*i+x+1] = static_cast((p[i] >> 0) & 0x0F); - buffer[2*i+x] = static_cast(buffer[2*i+x] + (buffer[2*i+x] > 9 ? 'A' - 10 : '0')); - buffer[2*i+x+1] = static_cast(buffer[2*i+x+1] + (buffer[2*i+x+1] > 9 ? 'A' - 10 : '0')); - } - return std::string(&buffer[0], sizeof(buffer)); -} - -inline utl::Handle::Handle() : - value(0) - { } - -inline utl::Handle::Handle(const uint64_t& v) : - value(v) - { } - -inline utl::Handle::Handle(const Handle& other) : - value(other.value) - { } - -inline bool -utl::Handle::fromString(const std::string& str, Handle& handle) -{ - memset(&handle, 0, sizeof(handle)); - const char *c = str.c_str(); - const char *e = c + str.size(); - uint8_t* p = reinterpret_cast(&handle); - size_t i = 0; - while(c < e && i < 2*sizeof(handle)) - { - if (*c != '-') - { - uint8_t v; - if (*c >= '0' && *c <= '9') - v = static_cast(*c - '0'); - else if (*c >= 'a' && *c <= 'f') - v = static_cast(*c - 'a'); - else if (*c >= 'A' && *c <= 'F') - v = static_cast(*c - 'A'); - else - return false; - if (i & 1) - v = static_cast(v << 4); - p[i >> 1] |= v; - ++i; - } - ++c; - } - return (c == e && i == 2*sizeof(handle)); -} - -inline const utl::Handle& -utl::Handle::empty() -{ - static const Handle value; - return value; -} - -inline utl::__impl::HandleData utl::__impl::makeHandleData(const Handle& handle) -{ - HandleData hd = reinterpret_cast(handle); - hd.systemId = ntoh(hd.systemId); - hd.typeId = ntoh(hd.typeId); - hd.counter = ntoh(hd.counter); - hd.entryIndex = ntoh(hd.entryIndex); - return hd; -} - -inline utl::Handle utl::__impl::makeHandle(HandleData hd) -{ - hd.systemId = hton(hd.systemId); - hd.typeId = hton(hd.typeId); - hd.counter = hton(hd.counter); - hd.entryIndex = hton(hd.entryIndex); - return reinterpret_cast(hd); -} - -/* ENTRY *****************************************************************************************/ - -template -inline utl::__impl::InternIndex -utl::__impl::Entry::next() const -{ - return _next; -} - -template -inline void -utl::__impl::Entry::next( - InternIndex value) -{ - _next = value; -} - -template -inline utl::__impl::InternIndex -utl::__impl::Entry::prev() const -{ - return _prev; -} - -template -inline void -utl::__impl::Entry::prev( - InternIndex value) -{ - _prev = value; -} - -template -inline utl::__impl::EntryStatus -utl::__impl::Entry::status() const -{ - return _status; -} - -template -inline void -utl::__impl::Entry::link(InternIndex prev, InternIndex next, EntryStatus status) -{ - assert(status != EntryStatus::Unknown); - _prev = prev; - _next = next; - _status = status; -} - -template -inline void -utl::__impl::Entry::unlink() -{ - _prev = INVALID_INDEX; - _next = INVALID_INDEX; - _status = EntryStatus::Unknown; -} - -template -inline uint16_t -utl::__impl::Entry::counter() const - { return _counter; } - -template -inline void -utl::__impl::Entry::assign( - value_type value, - const TypeId& tId, - const uint16_t cntr) -{ - using namespace ::utl; - using namespace ::utl::__impl; - assert(_status == EntryStatus::Used); - _typeId = tId; - _data = value; - if (cntr != 0) - _counter = cntr; - else if (++_counter == 0) - _counter = 1; -} - -template -inline typename utl::__impl::Entry::value_type -utl::__impl::Entry::data() -{ - return *_data; -} - -template -inline void -utl::__impl::Entry::data( - value_type v) -{ - _data = v; -} - -template -inline utl::__impl::Entry::Entry() : - _next (INVALID_INDEX), - _prev (INVALID_INDEX), - _counter(0), - _status (EntryStatus::Unknown), - _typeId (0) - { } - -template -inline utl::__impl::Entry::Entry(Entry&& other) : - _next (std::move(other)._next), - _prev (std::move(other)._prev), - _counter(std::move(other)._counter), - _status (std::move(other)._status), - _typeId (std::move(other)._typeId), - _data (std::move(other)._data) - { } - -template -inline utl::__impl::Entry::Entry(const Entry& other) : - _next (other._next), - _prev (other._prev), - _counter(other._counter), - _status (other._status), - _typeId (other._typeId), - _data (other._data) - { } - -/* SYSTEM ****************************************************************************************/ - -template -inline void -utl::__impl::System::pushFront( - Index index, - InternIndex& first, - InternIndex& last, - EntryStatus status) -{ - assert(index < _entries.size()); - auto& entry = _entries[index]; - assert(entry.status() == EntryStatus::Unknown); - if (first != INVALID_INDEX) - { - assert(first >= 0); - assert(first < _entries.size()); - auto& firstEntry = _entries[first]; - assert(firstEntry.status() == status); - firstEntry.prev(index); - } - entry.link(INVALID_INDEX, first, status); - first = index; - if (last == INVALID_INDEX) - last = index; -} - -template -inline void -utl::__impl::System::pushBack( - Index index, - InternIndex& first, - InternIndex& last, - EntryStatus status) -{ - assert(index < _entries.size()); - auto& entry = _entries[index]; - assert(entry.status() == EntryStatus::Unknown); - if (last != INVALID_INDEX) - { - assert(last >= 0); - assert(last < _entries.size()); - auto& lastEntry = _entries[last]; - assert(lastEntry.status() == status); - lastEntry.next(index); - } - entry.link(last, INVALID_INDEX, status); - last = index; - if (first == INVALID_INDEX) - first = index; -} - -template -inline utl::__impl::Index -utl::__impl::System::popFront( - bool canGrow, - InternIndex& first, - InternIndex& last, - EntryStatus status) -{ - if ( canGrow - && ( first >= static_cast(_entries.size()) - || first == INVALID_INDEX)) - grow(first + GROW_SIZE); - assert(first >= 0); - assert(first < _entries.size()); - auto& entry = _entries[first]; - assert(entry.status() == status); - Index ret = first; - if (last == first) - last = entry.next(); - first = entry.next(); - entry.unlink(); - if (first != INVALID_INDEX) - { - assert(first >= 0); - assert(first < _entries.size()); - auto& firstEntry = _entries[first]; - assert(firstEntry.status() == status); - firstEntry.prev(INVALID_INDEX); - } - return ret; -} - -template -inline utl::__impl::Index -utl::__impl::System::popBack( - bool canGrow, - InternIndex& first, - InternIndex& last, - EntryStatus status) -{ - if ( canGrow - && last >= _entries.size()) - grow(last + GROW_SIZE); - assert(last >= 0); - assert(last < _entries.size()); - auto& entry = _entries[last]; - assert(entry.status() == status); - Index ret = last; - if (first == last) - first = entry._prev; - last = entry._prev; - entry.unlink(); - if (last != INVALID_INDEX) - { - assert(last >= 0); - assert(last < _entries.size()); - auto& lastEntry = _entries[last]; - assert(lastEntry.status() == status); - lastEntry.next(INVALID_INDEX); - } - return ret; -} - -template -inline void -utl::__impl::System::remove( - Index index, - InternIndex& first, - InternIndex& last, - EntryStatus status) -{ - assert(index >= 0); - assert(index < _entries.size()); - auto& entry = _entries[index]; - assert(entry.status() == status); - if (entry.prev() != INVALID_INDEX) - { - assert(entry.prev() >= 0); - assert(entry.prev() < _entries.size()); - _entries[entry.prev()].next(entry.next()); - } - if (entry.next() != INVALID_INDEX) - { - assert(entry.next() >= 0); - assert(entry.next() < _entries.size()); - _entries[entry.next()].prev(entry.prev()); - } - if (first == static_cast(index)) - first = entry.next(); - if (last == static_cast(index)) - last = entry.prev(); - entry.unlink(); -} - -template -inline void -utl::__impl::System::grow( - size_t size) -{ - if (size == 0) - size = _entries.size() + GROW_SIZE; - if (size < _entries.size()) - return; - size_t idx = _entries.size(); - _entries.resize(size); - while (idx < _entries.size()) - { - pushBackFree(idx); - ++idx; - } -} - -template -inline void -utl::__impl::System::pushFrontFree( - Index index) -{ - pushFront(index, _firstFree, _lastFree, EntryStatus::Free); -} - -template -inline void -utl::__impl::System::pushFrontUsed( - Index index) -{ - pushFront(index, _firstUsed, _lastUsed, EntryStatus::Used); -} - -template -inline void -utl::__impl::System::pushBackFree( - Index index) -{ - pushBack(index, _firstFree, _lastFree, EntryStatus::Free); -} - -template -inline void -utl::__impl::System::pushBackUsed( - Index index) -{ - pushBack(index, _firstUsed, _lastUsed, EntryStatus::Used); -} - -template -inline utl::__impl::Index -utl::__impl::System::popFrontFree() -{ - return popFront(true, _firstFree, _lastFree, EntryStatus::Free); -} - -template -inline utl::__impl::Index -utl::__impl::System::popFrontUsed() -{ - return popFront(false, _firstUsed, _lastUsed, EntryStatus::Used); -} - -template -inline utl::__impl::Index -utl::__impl::System::popBackFree() -{ - return popBack(true, _firstFree, _lastFree, EntryStatus::Free); -} - -template -inline utl::__impl::Index -utl::__impl::System::popBackUsed() -{ - return popBack(false, _firstUsed, _lastUsed, EntryStatus::Used); -} - -template -inline void -utl::__impl::System::removeFree( - Index index) -{ - remove(index, _firstFree, _lastFree, EntryStatus::Free); -} - -template -inline void -utl::__impl::System::removeUsed( - Index index) -{ - remove(index, _firstUsed, _lastUsed, EntryStatus::Used); -} - -template -inline size_t -utl::__impl::System::size() const -{ - return _entries.size(); -} - - -template -inline typename utl::__impl::System::entry_type& -utl::__impl::System::operator[]( - const Index& index) -{ - if (index >= _entries.size()) - grow(index + GROW_SIZE); - return _entries[index]; -} - -template -inline const typename utl::__impl::System::entry_type& -utl::__impl::System::operator[]( - const Index& index) const -{ - return _entries.at(index); -} - -template -inline utl::__impl::System::System() : - _firstFree (INVALID_INDEX), - _lastFree (INVALID_INDEX), - _firstUsed (INVALID_INDEX), - _lastUsed (INVALID_INDEX) - { } - -template -inline utl::__impl::System::System(System&& other) : - _firstFree (std::move(other)._firstFree), - _lastFree (std::move(other)._lastFree), - _firstUsed (std::move(other)._firstUsed), - _lastUsed (std::move(other)._lastUsed), - _entries (std::move(other)._entries) - { } - -template -inline utl::__impl::System::System(const System&& other) : - _firstFree (other._firstFree), - _lastFree (other._lastFree), - _firstUsed (other._firstUsed), - _lastUsed (other._lastUsed), - _entries (other._entries) - { } - -/* SYSTEMS ***************************************************************************************/ - -template -inline typename utl::__impl::Systems::system_type& -utl::__impl::Systems::operator[]( - const Index& index) -{ - if (index >= _systems.size()) - _systems.resize(index + 1); - return _systems[index]; -} - -template -inline const typename utl::__impl::Systems::system_type& -utl::__impl::Systems::operator[]( - const Index& index) const -{ - return _systems[index]; -} - -template -inline size_t -utl::__impl::Systems::size() const -{ - return _systems.size(); -} - -template -inline void -utl::__impl::Systems::clear() -{ - _systems.clear(); -} - -/* HANDLEMANAGER *********************************************************************************/ - -template -inline bool -utl::HandleManager::isValid( - const utl::Handle& handle) const -{ - using namespace __impl; - auto hd = makeHandleData(handle); - if (hd.systemId >= _systems.size()) - return false; - auto& system = _systems[hd.systemId]; - if (hd.entryIndex >= system.size()) - return false; - auto& entry = system[hd.entryIndex]; - return entry.status() == EntryStatus::Used - && entry.counter() == hd.counter; -} - -template -inline bool -utl::HandleManager::tryGet( - const utl::Handle& handle, - typename utl::HandleManager::value_type& value) -{ - using namespace __impl; - auto ret = isValid(handle); - if (ret) - { - auto hd = makeHandleData(handle); - value = _systems[hd.systemId][hd.entryIndex].data(); - } - return ret; -} - -template -inline typename utl::HandleManager::value_type -utl::HandleManager::get( - const utl::Handle& handle) -{ - value_type ret; - if (!tryGet(handle, ret)) - throw Exception("invalid handle"); - return ret; -} - -template -inline bool -utl::HandleManager::update( - const utl::Handle& handle, - typename utl::HandleManager::value_type value) -{ - using namespace __impl; - if (isValid(handle)) - { - auto hd = makeHandleData(handle); - _systems[hd.systemId][hd.entryIndex].data(value); - return true; - } - return false; -} - -template -inline bool -utl::HandleManager::set( - const utl::Handle& handle, - typename utl::HandleManager::value_type value) -{ - using namespace __impl; - if (!isValid(handle)) - { - auto hd = makeHandleData(handle); - auto& system = _systems[hd.systemId]; - auto& entry = system[hd.entryIndex]; - bool ret = entry.status() == EntryStatus::Free; - if (ret) - { - system.removeFree (hd.entryIndex); - system.pushBackUsed(hd.entryIndex); - entry.assign(value, hd.typeId, hd.counter); - } - return ret; - } - else - { - return update(handle, value); - } -} - -template -inline utl::Handle -utl::HandleManager::insert( - const TypeId& tId, - const SystemId& sId, - typename utl::HandleManager::value_type value) -{ - using namespace __impl; - auto& system = _systems[sId]; - auto index = system.popFrontFree(); - system.pushBackUsed(index); - auto& entry = system[index]; - entry.assign(value, tId); - HandleData hd; - hd.entryIndex = static_cast(index); - hd.counter = entry.counter(); - hd.typeId = tId, - hd.systemId = sId; - return makeHandle(hd); -} - -template -inline bool -utl::HandleManager::remove( - const utl::Handle& handle) -{ - using namespace __impl; - if (!isValid(handle)) - return false; - auto hd = makeHandleData(handle); - auto& system = _systems[hd.systemId]; - system.removeUsed(hd.entryIndex); - system.pushFrontFree(hd.entryIndex); - return true; -} - -template -inline typename utl::HandleManager::value_type& -utl::HandleManager::operator[]( - const utl::Handle& handle) -{ - using namespace __impl; - if (!isValid(handle)) - throw Exception("invalid handle"); - auto hd = makeHandleData(handle); - auto& system = _systems[hd.systemId]; - auto& entry = system[hd.entryIndex]; - return entry.data; -} - -template -inline void -utl::HandleManager::clear() - { _systems.clear(); } diff --git a/src/cpputils/Logger.h b/src/cpputils/Logger.h deleted file mode 100644 index fe42532..0000000 --- a/src/cpputils/Logger.h +++ /dev/null @@ -1,187 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#include "Exception.h" - -// () mandatory -// [] optional -// (logger), (LogLevel: Debug|Info|Warn|Error), [Sender], [Message, [Arguments]] -#define logMessage(logger, level, ...) \ - if (logger.isEnabled(logging::Level::level)) \ - logger.makeLogHelper(logging::Level::level, __FILE__, __LINE__, ## __VA_ARGS__ ) = logging::LogMessage() - -// () mandatory -// [] optional -// (LogLevel: Debug|Info|Warn|Error), [Sender], [Message, [Arguments]] -#define logGlobalMessage(level, ...) \ - if (logging::isEnabled(logging::Level::level)) \ - logging::makeLogHelper(logging::Level::level, __FILE__, __LINE__, ## __VA_ARGS__ ) = logging::LogMessage() - - -namespace logging -{ - - enum class Level - { - Debug = 0, - Info, - Warn, - Error, - }; - - struct Data - { - Level level; - std::chrono::steady_clock::time_point time; - void* sender; - std::thread::id thread; - const char* file; - int line; - std::string name; - std::string message; - }; - using DataPtrS = std::shared_ptr; - - struct Logger; - - struct LogMessage - { - private: - std::ostringstream _msg; - - public: - inline std::string str() const - { return _msg.str(); } - - template - inline LogMessage& operator <<(const T& value) - { - _msg << value; - return *this; - } - - inline LogMessage& operator <<(std::ostream& (*callback)(std::ostream&)) - { - callback(_msg); - return *this; - } - - LogMessage() : - _msg() - { } - - LogMessage(const std::string& msg) : - _msg(msg) - { } - - private: - LogMessage(const LogMessage&) = delete; - LogMessage(LogMessage&&) = delete; - }; - - struct LogHelper - { - private: - Logger& _logger; - DataPtrS _data; - - public: - inline void operator=(const LogMessage& msg) - { _data->message += msg.str(); } - - LogHelper(Logger& logger, DataPtrS data); - ~LogHelper(); - }; - - struct Logger - { - private: - Logger(const Logger&) = delete; - Logger(Logger&&) = delete; - - public: - Logger() { } - - virtual const std::string& name() const; - virtual bool isEnabled(Level level) const; - virtual void log(DataPtrS data) const; - - template - inline LogHelper makeLogHelper(Level level, const char* file, int line, Sender* sender, std::string message) - { return makeLogHelper(level, file, line, static_cast(sender), message); } - - template - inline LogHelper makeLogHelper(Level level, const char* file, int line, Sender* sender) - { return makeLogHelper(level, file, line, static_cast(sender), std::string()); } - - inline LogHelper makeLogHelper(Level level, const char* file, int line, std::string message) - { return makeLogHelper(level, file, line, nullptr, message); } - - inline LogHelper makeLogHelper(Level level, const char* file, int line) - { return makeLogHelper(level, file, line, nullptr, std::string()); } - - template - inline LogHelper makeLogHelper(Level level, const char* file, int line, Sender* sender, std::string message, Args... args) - { - std::unique_ptr buff(static_cast(malloc(0x8000)), &free); - auto len = snprintf(buff.get(), 10240, message.c_str(), args...); - if (len < 0) - throw utl::ErrorException(errno); - return makeLogHelper(level, file, line, sender, std::string(buff.get(), len)); - } - - template - inline LogHelper makeLogHelper(Level level, const char* file, int line, std::string message, Args... args) - { return makeLogHelper(level, file, line, nullptr, message, args...); } - - }; - - template<> - inline LogHelper Logger::makeLogHelper(Level level, const char* file, int line, void* sender, std::string message) - { - DataPtrS data(new Data()); - data->level = level; - data->time = std::chrono::steady_clock::now(); - data->thread = std::this_thread::get_id(); - data->file = file; - data->line = line; - data->sender = sender; - data->name = name(); - data->message = message; - return LogHelper(*this, data); - } - - Logger& getLogger(const std::string& name = ""); - - inline bool isEnabled(Level level) - { return getLogger().isEnabled(level); } - - template - inline LogHelper makeLogHelper(Level level, const char* file, int line, Sender* sender, std::string message) - { return getLogger().makeLogHelper(level, file, line, sender, message); } - - template - inline LogHelper makeLogHelper(Level level, const char* file, int line, Sender* sender) - { return getLogger().makeLogHelper(level, file, line, sender, std::string()); } - - inline LogHelper makeLogHelper(Level level, const char* file, int line, std::string message) - { return getLogger().makeLogHelper(level, file, line, nullptr, message); } - - inline LogHelper makeLogHelper(Level level, const char* file, int line) - { return getLogger().makeLogHelper(level, file, line, nullptr, std::string()); } - - template - inline LogHelper makeLogHelper(Level level, const char* file, int line, Sender* sender, std::string message, Args... args) - { return getLogger().makeLogHelper(level, file, line, sender, message, args...); } - - template - inline LogHelper makeLogHelper(Level level, const char* file, int line, std::string message, Args... args) - { return getLogger().makeLogHelper(level, file, line, nullptr, message, args...); } - - void resetLogging(); - -} diff --git a/src/cpputils/LoggerImpl.h b/src/cpputils/LoggerImpl.h deleted file mode 100644 index 4771218..0000000 --- a/src/cpputils/LoggerImpl.h +++ /dev/null @@ -1,189 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -#include "Logger.h" - -namespace logging -{ - - struct Consumer - { - private: - std::string _name; - - public: - virtual void log(DataPtrS data) = 0; - - inline const std::string& name() const - { return _name; } - - Consumer(const std::string& n, bool autoRegister); - ~Consumer(); - }; - - struct StreamConsumer : public Consumer - { - private: - mutable std::mutex _mutex; - std::ostream* _stream; - bool _ownsStream; - - public: - void log(DataPtrS data) override; - - StreamConsumer(const std::string& name, std::ostream& stream, bool ownsStream, bool autoRegister) : - Consumer (name, autoRegister), - _stream (&stream), - _ownsStream (ownsStream) - { } - - virtual ~StreamConsumer() - { - if (_ownsStream && _stream) - { - delete _stream; - _stream = nullptr; - } - } - }; - - - - struct Matcher - { - virtual bool match(const Logger& logger) const - { return false; } - - virtual bool match(const Consumer& consumer) const - { return false; } - }; - - struct AllMatcher : public Matcher - { - bool match(const Logger& logger) const override; - bool match(const Consumer& consumer) const override; - }; - - struct RegexMatcher : public Matcher - { - private: - std::regex _regex; - bool _invert; - - public: - bool match(const Logger& logger) const override; - bool match(const Consumer& consumer) const override; - - RegexMatcher(const std::string expression, bool invert = false) : - _regex (expression), - _invert (invert) - { } - }; - - struct DefaultLoggerMatcher : public Matcher - { - private: - Logger& _defaultLogger; - - public: - using Matcher::match; - bool match(const Logger& logger) const override; - - DefaultLoggerMatcher() : - _defaultLogger(getLogger(std::string())) - { } - }; - - using RuleHandle = void*; - using MatcherPtrU = std::unique_ptr; - - struct Rule - { - private: - mutable std::mutex _mutex; - std::set _consumer; - - public: - MatcherPtrU loggerMatcher; - MatcherPtrU consumerMatcher; - Level minLevel; - Level maxLevel; - - inline bool isEnabled(Level level) const - { - return minLevel <= level - && maxLevel >= level; - } - - inline void registerConsumer(Consumer& consumer) - { - std::lock_guard lk(_mutex); - _consumer.insert(&consumer); - } - - inline void unregisterConsumer(Consumer& consumer) - { - std::lock_guard lk(_mutex); - _consumer.erase(&consumer); - } - - inline void log(DataPtrS data) - { - std::lock_guard lk(_mutex); - if (isEnabled(data->level)) - { - for (auto& c : _consumer) - c->log(data); - } - } - - Rule(MatcherPtrU lm, MatcherPtrU cm, Level min, Level max) : - loggerMatcher (std::move(lm)), - consumerMatcher(std::move(cm)), - minLevel (min), - maxLevel (max) - { } - }; - - - struct LoggerImpl : public Logger - { - private: - mutable std::mutex _mutex; - std::string _name; - std::set _rules; - - public: - const std::string& name() const override; - bool isEnabled(Level level) const override; - void log(DataPtrS data) const override; - - inline void registerRule(Rule& rule) - { - std::lock_guard lk(_mutex); - _rules.insert(&rule); - } - - inline void unregisterRule(Rule& rule) - { - std::lock_guard lk(_mutex); - _rules.erase(&rule); - } - - LoggerImpl(const std::string& n) : - _name(n) - { } - }; - - void registerConsumer (Consumer& consumer); - void unregisterConsumer(Consumer& consumer); - - RuleHandle defineRule(MatcherPtrU loggerMatcher, MatcherPtrU consumerMatcher, Level minLevel = Level::Debug, Level maxLevel = Level::Error); - void undefineRule(RuleHandle handle); - -} \ No newline at end of file diff --git a/src/cpputils/Misc.h b/src/cpputils/Misc.h deleted file mode 100644 index 00599b5..0000000 --- a/src/cpputils/Misc.h +++ /dev/null @@ -1,237 +0,0 @@ -#pragma once - -#include -#include - -#if defined(__linux__) -# include -#elif defined(__FreeBSD__) || defined(__NetBSD__) -# include -#elif defined(__OpenBSD__) -# include -# define be16toh(x) betoh16(x) -# define be32toh(x) betoh32(x) -# define be64toh(x) betoh64(x) -#endif - -namespace utl -{ - - /* TypeHelper ********************************************************************************/ - template - struct TypeHelper - { - public: - static inline std::string name() - { - int status; - auto name = abi::__cxa_demangle(typeid(T).name(), 0, 0, &status); - return std::string(name ? name : typeid(T).name()); - } - }; - - /* simple class that stores a value of type T */ - template - struct wrapper - { - using value_type = T; - - value_type value; - - inline value_type& operator*() - { return value; } - - inline const value_type& operator*() const - { return value; } - - inline wrapper& operator=(const value_type v) - { - value = v; - return *this; - } - - inline wrapper& operator=(const wrapper& other) - { - value = other.value; - return *this; - } - - inline wrapper& operator=(wrapper&& other) - { - value = std::move(other).value; - return *this; - } - - inline wrapper() : - value(value_type()) - { } - - inline wrapper(const value_type& v) : - value(v) - { } - - inline wrapper(const wrapper& other) : - value(other.value) - { } - - inline wrapper(wrapper&& other) : - value(std::move(other.value)) - { } - }; - - template - struct wrapper - { - using value_type = T&; - using storage_type = T*; - - storage_type value; - - inline value_type operator*() const - { - assert(value != nullptr); - return *value; - } - - inline wrapper& operator=(const value_type v) - { - value = &v; - return *this; - } - - inline wrapper& operator=(const wrapper& other) - { - value = other.value; - return *this; - } - - inline wrapper& operator=(wrapper&& other) - { - value = std::move(other.value); - return *this; - } - - inline wrapper() : - value(nullptr) - { } - - inline wrapper(value_type v) : - value(&v) - { } - - inline wrapper(const wrapper& other) : - value(other.value) - { } - - inline wrapper(wrapper&& other) : - value(std::move(other.value)) - { } - }; - - /* Helper Methods ****************************************************************************/ - inline int bitCount(uint32_t u) - { - u = u - - ((u >> 1) & 033333333333) - - ((u >> 2) & 011111111111); - return ((u + (u >> 3)) & 030707070707) % 63; - } - - template - inline bool tryCast(T* t, S*& s) - { - s = dynamic_cast(t); - return static_cast(s); - } - - namespace __impl - { - template - struct network_convert_helper; - } - - template - inline T hton(const T& value) - { return __impl::network_convert_helper::hton(value); } - - template - inline T ntoh(const T& value) - { return __impl::network_convert_helper::ntoh(value); } - - - /* Indent Stream *****************************************************************************/ - namespace __impl - { - inline int identStreamIndex() - { - const int value = std::ios::xalloc(); - return value; - } - } - - inline std::ostream& incindent(std::ostream& os) - { - ++os.iword(__impl::identStreamIndex()); - return os; - } - - inline std::ostream& decindent(std::ostream& os) - { - auto& indent = os.iword(__impl::identStreamIndex()); - if (--indent < 0) - indent = 0; - return os; - } - - inline std::ostream& indent(std::ostream& os) - { - auto i = os.iword(__impl::identStreamIndex()); - while (i--) - os << " "; - return os; - } - - /* implementation ****************************************************************************/ - namespace __impl - { - template - struct network_convert_helper - { - static inline T hton(const T& t) - { return t; } - - static inline T ntoh(const T& t) - { return t; } - }; - - template - struct network_convert_helper - { - static inline T hton(const T& t) - { return reinterpret_cast(htobe16(reinterpret_cast(t))); } - - static inline T ntoh(const T& t) - { return reinterpret_cast(be16toh(reinterpret_cast(t))); } - }; - - template - struct network_convert_helper - { - static inline T hton(const T& t) - { return reinterpret_cast(htobe32(reinterpret_cast(t))); } - - static inline T ntoh(const T& t) - { return reinterpret_cast(be32toh(reinterpret_cast(t))); } - }; - - template - struct network_convert_helper - { - static inline T hton(const T& t) - { return reinterpret_cast(htobe64(reinterpret_cast(t))); } - - static inline T ntoh(const T& t) - { return reinterpret_cast(be64toh(reinterpret_cast(t))); } - }; - } -} \ No newline at end of file diff --git a/src/cpputils/container.h b/src/cpputils/container.h new file mode 100644 index 0000000..8d341b1 --- /dev/null +++ b/src/cpputils/container.h @@ -0,0 +1,5 @@ +#pragma once + +#include +#include +#include \ No newline at end of file diff --git a/src/cpputils/container/handle_manager.h b/src/cpputils/container/handle_manager.h new file mode 100644 index 0000000..c8bb544 --- /dev/null +++ b/src/cpputils/container/handle_manager.h @@ -0,0 +1,1005 @@ +#pragma once + +#include +#include +#include +#include + +#include +#include +#include + +namespace utl +{ + struct handle + { + uint64_t value; + + inline explicit operator bool () const; + inline operator uint64_t() const; + inline handle& operator = (uint64_t); + inline handle& operator = (const handle&); + + inline bool operator == (const handle&) const; + inline bool operator != (const handle&) const; + inline bool operator <= (const handle&) const; + inline bool operator >= (const handle&) const; + inline bool operator < (const handle&) const; + inline bool operator > (const handle&) const; + + inline bool operator == (const uint64_t&) const; + inline bool operator != (const uint64_t&) const; + inline bool operator <= (const uint64_t&) const; + inline bool operator >= (const uint64_t&) const; + inline bool operator < (const uint64_t&) const; + inline bool operator > (const uint64_t&) const; + + inline std::string to_string () const; + + inline handle(); + inline handle(const uint64_t&); + inline handle(const handle&); + + static inline bool from_string(const std::string& str, handle& handle); + static inline const handle& empty(); + }; + + using type_id_type = uint8_t; + using system_id_type = uint8_t; + + namespace __impl + { + using index_type = size_t; + + static constexpr index_type invalid_index(std::numeric_limits::max()); + static constexpr size_t grow_size (100); + + enum class entry_status + { + unknown, + used, + free, + }; + + #pragma pack(push, 1) + struct handle_data + { + system_id_type system_id; // 0..7 system id (to manage handles for multiple (dedicated) subsystems) + type_id_type type_id; // 8..15 type id (defined by user) + uint16_t counter; // 16..31 reusage counter + uint32_t entry_index; // 32..64 index in data array (unique for each system) + }; + #pragma pack(pop) + static_assert(sizeof(handle) == sizeof(handle_data), "mismatching size of handle and handle_data"); + static_assert(sizeof(handle) == 8, "size of handle is not equal 64"); + + inline handle_data make_handle_data(const handle& handle); + inline handle make_handle (handle_data hd); + + template + struct system; + + template + struct entry + { + public: + using value_type = T_value; + using this_type = entry; + using wrapper_type = wrapper; + + private: + index_type _next; + index_type _prev; + uint16_t _counter; + entry_status _status; + type_id_type _type_id; + wrapper_type _data; + + public: + inline index_type next () const; + inline void next (index_type value); + inline index_type prev () const; + inline void prev (index_type value); + inline entry_status status () const; + inline void link (index_type prev, index_type next, entry_status status); + inline void unlink (); + inline uint16_t counter () const; + inline void assign (value_type value, const type_id_type& tId, const uint16_t cntr = 0); + inline value_type data (); + inline void data (value_type v); + + inline entry(); + inline entry(entry&&); + inline entry(const entry&); + }; + + template + struct system + { + public: + using entry_type = T_entry; + using this_type = system; + using entry_vector_type = std::vector; + + private: + index_type _firstFree; + index_type _lastFree; + index_type _firstUsed; + index_type _lastUsed; + entry_vector_type _entries; + + inline void pushFront (index_type index, index_type& first, index_type& last, entry_status status); + inline void pushBack (index_type index, index_type& first, index_type& last, entry_status status); + inline index_type popFront (bool canGrow, index_type& first, index_type& last, entry_status status); + inline index_type popBack (bool canGrow, index_type& first, index_type& last, entry_status status); + inline void remove (index_type index, index_type& first, index_type& last, entry_status status); + + public: + inline void grow (size_t size = 0); + inline void pushFrontFree (index_type index); + inline void pushFrontUsed (index_type index); + inline void pushBackFree (index_type index); + inline void pushBackUsed (index_type index); + inline index_type popFrontFree (); + inline index_type popFrontUsed (); + inline index_type popBackFree (); + inline index_type popBackUsed (); + inline void removeFree (index_type index); + inline void removeUsed (index_type index); + inline size_t size () const; + + inline entry_type& operator[] (const index_type& index); + inline const entry_type& operator[] (const index_type& index) const; + + inline system(); + inline system(system&&); + inline system(const system&&); + }; + + template + struct systems + { + public: + using entry_type = T_entry; + using this_type = system; + using system_type = system; + using system_vector_type = std::vector; + + private: + system_vector_type _systems; + + public: + inline system_type& operator[] (const index_type& index); + inline const system_type& operator[] (const index_type& index) const; + inline size_t size () const; + inline void clear (); + }; + } + + inline type_id_type get_type_id(const handle& handle) + { return __impl::make_handle_data(handle).type_id; } + + inline system_id_type get_system_id(const handle& handle) + { return __impl::make_handle_data(handle).system_id; } + + template + class handle_manager + { + public: + using value_type = T; + using this_type = handle_manager; + using entry_type = __impl::entry; + using systems_type = __impl::systems; + + private: + systems_type _systems; + + public: + /** check if an given handle is valid + * @param handle handle to check + * @return TRUE if handle is valid, FALSE otherwise */ + inline bool is_valid(const handle& handle) const; + + /** try to get the value for a given handle + * @param handle handle to get value for + * @param value parameter to store value at + * @return TRUE on success, FALSE otherwise */ + inline bool try_get(const handle& handle, value_type& value); + + /** get the value for a given handle + * @param handle handle to get value for + * @return valid stored for handle */ + inline value_type get(const handle& handle); + + /** update the value of a given handle (only valid handles are accepted) + * @param handle handle to update value for + * @param value new value to store + * @return TRUE on success, FALSE otherwise (invalid handle) */ + inline bool update(const handle& handle, value_type value); + + /** set the value for a given handle (this will add the item to the manager if the handle is unknown) + * @param handle handle to set value for + * @param value value to store + * @return TRUE on success, FALSE otherwise (the storage entry is used by an other value) */ + inline bool set(const handle& handle, value_type value); + + /** insert a new value to the manager + * @param tId type id of the value + * @param sId system id of the value + * @param value value to add + * @return handle of the stored value */ + inline handle insert(const type_id_type& tId, const system_id_type& sId, value_type value); + + /** remove the value of a given handle + * @param handle handle to remove value for + * @return TRUE on success, FALSE otherwise (handle is invalid) */ + inline bool remove(const handle& handle); + + /** access values by a given handle + * @param handle handle to get value for + * @return reference to the value */ + inline value_type& operator[](const handle& handle); + + /** remove all stored valus and reset the handle manager completely */ + inline void clear(); + }; +} + +/* HELPER ****************************************************************************************/ + +inline +utl::handle::operator bool() const + { return static_cast(value); } + +inline +utl::handle::operator uint64_t() const + { return value; } + +inline utl::handle& +utl::handle::operator =(uint64_t v) +{ + value = v; + return *this; +} + +inline utl::handle& +utl::handle::operator =(const handle& other) +{ + value = other.value; + return *this; +} + +inline bool +utl::handle::operator ==(const handle& other) const + { return value == other.value; } + +inline bool +utl::handle::operator !=(const handle& other) const + { return value != other.value; } + +inline bool +utl::handle::operator <=(const handle& other) const + { return value <= other.value; } + +inline bool +utl::handle::operator >=(const handle& other) const + { return value >= other.value; } + +inline bool +utl::handle::operator <(const handle& other) const + { return value < other.value; } + +inline bool +utl::handle::operator >(const handle& other) const + { return value > other.value; } + +inline bool +utl::handle::operator ==(const uint64_t& other) const + { return value == other; } + +inline bool +utl::handle::operator !=(const uint64_t& other) const + { return value != other; } + +inline bool +utl::handle::operator <=(const uint64_t& other) const + { return value <= other; } + +inline bool +utl::handle::operator >=(const uint64_t& other) const + { return value >= other; } + +inline bool +utl::handle::operator <(const uint64_t& other) const + { return value < other; } + +inline bool +utl::handle::operator >(const uint64_t& other) const + { return value > other; } + +inline std::string +utl::handle::to_string() const +{ + char buffer[2*sizeof(*this)+3]; + memset(&buffer[0], 0, sizeof(buffer)); + const uint8_t *p = reinterpret_cast(this); + size_t x = 0; + for (size_t i = 0; i < sizeof(*this); ++i) + { + if (i == 1 || i == 2 || i == 4) + { + buffer[2*i+x] = '-'; + ++x; + } + buffer[2*i+x] = static_cast((p[i] >> 4) & 0x0F); + buffer[2*i+x+1] = static_cast((p[i] >> 0) & 0x0F); + buffer[2*i+x] = static_cast(buffer[2*i+x] + (buffer[2*i+x] > 9 ? 'A' - 10 : '0')); + buffer[2*i+x+1] = static_cast(buffer[2*i+x+1] + (buffer[2*i+x+1] > 9 ? 'A' - 10 : '0')); + } + return std::string(&buffer[0], sizeof(buffer)); +} + +inline utl::handle::handle() : + value(0) + { } + +inline utl::handle::handle(const uint64_t& v) : + value(v) + { } + +inline utl::handle::handle(const handle& other) : + value(other.value) + { } + +inline bool +utl::handle::from_string(const std::string& str, handle& handle) +{ + memset(&handle, 0, sizeof(handle)); + const char *c = str.c_str(); + const char *e = c + str.size(); + uint8_t* p = reinterpret_cast(&handle); + size_t i = 0; + while(c < e && i < 2*sizeof(handle)) + { + if (*c != '-') + { + uint8_t v; + if (*c >= '0' && *c <= '9') + v = static_cast(*c - '0'); + else if (*c >= 'a' && *c <= 'f') + v = static_cast(*c - 'a'); + else if (*c >= 'A' && *c <= 'F') + v = static_cast(*c - 'A'); + else + return false; + if (i & 1) + v = static_cast(v << 4); + p[i >> 1] |= v; + ++i; + } + ++c; + } + return (c == e && i == 2*sizeof(handle)); +} + +inline const utl::handle& +utl::handle::empty() +{ + static const handle value; + return value; +} + +inline utl::__impl::handle_data utl::__impl::make_handle_data(const handle& handle) +{ + handle_data hd = reinterpret_cast(handle); + hd.system_id = ntoh(hd.system_id); + hd.type_id = ntoh(hd.type_id); + hd.counter = ntoh(hd.counter); + hd.entry_index = ntoh(hd.entry_index); + return hd; +} + +inline utl::handle utl::__impl::make_handle(handle_data hd) +{ + hd.system_id = hton(hd.system_id); + hd.type_id = hton(hd.type_id); + hd.counter = hton(hd.counter); + hd.entry_index = hton(hd.entry_index); + return reinterpret_cast(hd); +} + +/* ENTRY *****************************************************************************************/ + +template +inline utl::__impl::index_type +utl::__impl::entry::next() const +{ + return _next; +} + +template +inline void +utl::__impl::entry::next( + index_type value) +{ + _next = value; +} + +template +inline utl::__impl::index_type +utl::__impl::entry::prev() const +{ + return _prev; +} + +template +inline void +utl::__impl::entry::prev( + index_type value) +{ + _prev = value; +} + +template +inline utl::__impl::entry_status +utl::__impl::entry::status() const +{ + return _status; +} + +template +inline void +utl::__impl::entry::link(index_type prev, index_type next, entry_status status) +{ + assert(status != entry_status::unknown); + _prev = prev; + _next = next; + _status = status; +} + +template +inline void +utl::__impl::entry::unlink() +{ + _prev = invalid_index; + _next = invalid_index; + _status = entry_status::unknown; +} + +template +inline uint16_t +utl::__impl::entry::counter() const + { return _counter; } + +template +inline void +utl::__impl::entry::assign( + value_type value, + const type_id_type& tId, + const uint16_t cntr) +{ + using namespace ::utl; + using namespace ::utl::__impl; + assert(_status == entry_status::used); + _type_id = tId; + _data = value; + if (cntr != 0) + _counter = cntr; + else if (++_counter == 0) + _counter = 1; +} + +template +inline typename utl::__impl::entry::value_type +utl::__impl::entry::data() +{ + return *_data; +} + +template +inline void +utl::__impl::entry::data( + value_type v) +{ + _data = v; +} + +template +inline utl::__impl::entry::entry() : + _next (invalid_index), + _prev (invalid_index), + _counter(0), + _status (entry_status::unknown), + _type_id (0) + { } + +template +inline utl::__impl::entry::entry(entry&& other) : + _next (std::move(other)._next), + _prev (std::move(other)._prev), + _counter(std::move(other)._counter), + _status (std::move(other)._status), + _type_id (std::move(other)._type_id), + _data (std::move(other)._data) + { } + +template +inline utl::__impl::entry::entry(const entry& other) : + _next (other._next), + _prev (other._prev), + _counter(other._counter), + _status (other._status), + _type_id (other._type_id), + _data (other._data) + { } + +/* SYSTEM ****************************************************************************************/ + +template +inline void +utl::__impl::system::pushFront( + index_type index, + index_type& first, + index_type& last, + entry_status status) +{ + assert(index < _entries.size()); + auto& entry = _entries[index]; + assert(entry.status() == entry_status::unknown); + if (first != invalid_index) + { + assert(first >= 0); + assert(first < _entries.size()); + auto& firstEntry = _entries[first]; + assert(firstEntry.status() == status); + firstEntry.prev(index); + } + entry.link(invalid_index, first, status); + first = index; + if (last == invalid_index) + last = index; +} + +template +inline void +utl::__impl::system::pushBack( + index_type index, + index_type& first, + index_type& last, + entry_status status) +{ + assert(index < _entries.size()); + auto& entry = _entries[index]; + assert(entry.status() == entry_status::unknown); + if (last != invalid_index) + { + assert(last >= 0); + assert(last < _entries.size()); + auto& lastEntry = _entries[last]; + assert(lastEntry.status() == status); + lastEntry.next(index); + } + entry.link(last, invalid_index, status); + last = index; + if (first == invalid_index) + first = index; +} + +template +inline utl::__impl::index_type +utl::__impl::system::popFront( + bool canGrow, + index_type& first, + index_type& last, + entry_status status) +{ + if ( canGrow + && ( first >= _entries.size() + || first == invalid_index)) + grow((first != invalid_index ? first : 0) + grow_size); + assert(first >= 0); + assert(first < _entries.size()); + auto& entry = _entries[first]; + assert(entry.status() == status); + index_type ret = first; + if (last == first) + last = entry.next(); + first = entry.next(); + entry.unlink(); + if (first != invalid_index) + { + assert(first >= 0); + assert(first < _entries.size()); + auto& firstEntry = _entries[first]; + assert(firstEntry.status() == status); + firstEntry.prev(invalid_index); + } + return ret; +} + +template +inline utl::__impl::index_type +utl::__impl::system::popBack( + bool canGrow, + index_type& first, + index_type& last, + entry_status status) +{ + if ( canGrow + && ( last >= _entries.size() + || last == invalid_index)) + grow((last != invalid_index ? last : 0) + grow_size); + assert(last >= 0); + assert(last < _entries.size()); + auto& entry = _entries[last]; + assert(entry.status() == status); + index_type ret = last; + if (first == last) + first = entry._prev; + last = entry._prev; + entry.unlink(); + if (last != invalid_index) + { + assert(last >= 0); + assert(last < _entries.size()); + auto& lastEntry = _entries[last]; + assert(lastEntry.status() == status); + lastEntry.next(invalid_index); + } + return ret; +} + +template +inline void +utl::__impl::system::remove( + index_type index, + index_type& first, + index_type& last, + entry_status status) +{ + assert(index >= 0); + assert(index < _entries.size()); + auto& entry = _entries[index]; + assert(entry.status() == status); + if (entry.prev() != invalid_index) + { + assert(entry.prev() >= 0); + assert(entry.prev() < _entries.size()); + _entries[entry.prev()].next(entry.next()); + } + if (entry.next() != invalid_index) + { + assert(entry.next() >= 0); + assert(entry.next() < _entries.size()); + _entries[entry.next()].prev(entry.prev()); + } + if (first == index) + first = entry.next(); + if (last == index) + last = entry.prev(); + entry.unlink(); +} + +template +inline void +utl::__impl::system::grow( + size_t size) +{ + if (size == 0) + size = _entries.size() + grow_size; + if (size < _entries.size()) + return; + size_t idx = _entries.size(); + _entries.resize(size); + while (idx < _entries.size()) + { + pushBackFree(idx); + ++idx; + } +} + +template +inline void +utl::__impl::system::pushFrontFree( + index_type index) +{ + pushFront(index, _firstFree, _lastFree, entry_status::free); +} + +template +inline void +utl::__impl::system::pushFrontUsed( + index_type index) +{ + pushFront(index, _firstUsed, _lastUsed, entry_status::used); +} + +template +inline void +utl::__impl::system::pushBackFree( + index_type index) +{ + pushBack(index, _firstFree, _lastFree, entry_status::free); +} + +template +inline void +utl::__impl::system::pushBackUsed( + index_type index) +{ + pushBack(index, _firstUsed, _lastUsed, entry_status::used); +} + +template +inline utl::__impl::index_type +utl::__impl::system::popFrontFree() +{ + return popFront(true, _firstFree, _lastFree, entry_status::free); +} + +template +inline utl::__impl::index_type +utl::__impl::system::popFrontUsed() +{ + return popFront(false, _firstUsed, _lastUsed, entry_status::used); +} + +template +inline utl::__impl::index_type +utl::__impl::system::popBackFree() +{ + return popBack(true, _firstFree, _lastFree, entry_status::free); +} + +template +inline utl::__impl::index_type +utl::__impl::system::popBackUsed() +{ + return popBack(false, _firstUsed, _lastUsed, entry_status::used); +} + +template +inline void +utl::__impl::system::removeFree( + index_type index) +{ + remove(index, _firstFree, _lastFree, entry_status::free); +} + +template +inline void +utl::__impl::system::removeUsed( + index_type index) +{ + remove(index, _firstUsed, _lastUsed, entry_status::used); +} + +template +inline size_t +utl::__impl::system::size() const +{ + return _entries.size(); +} + + +template +inline typename utl::__impl::system::entry_type& +utl::__impl::system::operator[]( + const index_type& index) +{ + if (index >= _entries.size()) + grow(index + grow_size); + return _entries[index]; +} + +template +inline const typename utl::__impl::system::entry_type& +utl::__impl::system::operator[]( + const index_type& index) const +{ + return _entries.at(index); +} + +template +inline utl::__impl::system::system() : + _firstFree (invalid_index), + _lastFree (invalid_index), + _firstUsed (invalid_index), + _lastUsed (invalid_index) + { } + +template +inline utl::__impl::system::system(system&& other) : + _firstFree (std::move(other)._firstFree), + _lastFree (std::move(other)._lastFree), + _firstUsed (std::move(other)._firstUsed), + _lastUsed (std::move(other)._lastUsed), + _entries (std::move(other)._entries) + { } + +template +inline utl::__impl::system::system(const system&& other) : + _firstFree (other._firstFree), + _lastFree (other._lastFree), + _firstUsed (other._firstUsed), + _lastUsed (other._lastUsed), + _entries (other._entries) + { } + +/* SYSTEMS ***************************************************************************************/ + +template +inline typename utl::__impl::systems::system_type& +utl::__impl::systems::operator[]( + const index_type& index) +{ + if (index >= _systems.size()) + _systems.resize(index + 1); + return _systems[index]; +} + +template +inline const typename utl::__impl::systems::system_type& +utl::__impl::systems::operator[]( + const index_type& index) const +{ + return _systems[index]; +} + +template +inline size_t +utl::__impl::systems::size() const +{ + return _systems.size(); +} + +template +inline void +utl::__impl::systems::clear() +{ + _systems.clear(); +} + +/* handleMANAGER *********************************************************************************/ + +template +inline bool +utl::handle_manager::is_valid( + const utl::handle& handle) const +{ + using namespace __impl; + auto hd = make_handle_data(handle); + if (hd.system_id >= _systems.size()) + return false; + auto& system = _systems[hd.system_id]; + if (hd.entry_index >= system.size()) + return false; + auto& entry = system[hd.entry_index]; + return entry.status() == entry_status::used + && entry.counter() == hd.counter; +} + +template +inline bool +utl::handle_manager::try_get( + const utl::handle& handle, + typename utl::handle_manager::value_type& value) +{ + using namespace __impl; + auto ret = is_valid(handle); + if (ret) + { + auto hd = make_handle_data(handle); + value = _systems[hd.system_id][hd.entry_index].data(); + } + return ret; +} + +template +inline typename utl::handle_manager::value_type +utl::handle_manager::get( + const utl::handle& handle) +{ + value_type ret; + if (!try_get(handle, ret)) + throw exception("invalid handle"); + return ret; +} + +template +inline bool +utl::handle_manager::update( + const utl::handle& handle, + typename utl::handle_manager::value_type value) +{ + using namespace __impl; + if (is_valid(handle)) + { + auto hd = make_handle_data(handle); + _systems[hd.system_id][hd.entry_index].data(value); + return true; + } + return false; +} + +template +inline bool +utl::handle_manager::set( + const utl::handle& handle, + typename utl::handle_manager::value_type value) +{ + using namespace __impl; + if (!is_valid(handle)) + { + auto hd = make_handle_data(handle); + auto& system = _systems[hd.system_id]; + auto& entry = system[hd.entry_index]; + bool ret = entry.status() == entry_status::free; + if (ret) + { + system.removeFree (hd.entry_index); + system.pushBackUsed(hd.entry_index); + entry.assign(value, hd.type_id, hd.counter); + } + return ret; + } + else + { + return update(handle, value); + } +} + +template +inline utl::handle +utl::handle_manager::insert( + const type_id_type& tId, + const system_id_type& sId, + typename utl::handle_manager::value_type value) +{ + using namespace __impl; + auto& system = _systems[sId]; + auto index = system.popFrontFree(); + system.pushBackUsed(index); + auto& entry = system[index]; + entry.assign(value, tId); + handle_data hd; + hd.entry_index = static_cast(index); + hd.counter = entry.counter(); + hd.type_id = tId, + hd.system_id = sId; + return make_handle(hd); +} + +template +inline bool +utl::handle_manager::remove( + const utl::handle& handle) +{ + using namespace __impl; + if (!is_valid(handle)) + return false; + auto hd = make_handle_data(handle); + auto& system = _systems[hd.system_id]; + system.removeUsed(hd.entry_index); + system.pushFrontFree(hd.entry_index); + return true; +} + +template +inline typename utl::handle_manager::value_type& +utl::handle_manager::operator[]( + const utl::handle& handle) +{ + using namespace __impl; + if (!is_valid(handle)) + throw exception("invalid handle"); + auto hd = make_handle_data(handle); + auto& system = _systems[hd.system_id]; + auto& entry = system[hd.entry_index]; + return entry.data; +} + +template +inline void +utl::handle_manager::clear() + { _systems.clear(); } diff --git a/src/cpputils/Nullable.h b/src/cpputils/container/nullable.h similarity index 52% rename from src/cpputils/Nullable.h rename to src/cpputils/container/nullable.h index 53ccd13..0c2715a 100644 --- a/src/cpputils/Nullable.h +++ b/src/cpputils/container/nullable.h @@ -2,13 +2,15 @@ #include #include -#include "Exception.h" + +#include +#include namespace utl { template - struct Nullable + struct nullable { public: using value_type = T; @@ -16,23 +18,23 @@ namespace utl using pointer_type = clean_type*; private: - struct Container + struct container { value_type value; template - Container(Args&&... args) : + container(Args&&... args) : value(std::forward(args)...) { } }; private: - std::unique_ptr _container; + std::unique_ptr _container; inline void check() const { if (!_container) - throw EInvalidOperation("nullable does not have a value"); + throw invalid_operation_exception("nullable does not have a value"); } public: @@ -42,7 +44,7 @@ namespace utl inline const value_type& value() const { check(); return _container->value; } - inline bool hasValue() const + inline bool has_value() const { return static_cast(_container); } inline void reset() @@ -69,75 +71,90 @@ namespace utl { return value(); } inline explicit operator bool() const - { return hasValue(); } + { return has_value(); } inline bool operator==(T v) const - { return hasValue() && value() == v; } + { return has_value() && value() == v; } - inline bool operator==(const Nullable& other) const - { return hasValue() && other.hasValue() && value() == other.value(); } + inline bool operator==(const nullable& other) const + { return has_value() && other.has_value() && value() == other.value(); } - inline bool operator<(const Nullable& other) const + inline bool operator<(const nullable& other) const { - return this->hasValue() - && other.hasValue() + return this->has_value() + && other.has_value() && value() < other.value(); } - inline bool operator>(const Nullable& other) const + inline bool operator>(const nullable& other) const { - return this->hasValue() - && other.hasValue() + return this->has_value() + && other.has_value() && value() < other.value(); } - inline bool operator<=(const Nullable& other) const + inline bool operator<=(const nullable& other) const { - return this->hasValue() - && other.hasValue() + return this->has_value() + && other.has_value() && value() < other.value(); } - inline bool operator>=(const Nullable& other) const + inline bool operator>=(const nullable& other) const { - return this->hasValue() - && other.hasValue() + return this->has_value() + && other.has_value() && value() < other.value(); } inline void operator=(value_type&& t) - { _container.reset(new Container(std::forward(t))); } + { _container.reset(new container(std::forward(t))); } - inline void operator=(const Nullable& other) + inline void operator=(const nullable& other) { - if (other.hasValue()) + if (other.has_value()) *this = other.value(); else reset(); } - inline void operator=(Nullable&& other) + inline void operator=(nullable&& other) { _container = std::move(other._container); } - Nullable() + nullable() { } template - Nullable(Args&&... args) : - _container(new Container(std::forward(args)...)) + nullable(Args&&... args) : + _container(new container(std::forward(args)...)) { } - Nullable(Nullable& other) + nullable(nullable& other) { if (static_cast(other)) *this = other(); } - Nullable(const Nullable& other) + nullable(const nullable& other) { if (static_cast(other)) *this = other(); } - Nullable(Nullable&& other) : + nullable(nullable&& other) : _container(std::move(other._container)) { } }; + namespace __impl + { + template + struct op_to_string, void> + { + inline void operator()(std::ostream& os, const nullable& s) const + { + if (s.has_value()) + op_to_string()(os, s.value()); + else + os << "null"; + } + }; + } + } \ No newline at end of file diff --git a/src/cpputils/SmartPtr.h b/src/cpputils/container/smart_ptr.h similarity index 79% rename from src/cpputils/SmartPtr.h rename to src/cpputils/container/smart_ptr.h index 63bec23..33b9e1a 100644 --- a/src/cpputils/SmartPtr.h +++ b/src/cpputils/container/smart_ptr.h @@ -2,13 +2,13 @@ #include #include "MetaProgramming.h" -#include "Exception.h" +#include "exception.h" namespace utl { template - struct SmartPtr + struct smart_ptr { private: template @@ -23,7 +23,7 @@ namespace utl public utl::mp_false { }; template class F, class X> - struct __impl_cop_is_value, utl::mp_enable_if, F>>> : + struct __impl_cop_is_value, utl::mp_enable_if, F>>> : public utl::mp_false { }; template @@ -40,20 +40,20 @@ namespace utl std::shared_ptr _value; public: - inline bool hasValue() const + inline bool has_value() const { return static_cast(_value); } inline T& value() { if (!_value) - throw utl::EInvalidOperation("SmartPtr does not have a value"); + throw utl::invalid_operation_exception("smart_ptr does not have a value"); return *_value; } inline const T& value() const { if (!_value) - throw utl::EInvalidOperation("SmartPtr does not have a value"); + throw utl::invalid_operation_exception("smart_ptr does not have a value"); return *_value; } @@ -70,95 +70,95 @@ namespace utl { return &value(); } inline operator bool() const - { return hasValue(); } + { return has_value(); } - inline SmartPtr& reset() + inline smart_ptr& reset() { _value.reset(); return *this; } template::value, int> = 0> - inline SmartPtr& reset(X& x) + inline smart_ptr& reset(X& x) { _value.reset(new X(x)); return *this; } template::value, int> = 0> - inline SmartPtr& reset(X&& x) + inline smart_ptr& reset(X&& x) { _value.reset(new X(std::move(x))); return *this; } template::value, int> = 0> - inline SmartPtr& reset(const SmartPtr& other) + inline smart_ptr& reset(const smart_ptr& other) { _value = other._value; return *this; } template::value, int> = 0> - inline SmartPtr& reset(SmartPtr&& other) + inline smart_ptr& reset(smart_ptr&& other) { _value = std::move(other._value); return *this; } template::value, int> = 0> - inline SmartPtr& reset(std::reference_wrapper&& ref) + inline smart_ptr& reset(std::reference_wrapper&& ref) { _value.reset(&ref.get(), op_deleter_noop()); return *this; } template - inline SmartPtr& reset(Args&&... args) + inline smart_ptr& reset(Args&&... args) { _value.reset(new T(std::forward(args)...)); return *this; } template - inline SmartPtr& operator=(X&& x) + inline smart_ptr& operator=(X&& x) { return reset(std::forward(x)); } - SmartPtr() + smart_ptr() { } template::value, int> = 0> - SmartPtr(X& x) : + smart_ptr(X& x) : _value(new X(x)) { } template::value, int> = 0> - SmartPtr(X&& x) : + smart_ptr(X&& x) : _value(new X(std::move(x))) { } template::value, int> = 0> - SmartPtr(X* x) : + smart_ptr(X* x) : _value(x) { } template::value, int> = 0> - SmartPtr(const SmartPtr& other) : + smart_ptr(const smart_ptr& other) : _value(other._value) { } template::value, int> = 0> - SmartPtr(SmartPtr&& other) : + smart_ptr(smart_ptr&& other) : _value(std::move(other._value)) { } template::value, int> = 0> - SmartPtr(std::reference_wrapper&& ref) : + smart_ptr(std::reference_wrapper&& ref) : _value(&ref.get(), op_deleter_noop()) { } template - SmartPtr(Args... args) : + smart_ptr(Args... args) : _value(new T(args...)) { } }; diff --git a/src/cpputils/container/wrapper.h b/src/cpputils/container/wrapper.h new file mode 100644 index 0000000..bfdd752 --- /dev/null +++ b/src/cpputils/container/wrapper.h @@ -0,0 +1,104 @@ +#pragma once + +namespace utl +{ + + /* simple class that stores a value of type T */ + template + struct wrapper + { + using value_type = T; + + value_type value; + + inline value_type& operator*() + { return value; } + + inline const value_type& operator*() const + { return value; } + + inline wrapper& operator=(value_type v) + { + value = v; + return *this; + } + + inline wrapper& operator=(const wrapper& other) + { + value = other.value; + return *this; + } + + inline wrapper& operator=(wrapper&& other) + { + value = std::move(other).value; + return *this; + } + + inline wrapper() : + value(value_type()) + { } + + inline wrapper(const value_type& v) : + value(v) + { } + + inline wrapper(const wrapper& other) : + value(other.value) + { } + + inline wrapper(wrapper&& other) : + value(std::move(other.value)) + { } + }; + + template + struct wrapper + { + using value_type = T&; + using storage_type = T*; + + storage_type value; + + inline value_type operator*() const + { + assert(value != nullptr); + return *value; + } + + inline wrapper& operator=(value_type v) + { + value = &v; + return *this; + } + + inline wrapper& operator=(const wrapper& other) + { + value = other.value; + return *this; + } + + inline wrapper& operator=(wrapper&& other) + { + value = std::move(other.value); + return *this; + } + + inline wrapper() : + value(nullptr) + { } + + inline wrapper(value_type v) : + value(&v) + { } + + inline wrapper(const wrapper& other) : + value(other.value) + { } + + inline wrapper(wrapper&& other) : + value(std::move(other.value)) + { } + }; + +} \ No newline at end of file diff --git a/src/cpputils/logging.h b/src/cpputils/logging.h new file mode 100644 index 0000000..e69de29 diff --git a/src/cpputils/logging/consumer.h b/src/cpputils/logging/consumer.h new file mode 100644 index 0000000..420457e --- /dev/null +++ b/src/cpputils/logging/consumer.h @@ -0,0 +1,4 @@ +#pragma once + +#include +#include diff --git a/src/cpputils/logging/consumer/consumer.h b/src/cpputils/logging/consumer/consumer.h new file mode 100644 index 0000000..16a9468 --- /dev/null +++ b/src/cpputils/logging/consumer/consumer.h @@ -0,0 +1,24 @@ +#pragma once + +#include + +namespace utl { +namespace logging { + + struct consumer + { + private: + std::string _name; + + public: + virtual void log(data_ptr_s data) = 0; + + inline const std::string& name() const + { return _name; } + + consumer(const std::string& n, bool autoRegister); + ~consumer(); + }; + +} +} diff --git a/src/cpputils/logging/consumer/consumer_stream.h b/src/cpputils/logging/consumer/consumer_stream.h new file mode 100644 index 0000000..ca5602f --- /dev/null +++ b/src/cpputils/logging/consumer/consumer_stream.h @@ -0,0 +1,25 @@ +#pragma once + +#include + +#include + +namespace utl { +namespace logging { + + struct consumer_stream : public consumer + { + private: + mutable std::mutex _mutex; + std::ostream* _stream; + bool _ownsStream; + + public: + void log(data_ptr_s data) override; + + consumer_stream(const std::string& name, std::ostream& stream, bool ownsStream, bool autoRegister); + virtual ~consumer_stream(); + }; + +} +} \ No newline at end of file diff --git a/src/cpputils/logging/global.h b/src/cpputils/logging/global.h new file mode 100644 index 0000000..19e4a9d --- /dev/null +++ b/src/cpputils/logging/global.h @@ -0,0 +1,42 @@ +#pragma once + +#include +#include + +// () mandatory +// [] optional +// (LogLevel: debug|info|warn|error), [T_sender], [Message, [Arguments]] +#define log_global_message(level, ...) \ + if (::utl::logging::is_enabled(::utl::logging::log_level::level)) \ + ::utl::logging::make_log_helper(::utl::logging::log_level::level, __FILE__, __LINE__, ## __VA_ARGS__ ) = ::utl::logging::log_message() + +namespace utl { +namespace logging { + + inline bool is_enabled(log_level level) + { return get_logger().is_enabled(level); } + + template + inline logger::helper make_log_helper(log_level level, const char* file, int line, T_sender* sender, std::string message) + { return get_logger().make_log_helper(level, file, line, sender, message); } + + template + inline logger::helper make_log_helper(log_level level, const char* file, int line, T_sender* sender) + { return get_logger().make_log_helper(level, file, line, sender, std::string()); } + + inline logger::helper make_log_helper(log_level level, const char* file, int line, std::string message) + { return get_logger().make_log_helper(level, file, line, nullptr, message); } + + inline logger::helper make_log_helper(log_level level, const char* file, int line) + { return get_logger().make_log_helper(level, file, line, nullptr, std::string()); } + + template + inline logger::helper make_log_helper(log_level level, const char* file, int line, T_sender* sender, std::string message, Args... args) + { return get_logger().make_log_helper(level, file, line, sender, message, args...); } + + template + inline logger::helper make_log_helper(log_level level, const char* file, int line, std::string message, Args... args) + { return get_logger().make_log_helper(level, file, line, nullptr, message, args...); } + +} +} \ No newline at end of file diff --git a/src/cpputils/logging/log_message.h b/src/cpputils/logging/log_message.h new file mode 100644 index 0000000..eba7dc5 --- /dev/null +++ b/src/cpputils/logging/log_message.h @@ -0,0 +1,42 @@ +#pragma once + +namespace utl { +namespace logging { + + struct log_message + { + private: + std::ostringstream _msg; + + public: + inline std::string str() const + { return _msg.str(); } + + template + inline log_message& operator <<(const T& value) + { + _msg << value; + return *this; + } + + inline log_message& operator <<(std::ostream& (*callback)(std::ostream&)) + { + callback(_msg); + return *this; + } + + log_message() : + _msg() + { } + + log_message(const std::string& msg) : + _msg(msg) + { } + + private: + log_message(log_message&&) = delete; + log_message(const log_message&) = delete; + }; + +} +} diff --git a/src/cpputils/logging/logger.h b/src/cpputils/logging/logger.h new file mode 100644 index 0000000..fe42e92 --- /dev/null +++ b/src/cpputils/logging/logger.h @@ -0,0 +1,98 @@ +#pragma once + +#include +#include +#include + +// () mandatory +// [] optional +// (logger), (LogLevel: debug|info|warn|error), [Sender], [Message, [Arguments]] +#define log_message(logger, level, ...) \ + if (logger.is_enabled(::utl::logging::log_level::level)) \ + logger.make_log_helper(::utl::logging::log_level::level, __FILE__, __LINE__, ## __VA_ARGS__ ) = ::utl::logging::log_message() + +namespace utl { +namespace logging { + + struct logger + { + public: + struct helper + { + private: + logger& _logger; + data_ptr_s _data; + + public: + inline void operator=(const log_message& msg) + { _data->message += msg.str(); } + + inline helper(logger& logger, data_ptr_s data) : + _logger (logger), + _data (data) + { } + + inline ~helper() + { _logger.log(_data); } + + public: + static inline helper create(logger& logger, log_level level, const char* file, int line, void* sender, const std::string& name, std::string message) + { + using namespace ::utl::logging; + data_ptr_s ret(new data()); + ret->level = level; + ret->time = std::chrono::steady_clock::now(); + ret->thread = std::this_thread::get_id(); + ret->file = file; + ret->line = line; + ret->sender = sender; + ret->name = name; + ret->message = message; + return helper(logger, ret); + } + }; + + private: + logger(logger&&) = delete; + logger(const logger&) = delete; + + public: + logger() { } + + virtual const std::string& name () const; + virtual bool is_enabled (log_level level) const; + virtual void log (data_ptr_s data) const; + + template + inline logger::helper make_log_helper(log_level level, const char* file, int line, Sender* sender, std::string message, Args... args) + { + std::unique_ptr buff(static_cast(malloc(0x8000)), &free); + auto len = snprintf(buff.get(), 10240, message.c_str(), args...); + if (len < 0) + throw utl::error_exception(errno); + return helper::create(*this, level, file, line, static_cast(sender), name(), std::string(buff.get(), len)); + } + + template + inline logger::helper make_log_helper(log_level level, const char* file, int line, std::string message, Args... args) + { return make_log_helper(level, file, line, nullptr, message, args...); } + + template + inline logger::helper make_log_helper(log_level level, const char* file, int line, Sender* sender, std::string message) + { return helper::create(*this, level, file, line, static_cast(sender), name(), message); } + + template + inline logger::helper make_log_helper(log_level level, const char* file, int line, Sender* sender) + { return make_log_helper(level, file, line, static_cast(sender), std::string()); } + + inline logger::helper make_log_helper(log_level level, const char* file, int line, std::string message) + { return make_log_helper(level, file, line, nullptr, message); } + + inline logger::helper make_log_helper(log_level level, const char* file, int line) + { return make_log_helper(level, file, line, nullptr, std::string()); } + }; + + logger& get_logger(const std::string& name = ""); + +} +} diff --git a/src/cpputils/logging/logger_impl.h b/src/cpputils/logging/logger_impl.h new file mode 100644 index 0000000..65591ae --- /dev/null +++ b/src/cpputils/logging/logger_impl.h @@ -0,0 +1,51 @@ +#pragma once + +#include +#include + +#include +#include + +namespace utl { +namespace logging { + + struct logger_impl : public logger + { + private: + mutable std::mutex _mutex; + std::string _name; + std::set _rules; + + public: + const std::string& name () const override; + bool is_enabled (log_level level) const override; + void log (data_ptr_s data) const override; + + inline void registerRule(rule& rule) + { + std::lock_guard lk(_mutex); + _rules.insert(&rule); + } + + inline void unregisterRule(rule& rule) + { + std::lock_guard lk(_mutex); + _rules.erase(&rule); + } + + logger_impl(const std::string& n) : + _name(n) + { } + }; + + using logger_impl_ptr_u = std::unique_ptr; + + void register_consumer (consumer& consumer); + void unregister_consumer(consumer& consumer); + + rule_handle define_rule (matcher_ptr_u logger_matcher, matcher_ptr_u consumer_matcher, log_level min_level = log_level::debug, log_level max_level = log_level::error); + void undefine_rule (rule_handle handle); + + void reset_logging(); + +} } \ No newline at end of file diff --git a/src/cpputils/logging/matcher.h b/src/cpputils/logging/matcher.h new file mode 100644 index 0000000..9ba8758 --- /dev/null +++ b/src/cpputils/logging/matcher.h @@ -0,0 +1,6 @@ +#pragma once + +#include +#include +#include +#include diff --git a/src/cpputils/logging/matcher/matcher.h b/src/cpputils/logging/matcher/matcher.h new file mode 100644 index 0000000..74d8241 --- /dev/null +++ b/src/cpputils/logging/matcher/matcher.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +#include +#include + +namespace utl { +namespace logging { + + struct matcher + { + virtual bool match(const logger& logger) const; + virtual bool match(const consumer& consumer) const; + }; + + using matcher_ptr_u = std::unique_ptr; + +} +} diff --git a/src/cpputils/logging/matcher/matcher_all.h b/src/cpputils/logging/matcher/matcher_all.h new file mode 100644 index 0000000..65115c2 --- /dev/null +++ b/src/cpputils/logging/matcher/matcher_all.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +namespace utl { +namespace logging { + + struct matcher_all : public matcher + { + bool match(const logger& logger) const override; + bool match(const consumer& consumer) const override; + }; + +} +} diff --git a/src/cpputils/logging/matcher/matcher_default.h b/src/cpputils/logging/matcher/matcher_default.h new file mode 100644 index 0000000..e8d7a66 --- /dev/null +++ b/src/cpputils/logging/matcher/matcher_default.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +namespace utl { +namespace logging { + + struct matcher_default : public matcher + { + private: + logger& _defaultLogger; + + public: + using matcher::match; + bool match(const logger& logger) const override; + matcher_default(); + }; + +} +} \ No newline at end of file diff --git a/src/cpputils/logging/matcher/matcher_regex.h b/src/cpputils/logging/matcher/matcher_regex.h new file mode 100644 index 0000000..77c5a68 --- /dev/null +++ b/src/cpputils/logging/matcher/matcher_regex.h @@ -0,0 +1,23 @@ +#pragma once + +#include + +#include + +namespace utl { +namespace logging { + + struct matcher_regex : public matcher + { + private: + std::regex _regex; + bool _invert; + + public: + bool match(const logger& logger) const override; + bool match(const consumer& consumer) const override; + matcher_regex(const std::string expression, bool invert = false); + }; + +} +} \ No newline at end of file diff --git a/src/cpputils/logging/rule.h b/src/cpputils/logging/rule.h new file mode 100644 index 0000000..701895b --- /dev/null +++ b/src/cpputils/logging/rule.h @@ -0,0 +1,63 @@ +#pragma once + +#include +#include + +#include +#include + +namespace utl { +namespace logging { + + struct rule + { + private: + mutable std::mutex _mutex; + std::set _consumer; + + public: + matcher_ptr_u logger_matcher; + matcher_ptr_u consumer_matcher; + log_level min_level; + log_level max_level; + + inline bool is_enabled(log_level level) const + { + return min_level <= level + && max_level >= level; + } + + inline void register_consumer(consumer& consumer) + { + std::lock_guard lk(_mutex); + _consumer.insert(&consumer); + } + + inline void unregister_consumer(consumer& consumer) + { + std::lock_guard lk(_mutex); + _consumer.erase(&consumer); + } + + inline void log(data_ptr_s data) + { + std::lock_guard lk(_mutex); + if (is_enabled(data->level)) + { + for (auto& c : _consumer) + c->log(data); + } + } + + rule(matcher_ptr_u lm, matcher_ptr_u cm, log_level min, log_level max) : + logger_matcher (std::move(lm)), + consumer_matcher(std::move(cm)), + min_level (min), + max_level (max) + { } + }; + + using rule_handle = void*; + +} +} \ No newline at end of file diff --git a/src/cpputils/logging/types.h b/src/cpputils/logging/types.h new file mode 100644 index 0000000..b600e87 --- /dev/null +++ b/src/cpputils/logging/types.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include + +namespace utl { +namespace logging { + + enum class log_level + { + debug = 0, + info, + warn, + error, + }; + + struct data + { + log_level level; + std::chrono::steady_clock::time_point time; + void* sender; + std::thread::id thread; + const char* file; + int line; + std::string name; + std::string message; + }; + using data_ptr_s = std::shared_ptr; + +} +} diff --git a/src/cpputils/misc.h b/src/cpputils/misc.h new file mode 100644 index 0000000..84b6cd2 --- /dev/null +++ b/src/cpputils/misc.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include \ No newline at end of file diff --git a/src/cpputils/misc/convert.h b/src/cpputils/misc/convert.h new file mode 100644 index 0000000..bc3264c --- /dev/null +++ b/src/cpputils/misc/convert.h @@ -0,0 +1,63 @@ +#pragma once + +namespace utl +{ + + namespace __impl + { + template + struct network_convert_helper; + } + + template + inline T hton(const T& value) + { return __impl::network_convert_helper::hton(value); } + + template + inline T ntoh(const T& value) + { return __impl::network_convert_helper::ntoh(value); } + + namespace __impl + { + template + struct network_convert_helper + { + static inline T hton(const T& t) + { return t; } + + static inline T ntoh(const T& t) + { return t; } + }; + + template + struct network_convert_helper + { + static inline T hton(const T& t) + { return reinterpret_cast(htobe16(reinterpret_cast(t))); } + + static inline T ntoh(const T& t) + { return reinterpret_cast(be16toh(reinterpret_cast(t))); } + }; + + template + struct network_convert_helper + { + static inline T hton(const T& t) + { return reinterpret_cast(htobe32(reinterpret_cast(t))); } + + static inline T ntoh(const T& t) + { return reinterpret_cast(be32toh(reinterpret_cast(t))); } + }; + + template + struct network_convert_helper + { + static inline T hton(const T& t) + { return reinterpret_cast(htobe64(reinterpret_cast(t))); } + + static inline T ntoh(const T& t) + { return reinterpret_cast(be64toh(reinterpret_cast(t))); } + }; + } + +} \ No newline at end of file diff --git a/src/cpputils/EnumConversion.h b/src/cpputils/misc/enum.h similarity index 67% rename from src/cpputils/EnumConversion.h rename to src/cpputils/misc/enum.h index 89fb55b..5a25074 100644 --- a/src/cpputils/EnumConversion.h +++ b/src/cpputils/misc/enum.h @@ -3,9 +3,10 @@ #include #include -#include "Exception.h" +#include +#include -#define DefEnumToStringMap(enum, ...) \ +#define DEFINE_ENUM_TO_STRING_MAP(enum, ...) \ namespace utl { \ namespace __impl { \ template<> \ @@ -21,7 +22,7 @@ } \ }; } } -#define DefStringToEnumMap(enum, less, ...) \ +#define DEFINE_STRING_TO_ENUM_MAP(enum, less, ...) \ namespace utl { \ namespace __impl { \ template<> \ @@ -37,7 +38,7 @@ } \ }; } } -#define DefDefaultEnumValue(enum, value) \ +#define DEFINE_DEFAULT_ENUM_VALUE(enum, value) \ namespace utl { \ namespace __impl { \ template<> \ @@ -99,23 +100,23 @@ namespace utl struct default_enum_value { static inline T value() - { throw Exception("unable to convert string to enum"); } + { throw exception("unable to convert string to enum"); } }; } - using InvariantStringLess = __impl::invariant_string_less; + using invariant_string_less = __impl::invariant_string_less; template - struct EnumConversion + struct enum_conversion { - using map_enum_to_string = __impl::map_enum_to_string; - using map_string_to_enum = __impl::map_string_to_enum; - using default_enum_value = __impl::default_enum_value; - using base_type = typename std::underlying_type::type; + using map_enum_to_string_type = __impl::map_enum_to_string; + using map_string_to_enum_type = __impl::map_string_to_enum; + using default_enum_value_type = __impl::default_enum_value; + using base_type = typename std::underlying_type::type; - static inline std::string toString(T value, bool addValue) + static inline std::string to_string(T value, bool addValue) { - static const auto& map = map_enum_to_string::value(); + static const auto& map = map_enum_to_string_type::value(); auto it = map.find(value); std::string ret; if (it != map.end()) @@ -129,9 +130,9 @@ namespace utl return ret; } - static inline bool tryToEnum(const std::string& str, T& value, bool acceptNumeric) + static inline bool try_to_enum(const std::string& str, T& value, bool acceptNumeric) { - static const auto& map = map_string_to_enum::value(); + static const auto& map = map_string_to_enum_type::value(); auto it = map.find(str); if (it != map.end()) { @@ -146,13 +147,30 @@ namespace utl return (c != e); } - static inline T toEnum(const std::string& str) + static inline T to_enum(const std::string& str) { T value; - return tryToEnum(str, value) + return try_to_enum(str, value) ? value - : default_enum_value::value(); + : default_enum_value_type::value(); } }; + namespace __impl + { + template + struct op_to_string::value>::type> + { + inline void operator()(std::ostream& os, const T& s) const + { os << enum_conversion::to_string(s, true); } + }; + + template + struct op_from_string::value>::type> + { + inline bool operator()(const std::string& s, T& value) const + { return enum_conversion::try_to_enum(s, value, true); } + }; + } + } \ No newline at end of file diff --git a/src/cpputils/misc/exception.h b/src/cpputils/misc/exception.h new file mode 100644 index 0000000..7f5e930 --- /dev/null +++ b/src/cpputils/misc/exception.h @@ -0,0 +1,168 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include "flags.h" + +namespace utl +{ + + struct exception : public std::exception + { + public: + enum class print_flag + { + ResolveAddress, + }; + using print_flags = shifted_flags; + + public: + static constexpr size_t max_stack_size = 15; + static const print_flags& default_print_flag() + { + static const print_flags value({ print_flag::ResolveAddress }); + return value; + }; + + private: + mutable bool _msg_cache_empty; + mutable std::string _msg_cache; + + protected: + virtual void print_message(std::ostream& os) const + { + os << message; + } + + public: + std::string message; + void* stack[max_stack_size]; + int stack_size; + + public: + void print(std::ostream& os, const print_flags& flags = default_print_flag()) const + { + print_message(os); + os << std::endl; + char** lines = nullptr; + if (flags.is_set(print_flag::ResolveAddress)) + lines = backtrace_symbols(stack, stack_size); + for (int i = 0; i < stack_size; ++i) + { + os << " [0x" << std::setw(2 * sizeof(void*)) << std::setfill('0') << std::hex << reinterpret_cast(stack[i]) << "]"; + if (lines && lines[i]) + os << " " << lines[i]; + os << std::endl; + } + } + + std::string print(const print_flags& flags = default_print_flag()) const + { + std::ostringstream os; + print(os, flags); + return os.str(); + } + + const char* what() const throw() override + { + if (_msg_cache_empty) + { + _msg_cache = print(); + _msg_cache_empty = false; + } + return _msg_cache.c_str(); + } + + inline friend std::ostream& operator <<(std::ostream& os, const exception& ex) + { + ex.print(os); + return os; + } + + public: + exception() : + exception("") + { } + + exception(std::string msg) : + message (msg), + stack_size (0), + _msg_cache_empty(true) + { + stack_size = backtrace(&stack[0], max_stack_size); + } + }; + + struct error_exception : public exception + { + public: + int error; + + error_exception(int e) : + exception(std::to_string(e) + " - " + strerror(e)), + error(e) + { } + + error_exception(const std::string& msg, int e) : + exception(msg + ": " + std::to_string(e) + " - " + strerror(e)), + error(e) + { } + }; + + struct out_of_range_exception : public exception + { + protected: + void print_message(std::ostream& os) const override + { + os << "index out of range (min=" << min << "; max=" << max << "; index=" << index << ")"; + if (!message.empty()) + os << " - " << message; + } + + public: + size_t min; + size_t max; + size_t index; + + out_of_range_exception(size_t mi, size_t ma, size_t idx, std::string msg = "") : + exception (msg), + min (mi), + max (ma), + index (idx) + { } + }; + + struct argument_exception : public exception + { + protected: + void print_message(std::ostream& os) const override + { + os << "invalid argument"; + if (!argument.empty()) + os << "(" << argument << ")"; + if (!message.empty()) + os << " - " << message; + } + + public: + std::string argument; + + argument_exception(std::string arg, std::string msg) : + exception (msg), + argument (arg) + { } + }; + + struct invalid_operation_exception : public exception + { + public: + invalid_operation_exception(std::string msg) : + exception(msg) + { } + }; + +} \ No newline at end of file diff --git a/src/cpputils/Flags.h b/src/cpputils/misc/flags.h similarity index 60% rename from src/cpputils/Flags.h rename to src/cpputils/misc/flags.h index 8fbfad7..39ada59 100644 --- a/src/cpputils/Flags.h +++ b/src/cpputils/misc/flags.h @@ -9,14 +9,14 @@ namespace utl template struct op_flag_convert_none { - static inline TBase toBase(const TEnum e) + static inline TBase to_base(const TEnum e) { return static_cast(e); } }; template struct op_flag_convert_shift { - static inline TBase toBase(const TEnum e) + static inline TBase to_base(const TEnum e) { return static_cast(1 << static_cast(e)); } }; @@ -24,20 +24,20 @@ namespace utl class TEnum, class TBase = typename std::underlying_type::type, class Op = op_flag_convert_none> - struct Flags + struct flags { public: TBase value; public: - inline bool isSet(TEnum e) const - { return static_cast(value & Op::toBase(e)); } + inline bool is_set(TEnum e) const + { return static_cast(value & Op::to_base(e)); } inline void set(TEnum e) - { value = static_cast(value | Op::toBase(e)); } + { value = static_cast(value | Op::to_base(e)); } inline void clear(TEnum e) - { value = static_cast(value & ~Op::toBase(e)); } + { value = static_cast(value & ~Op::to_base(e)); } inline void reset() { value = 0; } @@ -50,42 +50,42 @@ namespace utl { return static_cast(value); } bool operator[](TEnum e) const - { return isSet(e); } + { return is_set(e); } public: - Flags() : + flags() : value(0) { } - explicit Flags(TBase v) : + explicit flags(TBase v) : value(v) { } - Flags(TEnum e) : - value(Op::toBase(e)) + flags(TEnum e) : + value(Op::to_base(e)) { } - Flags(const Flags& other) : + flags(const flags& other) : value(other.value) { } - Flags(std::initializer_list list) : - Flags() + flags(std::initializer_list list) : + flags() { for (auto& e : list) set(e); } public: - static inline const Flags& empty() + static inline const flags& empty() { - static const Flags value(0); + static const flags value(0); return value; } - static inline const Flags& all() + static inline const flags& all() { - static const Flags value(std::numeric_limits::max()); + static const flags value(std::numeric_limits::max()); return value; } }; @@ -93,11 +93,11 @@ namespace utl template< class TEnum, class TBase = typename std::underlying_type::type> - using ShiftedFlags = Flags>; + using shifted_flags = flags>; template< class TEnum, class TBase = typename std::underlying_type::type> - using SimpleFlags = Flags>; + using simple_flags = flags>; } \ No newline at end of file diff --git a/src/cpputils/misc/indent.h b/src/cpputils/misc/indent.h new file mode 100644 index 0000000..41951d6 --- /dev/null +++ b/src/cpputils/misc/indent.h @@ -0,0 +1,39 @@ +#pragma once + +#include + +namespace utl +{ + + namespace __impl + { + inline int indent_stream_index() + { + const int value = std::ios::xalloc(); + return value; + } + } + + inline std::ostream& incindent(std::ostream& os) + { + ++os.iword(__impl::indent_stream_index()); + return os; + } + + inline std::ostream& decindent(std::ostream& os) + { + auto& indent = os.iword(__impl::indent_stream_index()); + if (--indent < 0) + indent = 0; + return os; + } + + inline std::ostream& indent(std::ostream& os) + { + auto i = os.iword(__impl::indent_stream_index()); + while (i--) + os << " "; + return os; + } + +} \ No newline at end of file diff --git a/src/cpputils/Linq.h b/src/cpputils/misc/linq.h similarity index 95% rename from src/cpputils/Linq.h rename to src/cpputils/misc/linq.h index 955b299..aeeac84 100644 --- a/src/cpputils/Linq.h +++ b/src/cpputils/misc/linq.h @@ -4,21 +4,23 @@ #include #include #include +#include +#include -#include "Misc.h" -#include "Nullable.h" -#include "Exception.h" -#include "mp/core.h" +#include +#include +#include +#include // #define LINQ_DEBUG #ifdef LINQ_DEBUG - #include "Misc.h" - #define LINQ_TYPE_NAME() utl::TypeHelper::name() - #define LINQ_CTOR() do { std::cout << "CTOR(this=" << this << ")" << LINQ_TYPE_NAME() << std::endl; } while(0) - #define LINQ_COPY_CTOR() do { std::cout << "COPY(this=" << this << ")" << LINQ_TYPE_NAME() << std::endl; } while(0) - #define LINQ_MOVE_CTOR() do { std::cout << "MOVE(this=" << this << ")" << LINQ_TYPE_NAME() << std::endl; } while(0) - #define LINQ_DTOR() do { std::cout << "DTOR(this=" << this << ")" << LINQ_TYPE_NAME() << std::endl; } while(0) + #include + #define LINQ_TYPE_NAME() utl::type_helper::name() + #define LINQ_CTOR() do { std::cout << "CTOR " << ++::utl::linq::__impl::ref_counter::value() << "(this=" << this << ")" << LINQ_TYPE_NAME() << std::endl; } while(0) + #define LINQ_COPY_CTOR() do { std::cout << "COPY " << ++::utl::linq::__impl::ref_counter::value() << "(this=" << this << ")" << LINQ_TYPE_NAME() << std::endl; } while(0) + #define LINQ_MOVE_CTOR() do { std::cout << "MOVE " << ++::utl::linq::__impl::ref_counter::value() << "(this=" << this << ")" << LINQ_TYPE_NAME() << std::endl; } while(0) + #define LINQ_DTOR() do { std::cout << "DTOR " << --::utl::linq::__impl::ref_counter::value() << "(this=" << this << ")" << LINQ_TYPE_NAME() << std::endl; } while(0) #else #define LINQ_TYPE_NAME() while(0) #define LINQ_CTOR() while(0) @@ -27,10 +29,23 @@ #define LINQ_DTOR() while(0) #endif -namespace linq -{ +namespace utl{ +namespace linq { + namespace __impl { + #ifdef LINQ_DEBUG + template + struct ref_counter + { + static inline size_t& value() + { + static size_t value = 0; + return value; + } + }; + #endif + struct tag_range { }; struct tag_builder { }; @@ -220,7 +235,7 @@ namespace linq assert(current != end); return value_type( *current->first, - std::move(container.createRange(range_indices))); + container.createRange(range_indices)); } inline bool next() @@ -315,11 +330,11 @@ namespace linq template inline auto operator >> (TBuilder&& builder) & - { return builder.build(std::move(lookup_key_value_range(*this))); } + { return builder.build(lookup_key_value_range(*this)); } template inline auto operator >> (TBuilder&& builder) && - { return builder.build(std::move(lookup_key_value_range(std::move(*this)))); } + { return builder.build(lookup_key_value_range(std::move(*this))); } private: inline lookup(keys_type&& k, values_type&& v) : @@ -606,7 +621,7 @@ namespace linq using this_type = select_range; using range_value_type = mp_range_value_type; using value_type = decltype(std::declval()(std::declval())); - using cache_type = utl::Nullable; + using cache_type = utl::nullable; predicate_type predicate; range_type range; @@ -670,12 +685,12 @@ namespace linq using this_type = where_range; using range_value_type = mp_range_value_type; using predicate_return_type = decltype(std::declval()(std::declval())); - using inner_range_type = utl::mp::eval_if< + using inner_range_type = utl::mp::eval_if_t< std::is_base_of, predicate_return_type, mp_make_inner_range, predicate_return_type>; using value_type = mp_range_value_type; - using inner_range_cache_type = utl::Nullable; + using inner_range_cache_type = utl::nullable; predicate_type predicate; range_type range; @@ -757,7 +772,7 @@ namespace linq inline value_type& front() { assert(current >= 0 && static_cast(current) < values.size()); - return *values.at(current); + return *values.at(static_cast(current)); } inline bool next() @@ -1179,10 +1194,10 @@ namespace linq using range_value_type = mp_range_value_type; if (!range.next()) - throw utl::Exception("range is empty"); + throw utl::exception("range is empty"); auto ret = std::forward(range.front()); if (range.next()) - throw utl::Exception("range contains more than one value"); + throw utl::exception("range contains more than one value"); return ret; } }; @@ -1210,7 +1225,7 @@ namespace linq { using range_value_type = mp_range_value_type; if (!range.next()) - throw utl::Exception("range is empty"); + throw utl::exception("range is empty"); return std::forward(range.front()); } }; @@ -1281,7 +1296,7 @@ namespace linq while(range.next()) tmp = std::forward(range.front()); if (!static_cast(tmp)) - throw utl::Exception("range is empty"); + throw utl::exception("range is empty"); return std::forward(*tmp); } }; @@ -1318,7 +1333,7 @@ namespace linq vector_type ret; ret.reserve(capacity); while (range.next()) - ret.emplace_back(std::move(range.front())); + ret.emplace_back(std::forward(range.front())); return ret; } @@ -1338,7 +1353,7 @@ namespace linq list_type ret; while (range.next()) - ret.emplace_back(std::move(range.front())); + ret.emplace_back(std::forward(range.front())); return ret; } }; @@ -1369,7 +1384,7 @@ namespace linq key_predicate(range.front()), value_predicate(range.front())); if (!ret.second) - throw utl::Exception("duplicate key in range"); + throw utl::exception("duplicate key in range"); } return map; } @@ -1590,10 +1605,10 @@ namespace linq template inline auto to_map(TKeyPredicate&& kp) - { return to_map(std::forward(kp), std::move(op_select_value_default())); } + { return to_map(std::forward(kp), op_select_value_default()); } inline auto to_map() - { return to_map(std::move(op_select_key_default()), std::move(op_select_value_default())); } + { return to_map(op_select_key_default(), op_select_value_default()); } template inline auto for_each(TPredicate&& p) @@ -1605,14 +1620,16 @@ namespace linq template inline auto to_lookup(TKeyPredicate&& kp) - { return to_lookup(std::forward(kp), std::move(op_select_value_default())); } + { return to_lookup(std::forward(kp), op_select_value_default()); } inline auto to_lookup() - { return to_lookup(std::move(op_select_key_default()), std::move(op_select_value_default())); } + { return to_lookup(op_select_key_default(), op_select_value_default()); } template using lookup_value_range_type = typename __impl::lookup::lookup_range_wrapper; template using lookup_key_value_range_type = typename __impl::lookup::lookup_key_value_range_wrapper; + +} } \ No newline at end of file diff --git a/src/cpputils/misc/misc.h b/src/cpputils/misc/misc.h new file mode 100644 index 0000000..06ceb86 --- /dev/null +++ b/src/cpputils/misc/misc.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include + +#if defined(__linux__) +# include +#elif defined(__FreeBSD__) || defined(__NetBSD__) +# include +#elif defined(__OpenBSD__) +# include +# define be16toh(x) betoh16(x) +# define be32toh(x) betoh32(x) +# define be64toh(x) betoh64(x) +#endif + +namespace utl +{ + + inline int bit_count(uint32_t u) + { + u = u + - ((u >> 1) & 033333333333) + - ((u >> 2) & 011111111111); + return ((u + (u >> 3)) & 030707070707) % 63; + } + + template + inline bool try_cast(T* t, S*& s) + { + s = dynamic_cast(t); + return static_cast(s); + } + +} \ No newline at end of file diff --git a/src/cpputils/StreamHelper.h b/src/cpputils/misc/stream.h similarity index 71% rename from src/cpputils/StreamHelper.h rename to src/cpputils/misc/stream.h index 5c531a6..a951314 100644 --- a/src/cpputils/StreamHelper.h +++ b/src/cpputils/misc/stream.h @@ -1,7 +1,7 @@ #pragma once #include -#include "Exception.h" +#include "exception.h" namespace utl { @@ -14,10 +14,10 @@ namespace utl inline void operator()(std::ostream& os, const T& t) { if (!os) - throw Exception("unable to write data to stream: invalid stream"); + throw exception("unable to write data to stream: invalid stream"); os.write(reinterpret_cast(&t), sizeof(t)); if (!os) - throw Exception("unable to write data to stream: stream error"); + throw exception("unable to write data to stream: stream error"); } }; @@ -27,11 +27,11 @@ namespace utl inline void operator()(std::istream& is, T& t) { if (!is) - throw Exception("unable to read data from stream: invalid stream"); + throw exception("unable to read data from stream: invalid stream"); if (is.read(reinterpret_cast(&t), sizeof(t)).gcount() != sizeof(t)) - throw Exception("unable to read data from stream: EOF"); + throw exception("unable to read data from stream: EOF"); if (!is) - throw Exception("unable to read data from stream: stream error"); + throw exception("unable to read data from stream: stream error"); } }; @@ -41,13 +41,13 @@ namespace utl inline void operator()(std::ostream& os, const std::string& t) { if (t.size() > std::numeric_limits::max()) - throw Exception("unable to write data to stream: string is to large"); + throw exception("unable to write data to stream: string is to large"); op_write_stream()(os, static_cast(t.size())); if (!os) - throw Exception("unable to write data to stream: invalid stream"); - os.write(t.data(), t.size()); + throw exception("unable to write data to stream: invalid stream"); + os.write(t.data(), static_cast(t.size())); if (!os) - throw Exception("unable to write data to stream: stream error"); + throw exception("unable to write data to stream: stream error"); } }; @@ -59,13 +59,13 @@ namespace utl uint32_t sz; op_read_stream()(is, sz); if (!is) - throw Exception("unable to read data from stream: invalid stream"); + throw exception("unable to read data from stream: invalid stream"); std::string tmp; tmp.resize(sz); if (is.read(const_cast(tmp.data()), sz).gcount() != sz) - throw Exception("unable to read data from stream: EOF"); + throw exception("unable to read data from stream: EOF"); if (!is) - throw Exception("unable to read data from stream: stream error"); + throw exception("unable to read data from stream: stream error"); t = std::move(tmp); } }; @@ -85,7 +85,7 @@ namespace utl }; } - struct StreamHelper + struct stream_helper { template static inline void write(std::ostream& os, const T& t) @@ -104,4 +104,18 @@ namespace utl } }; + struct stream_format_saver + { + std::ios state; + std::ostream& stream; + + stream_format_saver(std::ostream& s) : + state (nullptr), + stream (s) + { state.copyfmt(stream); } + + ~stream_format_saver() + { stream.copyfmt(state); } + }; + } \ No newline at end of file diff --git a/src/cpputils/StringHelper.h b/src/cpputils/misc/string.h similarity index 61% rename from src/cpputils/StringHelper.h rename to src/cpputils/misc/string.h index 5bcf6c1..fe7b92e 100644 --- a/src/cpputils/StringHelper.h +++ b/src/cpputils/misc/string.h @@ -1,8 +1,7 @@ #pragma once #include -#include "Nullable.h" -#include "EnumConversion.h" +#include namespace utl { @@ -17,39 +16,19 @@ namespace utl }; template - struct op_to_string().toString(std::declval()), void())> + struct op_to_string().to_string(std::declval()), void())> { inline void operator()(std::ostream& os, const T& s) const - { s.toString(os); } + { s.to_string(os); } }; template - struct op_to_string().toString(), void())> + struct op_to_string().to_string(), void())> { inline void operator()(std::ostream& os, const T& s) const - { os << s.toString(); } + { os << s.to_string(); } }; - template - struct op_to_string::value>::type> - { - inline void operator()(std::ostream& os, const T& s) const - { os << EnumConversion::toString(s, true); } - }; - - template - struct op_to_string, void> - { - inline void operator()(std::ostream& os, const Nullable& s) const - { - if (s.hasValue()) - op_to_string()(os, s.value()); - else - os << "null"; - } - }; - - template struct op_from_string { @@ -82,24 +61,17 @@ namespace utl }; template - struct op_from_string().fromString(std::declval()), void())> - { - inline bool operator()(const std::string& s, T& value) const - { return value.fromString(s); } - }; - - template - struct op_from_string(), std::declval()), void())> + struct op_from_string().from_string(std::declval()), void())> { inline bool operator()(const std::string& s, T& value) const - { return T::fromString(s, value); } + { return value.from_string(s); } }; template - struct op_from_string::value>::type> + struct op_from_string(), std::declval()), void())> { inline bool operator()(const std::string& s, T& value) const - { return EnumConversion::tryToEnum(s, value, true); } + { return T::from_string(s, value); } }; template @@ -128,42 +100,42 @@ namespace utl } template - inline void toString(std::ostream& os, const T& t) + inline void to_string(std::ostream& os, const T& t) { __impl::op_to_string()(os, t); } template - inline std::string toString(const T& t) + inline std::string to_string(const T& t) { std::ostringstream ss; - toString(ss, t); + to_string(ss, t); return ss.str(); } template<> - inline std::string toString(const std::string& s) + inline std::string to_string(const std::string& s) { return s; } template - inline bool tryFromString(const std::string& s, T& value) + inline bool try_from_string(const std::string& s, T& value) { return __impl::op_from_string()(s, value); } template - inline T fromString(const std::string& s, T defaultValue) + inline T from_string(const std::string& s, T defaultValue) { T tmp; - return tryFromString(s, tmp) + return try_from_string(s, tmp) ? tmp : defaultValue; } template - inline T fromString(const std::string& s) + inline T from_string(const std::string& s) { T tmp; - if (!tryFromString(s, tmp)) - throw Exception(std::string("unable to convert string to specific value: ") + s); + if (!try_from_string(s, tmp)) + throw exception(std::string("unable to convert string to specific value: ") + s); return tmp; } diff --git a/src/cpputils/Time.h b/src/cpputils/misc/time.h similarity index 97% rename from src/cpputils/Time.h rename to src/cpputils/misc/time.h index a878a88..bdd67fc 100644 --- a/src/cpputils/Time.h +++ b/src/cpputils/misc/time.h @@ -20,7 +20,7 @@ namespace utl const std::chrono::seconds sec = std::chrono::duration_cast(d); tv.tv_sec = sec.count(); tv.tv_usec = std::chrono::duration_cast(d - sec).count(); - return std::move(tv); + return tv; } }; @@ -44,7 +44,7 @@ namespace utl const std::chrono::seconds sec = std::chrono::duration_cast(d); ts.tv_sec = sec.count(); ts.tv_nsec = std::chrono::duration_cast(d - sec).count(); - return std::move(ts); + return ts; } }; diff --git a/src/cpputils/TransformIterator.h b/src/cpputils/misc/transform_iterator.h similarity index 84% rename from src/cpputils/TransformIterator.h rename to src/cpputils/misc/transform_iterator.h index 076854d..0976179 100644 --- a/src/cpputils/TransformIterator.h +++ b/src/cpputils/misc/transform_iterator.h @@ -10,13 +10,13 @@ namespace utl } template - struct TransformIterator; + struct transform_iterator; template - struct TransformIterator> + struct transform_iterator> { public: - using iterator_type = TransformIterator; + using iterator_type = transform_iterator; using iterator_category = std::input_iterator_tag; using difference_type = typename It::difference_type; using return_type = decltype(std::declval()(std::declval())); @@ -29,10 +29,10 @@ namespace utl Transform _transform; public: - TransformIterator() + transform_iterator() { } - TransformIterator(It it, Transform transform) : + transform_iterator(It it, Transform transform) : _it (it), _transform (transform) { } @@ -66,10 +66,10 @@ namespace utl }; template - struct TransformIterator> + struct transform_iterator> { public: - using iterator_type = TransformIterator; + using iterator_type = transform_iterator; using iterator_category = std::input_iterator_tag; using difference_type = typename It::difference_type; using return_type = decltype(std::declval()(std::declval())); @@ -82,10 +82,10 @@ namespace utl Transform _transform; public: - TransformIterator() + transform_iterator() { } - TransformIterator(It it, Transform transform) : + transform_iterator(It it, Transform transform) : _it (it), _transform (transform) { } @@ -128,10 +128,10 @@ namespace utl }; template - struct TransformIterator> + struct transform_iterator> { public: - using iterator_type = TransformIterator; + using iterator_type = transform_iterator; using iterator_category = std::input_iterator_tag; using difference_type = typename It::difference_type; using return_type = decltype(std::declval()(std::declval())); @@ -144,10 +144,10 @@ namespace utl Transform _transform; public: - TransformIterator() + transform_iterator() { } - TransformIterator(It it, Transform transform) : + transform_iterator(It it, Transform transform) : _it (it), _transform (transform) { } @@ -226,11 +226,11 @@ namespace utl }; template - TransformIterator makeTransformIterator(const It& it, const Transform& transform) - { return TransformIterator(it, transform); } + transform_iterator make_transform_iterator(const It& it, const Transform& transform) + { return transform_iterator(it, transform); } template = 0> - inline TransformIterator - operator+(const typename TransformIterator::difference_type& n, const TransformIterator& it) + inline transform_iterator + operator+(const typename transform_iterator::difference_type& n, const transform_iterator& it) { return it + n; } } \ No newline at end of file diff --git a/src/cpputils/misc/type_helper.h b/src/cpputils/misc/type_helper.h new file mode 100644 index 0000000..877e845 --- /dev/null +++ b/src/cpputils/misc/type_helper.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +namespace utl +{ + + template + struct type_helper + { + public: + static inline std::string name() + { + int status; + auto name = abi::__cxa_demangle(typeid(T).name(), 0, 0, &status); + return std::string(name ? name : typeid(T).name()); + } + }; + +} \ No newline at end of file diff --git a/src/cpputils/mp.h b/src/cpputils/mp.h new file mode 100644 index 0000000..2a5525e --- /dev/null +++ b/src/cpputils/mp.h @@ -0,0 +1,7 @@ +#pragma once + +#include +#include +#include +#include +#include \ No newline at end of file diff --git a/src/cpputils/mp/MetaProgramming.h.old b/src/cpputils/mp/MetaProgramming.h.old deleted file mode 100644 index 76ee24c..0000000 --- a/src/cpputils/mp/MetaProgramming.h.old +++ /dev/null @@ -1,980 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -#define MP_DEBUG - -#if defined __GNUC__ -# define LIKELY(EXPR) __builtin_expect(!!(EXPR), 1) -#else -# define LIKELY(EXPR) (!!(EXPR)) -#endif - -#if defined MP_DEBUG -# define X_ASSERT(CHECK) void(0) -#else -# define X_ASSERT(CHECK) ( LIKELY(CHECK) ? void(0) : []{assert(!#CHECK);}() ) -#endif - -namespace utl -{ - - /* types */ - template - using mp_const = std::integral_constant; - - template - using mp_bool = mp_const; - - template - using mp_size_t = mp_const; - - template - struct mp_list { }; - - template - struct mp_identity - { using type = T; }; - - template - struct mp_inherit : T... - { }; - - template - struct mp_integer_sequence - { }; - - template - using mp_index_sequence = mp_integer_sequence; - - - - /* constants */ - using mp_true = mp_bool; - using mp_false = mp_bool; - using mp_zero = mp_size_t<0>; - - - - /* modifier */ - template - using mp_add_pointer = T*; - - template - using mp_add_reference = T&; - - template - using mp_remove_ptr = typename std::remove_pointer::type; - - template - using mp_remove_const = typename std::remove_const::type; - - template - using mp_remove_cv = typename std::remove_cv::type; - - template - using mp_remove_ref = typename std::remove_reference::type; - - template - using mp_clean_type = mp_remove_cv>>; - - - - /* conditionals */ - template - using mp_is_same = mp_bool::value>; - - template - using mp_is_base_of = mp_bool::value>; - - template - using mp_enable_if = typename std::enable_if::type; - - template - using mp_enable_if_c = typename std::enable_if::type; - - - - namespace __impl - { - /* logical operations */ - template - struct mp_if_c_impl; - - template class E, class... A> - struct mp_eval_if_c_impl; - - template - struct mp_not_impl; - - template - struct mp_and_impl; - - template - struct mp_or_impl; - - - - /* arithmetic */ - template - struct mp_plus_impl; - - template - struct mp_minus_impl; - - template - struct mp_multiply_impl; - - template - struct mp_divide_impl; - - - - /* generator functions */ - template - struct next_integer_sequence; - - template - struct mp_make_int_seq_impl; - - template - struct mp_repeat_impl; - - - - /* list operations returning a numeric value */ - template - struct mp_size_impl; - - template - struct mp_count_impl; - - template class P> - struct mp_count_if_impl; - - - - /* operations to manipulate list content */ - template - struct mp_push_front_impl; - - template - struct mp_pop_front_impl; - - template - struct mp_push_back_impl; - - template - struct mp_concat_impl; - - template class F> - struct mp_filter_impl; - - - - /* list operations returning a bool value */ - template - struct mp_empty_impl; - - template - struct mp_contains_impl; - - - - /* list operations returing elements from the list */ - template - struct mp_front_impl; - - template - struct mp_second_impl; - - template - struct mp_at_c_impl; - - template class F, class TDefault> - struct mp_search_impl; - - template - struct mp_find_impl; - - template - struct mp_map_find_impl; - - - - /* list manipulators returning a new list */ - template - struct mp_clear_impl; - - template - struct mp_unique_impl; - - template class B> - struct mp_rename_impl; - - template - struct mp_append_impl; - - template - struct mp_map_from_list_impl; - - template class F, class E, class... L> - struct mp_transform_impl; - - - - /* unique id */ - template - struct mp_unique_counter; - - template - struct mp_unique_id; - - - - /* strings */ - struct tag_reference { }; - struct tag_array { }; - - template - struct mp_string_impl; - - template - struct mp_int_to_string_impl; - - template - using mp_array_string = mp_string_impl; - - template - struct mp_string_type_join_impl; - - - - /* tuple */ - template - struct mp_tuple_call_helper - { - static inline void exec(F f, T& t, Args&&... args) - { } - }; - - template - struct mp_tuple_call_helper - { - static inline void exec(F f, T& t, Args&&... args) - { f(t, std::forward(args)...); } - }; - - template - using mp_tuple_filter = mp_true; - - template class Filter, class T, class F, size_t... I, class... Args> - void for_each_in_tuple_filter(T& t, F f, const mp_index_sequence&, Args&&... args) - { - using expander = int[]; - (void) f; - (void) expander { (mp_tuple_call_helper< - Filter(t))>::value, - F, - decltype(std::get(t)), - Args...>::exec( - f, - std::get(t), - std::forward(args)...), 0)... }; - } - } - - - - /* logical operations */ - template - using mp_if = typename __impl::mp_if_c_impl::type; - - template - using mp_if_c = typename __impl::mp_if_c_impl::type; - - template class E, class... A> - using mp_eval_if = typename __impl::mp_eval_if_c_impl::type; - - template class E, class... A> - using mp_eval_if_c = typename __impl::mp_eval_if_c_impl::type; - - template - using mp_not = typename __impl::mp_not_impl::type; - - template - using mp_and = typename __impl::mp_and_impl::type; - - template - using mp_or = typename __impl::mp_or_impl::type; - - - - /* arithmetic */ - template - using mp_plus = typename __impl::mp_plus_impl::type; - - template - using mp_minus = typename __impl::mp_minus_impl::type; - - template - using mp_multiply = typename __impl::mp_multiply_impl::type; - - template - using mp_divide = typename __impl::mp_divide_impl::type; - - - - /* generator functions */ - template - using mp_make_integer_sequence = typename __impl::mp_make_int_seq_impl::type; - - template - using mp_make_index_sequence = mp_make_integer_sequence; - - template - using mp_repeat = typename __impl::mp_repeat_impl::type; - - - - /* list operations returning a numeric value */ - template - using mp_length = mp_const; - - template - using mp_size = typename __impl::mp_rename_impl::type; - - template - using mp_count = typename __impl::mp_count_impl::type; - - template class P> - using mp_count_if = typename __impl::mp_count_if_impl::type; - - - - /* operations to manipulate list content */ - template - using mp_push_front = typename __impl::mp_push_front_impl::type; - - template - using mp_pop_front = typename __impl::mp_pop_front_impl::type; - - template - using mp_push_back = typename __impl::mp_push_back_impl::type; - - template - using mp_concat = typename __impl::mp_concat_impl::type; - - template class F> - using mp_filter = typename __impl::mp_filter_impl::type; - - - - /* list operations returning a bool value */ - template - using mp_empty = typename __impl::mp_empty_impl::type; - - template - using mp_contains = mp_bool::value != 0>; - - - - /* list operations returing elements from the list */ - template - using mp_front = typename __impl::mp_front_impl::type; - - template - using mp_second = typename __impl::mp_second_impl::type; - - template - using mp_at = typename __impl::mp_at_c_impl::type; - - template - using mp_at_c = typename __impl::mp_at_c_impl::type; - - template class F, class TDefault = void> - using mp_search = typename __impl::mp_search_impl::type; - - template - using mp_find = typename __impl::mp_find_impl::type; - - template - using mp_map_find = typename __impl::mp_map_find_impl::type; - - - - /* list manipulators returning a new list */ - template - using mp_clear = typename __impl::mp_clear_impl::type; - - template - using mp_unique = typename __impl::mp_unique_impl>::type; - - template class B> - using mp_rename = typename __impl::mp_rename_impl::type; - - template - using mp_append = typename __impl::mp_append_impl::type; - - template - using mp_map_from_list = typename __impl::mp_map_from_list_impl::value>>::type; - - template class F, class... L> - using mp_transform = typename __impl::mp_transform_impl, L...>::type; - - - - /* unique id */ - template - inline size_t nextUniqueId() - { return __impl::mp_unique_counter::next(); } - - template - inline size_t getUniqueId() - { return __impl::mp_unique_id::value(); } - - - - /* strings */ - template - using mp_string = __impl::mp_string_impl; - - template - constexpr auto mp_int_to_string() - { return __impl::mp_int_to_string_impl::value; } - - template - constexpr mp_string mp_make_string(const char (&data)[N]) - { return mp_string(data); } - - template - constexpr __impl::mp_array_string mp_string_cat( - const __impl::mp_string_impl& s1, - const __impl::mp_string_impl& s2) - { return __impl::mp_array_string(s1, s2); }; - - template - constexpr auto operator + ( - const __impl::mp_string_impl& s1, - const __impl::mp_string_impl& s2) - { return mp_string_cat(s1, s2); }; - - template - constexpr auto mp_string_join( - const __impl::mp_string_impl& j, - const __impl::mp_string_impl& s1, - const __impl::mp_string_impl& s2) - { return mp_string_cat(s1, mp_string_cat(j, s2)); } - - template - constexpr auto mp_string_join( - const __impl::mp_string_impl& j, - const __impl::mp_string_impl& s, - const __impl::mp_string_impl&... rest) - { return mp_string_cat(s, mp_string_cat(j, mp_string_join(j, rest...))); } - - template - using mp_string_type_join = __impl::mp_string_type_join_impl; - - - - /* tuple */ - template - void mp_for_each_in_tuple(std::tuple& t, F f, Args&&... args) - { __impl::for_each_in_tuple_filter<__impl::mp_tuple_filter>(t, f, mp_make_index_sequence::value>(), std::forward(args)...); } - - template - void mp_for_each_in_tuple(const std::tuple& t, F f, Args&&... args) - { __impl::for_each_in_tuple_filter<__impl::mp_tuple_filter>(t, f, mp_make_index_sequence::value>(), std::forward(args)...); } - - template class Filter, class... T, class F, class... Args> - void mp_for_each_in_tuple_filter(std::tuple& t, F f, Args&&... args) - { __impl::for_each_in_tuple_filter(t, f, mp_make_index_sequence::value>(), std::forward(args)...); } - - template class Filter, class... T, class F, class... Args> - void mp_for_each_in_tuple_filter(const std::tuple& t, F f, Args&&... args) - { __impl::for_each_in_tuple_filter(t, f, mp_make_index_sequence::value>(), std::forward(args)...); } - - template class F> - struct mp_for_each_proxy - { - template - inline void operator()(T& t, Args&&... args) const - { F>::exec(t, std::forward(args)...); } - }; - - - - namespace __impl - { - /* helper */ - constexpr size_t cx_plus() - { return 0; } - - template - constexpr size_t cx_plus(T1 t1, T... t) - { return t1 + cx_plus(t...); } - - constexpr bool cx_and() - { return true; } - - template - constexpr bool cx_and(bool b, T... t) - { return b && cx_and(t...); } - - constexpr bool cx_or() - { return false; } - - template - constexpr bool cx_or(bool b, T... t) - { return b || cx_or(t...); } - - constexpr size_t cx_find_index( bool const * first, bool const * last ) - { return first == last || *first ? 0 : 1 + cx_find_index(first + 1, last); } - - - - /* logical operations */ - template - struct mp_if_c_impl - { using type = T; }; - - template - struct mp_if_c_impl - { using type = F; }; - - template class E, class... A> - struct mp_eval_if_c_impl - { using type = T; }; - - template class E, class... A> - struct mp_eval_if_c_impl - { using type = E; }; - - template class L, class... T> - struct mp_not_impl> - { using type = L...>; }; - - template class L, class... T> - struct mp_and_impl> - { using type = mp_bool::value...)>; }; - - template class L, class... T> - struct mp_or_impl> - { using type = mp_bool::value...)>; }; - - - - /* arithmetic */ - template class L, class T> - struct mp_plus_impl> - { using type = T; }; - - template class L, class T1, class... T> - struct mp_plus_impl> - { - using _type = mp_remove_const; - static constexpr _type _value = T1::value + mp_plus>::value; - using type = mp_const<_type, _value>; - }; - - template class L, class T> - struct mp_minus_impl> - { using type = T; }; - - template class L, class T1, class... T> - struct mp_minus_impl> - { - using _type = mp_remove_const; - static constexpr _type _value = T1::value - mp_plus>::value; - using type = mp_const<_type, _value>; - }; - - template class L, class T> - struct mp_multiply_impl> - { using type = T; }; - - template class L, class T1, class... T> - struct mp_multiply_impl> - { - using _type = mp_remove_const; - static constexpr _type _value = T1::value * mp_multiply>::value; - using type = mp_const<_type, _value>; - }; - - template class L, class T> - struct mp_divide_impl> - { using type = T; }; - - template class L, class T1, class... T> - struct mp_divide_impl> - { - using _type = mp_remove_const; - static constexpr _type _value = T1::value / mp_multiply>::value; - using type = mp_const<_type, _value>; - }; - - - - /* generator functions */ - template - struct next_integer_sequence; - - template - struct next_integer_sequence> - { using type = mp_integer_sequence; }; - - template - struct mp_make_int_seq_impl - { using type = typename next_integer_sequence::type>::type; }; - - template - struct mp_make_int_seq_impl - { using type = mp_integer_sequence; }; - - template - struct mp_repeat_impl - { - using _l1 = typename mp_repeat_impl::type; - using _l2 = typename mp_repeat_impl::type; - using type = mp_append<_l1, _l1, _l2>; - }; - - template struct mp_repeat_impl<0, T...> - { using type = mp_list<>; }; - - template struct mp_repeat_impl<1, T...> - { using type = mp_list; }; - - - - /* list operations returning a numeric value */ - template class L, class... T> - struct mp_size_impl> - { using type = mp_length; }; - - template class L, class... T, class V> - struct mp_count_impl, V> - { using type = mp_size_t::value...)>; }; - - template class L, class... T, template class P> - struct mp_count_if_impl, P> - { using type = mp_size_t::value...)>; }; - - - - /* operations to manipulate list content */ - template class L, class... U, class... T> - struct mp_push_front_impl, T...> - { using type = L; }; - - template class L, class T1, class... T> - struct mp_pop_front_impl> - { using type = L; }; - - template class L, class... U, class... T> - struct mp_push_back_impl, T...> - { using type = L; }; - - template class L1, template class L2, class... T1, class... T2> - struct mp_concat_impl, L2> - { using type = L1; }; - - template class L1, template class L2, class... T1, class... T2, class... L> - struct mp_concat_impl, L2, L...> - { - using _rest = mp_concat, L...>; - using type = mp_concat, _rest>; - }; - - template class L, template class F> - struct mp_filter_impl, F> - { using type = L<>; }; - - template class L, template class F, class T1, class... T> - struct mp_filter_impl, F> - { - using _rest = mp_filter, F>; - using _match = F; - using type = mp_eval_if_c<_match::value == 0, _rest, mp_push_front, _rest, T1>; - }; - - - - /* list operations returning a bool value */ - template class L1, class... T> - struct mp_empty_impl> - { using type = mp_bool::value == 0>; }; - - template class L1, class... T, class... L> - struct mp_empty_impl, L...> - { - static constexpr bool _first = !static_cast(mp_length::value); - static constexpr bool _other = static_cast(mp_empty::value); - using type = mp_bool<_first && _other>; - }; - - - - /* list operations returing elements from the list */ - template class L, class T1, class... T> - struct mp_front_impl> - { using type = T1; }; - - template class L, class T1, class T2, class... T> - struct mp_second_impl> - { using type = T2; }; - - template - struct mp_at_c_impl - { - using map = mp_map_from_list; - using type = mp_second>>; - }; - - template class F, class TDefault> - struct mp_search_helper; - - template class L, template class F, class TDefault, class T1, class... T> - struct mp_search_helper, F, TDefault> - { using type = T1; }; - - template class L, template class F, class TDefault, class T1, class... T> - struct mp_search_helper, F, TDefault> - { using type = mp_search, F, TDefault>; }; - - template class L, template class F, class TDefault> - struct mp_search_impl, F, TDefault> - { using type = TDefault; }; - - template class L, template class F, class TDefault, class T1, class... T> - struct mp_search_impl, F, TDefault> - { - using c_value = F; - using type = typename mp_search_helper, F, TDefault>::type; - }; - - template class L, class V> - struct mp_find_impl, V> - { using type = mp_zero; }; - - template class L, class... T, class V> - struct mp_find_impl, V> - { - static constexpr bool _v[] = { std::is_same::value... }; - using type = mp_size_t; - }; - - template class M, class... T, class K> - struct mp_map_find_impl, K> - { - static mp_identity f( ... ); - - template class L, class... U> - static mp_identity> - f( mp_identity>* ); - - using U = mp_inherit...>; - using V = decltype( f((U*)0) ); - using type = typename V::type; - }; - - - - /* list manipulators returning a new list */ - template class L, class... T> - struct mp_clear_impl> - { using type = L<>; }; - - template class L, class... T> - struct mp_unique_impl, L> - { using type = L; }; - - template class L, class C, class T1, class... T> - struct mp_unique_impl, C> - { - using type = mp_if< - mp_contains, - typename mp_unique_impl, C>::type, - typename mp_unique_impl, mp_push_back>::type - >; - }; - - template class A, class... T, template class B> - struct mp_rename_impl, B> - { using type = B; }; - - template<> - struct mp_append_impl<> - { using type = mp_list<>; }; - - template class L, class... T> - struct mp_append_impl> - { using type = L; }; - - template< - template class L1, class... T1, - template class L2, class... T2, class... Lr> - struct mp_append_impl, L2, Lr...> - { using type = mp_append, Lr...>; }; - - template class L, class... T, size_t... J> - struct mp_map_from_list_impl, mp_integer_sequence> - { using type = mp_list, T>...>; }; - - template class F, class L1, class... L> - struct mp_transform_impl - { using type = mp_clear; }; - - template class F, class... L> - struct mp_transform_impl - { - using _first = F< typename mp_front_impl::type... >; - using _rest = mp_transform< F, typename mp_pop_front_impl::type... >; - using type = mp_push_front<_rest, _first>; - }; - - - - /* unique id */ - template - struct mp_unique_counter - { - static inline size_t next() - { - static size_t value; - return value++; - } - }; - - template - struct mp_unique_id - { - static inline size_t value() - { - static const size_t value = mp_unique_counter::next(); - return value; - } - }; - - - - /* string */ - template - struct mp_string_impl - { - private: - const char (&_data)[N + 1]; - - public: - inline std::string str() const - { return std::string(_data, N); } - - inline constexpr const char* data() const - { return _data; } - - inline constexpr size_t size() const - { return N; } - - inline constexpr char operator[](size_t i) const - { return X_ASSERT(i >= 0 && i < N), _data[i]; } - - constexpr mp_string_impl(const char (&data)[N + 1]) : - _data((X_ASSERT(data[N] == '\0'), data)) - { } - }; - - template - struct mp_string_impl - { - private: - constexpr static size_t strsize(const char* s) - { - size_t ret = 0; - while (s[ret] != 0) - ++ret; - return ret; - } - - private: - char _data[N + 1]; - - template - constexpr mp_string_impl( - const mp_string_impl< N1, T1>& s1, - const mp_string_impl& s2, - mp_index_sequence, - mp_index_sequence) : - _data { s1[I1]..., s2[I2]..., '\0' } - { } - - public: - inline std::string str() const - { return std::string(_data, N); } - - inline constexpr const char* data() const - { return _data; } - - inline constexpr size_t size() const - { return N; } - - inline constexpr char operator[](size_t i) const - { return X_ASSERT(i >= 0 && i < N), _data[i]; } - - template> - constexpr mp_string_impl(char c) : - _data { c, '\0' } - { } - - template = true> - constexpr mp_string_impl( - const mp_string_impl& s1, - const mp_string_impl& s2) : - mp_string_impl(s1, s2, mp_make_index_sequence(), mp_make_index_sequence()) - { } - }; - - template - struct __int_to_char; - - template - struct __int_to_char= 0 && X::value <= 9>> - { static constexpr auto value = mp_array_string<1>('0' + X::value); }; - - template - struct __int_to_char= 10 && X::value <= 16>> - { static constexpr auto value = mp_array_string<1>('A' + X::value - 10); }; - - template - struct __int_to_string_helper - { - using _type = typename X::value_type; - using _next = mp_const<_type, X::value / static_cast<_type>(Base)>; - using _this = mp_const<_type, X::value % static_cast<_type>(Base)>; - static constexpr auto value = mp_string_cat( - __int_to_string_helper<_next, Base, _next::value == 0>::value, - __int_to_char<_this>::value); - }; - - template - struct __int_to_string_helper - { static constexpr auto value = mp_make_string(""); }; - - template - struct mp_int_to_string_impl - { - static constexpr auto value = __int_to_string_helper::value; - }; - - template class L, class... T> - struct mp_string_type_join_impl> - { - static constexpr auto value = mp_string_join(J::value, T::value...); - }; - - } -} \ No newline at end of file diff --git a/src/cpputils/mp/container.h b/src/cpputils/mp/container.h new file mode 100644 index 0000000..ce813a9 --- /dev/null +++ b/src/cpputils/mp/container.h @@ -0,0 +1,3 @@ +#pragma once + +#include \ No newline at end of file diff --git a/src/cpputils/mp/container/pair.h b/src/cpputils/mp/container/pair.h new file mode 100644 index 0000000..632bf98 --- /dev/null +++ b/src/cpputils/mp/container/pair.h @@ -0,0 +1,238 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace utl { +namespace mp { + + struct tag_pair { }; + + constexpr auto make_pair = make; + + namespace __impl + { + template + struct pair_index; + } + + template + struct pair : + private intern::ebo<__impl::pair_index<0>, First>, + private intern::ebo<__impl::pair_index<1>, Second> + { + using this_type = pair; + + // default constructor + template::value && + is_constructible::value>> + constexpr pair() + : intern::ebo<__impl::pair_index<0>, First>() + , intern::ebo<__impl::pair_index<1>, Second>() + { } + + // variadic constructors + template::value && + is_constructible::value>> + constexpr pair(First f, Second s) + : intern::ebo<__impl::pair_index<0>, First>(f) + , intern::ebo<__impl::pair_index<1>, Second>(s) + { } + + template::value && + is_convertible::value>> + constexpr pair(F&& f, S&& s) + : intern::ebo<__impl::pair_index<0>, First>(std::forward(f)) + , intern::ebo<__impl::pair_index<1>, Second>(std::forward(s)) + { } + + // copy and move constructor + template::value && + is_constructible::value && + is_convertible::value && + is_convertible::value>> + constexpr pair(const pair& other) + : intern::ebo<__impl::pair_index<0>, First>(mp::first(other)) + , intern::ebo<__impl::pair_index<1>, Second>(mp::second(other)) + { } + + template::value && + is_constructible::value && + is_convertible::value && + is_convertible::value>> + constexpr pair(pair&& other) + : intern::ebo<__impl::pair_index<0>, First>(mp::first(std::forward>(other))) + , intern::ebo<__impl::pair_index<1>, Second>(mp::second(std::forward>(other))) + { } + + // copy and move assignment + template ::value && + is_assignable::value>> + constexpr pair& operator=(const pair& other) { + mp::first(*this) = mp::first(other); + mp::second(*this) = mp::second(other); + return *this; + } + + template ::value && + is_assignable::value>> + constexpr pair& operator=(pair&& other) { + mp::first(*this) = mp::first(std::move>(other)); + mp::second(*this) = mp::second(std::move>(other)); + return *this; + } + + constexpr auto first() const + { return mp::first(*this); } + + constexpr auto second() const + { return mp::second(*this); } + + // Prevent the compiler from defining the default copy and move + // constructors, which interfere with the SFINAE above. + ~pair() = default; + + friend struct __impl::first_impl; + friend struct __impl::second_impl; + }; + + namespace intern { + + template<> + struct operators_comparable + { static constexpr bool value = true; }; + + template<> + struct operators_orderable + { static constexpr bool value = true; }; + + } + + namespace __impl + { + /* tag_of */ + template + struct tag_of_impl> + { using type = tag_pair; }; + + /* make */ + template<> + struct make_impl + { + template + static constexpr pair, decay_type> apply(F&& f, S&& s) + { return { static_cast(f), static_cast(s) }; } + }; + + /* first */ + template<> + struct first_impl + { + using type = int; + + template + static constexpr auto apply(pair& p) + { + return intern::ebo_get>( + static_cast, First>&>(p) + ); + } + + template + static constexpr auto apply(pair&& p) + { + return intern::ebo_get>( + static_cast, First>&&>(p) + ); + } + + template + static constexpr auto apply(const pair& p) + { + return intern::ebo_get>( + static_cast, First>&>(p) + ); + } + }; + + /* second */ + template<> + struct second_impl + { + template + static constexpr auto apply(pair& p) + { + return intern::ebo_get>( + static_cast, Second>&>(p) + ); + } + + template + static constexpr auto apply(pair&& p) + { + return intern::ebo_get>( + static_cast, Second>&&>(p) + ); + } + + template + static constexpr auto apply(const pair& p) + { + return intern::ebo_get>( + static_cast, Second>&>(p) + ); + } + }; + + /* equal */ + template<> + struct equal_impl + { + template + static constexpr auto apply(const L& l, const R& r) + { + return and_( + equal(first(l), first(r)), + equal(second(l), second(r))); + } + }; + + /* less */ + template<> + struct less_impl + { + template + static constexpr auto apply(const L& l, const R& r) + { + return or_( + less(first(l), first(r)), + and_( + less_equal(first (l), first (r)), + less (second(l), second(r)) + ) + ); + } + }; + } + +} +} \ No newline at end of file diff --git a/src/cpputils/mp/core.h b/src/cpputils/mp/core.h index 9cf8b82..ab9db5a 100644 --- a/src/cpputils/mp/core.h +++ b/src/cpputils/mp/core.h @@ -1,168 +1,7 @@ -#include -#include +#pragma once -namespace utl { -namespace mp { - - /*********************************************************************************************/ - /* types *************************************************************************************/ - /*********************************************************************************************/ - template - struct tag_const { }; - - template - struct integral_constant : - public std::integral_constant - { - using tag = tag_const; - }; - - template - constexpr integral_constant make_const { }; - - template - using c_bool = integral_constant; - - template - using c_size_t = integral_constant; - - template - struct list { }; - - template - struct inherit : T... - { }; - - template - struct integer_sequence - { }; - - template - using index_sequence = integer_sequence; - - - - /*********************************************************************************************/ - /* constants *********************************************************************************/ - /*********************************************************************************************/ - using c_true = c_bool; - using c_false = c_bool; - using c_zero = c_size_t<0>; - - - - /*********************************************************************************************/ - /* modifier **********************************************************************************/ - /*********************************************************************************************/ - template - using add_pointer = T*; - - template - using add_reference = T&; - - template - using remove_ptr = typename std::remove_pointer::type; - - template - using remove_const = typename std::remove_const::type; - - template - using remove_cv = typename std::remove_cv::type; - - template - using remove_ref = typename std::remove_reference::type; - - template - using clean_type = remove_cv>>; - - namespace __impl /* forward declaration */ - { - template> - struct decay_impl; - } - - template - using decay = typename __impl::decay_impl::type; - - namespace __impl /* implementation */ - { - template > - struct decay - { using type = remove_cv; }; - - template - struct decay - { using type = U*; }; - - template - struct decay - { using type = U*; }; - - template - struct decay - { using type = R(*)(A...); }; - - template - struct decay - { using type = R(*)(A..., ...); }; - } - - - - /*********************************************************************************************/ - /* conditionals ******************************************************************************/ - /*********************************************************************************************/ - namespace __impl /* forward declaration */ - { - template - struct if_c_impl; - - template typename E, typename... A> - struct eval_if_c_impl; - } - - template - using is_same = c_bool::value>; - - template - using is_base_of = c_bool::value>; - - template - using enable_if = typename std::enable_if::type; - - template - using enable_if_c = typename std::enable_if::type; - - template - using if_t = typename __impl::if_c_impl::type; - - template - using if_c = typename __impl::if_c_impl::type; - - template typename E, typename... A> - using eval_if = typename __impl::eval_if_c_impl::type; - - template typename E, typename... A> - using eval_if_c = typename __impl::eval_if_c_impl::type; - - namespace __impl /* implementation */ - { - template - struct if_c_impl - { using type = T; }; - - template - struct if_c_impl - { using type = F; }; - - template typename E, typename... A> - struct eval_if_c_impl - { using type = T; }; - - template typename E, typename... A> - struct eval_if_c_impl - { using type = E; }; - } - -} -} \ No newline at end of file +#include +#include +#include +#include +#include \ No newline at end of file diff --git a/src/cpputils/mp/core/checker.h b/src/cpputils/mp/core/checker.h new file mode 100644 index 0000000..77907cd --- /dev/null +++ b/src/cpputils/mp/core/checker.h @@ -0,0 +1,51 @@ +#pragma once + +#include +#include + +namespace utl { +namespace mp { + + namespace __impl /* forward declaration */ + { + template + struct is_valid_impl; + } + + template + using is_same = c_bool::value>; + + template + using is_base_of = c_bool::value>; + + template + using is_constructible = c_bool::value>; + + template + using is_empty = c_bool::value>; + + template + using is_final = c_bool::value>; + + template + using is_convertible = c_bool::value>; + + template + using is_assignable = c_bool::value>; + + template + using is_valid = __impl::is_valid_impl; + + template + using is_arithmetic = c_bool::value>; + + namespace __impl /* implementation */ + { + template + struct is_valid_impl : + public c_true + { }; + } + +} +} \ No newline at end of file diff --git a/src/cpputils/mp/core/conditionals.h b/src/cpputils/mp/core/conditionals.h new file mode 100644 index 0000000..73fd489 --- /dev/null +++ b/src/cpputils/mp/core/conditionals.h @@ -0,0 +1,53 @@ +#pragma once + +namespace utl { +namespace mp { + + namespace __impl /* forward declaration */ + { + template + struct if_c_impl; + + template class E, typename... A> + struct eval_if_c_impl; + } + + template + using enable_if = typename std::enable_if::type; + + template + using enable_if_c = typename std::enable_if::type; + + template + using if_t = typename __impl::if_c_impl::type; + + template + using if_c = typename __impl::if_c_impl::type; + + template class E, typename... A> + using eval_if_t = typename __impl::eval_if_c_impl::type; + + template class E, typename... A> + using eval_if_c = typename __impl::eval_if_c_impl::type; + + namespace __impl /* implementation */ + { + template + struct if_c_impl + { using type = T; }; + + template + struct if_c_impl + { using type = F; }; + + template class E, typename... A> + struct eval_if_c_impl + { using type = T; }; + + template class E, typename... A> + struct eval_if_c_impl + { using type = E; }; + } + +} +} \ No newline at end of file diff --git a/src/cpputils/mp/core/const.h b/src/cpputils/mp/core/const.h new file mode 100644 index 0000000..5f9c404 --- /dev/null +++ b/src/cpputils/mp/core/const.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include + +namespace utl { +namespace mp { + + template + struct tag_const { }; + + template + struct integral_constant : + public std::integral_constant + { + using tag = tag_const; + }; + + template + using c_bool = integral_constant; + + template + using c_size_t = integral_constant; + + using c_true = c_bool; + using c_false = c_bool; + using c_zero = c_size_t<0>; + +} +} \ No newline at end of file diff --git a/src/cpputils/mp/core/modifier.h b/src/cpputils/mp/core/modifier.h new file mode 100644 index 0000000..1190a3a --- /dev/null +++ b/src/cpputils/mp/core/modifier.h @@ -0,0 +1,78 @@ +#pragma once + +#include + +namespace utl { +namespace mp { + + template + using add_pointer = T*; + + template + using add_reference = T&; + + template + using remove_ptr = typename std::remove_pointer::type; + + template + using remove_const = typename std::remove_const::type; + + template + using remove_cv = typename std::remove_cv::type; + + template + using remove_ref = typename std::remove_reference::type; + + template + using clean_type = remove_cv>>; + + namespace __impl /* forward declaration */ + { + template> + struct decay_impl; + + template + struct common_type_impl + { }; + } + + template + using decay = __impl::decay_impl; + + template + using decay_type = typename __impl::decay_impl::type; + + template + using common_type = __impl::common_type_impl; + + namespace __impl /* implementation */ + { + /* decay */ + template + struct decay_impl + { using type = remove_cv; }; + + template + struct decay_impl + { using type = U*; }; + + template + struct decay_impl + { using type = U*; }; + + template + struct decay_impl + { using type = R(*)(A...); }; + + template + struct decay_impl + { using type = R(*)(A..., ...); }; + + /* common_type */ + template + struct common_type_impl() : std::declval()))> + { using type = decay() : std::declval()))>; }; + } + +} +} \ No newline at end of file diff --git a/src/cpputils/mp/core/types.h b/src/cpputils/mp/core/types.h new file mode 100644 index 0000000..f73c1f2 --- /dev/null +++ b/src/cpputils/mp/core/types.h @@ -0,0 +1,10 @@ +#pragma once + +namespace utl { +namespace mp { + + template + using void_t = void; + +} +} \ No newline at end of file diff --git a/src/cpputils/mp/intern.h b/src/cpputils/mp/intern.h new file mode 100644 index 0000000..5f6f0e7 --- /dev/null +++ b/src/cpputils/mp/intern.h @@ -0,0 +1,3 @@ +#pragma once + +#include \ No newline at end of file diff --git a/src/cpputils/mp/intern/comparable_equal.h b/src/cpputils/mp/intern/comparable_equal.h new file mode 100644 index 0000000..a51ab12 --- /dev/null +++ b/src/cpputils/mp/intern/comparable_equal.h @@ -0,0 +1,39 @@ +#pragma once + +#include +#include + +namespace utl { +namespace mp { +namespace intern { + + template + struct comparable_equal + : c_false + { }; + + template + struct comparable_equal(std::declval()) == std::forward(std::declval()) ? 0 : 0), + decltype(std::forward(std::declval()) != std::forward(std::declval()) ? 0 : 0)>> + : c_true + { }; + + template + struct comparable_equal::value, + void_t< + decltype(std::forward(std::declval()) == std::forward(std::declval()) ? 0 : 0), + decltype(std::forward(std::declval()) == std::forward(std::declval()) ? 0 : 0), + decltype(std::forward(std::declval()) != std::forward(std::declval()) ? 0 : 0), + decltype(std::forward(std::declval()) != std::forward(std::declval()) ? 0 : 0), + common_type>>> + : c_bool< + comparable_equal::value && + comparable_equal::value && + comparable_equal>::value> + { }; + +} +} +} \ No newline at end of file diff --git a/src/cpputils/mp/intern/comparable_less.h b/src/cpputils/mp/intern/comparable_less.h new file mode 100644 index 0000000..c012b93 --- /dev/null +++ b/src/cpputils/mp/intern/comparable_less.h @@ -0,0 +1,36 @@ +#pragma once + +#include +#include + +namespace utl { +namespace mp { +namespace intern { + + template + struct comparable_less + : c_false + { }; + + template + struct comparable_less(std::declval()) < std::forward(std::declval()) ? 0 : 0)>> + : c_true + { }; + + template + struct comparable_less::value, + void_t< + decltype(std::forward(std::declval()) < std::forward(std::declval()) ? 0 : 0), + decltype(std::forward(std::declval()) < std::forward(std::declval()) ? 0 : 0), + common_type>>> + : c_bool< + comparable_less::value && + comparable_less::value && + comparable_less>::value> + { }; + +} +} +} \ No newline at end of file diff --git a/src/cpputils/mp/intern/ebo.h b/src/cpputils/mp/intern/ebo.h new file mode 100644 index 0000000..297e82d --- /dev/null +++ b/src/cpputils/mp/intern/ebo.h @@ -0,0 +1,83 @@ +#pragma once + +#include "../core.h" + +namespace utl { +namespace mp { +namespace intern { + + template::value && !is_final::value> + struct ebo; + + template + constexpr const Value& ebo_get(const ebo& x) + { return x; } + + template + constexpr Value& ebo_get(ebo& x) + { return x; } + + template + constexpr Value&& ebo_get(ebo&& x) + { return x; } + + template + constexpr const Value& ebo_get(const ebo& x) + { return x._data; } + + template + constexpr Value& ebo_get(ebo& x) + { return x._data; } + + template + constexpr Value&& ebo_get(ebo&& x) + { return static_cast(x._data); } + + template + struct ebo : + public Value + { + constexpr ebo() + { } + + template + explicit constexpr ebo(T&& t) : + Value(std::forward(t)) + { } + + constexpr auto get() const& + { return ebo_get(*this); } + + constexpr auto get() & + { return ebo_get(*this); } + + constexpr auto get() && + { return ebo_get(std::move(*this)); } + }; + + template + struct ebo + { + Value _data; + + constexpr ebo() + { } + + template + explicit constexpr ebo(T&& t) : + _data(std::forward(t)) + { } + + constexpr auto get() const& + { return ebo_get(*this); } + + constexpr auto get() & + { return ebo_get(*this); } + + constexpr auto get() && + { return ebo_get(std::move(*this)); } + }; + +} +} +} \ No newline at end of file diff --git a/src/cpputils/mp/intern/has_value.h b/src/cpputils/mp/intern/has_value.h new file mode 100644 index 0000000..11a94aa --- /dev/null +++ b/src/cpputils/mp/intern/has_value.h @@ -0,0 +1,16 @@ +#pragma once + +#include + +namespace utl { +namespace mp { +namespace intern { + + template + struct has_value + : c_bool>>::value> + { }; + +} +} +} \ No newline at end of file diff --git a/src/cpputils/mp/intern/operators_comparable.h b/src/cpputils/mp/intern/operators_comparable.h new file mode 100644 index 0000000..353f34f --- /dev/null +++ b/src/cpputils/mp/intern/operators_comparable.h @@ -0,0 +1,36 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace utl { +namespace mp { + + namespace intern { + + template + struct operators_comparable + { static constexpr bool value = false; }; + + } + + namespace operators + { + template>::value && + intern::operators_comparable>::value>> + constexpr auto operator == (X&& x, Y&& y) + { return equal(std::forward(x), std::forward(y)); } + + template>::value && + intern::operators_comparable>::value>> + constexpr auto operator != (X&& x, Y&& y) + { return not_equal(std::forward(x), std::forward(y)); } + } + +} +} \ No newline at end of file diff --git a/src/cpputils/mp/intern/operators_orderable.h b/src/cpputils/mp/intern/operators_orderable.h new file mode 100644 index 0000000..7cf3514 --- /dev/null +++ b/src/cpputils/mp/intern/operators_orderable.h @@ -0,0 +1,50 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace utl { +namespace mp { + + namespace intern { + + template + struct operators_orderable + { static constexpr bool value = false; }; + + } + + namespace operators + { + template>::value && + intern::operators_orderable>::value>> + constexpr auto operator < (X&& x, Y&& y) + { return less(std::forward(x), std::forward(y)); } + + template>::value && + intern::operators_orderable>::value>> + constexpr auto operator <= (X&& x, Y&& y) + { return less_equal(std::forward(x), std::forward(y)); } + + template>::value && + intern::operators_orderable>::value>> + constexpr auto operator > (X&& x, Y&& y) + { return greater(std::forward(x), std::forward(y)); } + + template>::value && + intern::operators_orderable>::value>> + constexpr auto operator >= (X&& x, Y&& y) + { return greater_equal(std::forward(x), std::forward(y)); } + } + +} +} \ No newline at end of file diff --git a/src/cpputils/mp/operations.h b/src/cpputils/mp/operations.h new file mode 100644 index 0000000..c0c84fe --- /dev/null +++ b/src/cpputils/mp/operations.h @@ -0,0 +1,6 @@ +#pragma once + +#include +#include +#include +#include \ No newline at end of file diff --git a/src/cpputils/mp/operations/compare.h b/src/cpputils/mp/operations/compare.h new file mode 100644 index 0000000..bc0690a --- /dev/null +++ b/src/cpputils/mp/operations/compare.h @@ -0,0 +1,4 @@ +#pragma once + +#include +#include \ No newline at end of file diff --git a/src/cpputils/mp/operations/compare/equal.h b/src/cpputils/mp/operations/compare/equal.h new file mode 100644 index 0000000..6ae499a --- /dev/null +++ b/src/cpputils/mp/operations/compare/equal.h @@ -0,0 +1,73 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace utl { +namespace mp { + + namespace __impl + { + struct equal_t + { + template + constexpr auto operator()(const L& l, const R& r) const; + }; + } + + constexpr __impl::equal_t equal { }; + + namespace __impl + { + template + struct equal_impl + : equal_impl> + { }; + + template + struct equal_impl> + : default_ + { + template + static constexpr auto apply(Args&& ...) + { return c_false { }; } + }; + + template + struct equal_impl::value>> + { + template + static constexpr auto apply(X&& x, Y&& y) + { return static_cast(x) == static_cast(y); } + }; + + template + struct equal_impl::value>> + { + template + static constexpr auto apply(const X&, const Y&) + { + constexpr auto eq = equal(value(), value()); + constexpr bool truth_value = if_ (eq, true, false); + return c_bool { }; + } + }; + + template + constexpr auto equal_t::operator()(const L& l, const R& r) const + { + using l_tag_type = tag_of; + using r_tag_type = tag_of; + using equal_type = equal_impl; + return equal_type::apply(l, r); + } + } + +} +} \ No newline at end of file diff --git a/src/cpputils/mp/operations/compare/greater.h b/src/cpputils/mp/operations/compare/greater.h new file mode 100644 index 0000000..3778d68 --- /dev/null +++ b/src/cpputils/mp/operations/compare/greater.h @@ -0,0 +1,51 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace utl { +namespace mp { + + namespace __impl + { + struct greater_t + { + template + constexpr auto operator()(const L& l, const R& r) const; + }; + } + + constexpr __impl::greater_t greater { }; + + namespace __impl + { + template + struct greater_impl + : greater_impl> + { }; + + template + struct greater_impl> + : default_ + { + template + static constexpr auto apply(X&& x, Y&& y) + { return less(static_cast(y), static_cast(x)); } + }; + + template + constexpr auto greater_t::operator()(const L& l, const R& r) const + { + using l_tag_type = tag_of; + using r_tag_type = tag_of; + using greater_impl_type = greater_impl; + return greater_impl_type::apply(l, r); + } + } + +} +} \ No newline at end of file diff --git a/src/cpputils/mp/operations/compare/greater_equal.h b/src/cpputils/mp/operations/compare/greater_equal.h new file mode 100644 index 0000000..5edb04e --- /dev/null +++ b/src/cpputils/mp/operations/compare/greater_equal.h @@ -0,0 +1,51 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace utl { +namespace mp { + + namespace __impl + { + struct greater_equal_t + { + template + constexpr auto operator()(const L& l, const R& r) const; + }; + } + + constexpr __impl::greater_equal_t greater_equal { }; + + namespace __impl + { + template + struct greater_equal_impl + : greater_equal_impl> + { }; + + template + struct greater_equal_impl> + : default_ + { + template + static constexpr auto apply(X&& x, Y&& y) + { return not_(less(static_cast(x), static_cast(y))); } + }; + + template + constexpr auto greater_equal_t::operator()(const L& l, const R& r) const + { + using l_tag_type = tag_of; + using r_tag_type = tag_of; + using greater_equal_impl_type = greater_equal_impl; + return greater_equal_impl_type::apply(l, r); + } + } + +} +} \ No newline at end of file diff --git a/src/cpputils/mp/operations/compare/less.h b/src/cpputils/mp/operations/compare/less.h new file mode 100644 index 0000000..0241226 --- /dev/null +++ b/src/cpputils/mp/operations/compare/less.h @@ -0,0 +1,73 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace utl { +namespace mp { + + namespace __impl + { + struct less_t + { + template + constexpr auto operator()(const L& l, const R& r) const; + }; + } + + constexpr __impl::less_t less { }; + + namespace __impl + { + template + struct less_impl + : less_impl> + { }; + + template + struct less_impl> + : default_ + { + template + static constexpr auto apply(Args&& ...) + { return c_false { }; } + }; + + template + struct less_impl::value>> + { + template + static constexpr auto apply(X&& x, Y&& y) + { return static_cast(x) < static_cast(y); } + }; + + template + struct less_impl::value>> + { + template + static constexpr auto apply(const X&, const Y&) + { + constexpr auto eq = less(value(), value()); + constexpr bool truth_value = if_ (eq, true, false); + return c_bool { }; + } + }; + + template + constexpr auto less_t::operator()(const L& l, const R& r) const + { + using l_tag_type = tag_of; + using r_tag_type = tag_of; + using less_type = less_impl; + return less_type::apply(l, r); + } + } + +} +} \ No newline at end of file diff --git a/src/cpputils/mp/operations/compare/less_equal.h b/src/cpputils/mp/operations/compare/less_equal.h new file mode 100644 index 0000000..2b91092 --- /dev/null +++ b/src/cpputils/mp/operations/compare/less_equal.h @@ -0,0 +1,51 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace utl { +namespace mp { + + namespace __impl + { + struct less_equal_t + { + template + constexpr auto operator()(const L& l, const R& r) const; + }; + } + + constexpr __impl::less_equal_t less_equal { }; + + namespace __impl + { + template + struct less_equal_impl + : less_equal_impl> + { }; + + template + struct less_equal_impl> + : default_ + { + template + static constexpr auto apply(X&& x, Y&& y) + { return not_(less(static_cast(y), static_cast(x))); } + }; + + template + constexpr auto less_equal_t::operator()(const L& l, const R& r) const + { + using l_tag_type = tag_of; + using r_tag_type = tag_of; + using less_equal_impl_type = less_equal_impl; + return less_equal_impl_type::apply(l, r); + } + } + +} +} \ No newline at end of file diff --git a/src/cpputils/mp/operations/compare/not_equal.h b/src/cpputils/mp/operations/compare/not_equal.h new file mode 100644 index 0000000..cabd242 --- /dev/null +++ b/src/cpputils/mp/operations/compare/not_equal.h @@ -0,0 +1,51 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace utl { +namespace mp { + + namespace __impl + { + struct not_equal_t + { + template + constexpr auto operator()(const L& l, const R& r) const; + }; + } + + constexpr __impl::not_equal_t not_equal { }; + + namespace __impl + { + template + struct not_equal_impl + : not_equal_impl> + { }; + + template + struct not_equal_impl> + : default_ + { + template + static constexpr auto apply(X&& x, Y&& y) + { return not(equal(std::forward(x), std::forward(y))); } + }; + + template + constexpr auto not_equal_t::operator()(const L& l, const R& r) const + { + using l_tag_type = tag_of; + using r_tag_type = tag_of; + using not_equal_type = not_equal_impl; + return not_equal_type::apply(l, r); + } + } + +} +} \ No newline at end of file diff --git a/src/cpputils/mp/operations/eval.h b/src/cpputils/mp/operations/eval.h new file mode 100644 index 0000000..fab02a6 --- /dev/null +++ b/src/cpputils/mp/operations/eval.h @@ -0,0 +1,59 @@ +#pragma once + +#include +#include +#include +#include + +namespace utl { +namespace mp { + + namespace __impl + { + struct eval_t + { + template + constexpr auto operator()(Expr&& expr) const; + }; + } + + constexpr __impl::eval_t eval { }; + + namespace __impl + { + template + struct eval_impl + : eval_impl> + { }; + + template + struct eval_impl> + : default_ + { + template + static constexpr auto eval_helper(Expr&& expr, int) + { return static_cast(expr)(); } + + template + static constexpr auto eval_helper(Expr&&, ...) + { + static_assert(wrong { }, + "eval(expr) requires the expression to be a a nullary Callable"); + } + + template + static constexpr decltype(auto) apply(Expr&& expr) + { return eval_helper(static_cast(expr), int { }); } + }; + + template + constexpr auto eval_t::operator()(Expr&& expr) const + { + using tag_type = tag_of; + using eval_impl_type = eval_impl; + return eval_impl_type::apply(std::forward(expr));; + } + } + +} +} \ No newline at end of file diff --git a/src/cpputils/mp/operations/eval_if.h b/src/cpputils/mp/operations/eval_if.h new file mode 100644 index 0000000..a1b77e6 --- /dev/null +++ b/src/cpputils/mp/operations/eval_if.h @@ -0,0 +1,80 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace utl { +namespace mp { + + namespace __impl + { + struct eval_if_t + { + template + constexpr auto operator()(Cond&& c, Then&& t, Else&& e) const; + }; + } + + constexpr __impl::eval_if_t eval_if { }; + + namespace __impl + { + template + struct eval_if_impl + : eval_if_impl> + { }; + + template + struct eval_if_impl> + : default_ + { + template + static constexpr auto apply(Args&& ...) = delete; + }; + + template + struct eval_if_impl::value>> + { + template + static constexpr auto apply(const Cond& cond, Then&& t, Else&& e) + { + return cond ? eval(std::forward(t)) + : eval(std::forward(e)); + } + }; + + template + struct eval_if_impl::value>> + { + template + static constexpr auto eval_if_helper(c_true, Then&& t, Else&& e) + { return eval(std::forward(t)); } + + template + static constexpr auto eval_if_helper(c_false, Then&& t, Else&& e) + { return eval(std::forward(e)); } + + template + static constexpr auto apply(const Cond&, Then&& t, Else&& e) + { + constexpr auto cond = value(); + constexpr bool truth_value = if_(cond, true, false); + return eval_if_helper(c_bool { }, std::forward(t), std::forward(e)); + } + }; + + template + constexpr auto eval_if_t::operator()(Cond&& c, Then&& t, Else&& e) const + { + using tag_type = tag_of; + using eval_if_type = eval_if_impl; + return eval_if_type::apply(std::forward(c), std::forward(t), std::forward(e)); + } + } + +} +} \ No newline at end of file diff --git a/src/cpputils/mp/operations/first.h b/src/cpputils/mp/operations/first.h new file mode 100644 index 0000000..5cc75ca --- /dev/null +++ b/src/cpputils/mp/operations/first.h @@ -0,0 +1,46 @@ +#pragma once + +#include +#include +#include + +namespace utl { +namespace mp { + + namespace __impl + { + struct first_t + { + template + constexpr auto operator()(T&& t) const; + }; + } + + constexpr __impl::first_t first { }; + + namespace __impl + { + template + struct first_impl + : first_impl> + { }; + + template + struct first_impl> + : default_ + { + template + static constexpr auto apply(Args&& ...) = delete; + }; + + template + constexpr auto first_t::operator()(T&& t) const + { + using tag_type = tag_of; + using first_type = first_impl; + return first_type::apply(std::forward(t)); + } + } + +} +} \ No newline at end of file diff --git a/src/cpputils/mp/operations/if.fwd.h b/src/cpputils/mp/operations/if.fwd.h new file mode 100644 index 0000000..a79a8f3 --- /dev/null +++ b/src/cpputils/mp/operations/if.fwd.h @@ -0,0 +1,18 @@ +#pragma once + +namespace utl { +namespace mp { + + namespace __impl + { + struct if_t + { + template + constexpr auto operator()(Cond&& c, Then&& t, Else&& e) const; + }; + } + + constexpr __impl::if_t if_ { }; + +} +} \ No newline at end of file diff --git a/src/cpputils/mp/operations/if.h b/src/cpputils/mp/operations/if.h new file mode 100644 index 0000000..5cfac9c --- /dev/null +++ b/src/cpputils/mp/operations/if.h @@ -0,0 +1,52 @@ +#pragma once + +#include + +#include +#include +#include +#include + +namespace utl { +namespace mp { + + namespace __impl + { + template + struct hold { + T value; + constexpr T&& operator()() && + { return static_cast(value); } + }; + + template + struct if_impl + : if_impl> + { }; + + template + struct if_impl> + : default_ + { + template + static constexpr auto apply(Cond&& c, Then&& t, Else&& e) + { + return eval_if( + std::forward(c), + hold { static_cast(t) }, + hold { static_cast(e) } + ); + } + }; + + template + constexpr auto if_t::operator()(Cond&& c, Then&& t, Else&& e) const + { + using tag_type = tag_of; + using if_type = if_impl; + return if_type::apply(std::forward(c), std::forward(t), std::forward(e)); + } + } + +} +} \ No newline at end of file diff --git a/src/cpputils/mp/operations/logical.h b/src/cpputils/mp/operations/logical.h new file mode 100644 index 0000000..eb5c55b --- /dev/null +++ b/src/cpputils/mp/operations/logical.h @@ -0,0 +1,4 @@ +#pragma once + +#include +#include \ No newline at end of file diff --git a/src/cpputils/mp/operations/logical/and.h b/src/cpputils/mp/operations/logical/and.h new file mode 100644 index 0000000..e7ab46c --- /dev/null +++ b/src/cpputils/mp/operations/logical/and.h @@ -0,0 +1,63 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace utl { +namespace mp { + + namespace __impl + { + struct and_t + { + template + constexpr auto operator()(X&& x, Y&& y) const; + + template + constexpr auto operator()(X&& x, Y&&... y) const; + }; + } + + constexpr __impl::and_t and_ { }; + + namespace __impl + { + template + struct and_impl + : and_impl> + { }; + + template + struct and_impl> + : default_ + { + template + static constexpr auto apply(X&& x, Y&& y) + { return if_(x, static_cast(y), x); } + }; + + template + constexpr auto and_t::operator()(X&& x, Y&& y) const + { + using tag_type = tag_of; + using and_impl_type = and_impl; + return and_impl_type::apply(std::forward(x), std::forward(y)); + }; + /* TODO + template + constexpr auto and_t::operator()(X&& x, Y&& ...y) const + { + return detail::variadic::foldl1( + *this, + static_cast(x), + static_cast(y)... + ); + } + */ + } + +} +} \ No newline at end of file diff --git a/src/cpputils/mp/operations/logical/not.h b/src/cpputils/mp/operations/logical/not.h new file mode 100644 index 0000000..dd29455 --- /dev/null +++ b/src/cpputils/mp/operations/logical/not.h @@ -0,0 +1,55 @@ +#pragma once + +#include +#include +#include +#include + +namespace utl { +namespace mp { + + namespace __impl + { + struct not_t + { + template + constexpr auto operator()(X&& x) const; + }; + } + + constexpr __impl::not_t not_ { }; + + namespace __impl + { + template + struct not_impl + : not_impl> + { }; + + template + struct not_impl> + : default_ + { + template + static constexpr auto apply(Args&& ...) = delete; + }; + + template + struct not_impl::value>> + { + template + static constexpr auto apply(const X& x) + { return x ? false : true; } + }; + + template + constexpr auto not_t::operator()(X&& x) const + { + using tag_type = tag_of; + using not_impl_type = not_impl; + return not_impl_type::apply(std::forward(x)); + }; + } + +} +} \ No newline at end of file diff --git a/src/cpputils/mp/operations/logical/or.h b/src/cpputils/mp/operations/logical/or.h new file mode 100644 index 0000000..5805cd9 --- /dev/null +++ b/src/cpputils/mp/operations/logical/or.h @@ -0,0 +1,63 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace utl { +namespace mp { + + namespace __impl + { + struct or_t + { + template + constexpr auto operator()(X&& x, Y&& y) const; + + template + constexpr auto operator()(X&& x, Y&&... y) const; + }; + } + + constexpr __impl::or_t or_ { }; + + namespace __impl + { + template + struct or_impl + : or_impl> + { }; + + template + struct or_impl> + : default_ + { + template + static constexpr auto apply(X&& x, Y&& y) + { return if_(x, x, static_cast(y)); } + }; + + template + constexpr auto or_t::operator()(X&& x, Y&& y) const + { + using tag_type = tag_of; + using or_impl_type = or_impl; + return or_impl_type::apply(std::forward(x), std::forward(y)); + }; + /* TODO + template + constexpr auto or_t::operator()(X&& x, Y&& ...y) const + { + return detail::variadic::foldl1( + *this, + static_cast(x), + static_cast(y)... + ); + } + */ + } + +} +} \ No newline at end of file diff --git a/src/cpputils/mp/operations/second.h b/src/cpputils/mp/operations/second.h new file mode 100644 index 0000000..80e925f --- /dev/null +++ b/src/cpputils/mp/operations/second.h @@ -0,0 +1,46 @@ +#pragma once + +#include +#include +#include + +namespace utl { +namespace mp { + + namespace __impl + { + struct second_t + { + template + constexpr auto operator()(T&& t) const; + }; + } + + constexpr __impl::second_t second { }; + + namespace __impl + { + template + struct second_impl + : second_impl> + { }; + + template + struct second_impl> + : default_ + { + template + static constexpr auto apply(Args&& ...) = delete; + }; + + template + constexpr auto second_t::operator()(T&& t) const + { + using tag = tag_of; + using second = second_impl; + return second::apply(std::forward(t)); + } + } + +} +} \ No newline at end of file diff --git a/src/cpputils/mp/operations/value.h b/src/cpputils/mp/operations/value.h new file mode 100644 index 0000000..ab9975f --- /dev/null +++ b/src/cpputils/mp/operations/value.h @@ -0,0 +1,54 @@ +#pragma once + +#include +#include +#include + +namespace utl { +namespace mp { + + namespace __impl + { + template + struct value_impl; + } + + template + constexpr auto value() + { + using t_clean_type = clean_type; + using tag_type = tag_of; + using value_impl_type = __impl::value_impl; + return value_impl_type::template apply(); + } + + template + constexpr decltype(auto) value(T const&) + { return value(); } + + namespace __impl + { + template + struct value_impl + : value_impl> + { }; + + template + struct value_impl> + : default_ + { + template + static constexpr auto apply(Args&& ...args) = delete; + }; + + template + struct value_impl> + { + template + static constexpr auto apply() + { return C::value; } + }; + } + +} +} \ No newline at end of file diff --git a/src/cpputils/mp/util.h b/src/cpputils/mp/util.h index ae6bf59..d5ff0bc 100644 --- a/src/cpputils/mp/util.h +++ b/src/cpputils/mp/util.h @@ -1,151 +1,8 @@ -#include "core.h" - -namespace utl { -namespace mp { - - namespace __impl /* forward declaration */ - { - /* when */ - template - struct is_valid_impl; - - template - struct wrong_impl; - - /* default */ - template - struct is_default_impl; - - /* tag_of */ - template - struct tag_of_impl; - - /* is_a */ - template - struct is_a_impl; - - /* make */ - template - struct make_t; - } - - /* when */ - template - using is_valid = __impl::is_valid_impl; - - template - using wrong = __impl::wrong_impl; - - template - struct when; - - template - using when_valid = when::value>; - - /* default */ - template - using is_default = __impl::is_default_impl; - - /* tag_of */ - template - using tag_of = typename __impl::tag_of_impl::type; - - /* is_a */ - template - constexpr __impl::is_a_impl is_a { }; - - template - constexpr __impl::is_a_impl is_an { }; - - /* make */ - template - constexpr __impl::make_t make { }; - - namespace __impl /* implementation */ - { - /* when */ - template - struct is_valid_impl : - public c_true - { }; - - template - struct wrong_impl : - public c_false - { }; - - /* default */ - struct default_ { }; - - template - struct is_default_impl : - public c_false - { }; - - template - struct is_default_impl(std::declval()))> : - public c_true - { }; - - /* tag_of */ - template - struct tag_of_impl : - public tag_of_impl> - { }; - - template - struct tag_of_impl> - { using type = T; }; - - template - struct tag_of_impl::tag>> - { using type = typename clean_type::tag; }; - - /* is_a */ - template - struct is_a_impl : - public is_same> - { }; - - template - struct is_a_impl - { - template - constexpr auto operator()(const T&) const noexcept - { return is_a; } - }; - - /* make */ - template - struct make_impl : - public make_impl> - { }; - - template - struct make_impl> : - public default_ - { - template - static constexpr auto make_helper(int, X&&... x) - -> decltype(T(std::forward(x)...)) - { return T(std::forward(x)...); } - - template - static constexpr auto make_helper(long, X&&... x) - { static_assert((sizeof...(X), false), "there exists no constructor for the given data type"); } - - template - static constexpr auto apply(X&& ...x) - { return make_helper(int{}, std::forward(x)...); } - }; - - template - struct make_t - { - template - constexpr auto operator()(X&&... x) const noexcept - { return make_impl::apply(std::forward(x)...); } - }; - } -} -} \ No newline at end of file +#pragma once + +#include +#include +#include +#include +#include +#include \ No newline at end of file diff --git a/src/cpputils/mp/util/default.h b/src/cpputils/mp/util/default.h new file mode 100644 index 0000000..933513d --- /dev/null +++ b/src/cpputils/mp/util/default.h @@ -0,0 +1,33 @@ +#pragma once + +#include + +namespace utl { +namespace mp { + + namespace __impl /* forward declaration */ + { + template + struct is_default_impl; + } + + template + using is_default = __impl::is_default_impl; + + namespace __impl /* implementation */ + { + struct default_ { }; + + template + struct is_default_impl : + public c_false + { }; + + template + struct is_default_impl(std::declval()))> : + public c_true + { }; + } + +} +} \ No newline at end of file diff --git a/src/cpputils/mp/util/is_a.h b/src/cpputils/mp/util/is_a.h new file mode 100644 index 0000000..e48ebec --- /dev/null +++ b/src/cpputils/mp/util/is_a.h @@ -0,0 +1,38 @@ +#pragma once + +#include +#include + +namespace utl { +namespace mp { + + namespace __impl /* forward declaration */ + { + template + struct is_a_impl; + } + + template + constexpr __impl::is_a_impl is_a { }; + + template + constexpr __impl::is_a_impl is_an { }; + + namespace __impl /* implementation */ + { + template + struct is_a_impl : + public is_same> + { }; + + template + struct is_a_impl + { + template + constexpr auto operator()(const T&) const noexcept + { return is_a; } + }; + } + +} +} \ No newline at end of file diff --git a/src/cpputils/mp/util/make.h b/src/cpputils/mp/util/make.h new file mode 100644 index 0000000..624c5e4 --- /dev/null +++ b/src/cpputils/mp/util/make.h @@ -0,0 +1,55 @@ + +#pragma once + +#include +#include +#include + +namespace utl { +namespace mp { + + namespace __impl /* forward declaration */ + { + template + struct make_t; + } + + template + constexpr __impl::make_t make { }; + + namespace __impl /* implementation */ + { + template + struct make_impl : + public make_impl> + { }; + + template + struct make_impl> : + public default_ + { + template + static constexpr auto make_helper(int, X&&... x) + -> decltype(T(std::forward(x)...)) + { return T(std::forward(x)...); } + + template + static constexpr auto make_helper(long, X&&... x) + { static_assert((sizeof...(X), false), "there exists no constructor for the given data type"); } + + template + static constexpr auto apply(X&& ...x) + { return make_helper(int{}, std::forward(x)...); } + }; + + template + struct make_t + { + template + constexpr auto operator()(X&&... x) const noexcept + { return make_impl::apply(std::forward(x)...); } + }; + } + +} +} \ No newline at end of file diff --git a/src/cpputils/mp/util/tag_of.h b/src/cpputils/mp/util/tag_of.h new file mode 100644 index 0000000..72d94a2 --- /dev/null +++ b/src/cpputils/mp/util/tag_of.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include + +namespace utl { +namespace mp { + + namespace __impl /* forward declaration */ + { + template + struct tag_of_impl; + } + + template + using tag_of = typename __impl::tag_of_impl>::type; + + namespace __impl /* implementation */ + { + template + struct tag_of_impl : + public tag_of_impl> + { }; + + template + struct tag_of_impl> + { using type = T; }; + + template + struct tag_of_impl::tag>> + { using type = typename clean_type::tag; }; + } + +} +} \ No newline at end of file diff --git a/src/cpputils/mp/convert.h b/src/cpputils/mp/util/to.h similarity index 91% rename from src/cpputils/mp/convert.h rename to src/cpputils/mp/util/to.h index a34e77a..928e516 100644 --- a/src/cpputils/mp/convert.h +++ b/src/cpputils/mp/util/to.h @@ -1,39 +1,41 @@ -#include "util.h" +#pragma once + +#include +#include +#include namespace utl { namespace mp { namespace __impl /* forward declaration */ { - /* to */ template struct to_t; template - struct is_convertible_impl; + struct is_mp_convertible_impl; template struct is_embedded_impl; } - /* to */ template constexpr __impl::to_t to { }; template - using is_convertible = __impl::is_convertible_impl; + using is_mp_convertible = __impl::is_mp_convertible_impl; template using is_embedded = __impl::is_embedded_impl; namespace __impl /* implementation */ { - /* to */ struct no_conversion { }; template struct embedding { }; + /* to_impl */ template struct to_impl; @@ -68,6 +70,15 @@ namespace mp { { return std::forward(x); } }; + template + struct to_impl : + public embedding<> + { + static constexpr T* apply(decltype(nullptr)) + { return nullptr; } + }; + + /* to_t */ template struct to_t { @@ -138,24 +149,18 @@ namespace mp { #undef DEFINE_CHAR_EMBEDDING_IMPL - template - struct to_impl : - public embedding<> - { - static constexpr T* apply(decltype(nullptr)) - { return nullptr; } - }; - + /* is_mp_convertible_impl */ template - struct is_convertible_impl : + struct is_mp_convertible_impl : public std::true_type { }; template - struct is_convertible_impl(std::declval>()))> : + struct is_mp_convertible_impl(std::declval>()))> : public std::false_type { }; + /* is_embedded_impl */ template struct is_embedded_impl : public std::false_type diff --git a/src/cpputils/mp/util/when.h b/src/cpputils/mp/util/when.h new file mode 100644 index 0000000..8c87252 --- /dev/null +++ b/src/cpputils/mp/util/when.h @@ -0,0 +1,32 @@ +#pragma once + +#include + +namespace utl { +namespace mp { + + namespace __impl /* forward declaration */ + { + template + struct wrong_impl; + } + + template + struct when; + + template + using when_valid = when::value>; + + template + using wrong = __impl::wrong_impl; + + namespace __impl /* implementation */ + { + template + struct wrong_impl : + public c_false + { }; + } + +} +} \ No newline at end of file diff --git a/src/impl/logging/LoggerImpl.cpp.old b/src/impl/logging/LoggerImpl.cpp.old new file mode 100644 index 0000000..e303047 --- /dev/null +++ b/src/impl/logging/LoggerImpl.cpp.old @@ -0,0 +1,119 @@ +#include +#include + +#include "cpputils/logger_impl.h" + +using namespace logging; + +std::string EmptyString; + +consumer::consumer(const std::string& n, bool autoRegister) : + _name(n) +{ + if (autoRegister) + register_consumer(*this); +} + +consumer::~consumer() + { unregister_consumer(*this); } + +void consumer_stream::log(data_ptr_s data) +{ + std::lock_guard lk(_mutex); + + using namespace std; + if (!data) + return; + auto& d = *data; + auto t = std::chrono::duration_cast>>(d.time.time_since_epoch()).count(); + auto f = d.file; + if (f) + { + auto tmp = strrchr(f, '/'); + if (tmp) + f = tmp + 1; + } + else + f = "unknown"; + + StreamFormatSaver formatSaver(*_stream); + if (t >= 0) *_stream << "[" << fixed << setfill(' ') << setw(17) << setprecision(6) << t << "] "; + switch(d.level) + { + case level::Debug: *_stream << "DEBUG "; break; + case level::Info: *_stream << "INFO "; break; + case level::Warn: *_stream << "WARN "; break; + case level::Error: *_stream << "ERROR "; break; + } + + if (d.sender) *_stream << "0x" << hex << setw(2 * sizeof(void*)) << setfill('0') << d.sender; + else *_stream << " "; + if (d.thread != std::thread::id()) *_stream << "@" << hex << setw(2 * sizeof(void*)) << setfill('0') << d.thread; + else *_stream << " "; + if (!d.name.empty()) *_stream << " '" << d.name << "'"; + if (d.line) *_stream << " - " << setw(25) << setfill(' ') << f << ":" << setw(5) << setfill(' ') << dec << d.line; + if (!d.message.empty()) + { + *_stream << ": " << d.message; + if (d.message.back() != '\n') + *_stream << std::endl; + } + else + *_stream << std::endl; +} + + + +bool matcher_all::match(const logger& logger) const + { return true; } + +bool matcher_all::match(const consumer& consumer) const + { return true; } + +bool matcher_regex::match(const logger& logger) const + { return !logger.name().empty() && std::regex_match(logger.name(), _regex) != _invert; } + +bool matcher_regex::match(const consumer& consumer) const + { return !consumer.name().empty() && std::regex_match(consumer.name(), _regex) != _invert; } + +bool matcher_default::match(const logger& logger) const + { return &_defaultLogger == &logger; } + + + + +const std::string& logger::name() const + { return EmptyString; } + +bool logger::is_enabled(level level) const + { return false; } + +void logger::log(data_ptr_s data) const + { /* no op */ } + + + +const std::string& logger_impl::name() const + { return _name; } + +bool logger_impl::is_enabled(level level) const +{ + for (auto& rule : _rules) + { + if (rule->is_enabled(level)) + return true; + } + return false; +} + +void logger_impl::log(data_ptr_s data) const +{ + std::lock_guard lk(_mutex); + for (auto& r : _rules) + r->log(data); +} + +namespace logging +{ + +} \ No newline at end of file diff --git a/src/impl/logging/consumer/consumer.cpp b/src/impl/logging/consumer/consumer.cpp new file mode 100644 index 0000000..22914ad --- /dev/null +++ b/src/impl/logging/consumer/consumer.cpp @@ -0,0 +1,14 @@ +#include +#include + +using namespace ::utl::logging; + +consumer::consumer(const std::string& n, bool autoRegister) : + _name(n) +{ + if (autoRegister) + register_consumer(*this); +} + +consumer::~consumer() + { unregister_consumer(*this); } \ No newline at end of file diff --git a/src/impl/logging/consumer/consumer_stream.cpp b/src/impl/logging/consumer/consumer_stream.cpp new file mode 100644 index 0000000..ee293c2 --- /dev/null +++ b/src/impl/logging/consumer/consumer_stream.cpp @@ -0,0 +1,66 @@ +#include +#include +#include + +using namespace ::utl; +using namespace ::utl::logging; + +void consumer_stream::log(data_ptr_s data) +{ + std::lock_guard lk(_mutex); + + using namespace std; + if (!data) + return; + auto& d = *data; + auto t = std::chrono::duration_cast>>(d.time.time_since_epoch()).count(); + auto f = d.file; + if (f) + { + auto tmp = strrchr(f, '/'); + if (tmp) + f = tmp + 1; + } + else + f = "unknown"; + + stream_format_saver format_saver(*_stream); + if (t >= 0) *_stream << "[" << fixed << setfill(' ') << setw(17) << setprecision(6) << t << "] "; + switch(d.level) + { + case log_level::debug: *_stream << "DEBUG "; break; + case log_level::info: *_stream << "INFO "; break; + case log_level::warn: *_stream << "WARN "; break; + case log_level::error: *_stream << "ERROR "; break; + } + + if (d.sender) *_stream << "0x" << hex << setw(2 * sizeof(void*)) << setfill('0') << d.sender; + else *_stream << " "; + if (d.thread != std::thread::id()) *_stream << "@" << hex << setw(2 * sizeof(void*)) << setfill('0') << d.thread; + else *_stream << " "; + if (!d.name.empty()) *_stream << " '" << d.name << "'"; + if (d.line) *_stream << " - " << setw(25) << setfill(' ') << f << ":" << setw(5) << setfill(' ') << dec << d.line; + if (!d.message.empty()) + { + *_stream << ": " << d.message; + if (d.message.back() != '\n') + *_stream << std::endl; + } + else + *_stream << std::endl; +} + +consumer_stream::consumer_stream(const std::string& name, std::ostream& stream, bool ownsStream, bool autoRegister) : + consumer (name, autoRegister), + _stream (&stream), + _ownsStream (ownsStream) + { } + +consumer_stream::~consumer_stream() +{ + if (_ownsStream && _stream) + { + delete _stream; + _stream = nullptr; + } +} \ No newline at end of file diff --git a/src/impl/logging/global.cpp b/src/impl/logging/global.cpp new file mode 100644 index 0000000..9d992f6 --- /dev/null +++ b/src/impl/logging/global.cpp @@ -0,0 +1,129 @@ +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace utl { +namespace logging { + + struct manager + { + private: + logger_impl _default_logger; + std::map _logger; + std::list _rules; + std::set _consumer; + + logger_impl& initLogger(logger_impl& logger) + { + for (auto& rule : _rules) + { + if (rule.logger_matcher->match(logger)) + logger.registerRule(rule); + } + return logger; + } + + public: + inline logger& get_logger(const std::string& name) + { + if (name.empty()) + return _default_logger; + auto it = _logger.find(name); + return (it != _logger.end() + ? *it->second + : initLogger(*_logger.emplace(name, logger_impl_ptr_u(new logger_impl(name))).first->second)); + } + + void register_consumer(consumer& consumer) + { + _consumer.insert(&consumer); + for (auto& rule : _rules) + { + if (rule.consumer_matcher->match(consumer)) + rule.register_consumer(consumer); + } + } + + void unregister_consumer(consumer& consumer) + { + for (auto& rule : _rules) + rule.unregister_consumer(consumer); + } + + rule_handle define_rule(matcher_ptr_u logger_matcher, matcher_ptr_u consumer_matcher, log_level min_level, log_level max_level) + { + _rules.emplace_back(std::move(logger_matcher), std::move(consumer_matcher), min_level, max_level); + auto& rule = _rules.back(); + for (auto& c : _consumer) + { + if (rule.consumer_matcher->match(*c)) + rule.register_consumer(*c); + } + if (rule.logger_matcher->match(_default_logger)) + _default_logger.registerRule(rule); + for (auto& l : _logger) + { + if (rule.logger_matcher->match(*l.second)) + l.second->registerRule(rule); + } + return &rule; + } + + void undefine_rule(rule_handle handle) + { + auto r = static_cast(handle); + auto it = _rules.begin(); + while (&*it != r && it != _rules.end()) + ++it; + if (it == _rules.end()) + return; + _default_logger.unregisterRule(*it); + for (auto& l : _logger) + l.second->unregisterRule(*it); + _rules.erase(it); + } + + inline void reset() + { + _logger.clear(); + _rules.clear(); + _consumer.clear(); + } + + manager() : + _default_logger(std::string()) + { } + }; + + manager& get_manager() + { + static manager value; + return value; + } + + logger& get_logger(const std::string& name) + { return get_manager().get_logger(name); } + + void register_consumer(consumer& consumer) + { return get_manager().register_consumer(consumer); } + + void unregister_consumer(consumer& consumer) + { return get_manager().unregister_consumer(consumer); } + + rule_handle define_rule(matcher_ptr_u logger_matcher, matcher_ptr_u consumer_matcher, log_level min_level, log_level max_level) + { return get_manager().define_rule(std::move(logger_matcher), std::move(consumer_matcher), min_level, max_level); } + + void undefine_rule(rule_handle rule) + { return get_manager().undefine_rule(rule); } + + void reset_logging() + { get_manager().reset(); } + +} +} \ No newline at end of file diff --git a/src/impl/logging/logger.cpp b/src/impl/logging/logger.cpp new file mode 100644 index 0000000..d381c13 --- /dev/null +++ b/src/impl/logging/logger.cpp @@ -0,0 +1,15 @@ +#include + +using namespace ::utl::logging; + +const std::string& logger::name() const +{ + static std::string name; + return name; +} + +bool logger::is_enabled(log_level level) const + { return false; } + +void logger::log(data_ptr_s data) const + { /* no op */ } \ No newline at end of file diff --git a/src/impl/logging/logger_impl.cpp b/src/impl/logging/logger_impl.cpp new file mode 100644 index 0000000..cfffa66 --- /dev/null +++ b/src/impl/logging/logger_impl.cpp @@ -0,0 +1,23 @@ +#include + +using namespace ::utl::logging; + +const std::string& logger_impl::name() const + { return _name; } + +bool logger_impl::is_enabled(log_level level) const +{ + for (auto& rule : _rules) + { + if (rule->is_enabled(level)) + return true; + } + return false; +} + +void logger_impl::log(data_ptr_s data) const +{ + std::lock_guard lk(_mutex); + for (auto& r : _rules) + r->log(data); +} diff --git a/src/impl/logging/matcher.cpp b/src/impl/logging/matcher.cpp new file mode 100644 index 0000000..128b173 --- /dev/null +++ b/src/impl/logging/matcher.cpp @@ -0,0 +1,41 @@ +#include + +using namespace ::utl::logging; + +/* matcher */ + +bool matcher::match(const logger& logger) const + { return false; } + +bool matcher::match(const consumer& consumer) const + { return false; } + +/* matcher_all */ + +bool matcher_all::match(const logger& logger) const + { return true; } + +bool matcher_all::match(const consumer& consumer) const + { return true; } + +/* matcher_regex */ + +bool matcher_regex::match(const logger& logger) const + { return !logger.name().empty() && std::regex_match(logger.name(), _regex) != _invert; } + +bool matcher_regex::match(const consumer& consumer) const + { return !consumer.name().empty() && std::regex_match(consumer.name(), _regex) != _invert; } + +matcher_regex::matcher_regex(const std::string expression, bool invert) : + _regex (expression), + _invert (invert) + { } + +/* matcher_default */ + +bool matcher_default::match(const logger& logger) const + { return &_defaultLogger == &logger; } + +matcher_default::matcher_default() : + _defaultLogger(get_logger(std::string())) + { } \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index c6eca7d..c95fe8b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -8,6 +8,7 @@ If ( __COTIRE_INCLUDED ) EndIf ( ) Target_Link_Libraries ( test_cpputils + cpputils gtest gmock gmock_main diff --git a/test/EnumConversionTests.cpp b/test/EnumConversionTests.cpp deleted file mode 100644 index c1287f9..0000000 --- a/test/EnumConversionTests.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include - -namespace enum_conversion_tests -{ - #include "../src/cpputils/EnumConversion.h" - - enum class TestEnum - { - Test0, - Test1, - Test2, - Test3 - }; - - DefEnumToStringMap( - TestEnum, - { TestEnum::Test0, "Test0" }, - { TestEnum::Test1, "Test1" }, - { TestEnum::Test2, "Test2" }, - { TestEnum::Test3, "Test3" } - ); - - DefStringToEnumMap( - TestEnum, - InvariantStringLess, - { "test0", TestEnum::Test0 }, - { "test1", TestEnum::Test1 }, - { "test2", TestEnum::Test2 }, - { "test3", TestEnum::Test3 } - ); -} - -using namespace ::testing; -using namespace ::enum_conversion_tests; -using namespace ::enum_conversion_tests::utl; - -TEST(EnumConversionTests, toString) -{ - EXPECT_EQ(std::string("Test0(0)"), utl::EnumConversion::toString(TestEnum::Test0, true)); - EXPECT_EQ(std::string("Test1"), utl::EnumConversion::toString(TestEnum::Test1, false)); - EXPECT_EQ(std::string("Test2(2)"), utl::EnumConversion::toString(TestEnum::Test2, true)); - EXPECT_EQ(std::string("Test3"), utl::EnumConversion::toString(TestEnum::Test3, false)); - EXPECT_EQ(std::string("123"), utl::EnumConversion::toString(static_cast(123), true)); -} - -TEST(EnumConversionTests, toEnum) -{ - TestEnum e; - EXPECT_TRUE (utl::EnumConversion::tryToEnum("test0", e, false)); - EXPECT_EQ (TestEnum::Test0, e); - - EXPECT_TRUE (utl::EnumConversion::tryToEnum("Test1", e, false)); - EXPECT_EQ (TestEnum::Test1, e); - - EXPECT_FALSE(utl::EnumConversion::tryToEnum("asd", e, false)); - - EXPECT_FALSE(utl::EnumConversion::tryToEnum("1", e, false)); - - EXPECT_TRUE (utl::EnumConversion::tryToEnum("2", e, true)); - EXPECT_EQ (TestEnum::Test2, e); -} \ No newline at end of file diff --git a/test/FlagsTests.cpp b/test/FlagsTests.cpp deleted file mode 100644 index da2eb78..0000000 --- a/test/FlagsTests.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#include - -namespace flags_tests -{ - #include "../src/cpputils/Flags.h" -} - -using namespace ::testing; -using namespace ::flags_tests::utl; - -enum class TestFlag : uint8_t -{ - value0, - value1, - value2, - value3, - value4 -}; - -using TestFlags = ShiftedFlags; - -TEST(FlagsTest, ctor) -{ - TestFlags f0; - EXPECT_EQ(0, f0()); - - TestFlags f1({ TestFlag::value1, TestFlag::value3 }); - EXPECT_EQ(10, f1()); - - TestFlags f2(f1); - EXPECT_EQ(10, f2()); - - TestFlags f3(TestFlag::value3); - EXPECT_EQ(8, f3()); -} - -TEST(FlagsTest, set) -{ - TestFlags f; - EXPECT_FALSE(static_cast(f)); - f.set(TestFlag::value1); - EXPECT_TRUE(static_cast(f)); - EXPECT_TRUE(f[TestFlag::value1]); -} - -TEST(FlagsTest, isSet) -{ - TestFlags f({ TestFlag::value1, TestFlag::value3 }); - - EXPECT_FALSE(f[TestFlag::value0]); - EXPECT_TRUE (f[TestFlag::value1]); - EXPECT_FALSE(f[TestFlag::value2]); - EXPECT_TRUE (f[TestFlag::value3]); - EXPECT_FALSE(f[TestFlag::value4]); - - EXPECT_FALSE(f.isSet(TestFlag::value0)); - EXPECT_TRUE (f.isSet(TestFlag::value1)); - EXPECT_FALSE(f.isSet(TestFlag::value2)); - EXPECT_TRUE (f.isSet(TestFlag::value3)); - EXPECT_FALSE(f.isSet(TestFlag::value4)); -} - -TEST(FlagsTest, clear) -{ - TestFlags f({ TestFlag::value1, TestFlag::value3 }); - f.clear(TestFlag::value1); - EXPECT_FALSE(f.isSet(TestFlag::value1)); - EXPECT_TRUE (f.isSet(TestFlag::value3)); -} - -TEST(FlagsTest, reset) -{ - TestFlags f({ TestFlag::value1, TestFlag::value3 }); - f.reset(); - EXPECT_FALSE(static_cast(f)); -} \ No newline at end of file diff --git a/test/HandleManagerTests.cpp b/test/HandleManagerTests.cpp deleted file mode 100644 index ba01398..0000000 --- a/test/HandleManagerTests.cpp +++ /dev/null @@ -1,120 +0,0 @@ -#include -#include "../src/cpputils/StringHelper.h" -#include "../src/cpputils/HandleManager.h" - -using namespace utl; - -using HandleManagerInt = utl::HandleManager; - -TEST(HandleManagerTest, fromString_toString) -{ - Handle handle; - EXPECT_FALSE(tryFromString("11-22-3344-5566778", handle)); - EXPECT_TRUE (tryFromString("11-22-3344-55667788", handle)); - EXPECT_EQ (std::string("11-22-3344-55667788"), toString(handle)); - EXPECT_TRUE (tryFromString("1122-3344-55667788", handle)); - EXPECT_EQ (std::string("11-22-3344-55667788"), toString(handle)); - EXPECT_TRUE (tryFromString("11-223344-55667788", handle)); - EXPECT_EQ (std::string("11-22-3344-55667788"), toString(handle)); - EXPECT_TRUE (tryFromString("11-22-334455667788", handle)); - EXPECT_EQ (std::string("11-22-3344-55667788"), toString(handle)); - EXPECT_TRUE (tryFromString("1122334455667788", handle)); - EXPECT_EQ (std::string("11-22-3344-55667788"), toString(handle)); -} - -TEST(HandleManagerTest, insert) -{ - HandleManagerInt manager; - auto handle = manager.insert(0, 0, 123); - EXPECT_TRUE(static_cast(handle)); -} - -TEST(HandleManagerTest, remove) -{ - HandleManagerInt manager; - auto handle = manager.insert(0, 0, 123); - EXPECT_FALSE(manager.remove(156161)); - EXPECT_FALSE(manager.remove(1136)); - EXPECT_FALSE(manager.remove(627624)); - EXPECT_FALSE(manager.remove(0)); - EXPECT_TRUE (manager.remove(handle)); -} - -TEST(HandleManagerTest, clear) -{ - HandleManagerInt manager; - auto handle1 = manager.insert(0, 0, 123); - manager.clear(); - auto handle2 = manager.insert(0, 0, 555); - EXPECT_EQ(handle1, handle2); -} - -TEST(HandleManagerTest, isValid) -{ - HandleManagerInt manager; - EXPECT_FALSE(manager.isValid(0)); - EXPECT_FALSE(manager.isValid(123)); - EXPECT_FALSE(manager.isValid(51627)); - EXPECT_FALSE(manager.isValid(1513)); - EXPECT_FALSE(manager.isValid(16621)); - - auto handle = manager.insert(0, 0, 123); - EXPECT_TRUE(manager.isValid(handle)); -} - -TEST(HandleManagerTest, tryGet) -{ - int val; - HandleManagerInt manager; - EXPECT_FALSE(manager.tryGet(123, val)); - EXPECT_FALSE(manager.tryGet(5132, val)); - EXPECT_FALSE(manager.tryGet(6216, val)); - EXPECT_FALSE(manager.tryGet(15616724, val)); - EXPECT_FALSE(manager.tryGet(12353, val)); - - auto handle = manager.insert(1, 2, 555); - EXPECT_TRUE(manager.tryGet(handle, val)); - EXPECT_EQ (555, val); -} - -TEST(HandleManagerTest, get) -{ - HandleManagerInt manager; - EXPECT_ANY_THROW(manager.get(123)); - EXPECT_ANY_THROW(manager.get(5132)); - EXPECT_ANY_THROW(manager.get(6216)); - EXPECT_ANY_THROW(manager.get(15616724)); - EXPECT_ANY_THROW(manager.get(12353)); - - auto handle = manager.insert(1, 2, 555); - EXPECT_EQ(555, manager.get(handle)); -} - -TEST(HandleManagerTest, update) -{ - HandleManagerInt manager; - EXPECT_FALSE(manager.update(123, 555)); - EXPECT_FALSE(manager.update(5132, 555)); - EXPECT_FALSE(manager.update(6216, 555)); - EXPECT_FALSE(manager.update(15616724, 555)); - EXPECT_FALSE(manager.update(12353, 555)); - - auto handle = manager.insert(1, 2, 555); - EXPECT_TRUE(manager.update(handle, 554)); - EXPECT_EQ (554, manager.get(handle)); -} - -TEST(HandleManagerTest, set) -{ - HandleManagerInt manager; - auto handle = fromString("00-00-0001-00000000"); - EXPECT_TRUE (manager.set(handle, 555)); - EXPECT_EQ (555, manager.get(handle)); - - handle = fromString("00-00-0001-00000000"); - EXPECT_TRUE (manager.set(handle, 554)); - EXPECT_EQ (554, manager.get(handle)); - - EXPECT_FALSE(manager.set(fromString("00-00-0002-00000000"), 553)); - EXPECT_EQ (554, manager.get(handle)); -} \ No newline at end of file diff --git a/test/LoggingTests.cpp b/test/LoggingTests.cpp deleted file mode 100644 index 2e8f0bd..0000000 --- a/test/LoggingTests.cpp +++ /dev/null @@ -1,135 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace logging_tests -{ - #include "../src/LoggerImpl.cpp" -} - -using namespace ::testing; -using namespace ::logging_tests; -using namespace ::logging_tests::logging; - -struct LoggingReset -{ - ~LoggingReset() - { ::logging_tests::logging::resetLogging(); } -}; - -struct ConsumerMock : public Consumer -{ - MOCK_METHOD1(log, void (DataPtrS data)); - - ConsumerMock(const std::string& n) : - Consumer(n, true) - { } -}; - -MATCHER_P5(MatchLogData, level, sender, thread, name, message, "") -{ - if (!arg) - return false; - auto& d = *arg; - return d.level == level - && d.sender == sender - && d.thread == thread - && d.name == name - && d.message == message; -} - -TEST(LoggingTests, AllMatcher) -{ - LoggingReset loggingReset; - StreamConsumer c0("TestConsumer1", std::cout, false, false); - StreamConsumer c1("TestConsumer2", std::cout, false, false); - - auto& l0 = getLogger(); - auto& l1 = getLogger("TestLogger"); - - AllMatcher matcher; - - EXPECT_TRUE(matcher.match(c0)); - EXPECT_TRUE(matcher.match(c1)); - EXPECT_TRUE(matcher.match(l0)); - EXPECT_TRUE(matcher.match(l1)); -} - -TEST(LoggingTests, DefaultLoggerMatcher) -{ - LoggingReset loggingReset; - StreamConsumer c0("TestConsumer1", std::cout, false, false); - StreamConsumer c1("TestConsumer2", std::cout, false, false); - - auto& l0 = getLogger(); - auto& l1 = getLogger("TestLogger"); - - DefaultLoggerMatcher matcher; - - EXPECT_FALSE(matcher.match(c0)); - EXPECT_FALSE(matcher.match(c1)); - EXPECT_TRUE (matcher.match(l0)); - EXPECT_FALSE(matcher.match(l1)); -} - -TEST(LoggingTests, RegexMatcher) -{ - LoggingReset loggingReset; - StreamConsumer c0("TestConsumer1", std::cout, false, false); - StreamConsumer c1("TestConsumer2", std::cout, false, false); - - auto& l0 = getLogger(); - auto& l1 = getLogger("TestLogger"); - - RegexMatcher matcher0("TestConsumer1"); - RegexMatcher matcher1("ASEF", true); - - EXPECT_TRUE (matcher0.match(c0)); - EXPECT_FALSE(matcher0.match(c1)); - EXPECT_FALSE(matcher1.match(l0)); - EXPECT_TRUE (matcher1.match(l1)); -} - -TEST(LoggingTests, log) -{ - LoggingReset loggingReset; - StrictMock c0("consumer0"); - StrictMock c1("Consumer1"); - - EXPECT_CALL(c0, log(MatchLogData( - Level::Info, - (void*)12, - std::this_thread::get_id(), - std::string("logger0"), - std::string("test1 info")))); - - EXPECT_CALL(c0, log(MatchLogData( - Level::Warn, - (void*)13, - std::this_thread::get_id(), - std::string("logger0"), - std::string("test1 warn")))); - - defineRule(MatcherPtrU(new RegexMatcher("logger0")), MatcherPtrU(new RegexMatcher("consumer0")), Level::Info, Level::Warn); - - auto& l0 = getLogger("logger0"); - auto& l1 = getLogger("logger1"); - - logMessage(l0, Debug, (void*)11, "test1 ") << "debug"; - logMessage(l0, Info, (void*)12, "test1 ") << "info"; - logMessage(l0, Warn, (void*)13, "test1 ") << "warn"; - logMessage(l0, Error, (void*)14, "test1 ") << "error"; - - logMessage(l1, Debug, (void*)21, "test2 ") << "debug"; - logMessage(l1, Info, (void*)22, "test2 ") << "info"; - logMessage(l1, Warn, (void*)23, "test2 ") << "warn"; - logMessage(l1, Error, (void*)24, "test2 ") << "error"; -} - diff --git a/test/MiscTests.cpp b/test/MiscTests.cpp deleted file mode 100644 index 0adf8dd..0000000 --- a/test/MiscTests.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include - -namespace utils_tests -{ - #include "../src/cpputils/Misc.h" -} - -using namespace ::testing; -using namespace ::utils_tests::utl; - -TEST(UtilsTests, bitCount) -{ - EXPECT_EQ(0, bitCount(0b0000'0000'0000'0000'0000'0000'0000'0000u)); - EXPECT_EQ(1, bitCount(0b0000'0000'0000'0000'0000'0000'0000'1000u)); - EXPECT_EQ(2, bitCount(0b0000'0000'0000'0000'0000'1000'0000'1000u)); - EXPECT_EQ(3, bitCount(0b0000'0000'0010'0000'0000'1000'0000'1000u)); - EXPECT_EQ(4, bitCount(0b0010'0000'0010'0000'0000'1000'0000'1000u)); - EXPECT_EQ(5, bitCount(0b0010'0000'0010'0000'0000'1000'1000'1000u)); - EXPECT_EQ(6, bitCount(0b0010'0000'0010'0000'0000'1000'1000'1001u)); - EXPECT_EQ(7, bitCount(0b0010'0000'0010'0000'0000'1000'1000'1101u)); - EXPECT_EQ(8, bitCount(0b0010'0100'0010'0000'0000'1000'1000'1101u)); -} \ No newline at end of file diff --git a/test/StringHelperTests.cpp b/test/StringHelperTests.cpp deleted file mode 100644 index ba42eb4..0000000 --- a/test/StringHelperTests.cpp +++ /dev/null @@ -1,97 +0,0 @@ -#include -#include -#include - -namespace string_helper_tests -{ - #include "../src/cpputils/StringHelper.h" - - enum class TestEnum - { - Test0, - Test1, - Test2, - Test3 - }; - - DefEnumToStringMap( - TestEnum, - { TestEnum::Test0, "Test0" }, - { TestEnum::Test1, "Test1" }, - { TestEnum::Test2, "Test2" }, - { TestEnum::Test3, "Test3" } - ); - - DefStringToEnumMap( - TestEnum, - InvariantStringLess, - { "test0", TestEnum::Test0 }, - { "test1", TestEnum::Test1 }, - { "test2", TestEnum::Test2 }, - { "test3", TestEnum::Test3 } - ); - - struct TestClass1 - { - int i; - - std::string toString() const - { return std::to_string(i); } - - bool fromString(const std::string& s) - { return static_cast(std::istringstream(s) >> i); } - }; - - struct TestClass2 - { - int i; - - void toString(std::ostream& os) const - { os << i; } - - static bool fromString(const std::string& s, TestClass2& v) - { return static_cast(std::istringstream(s) >> v.i); } - }; -} - -using namespace ::testing; -using namespace ::string_helper_tests; -using namespace ::string_helper_tests::utl; - -TEST(StringHelperTests, toString) -{ - EXPECT_EQ(std::string("4.5"), utl::toString(4.5)); - EXPECT_EQ(std::string("test"), utl::toString("test")); - EXPECT_EQ(std::string("fuu"), utl::toString(std::string("fuu"))); - EXPECT_EQ(std::string("Test1(1)"), utl::toString(TestEnum::Test1)); - EXPECT_EQ(std::string("5"), utl::toString(TestClass1 { 5 })); - EXPECT_EQ(std::string("6"), utl::toString(TestClass2 { 6 })); -} - -TEST(StringHelperTests, fromString) -{ - double d; - EXPECT_FALSE(utl::tryFromString("abc", d)); - EXPECT_TRUE (utl::tryFromString("4.5", d)); - EXPECT_TRUE (d >= 4.5 && d <= 4.5); - - int i; - EXPECT_FALSE(utl::tryFromString("abc", i)); - EXPECT_TRUE (utl::tryFromString("123", i)); - EXPECT_EQ (123, i); - - TestEnum e; - EXPECT_FALSE(utl::tryFromString("abc", e)); - EXPECT_TRUE (utl::tryFromString("test1", e)); - EXPECT_EQ (TestEnum::Test1, e); - - TestClass1 t1; - EXPECT_FALSE(utl::tryFromString("abc", t1)); - EXPECT_TRUE (utl::tryFromString("11", t1)); - EXPECT_EQ (11, t1.i); - - TestClass2 t2; - EXPECT_FALSE(utl::tryFromString("abc", t2)); - EXPECT_TRUE (utl::tryFromString("12", t2)); - EXPECT_EQ (12, t2.i); -} \ No newline at end of file diff --git a/test/container/handle_manager.cpp b/test/container/handle_manager.cpp new file mode 100644 index 0000000..4439a08 --- /dev/null +++ b/test/container/handle_manager.cpp @@ -0,0 +1,120 @@ +#include +#include +#include + +using namespace utl; + +using handle_manager_int = utl::handle_manager; + +TEST(handle_manager_tests, from_string_to_string) +{ + handle h; + EXPECT_FALSE(try_from_string("11-22-3344-5566778", h)); + EXPECT_TRUE (try_from_string("11-22-3344-55667788", h)); + EXPECT_EQ (std::string("11-22-3344-55667788"), to_string(h)); + EXPECT_TRUE (try_from_string("1122-3344-55667788", h)); + EXPECT_EQ (std::string("11-22-3344-55667788"), to_string(h)); + EXPECT_TRUE (try_from_string("11-223344-55667788", h)); + EXPECT_EQ (std::string("11-22-3344-55667788"), to_string(h)); + EXPECT_TRUE (try_from_string("11-22-334455667788", h)); + EXPECT_EQ (std::string("11-22-3344-55667788"), to_string(h)); + EXPECT_TRUE (try_from_string("1122334455667788", h)); + EXPECT_EQ (std::string("11-22-3344-55667788"), to_string(h)); +} + +TEST(handle_manager_tests, insert) +{ + handle_manager_int manager; + auto handle = manager.insert(0, 0, 123); + EXPECT_TRUE(static_cast(handle)); +} + +TEST(handle_manager_tests, remove) +{ + handle_manager_int manager; + auto handle = manager.insert(0, 0, 123); + EXPECT_FALSE(manager.remove(156161)); + EXPECT_FALSE(manager.remove(1136)); + EXPECT_FALSE(manager.remove(627624)); + EXPECT_FALSE(manager.remove(0)); + EXPECT_TRUE (manager.remove(handle)); +} + +TEST(handle_manager_tests, clear) +{ + handle_manager_int manager; + auto handle1 = manager.insert(0, 0, 123); + manager.clear(); + auto handle2 = manager.insert(0, 0, 555); + EXPECT_EQ(handle1, handle2); +} + +TEST(handle_manager_tests, is_valid) +{ + handle_manager_int manager; + EXPECT_FALSE(manager.is_valid(0)); + EXPECT_FALSE(manager.is_valid(123)); + EXPECT_FALSE(manager.is_valid(51627)); + EXPECT_FALSE(manager.is_valid(1513)); + EXPECT_FALSE(manager.is_valid(16621)); + + auto handle = manager.insert(0, 0, 123); + EXPECT_TRUE(manager.is_valid(handle)); +} + +TEST(handle_manager_tests, try_get) +{ + int val; + handle_manager_int manager; + EXPECT_FALSE(manager.try_get(123, val)); + EXPECT_FALSE(manager.try_get(5132, val)); + EXPECT_FALSE(manager.try_get(6216, val)); + EXPECT_FALSE(manager.try_get(15616724, val)); + EXPECT_FALSE(manager.try_get(12353, val)); + + auto handle = manager.insert(1, 2, 555); + EXPECT_TRUE(manager.try_get(handle, val)); + EXPECT_EQ (555, val); +} + +TEST(handle_manager_tests, get) +{ + handle_manager_int manager; + EXPECT_ANY_THROW(manager.get(123)); + EXPECT_ANY_THROW(manager.get(5132)); + EXPECT_ANY_THROW(manager.get(6216)); + EXPECT_ANY_THROW(manager.get(15616724)); + EXPECT_ANY_THROW(manager.get(12353)); + + auto handle = manager.insert(1, 2, 555); + EXPECT_EQ(555, manager.get(handle)); +} + +TEST(handle_manager_tests, update) +{ + handle_manager_int manager; + EXPECT_FALSE(manager.update(123, 555)); + EXPECT_FALSE(manager.update(5132, 555)); + EXPECT_FALSE(manager.update(6216, 555)); + EXPECT_FALSE(manager.update(15616724, 555)); + EXPECT_FALSE(manager.update(12353, 555)); + + auto handle = manager.insert(1, 2, 555); + EXPECT_TRUE(manager.update(handle, 554)); + EXPECT_EQ (554, manager.get(handle)); +} + +TEST(handle_manager_tests, set) +{ + handle_manager_int manager; + auto handle = from_string("00-00-0001-00000000"); + EXPECT_TRUE (manager.set(handle, 555)); + EXPECT_EQ (555, manager.get(handle)); + + handle = from_string("00-00-0001-00000000"); + EXPECT_TRUE (manager.set(handle, 554)); + EXPECT_EQ (554, manager.get(handle)); + + EXPECT_FALSE(manager.set(from_string("00-00-0002-00000000"), 553)); + EXPECT_EQ (554, manager.get(handle)); +} \ No newline at end of file diff --git a/test/NullableTests.cpp b/test/container/nullable.cpp similarity index 65% rename from test/NullableTests.cpp rename to test/container/nullable.cpp index 36a6c4e..d75c434 100644 --- a/test/NullableTests.cpp +++ b/test/container/nullable.cpp @@ -1,50 +1,44 @@ -#include -#include #include +#include -namespace nullable_tests +struct TestData { - #include "../src/cpputils/Nullable.h" + static int ctorCount; + static int dtorCount; - struct TestData - { - static int ctorCount; - static int dtorCount; + TestData() + { ++ctorCount; } - TestData() - { ++ctorCount; } + ~TestData() + { ++dtorCount; } +}; - ~TestData() - { ++dtorCount; } - }; - - struct NonCopyableTestData - { - int value; +struct NonCopyableTestData +{ + int value; - NonCopyableTestData(int v) : - value(v) - { } + NonCopyableTestData(int v) : + value(v) + { } - NonCopyableTestData(NonCopyableTestData&& other) : - value(0) - { std::swap(value, other.value); } + NonCopyableTestData(NonCopyableTestData&& other) : + value(0) + { std::swap(value, other.value); } - NonCopyableTestData(const NonCopyableTestData&) = delete; - }; + NonCopyableTestData(const NonCopyableTestData&) = delete; +}; - using NullableInt = utl::Nullable; - using NullableIntRef = utl::Nullable; - using NullableString = utl::Nullable; - using NullableTestData = utl::Nullable; - using NullableNonCopyableTestData = utl::Nullable; +using NullableInt = utl::nullable; +using NullableIntRef = utl::nullable; +using NullableString = utl::nullable; +using NullableTestData = utl::nullable; +using NullableNonCopyableTestData = utl::nullable; - int TestData::ctorCount = 0; - int TestData::dtorCount = 0; -} +int TestData::ctorCount = 0; +int TestData::dtorCount = 0; -using namespace nullable_tests; -using namespace nullable_tests::utl; +using namespace ::utl; +using namespace ::testing; TEST(NullableTest, ctor_empty) { @@ -102,7 +96,7 @@ TEST(NullableTest, movable_object) NonCopyableTestData data(5); NullableNonCopyableTestData tmp; tmp = std::move(data); - ASSERT_TRUE ( tmp.hasValue() ); + ASSERT_TRUE ( tmp.has_value() ); ASSERT_EQ ( 5, tmp.value().value ); ASSERT_EQ ( 0, data.value ); } @@ -110,18 +104,18 @@ TEST(NullableTest, movable_object) TEST(NullableTest, hasValue_operatorBool) { EXPECT_FALSE(static_cast(NullableInt())); - EXPECT_FALSE(NullableInt().hasValue()); + EXPECT_FALSE(NullableInt().has_value()); EXPECT_TRUE (static_cast(NullableInt(5))); - EXPECT_TRUE (NullableInt(5).hasValue()); + EXPECT_TRUE (NullableInt(5).has_value()); } TEST(NullableTest, reset) { NullableTestData n(TestData{}); - EXPECT_TRUE (n.hasValue()); + EXPECT_TRUE (n.has_value()); int tmp = TestData::dtorCount; n.reset(); - EXPECT_FALSE(n.hasValue()); + EXPECT_FALSE(n.has_value()); EXPECT_EQ (tmp + 1, TestData::dtorCount); } diff --git a/test/logging/logging_tests.cpp b/test/logging/logging_tests.cpp new file mode 100644 index 0000000..d773394 --- /dev/null +++ b/test/logging/logging_tests.cpp @@ -0,0 +1,124 @@ +#include +#include +#include +#include +#include + +using namespace ::testing; +using namespace ::utl::logging; + +struct LoggingReset +{ + ~LoggingReset() + { reset_logging(); } +}; + +struct consumer_mock : public consumer +{ + MOCK_METHOD1(log, void (data_ptr_s data)); + + consumer_mock(const std::string& n) : + consumer(n, true) + { } +}; + +MATCHER_P5(MatchLogData, level, sender, thread, name, message, "") +{ + if (!arg) + return false; + auto& d = *arg; + return d.level == level + && d.sender == sender + && d.thread == thread + && d.name == name + && d.message == message; +} + +TEST(LoggingTests, matcher_all) +{ + LoggingReset loggingReset; + consumer_stream c0("TestConsumer1", std::cout, false, false); + consumer_stream c1("TestConsumer2", std::cout, false, false); + + auto& l0 = get_logger(); + auto& l1 = get_logger("TestLogger"); + + matcher_all matcher; + + EXPECT_TRUE(matcher.match(c0)); + EXPECT_TRUE(matcher.match(c1)); + EXPECT_TRUE(matcher.match(l0)); + EXPECT_TRUE(matcher.match(l1)); +} + +TEST(LoggingTests, matcher_default) +{ + LoggingReset loggingReset; + consumer_stream c0("TestConsumer1", std::cout, false, false); + consumer_stream c1("TestConsumer2", std::cout, false, false); + + auto& l0 = get_logger(); + auto& l1 = get_logger("TestLogger"); + + matcher_default matcher; + + EXPECT_FALSE(matcher.match(c0)); + EXPECT_FALSE(matcher.match(c1)); + EXPECT_TRUE (matcher.match(l0)); + EXPECT_FALSE(matcher.match(l1)); +} + +TEST(LoggingTests, matcher_regex) +{ + LoggingReset loggingReset; + consumer_stream c0("TestConsumer1", std::cout, false, false); + consumer_stream c1("TestConsumer2", std::cout, false, false); + + auto& l0 = get_logger(); + auto& l1 = get_logger("TestLogger"); + + matcher_regex matcher0("TestConsumer1"); + matcher_regex matcher1("ASEF", true); + + EXPECT_TRUE (matcher0.match(c0)); + EXPECT_FALSE(matcher0.match(c1)); + EXPECT_FALSE(matcher1.match(l0)); + EXPECT_TRUE (matcher1.match(l1)); +} + +TEST(LoggingTests, log) +{ + LoggingReset loggingReset; + StrictMock c0("consumer0"); + StrictMock c1("Consumer1"); + + EXPECT_CALL(c0, log(MatchLogData( + log_level::info, + (void*)12, + std::this_thread::get_id(), + std::string("logger0"), + std::string("test1 info")))); + + EXPECT_CALL(c0, log(MatchLogData( + log_level::warn, + (void*)13, + std::this_thread::get_id(), + std::string("logger0"), + std::string("test1 warn")))); + + define_rule(matcher_ptr_u(new matcher_regex("logger0")), matcher_ptr_u(new matcher_regex("consumer0")), log_level::info, log_level::warn); + + auto& l0 = get_logger("logger0"); + auto& l1 = get_logger("logger1"); + + log_message(l0, debug, (void*)11, "test1 ") << "debug"; + log_message(l0, info, (void*)12, "test1 ") << "info"; + log_message(l0, warn, (void*)13, "test1 ") << "warn"; + log_message(l0, error, (void*)14, "test1 ") << "error"; + + log_message(l1, debug, (void*)21, "test2 ") << "debug"; + log_message(l1, info, (void*)22, "test2 ") << "info"; + log_message(l1, warn, (void*)23, "test2 ") << "warn"; + log_message(l1, error, (void*)24, "test2 ") << "error"; +} + diff --git a/test/misc/enum.cpp b/test/misc/enum.cpp new file mode 100644 index 0000000..b6aa45b --- /dev/null +++ b/test/misc/enum.cpp @@ -0,0 +1,65 @@ +#include +#include + +enum class TestEnum +{ + Test0, + Test1, + Test2, + Test3 +}; + +DEFINE_ENUM_TO_STRING_MAP( + TestEnum, + { TestEnum::Test0, "Test0" }, + { TestEnum::Test1, "Test1" }, + { TestEnum::Test2, "Test2" }, + { TestEnum::Test3, "Test3" } +); + +DEFINE_STRING_TO_ENUM_MAP( + TestEnum, + invariant_string_less, + { "test0", TestEnum::Test0 }, + { "test1", TestEnum::Test1 }, + { "test2", TestEnum::Test2 }, + { "test3", TestEnum::Test3 } +); + +using namespace ::utl; +using namespace ::testing; + +TEST(enum_tests, to_string) +{ + EXPECT_EQ(std::string("Test1(1)"), utl::to_string(TestEnum::Test1)); + EXPECT_EQ(std::string("Test0(0)"), utl::enum_conversion::to_string(TestEnum::Test0, true)); + EXPECT_EQ(std::string("Test1"), utl::enum_conversion::to_string(TestEnum::Test1, false)); + EXPECT_EQ(std::string("Test2(2)"), utl::enum_conversion::to_string(TestEnum::Test2, true)); + EXPECT_EQ(std::string("Test3"), utl::enum_conversion::to_string(TestEnum::Test3, false)); + EXPECT_EQ(std::string("123"), utl::enum_conversion::to_string(static_cast(123), true)); +} + +TEST(enum_tests, from_string) +{ + TestEnum e; + EXPECT_FALSE(utl::try_from_string("abc", e)); + EXPECT_TRUE (utl::try_from_string("test1", e)); + EXPECT_EQ (TestEnum::Test1, e); +} + +TEST(enum_tests, to_enum) +{ + TestEnum e; + EXPECT_TRUE (utl::enum_conversion::try_to_enum("test0", e, false)); + EXPECT_EQ (TestEnum::Test0, e); + + EXPECT_TRUE (utl::enum_conversion::try_to_enum("Test1", e, false)); + EXPECT_EQ (TestEnum::Test1, e); + + EXPECT_FALSE(utl::enum_conversion::try_to_enum("asd", e, false)); + + EXPECT_FALSE(utl::enum_conversion::try_to_enum("1", e, false)); + + EXPECT_TRUE (utl::enum_conversion::try_to_enum("2", e, true)); + EXPECT_EQ (TestEnum::Test2, e); +} \ No newline at end of file diff --git a/test/misc/flags.cpp b/test/misc/flags.cpp new file mode 100644 index 0000000..2fed43d --- /dev/null +++ b/test/misc/flags.cpp @@ -0,0 +1,72 @@ +#include +#include + +using namespace ::utl; +using namespace ::testing; + +enum class TestFlag : uint8_t +{ + value0, + value1, + value2, + value3, + value4 +}; + +using Testflags = shifted_flags; + +TEST(flagsTest, ctor) +{ + Testflags f0; + EXPECT_EQ(0, f0()); + + Testflags f1({ TestFlag::value1, TestFlag::value3 }); + EXPECT_EQ(10, f1()); + + Testflags f2(f1); + EXPECT_EQ(10, f2()); + + Testflags f3(TestFlag::value3); + EXPECT_EQ(8, f3()); +} + +TEST(flagsTest, set) +{ + Testflags f; + EXPECT_FALSE(static_cast(f)); + f.set(TestFlag::value1); + EXPECT_TRUE(static_cast(f)); + EXPECT_TRUE(f[TestFlag::value1]); +} + +TEST(flagsTest, is_set) +{ + Testflags f({ TestFlag::value1, TestFlag::value3 }); + + EXPECT_FALSE(f[TestFlag::value0]); + EXPECT_TRUE (f[TestFlag::value1]); + EXPECT_FALSE(f[TestFlag::value2]); + EXPECT_TRUE (f[TestFlag::value3]); + EXPECT_FALSE(f[TestFlag::value4]); + + EXPECT_FALSE(f.is_set(TestFlag::value0)); + EXPECT_TRUE (f.is_set(TestFlag::value1)); + EXPECT_FALSE(f.is_set(TestFlag::value2)); + EXPECT_TRUE (f.is_set(TestFlag::value3)); + EXPECT_FALSE(f.is_set(TestFlag::value4)); +} + +TEST(flagsTest, clear) +{ + Testflags f({ TestFlag::value1, TestFlag::value3 }); + f.clear(TestFlag::value1); + EXPECT_FALSE(f.is_set(TestFlag::value1)); + EXPECT_TRUE (f.is_set(TestFlag::value3)); +} + +TEST(flagsTest, reset) +{ + Testflags f({ TestFlag::value1, TestFlag::value3 }); + f.reset(); + EXPECT_FALSE(static_cast(f)); +} \ No newline at end of file diff --git a/test/LinqTests.cpp b/test/misc/linq.cpp similarity index 99% rename from test/LinqTests.cpp rename to test/misc/linq.cpp index 1dc897f..c9b478f 100644 --- a/test/LinqTests.cpp +++ b/test/misc/linq.cpp @@ -1,7 +1,6 @@ #include #include -#include "../src/cpputils/Misc.h" -#include "../src/cpputils/Linq.h" +#include namespace linq_tests { @@ -65,7 +64,8 @@ namespace linq_tests }; } -using namespace ::linq; +using namespace ::utl; +using namespace ::utl::linq; using namespace ::linq_tests; TEST(LinqTest, from_iterator) diff --git a/test/misc/misc.cpp b/test/misc/misc.cpp new file mode 100644 index 0000000..cb636df --- /dev/null +++ b/test/misc/misc.cpp @@ -0,0 +1,18 @@ +#include +#include + +using namespace ::utl; +using namespace ::testing; + +TEST(UtilsTests, bit_count) +{ + EXPECT_EQ(0, bit_count(0b0000'0000'0000'0000'0000'0000'0000'0000u)); + EXPECT_EQ(1, bit_count(0b0000'0000'0000'0000'0000'0000'0000'1000u)); + EXPECT_EQ(2, bit_count(0b0000'0000'0000'0000'0000'1000'0000'1000u)); + EXPECT_EQ(3, bit_count(0b0000'0000'0010'0000'0000'1000'0000'1000u)); + EXPECT_EQ(4, bit_count(0b0010'0000'0010'0000'0000'1000'0000'1000u)); + EXPECT_EQ(5, bit_count(0b0010'0000'0010'0000'0000'1000'1000'1000u)); + EXPECT_EQ(6, bit_count(0b0010'0000'0010'0000'0000'1000'1000'1001u)); + EXPECT_EQ(7, bit_count(0b0010'0000'0010'0000'0000'1000'1000'1101u)); + EXPECT_EQ(8, bit_count(0b0010'0100'0010'0000'0000'1000'1000'1101u)); +} \ No newline at end of file diff --git a/test/StreamHelperTests.cpp b/test/misc/stream.cpp similarity index 69% rename from test/StreamHelperTests.cpp rename to test/misc/stream.cpp index 0b1bdb1..1665b8d 100644 --- a/test/StreamHelperTests.cpp +++ b/test/misc/stream.cpp @@ -1,8 +1,5 @@ -#include -#include #include - -#include "../src/cpputils/StreamHelper.h" +#include namespace stream_helper_tests { @@ -18,63 +15,63 @@ namespace stream_helper_tests std::string s; void serialize(std::ostream& os) const - { utl::StreamHelper::write(os, s); } + { utl::stream_helper::write(os, s); } void deserialize(std::istream& is) - { utl::StreamHelper::read(is, s); } + { utl::stream_helper::read(is, s); } }; } -using namespace utl; +using namespace ::utl; using namespace ::testing; -using namespace stream_helper_tests; +using namespace ::stream_helper_tests; TEST(StreamHelperTests, write_scalar) { std::ostringstream os; - StreamHelper::write(os, static_cast(0x12345678)); + stream_helper::write(os, static_cast(0x12345678)); EXPECT_EQ(std::string("\x78\x56\x34\x12", 4), os.str()); } TEST(StreamHelperTests, write_string) { std::ostringstream os; - StreamHelper::write(os, std::string("test")); + stream_helper::write(os, std::string("test")); EXPECT_EQ(std::string("\x04\x00\x00\x00test", 8), os.str()); } TEST(StreamHelperTests, write_simpleStruct) { std::ostringstream os; - StreamHelper::write(os, SimpleStruct { 0x78563412, 5 }); + stream_helper::write(os, SimpleStruct { 0x78563412, 5 }); EXPECT_EQ(std::string("\x12\x34\x56\x78\x05", 5), os.str()); } TEST(StreamHelperTests, write_managedStruct) { std::ostringstream os; - StreamHelper::write(os, ManagedStruct { "test" }); + stream_helper::write(os, ManagedStruct { "test" }); EXPECT_EQ(std::string("\x04\x00\x00\x00test", 8), os.str()); } TEST(StreamHelperTests, read_scalar) { std::istringstream is(std::string("\x78\x56\x34\x12", 4)); - auto ret = StreamHelper::read(is); + auto ret = stream_helper::read(is); EXPECT_EQ(0x12345678, ret); } TEST(StreamHelperTests, read_string) { std::istringstream is(std::string("\x04\x00\x00\x00test", 8)); - auto ret = StreamHelper::read(is); + auto ret = stream_helper::read(is); EXPECT_EQ(std::string("test"), ret); } TEST(StreamHelperTests, read_simpleStruct) { std::istringstream is(std::string("\x12\x34\x56\x78\x05", 5)); - auto ret = StreamHelper::read(is); + auto ret = stream_helper::read(is); EXPECT_EQ(0x78563412, ret.u32); EXPECT_EQ(5, ret.u8); } @@ -82,6 +79,6 @@ TEST(StreamHelperTests, read_simpleStruct) TEST(StreamHelperTests, read_managedStruct) { std::istringstream is(std::string("\x04\x00\x00\x00test", 8)); - auto ret = StreamHelper::read(is); + auto ret = stream_helper::read(is); EXPECT_EQ(std::string("test"), ret.s); } \ No newline at end of file diff --git a/test/misc/string.cpp b/test/misc/string.cpp new file mode 100644 index 0000000..0b8d2b2 --- /dev/null +++ b/test/misc/string.cpp @@ -0,0 +1,59 @@ +#include +#include + +struct TestClass1 +{ + int i; + + std::string to_string() const + { return std::to_string(i); } + + bool from_string(const std::string& s) + { return static_cast(std::istringstream(s) >> i); } +}; + +struct TestClass2 +{ + int i; + + void to_string(std::ostream& os) const + { os << i; } + + static bool from_string(const std::string& s, TestClass2& v) + { return static_cast(std::istringstream(s) >> v.i); } +}; + +using namespace ::utl; +using namespace ::testing; + +TEST(StringHelperTests, to_string) +{ + EXPECT_EQ(std::string("4.5"), utl::to_string(4.5)); + EXPECT_EQ(std::string("test"), utl::to_string("test")); + EXPECT_EQ(std::string("fuu"), utl::to_string(std::string("fuu"))); + EXPECT_EQ(std::string("5"), utl::to_string(TestClass1 { 5 })); + EXPECT_EQ(std::string("6"), utl::to_string(TestClass2 { 6 })); +} + +TEST(StringHelperTests, from_string) +{ + double d; + EXPECT_FALSE(utl::try_from_string("abc", d)); + EXPECT_TRUE (utl::try_from_string("4.5", d)); + EXPECT_TRUE (d >= 4.5 && d <= 4.5); + + int i; + EXPECT_FALSE(utl::try_from_string("abc", i)); + EXPECT_TRUE (utl::try_from_string("123", i)); + EXPECT_EQ (123, i); + + TestClass1 t1; + EXPECT_FALSE(utl::try_from_string("abc", t1)); + EXPECT_TRUE (utl::try_from_string("11", t1)); + EXPECT_EQ (11, t1.i); + + TestClass2 t2; + EXPECT_FALSE(utl::try_from_string("abc", t2)); + EXPECT_TRUE (utl::try_from_string("12", t2)); + EXPECT_EQ (12, t2.i); +} \ No newline at end of file diff --git a/test/TimeTests.cpp b/test/misc/time.cpp similarity index 88% rename from test/TimeTests.cpp rename to test/misc/time.cpp index 5b4185e..f83e75f 100644 --- a/test/TimeTests.cpp +++ b/test/misc/time.cpp @@ -1,12 +1,8 @@ #include #include +#include -namespace time_tests -{ - #include "../src/cpputils/Time.h" -} - -using namespace time_tests::utl; +using namespace ::utl; TEST(TimeTest, duration_to_timespec) { diff --git a/test/TransformIteratorTests.cpp b/test/misc/transform_iterator.cpp similarity index 78% rename from test/TransformIteratorTests.cpp rename to test/misc/transform_iterator.cpp index 912da84..735af76 100644 --- a/test/TransformIteratorTests.cpp +++ b/test/misc/transform_iterator.cpp @@ -1,14 +1,9 @@ #include -#include #include +#include -namespace transform_iterator_tests -{ - #include "../src/cpputils/TransformIterator.h" -} - -using namespace transform_iterator_tests; -using namespace transform_iterator_tests::utl; +using namespace ::utl; +using namespace ::testing; struct op_add_10 { @@ -25,8 +20,8 @@ struct op_add_10 TEST(TransformIteratorTests, bidirectional_inc) { std::list l { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; - auto it = makeTransformIterator(l.begin(), op_add_10()); - auto itEnd = makeTransformIterator(l.end(), op_add_10()); + auto it = make_transform_iterator(l.begin(), op_add_10()); + auto itEnd = make_transform_iterator(l.end(), op_add_10()); ASSERT_NE(itEnd, it); EXPECT_EQ(11, *it++); ASSERT_NE(itEnd, it); @@ -51,8 +46,8 @@ TEST(TransformIteratorTests, bidirectional_inc) TEST(TransformIteratorTests, bidirectional_dec) { std::list l { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; - auto itBeg = makeTransformIterator(l.begin(), op_add_10()); - auto it = makeTransformIterator(l.end(), op_add_10()); + auto itBeg = make_transform_iterator(l.begin(), op_add_10()); + auto it = make_transform_iterator(l.end(), op_add_10()); --it; ASSERT_NE(itBeg, it); EXPECT_EQ(19, *it--); @@ -77,8 +72,8 @@ TEST(TransformIteratorTests, bidirectional_dec) TEST(TransformIteratorTests, random_access) { std::vector l { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; - auto it = makeTransformIterator(l.begin(), op_add_10()); - auto itEnd = makeTransformIterator(l.end(), op_add_10()); + auto it = make_transform_iterator(l.begin(), op_add_10()); + auto itEnd = make_transform_iterator(l.end(), op_add_10()); ASSERT_NE(itEnd, it); EXPECT_EQ(9, itEnd - it); EXPECT_EQ(11, it[0]); @@ -97,8 +92,8 @@ TEST(TransformIteratorTests, lambda) std::vector l { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; auto lambda = [](int& i) { return &i; }; - auto it = makeTransformIterator(l.begin(), lambda); - auto itEnd = makeTransformIterator(l.end(), lambda); + auto it = make_transform_iterator(l.begin(), lambda); + auto itEnd = make_transform_iterator(l.end(), lambda); ASSERT_NE(itEnd, it); EXPECT_EQ(&l.at(0), *it++); ASSERT_NE(itEnd, it); diff --git a/test/mp/MetaProgrammingTests.cpp.old b/test/mp/MetaProgrammingTests.cpp.old deleted file mode 100644 index a5ff4b6..0000000 --- a/test/mp/MetaProgrammingTests.cpp.old +++ /dev/null @@ -1,341 +0,0 @@ -#if 0 -#include - -#include "../src/cpputils/MetaProgramming.h" - -using namespace utl; - -struct X1 { }; -struct X2 { }; -struct X3 { }; - -struct Y1 { }; -struct Y2 { }; -struct Y3 { }; - -struct Z1 { }; -struct Z2 { }; -struct Z3 { }; - - -/* logical operations ****************************************************************************/ -/* mp_if */ -using mp_if_c_expected_0 = int; -using mp_if_c_actual_0 = mp_if_c; -static_assert(std::is_same::value, "mp_if"); - -using mp_if_c_expected_1 = double; -using mp_if_c_actual_1 = mp_if_c; -static_assert(std::is_same::value, "mp_if"); - -/* mp_eval_if(_c) */ -using mp_eval_if_expected_0 = int; -using mp_eval_if_actual_0 = mp_eval_if_c; /* erroneous mp_add_pointer require only one argument */ -static_assert(std::is_same::value, "mp_eval_if(_c)"); - -using mp_eval_if_expected_1 = int*; -using mp_eval_if_actual_1 = mp_eval_if_c; -static_assert(std::is_same::value, ""); - -/* mp_not */ -using mp_not_input = mp_list; -using mp_not_exected = mp_list; -using mp_not_actual = mp_not; -static_assert(std::is_same::value, "mp_not"); - -/* mp_and */ -using mp_and_input_0 = mp_list; -using mp_and_expected_0 = mp_false; -using mp_and_actual_0 = mp_and; -static_assert(std::is_same::value, "mp_and"); - -using mp_and_input_1 = mp_list; -using mp_and_expected_1 = mp_true; -using mp_and_actual_1 = mp_and; -static_assert(std::is_same::value, "mp_and"); - -/* mp_or */ -using mp_or_input_0 = mp_list; -using mp_or_expected_0 = mp_false; -using mp_or_actual_0 = mp_or; -static_assert(std::is_same::value, "mp_or"); - -using mp_or_input_1 = mp_list; -using mp_or_expected_1 = mp_true; -using mp_or_actual_1 = mp_or; -static_assert(std::is_same::value, "mp_or"); - - - -/* arithmetic ************************************************************************************/ -/* mp_plus */ -using mp_plus_input = mp_list, mp_const, mp_const>; -using mp_plus_expected = mp_const; -using mp_plus_actual = mp_plus; -static_assert(std::is_same::value, "mp_plus"); - -/* mp_minus */ -using mp_minus_input = mp_list, mp_const, mp_const>; -using mp_minus_expected = mp_const; -using mp_minus_actual = mp_minus; -static_assert(std::is_same::value, "mp_minus"); - -/* mp_multiply */ -using mp_multiply_input = mp_list, mp_const, mp_const>; -using mp_multiply_expected = mp_const; -using mp_multiply_actual = mp_multiply; -static_assert(std::is_same::value, "mp_multiply"); - -/* mp_divide */ -using mp_divide_input = mp_list, mp_const, mp_const>; -using mp_divide_expected = mp_const; -using mp_divide_actual = mp_divide; -static_assert(std::is_same::value, "mp_divide"); - - - -/* generator functions ***************************************************************************/ -/* mp_make_integer_sequence */ -using mp_make_integer_sequence_expected = mp_integer_sequence; -using mp_make_integer_sequence_actual = mp_make_integer_sequence; -static_assert(std::is_same::value, "mp_make_integer_sequence"); - -/* mp_make_index_sequence */ -using mp_make_index_sequence_expected = mp_index_sequence<0, 1, 2, 3, 4, 5>; -using mp_make_index_sequence_actual = mp_make_index_sequence<6>; -static_assert(std::is_same::value, "mp_make_index_sequence"); - -/* mp_repeat */ -using mp_repeat_expected = mp_list; -using mp_repeat_actual = mp_repeat<3, X1, X2, X3>; -static_assert(std::is_same::value, "mp_repeat"); - - - -/* list operations returning a numeric value *****************************************************/ -/* mp_length */ -using mp_length_expected = mp_size_t<3>; -using mp_length_actual = mp_length; -static_assert(std::is_same::value, "mp_length"); - -/* mp_size */ -using mp_size_input = mp_list; -using mp_size_expected = mp_size_t<3>; -using mp_size_actual = mp_size; -static_assert(std::is_same::value, "mp_size"); - -/* mp_count */ -using mp_count_input = mp_list; -using mp_count_expected = mp_size_t<3>; -using mp_count_actual = mp_count; -static_assert(std::is_same::value, "mp_count"); - -/* mp_count_if */ -template -using mp_count_if_op = mp_or, std::is_same>>; -using mp_count_if_input = mp_list; -using mp_count_if_expected = mp_size_t<5>; -using mp_count_if_actual = mp_count_if; -static_assert(std::is_same::value, "mp_count_if"); - - - -/* operations to manipulate list content *********************************************************/ -/* mp_push_front */ -using mp_push_front_input = mp_list; -using mp_push_front_expected = mp_list; -using mp_push_front_actual = mp_push_front; -static_assert(std::is_same::value, "mp_push_front"); - -/* mp_pop_front */ -using mp_pop_front_input = mp_list; -using mp_pop_front_expected = mp_list; -using mp_pop_front_actual = mp_pop_front; -static_assert(std::is_same::value, "mp_pop_front"); - -/* mp_push_bask */ -using mp_push_back_input = mp_list; -using mp_push_back_expected = mp_list; -using mp_push_back_actual = mp_push_back; -static_assert(std::is_same::value, "mp_push_bask"); - -/* mp_concat */ -using mp_concat_expected = mp_list; -using mp_concat_actual = mp_concat, mp_list, mp_list>; -static_assert(std::is_same::value, "mp_concat"); - -/* mp_filter */ -template -using mp_filter_func = mp_bool, mp_is_same, mp_is_same>>::value == 0>; -using mp_filter_input = mp_list; -using mp_filter_expected = mp_list; -using mp_filter_actual = mp_filter; -static_assert(std::is_same::value, "mp_filter"); - - - -/* list operations returning a bool value ********************************************************/ -/* mp_empty */ -using mp_empty_input_0 = mp_list<>; -using mp_empty_input_1 = mp_list; -using mp_empty_expected_0 = mp_false; -using mp_empty_actual_0 = mp_empty; -static_assert(std::is_same::value, "mp_empty"); - -using mp_empty_expected_1 = mp_true; -using mp_empty_actual_1 = mp_empty; -static_assert(std::is_same::value, "mp_empty"); - -/* mp_contains */ -using mp_contains_input_0 = mp_list; -using mp_contains_expected_0 = mp_true; -using mp_contains_actual_0 = mp_contains; -static_assert(std::is_same::value, "mp_contains"); - -using mp_contains_input_1 = mp_list; -using mp_contains_expected_1 = mp_false; -using mp_contains_actual_1 = mp_contains; -static_assert(std::is_same::value, "mp_contains"); - - - -/* list operations returing elements from the list ***********************************************/ -/* mp_front */ -using mp_front_input = mp_list; -using mp_front_expected = X1; -using mp_front_actual = mp_front; -static_assert(std::is_same::value, "mp_front"); - -/* mp_second */ -using mp_second_input = mp_list; -using mp_second_expected = X2; -using mp_second_actual = mp_second; -static_assert(std::is_same::value, "mp_second"); - -/* mp_at(_c) */ -using mp_at_c_input = mp_list; -using mp_at_c_expected = Y1; -using mp_at_c_actual = mp_at_c; -static_assert(std::is_same::value, "mp_at(_c)"); - -/* mp_search */ -template -using mp_search_func_0 = std::is_same; -using mp_search_input_0 = mp_list; -using mp_search_expected_0 = X2; -using mp_search_actual_0 = mp_search; -static_assert(std::is_same::value, "mp_search"); - -template -using mp_search_func_1 = mp_false; -using mp_search_input_1 = mp_list; -using mp_search_expected_1 = Y2; -using mp_search_actual_1 = mp_search; -static_assert(std::is_same::value, "mp_search"); - -/* mp_find */ -using mp_find_input_0 = mp_list; -using mp_find_expected_0 = mp_size_t<2>; -using mp_find_actual_0 = mp_find; -static_assert(std::is_same::value, "mp_find"); - -using mp_find_input_1 = mp_list; -using mp_find_expected_1 = mp_size_t<4>; -using mp_find_actual_1 = mp_find; -static_assert(std::is_same::value, "mp_find"); - -/* mp_map_find */ -using mp_map_find_input_0 = mp_list, mp_list, mp_list>; -using mp_map_find_expected_0 = mp_list; -using mp_map_find_actual_0 = mp_map_find; -static_assert(std::is_same::value, "mp_map_find"); - -using mp_map_find_input_1 = mp_list, mp_list, mp_list>; -using mp_map_find_expected_1 = void; -using mp_map_find_actual_1 = mp_map_find; -static_assert(std::is_same::value, "mp_map_find"); - - - -/* list manipulators returning a new list ********************************************************/ -/* mp_clear */ -using mp_clear_input = mp_list; -using mp_clear_expected = mp_list<>; -using mp_clear_actual = mp_clear; -static_assert(std::is_same::value, "mp_unique"); - -/* mp_unique */ -using mp_unique_input = mp_list; -using mp_unique_expected = mp_list; -using mp_unique_actual = mp_unique; -static_assert(std::is_same::value, "mp_unique"); - -/* mp_rename */ -using mp_rename_input = mp_list; -using mp_rename_expected = std::tuple; -using mp_rename_actual = mp_rename; -static_assert(std::is_same::value, "mp_rename"); - -/* mp_append */ -using mp_append_input_X = mp_list; -using mp_append_input_Y = mp_list; -using mp_append_input_Z = mp_list; -using mp_append_expected = mp_list; -using mp_append_actual = mp_append; -static_assert(std::is_same::value, "mp_append"); - -/* mp_map_from_list */ -using mp_map_from_list_input = mp_list; -using mp_map_from_list_expected = mp_list, X1>, mp_list, X2>, mp_list, X3>>; -using mp_map_from_list_actual = mp_map_from_list; -static_assert(std::is_same::value, "mp_map_from_list"); - -/* mp_transform */ -using mp_transform_input_0 = std::tuple; -using mp_transform_input_1 = std::tuple; -using mp_transform_expected_0 = std::tuple, std::pair, std::pair>; -using mp_transform_actual_0 = mp_transform; -static_assert(std::is_same::value, "mp_transform"); - -using mp_transform_input_2 = mp_list; -using mp_transform_expected_1 = mp_list; -using mp_transform_actual_1 = mp_transform; -static_assert(std::is_same::value, "mp_transform"); - -/* unique id *************************************************************************************/ - -struct Counter1 { }; -struct Counter2 { }; - -TEST(MetaProgrammingTest, unique_id) -{ - auto uid1_1 = nextUniqueId(); - auto uid1_2 = nextUniqueId(); - ASSERT_EQ(uid1_1, 0); - ASSERT_EQ(uid1_2, 1); - - auto uid2_1 = getUniqueId(); - auto uid2_2 = getUniqueId(); - auto uid2_3 = getUniqueId(); - auto uid2_4 = getUniqueId(); - ASSERT_EQ(uid2_1, 0); - ASSERT_EQ(uid2_2, 1); - ASSERT_EQ(uid2_3, 2); - ASSERT_EQ(uid2_4, 0); -} - -TEST(MetaProgrammingTest, string) -{ - constexpr auto string1 = utl::mp_make_string("fuu bar"); - ASSERT_EQ ( string1.str(), std::string("fuu bar") ); -} - -TEST(MetaProgrammingTest, int_to_str) -{ - using t_int16 = utl::mp_const; - constexpr auto decStr = utl::mp_int_to_string(); - constexpr auto hexStr = utl::mp_int_to_string(); - ASSERT_EQ ( decStr.str(), std::string("16") ); - ASSERT_EQ ( hexStr.str(), std::string("10") ); -} -#endif \ No newline at end of file diff --git a/test/mp/container/pair.cpp b/test/mp/container/pair.cpp new file mode 100644 index 0000000..a528da8 --- /dev/null +++ b/test/mp/container/pair.cpp @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include +#include +#include + +using namespace ::utl::mp; +using namespace ::utl::mp::operators; + +namespace test_mp_container_pair +{ + constexpr auto my_pair = make_pair(1, 'x'); + static_assert(first(my_pair) == 1, ""); + static_assert(second(my_pair) == 'x', ""); + static_assert(my_pair.first() == 1, ""); + static_assert(my_pair.second() == 'x', ""); + + static_assert(equal(make_pair(1, 'x'), make_pair(1, 'x')), ""); + static_assert( make_pair(1, 'x') == make_pair(1, 'x'), ""); + + static_assert(not_equal(make_pair(1, 'x'), make_pair(2, 'x')), ""); + static_assert( make_pair(1, 'x') != make_pair(2, 'x'), ""); + + static_assert(less(make_pair(1, 'x'), make_pair(1, 'y')), ""); + static_assert(less(make_pair(1, 'x'), make_pair(2, 'x')), ""); + static_assert(less(make_pair(1, 'x'), make_pair(2, 'a')), ""); + + static_assert(make_pair(1, 'x') < make_pair(1, 'y'), ""); + static_assert(make_pair(1, 'x') < make_pair(2, 'x'), ""); + static_assert(make_pair(1, 'x') < make_pair(2, 'a'), ""); + + static_assert(less_equal(make_pair(1, 'x'), make_pair(1, 'x')), ""); + static_assert(less_equal(make_pair(1, 'x'), make_pair(1, 'y')), ""); + static_assert(less_equal(make_pair(1, 'x'), make_pair(2, 'x')), ""); + static_assert(less_equal(make_pair(1, 'x'), make_pair(2, 'a')), ""); + + static_assert(make_pair(1, 'x') <= make_pair(1, 'x'), ""); + static_assert(make_pair(1, 'x') <= make_pair(1, 'y'), ""); + static_assert(make_pair(1, 'x') <= make_pair(2, 'x'), ""); + static_assert(make_pair(1, 'x') <= make_pair(2, 'a'), ""); + + static_assert(greater(make_pair(1, 'y'), make_pair(1, 'x')), ""); + static_assert(greater(make_pair(2, 'x'), make_pair(1, 'x')), ""); + static_assert(greater(make_pair(2, 'a'), make_pair(1, 'x')), ""); + + static_assert(make_pair(1, 'y') > make_pair(1, 'x'), ""); + static_assert(make_pair(2, 'x') > make_pair(1, 'x'), ""); + static_assert(make_pair(2, 'a') > make_pair(1, 'x'), ""); + + static_assert(greater_equal(make_pair(1, 'x'), make_pair(1, 'x')), ""); + static_assert(greater_equal(make_pair(1, 'y'), make_pair(1, 'x')), ""); + static_assert(greater_equal(make_pair(2, 'x'), make_pair(1, 'x')), ""); + static_assert(greater_equal(make_pair(2, 'a'), make_pair(1, 'x')), ""); + + static_assert(make_pair(1, 'x') >= make_pair(1, 'x'), ""); + static_assert(make_pair(1, 'y') >= make_pair(1, 'x'), ""); + static_assert(make_pair(2, 'x') >= make_pair(1, 'x'), ""); + static_assert(make_pair(2, 'a') >= make_pair(1, 'x'), ""); +} \ No newline at end of file diff --git a/test/mp/core.cpp b/test/mp/core.cpp index 921e865..52a5743 100644 --- a/test/mp/core.cpp +++ b/test/mp/core.cpp @@ -1,6 +1,6 @@ #include -#include "../../src/cpputils/mp/core.h" +#include using namespace ::utl::mp; diff --git a/test/mp/intern/comparable_equal.cpp b/test/mp/intern/comparable_equal.cpp new file mode 100644 index 0000000..f2ab455 --- /dev/null +++ b/test/mp/intern/comparable_equal.cpp @@ -0,0 +1,8 @@ +#include + +using namespace ::utl::mp::intern; + +namespace test_mp_intern_comparable_equal +{ + static_assert(comparable_equal::value, ""); +} diff --git a/test/mp/intern/ebo.cpp b/test/mp/intern/ebo.cpp new file mode 100644 index 0000000..599c81e --- /dev/null +++ b/test/mp/intern/ebo.cpp @@ -0,0 +1,9 @@ +#include +#include + +using namespace ::utl::mp::intern; + +struct Key { }; +using ebo_type = ebo; +constexpr ebo_type myEbo(7); +static_assert(myEbo.get() == 7, "ebo.get"); \ No newline at end of file diff --git a/test/mp/intern/has_value.cpp b/test/mp/intern/has_value.cpp new file mode 100644 index 0000000..40b30ef --- /dev/null +++ b/test/mp/intern/has_value.cpp @@ -0,0 +1,10 @@ +#include + +using namespace ::utl::mp; +using namespace ::utl::mp::intern; + +namespace test_mp_intern_has_value +{ + static_assert( has_value::value, ""); + static_assert(!has_value::value, ""); +} \ No newline at end of file diff --git a/test/mp/mp.cpp b/test/mp/mp.cpp new file mode 100644 index 0000000..edf1d9b --- /dev/null +++ b/test/mp/mp.cpp @@ -0,0 +1 @@ +#include \ No newline at end of file diff --git a/test/mp/operations/compare/equal.cpp b/test/mp/operations/compare/equal.cpp new file mode 100644 index 0000000..8c312d8 --- /dev/null +++ b/test/mp/operations/compare/equal.cpp @@ -0,0 +1,9 @@ +#include + +using namespace ::utl::mp; + +namespace test_mp_operations_compare_equal +{ + static_assert(equal(1, 1), ""); + static_assert(!equal(1, 2), ""); +} \ No newline at end of file diff --git a/test/mp/operations/compare/less.cpp b/test/mp/operations/compare/less.cpp new file mode 100644 index 0000000..dff104e --- /dev/null +++ b/test/mp/operations/compare/less.cpp @@ -0,0 +1,9 @@ +#include + +using namespace ::utl::mp; + +namespace test_mp_operations_compare_equal +{ + static_assert(less(1, 2), ""); + static_assert(!less(2, 1), ""); +} \ No newline at end of file diff --git a/test/mp/util.cpp b/test/mp/util.cpp deleted file mode 100644 index febf8e7..0000000 --- a/test/mp/util.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include "../../src/cpputils/mp/util.h" - -using namespace ::utl::mp; - -struct tagged_int { using tag = int; }; -struct tagged_float { using tag = float; }; -struct tagged_not { }; - -/* default */ -struct is_default_true : public __impl::default_ { }; -struct is_default_false { }; -static_assert(is_default::value, "is_default"); -static_assert(!is_default::value, "is_default"); - -/* tag_of */ -using tagged_0_expected = int; -using tagged_1_expected = float; -using tagged_0_actual = tag_of; -using tagged_1_actual = tag_of; -using not_tagged_expected = tagged_not; -using not_tagged_actual = tag_of; -static_assert(is_same::value, "tag_of"); -static_assert(is_same::value, "tag_of"); -static_assert(is_same::value, "tag_of"); - -/* is_a */ -static_assert(is_a, "is_a"); -static_assert(!is_a, "is_a"); -static_assert(is_a>(make_const), "is_a"); -static_assert(!is_a>(make_const), "is_a"); - -TEST(mp_util_test, make) -{ - EXPECT_EQ(std::string("fuu"), make("fuu")); -} \ No newline at end of file diff --git a/test/mp/util/default.cpp b/test/mp/util/default.cpp new file mode 100644 index 0000000..1f5d397 --- /dev/null +++ b/test/mp/util/default.cpp @@ -0,0 +1,14 @@ +#include + +namespace test_mp_util_default +{ + struct is_default_true : public ::utl::mp::__impl::default_ { }; + struct is_default_false { }; +} + +using namespace ::utl::mp; +using namespace ::test_mp_util_default; + +static_assert( is_default::value, ""); +static_assert(!is_default::value, ""); +static_assert(!is_default::value, ""); \ No newline at end of file diff --git a/test/mp/util/is_a.cpp b/test/mp/util/is_a.cpp new file mode 100644 index 0000000..1734ac8 --- /dev/null +++ b/test/mp/util/is_a.cpp @@ -0,0 +1,18 @@ +#include +#include +#include + +namespace test_mp_util_is_a +{ + struct tagged_int { using tag = int; }; + struct tagged_float { using tag = float; }; + struct tagged_not { }; +} + +using namespace ::utl::mp; +using namespace ::test_mp_util_is_a; + +static_assert( is_a, "is_a"); +static_assert(!is_a, "is_a"); +static_assert( is_a>(integral_constant { }), "is_a"); +static_assert(!is_a>(integral_constant { }), "is_a"); \ No newline at end of file diff --git a/test/mp/util/make.cpp b/test/mp/util/make.cpp new file mode 100644 index 0000000..f865c59 --- /dev/null +++ b/test/mp/util/make.cpp @@ -0,0 +1,9 @@ +#include +#include + +using namespace ::utl::mp; + +TEST(mp_util_test, make) +{ + EXPECT_EQ(std::string("fuu"), make("fuu")); +} \ No newline at end of file diff --git a/test/mp/util/tag_of.cpp b/test/mp/util/tag_of.cpp new file mode 100644 index 0000000..4c05099 --- /dev/null +++ b/test/mp/util/tag_of.cpp @@ -0,0 +1,27 @@ +#include + +namespace test_mp_util_tag_of +{ + struct tagged_int { using tag = int; }; + struct tagged_float { using tag = float; }; + struct tagged_not { }; +} + +using namespace ::utl::mp; +using namespace ::test_mp_util_tag_of; + +using tagged_0_expected = int; +using tagged_0_actual = tag_of; +static_assert(is_same::value, ""); + +using tagged_1_expected = float; +using tagged_1_actual = tag_of; +static_assert(is_same::value, ""); + +using not_tagged_expected = tagged_not; +using not_tagged_actual = tag_of; +static_assert(is_same::value, ""); + +using bool_expected = bool; +using bool_actual = tag_of; +static_assert(is_same::value, ""); \ No newline at end of file diff --git a/test/mp/convert.cpp b/test/mp/util/to.cpp similarity index 96% rename from test/mp/convert.cpp rename to test/mp/util/to.cpp index 5cf3050..26055a2 100644 --- a/test/mp/convert.cpp +++ b/test/mp/util/to.cpp @@ -1,5 +1,5 @@ #include -#include "../../src/cpputils/mp/convert.h" +#include using namespace ::utl::mp; @@ -33,7 +33,7 @@ static_assert(is_embedded::value, "is_embedd static_assert(is_embedded::value, "is_embedded"); static_assert(is_embedded::value, "is_embedded"); -TEST(mp_convert_test, make) +TEST(test_mp_util_to, make) { EXPECT_EQ(to(static_cast(8)), 8); } \ No newline at end of file