.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.*
#define MSP_CORE_ALGORITHM_H_
#include <algorithm>
+#include <functional>
namespace Msp {
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)
{
const T &value;
T C::*mem_ptr;
- MemberMatch(const T &v, T C::*p): value(v), mem_ptr(p) { }
-
bool operator()(const C &obj) { return obj.*mem_ptr==value; }
};
template<typename Container, typename T>
inline typename Container::iterator find_member(Container &cont, const T &value, T Container::value_type::*mp)
{
- return find_if(cont, MemberMatch<typename Container::value_type, T>(value, mp));
+ return find_if(cont, MemberMatch<typename Container::value_type, T>{ value, mp });
}
template<typename Container, typename T>
inline typename Container::const_iterator find_member(const Container &cont, const T &value, T Container::value_type::*mp)
{
- return find_if(cont, MemberMatch<typename Container::value_type, T>(value, mp));
+ return find_if(cont, MemberMatch<typename Container::value_type, T>{ value, mp });
}
-template<typename C, typename T>
+template<typename C, typename T, typename P=std::less<T>>
struct MemberCompare
{
T C::*mem_ptr;
+ P pred;
MemberCompare(T C::*p): mem_ptr(p) { }
- bool operator()(const C &obj, const T &v) { return obj.*mem_ptr<v; }
- bool operator()(const T &v, const C &obj) { return v<obj.*mem_ptr; }
- bool operator()(const C &obj1, const C &obj2) { return obj1.*mem_ptr<obj2.*mem_ptr; }
+ bool operator()(const C &obj, const T &v) { return pred(obj.*mem_ptr, v); }
+ bool operator()(const T &v, const C &obj) { return pred(v, obj.*mem_ptr); }
+ bool operator()(const C &obj1, const C &obj2) { return pred(obj1.*mem_ptr, obj2.*mem_ptr); }
};
template<typename Container, typename T>
#include "mainthread.h"
+#include "mspcore_api.h"
-extern "C" void ANativeActivity_onCreate(ANativeActivity *activity, void * /*saved_state*/, size_t /*state_size*/)
+extern "C" MSPCORE_API void ANativeActivity_onCreate(ANativeActivity *activity, void * /*saved_state*/, size_t /*state_size*/)
{
static Msp::Android::MainThread *thread = nullptr;
if(thread)
#include <msp/io/print.h>
#include <msp/strings/utils.h>
#include "application.h"
+#include "except.h"
#include "getopt.h"
using namespace std;
Application::Application(const string &n)
{
if(_app)
- throw logic_error("instance already exists");
+ throw already_called("Application::Application");
if(!n.empty())
_name = n;
void Application::set_startup_info(const char *argv0, void *data)
{
if(_argv0)
- throw logic_error("startup info already set");
+ throw already_called("Application::set_startup_info");
static FS::Path exe;
_data = data;
}
+void *Application::get_data()
+{
+ return _data;
+}
+
+const char *Application::get_argv0()
+{
+ return _argv0;
+}
+
+const std::string &Application::get_name()
+{
+ return _name;
+}
+
int Application::main()
{
done = false;
Application::Starter::Starter()
{
if(_starter)
- throw logic_error("Can't create more than one Starter instance");
+ throw already_called("Application::Starter::Starter");
_starter = this;
}
#include <stdexcept>
#include <string>
+#include "mspcore_api.h"
#include "noncopyable.h"
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();
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
#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
--- /dev/null
+#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
#include <string>
#include <vector>
#include <msp/strings/lexicalcast.h>
+#include "mspcore_api.h"
#include "noncopyable.h"
namespace Msp {
-class usage_error: public std::runtime_error
+class MSPCORE_API usage_error: public std::runtime_error
{
private:
std::string m_help;
public:
usage_error(const std::string &w, const std::string &h = std::string()): std::runtime_error(w), m_help(h) { }
- ~usage_error() throw() override = default;
- const char *help() const throw() { return m_help.c_str(); }
+ const char *help() const noexcept { return m_help.c_str(); }
};
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
REQUIRED_ARG
};
- class Option
+ class MSPCORE_API Option
{
protected:
Option() = default;
virtual unsigned get_seen_count() const = 0;
};
- class Argument
+ class MSPCORE_API Argument
{
protected:
Argument() = default;
#include <stdexcept>
#include <typeinfo>
#include <msp/strings/lexicalcast.h>
+#include "mspcore_api.h"
namespace Msp {
} // namespace Internal
-class key_error: public std::runtime_error
+class MSPCORE_API key_error: public std::runtime_error
{
public:
template<typename T>
#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;
--- /dev/null
+#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
#ifndef MSP_CORE_MUTEX_H_
#define MSP_CORE_MUTEX_H_
+#include "mspcore_api.h"
#include "noncopyable.h"
#include "refptr.h"
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;
/**
Locks the mutex for the lifetime of the object.
*/
-class MutexLock
+class MSPCORE_API MutexLock
{
private:
Mutex &mutex;
#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;
#include <cstring>
#include "application.h"
+#include "mspcore_api.h"
-int main(int argc, char **argv)
+MSPCORE_API int main(int argc, char **argv)
{
void *data = nullptr;
#include <msp/io/console.h>
+#include "except.h"
#include "process.h"
#include "process_private.h"
unsigned Process::get_exit_code() const
{
if(!finished)
- throw logic_error("not finished");
+ throw invalid_state("not finished");
return exit_code;
}
#include <vector>
#include <msp/fs/path.h>
#include <msp/io/base.h>
+#include "mspcore_api.h"
#include "noncopyable.h"
namespace Msp {
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;
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>
#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;
#include <stdexcept>
#include <string>
+#include "mspcore_api.h"
namespace Msp {
-class system_error: public std::runtime_error
+class MSPCORE_API system_error: public std::runtime_error
{
private:
int m_code;
public:
system_error(const std::string &, int = -1);
system_error(const std::string &, const std::string &);
- ~system_error() throw() override = default;
- int code() const throw() { return m_code; }
+ int code() const noexcept { return m_code; }
private:
static std::string get_message(int);
-#include <stdexcept>
+#include "except.h"
#include "thread.h"
#include "thread_private.h"
void Thread::launch()
{
if(_state>=RUNNING)
- throw logic_error("already launched");
+ throw already_called("Thread::launch");
platform_launch();
_state = RUNNING;
thread->platform_setname();
thread->main();
thread->_state = FINISHED;
- return nullptr;
+ return 0;
}
} // namespace Msp
#define MSP_CORE_THREAD_H_
#include <string>
+#include "mspcore_api.h"
#include "noncopyable.h"
namespace Msp {
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;
struct Thread::Private
{
- ThreadHandle handle;
-
- Private(): handle(0) { }
+ ThreadHandle handle = 0;
static ThreadReturn THREAD_CALL main_wrapper(void *);
};
#include "application.h"
+#include "mspcore_api.h"
-int main(int argc, char **argv)
+MSPCORE_API int main(int argc, char **argv)
{
return Msp::Application::run(argc, argv, nullptr);
}
#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"
namespace Msp {
Process::~Process()
-{ }
+{
+ delete priv;
+}
void Process::platform_get_self_info(Private &priv)
{
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));
#include <type_traits>
#include <typeinfo>
#include "meta.h"
+#include "mspcore_api.h"
namespace Msp {
-class type_mismatch: public std::runtime_error
+class MSPCORE_API type_mismatch: public std::runtime_error
{
public:
type_mismatch(const std::type_info &, const std::type_info &);
- ~type_mismatch() throw() override = default;
};
-class Variant
+class MSPCORE_API Variant
{
-private:
- struct StoreBase
- {
- virtual ~StoreBase() { }
+public:
+ static constexpr unsigned INTERNAL_SIZE = 2*sizeof(void *);
- virtual const std::type_info &type_id() const = 0;
- virtual StoreBase *clone() const = 0;
- virtual bool type_equals(const StoreBase &) const = 0;
- virtual bool value_equals(const StoreBase &) const = 0;
+ struct Functions
+ {
+ const std::type_info &(*get_type)();
+ bool (*compare)(const char *, const char *);
+ void (*clone)(char *, const char *);
+ void (*move)(char *, char *);
+ void (*destroy)(char *);
};
+private:
template<typename T>
- struct Store: public StoreBase
- {
- T data;
+ using EnableNotVariant = typename std::enable_if<!std::is_same<typename std::remove_cv<typename std::remove_reference<T>::type>::type, Variant>::value>::type;
+
+ const Functions *funcs = nullptr;
+ alignas(void *) char storage[INTERNAL_SIZE];
+
+public:
+ Variant() = default;
+ template<typename T, typename = EnableNotVariant<T>>
+ Variant(T &&v) { assign(std::forward<T>(v)); }
+ Variant(const Variant &v) { copy_from(v); }
+ Variant(Variant &&v) { move_from(std::move(v)); }
+ ~Variant() { clear(); }
- Store(const T &d): data(d) { }
+ template<typename T, typename = EnableNotVariant<T>>
+ Variant &operator=(T &&v) { assign(std::forward<T>(v)); return *this; }
- const std::type_info &type_id() const override { return typeid(T); }
- StoreBase *clone() const override { return new Store<T>(data); }
- bool type_equals(const StoreBase &s) const override { return dynamic_cast<const Store<T> *>(&s); }
- bool value_equals(const StoreBase &s) const override { return _value_equals<T>(s); }
+ Variant &operator=(const Variant &v) { if(&v!=this) copy_from(v); return *this; }
+ Variant &operator=(Variant &&v) { if(&v!=this) move_from(std::move(v)); return *this; }
- template<typename U>
- typename std::enable_if<IsEqualityComparable<U>::value, bool>::type _value_equals(const StoreBase &s) const
- { const Store<T> *t = dynamic_cast<const Store<T> *>(&s); return (t && t->data==data); }
+ void clear();
- template<typename U>
- typename std::enable_if<!IsEqualityComparable<U>::value, bool>::type _value_equals(const StoreBase &) const
- { return false; }
- };
+private:
+ template<typename T>
+ void assign(T &&);
+
+ void copy_from(const Variant &);
+ void move_from(Variant &&);
- StoreBase *store = nullptr;
+ template<typename T>
+ T &get();
public:
- Variant() = default;
template<typename T>
- Variant(const T &v): store(new Store<typename std::remove_cv<T>::type>(v)) { }
- Variant(const Variant &v): store(v.store ? v.store->clone() : nullptr) { }
- ~Variant() { delete store; }
+ T &value() { return get<T>(); }
template<typename T>
- Variant &operator=(const T &v)
- {
- delete store;
- store = new Store<typename std::remove_cv<T>::type>(v);
- return *this;
- }
+ const T &value() const { return const_cast<Variant *>(this)->get<T>(); }
- Variant &operator=(const Variant &v)
- {
- if(&v==this)
- return *this;
+ template<typename T>
+ bool has_type() const { return type_equals(funcs, get_functions<typename std::remove_cv<T>::type>()); }
+
+ bool has_same_type(const Variant &v) const { return type_equals(funcs, v.funcs); }
+
+ template<typename T>
+ DEPRECATED bool check_type() const { return has_type<T>(); }
+
+ DEPRECATED bool check_same_type(const Variant &v) const { return has_same_type(v); }
+
+ bool operator==(const Variant &v) const { return (has_same_type(v) && funcs->compare(storage, v.storage)); }
+ bool operator!=(const Variant &v) const { return !(operator==(v)); }
- delete store;
- store = (v.store ? v.store->clone() : nullptr);
- return *this;
- }
+ template<typename T>
+ operator T() const { return value<T>(); }
private:
+ static bool type_equals(const Functions *, const Functions *);
+
template<typename T>
- Store<typename std::remove_cv<T>::type> *get_typed_store() const
- {
- typedef typename std::remove_cv<T>::type NCT;
- Store<NCT> *s = dynamic_cast<Store<NCT> *>(store);
- if(!s)
- throw type_mismatch(typeid(T), (store ? store->type_id() : typeid(void)));
- return s;
- }
+ static constexpr bool is_small() { return (sizeof(T)<=INTERNAL_SIZE && alignof(T)<=alignof(void *)); }
+
+ template<typename T, typename U>
+ using EnableSmall = typename std::enable_if<is_small<T>(), U>::type;
+
+ template<typename T, typename U>
+ using EnableLarge = typename std::enable_if<!is_small<T>(), U>::type;
-public:
template<typename T>
- T &value()
- {
- return get_typed_store<T>()->data;
- }
+ static const Functions *get_functions();
template<typename T>
- const T &value() const
- {
- return get_typed_store<T>()->data;
- }
+ static const std::type_info &get_type() { return typeid(T); }
template<typename T>
- bool check_type() const
- {
- return dynamic_cast<Store<typename std::remove_cv<T>::type> *>(store);
- }
+ static EnableSmall<T, void> create(char *s, T &&v)
+ { new(s) typename std::remove_reference<T>::type(std::forward<T>(v)); }
+
+ template<typename T>
+ static EnableLarge<T, void> create(char *s, T &&v)
+ { using V = typename std::remove_reference<T>::type; *reinterpret_cast<V **>(s) = new V(std::forward<T>(v)); }
+
+ template<typename T>
+ static typename std::enable_if<!IsEqualityComparable<T>::value, bool>::type compare(const char *, const char *)
+ { return false; }
+
+ template<typename T>
+ static typename std::enable_if<IsEqualityComparable<T>::value, EnableSmall<T, bool>>::type compare(const char *s1, const char *s2)
+ { return *reinterpret_cast<const T *>(s1)==*reinterpret_cast<const T *>(s2); }
+
+ template<typename T>
+ static typename std::enable_if<IsEqualityComparable<T>::value, EnableLarge<T, bool>>::type compare(const char *s1, const char *s2)
+ { return **reinterpret_cast<const T *const *>(s1)==**reinterpret_cast<const T *const *>(s2); }
+
+ template<typename T>
+ static EnableSmall<T, void> clone(char *s, const char *v)
+ { new(s) T(*reinterpret_cast<const T *>(v)); }
+
+ template<typename T>
+ static EnableLarge<T, void> clone(char *s, const char *v)
+ { *reinterpret_cast<T **>(s) = new T(**reinterpret_cast<const T *const *>(v)); }
- bool check_same_type(const Variant &v) const
- { return store && v.store && store->type_equals(*v.store); }
+ template<typename T>
+ static EnableSmall<T, void> move(char *s, char *v)
+ { new(s) T(std::move(*reinterpret_cast<T *>(v))); }
- bool operator==(const Variant &v) const
- { return store && v.store && store->value_equals(*v.store); }
+ template<typename T>
+ static EnableLarge<T, void> move(char *s, char *v)
+ { T *&p = *reinterpret_cast<T **>(v); *reinterpret_cast<T **>(s) = p; p = nullptr; }
- bool operator!=(const Variant &v) const
- { return !(operator==(v)); }
+ template<typename T>
+ static EnableSmall<T, void> destroy(char *s)
+ { reinterpret_cast<T *>(s)->~T(); }
template<typename T>
- operator T() const
- { return value<T>(); }
+ static EnableLarge<T, void> destroy(char *s)
+ { delete *reinterpret_cast<T **>(s); }
};
+
+inline void Variant::clear()
+{
+ if(funcs)
+ funcs->destroy(storage);
+ funcs = nullptr;
+}
+
+template<typename T>
+inline void Variant::assign(T &&v)
+{
+ clear();
+ funcs = get_functions<typename std::remove_cv<typename std::remove_reference<T>::type>::type>();
+ create(storage, std::forward<T>(v));
+}
+
+inline void Variant::copy_from(const Variant &v)
+{
+ clear();
+ if((funcs = v.funcs))
+ funcs->clone(storage, v.storage);
+}
+
+inline void Variant::move_from(Variant &&v)
+{
+ clear();
+ if((funcs = v.funcs))
+ funcs->move(storage, v.storage);
+ v.clear();
+}
+
+template<typename T>
+inline T &Variant::get()
+{
+ if(!has_type<T>())
+ throw type_mismatch(typeid(T), (funcs ? funcs->get_type() : typeid(void)));
+
+ if(sizeof(T)<=INTERNAL_SIZE)
+ return *reinterpret_cast<T *>(storage);
+ else
+ return **reinterpret_cast<T **>(storage);
+}
+
+inline bool Variant::type_equals(const Functions *funcs1, const Functions *funcs2)
+{
+ if(!funcs1 || !funcs2)
+ return false;
+ else if(funcs1==funcs2)
+ return true;
+ else
+ return funcs1->get_type()==funcs2->get_type();
+}
+
+template<typename T>
+inline const Variant::Functions *Variant::get_functions()
+{
+ static Functions funcs =
+ {
+ &get_type<T>,
+ &compare<T>,
+ &clone<T>,
+ &move<T>,
+ &destroy<T>
+ };
+ return &funcs;
+}
+
} // namespace Msp
#endif
#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;
-#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);
}
#ifndef MSP_CORE_MODULE_PLATFORM_H_
#define MSP_CORE_MODULE_PLATFORM_H_
-#include <windows.h>
+#include "winapi.h"
namespace Msp {
-#include <windows.h>
+#include "winapi.h"
#include "mutex.h"
#include "mutex_private.h"
#ifndef MSP_CORE_MUTEX_PLATFORM_H_
#define MSP_CORE_MUTEX_PLATFORM_H_
-#include <windows.h>
+#include "winapi.h"
namespace Msp {
-#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"
{
CloseHandle(priv->info.hProcess);
CloseHandle(priv->info.hThread);
+ delete priv;
}
void Process::platform_get_self_info(Private &priv)
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)
#ifndef MSP_CORE_PROCESS_PLATFORM_H_
#define MSP_CORE_PROCESS_PLATFORM_H_
-#include <windows.h>
+#include "winapi.h"
namespace Msp {
-#include <windows.h>
+#include "winapi.h"
#include <msp/core/systemerror.h>
#include <msp/time/timedelta.h>
#include "semaphore.h"
-#include <windows.h>
+#include "winapi.h"
#include <msp/strings/lexicalcast.h>
#include "systemerror.h"
-#include <windows.h>
+#include "winapi.h"
#include "thread.h"
#include "thread_private.h"
#ifndef MSP_CORE_THREAD_PLATFORM_H_
#define MSP_CORE_THREAD_PLATFORM_H_
-#include <windows.h>
+#include "winapi.h"
namespace Msp {
--- /dev/null
+#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
#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
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
--- /dev/null
+#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
--- /dev/null
+#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
#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
_current = _prev;
}
+const ErrorReporter *ErrorReporter::get_current()
+{
+ return _current;
+}
+
} // namespace Debug
} // namespace Msp
#define MSP_DEBUG_ERRORREPORTER_H_
#include <stdexcept>
+#include <msp/core/mspcore_api.h>
#include <msp/core/noncopyable.h>
namespace Msp {
namespace Debug {
-class ErrorReporter: private NonCopyable
+class MSPCORE_API ErrorReporter: private NonCopyable
{
private:
ErrorReporter *_prev = nullptr;
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;
};
#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
#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>
Note: This is not thread-safe. To profile multiple threads, create a separate
Profiler for each thread.
*/
-class Profiler: private NonCopyable
+class MSPCORE_API Profiler: private NonCopyable
{
public:
- struct CallInfo
+ struct MSPCORE_API CallInfo
{
Msp::Time::TimeStamp entry_time;
Msp::Time::TimeDelta duration;
};
- struct ScopeInfo
+ struct MSPCORE_API ScopeInfo
{
Time::TimeStamp first_call;
unsigned calls = 0;
#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"
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;
#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"
{
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);
{
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);
{
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);
#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 &);
};
/// 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
#include <msp/core/algorithm.h>
+#include <msp/core/except.h>
#include "filemonitor.h"
#include "filemonitor_platform.h"
void FileMonitor::use_event_dispatcher(IO::EventDispatcher &ed)
{
if(event_disp)
- throw logic_error("event_disp!=nullptr");
+ throw already_called("FileMonitor::use_event_dispatcher");
event_disp = &ed;
platform_use_event_dispatcher();
#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>
namespace Msp {
namespace FS {
-class FileMonitor: NonCopyable
+class MSPCORE_API FileMonitor: NonCopyable
{
private:
struct Private;
#include <msp/core/application.h>
#include <msp/core/environ.h>
+#include <msp/core/except.h>
#include "dir.h"
using namespace std;
{
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));
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();
}
#include <ostream>
#include <string>
#include <vector>
+#include <msp/core/mspcore_api.h>
namespace Msp {
namespace FS {
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;
#ifndef MSP_FS_REDIRECTEDPATH_H_
#define MSP_FS_REDIRECTEDPATH_H_
+#include <msp/core/mspcore_api.h>
#include "path.h"
namespace Msp {
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;
#include <cstdint>
#include <string>
+#include <msp/core/mspcore_api.h>
#include <msp/time/timestamp.h>
#include "path.h"
/**
Holds file information.
*/
-class Stat
+class MSPCORE_API Stat
{
private:
struct Private;
{ 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)
#include <msp/core/application.h>
#include <msp/core/environ.h>
+#include <msp/core/except.h>
#include "dir.h"
using namespace std;
{
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);
}
#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
-#include <windows.h>
+#include <msp/core/winapi.h>
#include <msp/core/mutex.h>
#include <msp/core/systemerror.h>
#include <msp/strings/regex.h>
#include <shlobj.h>
#include <msp/core/application.h>
+#include <msp/core/except.h>
#include "dir.h"
using namespace std;
{
const string &appname = Application::get_name();
if(appname.empty())
- throw logic_error("no application name");
+ throw invalid_state("no application name");
char datadir[MAX_PATH];
if(SHGetFolderPath(nullptr, CSIDL_LOCAL_APPDATA, nullptr, 0, datadir)==S_OK)
+#include <msp/core/except.h>
#include "filemonitor.h"
#include "filemonitor_platform.h"
FileMonitor::Private::Private(FileMonitor &)
{
- throw logic_error("not implemented");
+ throw unsupported("FileMonitor");
}
} // namespace FS
-#include <windows.h>
+#include <msp/core/winapi.h>
#include <aclapi.h>
#include <msp/core/systemerror.h>
#include <msp/strings/format.h>
#ifndef MSP_FS_STAT_PLATFORM_H_
#define MSP_FS_STAT_PLATFORM_H_
-#include <windows.h>
+#include <msp/core/winapi.h>
namespace Msp {
namespace FS {
-#include <windows.h>
+#include <msp/core/winapi.h>
+#include <msp/core/except.h>
#include <msp/core/systemerror.h>
#include "dir.h"
#include "utils.h"
Path readlink(const Path &link)
{
(void)link;
- throw logic_error("no symbolic links on win32");
+ throw unsupported("readlink");
}
Path realpath(const Path &path)
+#include <msp/core/except.h>
#include "asset.h"
using namespace std;
void Asset::set_block(bool)
{
- throw logic_error("Asset::set_block");
+ throw unsupported("Asset::set_block");
}
void Asset::set_inherit(bool)
{
- throw logic_error("Asset::set_inherit");
+ throw unsupported("Asset::set_inherit");
}
size_t Asset::do_write(const char *, size_t)
const Handle &Asset::get_handle(Mode)
{
- throw logic_error("Asset::get_handle");
+ throw unsupported("Asset::get_handle");
}
} // namespace IO
#ifndef MSP_IO_ASSET_H_
#define MSP_IO_ASSET_H_
+#include <msp/core/mspcore_api.h>
#include "seekable.h"
namespace Msp {
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;
#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"
/**
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
#include <cstring>
-#include <stdexcept>
+#include <msp/core/except.h>
#include "buffered.h"
#include "handle.h"
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()
const Handle &Buffered::get_handle(Mode)
{
- throw logic_error("Buffered::get_handle");
+ throw unsupported("Buffered::get_handle");
}
void Buffered::set_op(Mode op)
#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;
public:
std::size_t put(char) override;
- bool getline(std::string &);
- int get();
+ bool getline(std::string &) override;
+ int get() override;
const Handle &get_handle(Mode) override;
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
#ifndef MSP_IO_CONSOLE_H_
#define MSP_IO_CONSOLE_H_
+#include <msp/core/mspcore_api.h>
#include "eventobject.h"
#include "handle.h"
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
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
}
-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));
#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"
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
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;
#ifndef MSP_IO_EVENTOBJECT_H_
#define MSP_IO_EVENTOBJECT_H_
+#include <msp/core/mspcore_api.h>
#include "base.h"
namespace Msp {
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
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
+#include <msp/core/except.h>
#include "file.h"
#include "handle_private.h"
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)
const Handle &BufferedFile::get_handle(Mode)
{
- throw logic_error("BufferedFile::get_handle");
+ throw unsupported("BufferedFile::get_handle");
}
SeekOffset BufferedFile::seek(SeekOffset offset, SeekType type)
#include <stdexcept>
#include <string>
+#include <msp/core/mspcore_api.h>
#include "buffered.h"
#include "handle.h"
#include "seekable.h"
namespace Msp {
namespace IO {
-class file_not_found: public std::runtime_error
+class MSPCORE_API file_not_found: public std::runtime_error
{
public:
file_not_found(const std::string &fn): std::runtime_error(fn) { }
- ~file_not_found() throw() override = default;
};
-class file_already_exists: public std::runtime_error
+class MSPCORE_API file_already_exists: public std::runtime_error
{
public:
file_already_exists(const std::string &fn): std::runtime_error(fn) { }
- ~file_already_exists() throw() override = default;
};
Non-blocking mode is not supported on Win32.
*/
-class File: public Seekable
+class MSPCORE_API File: public Seekable
{
public:
enum CreateMode
{ return File::CreateMode(~static_cast<int>(m)); }
-class BufferedFile: public Seekable
+class MSPCORE_API BufferedFile: public Seekable
{
private:
File file;
#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;
#include <algorithm>
#include <cstring>
+#include <msp/core/except.h>
#include "handle.h"
#include "memory.h"
namespace Msp {
namespace IO {
-Memory::Memory(char *b, char *e, Mode m)
+Memory::Memory(char *d, std::size_t s, Mode m):
+ Memory(d, d+s, m)
+{ }
+
+Memory::Memory(char *b, char *e, Mode m):
+ begin(b),
+ end(e),
+ pos(begin)
{
- begin = b;
- end = e;
- pos = begin;
mode = m;
}
+Memory::Memory(const char *d, std::size_t s):
+ Memory(const_cast<char *>(d), const_cast<char *>(d+s), M_READ)
+{ }
+
+Memory::Memory(const char *b, const char *e):
+ Memory(const_cast<char *>(b), const_cast<char *>(e), M_READ)
+{ }
+
void Memory::set_block(bool)
{
- throw logic_error("Memory::set_block");
+ throw unsupported("Memory::set_block");
}
void Memory::set_inherit(bool)
{
- throw logic_error("Memory::set_inherit");
+ throw unsupported("Memory::set_inherit");
}
size_t Memory::do_write(const char *buf, size_t size)
const Handle &Memory::get_handle(Mode)
{
- throw logic_error("Memory::get_handle");
+ throw unsupported("Memory::get_handle");
}
SeekOffset Memory::seek(SeekOffset off, SeekType type)
#ifndef MSP_IO_MEMORY_H_
#define MSP_IO_MEMORY_H_
+#include <msp/core/mspcore_api.h>
#include "seekable.h"
namespace Msp {
namespace IO {
-class Memory: public Seekable
+class MSPCORE_API Memory: public Seekable
{
private:
char *begin = nullptr;
char *pos = nullptr;
public:
- Memory(char *d, std::size_t s, Mode m = M_RDWR): Memory(d, d+s, m) { }
+ Memory(char *d, std::size_t s, Mode m = M_RDWR);
Memory(char *, char *, Mode = M_RDWR);
- Memory(const char *d, std::size_t s): Memory(const_cast<char *>(d), const_cast<char *>(d+s), M_READ) { }
- Memory(const char *b, const char *e): Memory(const_cast<char *>(b), const_cast<char *>(e), M_READ) { }
+ Memory(const char *d, std::size_t s);
+ Memory(const char *b, const char *e);
void set_block(bool) override;
void set_inherit(bool) override;
#define MSP_IO_MODE_H_
#include <stdexcept>
+#include <msp/core/mspcore_api.h>
namespace Msp {
namespace IO {
{ m = b ? (m|f) : (m&~f); }
-class invalid_access: public std::logic_error
+class MSPCORE_API invalid_access: public std::logic_error
{
public:
invalid_access(Mode);
- ~invalid_access() throw() override = default;
};
} // namespace IO
#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"
namespace Msp {
namespace IO {
-class Pipe: public EventObject
+class MSPCORE_API Pipe: public EventObject
{
private:
Handle read_handle;
-#include <stdexcept>
+#include <msp/core/except.h>
#include <msp/core/algorithm.h>
#include "eventobject.h"
#include "poll.h"
#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;
}
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));
}
#include <map>
#include <vector>
+#include <msp/core/mspcore_api.h>
#include <msp/core/noncopyable.h>
#include <msp/time/timedelta.h>
{ return PollEvent(~static_cast<int>(e)); }
-class Poller: private NonCopyable
+class MSPCORE_API Poller: private NonCopyable
{
public:
struct PolledObject
{
- EventObject *object = nullptr;
- PollEvent events = P_NONE;
-
- PolledObject(EventObject *o, PollEvent e): object(o), events(e) { }
+ EventObject *object;
+ PollEvent events;
};
private:
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
#include <cstdint>
#include <stdexcept>
+#include <msp/core/mspcore_api.h>
#include "base.h"
namespace Msp {
};
-class bad_seek: public std::runtime_error
+class MSPCORE_API bad_seek: public std::runtime_error
{
public:
bad_seek(SeekOffset, SeekType);
};
-class Seekable: public Base
+class MSPCORE_API Seekable: public Base
{
protected:
Seekable() = default;
#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"
namespace Msp {
namespace IO {
-class Serial: public EventObject
+class MSPCORE_API Serial: public EventObject
{
public:
enum Parity
-#include <stdexcept>
+#include <msp/core/except.h>
#include "slice.h"
using namespace std;
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;
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()
const Handle &Slice::get_handle(Mode)
{
- throw logic_error("Slice::get_handle");
+ throw unsupported("Slice::get_handle");
}
SeekOffset Slice::seek(SeekOffset off, SeekType type)
#ifndef MSP_IO_SLICE_H_
#define MSP_IO_SLICE_H_
+#include <msp/core/mspcore_api.h>
#include "seekable.h"
namespace Msp {
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;
namespace Msp {
namespace IO {
-EventReader::EventReader(Handle &h, unsigned):
+EventReader::EventReader(Handle &h, size_t):
handle(h)
{ }
void EventReader::wait()
{ }
-unsigned EventReader::read(char *buf, unsigned len)
+unsigned EventReader::read(char *buf, size_t len)
{
return sys_read(handle, buf, len);
}
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;
}
}
else if(st==S_END)
return SEEK_END;
- throw invalid_argument("sys_seek_type");
+ throw invalid_argument("IO::sys_seek");
}
}
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)
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;
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;
{
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;
#define MSP_IO_UTILS_H_
#include <cstddef>
+#include <msp/core/mspcore_api.h>
namespace Msp {
namespace IO {
Note: If the data is not immediately available and the object is in non-blocking
mode, this function effectively becomes a busyloop until it can get more
data. */
-std::size_t read_all(Base &, char *, std::size_t);
+MSPCORE_API std::size_t read_all(Base &, char *, std::size_t);
} // namespace IO
} // namespace Msp
+#include <msp/core/except.h>
#include <msp/core/systemerror.h>
#include "console.h"
#include "handle_private.h"
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");
}
}
-#include <windows.h>
+#include <msp/core/winapi.h>
#include <algorithm>
#include <msp/core/systemerror.h>
#include "eventreader.h"
};
-EventReader::EventReader(Handle &h, unsigned size):
+EventReader::EventReader(Handle &h, size_t size):
handle(h),
priv(new Private)
{
}
}
-unsigned EventReader::read(char *buf, unsigned len)
+unsigned EventReader::read(char *buf, size_t len)
{
if(!priv->buf_avail)
{
size_t sys_read(Handle &handle, char *buf, size_t size)
{
if(size>numeric_limits<DWORD>::max())
- throw invalid_argument("read");
+ throw invalid_argument("IO::sys_read");
DWORD ret;
if(ReadFile(*handle, buf, size, &ret, nullptr)==0)
size_t sys_write(Handle &handle, const char *buf, size_t size)
{
if(size>numeric_limits<DWORD>::max())
- throw invalid_argument("write");
+ throw invalid_argument("IO::sys_write");
DWORD ret;
if(WriteFile(*handle, buf, size, &ret, nullptr)==0)
#ifndef MSP_IO_HANDLE_PLATFORM_H_
#define MSP_IO_HANDLE_PLATFORM_H_
-#include <windows.h>
+#include <msp/core/winapi.h>
namespace Msp {
namespace IO {
+#include <msp/core/except.h>
#include <msp/core/systemerror.h>
#include "eventobject.h"
#include "handle.h"
#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"
-#include <windows.h>
+#include <msp/core/winapi.h>
#include <msp/core/systemerror.h>
#include "handle.h"
#include "handle_private.h"
else if(st==S_END)
return FILE_END;
- throw invalid_argument("sys_seek_type");
+ throw invalid_argument("IO::sys_seek");
}
}
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");
}
}
{
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");
}
}
#ifndef MSP_IO_SERIAL_PLATFORM_H_
#define MSP_IO_SERIAL_PLATFORM_H_
-#include <windows.h>
+#include <msp/core/winapi.h>
namespace Msp {
namespace IO {
#ifdef WITH_ZLIB
#include <zlib.h>
#endif
+#include <msp/core/except.h>
#include "zlibcompressed.h"
using namespace std;
(void)buffer_size;
(void)stream_end;
(void)level;
- throw zlib_error("unsupported", -1);
+ throw unsupported("ZlibCompressed");
#endif
}
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()
const Handle &ZlibCompressed::get_handle(Mode)
{
- throw logic_error("ZlibCompressed::get_handle");
+ throw unsupported("ZlibCompressed::get_handle");
}
} // namespace IO
#include <stdexcept>
#include <string>
#include <sigc++/trackable.h>
+#include <msp/core/mspcore_api.h>
#include "base.h"
namespace Msp {
namespace IO {
-class zlib_error: public std::runtime_error
+class MSPCORE_API zlib_error: public std::runtime_error
{
private:
int m_code;
public:
zlib_error(const std::string &, int);
- ~zlib_error() throw() override = default;
- int code() const throw() { return m_code; }
+ int code() const noexcept { return m_code; }
};
/**
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;
#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) { }
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) { }
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);
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)
#define MSP_STRINGCODEC_CODEC_H_
#include <string>
+#include <msp/core/mspcore_api.h>
#include "except.h"
#include "ustring.h"
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:
/**
may find it useful or necessary to implement some other functions too
(particularly sync and reset for stateful codecs).
*/
- class Encoder
+ class MSPCORE_API Encoder
{
protected:
ErrorMode err_mode = THROW_ON_ERROR;
Each codec class should contain an Decoder class derived from this.
*/
- class Decoder
+ class MSPCORE_API Decoder
{
protected:
ErrorMode err_mode = THROW_ON_ERROR;
/** 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
#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
#define MSP_STRINGCODEC_EXCEPT_H_
#include <stdexcept>
+#include <msp/core/mspcore_api.h>
#include "ustring.h"
namespace Msp {
/**
Base class for codec errors.
*/
-class codec_error: public std::runtime_error
+class MSPCORE_API codec_error: public std::runtime_error
{
public:
codec_error(const std::string &w): std::runtime_error(w) { }
- ~codec_error() throw() override = default;
};
/**
Thrown when a codec can't encode the requested character.
*/
-class invalid_character: public codec_error
+class MSPCORE_API invalid_character: public codec_error
{
public:
invalid_character(unichar, const std::string &);
- ~invalid_character() throw() override = default;
};
/**
Thrown when a codec encounters a byte sequence it can't decode.
*/
-class invalid_sequence: public codec_error
+class MSPCORE_API invalid_sequence: public codec_error
{
public:
invalid_sequence(const std::string::const_iterator &, const std::string::const_iterator &, const std::string &);
- ~invalid_sequence() throw() override = default;
private:
std::string format_sequence(const std::string::const_iterator &, const std::string::const_iterator &);
+#include <msp/core/except.h>
#include "ascii.h"
#include "iso2022jp.h"
#include "jisx0201.h"
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;
#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
JISX0208
};
- class Encoder: public Codec::Encoder
+ class MSPCORE_API Encoder: public Codec::Encoder
{
private:
Mode mode = ASCII;
void transliterate(unichar, std::string &) override;
};
- class Decoder: public Codec::Decoder
+ class MSPCORE_API Decoder: public Codec::Decoder
{
private:
Mode mode = ASCII;
#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) { }
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) { }
#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) { }
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) { }
#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) { }
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) { }
#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) { }
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) { }
#ifndef MSP_STRINGCODEC_JISX0208_H_
#define MSP_STRINGCODEC_JISX0208_H_
+#include <msp/core/mspcore_api.h>
#include "codec.h"
namespace Msp {
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) { }
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) { }
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
#ifndef MSP_STRINGCODEC_UTF16_H_
#define MSP_STRINGCODEC_UTF16_H_
+#include <msp/core/mspcore_api.h>
#include "codec.h"
namespace Msp {
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
LITTLE
};
- class Encoder: public Codec::Encoder
+ class MSPCORE_API Encoder: public Codec::Encoder
{
private:
Endian endian = BIG;
void transliterate(unichar, std::string &) override;
};
- class Decoder: public Codec::Decoder
+ class MSPCORE_API Decoder: public Codec::Decoder
{
private:
Endian endian = AUTO;
#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) { }
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) { }
#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) { }
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) { }
#include <ostream>
#include <stdexcept>
#include <string>
+#include <msp/core/mspcore_api.h>
namespace Msp {
-class format_error: public std::logic_error
+class MSPCORE_API format_error: public std::logic_error
{
public:
format_error(const std::string &w): std::logic_error(w) { }
- ~format_error() throw() override = default;
};
b/B Binary integer conversion
P Uppercase pointer conversion (like %#X)
*/
-class Fmt
+class MSPCORE_API Fmt
{
public:
enum Type
#define MSP_STRINGS_FORMAT_H_
#include <string>
+#include <msp/core/mspcore_api.h>
#include "lexicalcast.h"
namespace Msp {
/**
Printf-like string formatter class.
*/
-class Formatter
+class MSPCORE_API Formatter
{
private:
std::string fmt;
#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
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())); }
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()); }
#include <string>
#include <stdexcept>
#include <msp/core/meta.h>
+#include <msp/core/mspcore_api.h>
#include "fmt.h"
namespace Msp {
/**
Thrown for errors in lexical conversions.
*/
-class lexical_error: public std::runtime_error
+class MSPCORE_API lexical_error: public std::runtime_error
{
public:
lexical_error(const std::string &w): runtime_error(w) { }
- ~lexical_error() throw() override = default;
};
/**
Thrown when the format is unsuitable for the type being converted.
*/
-class format_mismatch: public lexical_error
+class MSPCORE_API format_mismatch: public lexical_error
{
public:
format_mismatch(const std::string &w): lexical_error(w) { }
- ~format_mismatch() throw() override = default;
};
/**
Helper class for lexical_cast to facilitate operator overloading.
*/
-class LexicalConverter
+class MSPCORE_API LexicalConverter
{
private:
Fmt fmt;
};
-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
#include <list>
#include <stack>
#include <vector>
+#include <msp/core/except.h>
#include "format.h"
#include "regex.h"
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;
#include <stdexcept>
#include <string>
+#include <msp/core/mspcore_api.h>
#include "regmatch.h"
namespace Msp {
-class bad_regex: public std::logic_error
+class MSPCORE_API bad_regex: public std::logic_error
{
public:
bad_regex(const std::string &, const std::string &, const std::string::const_iterator &);
- ~bad_regex() throw() override = default;
private:
std::string make_where(const std::string &, const std::string::const_iterator &);
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;
#include <string>
#include <vector>
+#include <msp/core/mspcore_api.h>
namespace Msp {
matched by subregexes. These are ordered from left to right, by the opening
parenthesis of the subregex.
*/
-class RegMatch
+class MSPCORE_API RegMatch
{
public:
/**
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)
#include <string>
#include <vector>
+#include <msp/core/mspcore_api.h>
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 */
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>
}
/** 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
#define MSP_TIME_DATETIME_H_
#include <string>
+#include <msp/core/mspcore_api.h>
#include "timezone.h"
#include "rawtime.h"
are relatively slow. For purposes of internal scheduling in a program, a
TimeStamp is a better choice.
*/
-class DateTime
+class MSPCORE_API DateTime
{
private:
int year = 1970;
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
#include <cstdlib>
#include <ctime>
+#include <msp/core/mspcore_api.h>
#include <msp/strings/lexicalcast.h>
#include "rawtime.h"
/**
Represents a quantity of time, such as five seconds.
*/
-class TimeDelta
+class MSPCORE_API TimeDelta
{
private:
RawTime usec = 0;
public:
/** Constructs a zero TimeDelta. */
- TimeDelta() = default;
+ constexpr TimeDelta() = default;
/** Constructs a TimeDelta from a plain number. The purpose of this is to
allow serialization together with the raw() function. */
- explicit TimeDelta(RawTime u): usec(u) { }
+ explicit constexpr TimeDelta(RawTime u): usec(u) { }
/** Returns the raw number stored inside the TimeDelta. This should only be used
for serialization and the result should not be interpreted in any way. */
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;
{
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();
{
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();
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
}
-Timer::SlotProxy::SlotProxy(Slot *s):
- slot(s)
-{ }
-
bool Timer::SlotProxy::operator<(const SlotProxy &sp) const
{
return slot->get_timeout()>sp.slot->get_timeout();
#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>
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
private:
struct SlotProxy
{
- Slot *slot = nullptr;
+ Slot *slot;
- SlotProxy(Slot *);
bool operator<(const SlotProxy &) const;
};
#ifndef MSP_TIME_TIMESTAMP_H_
#define MSP_TIME_TIMESTAMP_H_
+#include <msp/core/mspcore_api.h>
#include "timedelta.h"
#include "rawtime.h"
For representing user-specified times, use the DateTime class.
*/
-class TimeStamp
+class MSPCORE_API TimeStamp
{
private:
RawTime usec = 0;
#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;
#define MSP_TIME_UTILS_H_
#include <string>
+#include <msp/core/mspcore_api.h>
namespace Msp {
namespace Time {
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
#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 {
-#include <windows.h>
+#include <msp/core/winapi.h>
#include <msp/core/systemerror.h>
#include "timezone.h"
-#include <windows.h>
+#include <msp/core/winapi.h>
#include "rawtime_private.h"
#include "timedelta.h"
#include "timestamp.h"
--- /dev/null
+/consoletest
+/consoletest.*
+/test
+/test.*
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 = "/..";
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()