]> git.tdb.fi Git - libs/core.git/commitdiff
Add move semantics to Variant master
authorMikko Rasa <tdb@tdb.fi>
Thu, 1 Jun 2023 07:17:56 +0000 (10:17 +0300)
committerMikko Rasa <tdb@tdb.fi>
Thu, 1 Jun 2023 07:17:56 +0000 (10:17 +0300)
142 files changed:
.gitignore
source/core/algorithm.h
source/core/android/main.cpp
source/core/application.cpp
source/core/application.h
source/core/environ.h
source/core/except.h [new file with mode: 0644]
source/core/getopt.h
source/core/maputils.h
source/core/module.h
source/core/mspcore_api.h [new file with mode: 0644]
source/core/mutex.h
source/core/noncopyable.h
source/core/osx/main.cpp
source/core/process.cpp
source/core/process.h
source/core/refptr.h
source/core/semaphore.h
source/core/systemerror.h
source/core/thread.cpp
source/core/thread.h
source/core/thread_private.h
source/core/unix/main.cpp
source/core/unix/process.cpp
source/core/variant.h
source/core/windows/environ.cpp
source/core/windows/main.cpp
source/core/windows/module_platform.h
source/core/windows/mutex.cpp
source/core/windows/mutex_platform.h
source/core/windows/process.cpp
source/core/windows/process_platform.h
source/core/windows/semaphore.cpp
source/core/windows/systemerror.cpp
source/core/windows/thread.cpp
source/core/windows/thread_platform.h
source/core/windows/winapi.h [new file with mode: 0644]
source/debug/backtrace.h
source/debug/debugapi.cpp [new file with mode: 0644]
source/debug/debugapi.h [new file with mode: 0644]
source/debug/demangle.h
source/debug/errorreporter.cpp
source/debug/errorreporter.h
source/debug/exceptiontrace.h
source/debug/profiler.h
source/debug/profilingscope.h
source/fs/dir.cpp
source/fs/dir.h
source/fs/filemonitor.cpp
source/fs/filemonitor.h
source/fs/osx/dir_location.cpp
source/fs/path.cpp
source/fs/path.h
source/fs/redirectedpath.h
source/fs/stat.h
source/fs/unix/dir_location.cpp
source/fs/utils.h
source/fs/windows/dir.cpp
source/fs/windows/dir_location.cpp
source/fs/windows/filemonitor.cpp
source/fs/windows/stat.cpp
source/fs/windows/stat_platform.h
source/fs/windows/utils.cpp
source/io/asset.cpp
source/io/asset.h
source/io/base.h
source/io/buffered.cpp
source/io/buffered.h
source/io/console.cpp
source/io/console.h
source/io/eventdispatcher.cpp
source/io/eventdispatcher.h
source/io/eventobject.h
source/io/eventreader.h
source/io/file.cpp
source/io/file.h
source/io/handle.h
source/io/memory.cpp
source/io/memory.h
source/io/mode.h
source/io/pipe.h
source/io/poll.cpp
source/io/poll.h
source/io/seekable.h
source/io/serial.h
source/io/slice.cpp
source/io/slice.h
source/io/unix/eventreader.cpp
source/io/unix/poll.cpp
source/io/unix/seekable.cpp
source/io/unix/serial.cpp
source/io/utils.h
source/io/windows/console.cpp
source/io/windows/eventreader.cpp
source/io/windows/handle.cpp
source/io/windows/handle_platform.h
source/io/windows/poll.cpp
source/io/windows/poll_platform.h
source/io/windows/seekable.cpp
source/io/windows/serial.cpp
source/io/windows/serial_platform.h
source/io/zlibcompressed.cpp
source/io/zlibcompressed.h
source/stringcodec/ascii.h
source/stringcodec/codec.cpp
source/stringcodec/codec.h
source/stringcodec/codecutils.h
source/stringcodec/except.h
source/stringcodec/iso2022jp.cpp
source/stringcodec/iso2022jp.h
source/stringcodec/iso646fi.h
source/stringcodec/iso88591.h
source/stringcodec/iso885915.h
source/stringcodec/jisx0201.h
source/stringcodec/jisx0208.h
source/stringcodec/utf16.h
source/stringcodec/utf8.h
source/stringcodec/windows1252.h
source/strings/fmt.h
source/strings/format.h
source/strings/glob.h
source/strings/lexicalcast.cpp
source/strings/lexicalcast.h
source/strings/regex.cpp
source/strings/regex.h
source/strings/regmatch.h
source/strings/utils.cpp
source/strings/utils.h
source/time/datetime.h
source/time/timedelta.cpp
source/time/timedelta.h
source/time/timer.cpp
source/time/timer.h
source/time/timestamp.h
source/time/timezone.h
source/time/utils.h
source/time/windows/rawtime_platform.h
source/time/windows/timezone.cpp
source/time/windows/utils.cpp
tests/.gitignore [new file with mode: 0644]
tests/path.cpp
tests/variant.cpp

index 20ad67dd8f6bc0bf4e3ff1502007525fc7f69940..17d6cb8e4860226fd59020f8682c1393ae3eac54 100644 (file)
@@ -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.*
index 51c2369d623b58790f4ca556018d0162cb96a185..43bbaeeb2c00ace3199beae6b1af8052cd0bfb51 100644 (file)
@@ -2,6 +2,7 @@
 #define MSP_CORE_ALGORITHM_H_
 
 #include <algorithm>
+#include <functional>
 
 namespace Msp {
 
@@ -29,6 +30,20 @@ inline typename Container::const_iterator find_if(const Container &cont, Predica
        return std::find_if(cont.begin(), cont.end(), pred);
 }
 
+template<typename T>
+struct ValueMatch
+{
+       const T &value;
+
+       bool operator()(const T &v) { return v==value; }
+};
+
+template<typename Container, typename T>
+inline bool any_equals(Container &cont, const T &value)
+{
+       return std::any_of(cont.begin(), cont.end(), ValueMatch<T>{value});
+}
+
 template<typename Container, typename T>
 inline typename Container::iterator lower_bound(Container &cont, const T &value)
 {
@@ -107,33 +122,32 @@ struct MemberMatch
        const T &value;
        T C::*mem_ptr;
 
-       MemberMatch(const T &v, T C::*p): value(v), mem_ptr(p) { }
-
        bool operator()(const C &obj) { return obj.*mem_ptr==value; }
 };
 
 template<typename Container, typename T>
 inline typename Container::iterator find_member(Container &cont, const T &value, T Container::value_type::*mp)
 {
-       return find_if(cont, MemberMatch<typename Container::value_type, T>(value, mp));
+       return find_if(cont, MemberMatch<typename Container::value_type, T>{ value, mp });
 }
 
 template<typename Container, typename T>
 inline typename Container::const_iterator find_member(const Container &cont, const T &value, T Container::value_type::*mp)
 {
-       return find_if(cont, MemberMatch<typename Container::value_type, T>(value, mp));
+       return find_if(cont, MemberMatch<typename Container::value_type, T>{ value, mp });
 }
 
-template<typename C, typename T>
+template<typename C, typename T, typename P=std::less<T>>
 struct MemberCompare
 {
        T C::*mem_ptr;
+       P pred;
 
        MemberCompare(T C::*p): mem_ptr(p) { }
 
-       bool operator()(const C &obj, const T &v) { return obj.*mem_ptr<v; }
-       bool operator()(const T &v, const C &obj) { return v<obj.*mem_ptr; }
-       bool operator()(const C &obj1, const C &obj2) { return obj1.*mem_ptr<obj2.*mem_ptr; }
+       bool operator()(const C &obj, const T &v) { return pred(obj.*mem_ptr, v); }
+       bool operator()(const T &v, const C &obj) { return pred(v, obj.*mem_ptr); }
+       bool operator()(const C &obj1, const C &obj2) { return pred(obj1.*mem_ptr, obj2.*mem_ptr); }
 };
 
 template<typename Container, typename T>
index ff811c19dd4172ba51c98953b76f1976bb3cc8ac..d6ad41525820c20acc283301d309e889bbea1a3e 100644 (file)
@@ -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)
index 8447eed669d2b8f58c9b078b547b1543b0bab27f..c214a06316598b54ed59403493df366a60ca568f 100644 (file)
@@ -9,6 +9,7 @@
 #include <msp/io/print.h>
 #include <msp/strings/utils.h>
 #include "application.h"
+#include "except.h"
 #include "getopt.h"
 
 using namespace std;
