]> 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)
185 files changed:
.gitignore
examples/z.cpp
source/core/algorithm.h
source/core/android/errorlogger.h
source/core/android/main.cpp
source/core/android/mainthread.cpp
source/core/android/mainthread.h
source/core/application.cpp
source/core/application.h
source/core/environ.h
source/core/except.h [new file with mode: 0644]
source/core/getopt.cpp
source/core/getopt.h
source/core/hash.cpp [deleted file]
source/core/hash.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/process_private.h
source/core/refptr.h
source/core/semaphore.h
source/core/systemerror.cpp
source/core/systemerror.h
source/core/thread.cpp
source/core/thread.h
source/core/thread_private.h
source/core/typeregistry.h
source/core/unix/main.cpp
source/core/unix/mutex.cpp
source/core/unix/process.cpp
source/core/unix/semaphore.cpp
source/core/unix/thread.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.cpp
source/debug/demangle.h
source/debug/errorreporter.cpp
source/debug/errorreporter.h
source/debug/exceptiontrace.cpp
source/debug/exceptiontrace.h
source/debug/profiler.cpp
source/debug/profiler.h
source/debug/profilingscope.h
source/fs/android/stat_owner.cpp
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.cpp
source/fs/stat.h
source/fs/stat_private.h
source/fs/unix/dir_location.cpp
source/fs/unix/filemonitor_platform.h
source/fs/unix/stat_owner.cpp
source/fs/unix/stat_platform.h
source/fs/utils.h
source/fs/windows/dir.cpp
source/fs/windows/dir_location.cpp
source/fs/windows/filemonitor.cpp
source/fs/windows/filemonitor_platform.h
source/fs/windows/stat.cpp
source/fs/windows/stat_platform.h
source/fs/windows/utils.cpp
source/io/android/asset.cpp
source/io/asset.cpp
source/io/asset.h
source/io/base.cpp
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.cpp
source/io/eventobject.h
source/io/eventreader.h
source/io/file.cpp
source/io/file.h
source/io/filtered.h [deleted file]
source/io/generic/asset.cpp
source/io/handle.cpp
source/io/handle.h
source/io/memory.cpp
source/io/memory.h
source/io/mode.h
source/io/pipe.cpp
source/io/pipe.h
source/io/poll.cpp
source/io/poll.h
source/io/seekable.h
source/io/serial.cpp
source/io/serial.h
source/io/slice.cpp
source/io/slice.h
source/io/unix/eventreader.cpp
source/io/unix/handle_platform.h
source/io/unix/poll.cpp
source/io/unix/poll_platform.h
source/io/unix/seekable.cpp
source/io/unix/serial.cpp
source/io/utils.cpp
source/io/utils.h
source/io/windows/console.cpp
source/io/windows/eventreader.cpp
source/io/windows/file.cpp
source/io/windows/handle.cpp
source/io/windows/handle_platform.h
source/io/windows/pipe.cpp
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.cpp
source/stringcodec/jisx0208.h
source/stringcodec/utf16.cpp
source/stringcodec/utf16.h
source/stringcodec/utf8.h
source/stringcodec/windows1252.h
source/strings/fmt.cpp
source/strings/fmt.h
source/strings/format.cpp
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.cpp
source/time/datetime.h
source/time/rawtime.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/unix/utils.cpp
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 d98392cfeaa92d18c102607ab171c3d1bed444d1..5f793c40cbdf08b68ac0316857ff8718856683da 100644 (file)
@@ -24,7 +24,7 @@ public:
 };
 
 Z::Z(int argc, char **argv):
