From e42c69a8d3416be5071637cd4e241593458cb941 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Fri, 23 Dec 2022 14:27:01 +0200 Subject: [PATCH 01/16] Rewrite the Variant class It now uses type erasure and small object optimization --- source/core/variant.h | 192 ++++++++++++++++++++++++++---------------- 1 file changed, 121 insertions(+), 71 deletions(-) diff --git a/source/core/variant.h b/source/core/variant.h index eaf5a34..04c372b 100644 --- a/source/core/variant.h +++ b/source/core/variant.h @@ -17,109 +17,159 @@ public: class Variant { -private: - struct StoreBase - { - virtual ~StoreBase() { } +public: + static constexpr unsigned INTERNAL_SIZE = 2*sizeof(void *); - virtual const std::type_info &type_id() const = 0; - virtual StoreBase *clone() const = 0; - virtual bool type_equals(const StoreBase &) const = 0; - virtual bool value_equals(const StoreBase &) const = 0; + struct Functions + { + const std::type_info &(*get_type)(); + bool (*compare)(const char *, const char *); + void (*clone)(char *, const char *); + void (*destroy)(char *); }; +private: + const Functions *funcs = nullptr; + alignas(void *) char storage[INTERNAL_SIZE]; + +public: + Variant() = default; template - struct Store: public StoreBase - { - T data; + Variant(const T &v) { assign(v); } + Variant(const Variant &v) { copy_from(v); } + ~Variant() { if(funcs) funcs->destroy(storage); } - Store(const T &d): data(d) { } + template + Variant &operator=(const T &v) { assign(v); return *this; } - const std::type_info &type_id() const override { return typeid(T); } - StoreBase *clone() const override { return new Store(data); } - bool type_equals(const StoreBase &s) const override { return dynamic_cast *>(&s); } - bool value_equals(const StoreBase &s) const override { return _value_equals(s); } + Variant &operator=(const Variant &v) { if(&v!=this) copy_from(v); return *this; } - template - typename std::enable_if::value, bool>::type _value_equals(const StoreBase &s) const - { const Store *t = dynamic_cast *>(&s); return (t && t->data==data); } +private: + template + void assign(const T &); - template - typename std::enable_if::value, bool>::type _value_equals(const StoreBase &) const - { return false; } - }; + void copy_from(const Variant &); - StoreBase *store = nullptr; + template + T &get(); public: - Variant() = default; template - Variant(const T &v): store(new Store::type>(v)) { } - Variant(const Variant &v): store(v.store ? v.store->clone() : nullptr) { } - ~Variant() { delete store; } + T &value() { return get(); } template - Variant &operator=(const T &v) - { - delete store; - store = new Store::type>(v); - return *this; - } + const T &value() const { return const_cast(this)->get(); } - Variant &operator=(const Variant &v) - { - if(&v==this) - return *this; + template + bool check_type() const { return funcs==get_functions::type>(); } - delete store; - store = (v.store ? v.store->clone() : nullptr); - return *this; - } + bool check_same_type(const Variant &v) const { return (funcs && funcs==v.funcs); } + + bool operator==(const Variant &v) const { return (has_same_type(v) && funcs->compare(storage, v.storage)); } + bool operator!=(const Variant &v) const { return !(operator==(v)); } + + template + operator T() const { return value(); } private: template - Store::type> *get_typed_store() const - { - typedef typename std::remove_cv::type NCT; - Store *s = dynamic_cast *>(store); - if(!s) - throw type_mismatch(typeid(T), (store ? store->type_id() : typeid(void))); - return s; - } + static constexpr bool is_small() { return (sizeof(T)<=INTERNAL_SIZE && alignof(T)<=alignof(void *)); } + + template + using EnableSmall = typename std::enable_if(), U>::type; + + template + using EnableLarge = typename std::enable_if(), U>::type; -public: template - T &value() - { - return get_typed_store()->data; - } + static const Functions *get_functions(); template - const T &value() const - { - return get_typed_store()->data; - } + static const std::type_info &get_type() { return typeid(T); } template - bool check_type() const - { - return dynamic_cast::type> *>(store); - } + static EnableSmall create(char *s, const T &v) + { new(s) T(v); } - bool check_same_type(const Variant &v) const - { return store && v.store && store->type_equals(*v.store); } + template + static EnableLarge create(char *s, const T &v) + { *reinterpret_cast(s) = new T(v); } - bool operator==(const Variant &v) const - { return store && v.store && store->value_equals(*v.store); } + template + static typename std::enable_if::value, bool>::type compare(const char *, const char *) + { return false; } - bool operator!=(const Variant &v) const - { return !(operator==(v)); } + template + static typename std::enable_if::value, EnableSmall>::type compare(const char *s1, const char *s2) + { return *reinterpret_cast(s1)==*reinterpret_cast(s2); } template - operator T() const - { return value(); } + static typename std::enable_if::value, EnableLarge>::type compare(const char *s1, const char *s2) + { return **reinterpret_cast(s1)==**reinterpret_cast(s2); } + + template + static EnableSmall clone(char *s, const char *v) + { new(s) T(*reinterpret_cast(v)); } + + template + static EnableLarge clone(char *s, const char *v) + { *reinterpret_cast(s) = new T(**reinterpret_cast(v)); } + + template + static EnableSmall destroy(char *s) + { reinterpret_cast(s)->~T(); } + + template + static EnableLarge destroy(char *s) + { delete *reinterpret_cast(s); } }; + +template +inline void Variant::assign(const T &value) +{ + if(funcs) + funcs->destroy(storage); + + funcs = get_functions::type>(); + create(storage, value); +} + +inline void Variant::copy_from(const Variant &v) +{ + if(funcs) + funcs->destroy(storage); + + funcs = v.funcs; + if(funcs) + funcs->clone(storage, v.storage); +} + +template +inline T &Variant::get() +{ + if(!has_type()) + throw type_mismatch(typeid(T), (funcs ? funcs->get_type() : typeid(void))); + + if(sizeof(T)<=INTERNAL_SIZE) + return *reinterpret_cast(storage); + else + return **reinterpret_cast(storage); +} + +template +inline const Variant::Functions *Variant::get_functions() +{ + static Functions funcs = + { + &get_type, + &compare, + &clone, + &destroy + }; + return &funcs; +} + } // namespace Msp #endif -- 2.43.0 From db3397e3b7b9839714ce28d9df2a8f226f2e58b2 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Fri, 23 Dec 2022 14:27:44 +0200 Subject: [PATCH 02/16] Rename Variant's check_type function to has_type --- source/core/variant.h | 9 +++++++-- tests/variant.cpp | 10 +++++----- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/source/core/variant.h b/source/core/variant.h index 04c372b..934a9e5 100644 --- a/source/core/variant.h +++ b/source/core/variant.h @@ -61,9 +61,14 @@ public: const T &value() const { return const_cast(this)->get(); } template - bool check_type() const { return funcs==get_functions::type>(); } + bool has_type() const { return funcs==get_functions::type>(); } - bool check_same_type(const Variant &v) const { return (funcs && funcs==v.funcs); } + bool has_same_type(const Variant &v) const { return (funcs && funcs==v.funcs); } + + template + DEPRECATED bool check_type() const { return has_type(); } + + DEPRECATED bool check_same_type(const Variant &v) const { return has_same_type(v); } bool operator==(const Variant &v) const { return (has_same_type(v) && funcs->compare(storage, v.storage)); } bool operator!=(const Variant &v) const { return !(operator==(v)); } diff --git a/tests/variant.cpp b/tests/variant.cpp index 99cacdf..8ec8972 100644 --- a/tests/variant.cpp +++ b/tests/variant.cpp @@ -99,11 +99,11 @@ void VariantTests::destruction() void VariantTests::types() { Variant var = 42U; - EXPECT(!var.check_type()); - EXPECT(var.check_type()); - EXPECT(!var.check_type()); - EXPECT(!var.check_type()); - EXPECT(!var.check_type()); + EXPECT(!var.has_type()); + EXPECT(var.has_type()); + EXPECT(!var.has_type()); + EXPECT(!var.has_type()); + EXPECT(!var.has_type()); } void VariantTests::mismatch() -- 2.43.0 From dbb2e02721b6250a434a807d92126c7716c40a15 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Tue, 27 Dec 2022 17:32:24 +0200 Subject: [PATCH 03/16] Fix an issue with normalizing paths of the form /foo/.. The separator indicating the root directory was being incorrectly removed, resulting in a path denoting the current directory. --- source/fs/path.cpp | 14 ++++++++++++-- tests/path.cpp | 2 ++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/source/fs/path.cpp b/source/fs/path.cpp index 0e86600..1181b92 100644 --- a/source/fs/path.cpp +++ b/source/fs/path.cpp @@ -133,11 +133,21 @@ void Path::add_component(const string &comp) path += DIRSEP; path += comp; } - else if(separators.empty()) + else if(start==0) + { + /* Removing the last component of a relative path results in the + current directory */ path = "."; + } + else if(start==1) + { + /* Removing the last component of an absolute path results in the + root directory */ + path.erase(start, string::npos); + } else { - // Otherwise, erase the last component + // Otherwise, erase the last component and its separator path.erase(separators.back(), string::npos); separators.pop_back(); } diff --git a/tests/path.cpp b/tests/path.cpp index fbb5ff5..d52630a 100644 --- a/tests/path.cpp +++ b/tests/path.cpp @@ -52,6 +52,8 @@ void PathTests::normalization() EXPECT_EQUAL(path.str(), "./foo"); path = "foo/.."; EXPECT_EQUAL(path.str(), "."); + path = "/foo/.."; + EXPECT_EQUAL(path.str(), "/"); path = "//foo"; EXPECT_EQUAL(path.str(), "/foo"); path = "/.."; -- 2.43.0 From 22c9118827a07fbbe12af916d25ee03dd0b3c9bd Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Tue, 27 Dec 2022 18:18:08 +0200 Subject: [PATCH 04/16] Add missing override specifiers --- source/io/buffered.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/io/buffered.h b/source/io/buffered.h index f078ea1..07b5d37 100644 --- a/source/io/buffered.h +++ b/source/io/buffered.h @@ -32,8 +32,8 @@ protected: public: std::size_t put(char) override; - bool getline(std::string &); - int get(); + bool getline(std::string &) override; + int get() override; const Handle &get_handle(Mode) override; -- 2.43.0 From e272f71f368f3f33643c7e935110dd92cc9d4d3a Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Wed, 28 Dec 2022 15:00:57 +0200 Subject: [PATCH 05/16] Fix a shadowed variable warning --- source/core/variant.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/core/variant.h b/source/core/variant.h index 934a9e5..60501f3 100644 --- a/source/core/variant.h +++ b/source/core/variant.h @@ -131,13 +131,13 @@ private: template -inline void Variant::assign(const T &value) +inline void Variant::assign(const T &v) { if(funcs) funcs->destroy(storage); funcs = get_functions::type>(); - create(storage, value); + create(storage, v); } inline void Variant::copy_from(const Variant &v) -- 2.43.0 From 672dd8d4178716824bf21a76685d91fc82a0a4af Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sun, 1 Jan 2023 22:20:39 +0200 Subject: [PATCH 06/16] Make lexical conversions from and to long long available everywhere The type became part of the C++ standard in C++11, so there's no longer need to guard it with __GNUC__. --- source/strings/lexicalcast.cpp | 4 ---- source/strings/lexicalcast.h | 4 ---- 2 files changed, 8 deletions(-) diff --git a/source/strings/lexicalcast.cpp b/source/strings/lexicalcast.cpp index 2b84d9b..5e9159c 100644 --- a/source/strings/lexicalcast.cpp +++ b/source/strings/lexicalcast.cpp @@ -530,13 +530,11 @@ void operator<<(LexicalConverter &c, unsigned v) void operator<<(LexicalConverter &c, unsigned long v) { c.result(int_to_str(v, c.get_fmt())); } -#ifdef __GNUC__ void operator<<(LexicalConverter &c, long long v) { c.result(int_to_str(v, c.get_fmt())); } void operator<<(LexicalConverter &c, unsigned long long v) { c.result(int_to_str(v, c.get_fmt())); } -#endif void operator<<(LexicalConverter &c, bool v) { c.result(bool_to_str(v, c.get_fmt())); } @@ -601,13 +599,11 @@ void operator>>(const LexicalConverter &c, unsigned int &v) void operator>>(const LexicalConverter &c, unsigned long &v) { v = str_to_int(c.get(), c.get_fmt()); } -#ifdef __GNUC__ void operator>>(const LexicalConverter &c, long long &v) { v = str_to_int(c.get(), c.get_fmt()); } void operator>>(const LexicalConverter &c, unsigned long long &v) { v = str_to_int(c.get(), c.get_fmt()); } -#endif void operator>>(const LexicalConverter &c, bool &v) { v = str_to_bool(c.get()); } diff --git a/source/strings/lexicalcast.h b/source/strings/lexicalcast.h index 9aecd32..12b5d08 100644 --- a/source/strings/lexicalcast.h +++ b/source/strings/lexicalcast.h @@ -58,10 +58,8 @@ void operator<<(LexicalConverter &, unsigned char); void operator<<(LexicalConverter &, unsigned short); void operator<<(LexicalConverter &, unsigned); void operator<<(LexicalConverter &, unsigned long); -#ifdef __GNUC__ void operator<<(LexicalConverter &, long long); void operator<<(LexicalConverter &, unsigned long long); -#endif void operator<<(LexicalConverter &, bool); void operator<<(LexicalConverter &, float); void operator<<(LexicalConverter &, double); @@ -79,10 +77,8 @@ void operator>>(const LexicalConverter &, unsigned char &); void operator>>(const LexicalConverter &, unsigned short &); void operator>>(const LexicalConverter &, unsigned int &); void operator>>(const LexicalConverter &, unsigned long &); -#ifdef __GNUC__ void operator>>(const LexicalConverter &, long long &); void operator>>(const LexicalConverter &, unsigned long long &); -#endif void operator>>(const LexicalConverter &, bool &); void operator>>(const LexicalConverter &, float &); void operator>>(const LexicalConverter &, double &); -- 2.43.0 From 5d51c374869f13f762039f58c03f3c5d75c12f07 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Mon, 2 Jan 2023 23:38:27 +0200 Subject: [PATCH 07/16] Fallback to comparing typeid in Variant if funcs are not the same On Windows it looks like instantiations of a function template in different modules may have different addresses of its static locals. --- source/core/variant.h | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/source/core/variant.h b/source/core/variant.h index 60501f3..5de5a72 100644 --- a/source/core/variant.h +++ b/source/core/variant.h @@ -61,9 +61,9 @@ public: const T &value() const { return const_cast(this)->get(); } template - bool has_type() const { return funcs==get_functions::type>(); } + bool has_type() const { return type_equals(funcs, get_functions::type>()); } - bool has_same_type(const Variant &v) const { return (funcs && funcs==v.funcs); } + bool has_same_type(const Variant &v) const { return type_equals(funcs, v.funcs); } template DEPRECATED bool check_type() const { return has_type(); } @@ -77,6 +77,8 @@ public: operator T() const { return value(); } private: + static bool type_equals(const Functions *, const Functions *); + template static constexpr bool is_small() { return (sizeof(T)<=INTERNAL_SIZE && alignof(T)<=alignof(void *)); } @@ -162,6 +164,16 @@ inline T &Variant::get() return **reinterpret_cast(storage); } +inline bool Variant::type_equals(const Functions *funcs1, const Functions *funcs2) +{ + if(!funcs1 || !funcs2) + return false; + else if(funcs1==funcs2) + return true; + else + return funcs1->get_type()==funcs2->get_type(); +} + template inline const Variant::Functions *Variant::get_functions() { -- 2.43.0 From 5d3a5019399f97af0371f4fd6dc415d36de6ac3a Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Tue, 3 Jan 2023 02:23:57 +0200 Subject: [PATCH 08/16] Add decorations for things which are considered part of the API --- source/core/android/main.cpp | 3 +- source/core/application.h | 5 ++- source/core/environ.h | 7 +-- source/core/except.h | 9 ++-- source/core/getopt.h | 9 ++-- source/core/maputils.h | 3 +- source/core/module.h | 3 +- source/core/mspcore_api.h | 18 ++++++++ source/core/mutex.h | 5 ++- source/core/noncopyable.h | 4 +- source/core/osx/main.cpp | 3 +- source/core/process.h | 3 +- source/core/semaphore.h | 3 +- source/core/systemerror.h | 3 +- source/core/thread.h | 3 +- source/core/unix/main.cpp | 3 +- source/core/variant.h | 5 ++- source/core/windows/main.cpp | 3 +- source/debug/backtrace.h | 7 +-- source/debug/debugapi.h | 6 ++- source/debug/demangle.h | 3 +- source/debug/errorreporter.h | 3 +- source/debug/exceptiontrace.h | 6 ++- source/debug/profiler.h | 7 +-- source/debug/profilingscope.h | 3 +- source/fs/dir.h | 33 +++++++------- source/fs/filemonitor.h | 3 +- source/fs/path.h | 5 ++- source/fs/redirectedpath.h | 3 +- source/fs/stat.h | 5 ++- source/fs/utils.h | 25 ++++++----- source/io/asset.h | 3 +- source/io/base.h | 3 +- source/io/buffered.h | 3 +- source/io/console.h | 9 ++-- source/io/eventdispatcher.h | 3 +- source/io/eventobject.h | 3 +- source/io/file.h | 9 ++-- source/io/handle.h | 3 +- source/io/memory.h | 3 +- source/io/mode.h | 3 +- source/io/pipe.h | 3 +- source/io/poll.h | 7 +-- source/io/seekable.h | 5 ++- source/io/serial.h | 3 +- source/io/slice.h | 3 +- source/io/utils.h | 3 +- source/io/zlibcompressed.h | 5 ++- source/stringcodec/ascii.h | 7 +-- source/stringcodec/codec.h | 11 ++--- source/stringcodec/codecutils.h | 4 +- source/stringcodec/except.h | 7 +-- source/stringcodec/iso2022jp.h | 7 +-- source/stringcodec/iso646fi.h | 7 +-- source/stringcodec/iso88591.h | 7 +-- source/stringcodec/iso885915.h | 7 +-- source/stringcodec/jisx0201.h | 7 +-- source/stringcodec/jisx0208.h | 11 ++--- source/stringcodec/utf16.h | 7 +-- source/stringcodec/utf8.h | 7 +-- source/stringcodec/windows1252.h | 7 +-- source/strings/fmt.h | 5 ++- source/strings/format.h | 3 +- source/strings/glob.h | 5 ++- source/strings/lexicalcast.h | 77 ++++++++++++++++---------------- source/strings/regex.h | 5 ++- source/strings/regmatch.h | 3 +- source/strings/utils.h | 33 +++++++------- source/time/datetime.h | 3 +- source/time/timedelta.h | 21 ++++----- source/time/timer.h | 3 +- source/time/timestamp.h | 3 +- source/time/timezone.h | 3 +- source/time/utils.h | 9 ++-- 74 files changed, 318 insertions(+), 223 deletions(-) create mode 100644 source/core/mspcore_api.h diff --git a/source/core/android/main.cpp b/source/core/android/main.cpp index ff811c1..d6ad415 100644 --- a/source/core/android/main.cpp +++ b/source/core/android/main.cpp @@ -1,6 +1,7 @@ #include "mainthread.h" +#include "mspcore_api.h" -extern "C" void ANativeActivity_onCreate(ANativeActivity *activity, void * /*saved_state*/, size_t /*state_size*/) +extern "C" MSPCORE_API void ANativeActivity_onCreate(ANativeActivity *activity, void * /*saved_state*/, size_t /*state_size*/) { static Msp::Android::MainThread *thread = nullptr; if(thread) diff --git a/source/core/application.h b/source/core/application.h index 972f3b7..2a1cc05 100644 --- a/source/core/application.h +++ b/source/core/application.h @@ -3,6 +3,7 @@ #include #include +#include "mspcore_api.h" #include "noncopyable.h" namespace Msp { @@ -10,10 +11,10 @@ namespace Msp { /** Base class for applications. See also RegisteredApplication. */ -class Application: private NonCopyable +class MSPCORE_API Application: private NonCopyable { protected: - class Starter + class MSPCORE_API Starter { protected: Starter(); diff --git a/source/core/environ.h b/source/core/environ.h index 67fde05..7fbca16 100644 --- a/source/core/environ.h +++ b/source/core/environ.h @@ -2,12 +2,13 @@ #define ENVIRON_H_ #include +#include "mspcore_api.h" namespace Msp { -std::string getenv(const std::string &); -void setenv(const std::string &, const std::string &); -void unsetenv(const std::string &); +MSPCORE_API std::string getenv(const std::string &); +MSPCORE_API void setenv(const std::string &, const std::string &); +MSPCORE_API void unsetenv(const std::string &); } // namespace Msp diff --git a/source/core/except.h b/source/core/except.h index 65d9ef9..1673ff4 100644 --- a/source/core/except.h +++ b/source/core/except.h @@ -2,31 +2,32 @@ #define MSP_CORE_EXCEPT_H_ #include +#include "mspcore_api.h" namespace Msp { -class invalid_state: public std::logic_error +class MSPCORE_API invalid_state: public std::logic_error { public: invalid_state(const std::string &w): logic_error(w) { } }; -class already_called: public invalid_state +class MSPCORE_API already_called: public invalid_state { public: already_called(const std::string &w): invalid_state(w) { } }; -class unsupported: public std::logic_error +class MSPCORE_API unsupported: public std::logic_error { public: unsupported(const std::string &w): logic_error(w) { } }; -class internal_error: public std::logic_error +class MSPCORE_API internal_error: public std::logic_error { public: internal_error(const std::string &w): logic_error(w) { } diff --git a/source/core/getopt.h b/source/core/getopt.h index cdf5ee3..59c810c 100644 --- a/source/core/getopt.h +++ b/source/core/getopt.h @@ -6,11 +6,12 @@ #include #include #include +#include "mspcore_api.h" #include "noncopyable.h" namespace Msp { -class usage_error: public std::runtime_error +class MSPCORE_API usage_error: public std::runtime_error { private: std::string m_help; @@ -58,7 +59,7 @@ A built-in --help option is provided and will output a list of options, arguments and their associated help texts. An application may override this by providing its own option with the same name. */ -class GetOpt: private NonCopyable +class MSPCORE_API GetOpt: private NonCopyable { public: enum ArgType @@ -68,7 +69,7 @@ public: REQUIRED_ARG }; - class Option + class MSPCORE_API Option { protected: Option() = default; @@ -88,7 +89,7 @@ public: virtual unsigned get_seen_count() const = 0; }; - class Argument + class MSPCORE_API Argument { protected: Argument() = default; diff --git a/source/core/maputils.h b/source/core/maputils.h index 26b72cc..9a72d4d 100644 --- a/source/core/maputils.h +++ b/source/core/maputils.h @@ -4,6 +4,7 @@ #include #include #include +#include "mspcore_api.h" namespace Msp { @@ -39,7 +40,7 @@ static std::string stringify_key(const T &k) } // namespace Internal -class key_error: public std::runtime_error +class MSPCORE_API key_error: public std::runtime_error { public: template diff --git a/source/core/module.h b/source/core/module.h index 4b1e3e8..64d761f 100644 --- a/source/core/module.h +++ b/source/core/module.h @@ -2,11 +2,12 @@ #define MSP_CORE_MODULE_H_ #include +#include "mspcore_api.h" #include "noncopyable.h" namespace Msp { -class Module: private NonCopyable +class MSPCORE_API Module: private NonCopyable { private: struct Private; diff --git a/source/core/mspcore_api.h b/source/core/mspcore_api.h new file mode 100644 index 0000000..eed6bcc --- /dev/null +++ b/source/core/mspcore_api.h @@ -0,0 +1,18 @@ +#ifndef MSP_CORE_API_H_ +#define MSP_CORE_API_H_ + +#if defined(_WIN32) +#if defined(MSPCORE_BUILD) +#define MSPCORE_API __declspec(dllexport) +#elif defined(MSPCORE_IMPORT) +#define MSPCORE_API __declspec(dllimport) +#else +#define MSPCORE_API +#endif +#elif defined(__GNUC__) +#define MSPCORE_API __attribute__((visibility("default"))) +#else +#define MSPCORE_API +#endif + +#endif diff --git a/source/core/mutex.h b/source/core/mutex.h index 6582074..a48f58c 100644 --- a/source/core/mutex.h +++ b/source/core/mutex.h @@ -1,6 +1,7 @@ #ifndef MSP_CORE_MUTEX_H_ #define MSP_CORE_MUTEX_H_ +#include "mspcore_api.h" #include "noncopyable.h" #include "refptr.h" @@ -10,7 +11,7 @@ namespace Msp { A class for controlling mutually exclusive access to a resource. Only one thread can hold a lock on the mutex at a time. */ -class Mutex: private NonCopyable +class MSPCORE_API Mutex: private NonCopyable { friend class Semaphore; @@ -38,7 +39,7 @@ public: /** Locks the mutex for the lifetime of the object. */ -class MutexLock +class MSPCORE_API MutexLock { private: Mutex &mutex; diff --git a/source/core/noncopyable.h b/source/core/noncopyable.h index c948c57..78f9e66 100644 --- a/source/core/noncopyable.h +++ b/source/core/noncopyable.h @@ -1,9 +1,11 @@ #ifndef MSP_CORE_NONCOPYABLE_H_ #define MSP_CORE_NONCOPYABLE_H_ +#include "mspcore_api.h" + namespace Msp { -class NonCopyable +class MSPCORE_API NonCopyable { protected: NonCopyable() = default; diff --git a/source/core/osx/main.cpp b/source/core/osx/main.cpp index 4bb81c8..55d4a30 100644 --- a/source/core/osx/main.cpp +++ b/source/core/osx/main.cpp @@ -1,7 +1,8 @@ #include #include "application.h" +#include "mspcore_api.h" -int main(int argc, char **argv) +MSPCORE_API int main(int argc, char **argv) { void *data = nullptr; diff --git a/source/core/process.h b/source/core/process.h index 0d7faa6..ed997f8 100644 --- a/source/core/process.h +++ b/source/core/process.h @@ -5,6 +5,7 @@ #include #include #include +#include "mspcore_api.h" #include "noncopyable.h" namespace Msp { @@ -22,7 +23,7 @@ the process or capture its output, use an IO::Pipe. Redirections performed on the self object take effect immediately. It is recommended to perform such redirections directly on the Console objects. */ -class Process: private NonCopyable +class MSPCORE_API Process: private NonCopyable { public: typedef std::vector Arguments; diff --git a/source/core/semaphore.h b/source/core/semaphore.h index 28c3b3d..f504289 100644 --- a/source/core/semaphore.h +++ b/source/core/semaphore.h @@ -2,11 +2,12 @@ #define MSP_CORE_SEMAPHORE_H_ #include +#include "mspcore_api.h" #include "noncopyable.h" namespace Msp { -class Semaphore: private NonCopyable +class MSPCORE_API Semaphore: private NonCopyable { private: struct Private; diff --git a/source/core/systemerror.h b/source/core/systemerror.h index 5edbe9d..cce3c5c 100644 --- a/source/core/systemerror.h +++ b/source/core/systemerror.h @@ -3,10 +3,11 @@ #include #include +#include "mspcore_api.h" namespace Msp { -class system_error: public std::runtime_error +class MSPCORE_API system_error: public std::runtime_error { private: int m_code; diff --git a/source/core/thread.h b/source/core/thread.h index ef071cd..71acb22 100644 --- a/source/core/thread.h +++ b/source/core/thread.h @@ -2,6 +2,7 @@ #define MSP_CORE_THREAD_H_ #include +#include "mspcore_api.h" #include "noncopyable.h" namespace Msp { @@ -13,7 +14,7 @@ automatically started upon creation - you must manually call launch() instead. This is to allow initializing variables of the derived class before the thread is started. */ -class Thread: private NonCopyable +class MSPCORE_API Thread: private NonCopyable { private: struct Private; diff --git a/source/core/unix/main.cpp b/source/core/unix/main.cpp index 58c9fda..010459f 100644 --- a/source/core/unix/main.cpp +++ b/source/core/unix/main.cpp @@ -1,6 +1,7 @@ #include "application.h" +#include "mspcore_api.h" -int main(int argc, char **argv) +MSPCORE_API int main(int argc, char **argv) { return Msp::Application::run(argc, argv, nullptr); } diff --git a/source/core/variant.h b/source/core/variant.h index 5de5a72..c0b0aeb 100644 --- a/source/core/variant.h +++ b/source/core/variant.h @@ -5,17 +5,18 @@ #include #include #include "meta.h" +#include "mspcore_api.h" namespace Msp { -class type_mismatch: public std::runtime_error +class MSPCORE_API type_mismatch: public std::runtime_error { public: type_mismatch(const std::type_info &, const std::type_info &); }; -class Variant +class MSPCORE_API Variant { public: static constexpr unsigned INTERNAL_SIZE = 2*sizeof(void *); diff --git a/source/core/windows/main.cpp b/source/core/windows/main.cpp index 11df925..11da64b 100644 --- a/source/core/windows/main.cpp +++ b/source/core/windows/main.cpp @@ -2,11 +2,12 @@ #include #include #include "application.h" +#include "mspcore_api.h" using namespace std; using namespace Msp; -int main(int argc, char **argv) +MSPCORE_API int main(int argc, char **argv) { return Msp::Application::run(argc, argv); } diff --git a/source/debug/backtrace.h b/source/debug/backtrace.h index 98aa4d8..b8e06af 100644 --- a/source/debug/backtrace.h +++ b/source/debug/backtrace.h @@ -4,11 +4,12 @@ #include #include #include +#include namespace Msp { namespace Debug { -class Backtrace +class MSPCORE_API Backtrace { public: struct StackFrame @@ -27,8 +28,8 @@ public: static Backtrace create(); }; -std::ostream &operator<<(std::ostream &, const Backtrace &); -std::ostream &operator<<(std::ostream &, const Backtrace::StackFrame &); +MSPCORE_API std::ostream &operator<<(std::ostream &, const Backtrace &); +MSPCORE_API std::ostream &operator<<(std::ostream &, const Backtrace::StackFrame &); } // namespace Debug } // namespace Msp diff --git a/source/debug/debugapi.h b/source/debug/debugapi.h index 80dcc4c..0f1a501 100644 --- a/source/debug/debugapi.h +++ b/source/debug/debugapi.h @@ -1,6 +1,8 @@ #ifndef MSP_DEBUG_DEBUGAPI_H_ #define MSP_DEBUG_DEBUGAPI_H_ +#include + namespace Msp { namespace Debug { @@ -11,8 +13,8 @@ enum DebuggerType UNKNOWN, }; -DebuggerType check_debugger(bool = false); -void debug_break(); +MSPCORE_API DebuggerType check_debugger(bool = false); +MSPCORE_API void debug_break(); } // namespace Debug } // namespace Msp diff --git a/source/debug/demangle.h b/source/debug/demangle.h index 213a348..2233435 100644 --- a/source/debug/demangle.h +++ b/source/debug/demangle.h @@ -2,11 +2,12 @@ #define MSP_DEBUG_DEMANGLE_H_ #include +#include namespace Msp { namespace Debug { -std::string demangle(const std::string &); +MSPCORE_API std::string demangle(const std::string &); } // namespace Debug } // namespace Msp diff --git a/source/debug/errorreporter.h b/source/debug/errorreporter.h index 9a60f85..ce14c63 100644 --- a/source/debug/errorreporter.h +++ b/source/debug/errorreporter.h @@ -2,12 +2,13 @@ #define MSP_DEBUG_ERRORREPORTER_H_ #include +#include #include namespace Msp { namespace Debug { -class ErrorReporter: private NonCopyable +class MSPCORE_API ErrorReporter: private NonCopyable { private: ErrorReporter *_prev = nullptr; diff --git a/source/debug/exceptiontrace.h b/source/debug/exceptiontrace.h index 52664b6..0786c78 100644 --- a/source/debug/exceptiontrace.h +++ b/source/debug/exceptiontrace.h @@ -1,13 +1,15 @@ #ifndef MSP_DEBUG_EXCEPTIONTRACE_H_ #define MSP_DEBUG_EXCEPTIONTRACE_H_ +#include + namespace Msp { namespace Debug { class Backtrace; -void enable_exception_trace(bool); -const Backtrace &get_exception_trace(); +MSPCORE_API void enable_exception_trace(bool); +MSPCORE_API const Backtrace &get_exception_trace(); } // namespace Debug } // namespace Msp diff --git a/source/debug/profiler.h b/source/debug/profiler.h index 22d2c9a..7d98dc7 100644 --- a/source/debug/profiler.h +++ b/source/debug/profiler.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -25,16 +26,16 @@ profiled. Note: This is not thread-safe. To profile multiple threads, create a separate Profiler for each thread. */ -class Profiler: private NonCopyable +class MSPCORE_API Profiler: private NonCopyable { public: - struct CallInfo + struct MSPCORE_API CallInfo { Msp::Time::TimeStamp entry_time; Msp::Time::TimeDelta duration; }; - struct ScopeInfo + struct MSPCORE_API ScopeInfo { Time::TimeStamp first_call; unsigned calls = 0; diff --git a/source/debug/profilingscope.h b/source/debug/profilingscope.h index 586efa3..7b8bcf3 100644 --- a/source/debug/profilingscope.h +++ b/source/debug/profilingscope.h @@ -1,6 +1,7 @@ #ifndef MSP_DEBUG_PROFILINGSCOPE_H_ #define MSP_DEBUG_PROFILINGSCOPE_H_ +#include #include #include #include "profiler.h" @@ -13,7 +14,7 @@ RAII timing class to accompany Profiler. Timing starts when an object is created and ends when it goes out of scope. If there was another object in an outer scope, it is notified of the time used in inner scopes. */ -class ProfilingScope: private NonCopyable +class MSPCORE_API ProfilingScope: private NonCopyable { private: Profiler &profiler; diff --git a/source/fs/dir.h b/source/fs/dir.h index bef89c6..960be2e 100644 --- a/source/fs/dir.h +++ b/source/fs/dir.h @@ -4,12 +4,13 @@ #include #include #include +#include #include "path.h" namespace Msp { namespace FS { -class not_a_directory: public std::runtime_error +class MSPCORE_API not_a_directory: public std::runtime_error { public: not_a_directory(const Path &); @@ -17,50 +18,50 @@ public: }; /// Creates a directory -void mkdir(const Path &path, int mode); +MSPCORE_API void mkdir(const Path &path, int mode); /// Creates a directory and any required parent directories -void mkpath(const Path &path, int mode); +MSPCORE_API void mkpath(const Path &path, int mode); /// Removes a directory, which must be empty -void rmdir(const Path &path); +MSPCORE_API void rmdir(const Path &path); /// Removes a directory and anything it contains -void rmpath(const Path &path); +MSPCORE_API void rmpath(const Path &path); /// Lists the contents of a directory -std::vector list_files(const Path &path); +MSPCORE_API std::vector list_files(const Path &path); /// Lists the contents of a directory, filtered with a regex -std::vector list_filtered(const Path &path, const std::string &filter); +MSPCORE_API std::vector list_filtered(const Path &path, const std::string &filter); /// Returns the current working directory -Path getcwd(); +MSPCORE_API Path getcwd(); /// Changes the current working directory -void chdir(const Path &); +MSPCORE_API void chdir(const Path &); /// Returns the user's home directory -Path get_home_dir(); +MSPCORE_API Path get_home_dir(); /// Returns a directory suitable for storing user-specific data. -Path get_user_data_dir(); +MSPCORE_API Path get_user_data_dir(); /// Returns a directory containing system-wide configuration. -Path get_sys_conf_dir(); +MSPCORE_API Path get_sys_conf_dir(); /// Returns a directory containing immutable system-wide data. -Path get_sys_data_dir(); +MSPCORE_API Path get_sys_data_dir(); /// Returns a directory containing system-wide architecture-specific files. -Path get_sys_lib_dir(); +MSPCORE_API Path get_sys_lib_dir(); /** Looks for a file in a list of paths. Returns the absolute path to the first existing location, or an empty Path if the file is not found at all. */ -Path path_lookup(const std::string &, const std::vector &); +MSPCORE_API Path path_lookup(const std::string &, const std::vector &); /** Looks for a file using the PATH environment variable. */ -Path path_lookup(const std::string &); +MSPCORE_API Path path_lookup(const std::string &); } // namespace FS } // namespace Msp diff --git a/source/fs/filemonitor.h b/source/fs/filemonitor.h index 220b969..3ce5d79 100644 --- a/source/fs/filemonitor.h +++ b/source/fs/filemonitor.h @@ -1,6 +1,7 @@ #ifndef FILEMONITOR_H_ #define FILEMONITOR_H_ +#include #include #include #include @@ -8,7 +9,7 @@ namespace Msp { namespace FS { -class FileMonitor: NonCopyable +class MSPCORE_API FileMonitor: NonCopyable { private: struct Private; diff --git a/source/fs/path.h b/source/fs/path.h index 30fe683..1b15047 100644 --- a/source/fs/path.h +++ b/source/fs/path.h @@ -4,6 +4,7 @@ #include #include #include +#include namespace Msp { namespace FS { @@ -28,13 +29,13 @@ A path can also be treated as an array of components, supporting indexing, iteration and slicing. In this context the root directory is treated as a component of its own. */ -class Path +class MSPCORE_API Path { private: typedef std::vector PositionArray; public: - class Iterator + class MSPCORE_API Iterator { public: typedef PositionArray::difference_type difference_type; diff --git a/source/fs/redirectedpath.h b/source/fs/redirectedpath.h index 50a3609..95888f7 100644 --- a/source/fs/redirectedpath.h +++ b/source/fs/redirectedpath.h @@ -1,6 +1,7 @@ #ifndef MSP_FS_REDIRECTEDPATH_H_ #define MSP_FS_REDIRECTEDPATH_H_ +#include #include "path.h" namespace Msp { @@ -12,7 +13,7 @@ goes out of scope, it is renamed to the original path. If destruction happens due to an exception, it is unlinked instead. The primary use for this is to atomically overwrite a file with a new version. */ -class RedirectedPath: public Path +class MSPCORE_API RedirectedPath: public Path { private: Path original; diff --git a/source/fs/stat.h b/source/fs/stat.h index c32e879..fd6a2f7 100644 --- a/source/fs/stat.h +++ b/source/fs/stat.h @@ -3,6 +3,7 @@ #include #include +#include #include #include "path.h" @@ -22,7 +23,7 @@ typedef uint64_t FileSize; /** Holds file information. */ -class Stat +class MSPCORE_API Stat { private: struct Private; @@ -73,7 +74,7 @@ inline Stat lstat(const Path &path) { return Stat::lstat(path); } /// Tests for existence of a file -bool exists(const Path &path); +MSPCORE_API bool exists(const Path &path); /// Tests whether a path refers to an existing regular file inline bool is_reg(const Path &path) diff --git a/source/fs/utils.h b/source/fs/utils.h index e518d35..9c4bb5c 100644 --- a/source/fs/utils.h +++ b/source/fs/utils.h @@ -1,50 +1,51 @@ #ifndef MSP_FS_UTILS_H_ #define MSP_FS_UTILS_H_ +#include #include "path.h" namespace Msp { namespace FS { /// Extracts the last component of the path. -std::string basename(const Path &); +MSPCORE_API std::string basename(const Path &); /// Removes the last component from the path. -Path dirname(const Path &); +MSPCORE_API Path dirname(const Path &); /** Returns the base part of a filename. This includes everything up to the last dot, but not the dot itself. */ -std::string basepart(const std::string &); +MSPCORE_API std::string basepart(const std::string &); /** Returns the extension part of a filename. This includes the last dot and everything after it. */ -std::string extpart(const std::string &); +MSPCORE_API std::string extpart(const std::string &); /// Fixes the case of a path to match files / directories on the filesystem. -Path fix_case(const Path &path); +MSPCORE_API Path fix_case(const Path &path); /// Reads the contents of a symbolic link -Path readlink(const Path &path); +MSPCORE_API Path readlink(const Path &path); /// Resolves all symlinks from a path. Will always return an absolute path. -Path realpath(const Path &path); +MSPCORE_API Path realpath(const Path &path); /// Removes a file -void unlink(const Path &path); +MSPCORE_API void unlink(const Path &path); /// Renames a file. Existing file, if any, is overwritten. -void rename(const Path &from, const Path &to); +MSPCORE_API void rename(const Path &from, const Path &to); /** Makes a path relative to some base path. That is, base/result==path. Both paths must be either absolute or relative. */ -Path relative(const Path &path, const Path &base); +MSPCORE_API Path relative(const Path &path, const Path &base); /// Returns the longest prefix shared by both paths. -Path common_ancestor(const Path &, const Path &); +MSPCORE_API Path common_ancestor(const Path &, const Path &); /** Determines how many levels a path is below another. Returns -1 if path is not a descendant of parent. Both paths must be either absolute or relative. */ -int descendant_depth(const Path &path, const Path &parent); +MSPCORE_API int descendant_depth(const Path &path, const Path &parent); } // namespace FS } // namespace Msp diff --git a/source/io/asset.h b/source/io/asset.h index 84c2837..41cf10d 100644 --- a/source/io/asset.h +++ b/source/io/asset.h @@ -1,6 +1,7 @@ #ifndef MSP_IO_ASSET_H_ #define MSP_IO_ASSET_H_ +#include #include "seekable.h" namespace Msp { @@ -11,7 +12,7 @@ Opens a file from the application's assets. On Android, this means the assets contained within the APK. On other platfoms, assets are located in the directory indicated by FS::get_sys_data_dir(). Assets are always read-only. */ -class Asset: public Seekable +class MSPCORE_API Asset: public Seekable { private: struct Private; diff --git a/source/io/base.h b/source/io/base.h index aadc6ac..92c860d 100644 --- a/source/io/base.h +++ b/source/io/base.h @@ -3,6 +3,7 @@ #include #include +#include #include #include #include "handle.h" @@ -15,7 +16,7 @@ namespace IO { /** Common interface for all I/O objects. */ -class Base: private NonCopyable +class MSPCORE_API Base: private NonCopyable { public: /** RAII synchronization primitive. Prevents concurrent access to the diff --git a/source/io/buffered.h b/source/io/buffered.h index 07b5d37..c05fc25 100644 --- a/source/io/buffered.h +++ b/source/io/buffered.h @@ -2,12 +2,13 @@ #define MSP_IO_BUFFERED_H_ #include +#include #include "base.h" namespace Msp { namespace IO { -class Buffered: public Base, public sigc::trackable +class MSPCORE_API Buffered: public Base, public sigc::trackable { private: Base &below; diff --git a/source/io/console.h b/source/io/console.h index ac66288..1755659 100644 --- a/source/io/console.h +++ b/source/io/console.h @@ -1,6 +1,7 @@ #ifndef MSP_IO_CONSOLE_H_ #define MSP_IO_CONSOLE_H_ +#include #include "eventobject.h" #include "handle.h" @@ -12,7 +13,7 @@ Provides access to standard input, output and error streams. This class can't be instantiated directly - use one of the cin, cout and cerr references instead. */ -class Console: public EventObject +class MSPCORE_API Console: public EventObject { public: enum Stream @@ -64,9 +65,9 @@ public: static Console &instance(Stream); }; -extern Console &cin; -extern Console &cout; -extern Console &cerr; +MSPCORE_API extern Console &cin; +MSPCORE_API extern Console &cout; +MSPCORE_API extern Console &cerr; } // namespace IO } // namespace Msp diff --git a/source/io/eventdispatcher.h b/source/io/eventdispatcher.h index d9a7afd..25341bf 100644 --- a/source/io/eventdispatcher.h +++ b/source/io/eventdispatcher.h @@ -3,6 +3,7 @@ #include #include +#include #include #include #include "poll.h" @@ -14,7 +15,7 @@ namespace IO { Put your I/O objects inside one of these to get signaled when something happens on some of them. */ -class EventDispatcher +class MSPCORE_API EventDispatcher { private: struct Slot: public sigc::trackable diff --git a/source/io/eventobject.h b/source/io/eventobject.h index cf987e4..75cfb73 100644 --- a/source/io/eventobject.h +++ b/source/io/eventobject.h @@ -1,6 +1,7 @@ #ifndef MSP_IO_EVENTOBJECT_H_ #define MSP_IO_EVENTOBJECT_H_ +#include #include "base.h" namespace Msp { @@ -13,7 +14,7 @@ Interface class for objects that can provide event-based I/O. These objects can be fed to the various poll functions in poll.h, or added to an EventDispatcher to generate event signals. */ -class EventObject: public Base +class MSPCORE_API EventObject: public Base { public: /** Emitted when there is data available for reading. If all data is not diff --git a/source/io/file.h b/source/io/file.h index 1068131..2af56ae 100644 --- a/source/io/file.h +++ b/source/io/file.h @@ -3,6 +3,7 @@ #include #include +#include #include "buffered.h" #include "handle.h" #include "seekable.h" @@ -10,13 +11,13 @@ namespace Msp { namespace IO { -class file_not_found: public std::runtime_error +class MSPCORE_API file_not_found: public std::runtime_error { public: file_not_found(const std::string &fn): std::runtime_error(fn) { } }; -class file_already_exists: public std::runtime_error +class MSPCORE_API file_already_exists: public std::runtime_error { public: file_already_exists(const std::string &fn): std::runtime_error(fn) { } @@ -28,7 +29,7 @@ A class for reading and writing files. Non-blocking mode is not supported on Win32. */ -class File: public Seekable +class MSPCORE_API File: public Seekable { public: enum CreateMode @@ -80,7 +81,7 @@ inline File::CreateMode operator~(File::CreateMode m) { return File::CreateMode(~static_cast(m)); } -class BufferedFile: public Seekable +class MSPCORE_API BufferedFile: public Seekable { private: File file; diff --git a/source/io/handle.h b/source/io/handle.h index 6140e11..06c2034 100644 --- a/source/io/handle.h +++ b/source/io/handle.h @@ -2,11 +2,12 @@ #define MSP_IO_HANDLE_H_ #include +#include namespace Msp { namespace IO { -class Handle +class MSPCORE_API Handle { public: struct Private; diff --git a/source/io/memory.h b/source/io/memory.h index 75cf7f5..5ae2a34 100644 --- a/source/io/memory.h +++ b/source/io/memory.h @@ -1,12 +1,13 @@ #ifndef MSP_IO_MEMORY_H_ #define MSP_IO_MEMORY_H_ +#include #include "seekable.h" namespace Msp { namespace IO { -class Memory: public Seekable +class MSPCORE_API Memory: public Seekable { private: char *begin = nullptr; diff --git a/source/io/mode.h b/source/io/mode.h index 65b4089..6230a65 100644 --- a/source/io/mode.h +++ b/source/io/mode.h @@ -2,6 +2,7 @@ #define MSP_IO_MODE_H_ #include +#include namespace Msp { namespace IO { @@ -30,7 +31,7 @@ inline void adjust_mode(Mode &m, Mode f, bool b) { m = b ? (m|f) : (m&~f); } -class invalid_access: public std::logic_error +class MSPCORE_API invalid_access: public std::logic_error { public: invalid_access(Mode); diff --git a/source/io/pipe.h b/source/io/pipe.h index df5353a..c62aa36 100644 --- a/source/io/pipe.h +++ b/source/io/pipe.h @@ -1,6 +1,7 @@ #ifndef MSP_IO_PIPE_H_ #define MSP_IO_PIPE_H_ +#include #include "eventobject.h" #include "eventreader.h" #include "handle.h" @@ -8,7 +9,7 @@ namespace Msp { namespace IO { -class Pipe: public EventObject +class MSPCORE_API Pipe: public EventObject { private: Handle read_handle; diff --git a/source/io/poll.h b/source/io/poll.h index 4466ca3..53e3808 100644 --- a/source/io/poll.h +++ b/source/io/poll.h @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -31,7 +32,7 @@ inline PollEvent operator~(PollEvent e) { return PollEvent(~static_cast(e)); } -class Poller: private NonCopyable +class MSPCORE_API Poller: private NonCopyable { public: struct PolledObject @@ -64,8 +65,8 @@ public: const std::vector &get_result() const { return poll_result; } }; -PollEvent poll(EventObject &, PollEvent); -PollEvent poll(EventObject &, PollEvent, const Time::TimeDelta &); +MSPCORE_API PollEvent poll(EventObject &, PollEvent); +MSPCORE_API PollEvent poll(EventObject &, PollEvent, const Time::TimeDelta &); } // namespace IO } // namespace Msp diff --git a/source/io/seekable.h b/source/io/seekable.h index 84a5561..e549d24 100644 --- a/source/io/seekable.h +++ b/source/io/seekable.h @@ -3,6 +3,7 @@ #include #include +#include #include "base.h" namespace Msp { @@ -20,7 +21,7 @@ enum SeekType }; -class bad_seek: public std::runtime_error +class MSPCORE_API bad_seek: public std::runtime_error { public: bad_seek(SeekOffset, SeekType); @@ -28,7 +29,7 @@ public: }; -class Seekable: public Base +class MSPCORE_API Seekable: public Base { protected: Seekable() = default; diff --git a/source/io/serial.h b/source/io/serial.h index a07cd1f..b83f1e5 100644 --- a/source/io/serial.h +++ b/source/io/serial.h @@ -1,6 +1,7 @@ #ifndef MSP_IO_SERIAL_H_ #define MSP_IO_SERIAL_H_ +#include #include "eventobject.h" #include "eventreader.h" #include "handle.h" @@ -8,7 +9,7 @@ namespace Msp { namespace IO { -class Serial: public EventObject +class MSPCORE_API Serial: public EventObject { public: enum Parity diff --git a/source/io/slice.h b/source/io/slice.h index 2965f98..272fa2c 100644 --- a/source/io/slice.h +++ b/source/io/slice.h @@ -1,6 +1,7 @@ #ifndef MSP_IO_SLICE_H_ #define MSP_IO_SLICE_H_ +#include #include "seekable.h" namespace Msp { @@ -16,7 +17,7 @@ its range. If the offset of the underlying object is changed, the Slice will restore it before the next access. This enables multiple Slices to be created on top of the same object. */ -class Slice: public Seekable, public sigc::trackable +class MSPCORE_API Slice: public Seekable, public sigc::trackable { private: Seekable &below; diff --git a/source/io/utils.h b/source/io/utils.h index f73383d..4507f5c 100644 --- a/source/io/utils.h +++ b/source/io/utils.h @@ -2,6 +2,7 @@ #define MSP_IO_UTILS_H_ #include +#include namespace Msp { namespace IO { @@ -14,7 +15,7 @@ data is read, regardless of the blocking mode of the object. Note: If the data is not immediately available and the object is in non-blocking mode, this function effectively becomes a busyloop until it can get more data. */ -std::size_t read_all(Base &, char *, std::size_t); +MSPCORE_API std::size_t read_all(Base &, char *, std::size_t); } // namespace IO } // namespace Msp diff --git a/source/io/zlibcompressed.h b/source/io/zlibcompressed.h index 67cd673..1dc1569 100644 --- a/source/io/zlibcompressed.h +++ b/source/io/zlibcompressed.h @@ -4,12 +4,13 @@ #include #include #include +#include #include "base.h" namespace Msp { namespace IO { -class zlib_error: public std::runtime_error +class MSPCORE_API zlib_error: public std::runtime_error { private: int m_code; @@ -27,7 +28,7 @@ operates on top of another I/O object. To ensure proper termination of the compressed data stream, the ZlibCompressed object must be destroyed before the underlying object is closed. */ -class ZlibCompressed: public Base, public sigc::trackable +class MSPCORE_API ZlibCompressed: public Base, public sigc::trackable { private: struct Private; diff --git a/source/stringcodec/ascii.h b/source/stringcodec/ascii.h index bb5d0ee..755edeb 100644 --- a/source/stringcodec/ascii.h +++ b/source/stringcodec/ascii.h @@ -1,15 +1,16 @@ #ifndef MSP_STRINGCODEC_ASCII_H_ #define MSP_STRINGCODEC_ASCII_H_ +#include #include "codec.h" namespace Msp { namespace StringCodec { -class Ascii: public StandardCodec +class MSPCORE_API Ascii: public StandardCodec { public: - class Encoder: public Codec::Encoder + class MSPCORE_API Encoder: public Codec::Encoder { public: Encoder(ErrorMode em = DEFAULT): Codec::Encoder(em) { } @@ -19,7 +20,7 @@ public: void transliterate(unichar, std::string &) override; }; - class Decoder: public Codec::Decoder + class MSPCORE_API Decoder: public Codec::Decoder { public: Decoder(ErrorMode em = DEFAULT): Codec::Decoder(em) { } diff --git a/source/stringcodec/codec.h b/source/stringcodec/codec.h index 5e67d46..f53bae5 100644 --- a/source/stringcodec/codec.h +++ b/source/stringcodec/codec.h @@ -2,6 +2,7 @@ #define MSP_STRINGCODEC_CODEC_H_ #include +#include #include "except.h" #include "ustring.h" @@ -25,7 +26,7 @@ Unicode strings are represented as ustrings. An std::string is considered to be an encoded sequence of bytes. A codec is able to determine if an encoded string could be decoded with it. */ -class Codec +class MSPCORE_API Codec { public: /** @@ -36,7 +37,7 @@ public: may find it useful or necessary to implement some other functions too (particularly sync and reset for stateful codecs). */ - class Encoder + class MSPCORE_API Encoder { protected: ErrorMode err_mode = THROW_ON_ERROR; @@ -87,7 +88,7 @@ public: Each codec class should contain an Decoder class derived from this. */ - class Decoder + class MSPCORE_API Decoder { protected: ErrorMode err_mode = THROW_ON_ERROR; @@ -204,11 +205,11 @@ std::string transcode(const std::string &s) /** Creates a codec for an encoding by name. The caller is responsible for deleting the codec when it's no longer needed. */ -Codec *create_codec(const std::string &); +MSPCORE_API Codec *create_codec(const std::string &); /** Automatically detects the encoding of a string and creates a codec for it. The codec must be deleted when it's no longer needed. */ -Codec *detect_codec(const std::string &); +MSPCORE_API Codec *detect_codec(const std::string &); } // namespace StringCodec } // namespace Msp diff --git a/source/stringcodec/codecutils.h b/source/stringcodec/codecutils.h index 395949e..cf9eb2d 100644 --- a/source/stringcodec/codecutils.h +++ b/source/stringcodec/codecutils.h @@ -1,10 +1,12 @@ #ifndef MSP_STRINGCODEC_CODECUTILS_H_ #define MSP_STRINGCODEC_CODECUTILS_H_ +#include + namespace Msp { namespace StringCodec { -int transform_mapping_or_direct(const int *mapping, unsigned map_size, int ch, bool reverse); +MSPCORE_API int transform_mapping_or_direct(const int *mapping, unsigned map_size, int ch, bool reverse); } // namespace StringCodec } // namespace Msp diff --git a/source/stringcodec/except.h b/source/stringcodec/except.h index 19cb413..fc377e0 100644 --- a/source/stringcodec/except.h +++ b/source/stringcodec/except.h @@ -2,6 +2,7 @@ #define MSP_STRINGCODEC_EXCEPT_H_ #include +#include #include "ustring.h" namespace Msp { @@ -10,7 +11,7 @@ namespace StringCodec { /** Base class for codec errors. */ -class codec_error: public std::runtime_error +class MSPCORE_API codec_error: public std::runtime_error { public: codec_error(const std::string &w): std::runtime_error(w) { } @@ -20,7 +21,7 @@ public: /** Thrown when a codec can't encode the requested character. */ -class invalid_character: public codec_error +class MSPCORE_API invalid_character: public codec_error { public: invalid_character(unichar, const std::string &); @@ -30,7 +31,7 @@ public: /** Thrown when a codec encounters a byte sequence it can't decode. */ -class invalid_sequence: public codec_error +class MSPCORE_API invalid_sequence: public codec_error { public: invalid_sequence(const std::string::const_iterator &, const std::string::const_iterator &, const std::string &); diff --git a/source/stringcodec/iso2022jp.h b/source/stringcodec/iso2022jp.h index a9bc1c2..0bb1ad3 100644 --- a/source/stringcodec/iso2022jp.h +++ b/source/stringcodec/iso2022jp.h @@ -1,12 +1,13 @@ #ifndef MSP_STRINGCODEC_ISO2022JP_H_ #define MSP_STRINGCODEC_ISO2022JP_H_ +#include #include "codec.h" namespace Msp { namespace StringCodec { -class Iso2022Jp: public StandardCodec +class MSPCORE_API Iso2022Jp: public StandardCodec { public: enum Mode @@ -16,7 +17,7 @@ public: JISX0208 }; - class Encoder: public Codec::Encoder + class MSPCORE_API Encoder: public Codec::Encoder { private: Mode mode = ASCII; @@ -32,7 +33,7 @@ public: void transliterate(unichar, std::string &) override; }; - class Decoder: public Codec::Decoder + class MSPCORE_API Decoder: public Codec::Decoder { private: Mode mode = ASCII; diff --git a/source/stringcodec/iso646fi.h b/source/stringcodec/iso646fi.h index fdb3d60..3f1bb70 100644 --- a/source/stringcodec/iso646fi.h +++ b/source/stringcodec/iso646fi.h @@ -1,15 +1,16 @@ #ifndef MSP_STRINGCODEC_ISO646FI_H_ #define MSP_STRINGCODEC_ISO646FI_H_ +#include #include "codec.h" namespace Msp { namespace StringCodec { -class Iso646Fi: public StandardCodec +class MSPCORE_API Iso646Fi: public StandardCodec { public: - class Encoder: public Codec::Encoder + class MSPCORE_API Encoder: public Codec::Encoder { public: Encoder(ErrorMode em = DEFAULT): Codec::Encoder(em) { } @@ -19,7 +20,7 @@ public: void transliterate(unichar, std::string &) override; }; - class Decoder: public Codec::Decoder + class MSPCORE_API Decoder: public Codec::Decoder { public: Decoder(ErrorMode em = DEFAULT): Codec::Decoder(em) { } diff --git a/source/stringcodec/iso88591.h b/source/stringcodec/iso88591.h index a8ba809..a6003ce 100644 --- a/source/stringcodec/iso88591.h +++ b/source/stringcodec/iso88591.h @@ -1,15 +1,16 @@ #ifndef MSP_STRINGCODEC_ISO88591_H_ #define MSP_STRINGCODEC_ISO88591_H_ +#include #include "codec.h" namespace Msp { namespace StringCodec { -class Iso88591: public StandardCodec +class MSPCORE_API Iso88591: public StandardCodec { public: - class Encoder: public Codec::Encoder + class MSPCORE_API Encoder: public Codec::Encoder { public: Encoder(ErrorMode em = DEFAULT): Codec::Encoder(em) { } @@ -19,7 +20,7 @@ public: void transliterate(unichar, std::string &) override; }; - class Decoder: public Codec::Decoder + class MSPCORE_API Decoder: public Codec::Decoder { public: Decoder(ErrorMode em = DEFAULT): Codec::Decoder(em) { } diff --git a/source/stringcodec/iso885915.h b/source/stringcodec/iso885915.h index 3791d05..2e81245 100644 --- a/source/stringcodec/iso885915.h +++ b/source/stringcodec/iso885915.h @@ -1,15 +1,16 @@ #ifndef MSP_STRINGCODEC_ISO885915_H_ #define MSP_STRINGCODEC_ISO885915_H_ +#include #include "codec.h" namespace Msp { namespace StringCodec { -class Iso885915: public StandardCodec +class MSPCORE_API Iso885915: public StandardCodec { public: - class Encoder: public Codec::Encoder + class MSPCORE_API Encoder: public Codec::Encoder { public: Encoder(ErrorMode em = DEFAULT): Codec::Encoder(em) { } @@ -19,7 +20,7 @@ public: void transliterate(unichar, std::string &) override; }; - class Decoder: public Codec::Decoder + class MSPCORE_API Decoder: public Codec::Decoder { public: Decoder(ErrorMode em = DEFAULT): Codec::Decoder(em) { } diff --git a/source/stringcodec/jisx0201.h b/source/stringcodec/jisx0201.h index 5cbda03..3194c78 100644 --- a/source/stringcodec/jisx0201.h +++ b/source/stringcodec/jisx0201.h @@ -1,15 +1,16 @@ #ifndef MSP_STRINGCODEC_JISX201_H_ #define MSP_STRINGCODEC_JISX201_H_ +#include #include "codec.h" namespace Msp { namespace StringCodec { -class JisX0201: public StandardCodec +class MSPCORE_API JisX0201: public StandardCodec { public: - class Encoder: public Codec::Encoder + class MSPCORE_API Encoder: public Codec::Encoder { public: Encoder(ErrorMode em = DEFAULT): Codec::Encoder(em) { } @@ -19,7 +20,7 @@ public: void transliterate(unichar, std::string &) override; }; - class Decoder: public Codec::Decoder + class MSPCORE_API Decoder: public Codec::Decoder { public: Decoder(ErrorMode em = DEFAULT): Codec::Decoder(em) { } diff --git a/source/stringcodec/jisx0208.h b/source/stringcodec/jisx0208.h index b0c03b2..0f29432 100644 --- a/source/stringcodec/jisx0208.h +++ b/source/stringcodec/jisx0208.h @@ -1,6 +1,7 @@ #ifndef MSP_STRINGCODEC_JISX0208_H_ #define MSP_STRINGCODEC_JISX0208_H_ +#include #include "codec.h" namespace Msp { @@ -11,10 +12,10 @@ Codec for the JIS X 0208 encoding. This is not particularly useful as a stand-alone codec, due to lack of a linefeed character among other things, but is included as part of some other encodings. */ -class JisX0208: public StandardCodec +class MSPCORE_API JisX0208: public StandardCodec { public: - class Encoder: public Codec::Encoder + class MSPCORE_API Encoder: public Codec::Encoder { public: Encoder(ErrorMode em = DEFAULT): Codec::Encoder(em) { } @@ -24,7 +25,7 @@ public: void transliterate(unichar, std::string &) override; }; - class Decoder: public Codec::Decoder + class MSPCORE_API Decoder: public Codec::Decoder { public: Decoder(ErrorMode em = DEFAULT): Codec::Decoder(em) { } @@ -46,8 +47,8 @@ struct Kuten explicit operator bool() { return ku!=0 && ten!=0; } }; -unichar jisx0208_to_ucs(Kuten); -Kuten ucs_to_jisx0208(unichar); +MSPCORE_API unichar jisx0208_to_ucs(Kuten); +MSPCORE_API Kuten ucs_to_jisx0208(unichar); } // namespace StringCodec } // namespace Msp diff --git a/source/stringcodec/utf16.h b/source/stringcodec/utf16.h index 73d81cb..a588b12 100644 --- a/source/stringcodec/utf16.h +++ b/source/stringcodec/utf16.h @@ -1,6 +1,7 @@ #ifndef MSP_STRINGCODEC_UTF16_H_ #define MSP_STRINGCODEC_UTF16_H_ +#include #include "codec.h" namespace Msp { @@ -11,7 +12,7 @@ The UTF-16 codec, as specified in the Unicode standard. Both little and big endian are supported, as well as autodetection with the BOM. In the absence of a BOM, big endian is assumed. */ -class Utf16: public StandardCodec +class MSPCORE_API Utf16: public StandardCodec { public: enum Endian @@ -21,7 +22,7 @@ public: LITTLE }; - class Encoder: public Codec::Encoder + class MSPCORE_API Encoder: public Codec::Encoder { private: Endian endian = BIG; @@ -35,7 +36,7 @@ public: void transliterate(unichar, std::string &) override; }; - class Decoder: public Codec::Decoder + class MSPCORE_API Decoder: public Codec::Decoder { private: Endian endian = AUTO; diff --git a/source/stringcodec/utf8.h b/source/stringcodec/utf8.h index f170916..c3f4a59 100644 --- a/source/stringcodec/utf8.h +++ b/source/stringcodec/utf8.h @@ -1,15 +1,16 @@ #ifndef MSP_STRINGCODEC_UTF8_H_ #define MSP_STRINGCODEC_UTF8_H_ +#include #include "codec.h" namespace Msp { namespace StringCodec { -class Utf8: public StandardCodec +class MSPCORE_API Utf8: public StandardCodec { public: - class Encoder: public Codec::Encoder + class MSPCORE_API Encoder: public Codec::Encoder { public: Encoder(ErrorMode em = DEFAULT): Codec::Encoder(em) { } @@ -19,7 +20,7 @@ public: void transliterate(unichar, std::string &) override; }; - class Decoder: public Codec::Decoder + class MSPCORE_API Decoder: public Codec::Decoder { public: Decoder(ErrorMode em = DEFAULT): Codec::Decoder(em) { } diff --git a/source/stringcodec/windows1252.h b/source/stringcodec/windows1252.h index bcea69b..b89fdae 100644 --- a/source/stringcodec/windows1252.h +++ b/source/stringcodec/windows1252.h @@ -1,15 +1,16 @@ #ifndef MSP_STRINGCODEC_WINDOWS1252_H_ #define MSP_STRINGCODEC_WINDOWS1252_H_ +#include #include "codec.h" namespace Msp { namespace StringCodec { -class Windows1252: public StandardCodec +class MSPCORE_API Windows1252: public StandardCodec { public: - class Encoder: public Codec::Encoder + class MSPCORE_API Encoder: public Codec::Encoder { public: Encoder(ErrorMode em = DEFAULT): Codec::Encoder(em) { } @@ -19,7 +20,7 @@ public: void transliterate(unichar, std::string &) override; }; - class Decoder: public Codec::Decoder + class MSPCORE_API Decoder: public Codec::Decoder { public: Decoder(ErrorMode em = DEFAULT): Codec::Decoder(em) { } diff --git a/source/strings/fmt.h b/source/strings/fmt.h index d6db418..88b297d 100644 --- a/source/strings/fmt.h +++ b/source/strings/fmt.h @@ -4,10 +4,11 @@ #include #include #include +#include namespace Msp { -class format_error: public std::logic_error +class MSPCORE_API format_error: public std::logic_error { public: format_error(const std::string &w): std::logic_error(w) { } @@ -34,7 +35,7 @@ Some new conversions are supported: b/B Binary integer conversion P Uppercase pointer conversion (like %#X) */ -class Fmt +class MSPCORE_API Fmt { public: enum Type diff --git a/source/strings/format.h b/source/strings/format.h index 49c40e9..7969ef3 100644 --- a/source/strings/format.h +++ b/source/strings/format.h @@ -2,6 +2,7 @@ #define MSP_STRINGS_FORMAT_H_ #include +#include #include "lexicalcast.h" namespace Msp { @@ -9,7 +10,7 @@ namespace Msp { /** Printf-like string formatter class. */ -class Formatter +class MSPCORE_API Formatter { private: std::string fmt; diff --git a/source/strings/glob.h b/source/strings/glob.h index a58d0b1..5ae5f55 100644 --- a/source/strings/glob.h +++ b/source/strings/glob.h @@ -2,11 +2,12 @@ #define MSP_STRINGS_GLOB_H_ #include +#include namespace Msp { -bool globmatch(const std::string &, const std::string &); -bool globcasematch(const std::string &, const std::string &); +MSPCORE_API bool globmatch(const std::string &, const std::string &); +MSPCORE_API bool globcasematch(const std::string &, const std::string &); } // namespace Msp diff --git a/source/strings/lexicalcast.h b/source/strings/lexicalcast.h index 12b5d08..ccb7790 100644 --- a/source/strings/lexicalcast.h +++ b/source/strings/lexicalcast.h @@ -5,6 +5,7 @@ #include #include #include +#include #include "fmt.h" namespace Msp { @@ -12,7 +13,7 @@ namespace Msp { /** Thrown for errors in lexical conversions. */ -class lexical_error: public std::runtime_error +class MSPCORE_API lexical_error: public std::runtime_error { public: lexical_error(const std::string &w): runtime_error(w) { } @@ -22,7 +23,7 @@ public: /** Thrown when the format is unsuitable for the type being converted. */ -class format_mismatch: public lexical_error +class MSPCORE_API format_mismatch: public lexical_error { public: format_mismatch(const std::string &w): lexical_error(w) { } @@ -32,7 +33,7 @@ public: /** Helper class for lexical_cast to facilitate operator overloading. */ -class LexicalConverter +class MSPCORE_API LexicalConverter { private: Fmt fmt; @@ -49,41 +50,41 @@ public: }; -void operator<<(LexicalConverter &, char); -void operator<<(LexicalConverter &, signed char); -void operator<<(LexicalConverter &, short); -void operator<<(LexicalConverter &, int); -void operator<<(LexicalConverter &, long); -void operator<<(LexicalConverter &, unsigned char); -void operator<<(LexicalConverter &, unsigned short); -void operator<<(LexicalConverter &, unsigned); -void operator<<(LexicalConverter &, unsigned long); -void operator<<(LexicalConverter &, long long); -void operator<<(LexicalConverter &, unsigned long long); -void operator<<(LexicalConverter &, bool); -void operator<<(LexicalConverter &, float); -void operator<<(LexicalConverter &, double); -void operator<<(LexicalConverter &, long double); -void operator<<(LexicalConverter &, const std::string &); -void operator<<(LexicalConverter &, const char *); -void operator<<(LexicalConverter &, const void *); - -void operator>>(const LexicalConverter &, char &); -void operator>>(const LexicalConverter &, signed char &); -void operator>>(const LexicalConverter &, short &); -void operator>>(const LexicalConverter &, int &); -void operator>>(const LexicalConverter &, long &); -void operator>>(const LexicalConverter &, unsigned char &); -void operator>>(const LexicalConverter &, unsigned short &); -void operator>>(const LexicalConverter &, unsigned int &); -void operator>>(const LexicalConverter &, unsigned long &); -void operator>>(const LexicalConverter &, long long &); -void operator>>(const LexicalConverter &, unsigned long long &); -void operator>>(const LexicalConverter &, bool &); -void operator>>(const LexicalConverter &, float &); -void operator>>(const LexicalConverter &, double &); -void operator>>(const LexicalConverter &, long double &); -void operator>>(const LexicalConverter &, std::string &); +MSPCORE_API void operator<<(LexicalConverter &, char); +MSPCORE_API void operator<<(LexicalConverter &, signed char); +MSPCORE_API void operator<<(LexicalConverter &, short); +MSPCORE_API void operator<<(LexicalConverter &, int); +MSPCORE_API void operator<<(LexicalConverter &, long); +MSPCORE_API void operator<<(LexicalConverter &, unsigned char); +MSPCORE_API void operator<<(LexicalConverter &, unsigned short); +MSPCORE_API void operator<<(LexicalConverter &, unsigned); +MSPCORE_API void operator<<(LexicalConverter &, unsigned long); +MSPCORE_API void operator<<(LexicalConverter &, long long); +MSPCORE_API void operator<<(LexicalConverter &, unsigned long long); +MSPCORE_API void operator<<(LexicalConverter &, bool); +MSPCORE_API void operator<<(LexicalConverter &, float); +MSPCORE_API void operator<<(LexicalConverter &, double); +MSPCORE_API void operator<<(LexicalConverter &, long double); +MSPCORE_API void operator<<(LexicalConverter &, const std::string &); +MSPCORE_API void operator<<(LexicalConverter &, const char *); +MSPCORE_API void operator<<(LexicalConverter &, const void *); + +MSPCORE_API void operator>>(const LexicalConverter &, char &); +MSPCORE_API void operator>>(const LexicalConverter &, signed char &); +MSPCORE_API void operator>>(const LexicalConverter &, short &); +MSPCORE_API void operator>>(const LexicalConverter &, int &); +MSPCORE_API void operator>>(const LexicalConverter &, long &); +MSPCORE_API void operator>>(const LexicalConverter &, unsigned char &); +MSPCORE_API void operator>>(const LexicalConverter &, unsigned short &); +MSPCORE_API void operator>>(const LexicalConverter &, unsigned int &); +MSPCORE_API void operator>>(const LexicalConverter &, unsigned long &); +MSPCORE_API void operator>>(const LexicalConverter &, long long &); +MSPCORE_API void operator>>(const LexicalConverter &, unsigned long long &); +MSPCORE_API void operator>>(const LexicalConverter &, bool &); +MSPCORE_API void operator>>(const LexicalConverter &, float &); +MSPCORE_API void operator>>(const LexicalConverter &, double &); +MSPCORE_API void operator>>(const LexicalConverter &, long double &); +MSPCORE_API void operator>>(const LexicalConverter &, std::string &); // Generic operators using stringstream diff --git a/source/strings/regex.h b/source/strings/regex.h index acc842b..42c1e01 100644 --- a/source/strings/regex.h +++ b/source/strings/regex.h @@ -3,11 +3,12 @@ #include #include +#include #include "regmatch.h" namespace Msp { -class bad_regex: public std::logic_error +class MSPCORE_API bad_regex: public std::logic_error { public: bad_regex(const std::string &, const std::string &, const std::string::const_iterator &); @@ -69,7 +70,7 @@ a bitmask. The MATCH_ANY instruction consumes the input character and always succeeds. */ -class Regex +class MSPCORE_API Regex { private: typedef std::basic_string Code; diff --git a/source/strings/regmatch.h b/source/strings/regmatch.h index 6af309e..8d4406a 100644 --- a/source/strings/regmatch.h +++ b/source/strings/regmatch.h @@ -3,6 +3,7 @@ #include #include +#include namespace Msp { @@ -16,7 +17,7 @@ part matched by the whole regex. Further groups, if present, indicate parts matched by subregexes. These are ordered from left to right, by the opening parenthesis of the subregex. */ -class RegMatch +class MSPCORE_API RegMatch { public: /** diff --git a/source/strings/utils.h b/source/strings/utils.h index f7e9433..28763e6 100644 --- a/source/strings/utils.h +++ b/source/strings/utils.h @@ -3,6 +3,7 @@ #include #include +#include namespace Msp { @@ -10,22 +11,22 @@ namespace Msp { than, equal to or greater than zero depending on whether the first string lexicographically precedes, is equal to or follows the second one, respectively. */ -int strcasecmp(const std::string &s1, const std::string &s2); +MSPCORE_API int strcasecmp(const std::string &s1, const std::string &s2); /** Converts a string to lower case. */ -std::string tolower(const std::string &); +MSPCORE_API std::string tolower(const std::string &); /** Converts a string to upper case. */ -std::string toupper(const std::string &); +MSPCORE_API std::string toupper(const std::string &); /** Checks whether a string consists of digits only. */ -bool isnumrc(const std::string &); +MSPCORE_API bool isnumrc(const std::string &); /** Checks whether a string consists of alphabetic characters only. */ -bool isalpha(const std::string &); +MSPCORE_API bool isalpha(const std::string &); /** Checks whether a string consists of alphanumeric characters only. */ -bool isalnum(const std::string &); +MSPCORE_API bool isalnum(const std::string &); /* These are required to make the standard version work from inside the Msp namespace */ @@ -40,27 +41,27 @@ be treated as a single separator. If max_split is non-negative, at most that many split will be performed, i.e. the resulting vector will contain at most max_split+1 elements. */ -std::vector split(const std::string &str, const std::string &sep = " \t\r\n", int max_split = -1); +MSPCORE_API std::vector split(const std::string &str, const std::string &sep = " \t\r\n", int max_split = -1); /** Splits a string on occurrences of a single character. */ -std::vector split(const std::string &str, char sep, int max_split = -1); +MSPCORE_API std::vector split(const std::string &str, char sep, int max_split = -1); /** Splits a string on occurrences of another string. */ -std::vector split_long(const std::string &str, const std::string &sep, int max_split = -1); +MSPCORE_API std::vector split_long(const std::string &str, const std::string &sep, int max_split = -1); /** Splits a string on occurrences of another string. Two consecutive separators will cause an empty string to be placed in the result. */ -std::vector split_fields(const std::string &str, const std::string &sep, int max_split = -1); +MSPCORE_API std::vector split_fields(const std::string &str, const std::string &sep, int max_split = -1); /** Splits a string on occurrences of a single character. Two consecutive separators will cause an empty string to be placed in the result. */ -std::vector split_fields(const std::string &str, char sep, int max_split = -1); +MSPCORE_API std::vector split_fields(const std::string &str, char sep, int max_split = -1); /** Appends a string to another, using a separator if both are non-empty. */ -std::string &append(std::string &str, const std::string &sep, const std::string &other); +MSPCORE_API std::string &append(std::string &str, const std::string &sep, const std::string &other); /** Joins two strings, using a separator if both are non-empty. */ -std::string join(const std::string &str1, const std::string &sep, const std::string &str2); +MSPCORE_API std::string join(const std::string &str1, const std::string &sep, const std::string &str2); /** Concatenates strings from an iterator range. */ template @@ -74,14 +75,14 @@ std::string join(Iter begin, Iter end, const std::string &sep = " ") } /** Strips leading and trailing whitespace from a string. */ -std::string strip(const std::string &); +MSPCORE_API std::string strip(const std::string &); /** Unescapes a string with C escape sequences. */ -std::string c_unescape(const std::string &str); +MSPCORE_API std::string c_unescape(const std::string &str); /** Escapes any non-printable characters in a string with C escape sequences. Optionally, any characters with the high bit set can be escaped as well. */ -std::string c_escape(const std::string &str, bool escape_8bit = true); +MSPCORE_API std::string c_escape(const std::string &str, bool escape_8bit = true); } // namespace Msp diff --git a/source/time/datetime.h b/source/time/datetime.h index a5d91cf..2336374 100644 --- a/source/time/datetime.h +++ b/source/time/datetime.h @@ -2,6 +2,7 @@ #define MSP_TIME_DATETIME_H_ #include +#include #include "timezone.h" #include "rawtime.h" @@ -20,7 +21,7 @@ Due to the complex internal representation, arithmetic operations on a DateTime are relatively slow. For purposes of internal scheduling in a program, a TimeStamp is a better choice. */ -class DateTime +class MSPCORE_API DateTime { private: int year = 1970; diff --git a/source/time/timedelta.h b/source/time/timedelta.h index 1a4274b..a6c7005 100644 --- a/source/time/timedelta.h +++ b/source/time/timedelta.h @@ -3,6 +3,7 @@ #include #include +#include #include #include "rawtime.h" @@ -12,7 +13,7 @@ namespace Time { /** Represents a quantity of time, such as five seconds. */ -class TimeDelta +class MSPCORE_API TimeDelta { private: RawTime usec = 0; @@ -60,18 +61,18 @@ public: template inline TimeDelta operator*(T a, const TimeDelta &t) { return t*a; } -void operator<<(LexicalConverter &, const TimeDelta &); +MSPCORE_API void operator<<(LexicalConverter &, const TimeDelta &); // Constants to be used in creation of TimeDeltas -extern const TimeDelta zero; -extern const TimeDelta usec; -extern const TimeDelta msec; -extern const TimeDelta sec; -extern const TimeDelta min; -extern const TimeDelta hour; -extern const TimeDelta day; -extern const TimeDelta week; +MSPCORE_API extern const TimeDelta zero; +MSPCORE_API extern const TimeDelta usec; +MSPCORE_API extern const TimeDelta msec; +MSPCORE_API extern const TimeDelta sec; +MSPCORE_API extern const TimeDelta min; +MSPCORE_API extern const TimeDelta hour; +MSPCORE_API extern const TimeDelta day; +MSPCORE_API extern const TimeDelta week; inline TimeDelta abs(const TimeDelta &t) { return t>=zero ? t : -t; } using std::abs; diff --git a/source/time/timer.h b/source/time/timer.h index 04d0be9..7cb5c76 100644 --- a/source/time/timer.h +++ b/source/time/timer.h @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -19,7 +20,7 @@ of the returned slot. This class is thread-safe, to allow running timers in a separate thread. */ -class Timer: private NonCopyable +class MSPCORE_API Timer: private NonCopyable { public: class Slot diff --git a/source/time/timestamp.h b/source/time/timestamp.h index 8068510..5081305 100644 --- a/source/time/timestamp.h +++ b/source/time/timestamp.h @@ -1,6 +1,7 @@ #ifndef MSP_TIME_TIMESTAMP_H_ #define MSP_TIME_TIMESTAMP_H_ +#include #include "timedelta.h" #include "rawtime.h" @@ -13,7 +14,7 @@ function. For representing user-specified times, use the DateTime class. */ -class TimeStamp +class MSPCORE_API TimeStamp { private: RawTime usec = 0; diff --git a/source/time/timezone.h b/source/time/timezone.h index 3fbeb54..83b4b58 100644 --- a/source/time/timezone.h +++ b/source/time/timezone.h @@ -1,12 +1,13 @@ #ifndef MSP_TIME_TIMEZONE_H_ #define MSP_TIME_TIMEZONE_H_ +#include #include "timedelta.h" namespace Msp { namespace Time { -class TimeZone +class MSPCORE_API TimeZone { private: std::string name; diff --git a/source/time/utils.h b/source/time/utils.h index 00b6ef8..dd325b0 100644 --- a/source/time/utils.h +++ b/source/time/utils.h @@ -2,6 +2,7 @@ #define MSP_TIME_UTILS_H_ #include +#include namespace Msp { namespace Time { @@ -10,15 +11,15 @@ class TimeDelta; class TimeStamp; /** Returns the current timestamp. */ -TimeStamp now(); +MSPCORE_API TimeStamp now(); -std::string format_now(const std::string &); +MSPCORE_API std::string format_now(const std::string &); /** Returns the CPU time used by the program so far. */ -TimeDelta get_cpu_time(); +MSPCORE_API TimeDelta get_cpu_time(); /** Sleeps for the given duration. */ -void sleep(const TimeDelta &); +MSPCORE_API void sleep(const TimeDelta &); } // namespace Time } // namespace Msp -- 2.43.0 From 34efed1510d68f8258c3b9db37a9f55dcb1eeda9 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Tue, 3 Jan 2023 15:29:58 +0200 Subject: [PATCH 09/16] Move Memory constructors to the .cpp file It's causing an undefined reference to vftable if they're in the header. --- source/io/memory.cpp | 20 ++++++++++++++++---- source/io/memory.h | 6 +++--- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/source/io/memory.cpp b/source/io/memory.cpp index 19629c4..0539fdb 100644 --- a/source/io/memory.cpp +++ b/source/io/memory.cpp @@ -9,14 +9,26 @@ using namespace std; namespace Msp { namespace IO { -Memory::Memory(char *b, char *e, Mode m) +Memory::Memory(char *d, std::size_t s, Mode m): + Memory(d, d+s, m) +{ } + +Memory::Memory(char *b, char *e, Mode m): + begin(b), + end(e), + pos(begin) { - begin = b; - end = e; - pos = begin; mode = m; } +Memory::Memory(const char *d, std::size_t s): + Memory(const_cast(d), const_cast(d+s), M_READ) +{ } + +Memory::Memory(const char *b, const char *e): + Memory(const_cast(b), const_cast(e), M_READ) +{ } + void Memory::set_block(bool) { throw unsupported("Memory::set_block"); diff --git a/source/io/memory.h b/source/io/memory.h index 5ae2a34..e009cfd 100644 --- a/source/io/memory.h +++ b/source/io/memory.h @@ -15,10 +15,10 @@ private: char *pos = nullptr; public: - Memory(char *d, std::size_t s, Mode m = M_RDWR): Memory(d, d+s, m) { } + Memory(char *d, std::size_t s, Mode m = M_RDWR); Memory(char *, char *, Mode = M_RDWR); - Memory(const char *d, std::size_t s): Memory(const_cast(d), const_cast(d+s), M_READ) { } - Memory(const char *b, const char *e): Memory(const_cast(b), const_cast(e), M_READ) { } + Memory(const char *d, std::size_t s); + Memory(const char *b, const char *e); void set_block(bool) override; void set_inherit(bool) override; -- 2.43.0 From 0b51556bd22d9d9c2dc10692fc3c1feb3c6e98b3 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Tue, 3 Jan 2023 16:03:19 +0200 Subject: [PATCH 10/16] Make time constants constexpr and move them to the header --- source/time/timedelta.cpp | 9 --------- source/time/timedelta.h | 20 ++++++++++---------- 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/source/time/timedelta.cpp b/source/time/timedelta.cpp index a56e0fe..5b381da 100644 --- a/source/time/timedelta.cpp +++ b/source/time/timedelta.cpp @@ -75,14 +75,5 @@ void operator<<(LexicalConverter &conv, const TimeDelta &td) conv.result(result); } -const TimeDelta zero(0); -const TimeDelta usec(1); -const TimeDelta msec(1000); -const TimeDelta sec(1000000); -const TimeDelta min(60*1000000); -const TimeDelta hour(3600*1000000LL); -const TimeDelta day(86400*1000000LL); -const TimeDelta week(7*86400*1000000LL); - } // namespace Time } // namespace Msp diff --git a/source/time/timedelta.h b/source/time/timedelta.h index a6c7005..2ff4bdd 100644 --- a/source/time/timedelta.h +++ b/source/time/timedelta.h @@ -20,11 +20,11 @@ private: public: /** Constructs a zero TimeDelta. */ - TimeDelta() = default; + constexpr TimeDelta() = default; /** Constructs a TimeDelta from a plain number. The purpose of this is to allow serialization together with the raw() function. */ - explicit TimeDelta(RawTime u): usec(u) { } + explicit constexpr TimeDelta(RawTime u): usec(u) { } /** Returns the raw number stored inside the TimeDelta. This should only be used for serialization and the result should not be interpreted in any way. */ @@ -65,14 +65,14 @@ MSPCORE_API void operator<<(LexicalConverter &, const TimeDelta &); // Constants to be used in creation of TimeDeltas -MSPCORE_API extern const TimeDelta zero; -MSPCORE_API extern const TimeDelta usec; -MSPCORE_API extern const TimeDelta msec; -MSPCORE_API extern const TimeDelta sec; -MSPCORE_API extern const TimeDelta min; -MSPCORE_API extern const TimeDelta hour; -MSPCORE_API extern const TimeDelta day; -MSPCORE_API extern const TimeDelta week; +constexpr TimeDelta zero(0); +constexpr TimeDelta usec(1); +constexpr TimeDelta msec(1000); +constexpr TimeDelta sec(1000000); +constexpr TimeDelta min(60*1000000); +constexpr TimeDelta hour(3600*1000000LL); +constexpr TimeDelta day(86400*1000000LL); +constexpr TimeDelta week(7*86400*1000000LL); inline TimeDelta abs(const TimeDelta &t) { return t>=zero ? t : -t; } using std::abs; -- 2.43.0 From 3ba20e3ddde250a78ab2410012551eb60304f766 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Tue, 3 Jan 2023 16:29:47 +0200 Subject: [PATCH 11/16] Add a wrapper header for windows.h Since Time::min is now defined in the header, it runs afoul of the min() macro defined in windows.h unless the latter is disabled. --- source/core/windows/main.cpp | 3 ++- source/core/windows/module_platform.h | 2 +- source/core/windows/mutex.cpp | 2 +- source/core/windows/mutex_platform.h | 2 +- source/core/windows/process.cpp | 2 +- source/core/windows/process_platform.h | 2 +- source/core/windows/semaphore.cpp | 2 +- source/core/windows/systemerror.cpp | 2 +- source/core/windows/thread.cpp | 2 +- source/core/windows/thread_platform.h | 2 +- source/core/windows/winapi.h | 12 ++++++++++++ source/fs/windows/dir.cpp | 2 +- source/fs/windows/stat.cpp | 2 +- source/fs/windows/stat_platform.h | 2 +- source/fs/windows/utils.cpp | 2 +- source/io/windows/eventreader.cpp | 2 +- source/io/windows/handle_platform.h | 2 +- source/io/windows/poll_platform.h | 2 +- source/io/windows/seekable.cpp | 2 +- source/io/windows/serial_platform.h | 2 +- source/time/windows/rawtime_platform.h | 2 +- source/time/windows/timezone.cpp | 2 +- source/time/windows/utils.cpp | 2 +- 23 files changed, 35 insertions(+), 22 deletions(-) create mode 100644 source/core/windows/winapi.h diff --git a/source/core/windows/main.cpp b/source/core/windows/main.cpp index 11da64b..df17020 100644 --- a/source/core/windows/main.cpp +++ b/source/core/windows/main.cpp @@ -1,4 +1,5 @@ -#include +#include "winapi.h" +#include #include #include #include "application.h" diff --git a/source/core/windows/module_platform.h b/source/core/windows/module_platform.h index 81dfd0f..eb0b633 100644 --- a/source/core/windows/module_platform.h +++ b/source/core/windows/module_platform.h @@ -1,7 +1,7 @@ #ifndef MSP_CORE_MODULE_PLATFORM_H_ #define MSP_CORE_MODULE_PLATFORM_H_ -#include +#include "winapi.h" namespace Msp { diff --git a/source/core/windows/mutex.cpp b/source/core/windows/mutex.cpp index e51fda4..6d39635 100644 --- a/source/core/windows/mutex.cpp +++ b/source/core/windows/mutex.cpp @@ -1,4 +1,4 @@ -#include +#include "winapi.h" #include "mutex.h" #include "mutex_private.h" diff --git a/source/core/windows/mutex_platform.h b/source/core/windows/mutex_platform.h index fae5e85..1d5c1c0 100644 --- a/source/core/windows/mutex_platform.h +++ b/source/core/windows/mutex_platform.h @@ -1,7 +1,7 @@ #ifndef MSP_CORE_MUTEX_PLATFORM_H_ #define MSP_CORE_MUTEX_PLATFORM_H_ -#include +#include "winapi.h" namespace Msp { diff --git a/source/core/windows/process.cpp b/source/core/windows/process.cpp index e19fd6b..0eae33b 100644 --- a/source/core/windows/process.cpp +++ b/source/core/windows/process.cpp @@ -1,4 +1,4 @@ -#include +#include "winapi.h" #include #include #include diff --git a/source/core/windows/process_platform.h b/source/core/windows/process_platform.h index 4cb793a..d55678e 100644 --- a/source/core/windows/process_platform.h +++ b/source/core/windows/process_platform.h @@ -1,7 +1,7 @@ #ifndef MSP_CORE_PROCESS_PLATFORM_H_ #define MSP_CORE_PROCESS_PLATFORM_H_ -#include +#include "winapi.h" namespace Msp { diff --git a/source/core/windows/semaphore.cpp b/source/core/windows/semaphore.cpp index c81f815..e45e4b9 100644 --- a/source/core/windows/semaphore.cpp +++ b/source/core/windows/semaphore.cpp @@ -1,4 +1,4 @@ -#include +#include "winapi.h" #include #include #include "semaphore.h" diff --git a/source/core/windows/systemerror.cpp b/source/core/windows/systemerror.cpp index 93aa7bd..754c90b 100644 --- a/source/core/windows/systemerror.cpp +++ b/source/core/windows/systemerror.cpp @@ -1,4 +1,4 @@ -#include +#include "winapi.h" #include #include "systemerror.h" diff --git a/source/core/windows/thread.cpp b/source/core/windows/thread.cpp index 8890a70..3231896 100644 --- a/source/core/windows/thread.cpp +++ b/source/core/windows/thread.cpp @@ -1,4 +1,4 @@ -#include +#include "winapi.h" #include "thread.h" #include "thread_private.h" diff --git a/source/core/windows/thread_platform.h b/source/core/windows/thread_platform.h index 50b1a5e..d88bd8b 100644 --- a/source/core/windows/thread_platform.h +++ b/source/core/windows/thread_platform.h @@ -1,7 +1,7 @@ #ifndef MSP_CORE_THREAD_PLATFORM_H_ #define MSP_CORE_THREAD_PLATFORM_H_ -#include +#include "winapi.h" namespace Msp { diff --git a/source/core/windows/winapi.h b/source/core/windows/winapi.h new file mode 100644 index 0000000..dca0880 --- /dev/null +++ b/source/core/windows/winapi.h @@ -0,0 +1,12 @@ +#ifndef MSP_CORE_WINAPI_H_ +#define MSP_CORE_WINAPI_H_ + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#ifndef NOMINMAX +#define NOMINMAX +#endif +#include + +#endif diff --git a/source/fs/windows/dir.cpp b/source/fs/windows/dir.cpp index fde0200..2ba2f1e 100644 --- a/source/fs/windows/dir.cpp +++ b/source/fs/windows/dir.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include #include diff --git a/source/fs/windows/stat.cpp b/source/fs/windows/stat.cpp index 8331e60..ee79476 100644 --- a/source/fs/windows/stat.cpp +++ b/source/fs/windows/stat.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include #include diff --git a/source/fs/windows/stat_platform.h b/source/fs/windows/stat_platform.h index 6440aca..89961c6 100644 --- a/source/fs/windows/stat_platform.h +++ b/source/fs/windows/stat_platform.h @@ -1,7 +1,7 @@ #ifndef MSP_FS_STAT_PLATFORM_H_ #define MSP_FS_STAT_PLATFORM_H_ -#include +#include namespace Msp { namespace FS { diff --git a/source/fs/windows/utils.cpp b/source/fs/windows/utils.cpp index f38d192..a1c2513 100644 --- a/source/fs/windows/utils.cpp +++ b/source/fs/windows/utils.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include #include "dir.h" diff --git a/source/io/windows/eventreader.cpp b/source/io/windows/eventreader.cpp index 33a095a..8f208c2 100644 --- a/source/io/windows/eventreader.cpp +++ b/source/io/windows/eventreader.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include #include "eventreader.h" diff --git a/source/io/windows/handle_platform.h b/source/io/windows/handle_platform.h index f12e5f7..776e8f3 100644 --- a/source/io/windows/handle_platform.h +++ b/source/io/windows/handle_platform.h @@ -1,7 +1,7 @@ #ifndef MSP_IO_HANDLE_PLATFORM_H_ #define MSP_IO_HANDLE_PLATFORM_H_ -#include +#include namespace Msp { namespace IO { diff --git a/source/io/windows/poll_platform.h b/source/io/windows/poll_platform.h index ec778ae..62a000f 100644 --- a/source/io/windows/poll_platform.h +++ b/source/io/windows/poll_platform.h @@ -1,7 +1,7 @@ #ifndef MSP_IO_POLL_PLATFORM_H_ #define MSP_IO_POLL_PLATFORM_H_ -#include +#include #include #include "poll.h" diff --git a/source/io/windows/seekable.cpp b/source/io/windows/seekable.cpp index c33a798..3756cf1 100644 --- a/source/io/windows/seekable.cpp +++ b/source/io/windows/seekable.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include "handle.h" #include "handle_private.h" diff --git a/source/io/windows/serial_platform.h b/source/io/windows/serial_platform.h index dd7dd50..3173736 100644 --- a/source/io/windows/serial_platform.h +++ b/source/io/windows/serial_platform.h @@ -1,7 +1,7 @@ #ifndef MSP_IO_SERIAL_PLATFORM_H_ #define MSP_IO_SERIAL_PLATFORM_H_ -#include +#include namespace Msp { namespace IO { diff --git a/source/time/windows/rawtime_platform.h b/source/time/windows/rawtime_platform.h index 60a9a59..bd57889 100644 --- a/source/time/windows/rawtime_platform.h +++ b/source/time/windows/rawtime_platform.h @@ -1,7 +1,7 @@ #ifndef MSP_TIME_RAWTIME_PLATFORM_H_ #define MSP_TIME_RAWTIME_PLATFORM_H_ -#include +#include #include "rawtime.h" namespace Msp { diff --git a/source/time/windows/timezone.cpp b/source/time/windows/timezone.cpp index 570c679..1b52644 100644 --- a/source/time/windows/timezone.cpp +++ b/source/time/windows/timezone.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include "timezone.h" diff --git a/source/time/windows/utils.cpp b/source/time/windows/utils.cpp index 2150a10..4d295a9 100644 --- a/source/time/windows/utils.cpp +++ b/source/time/windows/utils.cpp @@ -1,4 +1,4 @@ -#include +#include #include "rawtime_private.h" #include "timedelta.h" #include "timestamp.h" -- 2.43.0 From c77c9fc85ca6b9fc111b1a3d8a84c3903e3dd646 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Tue, 3 Jan 2023 17:42:11 +0200 Subject: [PATCH 12/16] Make Console references static instead of extern This avoids unresolved external errors on MSVC. It's not ideal because every translation unit will have its own copy of the references and initialize them separately, but the overhead for calling the instance accessor function is not too large. --- source/io/console.cpp | 4 ---- source/io/console.h | 7 ++++--- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/source/io/console.cpp b/source/io/console.cpp index abb872d..0ac05c6 100644 --- a/source/io/console.cpp +++ b/source/io/console.cpp @@ -68,9 +68,5 @@ Console &Console::instance(Stream s) throw invalid_argument("Console::instance"); } -Console &cin = Console::instance(Console::CIN); -Console &cout = Console::instance(Console::COUT); -Console &cerr = Console::instance(Console::CERR); - } // namespace IO } // namespace Msp diff --git a/source/io/console.h b/source/io/console.h index 1755659..fe777cc 100644 --- a/source/io/console.h +++ b/source/io/console.h @@ -65,9 +65,10 @@ public: static Console &instance(Stream); }; -MSPCORE_API extern Console &cin; -MSPCORE_API extern Console &cout; -MSPCORE_API extern Console &cerr; +// TODO make these inline instead of static when upgrading to C++17. +static Console &cin = Console::instance(Console::CIN); +static Console &cout = Console::instance(Console::COUT); +static Console &cerr = Console::instance(Console::CERR); } // namespace IO } // namespace Msp -- 2.43.0 From 96c28280b6b97198d7411e1f03222f6ce889b2a3 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Tue, 3 Jan 2023 18:07:33 +0200 Subject: [PATCH 13/16] Move accessors of static data members to .cpp files Importing data items directly is tricky on MSVC, so better to hide them behind functions. --- source/core/application.cpp | 15 +++++++++++++++ source/core/application.h | 6 +++--- source/debug/errorreporter.cpp | 5 +++++ source/debug/errorreporter.h | 2 +- 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/source/core/application.cpp b/source/core/application.cpp index 1b77a7c..c214a06 100644 --- a/source/core/application.cpp +++ b/source/core/application.cpp @@ -118,6 +118,21 @@ void Application::set_startup_info(const char *argv0, void *data) _data = data; } +void *Application::get_data() +{ + return _data; +} + +const char *Application::get_argv0() +{ + return _argv0; +} + +const std::string &Application::get_name() +{ + return _name; +} + int Application::main() { done = false; diff --git a/source/core/application.h b/source/core/application.h index 2a1cc05..d5a571a 100644 --- a/source/core/application.h +++ b/source/core/application.h @@ -54,9 +54,9 @@ public: Application::run(). */ static void set_startup_info(const char *, void *); - static void *get_data() { return _data; } - static const char *get_argv0() { return _argv0; } - static const std::string &get_name() { return _name; } + static void *get_data(); + static const char *get_argv0(); + static const std::string &get_name(); protected: /** Default main loop. Calls tick() repeatedly until exit() is called. A diff --git a/source/debug/errorreporter.cpp b/source/debug/errorreporter.cpp index edfa002..6591c03 100644 --- a/source/debug/errorreporter.cpp +++ b/source/debug/errorreporter.cpp @@ -16,5 +16,10 @@ ErrorReporter::~ErrorReporter() _current = _prev; } +const ErrorReporter *ErrorReporter::get_current() +{ + return _current; +} + } // namespace Debug } // namespace Msp diff --git a/source/debug/errorreporter.h b/source/debug/errorreporter.h index ce14c63..b702b7c 100644 --- a/source/debug/errorreporter.h +++ b/source/debug/errorreporter.h @@ -20,7 +20,7 @@ protected: public: virtual ~ErrorReporter(); - static const ErrorReporter *get_current() { return _current; } + static const ErrorReporter *get_current(); virtual bool report_uncaught_exception(const std::exception &) const = 0; }; -- 2.43.0 From 18ea2a132fa7eb5b92080c4d9d973415331f2373 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Wed, 4 Jan 2023 13:04:49 +0200 Subject: [PATCH 14/16] Update .gitignore to include build products on Windows --- .gitignore | 16 +++++++++------- tests/.gitignore | 4 ++++ 2 files changed, 13 insertions(+), 7 deletions(-) create mode 100644 tests/.gitignore diff --git a/.gitignore b/.gitignore index 20ad67d..17d6cb8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,16 @@ .config temp /grep -/libmspcore.a -/libmspcore.so -/libmspcore.dylib +/grep.* +/libmspcore.* /ls -/mspcore.pc +/ls.* +/mspcore.* +/mspcore-* +/mspcore_static.* /syncdir -/tests/consoletest -/tests/test -/tests/test.txt +/syncdir.* /transcode +/transcode.* /z +/z.* diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 0000000..c551524 --- /dev/null +++ b/tests/.gitignore @@ -0,0 +1,4 @@ +/consoletest +/consoletest.* +/test +/test.* -- 2.43.0 From 83fcabb1fc1acff5d115f07253f801fc3f7cca9a Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Thu, 1 Jun 2023 09:26:48 +0300 Subject: [PATCH 15/16] Add a helper function for clearing a Variant --- source/core/variant.h | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/source/core/variant.h b/source/core/variant.h index c0b0aeb..fccf891 100644 --- a/source/core/variant.h +++ b/source/core/variant.h @@ -38,13 +38,15 @@ public: template Variant(const T &v) { assign(v); } Variant(const Variant &v) { copy_from(v); } - ~Variant() { if(funcs) funcs->destroy(storage); } + ~Variant() { clear(); } template Variant &operator=(const T &v) { assign(v); return *this; } Variant &operator=(const Variant &v) { if(&v!=this) copy_from(v); return *this; } + void clear(); + private: template void assign(const T &); @@ -133,23 +135,25 @@ private: }; -template -inline void Variant::assign(const T &v) +inline void Variant::clear() { if(funcs) funcs->destroy(storage); + funcs = nullptr; +} +template +inline void Variant::assign(const T &v) +{ + clear(); funcs = get_functions::type>(); create(storage, v); } inline void Variant::copy_from(const Variant &v) { - if(funcs) - funcs->destroy(storage); - - funcs = v.funcs; - if(funcs) + clear(); + if((funcs = v.funcs)) funcs->clone(storage, v.storage); } -- 2.43.0 From 68d54a837efb1aa8ed41008eee0d93118c154238 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Thu, 1 Jun 2023 10:17:56 +0300 Subject: [PATCH 16/16] Add move semantics to Variant --- source/core/variant.h | 48 ++++++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/source/core/variant.h b/source/core/variant.h index fccf891..5cb1b93 100644 --- a/source/core/variant.h +++ b/source/core/variant.h @@ -26,32 +26,39 @@ public: const std::type_info &(*get_type)(); bool (*compare)(const char *, const char *); void (*clone)(char *, const char *); + void (*move)(char *, char *); void (*destroy)(char *); }; private: + template + using EnableNotVariant = typename std::enable_if::type>::type, Variant>::value>::type; + const Functions *funcs = nullptr; alignas(void *) char storage[INTERNAL_SIZE]; public: Variant() = default; - template - Variant(const T &v) { assign(v); } + template> + Variant(T &&v) { assign(std::forward(v)); } Variant(const Variant &v) { copy_from(v); } + Variant(Variant &&v) { move_from(std::move(v)); } ~Variant() { clear(); } - template - Variant &operator=(const T &v) { assign(v); return *this; } + template> + Variant &operator=(T &&v) { assign(std::forward(v)); return *this; } Variant &operator=(const Variant &v) { if(&v!=this) copy_from(v); return *this; } + Variant &operator=(Variant &&v) { if(&v!=this) move_from(std::move(v)); return *this; } void clear(); private: template - void assign(const T &); + void assign(T &&); void copy_from(const Variant &); + void move_from(Variant &&); template T &get(); @@ -98,12 +105,12 @@ private: static const std::type_info &get_type() { return typeid(T); } template - static EnableSmall create(char *s, const T &v) - { new(s) T(v); } + static EnableSmall create(char *s, T &&v) + { new(s) typename std::remove_reference::type(std::forward(v)); } template - static EnableLarge create(char *s, const T &v) - { *reinterpret_cast(s) = new T(v); } + static EnableLarge create(char *s, T &&v) + { using V = typename std::remove_reference::type; *reinterpret_cast(s) = new V(std::forward(v)); } template static typename std::enable_if::value, bool>::type compare(const char *, const char *) @@ -125,6 +132,14 @@ private: static EnableLarge clone(char *s, const char *v) { *reinterpret_cast(s) = new T(**reinterpret_cast(v)); } + template + static EnableSmall move(char *s, char *v) + { new(s) T(std::move(*reinterpret_cast(v))); } + + template + static EnableLarge move(char *s, char *v) + { T *&p = *reinterpret_cast(v); *reinterpret_cast(s) = p; p = nullptr; } + template static EnableSmall destroy(char *s) { reinterpret_cast(s)->~T(); } @@ -143,11 +158,11 @@ inline void Variant::clear() } template -inline void Variant::assign(const T &v) +inline void Variant::assign(T &&v) { clear(); - funcs = get_functions::type>(); - create(storage, v); + funcs = get_functions::type>::type>(); + create(storage, std::forward(v)); } inline void Variant::copy_from(const Variant &v) @@ -157,6 +172,14 @@ inline void Variant::copy_from(const Variant &v) funcs->clone(storage, v.storage); } +inline void Variant::move_from(Variant &&v) +{ + clear(); + if((funcs = v.funcs)) + funcs->move(storage, v.storage); + v.clear(); +} + template inline T &Variant::get() { @@ -187,6 +210,7 @@ inline const Variant::Functions *Variant::get_functions() &get_type, &compare, &clone, + &move, &destroy }; return &funcs; -- 2.43.0