@@ -24,7 +25,7 @@ void *Application::_data = nullptr;
 Application::Application(const string &n)
 {
        if(_app)
-               throw logic_error("instance already exists");
+               throw already_called("Application::Application");
 
        if(!n.empty())
                _name = n;
@@ -94,7 +95,7 @@ int Application::run(int argc, char **argv, void *data, void (*created_callback)
 void Application::set_startup_info(const char *argv0, void *data)
 {
        if(_argv0)
-               throw logic_error("startup info already set");
+               throw already_called("Application::set_startup_info");
 
        static FS::Path exe;
 
@@ -117,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;
@@ -146,7 +162,7 @@ void Application::_sighandler(int s)
 Application::Starter::Starter()
 {
        if(_starter)
-               throw logic_error("Can't create more than one Starter instance");
+               throw already_called("Application::Starter::Starter");
 
        _starter = this;
 }
index 972f3b73b1f8d9767e1f72bcd4ccdf6529415a47..d5a571a28a9f73306dffae3e99b470e39a2fcb47 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <stdexcept>
 #include <string>
+#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();
@@ -53,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
index 67fde05881651f467a87fbb4481f167ffea5aa55..7fbca16a126b406d68a9ffb9f6775a12caf0d943 100644 (file)
@@ -2,12 +2,13 @@
 #define ENVIRON_H_
 
 #include <string>
+#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
new file mode 100644 (file)
index 0000000..1673ff4
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef MSP_CORE_EXCEPT_H_
+#define MSP_CORE_EXCEPT_H_
+
+#include <stdexcept>
+#include "mspcore_api.h"
+
+namespace Msp {
+
+class MSPCORE_API invalid_state: public std::logic_error
+{
+public:
+       invalid_state(const std::string &w): logic_error(w) { }
+};
+
+
+class MSPCORE_API already_called: public invalid_state
+{
+public:
+       already_called(const std::string &w): invalid_state(w) { }
+};
+
+
+class MSPCORE_API unsupported: public std::logic_error
+{
+public:
+       unsupported(const std::string &w): logic_error(w) { }
+};
+
+
+class MSPCORE_API internal_error: public std::logic_error
+{
+public:
+       internal_error(const std::string &w): logic_error(w) { }
+};
+
+} // namespace Msp;
+
+#endif
index 575184f3400b2699cf3ba078a90633550ffd9e6d..59c810c5e4a5ff4182cd42d9736f8af9d708eae9 100644 (file)
@@ -6,20 +6,20 @@
 #include <string>
 #include <vector>
 #include <msp/strings/lexicalcast.h>
+#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;
 
 public:
        usage_error(const std::string &w, const std::string &h = std::string()): std::runtime_error(w), m_help(h) { }
-       ~usage_error() throw() override = default;
 
-       const char *help() const throw() { return m_help.c_str(); }
+       const char *help() const noexcept { return m_help.c_str(); }
 };
 
 
@@ -59,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
@@ -69,7 +69,7 @@ public:
                REQUIRED_ARG
        };
 
-       class Option
+       class MSPCORE_API Option
        {
        protected:
                Option() = default;
@@ -89,7 +89,7 @@ public:
                virtual unsigned get_seen_count() const = 0;
        };
 
-       class Argument
+       class MSPCORE_API Argument
        {
        protected:
                Argument() = default;
index 26b72cc29e7b1891e96e06552ebb67645f679ebb..9a72d4d30f30e0339bec305b5589dc14e73be9d1 100644 (file)
@@ -4,6 +4,7 @@
 #include <stdexcept>
 #include <typeinfo>
 #include <msp/strings/lexicalcast.h>
+#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<typename T>
index 4b1e3e8dd983b6e306418c299d5d78b633ee187a..64d761f363eb426b3c7c28a7e13f888617874f94 100644 (file)
@@ -2,11 +2,12 @@
 #define MSP_CORE_MODULE_H_
 
 #include <string>
+#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 (file)
index 0000000..eed6bcc
--- /dev/null
@@ -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
index 6582074e182c988c3d813671b3cb92668c27ceeb..a48f58c89d3de88831047dd27c51aa13dec7c91a 100644 (file)
@@ -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;
index c948c57c7ab6b21e29e6f8036d7ff0f374bf21bd..78f9e66c24d1ee15fc89f118c52bde404738eef0 100644 (file)
@@ -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;
index 4bb81c83c41c4380857e6f0d7b49497bb2fae65b..55d4a304ce08b1f91bef2fe9fce2b12146c41e4a 100644 (file)
@@ -1,7 +1,8 @@
 #include <cstring>
 #include "application.h"
+#include "mspcore_api.h"
 
-int main(int argc, char **argv)
+MSPCORE_API int main(int argc, char **argv)
 {
        void *data = nullptr;
 
index 43b7384a5a3d66d49fd708e45d7cd274795f04ac..4c5ed4651164615fc67b1d8a7c7523856876a233 100644 (file)
@@ -1,4 +1,5 @@
 #include <msp/io/console.h>
+#include "except.h"
 #include "process.h"
 #include "process_private.h"
 
@@ -78,7 +79,7 @@ void Process::execute(const FS::Path &command, const Arguments &args)
 unsigned Process::get_exit_code() const
 {
        if(!finished)
-               throw logic_error("not finished");
+               throw invalid_state("not finished");
        return exit_code;
 }
 
index 0d7faa6c82f96c0e1eb413e582eab6c5a10ff4f4..ed997f853e143a52bbfd386cda1e32115c937255 100644 (file)
@@ -5,6 +5,7 @@
 #include <vector>
 #include <msp/fs/path.h>
 #include <msp/io/base.h>
+#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<std::string> Arguments;
index 79401dce5be40094a9f55212c0c3fb4abd8f7dc9..1a164c1a90eafe69d3eab755b971400ff1f3e275 100644 (file)
@@ -10,10 +10,8 @@ struct RefCounts
                KEEP = 1U<<(sizeof(unsigned)*8-1)
        };
 
-       unsigned count;
-       unsigned weak_count;
-
-       RefCounts(): count(0), weak_count(0) { }
+       unsigned count = 0;
+       unsigned weak_count = 0;
 };
 
 template<typename T>
index 28c3b3d72cb8f009fd4474cfa73ab586db1a1d02..f5042892a1825bf1650f16e8ad93f833790f90a3 100644 (file)
@@ -2,11 +2,12 @@
 #define MSP_CORE_SEMAPHORE_H_
 
 #include <msp/time/timedelta.h>
+#include "mspcore_api.h"
 #include "noncopyable.h"
 
 namespace Msp {
 
-class Semaphore: private NonCopyable
+class MSPCORE_API Semaphore: private NonCopyable
 {
 private:
        struct Private;
index c2387fad828b2de624ef502b58f6cd031a5c0666..cce3c5c7e6ad4f8662171d6adf735d841f574f72 100644 (file)
@@ -3,10 +3,11 @@
 
 #include <stdexcept>
 #include <string>
+#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;
@@ -14,9 +15,8 @@ private:
 public:
        system_error(const std::string &, int = -1);
        system_error(const std::string &, const std::string &);
-       ~system_error() throw() override = default;
 
-       int code() const throw() { return m_code; }
+       int code() const noexcept { return m_code; }
 
 private:
        static std::string get_message(int);
index e860d6758f9e048f070b67855e7d7810456e7c48..ad78d945cbd85e995d954ba6411964ccaa702421 100644 (file)
@@ -1,4 +1,4 @@
-#include <stdexcept>
+#include "except.h"
 #include "thread.h"
 #include "thread_private.h"
 
@@ -39,7 +39,7 @@ void Thread::kill()
 void Thread::launch()
 {
        if(_state>=RUNNING)
-               throw logic_error("already launched");
+               throw already_called("Thread::launch");
 
        platform_launch();
        _state = RUNNING;
@@ -51,7 +51,7 @@ ThreadReturn THREAD_CALL Thread::Private::main_wrapper(void *arg)
        thread->platform_setname();
        thread->main();
        thread->_state = FINISHED;
-       return nullptr;
+       return 0;
 }
 
 } // namespace Msp
index ef071cd43ffb070f8c2ea2646a514ac2f514f9a6..71acb22079f749520e86b8939965483218fdb773 100644 (file)
@@ -2,6 +2,7 @@
 #define MSP_CORE_THREAD_H_
 
 #include <string>
+#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;
index 3c3b341565d4b1dcd12e085d6a4506d9b2ee74de..f133d6025fcb41e4f30c8b9ed35e62edbd35991a 100644 (file)
@@ -8,9 +8,7 @@ namespace Msp {
 
 struct Thread::Private
 {
-       ThreadHandle handle;
-
-       Private(): handle(0) { }
+       ThreadHandle handle = 0;
 
        static ThreadReturn THREAD_CALL main_wrapper(void *);
 };
index 58c9fda45e812e362d9f0d18d29568db387cf068..010459f55aab1d4bb5c4e24b805520784fe2fbb8 100644 (file)
@@ -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);
 }
index 7370b70803f94bff6c24c57a3adb453f5ea6682a..ee0a36d3b783ea30383470f6c411f3a007c54bed 100644 (file)
@@ -4,6 +4,7 @@
 #include <msp/core/systemerror.h>
 #include <msp/fs/dir.h>
 #include <msp/io/console.h>
+#include "except.h"
 #include "process.h"
 #include "process_private.h"
 
@@ -12,7 +13,9 @@ using namespace std;
 namespace Msp {
 
 Process::~Process()
-{ }
+{
+       delete priv;
+}
 
 void Process::platform_get_self_info(Private &priv)
 {
@@ -70,7 +73,7 @@ void Process::execute(const string &command, bool path_search, const Arguments &
 bool Process::wait(bool block)
 {
        if(!running)
-               throw logic_error("not running");
+               throw invalid_state("not running");
 
        int status;
        int pid = waitpid(priv->info.pid, &status, (block ? 0 : WNOHANG));
index af204f2233f3c7759665a0f6b729bd52459d4326..5cb1b931ca403eab55a0ef38e9be86b3afa3d0c5 100644 (file)
 #include <type_traits>
 #include <typeinfo>
 #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 &);
-       ~type_mismatch() throw() override = default;
 };
 
 
-class Variant
+class MSPCORE_API 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 (*move)(char *, char *);
+               void (*destroy)(char *);
        };
 
+private:
        template<typename T>
-       struct Store: public StoreBase
-       {
-               T data;
+       using EnableNotVariant = typename std::enable_if<!std::is_same<typename std::remove_cv<typename std::remove_reference<T>::type>::type, Variant>::value>::type;
+
+       const Functions *funcs = nullptr;
+       alignas(void *) char storage[INTERNAL_SIZE];
+
+public:
+       Variant() = default;
+       template<typename T, typename = EnableNotVariant<T>>
+       Variant(T &&v) { assign(std::forward<T>(v)); }
+       Variant(const Variant &v) { copy_from(v); }
+       Variant(Variant &&v) { move_from(std::move(v)); }
+       ~Variant() { clear(); }
 
-               Store(const T &d): data(d) { }
+       template<typename T, typename = EnableNotVariant<T>>
+       Variant &operator=(T &&v) { assign(std::forward<T>(v)); return *this; }
 
-               const std::type_info &type_id() const override { return typeid(T); }
-               StoreBase *clone() const override { return new Store<T>(data); }
-               bool type_equals(const StoreBase &s) const override { return dynamic_cast<const Store<T> *>(&s); }
-               bool value_equals(const StoreBase &s) const override { return _value_equals<T>(s); }
+       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; }
 
-               template<typename U>
-               typename std::enable_if<IsEqualityComparable<U>::value, bool>::type _value_equals(const StoreBase &s) const
-               { const Store<T> *t = dynamic_cast<const Store<T> *>(&s); return (t && t->data==data); }
+       void clear();
 
-               template<typename U>
-               typename std::enable_if<!IsEqualityComparable<U>::value, bool>::type _value_equals(const StoreBase &) const
-               { return false; }
-       };
+private:
+       template<typename T>
+       void assign(T &&);
+
+       void copy_from(const Variant &);
+       void move_from(Variant &&);
 
-       StoreBase *store = nullptr;
+       template<typename T>
+       T &get();
 
 public:
-       Variant() = default;
        template<typename T>
-       Variant(const T &v): store(new Store<typename std::remove_cv<T>::type>(v)) { }
-       Variant(const Variant &v): store(v.store ? v.store->clone() : nullptr) { }
-       ~Variant() { delete store; }
+       T &value() { return get<T>(); }
 
        template<typename T>
-       Variant &operator=(const T &v)
-       {
-               delete store;
-               store = new Store<typename std::remove_cv<T>::type>(v);
-               return *this;
-       }
+       const T &value() const { return const_cast<Variant *>(this)->get<T>(); }
 
-       Variant &operator=(const Variant &v)
-       {
-               if(&v==this)
-                       return *this;
+       template<typename T>
+       bool has_type() const { return type_equals(funcs, get_functions<typename std::remove_cv<T>::type>()); }
+
+       bool has_same_type(const Variant &v) const { return type_equals(funcs, v.funcs); }
+
+       template<typename T>
+       DEPRECATED bool check_type() const { return has_type<T>(); }
+
+       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)); }
 
-               delete store;
-               store = (v.store ? v.store->clone() : nullptr);
-               return *this;
-       }
+       template<typename T>
+       operator T() const { return value<T>(); }
 
 private:
+       static bool type_equals(const Functions *, const Functions *);
+
        template<typename T>