-       input_file(0)
+       input_file(nullptr)
 {
        string input_fn;
        GetOpt getopt;
index 268bf7b89f9ca54ac56ae6ff7d51e4f2fbfb64cc..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,32 +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 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 4512f09bb42c51b3122c0488ef9270aefba83af8..77fcec7469df1994083d050a60f68c35bf99c0e8 100644 (file)
@@ -9,7 +9,7 @@ namespace Android {
 class ErrorLogger: public Debug::ErrorReporter
 {
 public:
-       virtual bool report_uncaught_exception(const std::exception &) const;
+       bool report_uncaught_exception(const std::exception &) const override;
 };
 
 } // namespace Android
index a71d92f1c279d0ba43c24c62ea656024d726cdca..d6ad41525820c20acc283301d309e889bbea1a3e 100644 (file)
@@ -1,8 +1,9 @@
 #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 = 0;
+       static Msp::Android::MainThread *thread = nullptr;
        if(thread)
                thread->attach_to_activity(activity);
        else
index 8ce484a0dee75e4a014a7440d2775c891fbe18a3..6441c2059b8179066fc61336801940320dedad9a 100644 (file)
@@ -15,8 +15,7 @@ namespace Android {
 
 MainThread::MainThread(ANativeActivity *a):
        asset_manager(a->assetManager),
-       int_data_path(a->internalDataPath),
-       starting_up(true)
+       int_data_path(a->internalDataPath)
 {
        attach_to_activity(a);
        startup_mutex.lock();
@@ -54,7 +53,7 @@ void MainThread::resume_startup()
 JavaVM *MainThread::get_java_vm() const
 {
        if(!activity)
-               return 0;
+               return nullptr;
 
        return activity->vm;
 }
@@ -69,7 +68,7 @@ void MainThread::main()
        /* I have no idea how dependable this is, but it seems to be the only way
        to get the package name aside from making a Java call through JNI */
        char *appname = strdup(int_data_path[-2].c_str());
-       char *argv[] = { appname, 0 };
+       char *argv[] = { appname, nullptr };
        Msp::Android::ErrorLogger err_logger;
        FS::chdir(FS::dirname(int_data_path));
        Msp::Application::run(1, argv, this, &app_created);
index 609300fb85a8a4db64e680c9f4dfd7f754d78bc4..ab587ff0e879f8cc3cee12309c000255d2b8a7eb 100644 (file)
@@ -20,10 +20,10 @@ public:
        sigc::signal<void, AInputQueue *> signal_input_queue_destroyed;
 
 private:
-       ANativeActivity *activity;
-       AAssetManager *asset_manager;
+       ANativeActivity *activity = nullptr;
+       AAssetManager *asset_manager = nullptr;
        FS::Path int_data_path;
-       bool starting_up;
+       bool starting_up = true;
        Mutex startup_mutex;
 
 public:
@@ -41,7 +41,7 @@ public:
        void set_window_flags(unsigned, unsigned);
 
 private:
-       virtual void main();
+       void main() override;
 
        static void app_created(void *);
        static void activity_destroyed(ANativeActivity *);
index 2c6dc967296edeba82336d724096650b4db34a94..c214a06316598b54ed59403493df366a60ca568f 100644 (file)
@@ -9,33 +9,33 @@
 #include <msp/io/print.h>
 #include <msp/strings/utils.h>
 #include "application.h"
+#include "except.h"
 #include "getopt.h"
 
 using namespace std;
 
 namespace Msp {
 
-Application *Application::app_ = 0;
-Application::Starter *Application::starter_ = 0;
-const char *Application::argv0_ = 0;
-string Application::name_;
-void *Application::data_ = 0;
+Application *Application::_app = nullptr;
+Application::Starter *Application::_starter = nullptr;
+const char *Application::_argv0 = nullptr;
+string Application::_name;
+void *Application::_data = nullptr;
 
-Application::Application(const string &n):
-       exit_code(0)
+Application::Application(const string &n)
 {
-       if(app_)
-               throw logic_error("instance already exists");
+       if(_app)
+               throw already_called("Application::Application");
 
        if(!n.empty())
-               name_ = n;
+               _name = n;
        else
-               name_ = FS::basename(argv0_);
+               _name = FS::basename(_argv0);
 }
 
 int Application::run(int argc, char **argv, void *data, void (*created_callback)(void *))
 {
-       if(!starter_)
+       if(!_starter)
        {
                IO::cerr.write("Application::run called with no RegisteredApplication class!\n");
                return 126;
@@ -47,7 +47,7 @@ int Application::run(int argc, char **argv, void *data, void (*created_callback)
        {
                try
                {
-                       app_ = starter_->create_app(argc, argv);
+                       _app = _starter->create_app(argc, argv);
                }
                catch(const usage_error &e)
                {
@@ -58,9 +58,9 @@ int Application::run(int argc, char **argv, void *data, void (*created_callback)
                if(created_callback)
                        created_callback(data);
 
-               int result = app_->main();
-               Application *a = app_;
-               app_ = 0;
+               int result = _app->main();
+               Application *a = _app;
+               _app = nullptr;
                delete a;
                return result;
        }
@@ -85,8 +85,8 @@ int Application::run(int argc, char **argv, void *data, void (*created_callback)
                        }
                }
 
-               delete app_;
-               app_ = 0;
+               delete _app;
+               _app = nullptr;
 
                return 124;
        }
@@ -94,8 +94,8 @@ 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");
+       if(_argv0)
+               throw already_called("Application::set_startup_info");
 
        static FS::Path exe;
 
@@ -114,8 +114,23 @@ void Application::set_startup_info(const char *argv0, void *data)
        if(exe.empty())
                exe = FS::realpath(argv0);
 
-       argv0_ = exe.c_str();
-       data_ = data;
+       _argv0 = exe.c_str();
+       _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()
@@ -129,7 +144,7 @@ int Application::main()
 
 void Application::catch_signal(int s)
 {
-       signal(s, &sighandler_);
+       signal(s, &_sighandler);
 }
 
 void Application::exit(int c)
@@ -138,18 +153,18 @@ void Application::exit(int c)
        exit_code = c;
 }
 
-void Application::sighandler_(int s)
+void Application::_sighandler(int s)
 {
-       app_->sighandler(s);
+       _app->sighandler(s);
 }
 
 
 Application::Starter::Starter()
 {
-       if(starter_)
-               throw logic_error("Can't create more than one Starter instance");
+       if(_starter)
+               throw already_called("Application::Starter::Starter");
 
-       starter_ = this;
+       _starter = this;
 }
 
 } // namespace Msp
index 93fccd8de94e9d6b300d66f37d5de2a82bb5840d..d5a571a28a9f73306dffae3e99b470e39a2fcb47 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <stdexcept>
 #include <string>
+#include "mspcore_api.h"
 #include "noncopyable.h"
 
 namespace Msp {
@@ -10,35 +11,33 @@ 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();
        public:
-               virtual ~Starter() { }
+               virtual ~Starter() = default;
 
                virtual Application *create_app(int, char **) = 0;
        };
 
-       bool done;
-       int exit_code;
+       bool done = false;
+       int exit_code = 0;
 
 private:
-       static Starter *starter_;
-       static Application *app_;
-       static const char *argv0_;
-       static std::string name_;
-       static void *data_;
-
-       Application(const Application &);
-       Application &operator=(const Application &);
+       static Starter *_starter;
+       static Application *_app;
+       static const char *_argv0;
+       static std::string _name;
+       static void *_data;
+
 protected:
        Application(const std::string & = std::string());
 public:
-       virtual ~Application() { }
+       virtual ~Application() = default;
 
        /** Constructs an instance of the registered application class and runs it.
        If the application throws a usage_error, a help message is printed.  The
@@ -46,7 +45,7 @@ public:
 
        This function can only be called once.  The global main() function provided
        by the library normally does it automatically at program startup. */
-       static int run(int, char **, void * = 0, void (*)(void *) = 0);
+       static int run(int, char **, void * = nullptr, void (*)(void *) = nullptr);
 
        /** Sets application startup info, including argv[0] value and platform-
        specific data.
@@ -55,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
@@ -78,7 +77,7 @@ protected:
 private:
        /** Static wrapper function to call a member function of the Application
        instance. */
-       static void sighandler_(int);
+       static void _sighandler(int);
 };
 
 
@@ -96,16 +95,16 @@ private:
                Application *create_app(int argc, char **argv) { return new T(argc, argv); }
        };
 
-       static Starter starter_;
+       static Starter _starter;
 
 protected:
        RegisteredApplication(const std::string &n = std::string()):
                Application(n)
-       { (void)starter_; }  // Force the starter into existence
+       { (void)_starter; }  // Force the starter into existence
 };
 
 template<typename T>
-typename RegisteredApplication<T>::Starter RegisteredApplication<T>::starter_;
+typename RegisteredApplication<T>::Starter RegisteredApplication<T>::_starter;
 
 } // namespace Msp
 
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 13e235f25152912a5f86466b129cd2a9bf5999c7..cbc0afb0d76e9d5eec8f79e4a835d1cf01ff7700 100644 (file)
@@ -6,8 +6,7 @@ using namespace std;
 
 namespace Msp {
 
-GetOpt::GetOpt():
-       help(false)
+GetOpt::GetOpt()
 {
        add_option("help", help, NO_ARG).set_help("Displays this help");
 }
@@ -318,9 +317,6 @@ GetOpt::OptionImpl::OptionImpl(char s, const string &l, const Store &t, ArgType
        shrt(s),
        lng(l),
        arg_type(a),
-       seen_count(0),
-       ext_seen_count(0),
-       metavar("ARG"),
        store(t.clone())
 { }
 
index 405864bb27bfdda1668537a35630550465963482..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 help_;
+       std::string m_help;
 
 public:
-       usage_error(const std::string &w, const std::string &h = std::string()): std::runtime_error(w), help_(h) { }
-       ~usage_error() throw() { }
+       usage_error(const std::string &w, const std::string &h = std::string()): std::runtime_error(w), m_help(h) { }
 
-       const char *help() const throw() { return 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,12 +69,12 @@ public:
                REQUIRED_ARG
        };
 
-       class Option
+       class MSPCORE_API Option
        {
        protected:
-               Option() { }
+               Option() = default;
        public:
-               virtual ~Option() { }
+               virtual ~Option() = default;
 
                /// Sets help text for the option.
                virtual Option &set_help(const std::string &) = 0;
@@ -89,12 +89,12 @@ public:
                virtual unsigned get_seen_count() const = 0;
        };
 
-       class Argument
+       class MSPCORE_API Argument
        {
        protected:
-               Argument() { }
+               Argument() = default;
        public:
-               virtual ~Argument() { }
+               virtual ~Argument() = default;
 
                virtual Argument &set_help(const std::string &) = 0;
        };
@@ -103,9 +103,9 @@ private:
        class Store
        {
        protected:
-               Store() { }
+               Store() = default;
        public:
-               virtual ~Store() { }
+               virtual ~Store() = default;
 
                virtual Store *clone() const = 0;
 
@@ -117,28 +117,28 @@ private:
        class OptionImpl: public Option
        {
        protected:
-               char shrt;
+               char shrt = 0;
                std::string lng;
-               ArgType arg_type;
-               unsigned seen_count;
-               unsigned *ext_seen_count;
+               ArgType arg_type = NO_ARG;
+               unsigned seen_count = 0;
+               unsigned *ext_seen_count = nullptr;
                std::string help;
-               std::string metavar;
-               Store *store;
+               std::string metavar = "ARG";
+               Store *store = nullptr;
 
        public:
                OptionImpl(char, const std::string &, const Store &, ArgType);
-               virtual ~OptionImpl();
+               ~OptionImpl() override;
 
-               virtual OptionImpl &set_help(const std::string &);
-               virtual OptionImpl &set_help(const std::string &, const std::string &);
-               virtual OptionImpl &bind_seen_count(unsigned &);
+               OptionImpl &set_help(const std::string &) override;
+               OptionImpl &set_help(const std::string &, const std::string &) override;
+               OptionImpl &bind_seen_count(unsigned &) override;
                char get_short() const { return shrt; }
                const std::string &get_long() const { return lng; }
                ArgType get_arg_type() const { return arg_type; }
                const std::string &get_help() const { return help; }
                const std::string &get_metavar() const { return metavar; }
-               virtual unsigned get_seen_count() const { return seen_count; }
+               unsigned get_seen_count() const override { return seen_count; }
                void process();
                void process(const std::string &);
        };
@@ -147,15 +147,15 @@ private:
        {
        private:
                std::string name;
-               ArgType type;
+               ArgType type = REQUIRED_ARG;
                std::string help;
-               Store *store;
+               Store *store = nullptr;
 
        public:
                ArgumentImpl(const std::string &, const Store &, ArgType);
-               virtual ~ArgumentImpl();
+               ~ArgumentImpl() override;
 
-               virtual ArgumentImpl &set_help(const std::string &);
+               ArgumentImpl &set_help(const std::string &) override;
                const std::string &get_name() const { return name; }
                ArgType get_type() const { return type; }
                const std::string &get_help() const { return help; }
@@ -172,14 +172,14 @@ private:
        public:
                SimpleStore(T &d): data(d) { }
 
-               virtual SimpleStore *clone() const
+               SimpleStore *clone() const override
                { return new SimpleStore(data); }
 
-               virtual bool is_list() const { return false; }
+               bool is_list() const override { return false; }
 
-               virtual void store() { }
+               void store() override { }
 
-               virtual void store(const std::string &a)
+               void store(const std::string &a) override
                { data = lexical_cast<T>(a); }
        };
 
@@ -192,18 +192,18 @@ private:
        public:
                ListStore(T &d): data(d) { }
 
-               virtual ListStore *clone() const
+               ListStore *clone() const override
                { return new ListStore(data); }
 
-               virtual bool is_list() const { return true; }
+               bool is_list() const override { return true; }
 
-               virtual void store() { }
+               void store() override { }
 
-               virtual void store(const std::string &a)
+               void store(const std::string &a) override
                { data.push_back(lexical_cast<typename T::value_type>(a)); }
        };
 
-       bool help;
+       bool help = false;
        std::vector<OptionImpl *> opts;
        std::vector<ArgumentImpl *> args;
        std::vector<std::string> args_raw;
diff --git a/source/core/hash.cpp b/source/core/hash.cpp
deleted file mode 100644 (file)
index fe5e339..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-#include <stdexcept>
-#include "hash.h"
-
-using namespace std;
-
-namespace Msp {
-
-/*
-http://en.wikipedia.org/wiki/Fowler-Noll-Vo_hash_function
-http://www.isthe.com/chongo/tech/comp/fnv/index.html
-*/
-
-UInt32 hash32(const void *data, unsigned size, unsigned bits)
-{
-       if(bits==0 || bits>32)
-               throw invalid_argument("hash32");
-
-       static const unsigned prime = 16777619;
-       static const unsigned offset = 2166136261U;
-
-       unsigned result = offset;
-       for(unsigned i=0; i<size; ++i)
-               result = (result^*(reinterpret_cast<const unsigned char *>(data)+i))*prime;
-
-       if(bits<32)
-               result = (result>>bits ^ result) & ((1<<bits)-1);
-
-       return result;
-}
-
-UInt64 hash64(const void *data, unsigned size, unsigned bits)
-{
-       if(bits==0 || bits>64)
-               throw invalid_argument("hash64");
-
-       static const UInt64 prime = 1099511628211ULL;
-       static const UInt64 offset = 14695981039346656037ULL;
-
-       UInt64 result = offset;
-       for(unsigned i=0; i<size; ++i)
-               result = (result^*(reinterpret_cast<const unsigned char *>(data)+i))*prime;
-
-       if(bits<64)
-               result = (result>>bits ^ result) & ((1ULL<<bits)-1);
-
-       return result;
-}
-
-} // namespace Msp
index d696cae5b63542e65d6718f1012d0606b9f55833..e2201cf22110280172828fff9021d4e1daa36036 100644 (file)
 #ifndef MSP_CORE_HASH_H_
 #define MSP_CORE_HASH_H_
 
+#include <cstdint>
+#include <limits>
 #include <string>
-#include "inttypes.h"
 
 namespace Msp {
 
+template<unsigned N, unsigned L = 3+(N>8)+(N>16)+(N>32)+(N>64)>
+struct HashTraits;
+
+template<>
+struct HashTraits<64, 6>
+{
+       using HashType = uint64_t;
+       using ResultType = uint64_t;
+       static constexpr HashType prime = 1099511628211ULL;
+       static constexpr HashType offset = 14695981039346656037ULL;
+       static constexpr bool folded = false;
+};
+
+template<>
+struct HashTraits<32, 5>
+{
+       using HashType = uint32_t;
+       using ResultType = uint32_t;
+       static constexpr HashType prime = 16777619;
+       static constexpr HashType offset = 2166136261U;
+       static constexpr bool folded = false;
+};
+
+template<unsigned N>
+struct HashTraits<N, 6>
+{
+       using HashType = uint64_t;
+       using ResultType = uint64_t;
+       static constexpr bool folded = true;
+};
+
+template<unsigned N>
+struct HashTraits<N, 5>
+{
+       using HashType = uint32_t;
+       using ResultType = uint32_t;
+       static constexpr bool folded = true;
+};
+
+template<unsigned N>
+struct HashTraits<N, 4>
+{
+       using HashType = uint32_t;
+       using ResultType = uint16_t;
+       static constexpr bool folded = true;
+};
+
+template<unsigned N>
+struct HashTraits<N, 3>
+{
+       using HashType = uint32_t;
+       using ResultType = uint8_t;
+       static constexpr bool folded = true;
+};
+
 /**
-Computes a 32-bit Fowler-Noll-Vo (FNV-1a) hash.  The number of bits can be
-limited to less than 32, in which case XOR-folding is used to reduce the hash
-size.
+Computes a single round of a hash, adding one byte of data.  N must be a native
+hash size.
 */
-UInt32 hash32(const void *, unsigned, unsigned = 32);
+template<unsigned N>
+typename HashTraits<N>::ResultType hash_round(typename HashTraits<N>::HashType result, uint8_t byte)
+{
+       constexpr typename HashTraits<N>::HashType prime = HashTraits<N>::prime;
+       return (result^byte)*prime;
+}
 
 /**
-Convenience function to compute a 32-bit hash of a string.
+Updates a previously computed hash by adding bytes to it.  N must be a native
+hash size.
 */
-inline unsigned hash32(const std::string &s, unsigned b = 32)
-{ return hash32(s.data(), s.size(), b); }
+template<unsigned N>
+typename HashTraits<N>::ResultType hash_update(typename HashTraits<N>::HashType result, const void *data, std::size_t size)
+{
+       const uint8_t *ptr = static_cast<const uint8_t *>(data);
+       for(unsigned i=0; i<size; ++i)
+               result = hash_round<N>(result, *ptr++);
+       return result;
+}
+
+template<unsigned N>
+typename HashTraits<N>::ResultType hash_update(typename HashTraits<N>::HashType result, const std::string &str)
+{ return hash_update<N>(result, str.data(), str.size()); }
+
+// For some reason this causes an ambiguity error without the enable_if.
+template<unsigned N, typename T>
+typename std::enable_if<!std::is_same<T, std::string>::value, typename HashTraits<N>::ResultType>::type hash_update(typename HashTraits<N>::HashType result, const T &obj)
+{ return hash_update<N>(result, &obj, sizeof(obj)); }
 
 /**
-Computes a 64-bit Fowler-Noll-Vo (FNV-1a) hash.  Note that even if bits is
-limited to 32 or less, this does not produce the same result as hash32.
+Manually folds a hash to a smaller size.
 */
-UInt64 hash64(const void *, unsigned, unsigned = 64);
+template<unsigned N, typename T>
+typename std::enable_if<N!=std::numeric_limits<T>::digits, typename HashTraits<N>::ResultType>::type hash_fold(T hash)
+{ return (hash>>N ^ hash) & ((T(1)<<N)-1); }
+
+template<unsigned N, typename T>
+typename std::enable_if<N==std::numeric_limits<T>::digits, typename HashTraits<N>::ResultType>::type hash_fold(T hash)
+{ return hash; }
 
 /**
-Convenience function to compute a 64-bit hash of a string.
+Computes an N-bit Fowler-Noll-Vo (FNV-1a) hash.  If N is not a native hash
+size, the next larger native hash is computed and XOR-folding is applied to
+the result.
+
+http://en.wikipedia.org/wiki/Fowler-Noll-Vo_hash_function
+http://www.isthe.com/chongo/tech/comp/fnv/index.html
 */
-inline UInt64 hash64(const std::string &s, unsigned b = 64)
-{ return hash64(s.data(), s.size(), b); }
+template<unsigned N>
+typename HashTraits<N>::ResultType hash(const void *data, std::size_t size)
+{
+       constexpr unsigned hash_bits = std::numeric_limits<typename HashTraits<N>::HashType>::digits;
+       typename HashTraits<N>::HashType result = hash_update<hash_bits>(HashTraits<hash_bits>::offset, data, size);
+       if(HashTraits<N>::folded)
+               result = hash_fold<N>(result);
+       return result;
+}
 
-inline UInt32 fold32(UInt64 hash)
-{ return hash^(hash>>32); }
+/**
+Convenience function to compute an N-bit hash of a string.
+*/
+template<unsigned N>
+typename HashTraits<N>::ResultType hash(const std::string &str)
+{ return hash<N>(str.data(), str.size()); }
 
-inline UInt16 fold16(UInt64 hash)
-{ return hash^(hash>>16)^(hash>>32)^(hash>>48); }
+/**
+Convenience function to compute an N-bit hash of any object.  The entire object
+representation is hashed, including any padding bytes.
+*/
+template<unsigned N, typename T>
+typename HashTraits<N>::ResultType hash(const T &obj)
+{ return hash<N>(&obj, sizeof(obj)); }
 
 } // namespace Msp
 
index 88f47cd367b60c3e85d72d075e59370971295c79..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>
@@ -47,7 +48,7 @@ public:
                runtime_error(make_what(typeid(T), MapUtilsInternal::stringify_key(k)))
        { }
 
-       virtual ~key_error() throw() { }
+       ~key_error() throw() override = default;
 
 private:
        static std::string make_what(const std::type_info &, const std::string &);
index 4a2f04c15ce7bb62f03c1976945317141e200106..64d761f363eb426b3c7c28a7e13f888617874f94 100644 (file)
@@ -2,16 +2,17 @@
 #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;
 
-       Private *priv;
+       Private *priv = nullptr;
 
 public:
        Module(const std::string &);
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 3d3dc84dd3bca28e65c0ea770b00cc6851b6f552..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,14 +11,14 @@ 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;
 
 private:
        struct Private;
 
-       Private *priv;
+       Private *priv = nullptr;
 
 public:
        Mutex();
@@ -38,7 +39,7 @@ public:
 /**
 Locks the mutex for the lifetime of the object.
 */
-class MutexLock
+class MSPCORE_API MutexLock
 {
 private:
        Mutex &mutex;
@@ -67,7 +68,7 @@ public:
 
        T &operator*() const { return *data; }
        T *operator->() const { return data; }
-       void clear() { mutex = 0; data = 0; }
+       void clear() { mutex = nullptr; data = nullptr; }
 };
 
 }
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 e9a6fe273ddd6008ed28929640ec5b730102283b..55d4a304ce08b1f91bef2fe9fce2b12146c41e4a 100644 (file)
@@ -1,9 +1,10 @@
 #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 = 0;
+       void *data = nullptr;
 
        /* Applications launched from Finder get a special argument, which would
        interfere with GetOpt.  Remove it from argv but pass it as data so it can
@@ -17,7 +18,7 @@ int main(int argc, char **argv)
                        argv[j++] = argv[i];
        }
        argc = j;
-       argv[j] = 0;
+       argv[j] = nullptr;
 
        return Msp::Application::run(argc, argv, data);
 }
index dfbea341310d19a039e4924ee122c1c0fd054f9d..4c5ed4651164615fc67b1d8a7c7523856876a233 100644 (file)
@@ -1,4 +1,5 @@
 #include <msp/io/console.h>
+#include "except.h"
 #include "process.h"
 #include "process_private.h"
 
@@ -6,30 +7,15 @@ using namespace std;
 
 namespace Msp {
 
-Process *Process::_self = 0;
+Process *Process::_self = nullptr;
 
 Process::Process(const Private &p):
        priv(new Private(p))
-{
-       init();
-}
+{ }
 
 Process::Process():
        priv(new Private)
-{
-       init();
-}
-
-void Process::init()
-{
-       redirect = false;
-       cin = 0;
-       cout = 0;
-       cerr = 0;
-       running = false;
-       finished = false;
-       exit_code = 0;
-}
+{ }
 
 Process &Process::self()
 {
@@ -93,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 55b62cd450c534309d72dd7d39fa96f2cedbfb1c..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;
@@ -30,20 +31,19 @@ public:
 private:
        struct Private;
 
-       Private *priv;
+       Private *priv = nullptr;
        FS::Path work_dir;
-       bool redirect;
-       IO::Base *cin;
-       IO::Base *cout;
-       IO::Base *cerr;
-       bool running;
-       bool finished;
-       unsigned exit_code;
+       bool redirect = false;
+       IO::Base *cin = nullptr;
+       IO::Base *cout = nullptr;
+       IO::Base *cerr = nullptr;
+       bool running = false;
+       bool finished = false;
+       unsigned exit_code = 0;
 
        static Process *_self;
 
        Process(const Private &);
-       void init();
 public:
        Process();
        ~Process();
index f6f4f2eace1d488953ccb510478d86add0602a63..fcae0f08e62947c15c21b41ac8e89a971ade0ec8 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef MSP_CORE_PROCESS_PRIVATE_H_
 #define MSP_CORE_PROCESS_PRIVATE_H_
 
+#include "process.h"
 #include "process_platform.h"
 
 namespace Msp {
index a2160a52c50b1799ce45d87903de94ff2474eaf5..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>
@@ -31,14 +29,14 @@ class RefPtr
        template<typename U> friend class WeakPtr;
 
 private:
-       T *data;
-       RefCounts *counts;
+       T *data = nullptr;
+       RefCounts *counts = nullptr;
 
 public:
-       RefPtr(): data(0), counts(0) { }
-       RefPtr(T *d): data(d), counts(data ? new RefCounts : 0) { incref(); }
+       RefPtr() = default;
+       RefPtr(T *d): data(d), counts(data ? new RefCounts : nullptr) { incref(); }
 private:
-       RefPtr(T *d, RefCounts *c): data(d), counts(d ? c : 0) { incref(); }
+       RefPtr(T *d, RefCounts *c): data(d), counts(d ? c : nullptr) { incref(); }
 
 public:
        /* Must have this or the compiler will generate a default copy-c'tor despite
@@ -49,7 +47,7 @@ public:
        RefPtr(const RefPtr<U> &p): data(p.data), counts(p.counts) { incref(); }
 
        template<typename U>
-       RefPtr(const WeakPtr<U> &p): data(p.get()), counts(data ? p.counts : 0) { incref(); }
+       RefPtr(const WeakPtr<U> &p): data(p.get()), counts(data ? p.counts : nullptr) { incref(); }
 
        ~RefPtr() { decref(); }
 
@@ -81,7 +79,7 @@ public:
        T *get() const { return data; }
        T &operator*() const { return *data; }
        T *operator->() const { return data; }
-       operator bool() const { return data!=0; }
+       explicit operator bool() const { return data; }
 
        unsigned refcount() const { return (data ? counts->count : 0); }
 
@@ -102,19 +100,19 @@ class WeakPtr
        template<typename U> friend class WeakPtr;
 
 private:
-       T *data;
-       RefCounts *counts;
+       T *data = nullptr;
+       RefCounts *counts = nullptr;
 
 public:
-       WeakPtr(): data(0), counts(0) { }
+       WeakPtr() = default;
 private:
-       WeakPtr(T *d, RefCounts *c): data(d), counts(d ? c : 0) { incref(); }
+       WeakPtr(T *d, RefCounts *c): data(d), counts(d ? c : nullptr) { incref(); }
 
 public:
-       WeakPtr(const WeakPtr &p): data(p.get()), counts(data ? p.counts : 0) { incref(); }
+       WeakPtr(const WeakPtr &p): data(p.get()), counts(data ? p.counts : nullptr) { incref(); }
 
        template<typename U>
-       WeakPtr(const WeakPtr<U> &p): data(p.get()), counts(data ? p.counts : 0) { incref(); }
+       WeakPtr(const WeakPtr<U> &p): data(p.get()), counts(data ? p.counts : nullptr) { incref(); }
 
        template<typename U>
        WeakPtr(const RefPtr<U> &p): data(p.data), counts(p.counts) { incref(); }
@@ -131,7 +129,7 @@ private:
        template<typename U>
        WeakPtr &assign(const WeakPtr<U> &);
 
-       T *get() const { return (counts && counts->count ? data : 0); }
+       T *get() const { return (counts && counts->count ? data : nullptr); }
        void incref() { if(counts) ++counts->weak_count; }
        void decref();
 };
@@ -142,7 +140,7 @@ RefPtr<T> &RefPtr<T>::operator=(T *d)
 {
        decref();
        data = d;
-       counts = (d ? new RefCounts : 0);
+       counts = (d ? new RefCounts : nullptr);
        incref();
        return *this;
 }
@@ -151,6 +149,9 @@ template<typename T>
 template<typename U>
 RefPtr<T> &RefPtr<T>::assign(const RefPtr<U> &p)
 {
+       if(static_cast<const void *>(&p)==this)
+               return *this;
+
        decref();
        data = p.data;
        counts = p.counts;
@@ -162,9 +163,9 @@ template<typename T>
 T *RefPtr<T>::release()
 {
        T *d = data;
-       data = 0;
+       data = nullptr;
        decref();
-       counts = 0;
+       counts = nullptr;
        return d;
 }
 
@@ -176,17 +177,17 @@ void RefPtr<T>::decref()
        if(!counts->count)
        {
                delete data;
-               data = 0;
+               data = nullptr;
        }
        else if(counts->count==RefCounts::KEEP)
-               data = 0;
+               data = nullptr;
        else
                return;
 
        if(!counts->weak_count)
        {
                delete counts;
-               counts = 0;
+               counts = nullptr;
        }
 }
 
@@ -195,9 +196,12 @@ template<typename T>
 template<typename U>
 WeakPtr<T> &WeakPtr<T>::assign(const WeakPtr<U> &p)
 {
+       if(&p==this)
+               return *this;
+
        decref();
        data = p.get();
-       counts = (data ? p.counts : 0);
+       counts = (data ? p.counts : nullptr);
        incref();
        return *this;
 }
@@ -210,8 +214,8 @@ void WeakPtr<T>::decref()
        if(!counts->weak_count && (!counts->count || counts->count==RefCounts::KEEP))
        {
                delete counts;
-               data = 0;
-               counts = 0;
+               data = nullptr;
+               counts = nullptr;
        }
 }
 
index 9ab25f2d48306471bcfd63b0439e501ee5f0fc37..f5042892a1825bf1650f16e8ad93f833790f90a3 100644 (file)
@@ -2,16 +2,17 @@
 #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;
 
-       Private *priv;
+       Private *priv = nullptr;
 
 public:
        Semaphore(unsigned);
index 5424ef0ee647d564a624eb4e190553d7a808f88e..c6fd341cfcec873e59bef36c161c851f33d4338c 100644 (file)
@@ -7,12 +7,12 @@ namespace Msp {
 
 system_error::system_error(const string &w, int c):
        runtime_error(w+": "+get_message(c)),
-       code_(c)
+       m_code(c)
 { }
 
 system_error::system_error(const string &w, const string &e):
        runtime_error(w+": "+e),
-       code_(numeric_limits<int>::min())
+       m_code(numeric_limits<int>::min())
 { }
 
 } // namespace Msp
index c6b516af9f5dddba7d435a6d02408a9f68820f0e..cce3c5c7e6ad4f8662171d6adf735d841f574f72 100644 (file)
@@ -3,20 +3,20 @@
 
 #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 code_;
+       int m_code;
 
 public:
        system_error(const std::string &, int = -1);
        system_error(const std::string &, const std::string &);
-       virtual ~system_error() throw() { }
 
-       int code() const throw() { return code_; }
+       int code() const noexcept { return m_code; }
 
 private:
        static std::string get_message(int);
index 721e8cfef51f2ff772c304ff9ece65554c3f033a..ad78d945cbd85e995d954ba6411964ccaa702421 100644 (file)
@@ -1,4 +1,4 @@
-#include <stdexcept>
+#include "except.h"
 #include "thread.h"
 #include "thread_private.h"
 
@@ -7,43 +7,42 @@ using namespace std;
 namespace Msp {
 
 Thread::Thread(const string &name):
-       priv_(new Private),
-       name_(name),
-       state_(PENDING)
+       _priv(new Private),
+       _name(name)
 { }
 
 Thread::~Thread()
 {
        kill();
        join();
-       delete priv_;
+       delete _priv;
 }
 
 void Thread::join()
 {
-       if(state_>=JOINED)
+       if(_state>=JOINED)
                return;
 
        platform_join();
-       state_ = JOINED;
+       _state = JOINED;
 }
 
 void Thread::kill()
 {
-       if(state_!=RUNNING)
+       if(_state!=RUNNING)
                return;
 
        platform_kill();
-       state_ = KILLED;
+       _state = KILLED;
 }
 
 void Thread::launch()
 {
-       if(state_>=RUNNING)
-               throw logic_error("already launched");
+       if(_state>=RUNNING)
+               throw already_called("Thread::launch");
 
        platform_launch();
-       state_ = RUNNING;
+       _state = RUNNING;
 }
 
 ThreadReturn THREAD_CALL Thread::Private::main_wrapper(void *arg)
@@ -51,7 +50,7 @@ ThreadReturn THREAD_CALL Thread::Private::main_wrapper(void *arg)
        Thread *thread = reinterpret_cast<Thread *>(arg);
        thread->platform_setname();
        thread->main();
-       thread->state_ = FINISHED;
+       thread->_state = FINISHED;
        return 0;
 }
 
index 6a17912fdc3c03e0d0904aeb768b8a40ee316212..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;
@@ -27,19 +28,19 @@ private:
                JOINED
        };
 
-       Private *priv_;
-       std::string name_;
-       State state_;
+       Private *_priv = nullptr;
+       std::string _name;
+       State _state = PENDING;
 
 protected:
        Thread(const std::string & = std::string());
 public:
        virtual ~Thread();
 
-       const std::string &get_name() const { return name_; }
+       const std::string &get_name() const { return _name; }
 
        /** Indicates whether the thread has finished running. */
-       bool is_finished() { return state_>=FINISHED; }
+       bool is_finished() { return _state>=FINISHED; }
 
        /** Waits for the thread to exit.  Calling this from the thread will cause a
        deadlock. */
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 dd5dc01ba2e1e96db0e9056d7d5a9202669814cb..193fe07fa9810d1426a4a430e53e26d9eeb802c4 100644 (file)
@@ -40,7 +40,7 @@ private:
 
                RegisteredType(const std::string &kw): TypeBase(kw) { }
 
-               virtual void invoke(T arg) const { action(this->keyword, arg); }
+               void invoke(T arg) const override { action(this->keyword, arg); }
        };
 
        std::map<std::string, TypeBase *> types;
index 434dba1b30c1f25d017897bf6925480aeaf166e0..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, 0);
+       return Msp::Application::run(argc, argv, nullptr);
 }
