From fe8572d75ba2d56d89142fb468930d58b76f859f Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Wed, 3 Jan 2018 06:01:02 +0100 Subject: [PATCH] Remove inline methods and use explicit template instantiation to minimize the number of weak symbols --- lib/base/CMakeLists.txt | 2 +- lib/base/array.cpp | 51 ++++ lib/base/array.hpp | 51 +--- lib/base/dictionary.cpp | 59 ++++ lib/base/dictionary.hpp | 58 +--- lib/base/logger.cpp | 101 ++++--- lib/base/logger.hpp | 36 +-- lib/base/object.cpp | 1 + lib/base/object.hpp | 1 - lib/base/objectlock.cpp | 140 ++++++++++ lib/base/objectlock.hpp | 119 +------- lib/base/string.cpp | 422 ++++++++++++++++++++++++++++ lib/base/string.hpp | 471 ++++++-------------------------- lib/base/type.cpp | 6 + lib/base/type.hpp | 3 + lib/base/value.cpp | 175 +++++++++++- lib/base/value.hpp | 204 +++----------- tools/mkclass/classcompiler.cpp | 49 ++-- 18 files changed, 1111 insertions(+), 838 deletions(-) create mode 100644 lib/base/objectlock.cpp diff --git a/lib/base/CMakeLists.txt b/lib/base/CMakeLists.txt index ba9ee5d0e..fd61c8922 100644 --- a/lib/base/CMakeLists.txt +++ b/lib/base/CMakeLists.txt @@ -33,7 +33,7 @@ set(base_SOURCES exception.cpp fifo.cpp filelogger.cpp filelogger.thpp initialize.cpp json.cpp json-script.cpp library.cpp loader.cpp logger.cpp logger.thpp math-script.cpp netstring.cpp networkstream.cpp number.cpp number-script.cpp object.cpp - object-script.cpp objecttype.cpp primitivetype.cpp process.cpp ringbuffer.cpp scriptframe.cpp + object-script.cpp objectlock.cpp objecttype.cpp primitivetype.cpp process.cpp ringbuffer.cpp scriptframe.cpp function.cpp function.thpp function-script.cpp perfdatavalue.cpp perfdatavalue.thpp scriptglobal.cpp scriptutils.cpp serializer.cpp socket.cpp socketevents.cpp socketevents-epoll.cpp socketevents-poll.cpp stacktrace.cpp diff --git a/lib/base/array.cpp b/lib/base/array.cpp index 54439ad93..8a5f884e2 100644 --- a/lib/base/array.cpp +++ b/lib/base/array.cpp @@ -28,8 +28,20 @@ using namespace icinga; +template class std::vector; + REGISTER_PRIMITIVE_TYPE(Array, Object, Array::GetPrototype()); +Array::Array(void) +{ } + +Array::Array(std::initializer_list init) + : m_Data(init) +{ } + +Array::~Array(void) +{ } + /** * Restrieves a value from an array. * @@ -93,6 +105,34 @@ void Array::Add(Value&& value) m_Data.emplace_back(std::move(value)); } +/** + * Returns an iterator to the beginning of the array. + * + * Note: Caller must hold the object lock while using the iterator. + * + * @returns An iterator. + */ +Array::Iterator Array::Begin(void) +{ + ASSERT(OwnsLock()); + + return m_Data.begin(); +} + +/** + * Returns an iterator to the end of the array. + * + * Note: Caller must hold the object lock while using the iterator. + * + * @returns An iterator. + */ +Array::Iterator Array::End(void) +{ + ASSERT(OwnsLock()); + + return m_Data.end(); +} + /** * Returns the number of elements in the array. * @@ -273,3 +313,14 @@ void Array::SetFieldByName(const String& field, const Value& value, const DebugI Set(index, value); } + +Array::Iterator icinga::begin(Array::Ptr x) +{ + return x->Begin(); +} + +Array::Iterator icinga::end(Array::Ptr x) +{ + return x->End(); +} + diff --git a/lib/base/array.hpp b/lib/base/array.hpp index 1df29f506..a601b34d6 100644 --- a/lib/base/array.hpp +++ b/lib/base/array.hpp @@ -47,15 +47,10 @@ public: typedef std::vector::size_type SizeType; - Array(void) - { } + Array(void); + Array(std::initializer_list init); - Array(std::initializer_list init) - : m_Data(init) - { } - - ~Array(void) - { } + ~Array(void); Value Get(SizeType index) const; void Set(SizeType index, const Value& value); @@ -63,33 +58,8 @@ public: void Add(const Value& value); void Add(Value&& value); - /** - * Returns an iterator to the beginning of the array. - * - * Note: Caller must hold the object lock while using the iterator. - * - * @returns An iterator. - */ - Iterator Begin(void) - { - ASSERT(OwnsLock()); - - return m_Data.begin(); - } - - /** - * Returns an iterator to the end of the array. - * - * Note: Caller must hold the object lock while using the iterator. - * - * @returns An iterator. - */ - Iterator End(void) - { - ASSERT(OwnsLock()); - - return m_Data.end(); - } + Iterator Begin(void); + Iterator End(void); size_t GetLength(void) const; bool Contains(const Value& value) const; @@ -148,16 +118,11 @@ private: std::vector m_Data; /**< The data for the array. */ }; -inline Array::Iterator begin(Array::Ptr x) -{ - return x->Begin(); -} +Array::Iterator begin(Array::Ptr x); +Array::Iterator end(Array::Ptr x); -inline Array::Iterator end(Array::Ptr x) -{ - return x->End(); } -} +extern template class std::vector; #endif /* ARRAY_H */ diff --git a/lib/base/dictionary.cpp b/lib/base/dictionary.cpp index 68f78f4cd..bc1607174 100644 --- a/lib/base/dictionary.cpp +++ b/lib/base/dictionary.cpp @@ -25,8 +25,16 @@ using namespace icinga; +template class std::map; + REGISTER_PRIMITIVE_TYPE(Dictionary, Object, Dictionary::GetPrototype()); +Dictionary::Dictionary(void) +{ } + +Dictionary::~Dictionary(void) +{ } + /** * Retrieves a value from a dictionary. * @@ -116,6 +124,46 @@ bool Dictionary::Contains(const String& key) const return (m_Data.find(key) != m_Data.end()); } +/** + * Returns an iterator to the beginning of the dictionary. + * + * Note: Caller must hold the object lock while using the iterator. + * + * @returns An iterator. + */ +Dictionary::Iterator Dictionary::Begin(void) +{ + ASSERT(OwnsLock()); + + return m_Data.begin(); +} + +/** + * Returns an iterator to the end of the dictionary. + * + * Note: Caller must hold the object lock while using the iterator. + * + * @returns An iterator. + */ +Dictionary::Iterator Dictionary::End(void) +{ + ASSERT(OwnsLock()); + + return m_Data.end(); +} + +/** + * Removes the item specified by the iterator from the dictionary. + * + * @param it The iterator. + */ +void Dictionary::Remove(Dictionary::Iterator it) +{ + ASSERT(OwnsLock()); + + m_Data.erase(it); +} + /** * Removes the specified key from the dictionary. * @@ -233,3 +281,14 @@ bool Dictionary::GetOwnField(const String& field, Value *result) const { return Get(field, result); } + +Dictionary::Iterator icinga::begin(Dictionary::Ptr x) +{ + return x->Begin(); +} + +Dictionary::Iterator icinga::end(Dictionary::Ptr x) +{ + return x->End(); +} + diff --git a/lib/base/dictionary.hpp b/lib/base/dictionary.hpp index fadc1f41a..cfca95a6d 100644 --- a/lib/base/dictionary.hpp +++ b/lib/base/dictionary.hpp @@ -49,11 +49,9 @@ public: typedef std::map::value_type Pair; - Dictionary(void) - { } + Dictionary(void); - ~Dictionary(void) - { } + ~Dictionary(void); Value Get(const String& key) const; bool Get(const String& key, Value *result) const; @@ -61,49 +59,14 @@ public: void Set(const String& key, Value&& value); bool Contains(const String& key) const; - /** - * Returns an iterator to the beginning of the dictionary. - * - * Note: Caller must hold the object lock while using the iterator. - * - * @returns An iterator. - */ - Iterator Begin(void) - { - ASSERT(OwnsLock()); - - return m_Data.begin(); - } - - /** - * Returns an iterator to the end of the dictionary. - * - * Note: Caller must hold the object lock while using the iterator. - * - * @returns An iterator. - */ - Iterator End(void) - { - ASSERT(OwnsLock()); - - return m_Data.end(); - } + Iterator Begin(void); + Iterator End(void); size_t GetLength(void) const; void Remove(const String& key); - /** - * Removes the item specified by the iterator from the dictionary. - * - * @param it The iterator. - */ - void Remove(Iterator it) - { - ASSERT(OwnsLock()); - - m_Data.erase(it); - } + void Remove(Iterator it); void Clear(void); @@ -127,16 +90,11 @@ private: std::map m_Data; /**< The data for the dictionary. */ }; -inline Dictionary::Iterator begin(Dictionary::Ptr x) -{ - return x->Begin(); -} +Dictionary::Iterator begin(Dictionary::Ptr x); +Dictionary::Iterator end(Dictionary::Ptr x); -inline Dictionary::Iterator end(Dictionary::Ptr x) -{ - return x->End(); } -} +extern template class std::map; #endif /* DICTIONARY_H */ diff --git a/lib/base/logger.cpp b/lib/base/logger.cpp index 5897527cc..e134f0655 100644 --- a/lib/base/logger.cpp +++ b/lib/base/logger.cpp @@ -30,6 +30,16 @@ using namespace icinga; +template Log& Log::operator<<(const Value&); +template Log& Log::operator<<(const String&); +template Log& Log::operator<<(const std::string&); +template Log& Log::operator<<(const bool&); +template Log& Log::operator<<(const unsigned int&); +template Log& Log::operator<<(const int&); +template Log& Log::operator<<(const unsigned long&); +template Log& Log::operator<<(const long&); +template Log& Log::operator<<(const double&); + REGISTER_TYPE(Logger); std::set Logger::m_Loggers; @@ -73,46 +83,6 @@ std::set Logger::GetLoggers(void) return m_Loggers; } -/** - * Writes a message to the application's log. - * - * @param severity The message severity. - * @param facility The log facility. - * @param message The message. - */ -void icinga::IcingaLog(LogSeverity severity, const String& facility, - const String& message) -{ - LogEntry entry; - entry.Timestamp = Utility::GetTime(); - entry.Severity = severity; - entry.Facility = facility; - entry.Message = message; - - if (severity >= LogWarning) { - ContextTrace context; - - if (context.GetLength() > 0) { - std::ostringstream trace; - trace << context; - entry.Message += "\nContext:" + trace.str(); - } - } - - for (const Logger::Ptr& logger : Logger::GetLoggers()) { - ObjectLock llock(logger); - - if (!logger->IsActive()) - continue; - - if (entry.Severity >= logger->GetMinSeverity()) - logger->ProcessLogEntry(entry); - } - - if (Logger::IsConsoleLogEnabled() && entry.Severity >= Logger::GetConsoleLogSeverity()) - StreamLogger::ProcessLogEntry(std::cout, entry); -} - /** * Retrieves the minimum severity for this logger. * @@ -223,3 +193,54 @@ void Logger::ValidateSeverity(const String& value, const ValidationUtils& utils) BOOST_THROW_EXCEPTION(ValidationError(this, { "severity" }, "Invalid severity specified: " + value)); } } + +Log::Log(LogSeverity severity, const String& facility, const String& message) + : m_Severity(severity), m_Facility(facility) +{ + m_Buffer << message; +} + +Log::Log(LogSeverity severity, const String& facility) + : m_Severity(severity), m_Facility(facility) +{ } + +/** + * Writes the message to the application's log. + */ +Log::~Log(void) +{ + LogEntry entry; + entry.Timestamp = Utility::GetTime(); + entry.Severity = m_Severity; + entry.Facility = m_Facility; + entry.Message = m_Buffer.str(); + + if (m_Severity >= LogWarning) { + ContextTrace context; + + if (context.GetLength() > 0) { + std::ostringstream trace; + trace << context; + entry.Message += "\nContext:" + trace.str(); + } + } + + for (const Logger::Ptr& logger : Logger::GetLoggers()) { + ObjectLock llock(logger); + + if (!logger->IsActive()) + continue; + + if (entry.Severity >= logger->GetMinSeverity()) + logger->ProcessLogEntry(entry); + } + + if (Logger::IsConsoleLogEnabled() && entry.Severity >= Logger::GetConsoleLogSeverity()) + StreamLogger::ProcessLogEntry(std::cout, entry); +} + +Log& Log::operator<<(const char *val) +{ + m_Buffer << val; + return *this; +} diff --git a/lib/base/logger.hpp b/lib/base/logger.hpp index 406341d57..69606158c 100644 --- a/lib/base/logger.hpp +++ b/lib/base/logger.hpp @@ -104,25 +104,17 @@ private: static LogSeverity m_ConsoleLogSeverity; }; -void IcingaLog(LogSeverity severity, const String& facility, const String& message); - class Log { public: - Log(LogSeverity severity, const String& facility, const String& message) - : m_Severity(severity), m_Facility(facility) - { - m_Buffer << message; - } + Log(void) = delete; + Log(const Log& other) = delete; + Log& operator=(const Log& rhs) = delete; - Log(LogSeverity severity, const String& facility) - : m_Severity(severity), m_Facility(facility) - { } + Log(LogSeverity severity, const String& facility, const String& message); + Log(LogSeverity severity, const String& facility); - ~Log(void) - { - IcingaLog(m_Severity, m_Facility, m_Buffer.str()); - } + ~Log(void); template Log& operator<<(const T& val) @@ -131,16 +123,24 @@ public: return *this; } + Log& operator<<(const char *val); + private: LogSeverity m_Severity; String m_Facility; std::ostringstream m_Buffer; - - Log(void); - Log(const Log& other); - Log& operator=(const Log& rhs); }; +extern template Log& Log::operator<<(const Value&); +extern template Log& Log::operator<<(const String&); +extern template Log& Log::operator<<(const std::string&); +extern template Log& Log::operator<<(const bool&); +extern template Log& Log::operator<<(const unsigned int&); +extern template Log& Log::operator<<(const int&); +extern template Log& Log::operator<<(const unsigned long&); +extern template Log& Log::operator<<(const long&); +extern template Log& Log::operator<<(const double&); + } #endif /* LOGGER_H */ diff --git a/lib/base/object.cpp b/lib/base/object.cpp index 73104c0b9..f435ca9be 100644 --- a/lib/base/object.cpp +++ b/lib/base/object.cpp @@ -26,6 +26,7 @@ #include "base/logger.hpp" #include "base/exception.hpp" #include +#include using namespace icinga; diff --git a/lib/base/object.hpp b/lib/base/object.hpp index 8740f337c..a5cfaf502 100644 --- a/lib/base/object.hpp +++ b/lib/base/object.hpp @@ -22,7 +22,6 @@ #include "base/i2-base.hpp" #include "base/debug.hpp" -#include #include #include #include diff --git a/lib/base/objectlock.cpp b/lib/base/objectlock.cpp new file mode 100644 index 000000000..5d44de30b --- /dev/null +++ b/lib/base/objectlock.cpp @@ -0,0 +1,140 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012-2018 Icinga Development Team (https://www.icinga.com/) * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software Foundation * + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * + ******************************************************************************/ + +#include "base/objectlock.hpp" +#include + +using namespace icinga; + +#define I2MUTEX_UNLOCKED 0 +#define I2MUTEX_LOCKED 1 + +ObjectLock::ObjectLock(void) + : m_Object(nullptr), m_Locked(false) +{ } + +ObjectLock::~ObjectLock(void) +{ + Unlock(); +} + +ObjectLock::ObjectLock(const Object::Ptr& object) + : m_Object(object.get()), m_Locked(false) +{ + if (m_Object) + Lock(); +} + +ObjectLock::ObjectLock(const Object *object) + : m_Object(object), m_Locked(false) +{ + if (m_Object) + Lock(); +} + +void ObjectLock::LockMutex(const Object *object) +{ + unsigned int it = 0; + +#ifdef _WIN32 +# ifdef _WIN64 + while (likely(InterlockedCompareExchange64((LONGLONG *)&object->m_Mutex, I2MUTEX_LOCKED, I2MUTEX_UNLOCKED) != I2MUTEX_UNLOCKED)) { +# else /* _WIN64 */ + while (likely(InterlockedCompareExchange(&object->m_Mutex, I2MUTEX_LOCKED, I2MUTEX_UNLOCKED) != I2MUTEX_UNLOCKED)) { +# endif /* _WIN64 */ +#else /* _WIN32 */ + while (likely(!__sync_bool_compare_and_swap(&object->m_Mutex, I2MUTEX_UNLOCKED, I2MUTEX_LOCKED))) { +#endif /* _WIN32 */ + if (likely(object->m_Mutex > I2MUTEX_LOCKED)) { + boost::recursive_mutex *mtx = reinterpret_cast(object->m_Mutex); + mtx->lock(); + + return; + } + + Spin(it); + it++; + } + + boost::recursive_mutex *mtx = new boost::recursive_mutex(); + mtx->lock(); +#ifdef _WIN32 +# ifdef _WIN64 + InterlockedCompareExchange64((LONGLONG *)&object->m_Mutex, reinterpret_cast(mtx), I2MUTEX_LOCKED); +# else /* _WIN64 */ + InterlockedCompareExchange(&object->m_Mutex, reinterpret_cast(mtx), I2MUTEX_LOCKED); +# endif /* _WIN64 */ +#else /* _WIN32 */ + __sync_bool_compare_and_swap(&object->m_Mutex, I2MUTEX_LOCKED, reinterpret_cast(mtx)); +#endif /* _WIN32 */ +} + +void ObjectLock::Lock(void) +{ + ASSERT(!m_Locked && m_Object); + + LockMutex(m_Object); + + m_Locked = true; + +#ifdef I2_DEBUG +# ifdef _WIN32 + InterlockedExchange(&m_Object->m_LockOwner, GetCurrentThreadId()); +# else /* _WIN32 */ + __sync_lock_test_and_set(&m_Object->m_LockOwner, pthread_self()); +# endif /* _WIN32 */ +#endif /* I2_DEBUG */ +} + +void ObjectLock::Spin(unsigned int it) +{ + if (it < 8) { + /* Do nothing. */ + } +#ifdef SPIN_PAUSE + else if (it < 16) { + SPIN_PAUSE(); + } +#endif /* SPIN_PAUSE */ + else { +#ifdef _WIN32 + Sleep(0); +#else /* _WIN32 */ + sched_yield(); +#endif /* _WIN32 */ + } +} + +void ObjectLock::Unlock(void) +{ +#ifdef I2_DEBUG + if (m_Locked) { +# ifdef _WIN32 + InterlockedExchange(&m_Object->m_LockOwner, 0); +# else /* _WIN32 */ + __sync_lock_release(&m_Object->m_LockOwner); +# endif /* _WIN32 */ + } +#endif /* I2_DEBUG */ + + if (m_Locked) { + reinterpret_cast(m_Object->m_Mutex)->unlock(); + m_Locked = false; + } +} diff --git a/lib/base/objectlock.hpp b/lib/base/objectlock.hpp index 427e90a26..cf7c6d12b 100644 --- a/lib/base/objectlock.hpp +++ b/lib/base/objectlock.hpp @@ -22,9 +22,6 @@ #include "base/object.hpp" -#define I2MUTEX_UNLOCKED 0 -#define I2MUTEX_LOCKED 1 - namespace icinga { @@ -34,119 +31,19 @@ namespace icinga struct ObjectLock { public: - ObjectLock(void) - : m_Object(nullptr), m_Locked(false) - { } - - ~ObjectLock(void) - { - Unlock(); - } - - ObjectLock(const Object::Ptr& object) - : m_Object(object.get()), m_Locked(false) - { - if (m_Object) - Lock(); - } - - ObjectLock(const Object *object) - : m_Object(object), m_Locked(false) - { - if (m_Object) - Lock(); - } - - static void LockMutex(const Object *object) - { - unsigned int it = 0; - -#ifdef _WIN32 -# ifdef _WIN64 - while (likely(InterlockedCompareExchange64((LONGLONG *)&object->m_Mutex, I2MUTEX_LOCKED, I2MUTEX_UNLOCKED) != I2MUTEX_UNLOCKED)) { -# else /* _WIN64 */ - while (likely(InterlockedCompareExchange(&object->m_Mutex, I2MUTEX_LOCKED, I2MUTEX_UNLOCKED) != I2MUTEX_UNLOCKED)) { -# endif /* _WIN64 */ -#else /* _WIN32 */ - while (likely(!__sync_bool_compare_and_swap(&object->m_Mutex, I2MUTEX_UNLOCKED, I2MUTEX_LOCKED))) { -#endif /* _WIN32 */ - if (likely(object->m_Mutex > I2MUTEX_LOCKED)) { - boost::recursive_mutex *mtx = reinterpret_cast(object->m_Mutex); - mtx->lock(); - - return; - } - - Spin(it); - it++; - } - - boost::recursive_mutex *mtx = new boost::recursive_mutex(); - mtx->lock(); -#ifdef _WIN32 -# ifdef _WIN64 - InterlockedCompareExchange64((LONGLONG *)&object->m_Mutex, reinterpret_cast(mtx), I2MUTEX_LOCKED); -# else /* _WIN64 */ - InterlockedCompareExchange(&object->m_Mutex, reinterpret_cast(mtx), I2MUTEX_LOCKED); -# endif /* _WIN64 */ -#else /* _WIN32 */ - __sync_bool_compare_and_swap(&object->m_Mutex, I2MUTEX_LOCKED, reinterpret_cast(mtx)); -#endif /* _WIN32 */ - } - - void Lock(void) - { - ASSERT(!m_Locked && m_Object); - - LockMutex(m_Object); + ObjectLock(void); + ObjectLock(const Object::Ptr& object); + ObjectLock(const Object *object); - m_Locked = true; + ~ObjectLock(void); -#ifdef I2_DEBUG -# ifdef _WIN32 - InterlockedExchange(&m_Object->m_LockOwner, GetCurrentThreadId()); -# else /* _WIN32 */ - __sync_lock_test_and_set(&m_Object->m_LockOwner, pthread_self()); -# endif /* _WIN32 */ -#endif /* I2_DEBUG */ - } + static void LockMutex(const Object *object); - static void Spin(unsigned int it) - { - if (it < 8) { - /* Do nothing. */ - } -#ifdef SPIN_PAUSE - else if (it < 16) { - SPIN_PAUSE(); - } -#endif /* SPIN_PAUSE */ - else { -#ifdef _WIN32 - Sleep(0); -#else /* _WIN32 */ - sched_yield(); -#endif /* _WIN32 */ - } - } + void Lock(void); - void Unlock(void) - { -#ifdef I2_DEBUG - if (m_Locked) { -# ifdef _WIN32 - InterlockedExchange(&m_Object->m_LockOwner, 0); -# else /* _WIN32 */ - __sync_lock_release(&m_Object->m_LockOwner); -# endif /* _WIN32 */ - } -#endif /* I2_DEBUG */ + static void Spin(unsigned int it); - if (m_Locked) { - reinterpret_cast(m_Object->m_Mutex)->unlock(); - m_Locked = false; - } - } + void Unlock(void); private: const Object *m_Object; diff --git a/lib/base/string.cpp b/lib/base/string.cpp index 75300c234..4e8c1c1f6 100644 --- a/lib/base/string.cpp +++ b/lib/base/string.cpp @@ -25,10 +25,40 @@ using namespace icinga; +template class std::vector; + REGISTER_BUILTIN_TYPE(String, String::GetPrototype()); const String::SizeType String::NPos = std::string::npos; +String::String(void) + : m_Data() +{ } + +String::String(const char *data) + : m_Data(data) +{ } + +String::String(const std::string& data) + : m_Data(data) +{ } + +String::String(std::string&& data) + : m_Data(std::move(data)) +{ } + +String::String(String::SizeType n, char c) + : m_Data(n, c) +{ } + +String::String(const String& other) + : m_Data(other) +{ } + +String::String(String&& other) + : m_Data(std::move(other.m_Data)) +{ } + #ifndef _MSC_VER String::String(Value&& other) { @@ -36,6 +66,9 @@ String::String(Value&& other) } #endif /* _MSC_VER */ +String::~String(void) +{ } + String& String::operator=(Value&& other) { if (other.IsString()) @@ -52,3 +85,392 @@ String& String::operator+=(const Value& rhs) return *this; } +String& String::operator=(const String& rhs) +{ + m_Data = rhs.m_Data; + return *this; +} + +String& String::operator=(String&& rhs) +{ + m_Data = std::move(rhs.m_Data); + return *this; +} + +String& String::operator=(const std::string& rhs) +{ + m_Data = rhs; + return *this; +} + +String& String::operator=(const char *rhs) +{ + m_Data = rhs; + return *this; +} + +const char& String::operator[](String::SizeType pos) const +{ + return m_Data[pos]; +} + +char& String::operator[](String::SizeType pos) +{ + return m_Data[pos]; +} + +String& String::operator+=(const String& rhs) +{ + m_Data += rhs.m_Data; + return *this; +} + +String& String::operator+=(const char *rhs) +{ + m_Data += rhs; + return *this; +} + +String& String::operator+=(char rhs) +{ + m_Data += rhs; + return *this; +} + +bool String::IsEmpty(void) const +{ + return m_Data.empty(); +} + +bool String::operator<(const String& rhs) const +{ + return m_Data < rhs.m_Data; +} + +String::operator const std::string&(void) const +{ + return m_Data; +} + +const char *String::CStr(void) const +{ + return m_Data.c_str(); +} + +void String::Clear(void) +{ + m_Data.clear(); +} + +String::SizeType String::GetLength(void) const +{ + return m_Data.size(); +} + +std::string& String::GetData(void) +{ + return m_Data; +} + +const std::string& String::GetData(void) const +{ + return m_Data; +} + +String::SizeType String::Find(const String& str, String::SizeType pos) const +{ + return m_Data.find(str, pos); +} + +String::SizeType String::RFind(const String& str, String::SizeType pos) const +{ + return m_Data.rfind(str, pos); +} + +String::SizeType String::FindFirstOf(const char *s, String::SizeType pos) const +{ + return m_Data.find_first_of(s, pos); +} + +String::SizeType String::FindFirstOf(char ch, String::SizeType pos) const +{ + return m_Data.find_first_of(ch, pos); +} + +String::SizeType String::FindFirstNotOf(const char *s, String::SizeType pos) const +{ + return m_Data.find_first_not_of(s, pos); +} + +String::SizeType String::FindFirstNotOf(char ch, String::SizeType pos) const +{ + return m_Data.find_first_not_of(ch, pos); +} + +String::SizeType String::FindLastOf(const char *s, String::SizeType pos) const +{ + return m_Data.find_last_of(s, pos); +} + +String::SizeType String::FindLastOf(char ch, String::SizeType pos) const +{ + return m_Data.find_last_of(ch, pos); +} + +String String::SubStr(String::SizeType first, String::SizeType len) const +{ + return m_Data.substr(first, len); +} + +std::vector String::Split(const char *separators) const +{ + std::vector result; + boost::algorithm::split(result, m_Data, boost::is_any_of(separators)); + return result; +} + +void String::Replace(String::SizeType first, String::SizeType second, const String& str) +{ + m_Data.replace(first, second, str); +} + +String String::Trim(void) const +{ + String t = m_Data; + boost::algorithm::trim(t); + return t; +} + +String String::ToLower(void) const +{ + String t = m_Data; + boost::algorithm::to_lower(t); + return t; +} + +String String::ToUpper(void) const +{ + String t = m_Data; + boost::algorithm::to_upper(t); + return t; +} + +String String::Reverse(void) const +{ + String t = m_Data; + std::reverse(t.m_Data.begin(), t.m_Data.end()); + return t; +} + +void String::Append(int count, char ch) +{ + m_Data.append(count, ch); +} + +bool String::Contains(const String& str) const +{ + return (m_Data.find(str) != std::string::npos); +} + +void String::swap(String& str) +{ + m_Data.swap(str.m_Data); +} + +String::Iterator String::erase(String::Iterator first, String::Iterator last) +{ + return m_Data.erase(first, last); +} + +String::Iterator String::Begin(void) +{ + return m_Data.begin(); +} + +String::ConstIterator String::Begin(void) const +{ + return m_Data.begin(); +} + +String::Iterator String::End(void) +{ + return m_Data.end(); +} + +String::ConstIterator String::End(void) const +{ + return m_Data.end(); +} + +String::ReverseIterator String::RBegin(void) +{ + return m_Data.rbegin(); +} + +String::ConstReverseIterator String::RBegin(void) const +{ + return m_Data.rbegin(); +} + +String::ReverseIterator String::REnd(void) +{ + return m_Data.rend(); +} + +String::ConstReverseIterator String::REnd(void) const +{ + return m_Data.rend(); +} + +std::ostream& icinga::operator<<(std::ostream& stream, const String& str) +{ + stream << str.GetData(); + return stream; +} + +std::istream& icinga::operator>>(std::istream& stream, String& str) +{ + std::string tstr; + stream >> tstr; + str = tstr; + return stream; +} + +String icinga::operator+(const String& lhs, const String& rhs) +{ + return lhs.GetData() + rhs.GetData(); +} + +String icinga::operator+(const String& lhs, const char *rhs) +{ + return lhs.GetData() + rhs; +} + +String icinga::operator+(const char *lhs, const String& rhs) +{ + return lhs + rhs.GetData(); +} + +bool icinga::operator==(const String& lhs, const String& rhs) +{ + return lhs.GetData() == rhs.GetData(); +} + +bool icinga::operator==(const String& lhs, const char *rhs) +{ + return lhs.GetData() == rhs; +} + +bool icinga::operator==(const char *lhs, const String& rhs) +{ + return lhs == rhs.GetData(); +} + +bool icinga::operator<(const String& lhs, const char *rhs) +{ + return lhs.GetData() < rhs; +} + +bool icinga::operator<(const char *lhs, const String& rhs) +{ + return lhs < rhs.GetData(); +} + +bool icinga::operator>(const String& lhs, const String& rhs) +{ + return lhs.GetData() > rhs.GetData(); +} + +bool icinga::operator>(const String& lhs, const char *rhs) +{ + return lhs.GetData() > rhs; +} + +bool icinga::operator>(const char *lhs, const String& rhs) +{ + return lhs > rhs.GetData(); +} + +bool icinga::operator<=(const String& lhs, const String& rhs) +{ + return lhs.GetData() <= rhs.GetData(); +} + +bool icinga::operator<=(const String& lhs, const char *rhs) +{ + return lhs.GetData() <= rhs; +} + +bool icinga::operator<=(const char *lhs, const String& rhs) +{ + return lhs <= rhs.GetData(); +} + +bool icinga::operator>=(const String& lhs, const String& rhs) +{ + return lhs.GetData() >= rhs.GetData(); +} + +bool icinga::operator>=(const String& lhs, const char *rhs) +{ + return lhs.GetData() >= rhs; +} + +bool icinga::operator>=(const char *lhs, const String& rhs) +{ + return lhs >= rhs.GetData(); +} + +bool icinga::operator!=(const String& lhs, const String& rhs) +{ + return lhs.GetData() != rhs.GetData(); +} + +bool icinga::operator!=(const String& lhs, const char *rhs) +{ + return lhs.GetData() != rhs; +} + +bool icinga::operator!=(const char *lhs, const String& rhs) +{ + return lhs != rhs.GetData(); +} + +String::Iterator icinga::begin(String& x) +{ + return x.Begin(); +} + +String::ConstIterator icinga::begin(const String& x) +{ + return x.Begin(); +} + +String::Iterator icinga::end(String& x) +{ + return x.End(); +} + +String::ConstIterator icinga::end(const String& x) +{ + return x.End(); +} +String::Iterator icinga::range_begin(String& x) +{ + return x.Begin(); +} + +String::ConstIterator icinga::range_begin(const String& x) +{ + return x.Begin(); +} + +String::Iterator icinga::range_end(String& x) +{ + return x.End(); +} + +String::ConstIterator icinga::range_end(const String& x) +{ + return x.End(); +} diff --git a/lib/base/string.hpp b/lib/base/string.hpp index 9a844d447..ca2cb96af 100644 --- a/lib/base/string.hpp +++ b/lib/base/string.hpp @@ -58,246 +58,84 @@ public: typedef std::string::size_type SizeType; - String(void) - : m_Data() - { } - - String(const char *data) - : m_Data(data) - { } - - String(const std::string& data) - : m_Data(data) - { } - - String(std::string&& data) - : m_Data(data) - { } - - String(String::SizeType n, char c) - : m_Data(n, c) - { } - - String(const String& other) - : m_Data(other) - { } - - String(String&& other) - : m_Data(std::move(other.m_Data)) - { } + String(void); + String(const char *data); + String(const std::string& data); + String(std::string&& data); + String(String::SizeType n, char c); + String(const String& other); + String(String&& other); #ifndef _MSC_VER String(Value&& other); #endif /* _MSC_VER */ - ~String(void) - { } + ~String(void); template String(InputIterator begin, InputIterator end) : m_Data(begin, end) { } - String& operator=(const String& rhs) - { - m_Data = rhs.m_Data; - return *this; - } - - String& operator=(String&& rhs) - { - m_Data = std::move(rhs.m_Data); - return *this; - } - + String& operator=(const String& rhs); + String& operator=(String&& rhs); String& operator=(Value&& rhs); + String& operator=(const std::string& rhs); + String& operator=(const char *rhs); - String& operator=(const std::string& rhs) - { - m_Data = rhs; - return *this; - } - - String& operator=(const char *rhs) - { - m_Data = rhs; - return *this; - } - - const char& operator[](SizeType pos) const - { - return m_Data[pos]; - } - - char& operator[](SizeType pos) - { - return m_Data[pos]; - } - - String& operator+=(const String& rhs) - { - m_Data += rhs.m_Data; - return *this; - } - - String& operator+=(const char *rhs) - { - m_Data += rhs; - return *this; - } + const char& operator[](SizeType pos) const; + char& operator[](SizeType pos); + String& operator+=(const String& rhs); + String& operator+=(const char *rhs); String& operator+=(const Value& rhs); + String& operator+=(char rhs); - String& operator+=(char rhs) - { - m_Data += rhs; - return *this; - } - - bool IsEmpty(void) const - { - return m_Data.empty(); - } - - bool operator<(const String& rhs) const - { - return m_Data < rhs.m_Data; - } - - operator const std::string&(void) const - { - return m_Data; - } - - const char *CStr(void) const - { - return m_Data.c_str(); - } - - void Clear(void) - { - m_Data.clear(); - } + bool IsEmpty(void) const; - SizeType GetLength(void) const - { - return m_Data.size(); - } + bool operator<(const String& rhs) const; - std::string& GetData(void) - { - return m_Data; - } + operator const std::string&(void) const; - const std::string& GetData(void) const - { - return m_Data; - } + const char *CStr(void) const; - SizeType Find(const String& str, SizeType pos = 0) const - { - return m_Data.find(str, pos); - } + void Clear(void); - SizeType RFind(const String& str, SizeType pos = NPos) const - { - return m_Data.rfind(str, pos); - } + SizeType GetLength(void) const; - SizeType FindFirstOf(const char *s, SizeType pos = 0) const - { - return m_Data.find_first_of(s, pos); - } + std::string& GetData(void); + const std::string& GetData(void) const; - SizeType FindFirstOf(char ch, SizeType pos = 0) const - { - return m_Data.find_first_of(ch, pos); - } + SizeType Find(const String& str, SizeType pos = 0) const; + SizeType RFind(const String& str, SizeType pos = NPos) const; + SizeType FindFirstOf(const char *s, SizeType pos = 0) const; + SizeType FindFirstOf(char ch, SizeType pos = 0) const; + SizeType FindFirstNotOf(const char *s, SizeType pos = 0) const; + SizeType FindFirstNotOf(char ch, SizeType pos = 0) const; + SizeType FindLastOf(const char *s, SizeType pos = NPos) const; + SizeType FindLastOf(char ch, SizeType pos = NPos) const; - SizeType FindFirstNotOf(const char *s, SizeType pos = 0) const - { - return m_Data.find_first_not_of(s, pos); - } + String SubStr(SizeType first, SizeType len = NPos) const; - SizeType FindFirstNotOf(char ch, SizeType pos = 0) const - { - return m_Data.find_first_not_of(ch, pos); - } + std::vector Split(const char *separators) const; - SizeType FindLastOf(const char *s, SizeType pos = NPos) const - { - return m_Data.find_last_of(s, pos); - } + void Replace(SizeType first, SizeType second, const String& str); - SizeType FindLastOf(char ch, SizeType pos = NPos) const - { - return m_Data.find_last_of(ch, pos); - } + String Trim(void) const; - String SubStr(SizeType first, SizeType len = NPos) const - { - return m_Data.substr(first, len); - } + String ToLower(void) const; - std::vector Split(const char *separators) const - { - std::vector result; - boost::algorithm::split(result, m_Data, boost::is_any_of(separators)); - return result; - } + String ToUpper(void) const; - void Replace(SizeType first, SizeType second, const String& str) - { - m_Data.replace(first, second, str); - } + String Reverse(void) const; - String Trim(void) const - { - String t = m_Data; - boost::algorithm::trim(t); - return t; - } + void Append(int count, char ch); - String ToLower(void) const - { - String t = m_Data; - boost::algorithm::to_lower(t); - return t; - } + bool Contains(const String& str) const; - String ToUpper(void) const - { - String t = m_Data; - boost::algorithm::to_upper(t); - return t; - } + void swap(String& str); - String Reverse(void) const - { - String t = m_Data; - std::reverse(t.m_Data.begin(), t.m_Data.end()); - return t; - } - - void Append(int count, char ch) - { - m_Data.append(count, ch); - } - - bool Contains(const String& str) const - { - return (m_Data.find(str) != std::string::npos); - } - - void swap(String& str) - { - m_Data.swap(str.m_Data); - } - - Iterator erase(Iterator first, Iterator last) - { - return m_Data.erase(first, last); - } + Iterator erase(Iterator first, Iterator last); template void insert(Iterator p, InputIterator first, InputIterator last) @@ -305,45 +143,14 @@ public: m_Data.insert(p, first, last); } - Iterator Begin(void) - { - return m_Data.begin(); - } - - ConstIterator Begin(void) const - { - return m_Data.begin(); - } - - Iterator End(void) - { - return m_Data.end(); - } - - ConstIterator End(void) const - { - return m_Data.end(); - } - - ReverseIterator RBegin(void) - { - return m_Data.rbegin(); - } - - ConstReverseIterator RBegin(void) const - { - return m_Data.rbegin(); - } - - ReverseIterator REnd(void) - { - return m_Data.rend(); - } - - ConstReverseIterator REnd(void) const - { - return m_Data.rend(); - } + Iterator Begin(void); + ConstIterator Begin(void) const; + Iterator End(void); + ConstIterator End(void) const; + ReverseIterator RBegin(void); + ConstReverseIterator RBegin(void) const; + ReverseIterator REnd(void); + ConstReverseIterator REnd(void) const; static const SizeType NPos; @@ -353,160 +160,48 @@ private: std::string m_Data; }; -inline std::ostream& operator<<(std::ostream& stream, const String& str) -{ - stream << str.GetData(); - return stream; -} - -inline std::istream& operator>>(std::istream& stream, String& str) -{ - std::string tstr; - stream >> tstr; - str = tstr; - return stream; -} - -inline String operator+(const String& lhs, const String& rhs) -{ - return lhs.GetData() + rhs.GetData(); -} - -inline String operator+(const String& lhs, const char *rhs) -{ - return lhs.GetData() + rhs; -} - -inline String operator+(const char *lhs, const String& rhs) -{ - return lhs + rhs.GetData(); -} - -inline bool operator==(const String& lhs, const String& rhs) -{ - return lhs.GetData() == rhs.GetData(); -} - -inline bool operator==(const String& lhs, const char *rhs) -{ - return lhs.GetData() == rhs; -} - -inline bool operator==(const char *lhs, const String& rhs) -{ - return lhs == rhs.GetData(); -} - -inline bool operator<(const String& lhs, const char *rhs) -{ - return lhs.GetData() < rhs; -} - -inline bool operator<(const char *lhs, const String& rhs) -{ - return lhs < rhs.GetData(); -} - -inline bool operator>(const String& lhs, const String& rhs) -{ - return lhs.GetData() > rhs.GetData(); -} +std::ostream& operator<<(std::ostream& stream, const String& str); +std::istream& operator>>(std::istream& stream, String& str); -inline bool operator>(const String& lhs, const char *rhs) -{ - return lhs.GetData() > rhs; -} +String operator+(const String& lhs, const String& rhs); +String operator+(const String& lhs, const char *rhs); +String operator+(const char *lhs, const String& rhs); -inline bool operator>(const char *lhs, const String& rhs) -{ - return lhs > rhs.GetData(); -} - -inline bool operator<=(const String& lhs, const String& rhs) -{ - return lhs.GetData() <= rhs.GetData(); -} +bool operator==(const String& lhs, const String& rhs); +bool operator==(const String& lhs, const char *rhs); +bool operator==(const char *lhs, const String& rhs); -inline bool operator<=(const String& lhs, const char *rhs) -{ - return lhs.GetData() <= rhs; -} +bool operator<(const String& lhs, const char *rhs); +bool operator<(const char *lhs, const String& rhs); -inline bool operator<=(const char *lhs, const String& rhs) -{ - return lhs <= rhs.GetData(); -} +bool operator>(const String& lhs, const String& rhs); +bool operator>(const String& lhs, const char *rhs); +bool operator>(const char *lhs, const String& rhs); -inline bool operator>=(const String& lhs, const String& rhs) -{ - return lhs.GetData() >= rhs.GetData(); -} +bool operator<=(const String& lhs, const String& rhs); +bool operator<=(const String& lhs, const char *rhs); +bool operator<=(const char *lhs, const String& rhs); -inline bool operator>=(const String& lhs, const char *rhs) -{ - return lhs.GetData() >= rhs; -} +bool operator>=(const String& lhs, const String& rhs); +bool operator>=(const String& lhs, const char *rhs); +bool operator>=(const char *lhs, const String& rhs); -inline bool operator>=(const char *lhs, const String& rhs) -{ - return lhs >= rhs.GetData(); -} +bool operator!=(const String& lhs, const String& rhs); +bool operator!=(const String& lhs, const char *rhs); +bool operator!=(const char *lhs, const String& rhs); -inline bool operator!=(const String& lhs, const String& rhs) -{ - return lhs.GetData() != rhs.GetData(); -} +String::Iterator begin(String& x); +String::ConstIterator begin(const String& x); +String::Iterator end(String& x); +String::ConstIterator end(const String& x); +String::Iterator range_begin(String& x); +String::ConstIterator range_begin(const String& x); +String::Iterator range_end(String& x); +String::ConstIterator range_end(const String& x); -inline bool operator!=(const String& lhs, const char *rhs) -{ - return lhs.GetData() != rhs; } -inline bool operator!=(const char *lhs, const String& rhs) -{ - return lhs != rhs.GetData(); -} - -inline String::Iterator begin(String& x) -{ - return x.Begin(); -} - -inline String::ConstIterator begin(const String& x) -{ - return x.Begin(); -} - -inline String::Iterator end(String& x) -{ - return x.End(); -} - -inline String::ConstIterator end(const String& x) -{ - return x.End(); -} -inline String::Iterator range_begin(String& x) -{ - return x.Begin(); -} - -inline String::ConstIterator range_begin(const String& x) -{ - return x.Begin(); -} - -inline String::Iterator range_end(String& x) -{ - return x.End(); -} - -inline String::ConstIterator range_end(const String& x) -{ - return x.End(); -} - -} +extern template class std::vector; namespace boost { diff --git a/lib/base/type.cpp b/lib/base/type.cpp index bd0844572..c18ae9f9a 100644 --- a/lib/base/type.cpp +++ b/lib/base/type.cpp @@ -32,6 +32,12 @@ INITIALIZE_ONCE_WITH_PRIORITY([]() { Type::Register(type); }, 20); +Type::Type(void) +{ } + +Type::~Type(void) +{ } + String Type::ToString(void) const { return "type '" + GetName() + "'"; diff --git a/lib/base/type.hpp b/lib/base/type.hpp index 3b860bc79..09d550bd4 100644 --- a/lib/base/type.hpp +++ b/lib/base/type.hpp @@ -75,6 +75,9 @@ class Type : public Object public: DECLARE_OBJECT(Type); + Type(void); + ~Type(void); + virtual String ToString(void) const override; virtual String GetName(void) const = 0; diff --git a/lib/base/value.cpp b/lib/base/value.cpp index cb9472049..ee2f1816c 100644 --- a/lib/base/value.cpp +++ b/lib/base/value.cpp @@ -24,8 +24,182 @@ using namespace icinga; +template class boost::variant; +template const double& Value::Get(void) const; +template const bool& Value::Get(void) const; +template const String& Value::Get(void) const; +template const Object::Ptr& Value::Get(void) const; + Value icinga::Empty; +Value::Value(void) +{ } + +Value::Value(std::nullptr_t) +{ } + +Value::Value(int value) + : m_Value(double(value)) +{ } + +Value::Value(unsigned int value) + : m_Value(double(value)) +{ } + +Value::Value(long value) + : m_Value(double(value)) +{ } + +Value::Value(unsigned long value) + : m_Value(double(value)) +{ } + +Value::Value(long long value) + : m_Value(double(value)) +{ } + +Value::Value(unsigned long long value) + : m_Value(double(value)) +{ } + +Value::Value(double value) + : m_Value(value) +{ } + +Value::Value(bool value) + : m_Value(value) +{ } + +Value::Value(const String& value) + : m_Value(value) +{ } + +Value::Value(String&& value) + : m_Value(value) +{ } + +Value::Value(const char *value) + : m_Value(String(value)) +{ } + +Value::Value(const Value& other) + : m_Value(other.m_Value) +{ } + +Value::Value(Value&& other) +{ +#if BOOST_VERSION >= 105400 + m_Value = std::move(other.m_Value); +#else /* BOOST_VERSION */ + m_Value.swap(other.m_Value); +#endif /* BOOST_VERSION */ +} + +Value::Value(Object *value) + : Value(Object::Ptr(value)) +{ } + +Value::Value(const intrusive_ptr& value) +{ + if (value) + m_Value = value; +} + +Value::~Value(void) +{ } + +Value& Value::operator=(const Value& other) +{ + m_Value = other.m_Value; + return *this; +} + +Value& Value::operator=(Value&& other) +{ +#if BOOST_VERSION >= 105400 + m_Value = std::move(other.m_Value); +#else /* BOOST_VERSION */ + m_Value.swap(other.m_Value); +#endif /* BOOST_VERSION */ + + return *this; +} + +/** + * Checks whether the variant is empty. + * + * @returns true if the variant is empty, false otherwise. + */ +bool Value::IsEmpty(void) const +{ + return (GetType() == ValueEmpty || (IsString() && boost::get(m_Value).IsEmpty())); +} + +/** + * Checks whether the variant is scalar (i.e. not an object and not empty). + * + * @returns true if the variant is scalar, false otherwise. + */ +bool Value::IsScalar(void) const +{ + return !IsEmpty() && !IsObject(); +} + +/** +* Checks whether the variant is a number. +* +* @returns true if the variant is a number. +*/ +bool Value::IsNumber(void) const +{ + return (GetType() == ValueNumber); +} + +/** + * Checks whether the variant is a boolean. + * + * @returns true if the variant is a boolean. + */ +bool Value::IsBoolean(void) const +{ + return (GetType() == ValueBoolean); +} + +/** + * Checks whether the variant is a string. + * + * @returns true if the variant is a string. + */ +bool Value::IsString(void) const +{ + return (GetType() == ValueString); +} + +/** + * Checks whether the variant is a non-null object. + * + * @returns true if the variant is a non-null object, false otherwise. + */ +bool Value::IsObject(void) const +{ + return (GetType() == ValueObject); +} + +/** + * Returns the type of the value. + * + * @returns The type. + */ +ValueType Value::GetType(void) const +{ + return static_cast(m_Value.which()); +} + +void Value::Swap(Value& other) +{ + m_Value.swap(other.m_Value); +} + bool Value::ToBool(void) const { switch (GetType()) { @@ -111,4 +285,3 @@ Value Value::Clone(void) const else return *this; } - diff --git a/lib/base/value.hpp b/lib/base/value.hpp index 688f6cc10..07c62c174 100644 --- a/lib/base/value.hpp +++ b/lib/base/value.hpp @@ -52,107 +52,40 @@ enum ValueType class Value { public: - Value(void) - { } - - Value(std::nullptr_t) - { } - - Value(int value) - : m_Value(double(value)) - { } - - Value(unsigned int value) - : m_Value(double(value)) - { } - - Value(long value) - : m_Value(double(value)) - { } - - Value(unsigned long value) - : m_Value(double(value)) - { } - - Value(long long value) - : m_Value(double(value)) - { } - - Value(unsigned long long value) - : m_Value(double(value)) - { } - - Value(double value) - : m_Value(value) - { } - - Value(bool value) - : m_Value(value) - { } - - Value(const String& value) - : m_Value(value) - { } - - Value(String&& value) - : m_Value(value) - { } - - Value(const char *value) - : m_Value(String(value)) - { } - - Value(const Value& other) - : m_Value(other.m_Value) - { } - - Value(Value&& other) - { -#if BOOST_VERSION >= 105400 - m_Value = std::move(other.m_Value); -#else /* BOOST_VERSION */ - m_Value.swap(other.m_Value); -#endif /* BOOST_VERSION */ - } - - Value(Object *value) - { - if (!value) - return; - - m_Value = Object::Ptr(value); - } + Value(void); + Value(std::nullptr_t); + Value(int value); + Value(unsigned int value); + Value(long value); + Value(unsigned long value); + Value(long long value); + Value(unsigned long long value); + Value(double value); + Value(bool value); + Value(const String& value); + Value(String&& value); + Value(const char *value); + Value(const Value& other); + Value(Value&& other); + Value(Object *value); + Value(const intrusive_ptr& value); template Value(const intrusive_ptr& value) + : Value(static_pointer_cast(value)) { - if (!value) - return; - - m_Value = static_pointer_cast(value); + static_assert(!std::is_same::value, "T must not be Object"); } + ~Value(void); + bool ToBool(void) const; operator double(void) const; operator String(void) const; - Value& operator=(const Value& other) - { - m_Value = other.m_Value; - return *this; - } - - Value& operator=(Value&& other) - { -#if BOOST_VERSION >= 105400 - m_Value = std::move(other.m_Value); -#else /* BOOST_VERSION */ - m_Value.swap(other.m_Value); -#endif /* BOOST_VERSION */ - - return *this; - } + Value& operator=(const Value& other); + Value& operator=(Value&& other); bool operator==(bool rhs) const; bool operator!=(bool rhs) const; @@ -181,7 +114,7 @@ public: if (!IsObject()) BOOST_THROW_EXCEPTION(std::runtime_error("Cannot convert value of type '" + GetTypeName() + "' to an object.")); - const Object::Ptr& object = boost::get(m_Value); + const Object::Ptr& object = Get(); ASSERT(object); @@ -193,65 +126,12 @@ public: return tobject; } - /** - * Checks whether the variant is empty. - * - * @returns true if the variant is empty, false otherwise. - */ - bool IsEmpty(void) const - { - return (GetType() == ValueEmpty || (IsString() && boost::get(m_Value).IsEmpty())); - } - - /** - * Checks whether the variant is scalar (i.e. not an object and not empty). - * - * @returns true if the variant is scalar, false otherwise. - */ - bool IsScalar(void) const - { - return !IsEmpty() && !IsObject(); - } - - /** - * Checks whether the variant is a number. - * - * @returns true if the variant is a number. - */ - bool IsNumber(void) const - { - return (GetType() == ValueNumber); - } - - /** - * Checks whether the variant is a boolean. - * - * @returns true if the variant is a boolean. - */ - bool IsBoolean(void) const - { - return (GetType() == ValueBoolean); - } - - /** - * Checks whether the variant is a string. - * - * @returns true if the variant is a string. - */ - bool IsString(void) const - { - return (GetType() == ValueString); - } - - /** - * Checks whether the variant is a non-null object. - * - * @returns true if the variant is a non-null object, false otherwise. - */ - bool IsObject(void) const - { - return (GetType() == ValueObject); - } + bool IsEmpty(void) const; + bool IsScalar(void) const; + bool IsNumber(void) const; + bool IsBoolean(void) const; + bool IsString(void) const; + bool IsObject(void) const; template bool IsObjectType(void) const @@ -259,23 +139,12 @@ public: if (!IsObject()) return false; - return dynamic_cast(boost::get(m_Value).get()); + return dynamic_cast(Get().get()); } - /** - * Returns the type of the value. - * - * @returns The type. - */ - ValueType GetType(void) const - { - return static_cast(m_Value.which()); - } + ValueType GetType(void) const; - void Swap(Value& other) - { - m_Value.swap(other.m_Value); - } + void Swap(Value& other); String GetTypeName(void) const; @@ -293,6 +162,11 @@ private: boost::variant m_Value; }; +extern template const double& Value::Get(void) const; +extern template const bool& Value::Get(void) const; +extern template const String& Value::Get(void) const; +extern template const Object::Ptr& Value::Get(void) const; + extern Value Empty; Value operator+(const Value& lhs, const char *rhs); @@ -390,4 +264,6 @@ std::istream& operator>>(std::istream& stream, Value& value); } +extern template class boost::variant; + #endif /* VALUE_H */ diff --git a/tools/mkclass/classcompiler.cpp b/tools/mkclass/classcompiler.cpp index 525358d75..63f0f8ad0 100644 --- a/tools/mkclass/classcompiler.cpp +++ b/tools/mkclass/classcompiler.cpp @@ -219,7 +219,14 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&) m_Header << std::endl << "{" << std::endl << "public:" << std::endl - << "\t" << "DECLARE_PTR_TYPEDEFS(TypeImpl<" << klass.Name << ">);" << std::endl << std::endl; + << "\t" << "DECLARE_PTR_TYPEDEFS(TypeImpl<" << klass.Name << ">);" << std::endl << std::endl + << "\t" << "TypeImpl(void);" << std::endl + << "\t" << "~TypeImpl(void);" << std::endl << std::endl; + + m_Impl << "TypeImpl<" << klass.Name << ">::TypeImpl(void)" << std::endl + << "{ }" << std::endl << std::endl + << "TypeImpl<" << klass.Name << ">::~TypeImpl(void)" << std::endl + << "{ }" << std::endl << std::endl; /* GetName */ m_Header << "\t" << "virtual String GetName(void) const;" << std::endl; @@ -445,11 +452,11 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&) /* ObjectImpl */ m_Header << "template<>" << std::endl - << "class ObjectImpl<" << klass.Name << ">" - << " : public " << (klass.Parent.empty() ? "Object" : klass.Parent) << std::endl - << "{" << std::endl - << "public:" << std::endl - << "\t" << "DECLARE_PTR_TYPEDEFS(ObjectImpl<" << klass.Name << ">);" << std::endl << std::endl; + << "class ObjectImpl<" << klass.Name << ">" + << " : public " << (klass.Parent.empty() ? "Object" : klass.Parent) << std::endl + << "{" << std::endl + << "public:" << std::endl + << "\t" << "DECLARE_PTR_TYPEDEFS(ObjectImpl<" << klass.Name << ">);" << std::endl << std::endl; /* Validate */ m_Header << "\t" << "virtual void Validate(int types, const ValidationUtils& utils) override;" << std::endl; @@ -541,27 +548,27 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&) m_Impl << "}" << std::endl << std::endl; } - if (!klass.Fields.empty()) { - /* constructor */ - m_Header << "public:" << std::endl - << "\t" << "ObjectImpl<" << klass.Name << ">(void);" << std::endl; + /* constructor */ + m_Header << "public:" << std::endl + << "\t" << "ObjectImpl<" << klass.Name << ">(void);" << std::endl; - m_Impl << "ObjectImpl<" << klass.Name << ">::ObjectImpl(void)" << std::endl - << "{" << std::endl; + m_Impl << "ObjectImpl<" << klass.Name << ">::ObjectImpl(void)" << std::endl + << "{" << std::endl; - for (const Field& field : klass.Fields) { - m_Impl << "\t" << "Set" << field.GetFriendlyName() << "(" << "GetDefault" << field.GetFriendlyName() << "(), true);" << std::endl; - } + for (const Field& field : klass.Fields) { + m_Impl << "\t" << "Set" << field.GetFriendlyName() << "(" << "GetDefault" << field.GetFriendlyName() << "(), true);" << std::endl; + } - m_Impl << "}" << std::endl << std::endl; + m_Impl << "}" << std::endl << std::endl; - /* destructor */ - m_Header << "public:" << std::endl - << "\t" << "~ObjectImpl<" << klass.Name << ">(void);" << std::endl; + /* destructor */ + m_Header << "public:" << std::endl + << "\t" << "~ObjectImpl<" << klass.Name << ">(void);" << std::endl; - m_Impl << "ObjectImpl<" << klass.Name << ">::~ObjectImpl(void)" << std::endl - << "{ }" << std::endl << std::endl; + m_Impl << "ObjectImpl<" << klass.Name << ">::~ObjectImpl(void)" << std::endl + << "{ }" << std::endl << std::endl; + if (!klass.Fields.empty()) { /* SetField */ m_Header << "public:" << std::endl << "\t" << "virtual void SetField(int id, const Value& value, bool suppress_events = false, const Value& cookie = Empty) override;" << std::endl; -- 2.40.0