-       Store<typename std::remove_cv<T>::type> *get_typed_store() const
-       {
-               typedef typename std::remove_cv<T>::type NCT;
-               Store<NCT> *s = dynamic_cast<Store<NCT> *>(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<typename T, typename U>
+       using EnableSmall = typename std::enable_if<is_small<T>(), U>::type;
+
+       template<typename T, typename U>
+       using EnableLarge = typename std::enable_if<!is_small<T>(), U>::type;
 
-public:
        template<typename T>
-       T &value()
-       {
-               return get_typed_store<T>()->data;
-       }
+       static const Functions *get_functions();
 
        template<typename T>
-       const T &value() const
-       {
-               return get_typed_store<T>()->data;
-       }
+       static const std::type_info &get_type() { return typeid(T); }
 
        template<typename T>
-       bool check_type() const
-       {
-               return dynamic_cast<Store<typename std::remove_cv<T>::type> *>(store);
-       }
+       static EnableSmall<T, void> create(char *s, T &&v)
+       { new(s) typename std::remove_reference<T>::type(std::forward<T>(v)); }
+
+       template<typename T>
+       static EnableLarge<T, void> create(char *s, T &&v)
+       { using V = typename std::remove_reference<T>::type; *reinterpret_cast<V **>(s) = new V(std::forward<T>(v)); }
+
+       template<typename T>
+       static typename std::enable_if<!IsEqualityComparable<T>::value, bool>::type compare(const char *, const char *)
+       { return false; }
+
+       template<typename T>
+       static typename std::enable_if<IsEqualityComparable<T>::value, EnableSmall<T, bool>>::type compare(const char *s1, const char *s2)
+       { return *reinterpret_cast<const T *>(s1)==*reinterpret_cast<const T *>(s2); }
+
+       template<typename T>
+       static typename std::enable_if<IsEqualityComparable<T>::value, EnableLarge<T, bool>>::type compare(const char *s1, const char *s2)
+       { return **reinterpret_cast<const T *const *>(s1)==**reinterpret_cast<const T *const *>(s2); }
+
+       template<typename T>
+       static EnableSmall<T, void> clone(char *s, const char *v)
+       { new(s) T(*reinterpret_cast<const T *>(v)); }
+
+       template<typename T>
+       static EnableLarge<T, void> clone(char *s, const char *v)
+       { *reinterpret_cast<T **>(s) = new T(**reinterpret_cast<const T *const *>(v)); }
 
-       bool check_same_type(const Variant &v) const
-       { return store && v.store && store->type_equals(*v.store); }
+       template<typename T>
+       static EnableSmall<T, void> move(char *s, char *v)
+       { new(s) T(std::move(*reinterpret_cast<T *>(v))); }
 
-       bool operator==(const Variant &v) const
-       { return store && v.store && store->value_equals(*v.store); }
+       template<typename T>
+       static EnableLarge<T, void> move(char *s, char *v)
+       { T *&p = *reinterpret_cast<T **>(v); *reinterpret_cast<T **>(s) = p; p = nullptr; }
 
-       bool operator!=(const Variant &v) const
-       { return !(operator==(v)); }
+       template<typename T>
+       static EnableSmall<T, void> destroy(char *s)
+       { reinterpret_cast<T *>(s)->~T(); }
 
        template<typename T>
-       operator T() const
-       { return value<T>(); }
+       static EnableLarge<T, void> destroy(char *s)
+       { delete *reinterpret_cast<T **>(s); }
 };
 
+
+inline void Variant::clear()
+{
+       if(funcs)
+               funcs->destroy(storage);
+       funcs = nullptr;
+}
+
+template<typename T>
+inline void Variant::assign(T &&v)
+{
+       clear();
+       funcs = get_functions<typename std::remove_cv<typename std::remove_reference<T>::type>::type>();
+       create(storage, std::forward<T>(v));
+}
+
+inline void Variant::copy_from(const Variant &v)
+{
+       clear();
+       if((funcs = v.funcs))
+               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<typename T>
+inline T &Variant::get()
+{
+       if(!has_type<T>())
+               throw type_mismatch(typeid(T), (funcs ? funcs->get_type() : typeid(void)));
+
+       if(sizeof(T)<=INTERNAL_SIZE)
+               return *reinterpret_cast<T *>(storage);
+       else
+               return **reinterpret_cast<T **>(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<typename T>
+inline const Variant::Functions *Variant::get_functions()
+{
+       static Functions funcs =
+       {
+               &get_type<T>,
+               &compare<T>,
+               &clone<T>,
+               &move<T>,
+               &destroy<T>
+       };
+       return &funcs;
+}
+
 } // namespace Msp
 
 #endif
index ff5c2b001dcb2691fb09871b1afc129882589a1b..7abf7e55044cf236b46c73ca387cb3e7d6580398 100644 (file)
@@ -3,7 +3,7 @@
 #include "mutex.h"
 
 #ifdef __GNUC__
-extern "C" errno_t getenv_s(size_t *, char *, size_t, const char *);
+extern "C" __declspec(dllimport) errno_t getenv_s(size_t *, char *, size_t, const char *);
 #endif
 
 using namespace std;
index 11df925692c55d50bdabc5d6d52a5e072e8cbdde..df17020977f83a800d0ca8daace76326bda09023 100644 (file)
@@ -1,12 +1,14 @@
-#include <windows.h>
+#include "winapi.h"
+#include <shellapi.h>
 #include <msp/stringcodec/utf16.h>
 #include <msp/stringcodec/utf8.h>
 #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);
 }
index 81dfd0fecf292ed0313c42711e54a341e162c7a2..eb0b633a4f8f9e86144da4efbf16ee033c232da6 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef MSP_CORE_MODULE_PLATFORM_H_
 #define MSP_CORE_MODULE_PLATFORM_H_
 
-#include <windows.h>
+#include "winapi.h"
 
 namespace Msp {
 
index e51fda407b8a9beead0b3ce35040697ed7e54bcf..6d3963521249102a08de75316cce25bd2ec7a398 100644 (file)
@@ -1,4 +1,4 @@
-#include <windows.h>
+#include "winapi.h"
 #include "mutex.h"
 #include "mutex_private.h"
 
index fae5e853dc16db8579d5c0f6d2b16556d9e8f79e..1d5c1c0ebe30cf63fd9afb3d11f327af878586c9 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef MSP_CORE_MUTEX_PLATFORM_H_
 #define MSP_CORE_MUTEX_PLATFORM_H_
 
-#include <windows.h>
+#include "winapi.h"
 
 namespace Msp {
 
index 3bd03fa3816dbefc3faa71726fa1632c5537cdcd..0eae33bdab07eb4169d441ff865ac23aadd28b30 100644 (file)
@@ -1,7 +1,8 @@
-#include <windows.h>
+#include "winapi.h"
 #include <msp/core/systemerror.h>
 #include <msp/io/handle_private.h>
 #include <msp/strings/utils.h>
+#include "except.h"
 #include "process.h"
 #include "process_private.h"
 
@@ -43,6 +44,7 @@ Process::~Process()
 {
        CloseHandle(priv->info.hProcess);
        CloseHandle(priv->info.hThread);
+       delete priv;
 }
 
 void Process::platform_get_self_info(Private &priv)
@@ -99,7 +101,7 @@ void Process::execute(const string &command, bool path_search, const Arguments &
 bool Process::wait(bool block)
 {
        if(!running)
-               throw logic_error("not running");
+               throw invalid_state("not running");
 
        DWORD ret = WaitForSingleObject(priv->info.hProcess, (block ? INFINITE : 0));
        if(ret==WAIT_FAILED)
index 4cb793ad947747090219e4648f075966b3c8ded3..d55678ecb87c6820e20f376ed4ea3a547022310b 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef MSP_CORE_PROCESS_PLATFORM_H_
 #define MSP_CORE_PROCESS_PLATFORM_H_
 
-#include <windows.h>
+#include "winapi.h"
 
 namespace Msp {
 
index c81f815a2ad4bbcb50897f1bb1a327fdd6ef1df5..e45e4b9f70f921c02166a79be99fdc5dd21e05ce 100644 (file)
@@ -1,4 +1,4 @@
-#include <windows.h>
+#include "winapi.h"
 #include <msp/core/systemerror.h>
 #include <msp/time/timedelta.h>
 #include "semaphore.h"
index 93aa7bd5e89fa63fd96c6b303a1ea6b5aa1ce51c..754c90b9c25f13c420210d2c8290b5a99eb69452 100644 (file)
@@ -1,4 +1,4 @@
-#include <windows.h>
+#include "winapi.h"
 #include <msp/strings/lexicalcast.h>
 #include "systemerror.h"
 
index 8890a70fb1cbd0eaff8cf32cdea008950c92e43b..3231896c7a7d7283c01f4d863a6cc9a05175ed08 100644 (file)
@@ -1,4 +1,4 @@
-#include <windows.h>
+#include "winapi.h"
 #include "thread.h"
 #include "thread_private.h"
 
index 50b1a5e4f4c1e331d0ac048a86afb9e7fb135d08..d88bd8bff032248c65a90f431b77bd73b5376321 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef MSP_CORE_THREAD_PLATFORM_H_
 #define MSP_CORE_THREAD_PLATFORM_H_
 
-#include <windows.h>
+#include "winapi.h"
 
 namespace Msp {
 
diff --git a/source/core/windows/winapi.h b/source/core/windows/winapi.h
new file mode 100644 (file)
index 0000000..dca0880
--- /dev/null
@@ -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 <windows.h>
+
+#endif
index 98aa4d8cdd9736291253cecf403b10d75bf43b2a..b8e06af27b9c400d1e6f3b741627a0e6e716ee04 100644 (file)
@@ -4,11 +4,12 @@
 #include <ostream>
 #include <string>
 #include <vector>
+#include <msp/core/mspcore_api.h>
 
 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.cpp b/source/debug/debugapi.cpp
new file mode 100644 (file)
index 0000000..8fafdd9
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef _WIN32
+#include <signal.h>
+#endif
+#include <msp/fs/utils.h>
+#include <msp/io/file.h>
+#include <msp/strings/format.h>
+#include <msp/strings/utils.h>
+#include "debugapi.h"
+
+using namespace std;
+
+namespace Msp {
+namespace Debug {
+
+DebuggerType check_debugger(bool force_recheck)
+{
+       static DebuggerType debugger = NONE;
+       static bool checked = false;
+
+       if(!checked || force_recheck)
+       {
+               checked = true;
+
+#ifndef _WIN32
+               unsigned tracer_pid = 0;
+               IO::BufferedFile status("/proc/self/status");
+               string line;
+               while(status.getline(line))
+                       if(!line.compare(0, 10, "TracerPid:"))
+                       {
+                               tracer_pid = lexical_cast<unsigned>(strip(line.substr(10)));
+                               break;
+                       }
+
+               if(tracer_pid)
+               {
+                       FS::Path tracer_cmd = FS::readlink(format("/proc/%d/exe", tracer_pid));
+                       if(FS::basename(tracer_cmd)=="gdb")
+                               debugger = GDB;
+                       else
+                               debugger = UNKNOWN;
+               }
+#endif
+       }
+
+       return debugger;
+}
+
+void debug_break()
+{
+#ifdef _WIN32
+       __debugbreak();
+#else
+       raise(SIGTRAP);
+#endif
+}
+
+} // namespace Debug
+} // namespace Msp
diff --git a/source/debug/debugapi.h b/source/debug/debugapi.h
new file mode 100644 (file)
index 0000000..0f1a501
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef MSP_DEBUG_DEBUGAPI_H_
+#define MSP_DEBUG_DEBUGAPI_H_
+
+#include <msp/core/mspcore_api.h>
+
+namespace Msp {
+namespace Debug {
+
+enum DebuggerType
+{
+       NONE,
+       GDB,
+       UNKNOWN,
+};
+
+MSPCORE_API DebuggerType check_debugger(bool = false);
+MSPCORE_API void debug_break();
+
+} // namespace Debug
+} // namespace Msp
+
+#endif
index 213a348f5f2d280d22277ab3cfb91af50f121746..22334354034759f78344dbc3bf5543e3ef1af006 100644 (file)
@@ -2,11 +2,12 @@
 #define MSP_DEBUG_DEMANGLE_H_
 
 #include <string>
+#include <msp/core/mspcore_api.h>
 
 namespace Msp {
 namespace Debug {
 
-std::string demangle(const std::string &);
+MSPCORE_API std::string demangle(const std::string &);
 
 } // namespace Debug
 } // namespace Msp
index edfa0026d58a6b92c08f43c5138a3ccc4aca610f..6591c037ac68da524a76b740779c35549e5f7114 100644 (file)
@@ -16,5 +16,10 @@ ErrorReporter::~ErrorReporter()
        _current = _prev;
 }
 
+const ErrorReporter *ErrorReporter::get_current()
+{
+       return _current;
+}
+
 } // namespace Debug
 } // namespace Msp
index 9a60f85c0f41b8bbdc4244734302e0c47fabe1c3..b702b7cfb10138a92e07c709b6058999f841481d 100644 (file)
@@ -2,12 +2,13 @@
 #define MSP_DEBUG_ERRORREPORTER_H_
 
 #include <stdexcept>
+#include <msp/core/mspcore_api.h>
 #include <msp/core/noncopyable.h>
 
 namespace Msp {
 namespace Debug {
 
-class ErrorReporter: private NonCopyable
+class MSPCORE_API ErrorReporter: private NonCopyable
 {
 private:
        ErrorReporter *_prev = nullptr;
@@ -19,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;
 };
index 52664b6dbdd082731d9c681bc48b7e3cdecba471..0786c780013aa3a8447b857ce7c7c69dc2543a75 100644 (file)
@@ -1,13 +1,15 @@
 #ifndef MSP_DEBUG_EXCEPTIONTRACE_H_
 #define MSP_DEBUG_EXCEPTIONTRACE_H_
 
+#include <msp/core/mspcore_api.h>
+
 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
index 22d2c9a82c9fcb7df8545d16e7545d9ebb0720a3..7d98dc7556e7316fe3e69257877a4ba8c8c6a018 100644 (file)
@@ -4,6 +4,7 @@
 #include <map>
 #include <string>
 #include <vector>
+#include <msp/core/mspcore_api.h>
 #include <msp/core/noncopyable.h>
 #include <msp/time/timedelta.h>
 #include <msp/time/timestamp.h>
@@ -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;
index 586efa31d53fbf062a175ae7a44fb1e31897ac3f..7b8bcf375108c5a42ff80f98780571c2ab2bfda5 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef MSP_DEBUG_PROFILINGSCOPE_H_
 #define MSP_DEBUG_PROFILINGSCOPE_H_
 
+#include <msp/core/mspcore_api.h>
 #include <msp/core/noncopyable.h>
 #include <msp/time/timestamp.h>
 #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;
index 066d88bc1fd2c461bae39b5e3700d756f2aaa5b6..0f617e58717b984db918eb51e714a8534c01a410 100644 (file)
@@ -1,5 +1,6 @@
 #include <msp/core/application.h>
 #include <msp/core/environ.h>
+#include <msp/core/except.h>
 #include <msp/strings/utils.h>
 #include "dir.h"
 #include "path.h"
@@ -109,7 +110,7 @@ Path get_sys_conf_dir()
 {
        const char *argv0 = Application::get_argv0();
        if(!argv0)
-               throw logic_error("no startup command");
+               throw invalid_state("no startup command");
 
        Path dir = get_bin_dir(argv0);
 
@@ -128,7 +129,7 @@ Path get_sys_data_dir()
 {
        const char *argv0 = Application::get_argv0();
        if(!argv0)
-               throw logic_error("no startup command");
+               throw invalid_state("no startup command");
 
        Path dir = get_bin_dir(argv0);
 
@@ -144,7 +145,7 @@ Path get_sys_lib_dir()
 {
        const char *argv0 = Application::get_argv0();
        if(!argv0)
-               throw logic_error("no startup command");
+               throw invalid_state("no startup command");
 
        Path dir = get_bin_dir(argv0);
 
index bef89c6d72e1e160072be098450c8641bb0ec00a..960be2e00c0559e258c6f2edbd7e3863e3f6cb84 100644 (file)
@@ -4,12 +4,13 @@
 #include <stdexcept>
 #include <string>
 #include <vector>
+#include <msp/core/mspcore_api.h>
 #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<std::string> list_files(const Path &path);
+MSPCORE_API std::vector<std::string> list_files(const Path &path);
 
 /// Lists the contents of a directory, filtered with a regex
-std::vector<std::string> list_filtered(const Path &path, const std::string &filter);
+MSPCORE_API std::vector<std::string> 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<Path> &);
+MSPCORE_API Path path_lookup(const std::string &, const std::vector<Path> &);
 
 /** 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
index 5ab3f49197a0169c18b0df5a786be1064df8f94f..5ff6392a352fe4e06af3e97f0371d1b19d67c10b 100644 (file)
@@ -1,4 +1,5 @@
 #include <msp/core/algorithm.h>
+#include <msp/core/except.h>
 #include "filemonitor.h"
 #include "filemonitor_platform.h"
 
@@ -19,7 +20,7 @@ FileMonitor::~FileMonitor()
 void FileMonitor::use_event_dispatcher(IO::EventDispatcher &ed)
 {
        if(event_disp)
-               throw logic_error("event_disp!=nullptr");
+               throw already_called("FileMonitor::use_event_dispatcher");
 
        event_disp = &ed;
        platform_use_event_dispatcher();
index 220b9697594178d0ad73489d662b08a88d8d77bf..3ce5d79db2dc991ac562e0bb30f44df5cf11dee7 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef FILEMONITOR_H_
 #define FILEMONITOR_H_
 
+#include <msp/core/mspcore_api.h>
 #include <msp/core/noncopyable.h>
 #include <msp/fs/path.h>
 #include <msp/io/eventdispatcher.h>
@@ -8,7 +9,7 @@
 namespace Msp {
 namespace FS {
 
-class FileMonitor: NonCopyable
+class MSPCORE_API FileMonitor: NonCopyable
 {
 private:
        struct Private;
index b58b971961e25cdb83db4abe9f51e31c917c0fef..13aa3d2d500fd167153f16b4811f575004e517af 100644 (file)
@@ -1,5 +1,6 @@
 #include <msp/core/application.h>
 #include <msp/core/environ.h>
+#include <msp/core/except.h>
 #include "dir.h"
 
 using namespace std;
@@ -28,7 +29,7 @@ Path get_user_data_dir()
 {
        const string &appname = Application::get_name();
        if(appname.empty())
-               throw logic_error("no application name");
+               throw invalid_state("no application name");
 
        char buf[1024];
        unsigned len = get_application_support_dir(buf, sizeof(buf));
index 0e86600453be225bcb647ff699f3cb0b5f20649b..1181b923c1054f894c5f0e188119e067c6508566 100644 (file)
@@ -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();
                        }
index 30fe683eabafff9f64b8841f8706ea4cde8be341..1b15047cc528ece01f9d2061fcd0fd3740dedfef 100644 (file)
@@ -4,6 +4,7 @@
 #include <ostream>
 #include <string>
 #include <vector>
+#include <msp/core/mspcore_api.h>
 
 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<std::string::size_type> PositionArray;
 
 public:
-       class Iterator
+       class MSPCORE_API Iterator
        {
        public:
                typedef PositionArray::difference_type difference_type;
index 50a3609bd36eb7e163826707ddf7a0bc50c0a0df..95888f7ee8e9ac96c03896b48e99f98ff2395411 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef MSP_FS_REDIRECTEDPATH_H_
 #define MSP_FS_REDIRECTEDPATH_H_
 
+#include <msp/core/mspcore_api.h>
 #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;
index c32e8798162787b40b47a4ff41d9c7603689e806..fd6a2f75ba6092e7f72181b95b7c8fb332428fe8 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <cstdint>
 #include <string>
+#include <msp/core/mspcore_api.h>
 #include <msp/time/timestamp.h>
 #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)
index 73825875fd4df979ae1b7c5fff619af6982fb133..68d82a27f968c37d14c1e2c42aafe1814e679570 100644 (file)
@@ -1,5 +1,6 @@
 #include <msp/core/application.h>
 #include <msp/core/environ.h>
+#include <msp/core/except.h>
 #include "dir.h"
 
 using namespace std;
@@ -19,7 +20,7 @@ Path get_user_data_dir()
 {
        const string &appname = Application::get_name();
        if(appname.empty())
-               throw logic_error("no application name");
+               throw invalid_state("no application name");
 
        return get_home_dir()/("."+appname);
 }
index e518d35cf225da8e38692e5b09dffe2d21793af5..9c4bb5ca47fdeed1035a341d5e06e2bac54b00f8 100644 (file)
@@ -1,50 +1,51 @@
 #ifndef MSP_FS_UTILS_H_
 #define MSP_FS_UTILS_H_
 
+#include <msp/core/mspcore_api.h>
 #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
index fde0200d029708eccd7476911e5d8dd3fa18c285..2ba2f1e110f8e8f3aaf7dcbec38d50f052160578 100644 (file)
@@ -1,4 +1,4 @@
-#include <windows.h>
+#include <msp/core/winapi.h>
 #include <msp/core/mutex.h>
 #include <msp/core/systemerror.h>
 #include <msp/strings/regex.h>
index 4f9b8f643b723b9317af370a84dbc8b7e6529b8e..85c5c2fa30d1f6809c359cfb7f919605d83fedfb 100644 (file)
@@ -1,5 +1,6 @@
 #include <shlobj.h>
 #include <msp/core/application.h>
+#include <msp/core/except.h>
 #include "dir.h"
 
 using namespace std;
@@ -19,7 +20,7 @@ Path get_user_data_dir()
 {
        const string &appname = Application::get_name();
        if(appname.empty())
-               throw logic_error("no application name");
+               throw invalid_state("no application name");
 
        char datadir[MAX_PATH];
        if(SHGetFolderPath(nullptr, CSIDL_LOCAL_APPDATA, nullptr, 0, datadir)==S_OK)
index 3ed65b188aeb0d043e46d9a1a609572eaa2de055..63336e3fa3782680357e342dddda7e47e13cdb6b 100644 (file)
@@ -1,3 +1,4 @@
+#include <msp/core/except.h>
 #include "filemonitor.h"
 #include "filemonitor_platform.h"
 
@@ -21,7 +22,7 @@ void FileMonitor::tick()
 
 FileMonitor::Private::Private(FileMonitor &)
 {
-       throw logic_error("not implemented");
+       throw unsupported("FileMonitor");
 }
 
 } // namespace FS
index 8331e6068c5e28606226e0a26e2d456591c9920c..ee794767f7eaded5f9f7071e6434d07d4fc64e7a 100644 (file)
@@ -1,4 +1,4 @@
-#include <windows.h>
+#include <msp/core/winapi.h>
 #include <aclapi.h>
 #include <msp/core/systemerror.h>
 #include <msp/strings/format.h>
index 6440aca8bae7d06bf298493077cebea2f5b7dc26..89961c6794bf598d48079223153aac40acf2eb95 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef MSP_FS_STAT_PLATFORM_H_
 #define MSP_FS_STAT_PLATFORM_H_
 
-#include <windows.h>
+#include <msp/core/winapi.h>
 
 namespace Msp {
 namespace FS {
index ca9e7aa0f11f333f6710b93f48c1f86b3e62e7f9..a1c25136908d11a3248084fdce59f794490a5dcf 100644 (file)
@@ -1,4 +1,5 @@
-#include <windows.h>
+#include <msp/core/winapi.h>
+#include <msp/core/except.h>
 #include <msp/core/systemerror.h>
 #include "dir.h"
 #include "utils.h"
@@ -11,7 +12,7 @@ namespace FS {
 Path readlink(const Path &link)
 {
        (void)link;
-       throw logic_error("no symbolic links on win32");
+       throw unsupported("readlink");
 }
 
 Path realpath(const Path &path)
index 9284f97107f9e19a2eacfb121ddcd43c0c09e3b3..d605ff49573cb2e329513ea2d722023945de302b 100644 (file)
@@ -1,3 +1,4 @@
+#include <msp/core/except.h>
 #include "asset.h"
 
 using namespace std;
@@ -7,12 +8,12 @@ namespace IO {
 
 void Asset::set_block(bool)
 {
-       throw logic_error("Asset::set_block");
+       throw unsupported("Asset::set_block");
 }
 
 void Asset::set_inherit(bool)
 {
-       throw logic_error("Asset::set_inherit");
+       throw unsupported("Asset::set_inherit");
 }
 
 size_t Asset::do_write(const char *, size_t)
@@ -22,7 +23,7 @@ size_t Asset::do_write(const char *, size_t)
 
 const Handle &Asset::get_handle(Mode)
 {
-       throw logic_error("Asset::get_handle");
+       throw unsupported("Asset::get_handle");
 }
 
 } // namespace IO
index 84c2837656f4e8f05d2684e414b824e0e8e39047..41cf10ddc2dc44b8d5eb3aff934f65b8b617bbf2 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef MSP_IO_ASSET_H_
 #define MSP_IO_ASSET_H_
 
+#include <msp/core/mspcore_api.h>
 #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;
index aadc6acd48db7c49430e4823c74423a354168535..92c860d266f1923d275c6f568ef99c4a0e715863 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <cstddef>
 #include <sigc++/sigc++.h>
+#include <msp/core/mspcore_api.h>
 #include <msp/core/mutex.h>
 #include <msp/core/noncopyable.h>
 #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
index 638e4ec3696a77a71e7f516ccdd0ccf6033abdc3..9f001fbe9ae94b944611f368416799ceab836a04 100644 (file)
@@ -1,5 +1,5 @@
 #include <cstring>
-#include <stdexcept>
+#include <msp/core/except.h>
 #include "buffered.h"
 #include "handle.h"
 
@@ -33,12 +33,12 @@ Buffered::~Buffered()
 
 void Buffered::set_block(bool)
 {
-       throw logic_error("Buffered::set_block");
+       throw unsupported("Buffered::set_block");
 }
 
 void Buffered::set_inherit(bool)
 {
-       throw logic_error("Buffered::set_block");
+       throw unsupported("Buffered::set_block");
 }
 
 void Buffered::flush()
@@ -179,7 +179,7 @@ int Buffered::get()
 
 const Handle &Buffered::get_handle(Mode)
 {
-       throw logic_error("Buffered::get_handle");
+       throw unsupported("Buffered::get_handle");
 }
 
 void Buffered::set_op(Mode op)
index f078ea1094324d57d1533063aa457e019912ae2f..c05fc25eed5ad9454448d34f60a716ed091d56cb 100644 (file)
@@ -2,12 +2,13 @@
 #define MSP_IO_BUFFERED_H_
 
 #include <sigc++/trackable.h>
+#include <msp/core/mspcore_api.h>
 #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;
@@ -32,8 +33,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;
 
index abb872d12e41c915a3876250abe340ddec13bf52..0ac05c6b8c9fd08c0d813ed45d4435c15384b84e 100644 (file)
@@ -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
index ac66288832966bd4bf67355519ce2bed5d43170a..fe777cc04db02e90b88df52730c5f41ec3af513d 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef MSP_IO_CONSOLE_H_
 #define MSP_IO_CONSOLE_H_
 
+#include <msp/core/mspcore_api.h>
 #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,10 @@ public:
        static Console &instance(Stream);
 };
 
-extern Console &cin;
-extern Console &cout;
-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
index 9c233ee6a2a0cae226b972179d2519a0a51fc794..035a7f286f6284378ee9a9b5795458b2afe91de3 100644 (file)
@@ -69,11 +69,6 @@ void EventDispatcher::dispatch()
 }
 
 
-EventDispatcher::Slot::Slot(EventDispatcher &d, EventObject &o):
-       disp(d),
-       obj(o)
-{ }
-
 void EventDispatcher::Slot::connect_signals() const
 {
        obj.signal_events_changed.connect(sigc::mem_fun(this, &Slot::events_changed));
index f95f477daac5199df5995698a217baa64e6e3f99..25341bfe36fd04bc28878c0a8971bfce62de689e 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <set>
 #include <sigc++/trackable.h>
+#include <msp/core/mspcore_api.h>
 #include <msp/time/timedelta.h>
 #include <msp/time/timer.h>
 #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
@@ -22,7 +23,7 @@ private:
                EventDispatcher &disp;
                EventObject &obj;
 
-               Slot(EventDispatcher &, EventObject &);
+               Slot(EventDispatcher &d, EventObject &o): disp(d), obj(o) { }
 
                void connect_signals() const;
                void events_changed(PollEvent) const;
index cf987e4094fae6ce133c0f7c4f00491eb7e381df..75cfb73692c3b164ab821f765348dec337b5d699 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef MSP_IO_EVENTOBJECT_H_
 #define MSP_IO_EVENTOBJECT_H_
 
+#include <msp/core/mspcore_api.h>
 #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
index c4ae56b1de75567201a4215b4e47da61fa3a4368..11091ab98556a511e6d50720533815b91438f2a0 100644 (file)
@@ -28,14 +28,14 @@ private:
        Private *priv = nullptr;
 
 public:
-       EventReader(Handle &, unsigned);
+       EventReader(Handle &, std::size_t);
        ~EventReader();
 
        const Handle &get_event();
 
        void start();
        void wait();
-       unsigned read(char *, unsigned);
+       unsigned read(char *, std::size_t);
 };
 
 } // namespace IO
index 5ead278813d7bd73e8c9eae38282e8b07f1d0bd4..7d6e1f9b8df12feee60d3eae53b532db13ae55e0 100644 (file)
@@ -1,3 +1,4 @@
+#include <msp/core/except.h>
 #include "file.h"
 #include "handle_private.h"
 
@@ -104,7 +105,7 @@ void BufferedFile::set_block(bool b)
 
 void BufferedFile::set_inherit(bool)
 {
-       throw logic_error("BufferedFile::set_inherit");
+       throw unsupported("BufferedFile::set_inherit");
 }
 
 size_t BufferedFile::do_write(const char *buf, size_t size)
@@ -146,7 +147,7 @@ int BufferedFile::get()
 
 const Handle &BufferedFile::get_handle(Mode)
 {
-       throw logic_error("BufferedFile::get_handle");
+       throw unsupported("BufferedFile::get_handle");
 }
 
 SeekOffset BufferedFile::seek(SeekOffset offset, SeekType type)
index f23cc93e7d013b71dc33cbe060cd83ce939fbe4a..2af56ae67b2264913dcc3fa376ba5cde023c63b5 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <stdexcept>
 #include <string>
+#include <msp/core/mspcore_api.h>
 #include "buffered.h"
 #include "handle.h"
 #include "seekable.h"
 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) { }
-       ~file_not_found() throw() override = default;
 };
 
-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) { }
-       ~file_already_exists() throw() override = default;
 };
 
 
@@ -30,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
@@ -82,7 +81,7 @@ inline File::CreateMode operator~(File::CreateMode m)
 { return File::CreateMode(~static_cast<int>(m)); }
 
 
-class BufferedFile: public Seekable
+class MSPCORE_API BufferedFile: public Seekable
 {
 private:
        File file;
index 6140e116d74fb497d83085d921e11b515084616a..06c2034c5271995995fd2929027cc1951fcf9d7d 100644 (file)
@@ -2,11 +2,12 @@
 #define MSP_IO_HANDLE_H_
 
 #include <cstddef>
+#include <msp/core/mspcore_api.h>
 
 namespace Msp {
 namespace IO {
 
-class Handle
+class MSPCORE_API Handle
 {
 public:
        struct Private;
index 0b2d8f4c1b7f49ec7ccb93222d2bf48915abf3fd..0539fdbc4245f3c9c9ada441bf2aefdbcf0c0707 100644 (file)
@@ -1,5 +1,6 @@
 #include <algorithm>
 #include <cstring>
+#include <msp/core/except.h>
 #include "handle.h"
 #include "memory.h"
 
@@ -8,22 +9,34 @@ 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<char *>(d), const_cast<char *>(d+s), M_READ)
+{ }
+
+Memory::Memory(const char *b, const char *e):
+       Memory(const_cast<char *>(b), const_cast<char *>(e), M_READ)
+{ }
+
 void Memory::set_block(bool)
 {
-       throw logic_error("Memory::set_block");
+       throw unsupported("Memory::set_block");
 }
 
 void Memory::set_inherit(bool)
 {
-       throw logic_error("Memory::set_inherit");
+       throw unsupported("Memory::set_inherit");
 }
 
 size_t Memory::do_write(const char *buf, size_t size)
@@ -94,7 +107,7 @@ int Memory::get()
 
 const Handle &Memory::get_handle(Mode)
 {
-       throw logic_error("Memory::get_handle");
+       throw unsupported("Memory::get_handle");
 }
 
 SeekOffset Memory::seek(SeekOffset off, SeekType type)
index 75cf7f5a6056ff052ebef19b4622692f6bf138d5..e009cfdd24965d701d745e4dd865734615d4e85c 100644 (file)
@@ -1,12 +1,13 @@
 #ifndef MSP_IO_MEMORY_H_
 #define MSP_IO_MEMORY_H_
 
+#include <msp/core/mspcore_api.h>
 #include "seekable.h"
 
 namespace Msp {
 namespace IO {
 
-class Memory: public Seekable
+class MSPCORE_API Memory: public Seekable
 {
 private:
        char *begin = nullptr;
@@ -14,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<char *>(d), const_cast<char *>(d+s), M_READ) { }
-       Memory(const char *b, const char *e): Memory(const_cast<char *>(b), const_cast<char *>(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;
index 565eb0fb90043fdd1b9873ebe41942436aa00fbc..6230a6560936962c16ae448e888c9313b9e1890a 100644 (file)
@@ -2,6 +2,7 @@
 #define MSP_IO_MODE_H_
 
 #include <stdexcept>
+#include <msp/core/mspcore_api.h>
 
 namespace Msp {
 namespace IO {
@@ -30,11 +31,10 @@ 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);
-       ~invalid_access() throw() override = default;
 };
 
 } // namespace IO
index df5353a39eb078c6fc3eab7f6509a441b28cdd69..c62aa361b6dc1c349aca224f44b5ddf8b75d9ec5 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef MSP_IO_PIPE_H_
 #define MSP_IO_PIPE_H_
 
+#include <msp/core/mspcore_api.h>
 #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;
index 4f9b24f8e6340b8111c6a45824b60cecf336216c..7aa41e1c330c9ac41ae5ebdf9fa96eb3678a274c 100644 (file)
@@ -1,4 +1,4 @@
-#include <stdexcept>
+#include <msp/core/except.h>
 #include <msp/core/algorithm.h>
 #include "eventobject.h"
 #include "poll.h"
@@ -44,10 +44,10 @@ void Poller::set_object(EventObject &obj, PollEvent ev)
 
 #ifdef _WIN32
        if(objects.size()>=MAXIMUM_WAIT_OBJECTS)
-               throw logic_error("Maximum number of wait objects reached");
+               throw invalid_state("too many objects");
 #endif
 
-       objects.push_back(PolledObject(&obj, ev));
+       objects.push_back({ &obj, ev });
        objs_changed = true;
 }
 
@@ -91,7 +91,7 @@ PollEvent poll(EventObject &obj, PollEvent pe)
 PollEvent poll(EventObject &obj, PollEvent pe, const Time::TimeDelta &timeout)
 {
        if(timeout<Time::zero)
-               throw invalid_argument("poll");
+               throw invalid_argument("IO::poll");
 
        return platform_poll(obj, pe, static_cast<int>(timeout/Time::msec));
 }
index c8739239d960f4f801d1f1bd22846ddcd3a9989e..53e3808feceb4a00845e5a9ec63d0ae5918d8544 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <map>
 #include <vector>
+#include <msp/core/mspcore_api.h>
 #include <msp/core/noncopyable.h>
 #include <msp/time/timedelta.h>
 
@@ -31,15 +32,13 @@ inline PollEvent operator~(PollEvent e)
 { return PollEvent(~static_cast<int>(e)); }
 
 
-class Poller: private NonCopyable
+class MSPCORE_API Poller: private NonCopyable
 {
 public:
        struct PolledObject
        {
-               EventObject *object = nullptr;
-               PollEvent events = P_NONE;
-
-               PolledObject(EventObject *o, PollEvent e): object(o), events(e) { }
+               EventObject *object;
+               PollEvent events;
        };
 
 private:
@@ -66,8 +65,8 @@ public:
        const std::vector<PolledObject> &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
index 84a556163e764e40ed837703434a01dfd60fe9a9..e549d24c5dd7b8a0527b4cb9fc4e039ce887ad91 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <cstdint>
 #include <stdexcept>
+#include <msp/core/mspcore_api.h>
 #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;
index a07cd1fd43e404b3a0e82e603abff93388bd1cc0..b83f1e5fb5cb427ac476a86b54f004ba2943ffa1 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef MSP_IO_SERIAL_H_
 #define MSP_IO_SERIAL_H_
 
+#include <msp/core/mspcore_api.h>
 #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
index 535deae1184bfdf7900375652e4faf8bede8473d..9ca5966c30acd1c03a18af313bbad5cc34737c81 100644 (file)
@@ -1,4 +1,4 @@
-#include <stdexcept>
+#include <msp/core/except.h>
 #include "slice.h"
 
 using namespace std;
@@ -12,7 +12,7 @@ Slice::Slice(Seekable &b, SeekOffset s, SeekOffset l):
        length(l)
 {
        if(s<0 || l<0)
-               throw invalid_argument("Slice");
+               throw invalid_argument("Slice::Slice");
 
        Base::Synchronize sync(below);
        mode = below.get_mode()&M_RDWR;
@@ -21,12 +21,12 @@ Slice::Slice(Seekable &b, SeekOffset s, SeekOffset l):
 
 void Slice::set_block(bool)
 {
-       throw logic_error("Slice::set_block");
+       throw unsupported("Slice::set_block");
 }
 
 void Slice::set_inherit(bool)
 {
-       throw logic_error("Slice::set_inherit");
+       throw unsupported("Slice::set_inherit");
 }
 
 void Slice::flush()
@@ -108,7 +108,7 @@ int Slice::get()
 
 const Handle &Slice::get_handle(Mode)
 {
-       throw logic_error("Slice::get_handle");
+       throw unsupported("Slice::get_handle");
 }
 
 SeekOffset Slice::seek(SeekOffset off, SeekType type)
index 2965f9899a8252c8415b5c776e31dee8b6c490fd..272fa2c8c1b8d6191a21d123971dc162229f136d 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef MSP_IO_SLICE_H_
 #define MSP_IO_SLICE_H_
 
+#include <msp/core/mspcore_api.h>
 #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;
index afb14639de77c455511853c3a432b4d0f80c1ce0..b87a347897334d5aee851d705d29337c21128e6d 100644 (file)
@@ -3,7 +3,7 @@
 namespace Msp {
 namespace IO {
 
-EventReader::EventReader(Handle &h, unsigned):
+EventReader::EventReader(Handle &h, size_t):
        handle(h)
 { }
 
@@ -21,7 +21,7 @@ void EventReader::start()
 void EventReader::wait()
 { }
 
-unsigned EventReader::read(char *buf, unsigned len)
+unsigned EventReader::read(char *buf, size_t len)
 {
        return sys_read(handle, buf, len);
 }
index 28d3aebc5acba72970c0176a2b17581d4cf168ab..e3db10eae1cf215906b70d40456ce89a52d9ab5a 100644 (file)
@@ -91,7 +91,7 @@ void Poller::platform_poll(int timeout)
        for(unsigned i=0; (i<objects.size() && ret>0); ++i)
                if(priv->pfd[i].revents)
                {
-                       poll_result.push_back(PolledObject(objects[i].object, poll_event_from_sys(priv->pfd[i].revents)));
+                       poll_result.push_back({ objects[i].object, poll_event_from_sys(priv->pfd[i].revents) });
                        --ret;
                }
 }
index a402742a52338b7ba2d5f17cd639d6b37ca18c84..63af4b9646e7dace23ed2052b42d76293bbc8ffb 100644 (file)
@@ -21,7 +21,7 @@ int sys_seek_type(SeekType st)
        else if(st==S_END)
                return SEEK_END;
 
-       throw invalid_argument("sys_seek_type");
+       throw invalid_argument("IO::sys_seek");
 }
 
 }
index 70286b7ddd34294a98eea656704849501c681c85..728f3d884d92dfeb42411da62466769d19126c73 100644 (file)
@@ -80,14 +80,14 @@ void Serial::DeviceState::set_baud_rate(unsigned baud)
        case 3000000: speed = 0010015; break;
        case 3500000: speed = 0010016; break;
        case 4000000: speed = 0010017; break;
-       default: throw invalid_argument("set_baud_rate");
+       default: throw invalid_argument("Serial::set_baud_rate");
        }
 
        int ret = cfsetospeed(&state, speed);
        if(ret==0)
                ret = cfsetispeed(&state, speed);
        if(ret<0)
-               throw invalid_argument("set_baud_rate");
+               throw invalid_argument("Serial::set_baud_rate");
 }
 
 void Serial::DeviceState::set_data_bits(unsigned bits)
@@ -99,7 +99,7 @@ void Serial::DeviceState::set_data_bits(unsigned bits)
        case 6: flag = CS6; break;
        case 7: flag = CS7; break;
        case 8: flag = CS8; break;
-       default: throw invalid_argument("set_data_bits");
+       default: throw invalid_argument("Serial::set_data_bits");
        }
 
        state.c_cflag = (state.c_cflag&~CSIZE)|flag;
@@ -113,7 +113,7 @@ void Serial::DeviceState::set_parity(Serial::Parity par)
        case Serial::NONE: flag = 0; break;
        case Serial::EVEN: flag = PARENB; break;
        case Serial::ODD:  flag = PARENB|PARODD; break;
-       default: throw invalid_argument("set_parity");
+       default: throw invalid_argument("Serial::set_parity");
        }
 
        state.c_cflag = (state.c_cflag&~(PARENB|PARODD))|flag;
@@ -126,7 +126,7 @@ void Serial::DeviceState::set_stop_bits(unsigned bits)
        {
        case 1: flag = 0; break;
        case 2: flag = CSTOPB; break;
-       default: throw invalid_argument("set_stop_bits");
+       default: throw invalid_argument("Serial::set_stop_bits");
        }
 
        state.c_cflag = (state.c_cflag&~CSTOPB)|flag;
index f73383d94ba9dc29b78d17aaa0c2a1e4912afec7..4507f5c8046ca7e35b6a35a14dd990834b4fefc0 100644 (file)
@@ -2,6 +2,7 @@
 #define MSP_IO_UTILS_H_
 
 #include <cstddef>
+#include <msp/core/mspcore_api.h>
 
 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
index a331133c2bf8bec39762021e9da8f96889aed192..4f78487856b996814531511d1e1f7aa872641af2 100644 (file)
@@ -1,3 +1,4 @@
+#include <msp/core/except.h>
 #include <msp/core/systemerror.h>
 #include "console.h"
 #include "handle_private.h"
@@ -13,7 +14,7 @@ DWORD stream_to_sys(Msp::IO::Console::Stream stream)
        case Msp::IO::Console::CIN: return STD_INPUT_HANDLE;
        case Msp::IO::Console::COUT: return STD_OUTPUT_HANDLE;
        case Msp::IO::Console::CERR: return STD_ERROR_HANDLE;
-       default: throw invalid_argument("stream_to_sys");
+       default: throw Msp::internal_error("stream_to_sys");
        }
 }
 
index 4a0640f5395f799fc1aacb992cc107ec20214e54..8f208c20dda864c711ad5584697083c3df9b4ade 100644 (file)
@@ -1,4 +1,4 @@
-#include <windows.h>
+#include <msp/core/winapi.h>
 #include <algorithm>
 #include <msp/core/systemerror.h>
 #include "eventreader.h"
@@ -22,7 +22,7 @@ struct EventReader::Private
 };
 
 
-EventReader::EventReader(Handle &h, unsigned size):
+EventReader::EventReader(Handle &h, size_t size):
        handle(h),
        priv(new Private)
 {
@@ -92,7 +92,7 @@ void EventReader::wait()
        }
 }
 
-unsigned EventReader::read(char *buf, unsigned len)
+unsigned EventReader::read(char *buf, size_t len)
 {
        if(!priv->buf_avail)
        {
index 6d1219a24859e7757e9b1ba9e114ffbffa3793d7..e72282a4f98b0eaec2d8e5df50d3011850639e8f 100644 (file)
@@ -20,7 +20,7 @@ void sys_set_inherit(Handle &, bool)
 size_t sys_read(Handle &handle, char *buf, size_t size)
 {
        if(size>numeric_limits<DWORD>::max())
-               throw invalid_argument("read");
+               throw invalid_argument("IO::sys_read");
 
        DWORD ret;
        if(ReadFile(*handle, buf, size, &ret, nullptr)==0)
@@ -32,7 +32,7 @@ size_t sys_read(Handle &handle, char *buf, size_t size)
 size_t sys_write(Handle &handle, const char *buf, size_t size)
 {
        if(size>numeric_limits<DWORD>::max())
-               throw invalid_argument("write");
+               throw invalid_argument("IO::sys_write");
 
        DWORD ret;
        if(WriteFile(*handle, buf, size, &ret, nullptr)==0)
index f12e5f74771a044326688b439f9c645d4b0f456a..776e8f3cc328dd940bee7f7cfc0038b36ca0f846 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef MSP_IO_HANDLE_PLATFORM_H_
 #define MSP_IO_HANDLE_PLATFORM_H_
 
-#include <windows.h>
+#include <msp/core/winapi.h>
 
 namespace Msp {
 namespace IO {
index 0d644cd0a7cf6cfa3573df8444f465543a50f537..cbd92fd39678417c59375277c4ab0bd802606109 100644 (file)
@@ -1,3 +1,4 @@
+#include <msp/core/except.h>
 #include <msp/core/systemerror.h>
 #include "eventobject.h"
 #include "handle.h"
index ec778aecf030f6c0abfb97f7787e4d1e5315829c..62a000f5a748bab027f073df389e30a427f67407 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef MSP_IO_POLL_PLATFORM_H_
 #define MSP_IO_POLL_PLATFORM_H_
 
-#include <windows.h>
+#include <msp/core/winapi.h>
 #include <vector>
 #include "poll.h"
 
index 73c5cc51bc2824718bab9fb0af1591ddc0464b9b..3756cf1a7d44c937755158167d95ed616ef6712b 100644 (file)
@@ -1,4 +1,4 @@
-#include <windows.h>
+#include <msp/core/winapi.h>
 #include <msp/core/systemerror.h>
 #include "handle.h"
 #include "handle_private.h"
@@ -19,7 +19,7 @@ int sys_seek_type(SeekType st)
        else if(st==S_END)
                return FILE_END;
 
-       throw invalid_argument("sys_seek_type");
+       throw invalid_argument("IO::sys_seek");
 }
 
 }
index bd086dd4d88e0985d6ab292f0bebeed92f5453f2..d041c8705ba3305105f7e806cbcdce98a1e20493 100644 (file)
@@ -56,7 +56,7 @@ void Serial::DeviceState::set_parity(Serial::Parity par)
        case Serial::NONE: state.Parity = NOPARITY; break;
        case Serial::EVEN: state.Parity = EVENPARITY; break;
        case Serial::ODD:  state.Parity = ODDPARITY; break;
-       default: throw invalid_argument("set_parity");
+       default: throw invalid_argument("Serial::set_parity");
        }
 }
 
@@ -66,7 +66,7 @@ void Serial::DeviceState::set_stop_bits(unsigned bits)
        {
        case 1: state.StopBits = ONESTOPBIT; break;
        case 2: state.StopBits = TWOSTOPBITS; break;
-       default: throw invalid_argument("set_stop_bits");
+       default: throw invalid_argument("Serial::set_stop_bits");
        }
 }
 
index dd7dd5004920b53e2d9f8ebeb18e9cd7aea98b85..317373605cf0f1d6562e70a71e613d36ef75b374 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef MSP_IO_SERIAL_PLATFORM_H_
 #define MSP_IO_SERIAL_PLATFORM_H_
 
-#include <windows.h>
+#include <msp/core/winapi.h>
 
 namespace Msp {
 namespace IO {
index fba71eb06d5e8b9ced1df0e2e1ce1e8ba743c889..8896f147bf6b1ecb038e7739a275a4a7c5732a96 100644 (file)
@@ -1,6 +1,7 @@
 #ifdef WITH_ZLIB
 #include <zlib.h>
 #endif
+#include <msp/core/except.h>
 #include "zlibcompressed.h"
 
 using namespace std;
@@ -73,7 +74,7 @@ ZlibCompressed::ZlibCompressed(Base &b, Mode m, unsigned level):
        (void)buffer_size;
        (void)stream_end;
        (void)level;
-       throw zlib_error("unsupported", -1);
+       throw unsupported("ZlibCompressed");
 #endif
 }
 
@@ -96,12 +97,12 @@ ZlibCompressed::~ZlibCompressed()
 
 void ZlibCompressed::set_block(bool)
 {
-       throw logic_error("ZlibCompressed::set_block");
+       throw unsupported("ZlibCompressed::set_block");
 }
 
 void ZlibCompressed::set_inherit(bool)
 {
-       throw logic_error("ZlibCompressed::set_inherit");
+       throw unsupported("ZlibCompressed::set_inherit");
 }
 
 void ZlibCompressed::flush()
@@ -261,7 +262,7 @@ size_t ZlibCompressed::do_read(char *data, size_t size)
 
 const Handle &ZlibCompressed::get_handle(Mode)
 {
-       throw logic_error("ZlibCompressed::get_handle");
+       throw unsupported("ZlibCompressed::get_handle");
 }
 
 } // namespace IO
index eb35f6ce1b8c7c7b33e25cf86f39d36f83b8f782..1dc15697fc3e59089ac745fe16aa42a5aaff8094 100644 (file)
@@ -4,21 +4,21 @@
 #include <stdexcept>
 #include <string>
 #include <sigc++/trackable.h>
+#include <msp/core/mspcore_api.h>
 #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;
 
 public:
        zlib_error(const std::string &, int);
-       ~zlib_error() throw() override = default;
 
-       int code() const throw() { return m_code; }
+       int code() const noexcept { return m_code; }
 };
 
 /**
@@ -28,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;
index bb5d0eea023db4efbc9c6ca2a9d19b646699d89e..755edebce30995cd98baff4102ece87ec2f9e753 100644 (file)
@@ -1,15 +1,16 @@
 #ifndef MSP_STRINGCODEC_ASCII_H_
 #define MSP_STRINGCODEC_ASCII_H_
 
+#include <msp/core/mspcore_api.h>
 #include "codec.h"
 
 namespace Msp {
 namespace StringCodec {
 
-class Ascii: public StandardCodec<Ascii>
+class MSPCORE_API Ascii: public StandardCodec<Ascii>
 {
 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) { }
index abec134b1a0fd00a25f936952368beba22c62742..ff2bd63d5e657b8547392163d12aa50b94f40e13 100644 (file)
@@ -86,7 +86,7 @@ Codec *create_codec(const string &n)
                else if(em_str=="trans" || em_str=="transliterate")
                        em = TRANSLITERATE;
                else
-                       throw invalid_argument("invalid error mode");
+                       throw invalid_argument("StringCodec::create_codec");
        }
 
        if(name=="ascii") return new Ascii(em);
@@ -101,7 +101,7 @@ Codec *create_codec(const string &n)
        if(name=="utf16be") return new Utf16(em, Utf16::BIG);
        if(name=="utf16le") return new Utf16(em, Utf16::LITTLE);
        if(name=="windows1252" || name=="cp1252") return new Windows1252(em);
-       throw invalid_argument("unknown string codec");
+       throw invalid_argument("StringCodec::create_codec");
 }
 
 Codec *detect_codec(const string &str)
index 5e67d46049078f3555994eeca393ce9691bf75f8..f53bae5ba1d8ee86de0d469629ff21daad4b57d1 100644 (file)
@@ -2,6 +2,7 @@
 #define MSP_STRINGCODEC_CODEC_H_
 
 #include <string>
+#include <msp/core/mspcore_api.h>
 #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
index 395949e8e814e8d3e3cef04b3f097b0c4f8b029e..cf9eb2d10b2dd580507432c0fd31327e041c1c66 100644 (file)
@@ -1,10 +1,12 @@
 #ifndef MSP_STRINGCODEC_CODECUTILS_H_
 #define MSP_STRINGCODEC_CODECUTILS_H_
 
+#include <msp/core/mspcore_api.h>
+
 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
index 0c7b690d5d47e4acdfb454b9ff4a4ba100a675e3..fc377e0a36bc269be33a500d98ae3427ba5802ef 100644 (file)
@@ -2,6 +2,7 @@
 #define MSP_STRINGCODEC_EXCEPT_H_
 
 #include <stdexcept>
+#include <msp/core/mspcore_api.h>
 #include "ustring.h"
 
 namespace Msp {
@@ -10,33 +11,30 @@ 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) { }
-       ~codec_error() throw() override = default;
 };
 
 
 /**
 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 &);
-       ~invalid_character() throw() override = default;
 };
 
 
 /**
 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 &);
-       ~invalid_sequence() throw() override = default;
 
 private:
        std::string format_sequence(const std::string::const_iterator &, const std::string::const_iterator &);
index 3332922ccda68e81d354ca5f4e25f35bc96f492c..93c50f489fb8486182a1f2b69711efea71d5e01e 100644 (file)
@@ -1,3 +1,4 @@
+#include <msp/core/except.h>
 #include "ascii.h"
 #include "iso2022jp.h"
 #include "jisx0201.h"
@@ -122,7 +123,7 @@ unichar Iso2022Jp::Decoder::decode_char(const string &str, string::const_iterato
                else if(dec)
                        return dec->decode_char(str, i);
                else
-                       throw logic_error("no sub-decoder");
+                       throw internal_error("no sub-decoder");
 
                if(result>=0)
                        return result;
index a9bc1c2d513d37bb20486009bb6964764836d5e4..0bb1ad3f559f220f4a5e115ab6bcaafd5ff3ba96 100644 (file)
@@ -1,12 +1,13 @@
 #ifndef MSP_STRINGCODEC_ISO2022JP_H_
 #define MSP_STRINGCODEC_ISO2022JP_H_
 
+#include <msp/core/mspcore_api.h>
 #include "codec.h"
 
 namespace Msp {
 namespace StringCodec {
 
-class Iso2022Jp: public StandardCodec<Iso2022Jp>
+class MSPCORE_API Iso2022Jp: public StandardCodec<Iso2022Jp>
 {
 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;
index fdb3d606229b7b073ca85898e2cf2271c2297cb1..3f1bb703da0b810df16fbd48e2a71f2b2f19cf12 100644 (file)
@@ -1,15 +1,16 @@
 #ifndef MSP_STRINGCODEC_ISO646FI_H_
 #define MSP_STRINGCODEC_ISO646FI_H_
 
+#include <msp/core/mspcore_api.h>
 #include "codec.h"
 
 namespace Msp {
 namespace StringCodec {
 
-class Iso646Fi: public StandardCodec<Iso646Fi>
+class MSPCORE_API Iso646Fi: public StandardCodec<Iso646Fi>
 {
 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) { }
index a8ba809410ee40bd6a521bdc12fba74401375542..a6003ceda3eb1986b0f892936018f9de11032b10 100644 (file)
@@ -1,15 +1,16 @@
 #ifndef MSP_STRINGCODEC_ISO88591_H_
 #define MSP_STRINGCODEC_ISO88591_H_
 
+#include <msp/core/mspcore_api.h>
 #include "codec.h"
 
 namespace Msp {
 namespace StringCodec {
 
-class Iso88591: public StandardCodec<Iso88591>
+class MSPCORE_API Iso88591: public StandardCodec<Iso88591>
 {
 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) { }
index 3791d0594cf1d52ebba9598067001f5f802f15ca..2e812459af64e77199ec437a7de2e831cff462cc 100644 (file)
@@ -1,15 +1,16 @@
 #ifndef MSP_STRINGCODEC_ISO885915_H_
 #define MSP_STRINGCODEC_ISO885915_H_
 
+#include <msp/core/mspcore_api.h>
 #include "codec.h"
 
 namespace Msp {
 namespace StringCodec {
 
-class Iso885915: public StandardCodec<Iso885915>
+class MSPCORE_API Iso885915: public StandardCodec<Iso885915>
 {
 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) { }
index 5cbda036b16f28e02440fd31b54f6efef42c08a1..3194c784c8d5378ad90213754da7cd09e42ffcdb 100644 (file)
@@ -1,15 +1,16 @@
 #ifndef MSP_STRINGCODEC_JISX201_H_
 #define MSP_STRINGCODEC_JISX201_H_
 
+#include <msp/core/mspcore_api.h>
 #include "codec.h"
 
 namespace Msp {
 namespace StringCodec {
 
-class JisX0201: public StandardCodec<JisX0201>
+class MSPCORE_API JisX0201: public StandardCodec<JisX0201>
 {
 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) { }
index b0c03b2af8136593a2e9d26cc882c8596d20f1c9..0f29432efbfe91cb042ab8f8ff177d1174ca189e 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef MSP_STRINGCODEC_JISX0208_H_
 #define MSP_STRINGCODEC_JISX0208_H_
 
+#include <msp/core/mspcore_api.h>
 #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<JisX0208>
+class MSPCORE_API JisX0208: public StandardCodec<JisX0208>
 {
 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
index 73d81cb9c26a15ec4ad9c318e4525f5a5a4a3705..a588b124dddb27461f05c4a41b31aee8a1cd783f 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef MSP_STRINGCODEC_UTF16_H_
 #define MSP_STRINGCODEC_UTF16_H_
 
+#include <msp/core/mspcore_api.h>
 #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<Utf16>
+class MSPCORE_API Utf16: public StandardCodec<Utf16>
 {
 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;
index f170916f1d6c6d39ee1c1eb3d46f77df7068951e..c3f4a5930014f46c5d3a46318d2cf5c4f17ef4c6 100644 (file)
@@ -1,15 +1,16 @@
 #ifndef MSP_STRINGCODEC_UTF8_H_
 #define MSP_STRINGCODEC_UTF8_H_
 
+#include <msp/core/mspcore_api.h>
 #include "codec.h"
 
 namespace Msp {
 namespace StringCodec {
 
-class Utf8: public StandardCodec<Utf8>
+class MSPCORE_API Utf8: public StandardCodec<Utf8>
 {
 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) { }
index bcea69b7a60e6818cad0bcef0137c10228012d81..b89fdaea1646d7438eebfd52cd97bb45b91dabe5 100644 (file)
@@ -1,15 +1,16 @@
 #ifndef MSP_STRINGCODEC_WINDOWS1252_H_
 #define MSP_STRINGCODEC_WINDOWS1252_H_
 
+#include <msp/core/mspcore_api.h>
 #include "codec.h"
 
 namespace Msp {
 namespace StringCodec {
 
-class Windows1252: public StandardCodec<Windows1252>
+class MSPCORE_API Windows1252: public StandardCodec<Windows1252>
 {
 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) { }
index 45ae91749c5e3b51ae19b1ebc4dbec8d1627f4d5..88b297d7bede12e4895398696e7b909f36bbd3ab 100644 (file)
@@ -4,14 +4,14 @@
 #include <ostream>
 #include <stdexcept>
 #include <string>
+#include <msp/core/mspcore_api.h>
 
 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) { }
-       ~format_error() throw() override = default;
 };
 
 
@@ -35,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
index 49c40e9293512da2a656699d837f7f42834771c6..7969ef3930c01979e1948d63b97dccd9b6f2a026 100644 (file)
@@ -2,6 +2,7 @@
 #define MSP_STRINGS_FORMAT_H_
 
 #include <string>
+#include <msp/core/mspcore_api.h>
 #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;
index a58d0b14e1ffbc30049fba5f408809009954ea3a..5ae5f55861b85f4b6c216af23fd5759b90da3588 100644 (file)
@@ -2,11 +2,12 @@
 #define MSP_STRINGS_GLOB_H_
 
 #include <string>
+#include <msp/core/mspcore_api.h>
 
 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
 
index 2b84d9bbbcdaa4e93af36d15d6bb5063807f7ef6..5e9159ce97af5e42db1ad9ba63ee1669a21c2a93 100644 (file)
@@ -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<unsigned long>(c.get(), c.get_fmt()); }
 
-#ifdef __GNUC__
 void operator>>(const LexicalConverter &c, long long &v)
 { v = str_to_int<long long>(c.get(), c.get_fmt()); }
 
 void operator>>(const LexicalConverter &c, unsigned long long &v)
 { v = str_to_int<unsigned long long>(c.get(), c.get_fmt()); }
-#endif
 
 void operator>>(const LexicalConverter &c, bool &v)
 { v = str_to_bool(c.get()); }
index 393622d54771bb5197886a7423627fce6066b519..ccb77909893091c4a929bbd51772ab5ef9046682 100644 (file)
@@ -5,6 +5,7 @@
 #include <string>
 #include <stdexcept>
 #include <msp/core/meta.h>
+#include <msp/core/mspcore_api.h>
 #include "fmt.h"
 
 namespace Msp {
@@ -12,29 +13,27 @@ 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) { }
-       ~lexical_error() throw() override = default;
 };
 
 
 /**
 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) { }
-       ~format_mismatch() throw() override = default;
 };
 
 
 /**
 Helper class for lexical_cast to facilitate operator overloading.
 */
-class LexicalConverter
+class MSPCORE_API LexicalConverter
 {
 private:
        Fmt fmt;
@@ -51,45 +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);
-#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);
-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 &);
-#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 &);
-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
 
index 915d33556f17cdd8d4f3a23c48e9a3f5b8343054..5307c6990286ba373291281fb4ee230ff81d2d07 100644 (file)
@@ -2,6 +2,7 @@
 #include <list>
 #include <stack>
 #include <vector>
+#include <msp/core/except.h>
 #include "format.h"
 #include "regex.h"
 
@@ -477,7 +478,7 @@ bool Regex::run(const string &str, const string::const_iterator &begin, vector<R
                                                input_consumed = true;
                                        }
                                        else
-                                               throw logic_error("invalid instruction in regex bytecode");
+                                               throw internal_error("invalid instruction in regex bytecode");
 
                                        if(match_result==negate_match)
                                                terminate = true;
index bef5231e4b8a3cc3e1337da11ad682c94b9653db..42c1e01a6951a4c3229c4d5b9eadad18bc119d0d 100644 (file)
@@ -3,15 +3,15 @@
 
 #include <stdexcept>
 #include <string>
+#include <msp/core/mspcore_api.h>
 #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 &);
-       ~bad_regex() throw() override = default;
 
 private:
        std::string make_where(const std::string &, const std::string::const_iterator &);
@@ -70,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<unsigned char> Code;
index 6af309ea72185ea91e43706c1ef38538ced51976..8d4406a483ac19b01476a3684b73a2bde7a4e094 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <string>
 #include <vector>
+#include <msp/core/mspcore_api.h>
 
 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:
        /**
index eb2142d5be153b68c405a26a96dba0856f3e4091..748d717464690851585e22f9ccdc45da5885eabc 100644 (file)
@@ -258,7 +258,7 @@ string c_escape(const string &str, bool escape_8bit)
                        result += "\\\'";
                else if(c=='\\')
                        result += "\\\\";
-               else if(static_cast<unsigned char>(c)<' ' || (escape_8bit && (c&0x80)))
+               else if(static_cast<unsigned char>(c)<' ' || c==0x7F || (escape_8bit && (c&0x80)))
                {
                        char buf[4] = { '\\', 0 };
                        for(unsigned j=0; j<3; ++j)
index f7e9433fd2d07a3e7496e7e7735af77d5dfff4c0..28763e6eba37df81efcdce612e9569db1bbdc27c 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <string>
 #include <vector>
+#include <msp/core/mspcore_api.h>
 
 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<std::string> split(const std::string &str, const std::string &sep = " \t\r\n", int max_split = -1);
+MSPCORE_API std::vector<std::string> 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<std::string> split(const std::string &str, char sep, int max_split = -1);
+MSPCORE_API std::vector<std::string> split(const std::string &str, char sep, int max_split = -1);
 
 /** Splits a string on occurrences of another string. */
-std::vector<std::string> split_long(const std::string &str, const std::string &sep, int max_split = -1);
+MSPCORE_API std::vector<std::string> 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<std::string> split_fields(const std::string &str, const std::string &sep, int max_split = -1);
+MSPCORE_API std::vector<std::string> 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<std::string> split_fields(const std::string &str, char sep, int max_split = -1);
+MSPCORE_API std::vector<std::string> 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<typename Iter>
@@ -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
 
index a5d91cf3451d4b547e93698cabd1f191983b4b0f..2336374c6ae12164145f6afbb68bc26a23e22deb 100644 (file)
@@ -2,6 +2,7 @@
 #define MSP_TIME_DATETIME_H_
 
 #include <string>
+#include <msp/core/mspcore_api.h>
 #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;
index a56e0fe8a3944763240b79689a55adc3d69c9ad5..5b381daffbaf6ac7be6b7b7432f21dfd82cc2a1e 100644 (file)
@@ -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
index 1a4274ba3a35c05822ad6f18c43775cf02e592e4..2ff4bdd9d4b18a2c5f1c19980c105c87bc75149f 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <cstdlib>
 #include <ctime>
+#include <msp/core/mspcore_api.h>
 #include <msp/strings/lexicalcast.h>
 #include "rawtime.h"
 
@@ -12,18 +13,18 @@ namespace Time {
 /**
 Represents a quantity of time, such as five seconds.
 */
-class TimeDelta
+class MSPCORE_API TimeDelta
 {
 private:
        RawTime usec = 0;
 
 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. */
@@ -60,18 +61,18 @@ public:
 template<typename T>
 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;
+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;
index 04c3074494e921d39f3edb54e53e378c8623e826..eda782e0d92c5bf82c00418584e12917d03fa673 100644 (file)
@@ -22,7 +22,7 @@ Timer::Slot &Timer::add(const TimeDelta &td)
 {
        Slot *s = new Slot(td);
        MutexLock l(mutex);
-       slots.push_back(s);
+       slots.push_back({ s });
        push_heap(slots.begin(), slots.end());
        if(blocking)
                sem.signal();
@@ -33,7 +33,7 @@ Timer::Slot &Timer::add(const TimeStamp &ts)
 {
        Slot *s = new Slot(ts);
        MutexLock l(mutex);
-       slots.push_back(s);
+       slots.push_back({ s });
        push_heap(slots.begin(), slots.end());
        if(blocking)
                sem.signal();
@@ -113,7 +113,7 @@ void Timer::do_tick(const TimeDelta &timeout)
                if(next->signal_timeout.emit() && next->increment())
                {
                        MutexLock l(mutex);
-                       slots.push_back(next);
+                       slots.push_back({ next });
                        push_heap(slots.begin(), slots.end());
                }
                else
@@ -152,10 +152,6 @@ bool Timer::Slot::increment()
 }
 
 
-Timer::SlotProxy::SlotProxy(Slot *s):
-       slot(s)
-{ }
-
 bool Timer::SlotProxy::operator<(const SlotProxy &sp) const
 {
        return slot->get_timeout()>sp.slot->get_timeout();
index 33257319eba3466d89f28c650efcd26dde0a996d..7cb5c764d59979e0316e2e365444940ad8e4d786 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <vector>
 #include <sigc++/sigc++.h>
+#include <msp/core/mspcore_api.h>
 #include <msp/core/mutex.h>
 #include <msp/core/noncopyable.h>
 #include <msp/core/semaphore.h>
@@ -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
@@ -41,9 +42,8 @@ public:
 private:
        struct SlotProxy
        {
-               Slot *slot = nullptr;
+               Slot *slot;
 
-               SlotProxy(Slot *);
                bool operator<(const SlotProxy &) const;
        };
 
index 8068510a6647b00d739fba0d98cf31f5da4bbac8..50813057fa1492007eac716e80a857fd3fc615fe 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef MSP_TIME_TIMESTAMP_H_
 #define MSP_TIME_TIMESTAMP_H_
 
+#include <msp/core/mspcore_api.h>
 #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;
index 3fbeb543a243e1a7abd8922e07617ea9cda83992..83b4b5835fe4298dc047b35040d9066762066139 100644 (file)
@@ -1,12 +1,13 @@
 #ifndef MSP_TIME_TIMEZONE_H_
 #define MSP_TIME_TIMEZONE_H_
 
+#include <msp/core/mspcore_api.h>
 #include "timedelta.h"
 
 namespace Msp {
 namespace Time {
 
-class TimeZone
+class MSPCORE_API TimeZone
 {
 private:
        std::string name;
index 00b6ef86c274dca75cdaac1bd38eeaa353b3819d..dd325b0a1d546d18b92b402bbc1eb6578ec26df7 100644 (file)
@@ -2,6 +2,7 @@
 #define MSP_TIME_UTILS_H_
 
 #include <string>
+#include <msp/core/mspcore_api.h>
 
 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
index 60a9a59595c19a92f72218dd54516dc67cd148fb..bd57889d2de63de699b6b30b6ff1d769905e5cf7 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef MSP_TIME_RAWTIME_PLATFORM_H_
 #define MSP_TIME_RAWTIME_PLATFORM_H_
 
-#include <windows.h>
+#include <msp/core/winapi.h>
 #include "rawtime.h"
 
 namespace Msp {
index 570c6791d52e155759c12a2239946c5949b118a3..1b526440167ec03f842cd645fcaec2eedbeb3c0e 100644 (file)
@@ -1,4 +1,4 @@
-#include <windows.h>
+#include <msp/core/winapi.h>
 #include <msp/core/systemerror.h>
 #include "timezone.h"
 
index 2150a105b1b40dcc690f2d4c320fc690ddc66ff9..4d295a91b690ad9877be6181a90f3c86fee82080 100644 (file)
@@ -1,4 +1,4 @@
-#include <windows.h>
+#include <msp/core/winapi.h>
 #include "rawtime_private.h"
 #include "timedelta.h"
 #include "timestamp.h"
diff --git a/tests/.gitignore b/tests/.gitignore
new file mode 100644 (file)
index 0000000..c551524
--- /dev/null
@@ -0,0 +1,4 @@
+/consoletest
+/consoletest.*
+/test
+/test.*
index fbb5ff54588685527080faa9991ed94b14e4b8fb..d52630a29d4bd72dfe3f1af86d1484834a4f1d24 100644 (file)
@@ -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 = "/..";
index 99cacdf29eb3ff550f509aa575ba54b491ac45dc..8ec89722197f4742e17164f2f251741c8a6ebd62 100644 (file)
@@ -99,11 +99,11 @@ void VariantTests::destruction()
 void VariantTests::types()
 {
        Variant var = 42U;
-       EXPECT(!var.check_type<int>());
-       EXPECT(var.check_type<unsigned>());
-       EXPECT(!var.check_type<float>());
-       EXPECT(!var.check_type<bool>());
-       EXPECT(!var.check_type<string>());
+       EXPECT(!var.has_type<int>());
+       EXPECT(var.has_type<unsigned>());
+       EXPECT(!var.has_type<float>());
+       EXPECT(!var.has_type<bool>());
+       EXPECT(!var.has_type<string>());
 }
 
 void VariantTests::mismatch()