index 15e5c9a213dbce4893851d3641aa036b340be2ad..a23add577bb364c854499c976888663b961c5031 100644 (file)
@@ -9,7 +9,7 @@ namespace Msp {
 Mutex::Mutex():
        priv(new Private)
 {
-       pthread_mutex_init(&priv->mutex, 0);
+       pthread_mutex_init(&priv->mutex, nullptr);
 }
 
 Mutex::~Mutex()
index 99be2e1d75a592a87a07e926439add7a4a5bec17..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)
 {
@@ -35,7 +38,7 @@ void Process::execute(const string &command, bool path_search, const Arguments &
                        argv[0] = command.c_str();
                        for(unsigned i=0; i<args.size(); ++i)
                                argv[i+1] = args[i].c_str();
-                       argv[args.size()+1] = 0;
+                       argv[args.size()+1] = nullptr;
 
                        if(redirect)
                        {
@@ -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 81492585a52636d55f3934f07fa5e1da1c5a1ce1..f19bdab92d4da8c6ad636a8e7c796c6234f889fe 100644 (file)
@@ -14,17 +14,16 @@ struct Semaphore::Private
 {
        Mutex mutex;
        pthread_cond_t cond;
-       unsigned limit;
-       unsigned count;
+       unsigned limit = 1;
+       unsigned count = 0;
 };
 
 
 Semaphore::Semaphore(unsigned limit):
        priv(new Private)
 {
-       pthread_cond_init(&priv->cond, 0);
+       pthread_cond_init(&priv->cond, nullptr);
        priv->limit = limit;
-       priv->count = 0;
 }
 
 Semaphore::~Semaphore()
index 119d55f0571600a4b57de1bd1fea054acc1fb9d2..42231934c00ed6c58b9e0ec766bee7cecf7f3ebf 100644 (file)
@@ -7,24 +7,24 @@ namespace Msp {
 
 void Thread::platform_join()
 {
-       pthread_join(priv_->handle, 0);
+       pthread_join(_priv->handle, nullptr);
 }
 
 void Thread::platform_kill()
 {
-       pthread_kill(priv_->handle, SIGKILL);
+       pthread_kill(_priv->handle, SIGKILL);
 }
 
 void Thread::platform_launch()
 {
-       pthread_create(&priv_->handle, 0, &Private::main_wrapper, this);
+       pthread_create(&_priv->handle, nullptr, &Private::main_wrapper, this);
 }
 
 void Thread::platform_setname()
 {
 #if defined(__GLIBC__) && (__GLIBC__>2 || (__GLIBC__==2 && __GLIBC_MINOR__>=12))
-       if(!name_.empty())
-               pthread_setname_np(priv_->handle, name_.c_str());
+       if(!_name.empty())
+               pthread_setname_np(_priv->handle, _name.c_str());
 #endif
 }
 
index 5109dbcc11811ac8297f71e3903a1eb8c4f36f36..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() { }
 };
 
 
-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;
 
-               Store(const T &d): data(d) { }
+       const Functions *funcs = nullptr;
+       alignas(void *) char storage[INTERNAL_SIZE];
 
-               virtual const std::type_info &type_id() const { return typeid(T); }
-               virtual StoreBase *clone() const { return new Store<T>(data); }
-               virtual bool type_equals(const StoreBase &s) const { return dynamic_cast<const Store<T> *>(&s); }
-               virtual bool value_equals(const StoreBase &s) const { return value_equals_<T>(s); }
+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(); }
 
-               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); }
+       template<typename T, typename = EnableNotVariant<T>>
+       Variant &operator=(T &&v) { assign(std::forward<T>(v)); return *this; }
 
-               template<typename U>
-               typename std::enable_if<!IsEqualityComparable<U>::value, bool>::type value_equals_(const StoreBase &) const
-               { return false; }
-       };
+       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; }
 
-       StoreBase *store;
+       void clear();
+
+private:
+       template<typename T>
+       void assign(T &&);
+
+       void copy_from(const Variant &);
+       void move_from(Variant &&);
+
+       template<typename T>
+       T &get();
 
 public:
-       Variant(): store(0) { }
        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() : 0) { }
-       ~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)
-       {
-               delete store;
-               store = (v.store ? v.store->clone() : 0);
-               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)); }
+
+       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)!=0;
-       }
+       static EnableSmall<T, void> create(char *s, T &&v)
+       { new(s) typename std::remove_reference<T>::type(std::forward<T>(v)); }
 
-       bool check_same_type(const Variant &v) const
-       { return store && v.store && store->type_equals(*v.store); }
+       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)); }
+
+       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 829365088115289bcdedc0ebc315911f3bf3175c..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,12 +44,13 @@ Process::~Process()
 {
        CloseHandle(priv->info.hProcess);
        CloseHandle(priv->info.hThread);
+       delete priv;
 }
 
 void Process::platform_get_self_info(Private &priv)
 {
        priv.info.hProcess = GetCurrentProcess();
-       priv.info.hThread = 0;
+       priv.info.hThread = nullptr;
        priv.info.dwProcessId = GetCurrentProcessId();
        priv.info.dwThreadId = 0;
 }
@@ -61,12 +63,12 @@ void Process::execute(const string &command, bool path_search, const Arguments &
 
        STARTUPINFO startup;
        startup.cb = sizeof(STARTUPINFO);
-       startup.lpReserved = 0;
-       startup.lpDesktop = 0;
-       startup.lpTitle = 0;
+       startup.lpReserved = nullptr;
+       startup.lpDesktop = nullptr;
+       startup.lpTitle = nullptr;
        startup.dwFlags = 0;
        startup.cbReserved2 = 0;
-       startup.lpReserved2 = 0;
+       startup.lpReserved2 = nullptr;
        if(redirect)
        {
                startup.dwFlags |= STARTF_USESTDHANDLES;
@@ -78,9 +80,9 @@ void Process::execute(const string &command, bool path_search, const Arguments &
                HANDLE cerr_handle = (cerr ? *cerr->get_handle(IO::M_WRITE) : GetStdHandle(STD_ERROR_HANDLE));
                DuplicateHandle(self_handle, cerr_handle, self_handle, &startup.hStdError, 0, true, DUPLICATE_SAME_ACCESS);
        }
-       const char *cmdptr = (path_search ? 0 : command.c_str());
-       const char *wd = (work_dir.empty() ? 0 : work_dir.c_str());
-       if(!CreateProcess(cmdptr, const_cast<char *>(cmdline.c_str()), 0, 0, true, 0, 0, wd, &startup, &priv->info))
+       const char *cmdptr = (path_search ? nullptr : command.c_str());
+       const char *wd = (work_dir.empty() ? nullptr : work_dir.c_str());
+       if(!CreateProcess(cmdptr, const_cast<char *>(cmdline.c_str()), nullptr, nullptr, true, 0, nullptr, wd, &startup, &priv->info))
                throw system_error("CreateProcess");
 
        if(redirect)
@@ -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)
@@ -135,8 +137,8 @@ void Process::interrupt()
 
 Process::Private::Private()
 {
-       info.hProcess = 0;
-       info.hThread = 0;
+       info.hProcess = nullptr;
+       info.hThread = nullptr;
        info.dwProcessId = 0;
        info.dwThreadId = 0;
 }
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 98eb9ed221a3817052de50ffc7babb5797378ba8..754c90b9c25f13c420210d2c8290b5a99eb69452 100644 (file)
@@ -1,4 +1,4 @@
-#include <windows.h>
+#include "winapi.h"
 #include <msp/strings/lexicalcast.h>
 #include "systemerror.h"
 
@@ -11,7 +11,7 @@ string system_error::get_message(int c)
                c = GetLastError();
 
        char msg[1024];
-       if(FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, 0, c, 0, msg, sizeof(msg), 0))
+       if(FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, c, 0, msg, sizeof(msg), nullptr))
                return msg;
        else
                return lexical_cast<string>(c, Fmt().hex());
index ab02c4d04094394e384b91defd717b70ac5918df..3231896c7a7d7283c01f4d863a6cc9a05175ed08 100644 (file)
@@ -1,4 +1,4 @@
-#include <windows.h>
+#include "winapi.h"
 #include "thread.h"
 #include "thread_private.h"
 
@@ -6,18 +6,18 @@ namespace Msp {
 
 void Thread::platform_join()
 {
-       WaitForSingleObject(priv_->handle, INFINITE);
+       WaitForSingleObject(_priv->handle, INFINITE);
 }
 
 void Thread::platform_kill()
 {
-       TerminateThread(priv_->handle, 0);
+       TerminateThread(_priv->handle, 0);
 }
 
 void Thread::platform_launch()
 {
        DWORD dummy;  // Win9x needs the lpTthreadId parameter
-       priv_->handle = CreateThread(0, 0, &Private::main_wrapper, this, 0, &dummy);
+       _priv->handle = CreateThread(nullptr, 0, &Private::main_wrapper, this, 0, &dummy);
 }
 
 void Thread::platform_setname()
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 3f32ade0c4558478f633e93f02f9e9e29b261024..b8e06af27b9c400d1e6f3b741627a0e6e716ee04 100644 (file)
@@ -4,16 +4,17 @@
 #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
        {
-               void *address;
+               void *address = nullptr;
                std::string file;
                std::string symbol;
        };
@@ -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 e41eb9ad79f32152b92503d33168c6dd1a43d337..3ed3171960ff8decc29384d1216937c8042f35f4 100644 (file)
@@ -13,7 +13,7 @@ string demangle(const string &sym)
 {
 #ifdef __GNUC__
        int status;
-       char *dm = abi::__cxa_demangle(sym.c_str(), 0, 0, &status);
+       char *dm = abi::__cxa_demangle(sym.c_str(), nullptr, nullptr, &status);
        
        string result;
        if(status==0)
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 d4d51bcc4610a82fc6a28b7d6611f2d68275dd0a..6591c037ac68da524a76b740779c35549e5f7114 100644 (file)
@@ -3,17 +3,22 @@
 namespace Msp {
 namespace Debug {
 
-ErrorReporter *ErrorReporter::current = 0;
+ErrorReporter *ErrorReporter::_current = nullptr;
 
 ErrorReporter::ErrorReporter():
-       prev(current)
+       _prev(_current)
 {
-       current = this;
+       _current = this;
 }
 
 ErrorReporter::~ErrorReporter()
 {
-       current = prev;
+       _current = _prev;
+}
+
+const ErrorReporter *ErrorReporter::get_current()
+{
+       return _current;
 }
 
 } // namespace Debug
index 98806ddc72212df5d8ca7e321540fec105afcdcc..b702b7cfb10138a92e07c709b6058999f841481d 100644 (file)
@@ -2,24 +2,25 @@
 #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;
+       ErrorReporter *_prev = nullptr;
 
-       static ErrorReporter *current;
+       static ErrorReporter *_current;
 
 protected:
        ErrorReporter();
 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 8ffc9c81b988667cffa12d770c1a6e97e5244ba6..7a681c35010cee85277112cc2d5b9a5d7ec5fefa 100644 (file)
@@ -20,7 +20,7 @@ struct HookThrow
 
 HookThrow::HookThrow()
 {
-       void *handle = dlopen(0, RTLD_LAZY);
+       void *handle = dlopen(nullptr, RTLD_LAZY);
        orig_cxa_throw = reinterpret_cast<CxaThrowType *>(dlvsym(handle, "__cxa_throw", "CXXABI_1.3"));
        dlclose(handle);
 }
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 c82558b01f6e119720e7d119d5c2cf6d2ef36a65..65cc71ced0876d6863f7613d6f99561e6a82244b 100644 (file)
@@ -7,11 +7,6 @@ using namespace std;
 namespace Msp {
 namespace Debug {
 
-Profiler::Profiler():
-       period(0),
-       inner(0)
-{ }
-
 void Profiler::set_period(unsigned p)
 {
        if(p==period)
@@ -96,13 +91,5 @@ const Profiler::ScopeInfo &Profiler::get_scope(const string &sn) const
        return get_item(scopes, sn);
 }
 
-
-Profiler::ScopeInfo::ScopeInfo():
-       calls(0),
-       calls_per_sec(0),
-       hist_pos(0),
-       hist_full(false)
-{ }
-
 } // namespace Debug
 } // namespace Msp
index 521ce959c5de7cae234c04ae8de5861ac3f6b42e..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,39 +26,35 @@ 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;
+               unsigned calls = 0;
                Time::TimeDelta total_time;
                Time::TimeDelta self_time;
                Time::TimeDelta avg_time;
-               float calls_per_sec;
+               float calls_per_sec = 0;
                std::vector<CallInfo> history;
-               unsigned hist_pos;
-               bool hist_full;
+               unsigned hist_pos = 0;
+               bool hist_full = false;
                std::map<std::string, unsigned> called_from;
-
-               ScopeInfo();
        };
 
 private:
-       unsigned period;
+       unsigned period = 0;
        std::map<std::string, ScopeInfo> scopes;
-       ProfilingScope *inner;
+       ProfilingScope *inner = nullptr;
 
 public:
-       Profiler();
-
        /** Sets the averaging period for timing data, measured in calls.  Previous
        average timings are cleared. */
        void set_period(unsigned p);
index 4e4294e0269d04346c04e1c364d75f870fb231ee..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,18 +14,16 @@ 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;
        std::string name;
-       ProfilingScope *parent;
+       ProfilingScope *parent = nullptr;
        Time::TimeStamp entry_time;
        Time::TimeDelta time_spent;
        Time::TimeDelta child_time;
 
-       ProfilingScope(const ProfilingScope &);
-       ProfilingScope &operator=(const ProfilingScope &);
 public:
        ProfilingScope(Profiler &p, const std::string &n);
        ~ProfilingScope();
index 45fba304e76907325247e140476fd05b8127b9d7..48823e948372ae6f237eb906656683ff9464b1de 100644 (file)
@@ -9,17 +9,27 @@ namespace FS {
 
 void Stat::Private::fill_owner_info(Stat::OwnerInfo &result)
 {
-       struct passwd *owner;
-       if((owner = getpwuid(owner_id)))
-               result.owner = owner->pw_name;
+       if(owner_id!=INVALID_UID)
+       {
+               struct passwd *owner;
+               if((owner = getpwuid(owner_id)))
+                       result.owner = owner->pw_name;
+               else
+                       result.owner = format("%d", owner_id);
+       }
        else
-               result.owner = format("%d", owner_id);
+               result.owner = "None";
 
-       struct group *group;
-       if((group = getgrgid(group_id)))
-               result.group = group->gr_name;
+       if(group_id!=INVALID_GID)
+       {
+               struct group *group;
+               if((group = getgrgid(group_id)))
+                       result.group = group->gr_name;
+               else
+                       result.group = format("%d", group_id);
+       }
        else
-               result.group = format("%d", group_id);
+               result.group = "None";
 }
 
 } // namespace FS
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 c0a1c7460324f3163715d5c119b0fea701b3517e..960be2e00c0559e258c6f2edbd7e3863e3f6cb84 100644 (file)
@@ -4,63 +4,64 @@
 #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 &);
-       virtual ~not_a_directory() throw() { }
+       ~not_a_directory() throw() override = default;
 };
 
 /// 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 5ff5b7818b59f5d6c16b4d5da042eb0ec3e197cc..5ff6392a352fe4e06af3e97f0371d1b19d67c10b 100644 (file)
@@ -1,4 +1,5 @@
 #include <msp/core/algorithm.h>
+#include <msp/core/except.h>
 #include "filemonitor.h"
 #include "filemonitor_platform.h"
 
@@ -8,8 +9,7 @@ namespace Msp {
 namespace FS {
 
 FileMonitor::FileMonitor():
-       priv(new Private(*this)),
-       event_disp(0)
+       priv(new Private(*this))
 { }
 
 FileMonitor::~FileMonitor()
@@ -20,7 +20,7 @@ FileMonitor::~FileMonitor()
 void FileMonitor::use_event_dispatcher(IO::EventDispatcher &ed)
 {
        if(event_disp)
-               throw logic_error("event_disp!=0");
+               throw already_called("FileMonitor::use_event_dispatcher");
 
        event_disp = &ed;
        platform_use_event_dispatcher();
@@ -30,7 +30,6 @@ void FileMonitor::add_file(const FS::Path &path)
 {
        MonitoredFile file;
        file.path = path;
-       file.modified = false;
        prepare_file(file);
        files.push_back(file);
 }
index e96aff66637d239b5fd31a996ce544d4eb385bbc..3ce5d79db2dc991ac562e0bb30f44df5cf11dee7 100644 (file)
@@ -1,15 +1,15 @@
 #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>
-#include <msp/io/eventobject.h>
 
 namespace Msp {
 namespace FS {
 
-class FileMonitor: NonCopyable
+class MSPCORE_API FileMonitor: NonCopyable
 {
 private:
        struct Private;
@@ -17,16 +17,16 @@ private:
        struct MonitoredFile
        {
                FS::Path path;
-               bool modified;
-               int tag;
+               bool modified = false;
+               int tag = -1;
        };
 
 public:
        sigc::signal<void, const FS::Path &> signal_file_modified;
 
 private:
-       Private *priv;
-       IO::EventDispatcher *event_disp;
+       Private *priv = nullptr;
+       IO::EventDispatcher *event_disp = nullptr;
        std::vector<MonitoredFile> files;
 
 public:
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 a5a5a10a5532133582172da6abcdf93acdf62ea6..1181b923c1054f894c5f0e188119e067c6508566 100644 (file)
@@ -17,20 +17,7 @@ inline bool is_windows_drive(const string &p)
 namespace Msp {
 namespace FS {
 
-Path::Path()
-{ }
-
 Path::Path(const string &p)
-{
-       init(p);
-}
-
-Path::Path(const char *p)
-{
-       init(p);
-}
-
-void Path::init(const string &p)
 {
        if(p.empty())
                return;
@@ -146,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 e0b593caf2099839d2f517deb2a3b2b0e4e89ffb..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;
@@ -70,13 +71,10 @@ private:
        PositionArray separators;
 
 public:
-       Path();
+       Path() = default;
        Path(const std::string &);
-       Path(const char *);
-private:
-       void init(const std::string &);
+       Path(const char *p): Path(std::string(p)) { }
 
-public:
        /// Returns the path as a string.
        const std::string &str() const { return path; }
 
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 2269ae1a016fcf5b1857cb499fd4f21a24d62820..e296ead3816b9317ecd44f0bc82bf6fbd12cbbed 100644 (file)
@@ -7,20 +7,6 @@ using namespace std;
 namespace Msp {
 namespace FS {
 
-Stat::Private::Private():
-       owner_id(0),
-       group_id(0)
-{ }
-
-
-Stat::Stat():
-       exists(false),
-       type(UNKNOWN),
-       size(0),
-       alloc_size(0),
-       priv(0)
-{ }
-
 Stat::Stat(const Stat &other):
        exists(other.exists),
        type(other.type),
@@ -28,11 +14,14 @@ Stat::Stat(const Stat &other):
        alloc_size(other.alloc_size),
        mtime(other.mtime),
        owner_info(other.owner_info),
-       priv(other.priv ? new Private(*other.priv) : 0)
+       priv(other.priv ? new Private(*other.priv) : nullptr)
 { }
 
 Stat &Stat::operator=(const Stat &other)
 {
+       if(&other==this)
+               return *this;
+
        exists = other.exists;
        type = other.type;
        size = other.size;
@@ -40,7 +29,7 @@ Stat &Stat::operator=(const Stat &other)
        mtime = other.mtime;
        owner_info = other.owner_info;
        delete priv;
-       priv = (other.priv ? new Private(*other.priv) : 0);
+       priv = (other.priv ? new Private(*other.priv) : nullptr);
 
        return *this;
 }
index 3f056a5609eea802716037eb734c3d42ef51905d..fd6a2f75ba6092e7f72181b95b7c8fb332428fe8 100644 (file)
@@ -1,8 +1,9 @@
 #ifndef MSP_FS_STAT_H_
 #define MSP_FS_STAT_H_
 
+#include <cstdint>
 #include <string>
-#include <msp/core/inttypes.h>
+#include <msp/core/mspcore_api.h>
 #include <msp/time/timestamp.h>
 #include "path.h"
 
@@ -17,12 +18,12 @@ enum FileType
        SYMLINK
 };
 
-typedef UInt64 FileSize;
+typedef uint64_t FileSize;
 
 /**
 Holds file information.
 */
-class Stat
+class MSPCORE_API Stat
 {
 private:
        struct Private;
@@ -33,16 +34,16 @@ private:
                std::string group;
        };
 
-       bool exists;
-       FileType type;
-       FileSize size;
-       FileSize alloc_size;
+       bool exists = false;
+       FileType type = UNKNOWN;
+       FileSize size = 0;
+       FileSize alloc_size = 0;
        Time::TimeStamp mtime;
        mutable OwnerInfo owner_info;
-       Private *priv;
+       Private *priv = nullptr;
 
 public:
-       Stat();
+       Stat() = default;
        Stat(const Stat &);
        Stat &operator=(const Stat &);
        ~Stat();
@@ -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 7b20638d36ed5b5a1e75d2f14ce9fb102dfc44c0..23019a5b6982c22df324cee04ea3a16de7cd60e9 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef MSP_FS_STAT_PRIVATE_H_
 #define MSP_FS_STAT_PRIVATE_H_
 
+#include "stat.h"
 #include "stat_platform.h"
 
 namespace Msp {
@@ -8,10 +9,10 @@ namespace FS {
 
 struct Stat::Private
 {
-       UserID owner_id;
-       GroupID group_id;
+       UserID owner_id = INVALID_UID;
+       GroupID group_id = INVALID_GID;
 
-       Private();
+       Private() = default;
        Private(const Private &);
        ~Private();
 
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 ed900bfeb7a2faa49f79197a5b9126719b546977..a6e67a6b72edccd3070a03eb0100105013f77699 100644 (file)
@@ -1,6 +1,10 @@
 #ifndef MSP_FS_FILEMONITOR_PLATFORM_H_
 #define MSP_FS_FILEMONITOR_PLATFORM_H_
 
+#include <msp/fs/path.h>
+#include <msp/io/eventobject.h>
+#include "filemonitor.h"
+
 namespace Msp {
 namespace FS {
 
@@ -16,16 +20,16 @@ public:
        int add_watch(const FS::Path &, int);
        void remove_watch(int);
 
-       virtual void set_block(bool) { }
-       virtual void set_inherit(bool) { }
+       void set_block(bool) override { }
+       void set_inherit(bool) override { }
 
 protected:
-       virtual std::size_t do_write(const char *, std::size_t);
-       virtual std::size_t do_read(char *, std::size_t);
+       std::size_t do_write(const char *, std::size_t) override;
+       std::size_t do_read(char *, std::size_t) override;
 
 public:
-       virtual const IO::Handle &get_handle(IO::Mode) { return fd; }
-       virtual const IO::Handle &get_event_handle() { return fd; }
+       const IO::Handle &get_handle(IO::Mode) override { return fd; }
+       const IO::Handle &get_event_handle() override { return fd; }
 };
 
 
index 1a33d74efc0d862df0cbf85f3e1bd8a4a9ff5b11..9c643d9cf92c3533d8f80ee4df3b4649e567e4d6 100644 (file)
@@ -11,19 +11,29 @@ void Stat::Private::fill_owner_info(Stat::OwnerInfo &result)
 {
        char buf[1024];
 
-       struct passwd pw;
-       struct passwd *owner;
-       if(!getpwuid_r(owner_id, &pw, buf, sizeof(buf), &owner) && owner)
-               result.owner = owner->pw_name;
+       if(owner_id!=INVALID_UID)
+       {
+               struct passwd pw;
+               struct passwd *owner;
+               if(!getpwuid_r(owner_id, &pw, buf, sizeof(buf), &owner) && owner)
+                       result.owner = owner->pw_name;
+               else
+                       result.owner = format("%d", owner_id);
+       }
        else
-               result.owner = format("%d", owner_id);
+               result.owner = "None";
 
-       struct group gr;
-       struct group *group;
-       if(!getgrgid_r(group_id, &gr, buf, sizeof(buf), &group) && group)
-               result.group = group->gr_name;
+       if(group_id!=INVALID_GID)
+       {
+               struct group gr;
+               struct group *group;
+               if(!getgrgid_r(group_id, &gr, buf, sizeof(buf), &group) && group)
+                       result.group = group->gr_name;
+               else
+                       result.group = format("%d", group_id);
+       }
        else
-               result.group = format("%d", group_id);
+               result.group = "None";
 }
 
 } // namespace FS
index cc3f0957b58100d5c0e52cb1f67f851d75769e25..d888fed3d38180a13b1c45a4d79d1281b7f56112 100644 (file)
@@ -9,6 +9,9 @@ namespace FS {
 typedef uid_t UserID;
 typedef gid_t GroupID;
 
+const UserID INVALID_UID = -1;
+const GroupID INVALID_GID = -1;
+
 } // namespace FS
 } // namespace Msp
 
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 c6f6b9b6bd29893535ca64dd5b4423b5a39a8ad0..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>
@@ -28,7 +28,7 @@ vector<string> list_filtered(const Path &path, const string &filter)
        vector<string> result;
        WIN32_FIND_DATA entry;
        string pattern = path.str()+"\\*";
-       HANDLE search_handle = FindFirstFileEx(pattern.c_str(), FindExInfoBasic, &entry, FindExSearchNameMatch, 0, 0);
+       HANDLE search_handle = FindFirstFileEx(pattern.c_str(), FindExInfoBasic, &entry, FindExSearchNameMatch, nullptr, 0);
        if(search_handle==INVALID_HANDLE_VALUE)
        {
                DWORD err = GetLastError();
index 4c3b8668438d52d09c1b4816e745563b544dd75e..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;
@@ -10,7 +11,7 @@ namespace FS {
 Path get_home_dir()
 {
        char home[MAX_PATH];
-       if(SHGetFolderPath(0, CSIDL_PERSONAL, 0, 0, home)==S_OK)
+       if(SHGetFolderPath(nullptr, CSIDL_PERSONAL, nullptr, 0, home)==S_OK)
                return home;
        return ".";
 }
@@ -19,10 +20,10 @@ 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(0, CSIDL_LOCAL_APPDATA, 0, 0, datadir)==S_OK)
+       if(SHGetFolderPath(nullptr, CSIDL_LOCAL_APPDATA, nullptr, 0, datadir)==S_OK)
                return Path(datadir)/appname;
        return ".";
 }
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 392ec4b1208039e15b220e44593d1758459847e2..60bb86cfc695de822452f56253d79b4737b39f27 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef MSP_FS_FILEMONITOR_PLATFORM_H_
 #define MSP_FS_FILEMONITOR_PLATFORM_H_
 
+#include "filemonitor.h"
+
 namespace Msp {
 namespace FS {
 
index ac9e0c977ac537fcd97bb9230b794ba7f334cc8a..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>
@@ -13,7 +13,7 @@ namespace {
 PSID copy_sid(PSID sid)
 {
        if(!sid || !IsValidSid(sid))
-               return 0;
+               return nullptr;
        DWORD len = GetLengthSid(sid);
        PSID copy = reinterpret_cast<PSID>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len));
        if(!CopySid(len, copy, sid))
@@ -32,7 +32,7 @@ string get_account_name(PSID sid)
        char domain[1024];
        DWORD dlen = sizeof(domain);
        SID_NAME_USE use;
-       if(!LookupAccountSid(0, sid, name, &nlen, domain, &dlen, &use))
+       if(!LookupAccountSid(nullptr, sid, name, &nlen, domain, &dlen, &use))
                throw Msp::system_error("LookupAccountSid");
        return Msp::format("%s/%s", name, domain);
 }
@@ -50,20 +50,20 @@ Stat::Private::Private(const Private &other):
 
 Stat::Private::~Private()
 {
-       if(owner_id)
+       if(owner_id!=INVALID_UID)
                HeapFree(GetProcessHeap(), 0, owner_id);
-       if(group_id)
+       if(group_id!=INVALID_GID)
                HeapFree(GetProcessHeap(), 0, group_id);
 }
 
 void Stat::Private::fill_owner_info(Stat::OwnerInfo &result)
 {
-       if(owner_id)
+       if(owner_id!=INVALID_UID)
                result.owner = get_account_name(owner_id);
        else
                result.owner = "None";
 
-       if(group_id)
+       if(group_id!=INVALID_GID)
                result.group = get_account_name(group_id);
        else
                result.group = "None";
@@ -73,7 +73,7 @@ void Stat::Private::fill_owner_info(Stat::OwnerInfo &result)
 Stat Stat::stat(const Path &path)
 {
        HANDLE handle;
-       handle = CreateFile(path.str().c_str(), READ_CONTROL, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS, 0);
+       handle = CreateFile(path.str().c_str(), READ_CONTROL, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS, nullptr);
        if(handle==INVALID_HANDLE_VALUE)
        {
                DWORD err = GetLastError();
@@ -102,10 +102,10 @@ Stat Stat::stat(const Path &path)
        result.mtime = Time::TimeStamp(Time::filetime_to_rawtime(info.ftLastWriteTime));
 
        PSECURITY_DESCRIPTOR sec_desc;
-       PSID owner = 0;
-       PSID group = 0;
+       PSID owner = nullptr;
+       PSID group = nullptr;
        const SECURITY_INFORMATION sec_info = OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION;
-       DWORD err = GetSecurityInfo(handle, SE_FILE_OBJECT, sec_info, &owner, &group, 0, 0, &sec_desc);
+       DWORD err = GetSecurityInfo(handle, SE_FILE_OBJECT, sec_info, &owner, &group, nullptr, nullptr, &sec_desc);
        if(err)
        {
                CloseHandle(handle);
index 4e8cfbc3799d2f18d90f791dd6e0d92060fb7dd5..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 {
@@ -9,6 +9,9 @@ namespace FS {
 typedef PSID UserID;
 typedef PSID GroupID;
 
+const UserID INVALID_UID = nullptr;
+const GroupID INVALID_GID = nullptr;
+
 } // namespace FS
 } // namespace Msp
 
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 1b97eae3d1f7a5177575043521d893feaa4ff894..3e03034760f03bf75fb87190933406b336d19ced 100644 (file)
@@ -34,8 +34,9 @@ Asset::~Asset()
        delete priv;
 }
 
-unsigned Asset::do_read(char *buf, unsigned size)
+size_t Asset::do_read(char *buf, size_t size)
 {
+       // The function actually returns an int, despite taking size_t
        int ret = AAsset_read(priv->asset, buf, size);
        if(ret<0)
                throw runtime_error("Asset::do_read");
index 526133e3c383a95a49a6438676fb025c2e0981c3..d605ff49573cb2e329513ea2d722023945de302b 100644 (file)
@@ -1,3 +1,4 @@
+#include <msp/core/except.h>
 #include "asset.h"
 
 using namespace std;
@@ -7,22 +8,22 @@ 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");
 }
 
-unsigned Asset::do_write(const char *, unsigned)
+size_t Asset::do_write(const char *, size_t)
 {
        throw invalid_access(M_WRITE);
 }
 
 const Handle &Asset::get_handle(Mode)
 {
-       throw logic_error("Asset::get_handle");
+       throw unsupported("Asset::get_handle");
 }
 
 } // namespace IO
index c5b98cbfe9abe764fe2945ee964daa904ad00d05..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,29 +12,29 @@ 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;
 
-       Private *priv;
+       Private *priv = nullptr;
 
 public:
        Asset(const std::string &);
        ~Asset();
 
-       virtual void set_block(bool);
-       virtual void set_inherit(bool);
+       void set_block(bool) override;
+       void set_inherit(bool) override;
 
 private:
-       virtual unsigned do_write(const char *, unsigned);
-       virtual unsigned do_read(char *, unsigned);
+       std::size_t do_write(const char *, std::size_t) override;
+       std::size_t do_read(char *, std::size_t) override;
 
 public:
-       virtual const Handle &get_handle(Mode);
+       const Handle &get_handle(Mode) override;
 
-       virtual SeekOffset seek(SeekOffset, SeekType);
-       virtual SeekOffset tell() const;
+       SeekOffset seek(SeekOffset, SeekType) override;
+       SeekOffset tell() const override;
 };
 
 } // namespace IO
index 9c2b40a1f2a9460eee16a34f6e0b08aab245786c..b8c13d2193060f94f957178f8f01052c62593d41 100644 (file)
@@ -6,10 +6,7 @@ using namespace std;
 namespace Msp {
 namespace IO {
 
-Base::Base():
-       mode(M_READ),
-       eof_flag(false),
-       mutex(0)
+Base::Base()
 { }
 
 Base::~Base()
index 7bd5bd9e963a4be383f2407a50fdf8a6f1c07d3e..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
@@ -42,9 +43,9 @@ public:
        sigc::signal<void> signal_deleted;
 
 protected:
-       Mode mode;
-       bool eof_flag;
-       Mutex *mutex;
+       Mode mode = M_READ;
+       bool eof_flag = false;
+       Mutex *mutex = nullptr;
 
        Base();
 public:
index 77a5f45cef353e2771842f0b197f7cc48d443f35..9f001fbe9ae94b944611f368416799ceab836a04 100644 (file)
@@ -1,5 +1,5 @@
 #include <cstring>
-#include <stdexcept>
+#include <msp/core/except.h>
 #include "buffered.h"
 #include "handle.h"
 
@@ -13,8 +13,7 @@ Buffered::Buffered(Base &b, unsigned s):
        buf_size(s),
        buf(new char[buf_size]),
        begin(buf),
-       end(buf),
-       cur_op(M_NONE)
+       end(buf)
 {
        mode = below.get_mode();
        below.signal_flush_required.connect(sigc::mem_fun(this, &Buffered::flush));
@@ -34,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()
@@ -180,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 eeae3e4008bb3bc46629c6927323e3570bfa2747..c05fc25eed5ad9454448d34f60a716ed091d56cb 100644 (file)
@@ -2,40 +2,41 @@
 #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;
-       std::size_t buf_size;
-       char *buf;
-       char *begin;
-       char *end;
-       Mode cur_op;
+       std::size_t buf_size = 0;
+       char *buf = nullptr;
+       char *begin = nullptr;
+       char *end = nullptr;
+       Mode cur_op = M_NONE;
 
 public:
        Buffered(Base &, unsigned = 8192);
        ~Buffered();
 
-       virtual void set_block(bool);
-       virtual void set_inherit(bool);
+       void set_block(bool) override;
+       void set_inherit(bool) override;
 
        void flush();
 
 protected:
-       virtual std::size_t do_write(const char *, std::size_t);
-       virtual std::size_t do_read(char *, std::size_t);
+       std::size_t do_write(const char *, std::size_t) override;
+       std::size_t do_read(char *, std::size_t) override;
 public:
-       virtual std::size_t put(char);
+       std::size_t put(char) override;
 
-       bool getline(std::string &);
-       int get();
+       bool getline(std::string &) override;
+       int get() override;
 
-       virtual const Handle &get_handle(Mode);
+       const Handle &get_handle(Mode) override;
 
 private:
        void set_op(Mode);
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 1200086014e4dae5a82196dd48667c31dfe551a3..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
@@ -31,8 +32,8 @@ private:
 public:
        ~Console();
 
-       virtual void set_block(bool);
-       virtual void set_inherit(bool);
+       void set_block(bool) override;
+       void set_inherit(bool) override;
        
        /** If local echo is enabled, characters will appear on the console as they
        are typed.  Can only be used on an input Console.  */
@@ -54,19 +55,20 @@ public:
        void redirect(Base &);
 
 protected:
-       virtual std::size_t do_write(const char *, std::size_t);
-       virtual std::size_t do_read(char *, std::size_t);
+       std::size_t do_write(const char *, std::size_t) override;
+       std::size_t do_read(char *, std::size_t) override;
 
 public:
-       virtual const Handle &get_handle(Mode);
-       virtual const Handle &get_event_handle() { return handle; }
+       const Handle &get_handle(Mode) override;
+       const Handle &get_event_handle() override { return handle; }
 
        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 462e8bbd263ee0b962fdeac9176527fed9a87218..7d5ab5bf099e408593313218e2b70bef74aa43f6 100644 (file)
@@ -3,8 +3,7 @@
 namespace Msp {
 namespace IO {
 
-EventObject::EventObject():
-       events(P_NONE)
+EventObject::EventObject()
 { }
 
 EventObject::~EventObject()
@@ -12,8 +11,8 @@ EventObject::~EventObject()
 
 void EventObject::set_events(PollEvent e)
 {
-       events = e;
-       signal_events_changed.emit(events);
+       _events = e;
+       signal_events_changed.emit(_events);
 }
 
 void EventObject::event(PollEvent ev)
index 88a71c7dbac804db31ac8d22ad56dc4199c455ed..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
@@ -25,17 +26,17 @@ public:
        sigc::signal<void, PollEvent> signal_events_changed;
 
 private:
-       PollEvent events;
+       PollEvent _events = P_NONE;
 
 protected:
        EventObject();
-       virtual ~EventObject();
+       ~EventObject() override;
 
        void set_events(PollEvent);
 public:
        /** Returns a mask of the currently interesting events.  Used by
        EventDispatcher. */
-       PollEvent get_events() const { return events; }
+       PollEvent get_events() const { return _events; }
 
        /** Returns a handle for polling. */
        virtual const Handle &get_event_handle() = 0;
index 3c01f09ed8605cca3b518762700d4c85421bbfe0..11091ab98556a511e6d50720533815b91438f2a0 100644 (file)
@@ -25,17 +25,17 @@ private:
        struct Private;
 
        Handle &handle;
-       Private *priv;
+       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 aeac6c8d265556974ddfee94febdb8ea5fd131b7..2af56ae67b2264913dcc3fa376ba5cde023c63b5 100644 (file)
@@ -3,26 +3,24 @@
 
 #include <stdexcept>
 #include <string>
+#include <msp/core/mspcore_api.h>
 #include "buffered.h"
-#include "filtered.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() { }
 };
 
-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() { }
 };
 
 
@@ -31,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
@@ -55,22 +53,22 @@ public:
 private:
        void platform_init(const std::string &, CreateMode);
 public:
-       virtual ~File();
+       ~File() override;
 
-       virtual void set_block(bool);
-       virtual void set_inherit(bool);
+       void set_block(bool) override;
+       void set_inherit(bool) override;
 
 protected:
-       virtual std::size_t do_write(const char *, std::size_t);
-       virtual std::size_t do_read(char *, std::size_t);
+       std::size_t do_write(const char *, std::size_t) override;
+       std::size_t do_read(char *, std::size_t) override;
 
 public:
-       virtual void sync();
+       void sync();
 
-       virtual SeekOffset seek(SeekOffset, SeekType);
-       virtual SeekOffset tell() const;
+       SeekOffset seek(SeekOffset, SeekType) override;
+       SeekOffset tell() const override;
 
-       virtual const Handle &get_handle(Mode);
+       const Handle &get_handle(Mode) override;
 };
 
 inline File::CreateMode operator|(File::CreateMode m, File::CreateMode n)
@@ -83,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;
@@ -93,22 +91,22 @@ private:
 public:
        BufferedFile(const std::string &, Mode = M_READ, File::CreateMode = File::C_OVERWRITE);
 
-       virtual void set_block(bool);
-       virtual void set_inherit(bool);
+       void set_block(bool) override;
+       void set_inherit(bool) override;
 
 protected:
-       virtual std::size_t do_write(const char *, std::size_t);
-       virtual std::size_t do_read(char *, std::size_t);
+       std::size_t do_write(const char *, std::size_t) override;
+       std::size_t do_read(char *, std::size_t) override;
 public:
-       virtual std::size_t put(char);
+       std::size_t put(char) override;
 
-       virtual bool getline(std::string &);
-       virtual int get();
+       bool getline(std::string &) override;
+       int get() override;
 
-       virtual const Handle &get_handle(Mode);
+       const Handle &get_handle(Mode) override;
 
-       virtual SeekOffset seek(SeekOffset, SeekType);
-       virtual SeekOffset tell() const { return position; }
+       SeekOffset seek(SeekOffset, SeekType) override;
+       SeekOffset tell() const override { return position; }
 };
 
 } // namespace IO
diff --git a/source/io/filtered.h b/source/io/filtered.h
deleted file mode 100644 (file)
index 2092743..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-#ifndef MSP_IO_FILTERED_H_
-#define MSP_IO_FILTERED_H_
-
-namespace Msp {
-namespace IO {
-
-/**
-This class is broken by design.  Do not use.  It exposes base class methods in
-an unsafe and misleading way.  In particular, a Filtered<File, Buffered> causes
-seeks to behave incorrectly.
-*/
-template<typename B, typename F>
-class Filtered: public B
-{
-private:
-       struct Activator
-       {
-               Filtered &f;
-
-               Activator(Filtered &f_): f(f_) { f.active = true; }
-               ~Activator() { f.active = false; }
-       };
-
-       F filter;
-       bool active;
-
-public:
-       Filtered(): filter(*this), active(false) { }
-       ~Filtered() { active = true; }
-
-       template<typename A0>
-       Filtered(A0 a0): B(a0), filter(*this), active(false) { }
-
-       template<typename A0, typename A1>
-       Filtered(A0 a0, A1 a1): B(a0, a1), filter(*this), active(false) { }
-
-protected:
-       virtual unsigned do_write(const char *b, unsigned s)
-       {
-               if(!active)
-               {
-                       Activator a(*this);
-                       return filter.write(b, s);
-               }
-               else
-                       return B::do_write(b, s);
-       }
-
-       virtual unsigned do_read(char *b, unsigned s)
-       {
-               if(!active)
-               {
-                       Activator a(*this);
-                       return filter.read(b, s);
-               }
-               else
-                       return B::do_read(b, s);
-       }
-
-public:
-       virtual unsigned put(char c)
-       {
-               if(active)
-                       return B::put(c);
-
-               Activator a(*this);
-               return filter.put(c);
-       }
-
-       virtual bool getline(std::string &l)
-       {
-               if(active)
-                       return B::getline(l);
-
-               Activator a(*this);
-               return filter.getline(l);
-       }
-
-       virtual int get()
-       {
-               if(active)
-                       return B::get();
-                       
-               Activator a(*this);
-               return filter.get();
-       }
-
-       F &get_filter() { return filter; }
-};
-
-} // namespace IO
-} // namespace Msp
-
-#endif
index 7971f1b0346eeff7d848ca1a2c7f67183e4a3d03..b5cad9a47ce1b34097a8f716009aa972fda7e74d 100644 (file)
@@ -28,7 +28,7 @@ Asset::~Asset()
        delete priv;
 }
 
-unsigned Asset::do_read(char *buf, unsigned size)
+size_t Asset::do_read(char *buf, size_t size)
 {
        return priv->file->read(buf, size);
 }
index 693f93f4c1dbf16e052645c416d582b16702e361..53b5a7e4fbf8643a1a2347e4540593f63d72de1c 100644 (file)
@@ -25,9 +25,9 @@ Handle::~Handle()
        delete priv;
 }
 
-Handle::operator const void *() const
+Handle::operator bool() const
 {
-       return priv->handle!=INVALID_HANDLE_VALUE ? this : 0;
+       return priv->handle!=INVALID_HANDLE_VALUE;
 }
 
 
index be2097e7f248d042c95312185ec40a25e3dca55b..06c2034c5271995995fd2929027cc1951fcf9d7d 100644 (file)
@@ -2,17 +2,18 @@
 #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;
 
 private:
-       Private *priv;
+       Private *priv = nullptr;
 
 public:
        Handle();
@@ -23,10 +24,7 @@ public:
        Private &operator*() { return *priv; }
        const Private &operator*() const { return *priv; }
 
-       /** This is effectively a boolean conversion, but avoids accidental
-       conversion to OS native handles.  Unix-based systems use int and win32 uses
-       void *; const void * is not implicitly convertible to either. */
-       operator const void *() const;
+       explicit operator bool() const;
 };
 
 
index 616150f0ab72937e40989ae19dcdd401d5a95981..0539fdbc4245f3c9c9ada441bf2aefdbcf0c0707 100644 (file)
@@ -1,5 +1,6 @@
 #include <algorithm>
 #include <cstring>
+#include <msp/core/except.h>
 #include "handle.h"
 #include "memory.h"
 
@@ -8,43 +9,34 @@ using namespace std;
 namespace Msp {
 namespace IO {
 
-Memory::Memory(char *d, size_t s, Mode m)
-{
-       init(d, d+s, m);
-}
+Memory::Memory(char *d, std::size_t s, Mode m):
+       Memory(d, d+s, m)
+{ }
 
-Memory::Memory(char *b, char *e, Mode m)
+Memory::Memory(char *b, char *e, Mode m):
+       begin(b),
+       end(e),
+       pos(begin)
 {
-       init(b, e, m);
+       mode = m;
 }
 
-Memory::Memory(const char *cd, size_t s)
-{
-       char *d = const_cast<char *>(cd);
-       init(d, d+s, M_READ);
-}
+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)
-{
-       init(const_cast<char *>(b), const_cast<char *>(e), M_READ);
-}
-
-void Memory::init(char *b, char *e, Mode m)
-{
-       begin = b;
-       end = e;
-       pos = begin;
-       mode = m;
-}
+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)
@@ -115,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 5b9961c9a38728f7357fc1741e379c593589afdd..e009cfdd24965d701d745e4dd865734615d4e85c 100644 (file)
@@ -1,42 +1,40 @@
 #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;
-       char *end;
-       char *pos;
+       char *begin = nullptr;
+       char *end = nullptr;
+       char *pos = nullptr;
 
 public:
-       Memory(char *, std::size_t, Mode = M_RDWR);
+       Memory(char *d, std::size_t s, Mode m = M_RDWR);
        Memory(char *, char *, Mode = M_RDWR);
-       Memory(const char *, std::size_t);
-       Memory(const char *, const char *);
-private:
-       void init(char *, char *, Mode);
+       Memory(const char *d, std::size_t s);
+       Memory(const char *b, const char *e);
 
-public:
-       virtual void set_block(bool);
-       virtual void set_inherit(bool);
+       void set_block(bool) override;
+       void set_inherit(bool) override;
 
 private:
-       virtual std::size_t do_write(const char *, std::size_t);
-       virtual std::size_t do_read(char *, std::size_t);
+       std::size_t do_write(const char *, std::size_t) override;
+       std::size_t do_read(char *, std::size_t) override;
 public:
-       virtual std::size_t put(char);
-       virtual bool getline(std::string &);
-       virtual int get();
+       std::size_t put(char) override;
+       bool getline(std::string &) override;
+       int get() override;
 
-       virtual const Handle &get_handle(Mode);
+       const Handle &get_handle(Mode) override;
 
-       virtual SeekOffset seek(SeekOffset, SeekType);
-       virtual SeekOffset tell() const { return pos-begin; }
+       SeekOffset seek(SeekOffset, SeekType) override;
+       SeekOffset tell() const override { return pos-begin; }
 };
 
 } // namespace IO
index 0f7bb4fc37650cabe29389021d9c06be0b64bebe..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() { }
 };
 
 } // namespace IO
index 01bf20aaea32c056b33e2213dafdd1d0515c3f1e..f6bc335d4216a48e820f9bd98c10c1e9b8c761f3 100644 (file)
@@ -43,15 +43,19 @@ void Pipe::set_mode(Mode m)
 void Pipe::set_block(bool b)
 {
        adjust_mode(mode, M_NONBLOCK, !b);
-       sys_set_blocking(read_handle, b);
-       sys_set_blocking(write_handle, b);
+       if(read_handle)
+               sys_set_blocking(read_handle, b);
+       if(write_handle)
+               sys_set_blocking(write_handle, b);
 }
 
 void Pipe::set_inherit(bool i)
 {
        adjust_mode(mode, M_INHERIT, i);
-       sys_set_inherit(read_handle, i);
-       sys_set_inherit(write_handle, i);
+       if(read_handle)
+               sys_set_inherit(read_handle, i);
+       if(write_handle)
+               sys_set_inherit(write_handle, i);
 }
 
 size_t Pipe::do_write(const char *buf, size_t size)
index 5fc0b3d6006fa485c7c2f18ad2127cff064fdc1e..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;
@@ -23,16 +24,16 @@ public:
        ~Pipe();
 
        void set_mode(Mode);
-       virtual void set_block(bool);
-       virtual void set_inherit(bool);
+       void set_block(bool) override;
+       void set_inherit(bool) override;
 
 protected:
-       virtual std::size_t do_write(const char *, std::size_t);
-       virtual std::size_t do_read(char *, std::size_t);
+       std::size_t do_write(const char *, std::size_t) override;
+       std::size_t do_read(char *, std::size_t) override;
 
 public:
-       virtual const Handle &get_handle(Mode);
-       virtual const Handle &get_event_handle() { return reader.get_event(); }
+       const Handle &get_handle(Mode) override;
+       const Handle &get_event_handle() override { return reader.get_event(); }
 };
 
 } // namespace IO
index 4ca2f3d9767ea3315d172ba25dd51831afb7f660..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"
@@ -10,9 +10,7 @@ namespace Msp {
 namespace IO {
 
 Poller::Poller():
-       priv(new Private),
-       events_changed(false),
-       objs_changed(false)
+       priv(new Private)
 { }
 
 Poller::~Poller()
@@ -46,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;
 }
 
@@ -93,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 0fb1ebc700a86126822464b3ec3c4bdcfd45e5a4..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,24 +32,22 @@ 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;
                PollEvent events;
-
-               PolledObject(EventObject *o, PollEvent e): object(o), events(e) { }
        };
 
 private:
        struct Private;
 
        std::vector<PolledObject> objects;
-       Private *priv;
-       bool events_changed;
-       bool objs_changed;
+       Private *priv = nullptr;
+       bool events_changed = false;
+       bool objs_changed = false;
        std::vector<PolledObject> poll_result;
 
 public:
@@ -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 f0170b40f5af126de2c641431d7a2033cc1f1415..e549d24c5dd7b8a0527b4cb9fc4e039ce887ad91 100644 (file)
@@ -1,8 +1,9 @@
 #ifndef MSP_IO_SEEKABLE_H_
 #define MSP_IO_SEEKABLE_H_
 
+#include <cstdint>
 #include <stdexcept>
-#include <msp/core/inttypes.h>
+#include <msp/core/mspcore_api.h>
 #include "base.h"
 
 namespace Msp {
@@ -10,7 +11,7 @@ namespace IO {
 
 class Handle;
 
-typedef Int64 SeekOffset;
+typedef std::int64_t SeekOffset;
 
 enum SeekType
 {
@@ -20,18 +21,18 @@ enum SeekType
 };
 
 
-class bad_seek: public std::runtime_error
+class MSPCORE_API bad_seek: public std::runtime_error
 {
 public:
        bad_seek(SeekOffset, SeekType);
-       virtual ~bad_seek() throw() { }
+       ~bad_seek() throw() override = default;
 };
 
 
-class Seekable: public Base
+class MSPCORE_API Seekable: public Base
 {
 protected:
-       Seekable() { }
+       Seekable() = default;
 
 public:
        /** Changes the read/write offset.  Returns the new offset. */
index 09a9768023bad9e1fa00be0d398ac45a6933442c..b256b117098b96a64f337c5c73b5f28818f77627 100644 (file)
@@ -106,7 +106,7 @@ void Serial::set_parameters(const string &params)
        state.apply_to(handle);
 }
 
-unsigned Serial::do_write(const char *buf, unsigned size)
+size_t Serial::do_write(const char *buf, size_t size)
 {
        if(size==0)
                return 0;
@@ -114,12 +114,12 @@ unsigned Serial::do_write(const char *buf, unsigned size)
        return sys_write(handle, buf, size);
 }
 
-unsigned Serial::do_read(char *buf, unsigned size)
+size_t Serial::do_read(char *buf, size_t size)
 {
        if(size==0)
                return 0;
 
-       unsigned ret = reader.read(buf, size);
+       size_t ret = reader.read(buf, size);
        if(ret==0)
                set_eof();
 
index dbc7a77bd0578159d12a8ae3b0d202290a604162..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
@@ -29,14 +30,14 @@ public:
 private:
        void platform_init(const std::string &);
 public:
-       virtual ~Serial();
+       ~Serial() override;
 
 private:
        void close();
 
 public:
-       virtual void set_block(bool);
-       virtual void set_inherit(bool);
+       void set_block(bool) override;
+       void set_inherit(bool) override;
 
        void set_baud_rate(unsigned);
        void set_data_bits(unsigned);
@@ -45,12 +46,12 @@ public:
        void set_parameters(const std::string &);
 
 private:
-       virtual unsigned do_write(const char *, unsigned);
-       virtual unsigned do_read(char *, unsigned);
+       std::size_t do_write(const char *, std::size_t) override;
+       std::size_t do_read(char *, std::size_t) override;
 
 public:
-       virtual const Handle &get_handle(Mode);
-       virtual const Handle &get_event_handle() { return reader.get_event(); }
+       const Handle &get_handle(Mode) override;
+       const Handle &get_event_handle() override { return reader.get_event(); }
 };
 
 } // namespace IO
index 4007a5e22f1e83cd690c8e278c4a584b1d431aa4..9ca5966c30acd1c03a18af313bbad5cc34737c81 100644 (file)
@@ -1,4 +1,4 @@
-#include <stdexcept>
+#include <msp/core/except.h>
 #include "slice.h"
 
 using namespace std;
@@ -9,12 +9,10 @@ namespace IO {
 Slice::Slice(Seekable &b, SeekOffset s, SeekOffset l):
        below(b),
        start_offset(s),
-       length(l),
-       position(0),
-       sync_position(true)
+       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;
@@ -23,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()
@@ -110,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 8ca4327415ff29f16d19decee872a7f0234185d9..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,37 +17,37 @@ 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;
-       SeekOffset start_offset;
-       SeekOffset length;
-       SeekOffset position;
-       bool sync_position;
+       SeekOffset start_offset = 0;
+       SeekOffset length = 0;
+       SeekOffset position = 0;
+       bool sync_position = true;
 
 public:
        Slice(Seekable &, SeekOffset, SeekOffset);
 
-       virtual void set_block(bool);
-       virtual void set_inherit(bool);
+       void set_block(bool) override;
+       void set_inherit(bool) override;
 
 private:
        void flush();
 
        unsigned prepare_op(unsigned, Mode);
 protected:
-       virtual std::size_t do_write(const char *, std::size_t);
-       virtual std::size_t do_read(char *, std::size_t);
+       std::size_t do_write(const char *, std::size_t) override;
+       std::size_t do_read(char *, std::size_t) override;
 
 public:
-       virtual std::size_t put(char);
-       virtual int get();
+       std::size_t put(char) override;
+       int get() override;
 
-       virtual const Handle &get_handle(Mode);
+       const Handle &get_handle(Mode) override;
 
-       virtual SeekOffset seek(SeekOffset, SeekType);
-       virtual SeekOffset tell() const { return position; }
+       SeekOffset seek(SeekOffset, SeekType) override;
+       SeekOffset tell() const override { return position; }
 };
 
 } // namespace IO
index fcbc892fdd2d518fffbda590050bb57805e73ae2..b87a347897334d5aee851d705d29337c21128e6d 100644 (file)
@@ -3,9 +3,8 @@
 namespace Msp {
 namespace IO {
 
-EventReader::EventReader(Handle &h, unsigned):
-       handle(h),
-       priv(0)
+EventReader::EventReader(Handle &h, size_t):
+       handle(h)
 { }
 
 EventReader::~EventReader()
@@ -22,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 b241669e93e7bf8d865acfad01ae2043fa907897..4254687623215443b03e5f83215c4929b73da2de 100644 (file)
@@ -6,7 +6,7 @@ namespace IO {
 
 typedef int PlatformHandle;
 
-#define INVALID_HANDLE_VALUE -1
+const PlatformHandle INVALID_HANDLE_VALUE = -1;
 
 } // namespace IO
 } // namespace Msp
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 bfd83da7a7042c42c251b9a66d8589534dc3b6bb..0166b9835746a54c980dab41dfc2b34db1f18a31 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <poll.h>
 #include <vector>
+#include "poll.h"
 
 namespace Msp {
 namespace IO {
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 eee51cc57d28a6b365fb2e7da57fedeb358c32e5..2b80cc71a6c8ad20dd267b188de5bec7993d974f 100644 (file)
@@ -4,9 +4,9 @@
 namespace Msp {
 namespace IO {
 
-unsigned read_all(Base &obj, char *buf, unsigned size)
+size_t read_all(Base &obj, char *buf, size_t size)
 {
-       unsigned pos = 0;
+       size_t pos = 0;
        while(pos<size)
                pos += obj.read(buf+pos, size-pos);
 
index 8d4f9dd692c769f86b2a2aea71d4522eec9b7bbf..4507f5c8046ca7e35b6a35a14dd990834b4fefc0 100644 (file)
@@ -1,6 +1,9 @@
 #ifndef MSP_IO_UTILS_H_
 #define MSP_IO_UTILS_H_
 
+#include <cstddef>
+#include <msp/core/mspcore_api.h>
+
 namespace Msp {
 namespace IO {
 
@@ -12,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. */
-unsigned read_all(Base &, char *, unsigned);
+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 82d9e8c2a297a48dbe202eeace2edfbafc035328..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"
@@ -13,28 +13,25 @@ struct EventReader::Private
 {
        OVERLAPPED overlapped;
        Handle event;
-       unsigned buf_size;
-       char *buffer;
-       unsigned buf_avail;
-       char *buf_next;
-       bool pending;
-       bool eof;
+       size_t buf_size = 0;
+       char *buffer = nullptr;
+       size_t buf_avail = 0;
+       char *buf_next = nullptr;
+       bool pending = false;
+       bool eof = false;
 };
 
 
-EventReader::EventReader(Handle &h, unsigned size):
+EventReader::EventReader(Handle &h, size_t size):
        handle(h),
        priv(new Private)
 {
        memset(&priv->overlapped, 0, sizeof(OVERLAPPED));
-       *priv->event = CreateEvent(0, true, false, 0);
+       *priv->event = CreateEvent(nullptr, true, false, nullptr);
        priv->overlapped.hEvent = *priv->event;
        priv->buf_size = size;
        priv->buffer = new char[priv->buf_size];
-       priv->buf_avail = 0;
        priv->buf_next = priv->buffer;
-       priv->pending = false;
-       priv->eof = false;
 }
 
 EventReader::~EventReader()
@@ -95,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 3cbdc4a8ddaf5c6b4c91672479ebf4b1a1383c21..a388ade8fd687ae9db3c4bb5351e4f0e9332b8a4 100644 (file)
@@ -35,10 +35,10 @@ void File::platform_init(const string &fn, CreateMode cm)
 
        SECURITY_ATTRIBUTES sec_attr;
        sec_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
-       sec_attr.lpSecurityDescriptor = 0;
+       sec_attr.lpSecurityDescriptor = nullptr;
        sec_attr.bInheritHandle = !!(mode&M_INHERIT);
 
-       *handle = CreateFile(fn.c_str(), flags, share_flags, 0, create_flags, FILE_ATTRIBUTE_NORMAL, &sec_attr);
+       *handle = CreateFile(fn.c_str(), flags, share_flags, &sec_attr, create_flags, FILE_ATTRIBUTE_NORMAL, nullptr);
        if(!handle)
        {
                int err = GetLastError();
index 1cdf8ce208ed881d0d5510bc0efb3a93122640ca..e72282a4f98b0eaec2d8e5df50d3011850639e8f 100644 (file)
@@ -20,10 +20,10 @@ 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, 0)==0)
+       if(ReadFile(*handle, buf, size, &ret, nullptr)==0)
                throw system_error("ReadFile");
 
        return ret;
@@ -32,10 +32,10 @@ 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, 0)==0)
+       if(WriteFile(*handle, buf, size, &ret, nullptr)==0)
                throw system_error("WriteFile");
 
        return ret;
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 02d7f339f6485186b87c5311ef9241f6d0623a5b..70d256ceacc55e906e2b7adbdf93f613ee2cc569 100644 (file)
@@ -11,11 +11,11 @@ namespace IO {
 void Pipe::platform_init()
 {
        string name = format("\\\\.\\pipe\\%u.%p", GetCurrentProcessId(), this);
-       *read_handle = CreateNamedPipe(name.c_str(), PIPE_ACCESS_INBOUND|FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE, 1, 1024, 1024, 0, 0);
+       *read_handle = CreateNamedPipe(name.c_str(), PIPE_ACCESS_INBOUND|FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE, 1, 1024, 1024, 0, nullptr);
        if(!read_handle)
                throw system_error("CreateNamedPipe");
 
-       *write_handle = CreateFile(name.c_str(), GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
+       *write_handle = CreateFile(name.c_str(), GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, nullptr);
        if(!write_handle)
        {
                unsigned err = GetLastError();
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 ccf92c306a005872d530478a57fd080eba03d0db..62a000f5a748bab027f073df389e30a427f67407 100644 (file)
@@ -1,8 +1,9 @@
 #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"
 
 namespace Msp {
 namespace IO {
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 84a3175f875c4b0b774f1b5e1c1004db1d6bd351..d041c8705ba3305105f7e806cbcdce98a1e20493 100644 (file)
@@ -13,7 +13,7 @@ void Serial::platform_init(const string &port)
 {
        string name = "\\\\.\\"+port;
 
-       *handle = CreateFile(name.c_str(), GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, 0);
+       *handle = CreateFile(name.c_str(), GENERIC_READ|GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, nullptr);
        if(!handle)
                throw system_error(format("CreateFile(%s)", port));
        mode = M_READ|M_WRITE;
@@ -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 2220bcc46f063372698915a95e1ad1a45d1f74f0..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;
@@ -14,7 +15,7 @@ zlib_error::zlib_error(const string &w, int c):
 #else
        runtime_error(w),
 #endif
-       code_(c)
+       m_code(c)
 { }
 
 
@@ -30,23 +31,13 @@ struct ZlibCompressed::Private
 ZlibCompressed::Private::Private()
 {
 #ifdef WITH_ZLIB
-       stream.zalloc = 0;
-       stream.zfree = 0;
-       stream.opaque = 0;
+       stream.zalloc = nullptr;
+       stream.zfree = nullptr;
+       stream.opaque = nullptr;
 #endif
 }
 
 
-ZlibCompressed::ZlibCompressed(Base &b, unsigned level):
-       below(b)
-{
-       mode = below.get_mode()&M_RDWR;
-       if(mode!=M_READ && mode!=M_WRITE)
-               throw invalid_access(mode);
-
-       init(level);
-}
-
 ZlibCompressed::ZlibCompressed(Base &b, Mode m, unsigned level):
        below(b)
 {
@@ -54,16 +45,7 @@ ZlibCompressed::ZlibCompressed(Base &b, Mode m, unsigned level):
        if(mode!=M_READ && mode!=M_WRITE)
                throw invalid_access(m);
 
-       init(level);
-}
-
-void ZlibCompressed::init(unsigned level)
-{
 #ifdef WITH_ZLIB
-       buffer_size = 1024;
-       in_buffer = 0;
-       out_buffer = 0;
-       stream_end = false;
        priv = new Private;
 
        if(mode==M_WRITE)
@@ -92,7 +74,7 @@ void ZlibCompressed::init(unsigned level)
        (void)buffer_size;
        (void)stream_end;
        (void)level;
-       throw zlib_error("unsupported", -1);
+       throw unsupported("ZlibCompressed");
 #endif
 }
 
@@ -115,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()
@@ -280,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 e4ae6e08f852f9b6228f7ff0f4b415d80a08de81..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 code_;
+       int m_code;
 
 public:
        zlib_error(const std::string &, int);
-       ~zlib_error() throw() { }
 
-       int code() const throw() { return code_; }
+       int code() const noexcept { return m_code; }
 };
 
 /**
@@ -28,41 +28,37 @@ 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;
 
        Base &below;
-       std::size_t buffer_size;
-       unsigned char *in_buffer;
-       unsigned char *out_buffer;
-       bool stream_end;
-       Private *priv;
+       std::size_t buffer_size = 1024;
+       unsigned char *in_buffer = nullptr;
+       unsigned char *out_buffer = nullptr;
+       bool stream_end = false;
+       Private *priv = nullptr;
 
 public:
        /** Creates a zlib de/compression object.  The underlying object must be
        open for reading or writing, not both.  The level parameter determines
        compression quality, ranging from 1 (fastest) to 9 (best compression). */
-       ZlibCompressed(Base &, unsigned level = 9);
+       ZlibCompressed(Base &b, unsigned level = 9): ZlibCompressed(b, b.get_mode()&M_RDWR, level) { }
 
        /** Creates a zlib de/compression object.  Mode must be either read or
        write, and compatible with the underlying object. */
        ZlibCompressed(Base &, Mode, unsigned level = 9);
 
-private:
-       void init(unsigned);
-
-public:
-       virtual ~ZlibCompressed();
+       ~ZlibCompressed() override;
 
-       virtual void set_block(bool);
-       virtual void set_inherit(bool);
+       void set_block(bool) override;
+       void set_inherit(bool) override;
 
        void flush();
 
 protected:
-       virtual std::size_t do_write(const char *, std::size_t);
+       std::size_t do_write(const char *, std::size_t) override;
 
 private:
        /** Compresses data and writes it to the underlying object.  Returns true if
@@ -72,9 +68,9 @@ private:
        bool compress_data(int flush_mode);
 
 public:
-       virtual std::size_t do_read(char *, std::size_t);
+       std::size_t do_read(char *, std::size_t) override;
 
-       virtual const Handle &get_handle(Mode);
+       const Handle &get_handle(Mode) override;
 };
 
 } // namespace IO
index 69804942b08eae42b5dff3620f2394da10c85ff7..755edebce30995cd98baff4102ece87ec2f9e753 100644 (file)
@@ -1,35 +1,36 @@
 #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) { }
 
-               virtual void encode_char(unichar, std::string &);
+               void encode_char(unichar, std::string &) override;
        private:
-               virtual void transliterate(unichar, std::string &);
+               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) { }
 
-               virtual unichar decode_char(const std::string &, std::string::const_iterator &);
+               unichar decode_char(const std::string &, std::string::const_iterator &) override;
        };
 
        Ascii(ErrorMode em = DEFAULT): StandardCodec<Ascii>(em) { }
 
-       virtual const char *get_name() const { return "ASCII"; }
+       const char *get_name() const override { return "ASCII"; }
 };
 
 } // namespace StringCodec
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 1b893470c6e9462993d10953e36952b4fc08b6d1..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,14 +37,14 @@ 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;
+               ErrorMode err_mode = THROW_ON_ERROR;
 
                Encoder(ErrorMode em): err_mode(em==DEFAULT ? THROW_ON_ERROR : em) { }
        public:
-               virtual ~Encoder() { }
+               virtual ~Encoder() = default;
 
                /** Encodes a single unicode character.  If the character can't be
                represented in this encoding, error() should be called. */
@@ -87,14 +88,14 @@ public:
 
        Each codec class should contain an Decoder class derived from this.
        */
-       class Decoder
+       class MSPCORE_API Decoder
        {
        protected:
-               ErrorMode err_mode;
+               ErrorMode err_mode = THROW_ON_ERROR;
 
                Decoder(ErrorMode em): err_mode(em==DEFAULT ? THROW_ON_ERROR : em) { }
        public:
-               virtual ~Decoder() { }
+               virtual ~Decoder() = default;
 
                /** Decodes a single character from a string.  The iterator is advanced
                to the next character.  For stateful codecs, -1 may be returned if a
@@ -131,9 +132,9 @@ public:
        };
 
 protected:
-       Codec() { }
+       Codec() = default;
 public:
-       virtual ~Codec() { }
+       virtual ~Codec() = default;
 
        /** Returns the name of the encoding handled by this codec. */
        virtual const char *get_name() const = 0;
@@ -162,7 +163,7 @@ template<typename C>
 class StandardCodec: public Codec
 {
 private:
-       ErrorMode err_mode;
+       ErrorMode err_mode = THROW_ON_ERROR;
 
 protected:
        StandardCodec(ErrorMode em): err_mode(em==DEFAULT ? THROW_ON_ERROR : em) { }
@@ -171,10 +172,10 @@ protected:
        { return (em==DEFAULT ? err_mode : em); }
 
 public:
-       virtual Encoder *create_encoder(ErrorMode em = DEFAULT) const
+       Encoder *create_encoder(ErrorMode em = DEFAULT) const override
        { return new typename C::Encoder(get_error_mode(em)); }
 
-       virtual Decoder *create_decoder(ErrorMode em = DEFAULT) const
+       Decoder *create_decoder(ErrorMode em = DEFAULT) const override
        { return new typename C::Decoder(get_error_mode(em)); }
 };
 
@@ -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 6e2566682669ec0bbdc6a925d4fca2fb653c2250..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) { }
-       virtual ~codec_error() throw() { }
 };
 
 
 /**
 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 &);
-       virtual ~invalid_character() throw() { }
 };
 
 
 /**
 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 &);
-       virtual ~invalid_sequence() throw() { }
 
 private:
        std::string format_sequence(const std::string::const_iterator &, const std::string::const_iterator &);
index 296c1efe1ed479bd930a8b7f768d87b9a970d010..93c50f489fb8486182a1f2b69711efea71d5e01e 100644 (file)
@@ -1,3 +1,4 @@
+#include <msp/core/except.h>
 #include "ascii.h"
 #include "iso2022jp.h"
 #include "jisx0201.h"
@@ -80,7 +81,6 @@ void Iso2022Jp::Encoder::transliterate(unichar, string &buf)
 
 Iso2022Jp::Decoder::Decoder(ErrorMode em):
        Codec::Decoder(em),
-       mode(ASCII),
        dec(new Ascii::Decoder)
 { }
 
@@ -123,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 aa5c78b9d4de5bf23a2428c1cdffde7013ab0537..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,40 +17,40 @@ public:
                JISX0208
        };
 
-       class Encoder: public Codec::Encoder
+       class MSPCORE_API Encoder: public Codec::Encoder
        {
        private:
-               Mode mode;
+               Mode mode = ASCII;
 
        public:
-               Encoder(ErrorMode em = DEFAULT): Codec::Encoder(em), mode(ASCII) { }
+               Encoder(ErrorMode em = DEFAULT): Codec::Encoder(em) { }
 
-               virtual void encode_char(unichar, std::string &);
-               virtual void sync(std::string &);
-               virtual void reset();
+               void encode_char(unichar, std::string &) override;
+               void sync(std::string &) override;
+               void reset() override;
        private:
                void switch_mode(Mode, std::string &);
-               virtual void transliterate(unichar, std::string &);
+               void transliterate(unichar, std::string &) override;
        };
 
-       class Decoder: public Codec::Decoder
+       class MSPCORE_API Decoder: public Codec::Decoder
        {
        private:
-               Mode mode;
-               Codec::Decoder *dec;
+               Mode mode = ASCII;
+               Codec::Decoder *dec = nullptr;
 
        public:
                Decoder(ErrorMode = DEFAULT);
 
-               virtual unichar decode_char(const std::string &, std::string::const_iterator &);
-               virtual void reset();
+               unichar decode_char(const std::string &, std::string::const_iterator &) override;
+               void reset() override;
        private:
                void switch_mode(Mode);
        };
 
        Iso2022Jp(ErrorMode em = DEFAULT): StandardCodec<Iso2022Jp>(em) { }
 
-       virtual const char *get_name() const { return "ISO-2022-JP"; }
+       const char *get_name() const override { return "ISO-2022-JP"; }
 };
 
 } // namespace StringCodec
index 2266c2ca06f24a081d34d3abe7be009f67b95cf0..3f1bb703da0b810df16fbd48e2a71f2b2f19cf12 100644 (file)
@@ -1,35 +1,36 @@
 #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) { }
 
-               virtual void encode_char(unichar, std::string &);
+               void encode_char(unichar, std::string &) override;
        private:
-               virtual void transliterate(unichar, std::string &);
+               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) { }
 
-               virtual unichar decode_char(const std::string &, std::string::const_iterator &);
+               unichar decode_char(const std::string &, std::string::const_iterator &) override;
        };
 
        Iso646Fi(ErrorMode em = DEFAULT): StandardCodec<Iso646Fi>(em) { }
 
-       virtual const char *get_name() const { return "ISO-646-FI"; }
+       const char *get_name() const override { return "ISO-646-FI"; }
 };
 
 } // namespace StringCodec
index 2b5a624612d74c29da30b44f166f0713220147e2..a6003ceda3eb1986b0f892936018f9de11032b10 100644 (file)
@@ -1,35 +1,36 @@
 #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) { }
 
-               virtual void encode_char(unichar, std::string &);
+               void encode_char(unichar, std::string &) override;
        private:
-               virtual void transliterate(unichar, std::string &);
+               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) { }
 
-               virtual unichar decode_char(const std::string &, std::string::const_iterator &);
+               unichar decode_char(const std::string &, std::string::const_iterator &) override;
        };
 
        Iso88591(ErrorMode em = DEFAULT): StandardCodec<Iso88591>(em) { }
 
-       virtual const char *get_name() const { return "ISO-8859-1"; }
+       const char *get_name() const override { return "ISO-8859-1"; }
 };
 
 } // namespace StringCodec
index ffb3c9a944beff8dab608eaadf23387a76940c7b..2e812459af64e77199ec437a7de2e831cff462cc 100644 (file)
@@ -1,35 +1,36 @@
 #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) { }
 
-               virtual void encode_char(unichar, std::string &);
+               void encode_char(unichar, std::string &) override;
        private:
-               virtual void transliterate(unichar, std::string &);
+               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) { }
 
-               virtual unichar decode_char(const std::string &, std::string::const_iterator &);
+               unichar decode_char(const std::string &, std::string::const_iterator &) override;
        };
 
        Iso885915(ErrorMode em = DEFAULT): StandardCodec<Iso885915>(em) { }
 
-       virtual const char *get_name() const { return "ISO-8859-15"; }
+       const char *get_name() const override { return "ISO-8859-15"; }
 };
 
 } // namespace StringCodec
index 1e7c8ef2e70d4741b91f964ef6b9353e6e19f5a9..3194c784c8d5378ad90213754da7cd09e42ffcdb 100644 (file)
@@ -1,35 +1,36 @@
 #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) { }
 
-               virtual void encode_char(unichar, std::string &);
+               void encode_char(unichar, std::string &) override;
        private:
-               virtual void transliterate(unichar, std::string &);
+               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) { }
 
-               virtual unichar decode_char(const std::string &, std::string::const_iterator &);
+               unichar decode_char(const std::string &, std::string::const_iterator &) override;
        };
 
        JisX0201(ErrorMode em = DEFAULT): StandardCodec<JisX0201>(em) { }
 
-       virtual const char *get_name() const { return "JIS X 0201"; }
+       const char *get_name() const override { return "JIS X 0201"; }
 };
 
 } // namespace StringCodec
index c09782481537acd4a12a9cb342ce0997dfd20d1d..df28a376c10ff9760aafcee0cb84acd294c8fdde 100644 (file)
@@ -9,12 +9,12 @@ namespace StringCodec {
 
 void JisX0208::Encoder::encode_char(unichar ucs, string &buf)
 {
-       unsigned short jis = ucs_to_jisx0208(ucs);
+       Kuten jis = ucs_to_jisx0208(ucs);
        if(jis)
        {
                char jbuf[2];
-               jbuf[0] = jis>>8;
-               jbuf[1] = jis;
+               jbuf[0] = jis.ku+0x20;
+               jbuf[1] = jis.ten+0x20;
                buf.append(jbuf, 2);
        }
        else
@@ -79,8 +79,8 @@ Kuten ucs_to_jisx0208(unichar c)
        Kuten result;
        if(ucs_to_jisx0208_table[i].ucs==static_cast<unsigned short>(c))
        {
-               result.ku = (ucs_to_jisx0208_table[i].jis>>8)+1;
-               result.ten = ucs_to_jisx0208_table[i].jis+1;
+               result.ku = (ucs_to_jisx0208_table[i].jis>>8);
+               result.ten = ucs_to_jisx0208_table[i].jis;
        }
 
        return result;
index 293d2774304d1c27a41c061f9801e76a50260b22..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,45 +12,43 @@ 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) { }
 
-               virtual void encode_char(unichar, std::string &);
+               void encode_char(unichar, std::string &) override;
        private:
-               virtual void transliterate(unichar, std::string &);
+               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) { }
 
-               virtual unichar decode_char(const std::string &, std::string::const_iterator &);
+               unichar decode_char(const std::string &, std::string::const_iterator &) override;
        };
 
        JisX0208(ErrorMode em = DEFAULT): StandardCodec<JisX0208>(em) { }
 
-       virtual const char *get_name() const { return "JIS X 0208"; }
+       const char *get_name() const override { return "JIS X 0208"; }
 };
 
 
 struct Kuten
 {
-       unsigned short ku;
-       unsigned short ten;
+       unsigned short ku = 0;
+       unsigned short ten = 0;
 
-       Kuten(): ku(0), ten(0) { }
-
-       operator bool() { return ku!=0 && ten!=0; }
+       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 13d49ad4ed6250e1a9e95ee5084e20f424608796..f8ae093a64e8e67d16a9e9897dd5e3e13063b4a6 100644 (file)
@@ -7,8 +7,7 @@ namespace StringCodec {
 
 Utf16::Encoder::Encoder(ErrorMode em, Endian en):
        Codec::Encoder(em),
-       endian(en==AUTO ? BIG : en),
-       emit_bom(true)
+       endian(en==AUTO ? BIG : en)
 { }
 
 void Utf16::Encoder::encode_char(unichar ch, string &buf)
index 7fecf1efaad4ef7918da7b6ed8aa3f4122b69ef3..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,35 +22,35 @@ public:
                LITTLE
        };
 
-       class Encoder: public Codec::Encoder
+       class MSPCORE_API Encoder: public Codec::Encoder
        {
        private:
-               Endian endian;
-               bool emit_bom;
+               Endian endian = BIG;
+               bool emit_bom = true;
 
        public:
                Encoder(ErrorMode em = DEFAULT, Endian en = BIG);
 
-               virtual void encode_char(unichar, std::string &);
+               void encode_char(unichar, std::string &) override;
        private:
-               virtual void transliterate(unichar, std::string &);
+               void transliterate(unichar, std::string &) override;
        };
 
-       class Decoder: public Codec::Decoder
+       class MSPCORE_API Decoder: public Codec::Decoder
        {
        private:
-               Endian endian;
+               Endian endian = AUTO;
 
        public:
                Decoder(ErrorMode em = DEFAULT, Endian en = AUTO);
 
-               virtual unichar decode_char(const std::string &, std::string::const_iterator &);
+               unichar decode_char(const std::string &, std::string::const_iterator &) override;
        private:
                unichar decode_unit(const std::string &, const std::string::const_iterator &, std::string::const_iterator &);
        };
 
 private:
-       Endian endian;
+       Endian endian = AUTO;
 
 public:
        Utf16(ErrorMode em = DEFAULT, Endian en = AUTO):
@@ -57,13 +58,13 @@ public:
                endian(en)
        { }
 
-       virtual const char *get_name() const
+       const char *get_name() const override
        { return endian==BIG ? "UTF-16-BE" : endian==LITTLE ? "UTF-16-LE" : "UTF-16"; }
 
-       virtual Encoder *create_encoder(ErrorMode em = DEFAULT) const
+       Encoder *create_encoder(ErrorMode em = DEFAULT) const override
        { return new Encoder(get_error_mode(em), endian); }
 
-       virtual Decoder *create_decoder(ErrorMode em = DEFAULT) const
+       Decoder *create_decoder(ErrorMode em = DEFAULT) const override
        { return new Decoder(get_error_mode(em), endian); }
 };
 
index 94c627ec5a0ca0f905eac01ea4a4de4ef35fb934..c3f4a5930014f46c5d3a46318d2cf5c4f17ef4c6 100644 (file)
@@ -1,35 +1,36 @@
 #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) { }
 
-               virtual void encode_char(unichar, std::string &);
+               void encode_char(unichar, std::string &) override;
        private:
-               virtual void transliterate(unichar, std::string &);
+               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) { }
 
-               virtual unichar decode_char(const std::string &, std::string::const_iterator &);
+               unichar decode_char(const std::string &, std::string::const_iterator &) override;
        };
 
        Utf8(ErrorMode em = DEFAULT): StandardCodec<Utf8>(em) { }
 
-       virtual const char *get_name() const { return "UTF-8"; }
+       const char *get_name() const override { return "UTF-8"; }
 };
 
 } // namespace StringCodec
index c5d140fe06347d5d06f6d2aa44dbd1aafd78ab71..b89fdaea1646d7438eebfd52cd97bb45b91dabe5 100644 (file)
@@ -1,35 +1,36 @@
 #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) { }
 
-               virtual void encode_char(unichar, std::string &);
+               void encode_char(unichar, std::string &) override;
        private:
-               virtual void transliterate(unichar, std::string &);
+               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) { }
 
-               virtual unichar decode_char(const std::string &, std::string::const_iterator &);
+               unichar decode_char(const std::string &, std::string::const_iterator &) override;
        };
 
        Windows1252(ErrorMode em = DEFAULT): StandardCodec<Windows1252>(em) { }
 
-       virtual const char *get_name() const { return "Windows-1252"; }
+       const char *get_name() const override { return "Windows-1252"; }
 };
 
 } // namespace StringCodec
index 07484dd61c7fe27d514ee4a325e1d2fe7bbe366d..60703d8a117c1a19d814cc2a2c63cadc2dca7d91 100644 (file)
@@ -91,19 +91,7 @@ void Fmt::parse(const char *s)
 
 Fmt &Fmt::reset()
 {
-       wd = 0;
-       prec = 6;
-       spos = false;
-       fillc = ' ';
-       base = DEC;
-       sbase = false;
-       fmode = AUTOFLT;
-       spoint = false;
-       align = RIGHT;
-       ucase = false;
-       type = STR;
-
-       return *this;
+       return *this = Fmt();
 }
 
 void Fmt::apply(ostream &out) const
index ee84911bcec06fcd0fc34402ef8975133235b3ce..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) { }
-       virtual ~format_error() throw() { }
 };
 
 
@@ -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
@@ -68,22 +68,22 @@ public:
        };
 
 private:
-       unsigned wd;
-       unsigned prec;
-       bool spos;
-       wchar_t fillc;
-       Base base;
-       bool sbase;
-       FloatMode fmode;
-       bool spoint;
-       Align align;
-       bool ucase;
-       Type type;
+       unsigned wd = 0;
+       unsigned prec = 6;
+       bool spos = false;
+       wchar_t fillc = ' ';
+       Base base = DEC;
+       bool sbase = false;
+       FloatMode fmode = AUTOFLT;
+       bool spoint = false;
+       Align align = RIGHT;
+       bool ucase = false;
+       Type type = STR;
 
 public:
-       Fmt() { reset(); }
-       Fmt(const char *f) { reset(); parse(f); }
-       Fmt(const std::string &f) { reset(); parse(f.c_str()); }
+       Fmt() = default;
+       Fmt(const char *f) { parse(f); }
+       Fmt(const std::string &f) { parse(f.c_str()); }
 
 private:
        void parse(const char *);
index d2065e91cad058cd74f63fa5a34dcec45f258cde..42926e158d593a8a5d84ffb88dfcdddce26a80d5 100644 (file)
@@ -19,6 +19,9 @@ Formatter::Formatter(const Formatter &other):
 
 Formatter &Formatter::operator=(const Formatter &other)
 {
+       if(&other==this)
+               return *this;
+
        fmt = other.fmt;
        pos = fmt.begin()+(other.pos-other.fmt.begin());
        result = other.result;
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 2c867b2ce0572b7489a7fb6c9e74013efb6b7804..5e9159ce97af5e42db1ad9ba63ee1669a21c2a93 100644 (file)
@@ -1,6 +1,6 @@
 #include <cmath>
+#include <cstdint>
 #include <limits>
-#include <msp/core/inttypes.h>
 #include "format.h"
 #include "lexicalcast.h"
 
@@ -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())); }
@@ -557,7 +555,7 @@ void operator<<(LexicalConverter &c, const char *s)
 { c.result(str_to_str(s, c.get_fmt())); }
 
 void operator<<(LexicalConverter &c, const void *p)
-{ c.result(int_to_str(reinterpret_cast<IntPtr>(p), c.get_fmt())); }
+{ c.result(int_to_str(reinterpret_cast<intptr_t>(p), c.get_fmt())); }
 
 
 /*** operator>> ***/
@@ -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 4f54a8515df8e2806cc118e0a4d982b88ff0a5c2..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,37 +13,35 @@ 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) { }
-       virtual ~lexical_error() throw() { }
 };
 
 
 /**
 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) { }
-       virtual ~format_mismatch() throw() { }
 };
 
 
 /**
 Helper class for lexical_cast to facilitate operator overloading.
 */
-class LexicalConverter
+class MSPCORE_API LexicalConverter
 {
 private:
        Fmt fmt;
-       bool filled;
+       bool filled = false;
        std::string buf;
 
 public:
-       LexicalConverter(const Fmt &f): fmt(f), filled(false) { }
+       LexicalConverter(const Fmt &f): fmt(f) { }
        LexicalConverter(const std::string &s, const Fmt &f): fmt(f), filled(true), buf(s) { }
 
        const Fmt &get_fmt() const { return 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 c62405614525dd85b32a73361bd78133e03ef29f..5307c6990286ba373291281fb4ee230ff81d2d07 100644 (file)
@@ -2,6 +2,7 @@
 #include <list>
 #include <stack>
 #include <vector>
+#include <msp/core/except.h>
 #include "format.h"
 #include "regex.h"
 
@@ -56,7 +57,6 @@ string bad_regex::make_where(const string &e, const string::const_iterator &i)
 
 Regex::Regex(const string &expr)
 {
-       n_groups = 0;
        auto iter = expr.begin();
        code = compile(expr, iter, n_groups, false);
        ++n_groups;
@@ -478,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 094a295cdb77bc230dd0c79254a4459f1567d945..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 &);
-       virtual ~bad_regex() throw() { }
 
 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;
@@ -107,7 +107,7 @@ private:
        };
 
        Code code;
-       unsigned n_groups;
+       unsigned n_groups = 0;
 
 public:
        /** Constructs a new Regex object from a string representation. */
index b79104bad530f9f6846791e97cda7771f9252d37..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:
        /**
@@ -26,14 +27,13 @@ public:
        {
                typedef std::string::size_type size_type;
 
-               bool match;        //< Whether or not this group matched
-               size_type begin;   //< First offset of the match
-               size_type end;     //< One-past-last offset
-               size_type length;  //< Length of the match (end-begin)
-               std::string str;   //< The part of the string that matched
+               bool match = false;  //< Whether or not this group matched
+               size_type begin;     //< First offset of the match
+               size_type end;       //< One-past-last offset
+               size_type length;    //< Length of the match (end-begin)
+               std::string str;     //< The part of the string that matched
 
-               Group(): match(false) { }
-               operator bool() const { return match; }
+               explicit operator bool() const { return match; }
        };
 
 private:
@@ -41,7 +41,7 @@ private:
 
 public:
        /** Constructs a RegMatch representing a non-match. */
-       RegMatch() { }
+       RegMatch() = default;
 
        /** Constructs a new RegMatch from a string and groups.  The length and str
        members of each group are computed and need not be set.  Intended to be used
@@ -66,7 +66,7 @@ public:
        /** Shorthand for the group() function. */
        const Group &operator[](unsigned i) const { return group(i); }
 
-       operator bool() const { return !empty(); }
+       explicit operator bool() const { return !empty(); }
 };
 
 } // namespace Msp
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 e1abcf7da81aade456c90ce6f438fd61ea2958c7..e011f3b2ac0b8a3681048bd1c59e17194dbda03c 100644 (file)
@@ -29,7 +29,7 @@ inline unsigned char month_days(int y, unsigned char m)
 }
 
 template<typename T>
-inline int cmp_(T a, T b)
+inline int _cmp(T a, T b)
 {
        if(a<b)
                return -1;
@@ -45,52 +45,32 @@ namespace Time {
 
 DateTime::DateTime(const TimeStamp &ts)
 {
-       init(ts);
+       add_raw(ts.raw());
 }
 
-DateTime::DateTime(const TimeStamp &ts, const TimeZone &tz)
+DateTime::DateTime(const TimeStamp &ts, const TimeZone &tz):
+       DateTime(ts)
 {
-       init(ts);
        convert_timezone(tz);
 }
 
-DateTime::DateTime(int y, unsigned char m, unsigned char d)
-{
-       init(y, m, d, 0, 0, 0, 0);
-}
-
-DateTime::DateTime(int y, unsigned char m, unsigned char d, unsigned char h, unsigned char n, unsigned char s)
+DateTime::DateTime(int y, unsigned char m, unsigned char d):
+       DateTime(y, m, d, 0, 0, 0, 0)
+{ }
+
+DateTime::DateTime(int y, unsigned char m, unsigned char d, unsigned char h, unsigned char n, unsigned char s):
+       DateTime(y, m, d, h, n, s, 0)
+{ }
+
+DateTime::DateTime(int y, unsigned char m, unsigned char d, unsigned char h, unsigned char n, unsigned char s, unsigned u):
+       year(y),
+       month(m),
+       mday(d),
+       hour(h),
+       minute(n),
+       second(s),
+       usec(u)
 {
-       init(y, m, d, h, n, s, 0);
-}
-
-DateTime::DateTime(int y, unsigned char m, unsigned char d, unsigned char h, unsigned char n, unsigned char s, unsigned u)
-{
-       init(y, m, d, h, n, s, u);
-}
-
-void DateTime::init(const TimeStamp &ts)
-{
-       year = 1970;
-       month = 1;
-       mday = 1;
-       hour = 0;
-       minute = 0;
-       second = 0;
-       usec = 0;
-       add_raw(ts.raw());
-}
-
-void DateTime::init(int y, unsigned char m, unsigned char d, unsigned char h, unsigned char n, unsigned char s, unsigned u)
-{
-       year = y;
-       month = m;
-       mday = d;
-       hour = h;
-       minute = n;
-       second = s;
-       usec = u;
-
        if(usec>=1000000)
                throw out_of_range("DateTime::DateTime usec");
        if(second>=60)
@@ -251,19 +231,19 @@ DateTime &DateTime::operator-=(const TimeDelta &td)
 
 int DateTime::cmp(const DateTime &dt) const
 {
-       if(int c = cmp_(year, dt.year))
+       if(int c = _cmp(year, dt.year))
                return c;
-       if(int c = cmp_(month, dt.month))
+       if(int c = _cmp(month, dt.month))
                return c;
-       if(int c = cmp_(mday, dt.mday))
+       if(int c = _cmp(mday, dt.mday))
                return c;
-       if(int c = cmp_(hour, dt.hour))
+       if(int c = _cmp(hour, dt.hour))
                return c;
-       if(int c = cmp_(minute, dt.minute))
+       if(int c = _cmp(minute, dt.minute))
                return c;
-       if(int c = cmp_(second, dt.second))
+       if(int c = _cmp(second, dt.second))
                return c;
-       if(int c = cmp_(usec, dt.usec))
+       if(int c = _cmp(usec, dt.usec))
                return c;
        return 0;
 }
index b7f578cd9f71326ae510c0780c8714f195aa684d..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,16 +21,16 @@ 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;
-       unsigned char month;
-       unsigned char mday;
-       unsigned char hour;
-       unsigned char minute;
-       unsigned char second;
-       unsigned usec;
+       int year = 1970;
+       unsigned char month = 1;
+       unsigned char mday = 1;
+       unsigned char hour = 0;
+       unsigned char minute = 0;
+       unsigned char second = 0;
+       unsigned usec = 0;
        TimeZone zone;
 
 public:
@@ -38,11 +39,7 @@ public:
        DateTime(int, unsigned char, unsigned char);
        DateTime(int, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char);
        DateTime(int, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned);
-private:
-       void init(const TimeStamp &);
-       void init(int, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned);
 
-public:
        static DateTime parse_rfc3339(const std::string &);
 
        int get_year() const { return year; }
index 1af7956f25c09a5bb0103cb3e8f1b08b3094fbef..46b3e4df6908ec3c49e93752da2a3a0668e3b3dc 100644 (file)
@@ -1,12 +1,12 @@
 #ifndef MSP_TIME_RAWTIME_H_
 #define MSP_TIME_RAWTIME_H_
 
-#include <msp/core/inttypes.h>
+#include <cstdint>
 
 namespace Msp {
 namespace Time {
 
-typedef Int64 RawTime;
+typedef std::int64_t RawTime;
 
 } // namespace Time
 } // namespace Msp
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 2ce6eeb4e9e42d3d48db4a6d908d0c18c480810c..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;
+       RawTime usec = 0;
 
 public:
        /** Constructs a zero TimeDelta. */
-       TimeDelta(): usec(0) { }
+       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. */
@@ -54,24 +55,24 @@ public:
        bool operator==(const TimeDelta &t) const { return usec==t.usec; }
        bool operator!=(const TimeDelta &t) const { return usec!=t.usec; }
 
-       operator const void *() const { return usec ? this : 0; }
+       explicit operator bool() const { return usec; }
 };
 
 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 9411facc5d08bf667d73373e03eba43d0acd350c..eda782e0d92c5bf82c00418584e12917d03fa673 100644 (file)
@@ -9,8 +9,7 @@ namespace Msp {
 namespace Time {
 
 Timer::Timer():
-       sem(1),
-       blocking(false)
+       sem(1)
 { }
 
 Timer::~Timer()
@@ -23,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();
@@ -34,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();
@@ -72,7 +71,7 @@ void Timer::do_tick(const TimeDelta &timeout)
        if(timeout>=zero)
                deadline = now()+timeout;
 
-       Slot *next = 0;
+       Slot *next = nullptr;
        {
                MutexLock l(mutex);
                while(1)
@@ -114,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
@@ -153,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 8bd4d074a70ea569b19074b32e303323143fae81..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
@@ -43,14 +44,13 @@ private:
        {
                Slot *slot;
 
-               SlotProxy(Slot *);
                bool operator<(const SlotProxy &) const;
        };
 
        std::vector<SlotProxy> slots;
        Semaphore sem;
        Mutex mutex;
-       bool blocking;
+       bool blocking = false;
 
 public:
        Timer();
index 1317b26bc0ba067c7774ef9ecfd6fb7342e2bdff..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,15 +14,15 @@ function.
 
 For representing user-specified times, use the DateTime class.
 */
-class TimeStamp
+class MSPCORE_API TimeStamp
 {
 private:
-       RawTime usec;
+       RawTime usec = 0;
 
 public:
        /** Construct a TimeStamp that represents an arbitarily distant point in the
        past.  It's guaranteed to be less than any valid timestamp. */
-       TimeStamp(): usec(0) { }
+       TimeStamp() = default;
 
        /** Constructs a TimeStamp from a plain number.  The purpose of this is to allow
        serialization together with the raw() function. */
@@ -46,7 +47,7 @@ public:
        bool operator==(const TimeStamp &t) const { return usec==t.usec; }
        bool operator!=(const TimeStamp &t) const { return usec!=t.usec; }
 
-       operator const void *() const { return usec>0 ? this : 0; }
+       explicit operator bool() const { return usec>0; }
 
        static TimeStamp from_unixtime(time_t t) { return TimeStamp(t*1000000LL); }
 };
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 029c75bc3cb26e0bf5bc6929b81fb26d58cb5d93..f25f61c17c03f6ea09c06f4d495ab8c5d021fcaa 100644 (file)
@@ -13,7 +13,7 @@ namespace Time {
 TimeStamp now()
 {
        timeval tv;
-       gettimeofday(&tv, 0);
+       gettimeofday(&tv, nullptr);
        return TimeStamp(timeval_to_rawtime(tv));
 }
 
@@ -27,7 +27,7 @@ TimeDelta get_cpu_time()
 void sleep(const TimeDelta &d)
 {
        timespec ts = rawtime_to_timespec(d.raw());
-       while(nanosleep(&ts, 0)==-1)
+       while(nanosleep(&ts, nullptr)==-1)
                if(errno!=EINTR)
                        throw system_error("nanosleep");
 }
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()