.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.*
};
Z::Z(int argc, char **argv):
- input_file(0)
+ input_file(nullptr)
{
string input_fn;
GetOpt getopt;
#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 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>
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
#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
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();
JavaVM *MainThread::get_java_vm() const
{
if(!activity)
- return 0;
+ return nullptr;
return activity->vm;
}
/* 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);
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:
void set_window_flags(unsigned, unsigned);
private:
- virtual void main();
+ void main() override;
static void app_created(void *);
static void activity_destroyed(ANativeActivity *);
#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;
{
try
{
- app_ = starter_->create_app(argc, argv);
+ _app = _starter->create_app(argc, argv);
}
catch(const usage_error &e)
{
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;
}
}
}
- delete app_;
- app_ = 0;
+ delete _app;
+ _app = nullptr;
return 124;
}
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;
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()
void Application::catch_signal(int s)
{
- signal(s, &sighandler_);
+ signal(s, &_sighandler);
}
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
#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();
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
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.
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
private:
/** Static wrapper function to call a member function of the Application
instance. */
- static void sighandler_(int);
+ static void _sighandler(int);
};
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
#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
namespace Msp {
-GetOpt::GetOpt():
- help(false)
+GetOpt::GetOpt()
{
add_option("help", help, NO_ARG).set_help("Displays this help");
}
shrt(s),
lng(l),
arg_type(a),
- seen_count(0),
- ext_seen_count(0),
- metavar("ARG"),
store(t.clone())
{ }
#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(); }
};
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() { }
+ Option() = default;
public:
- virtual ~Option() { }
+ virtual ~Option() = default;
/// Sets help text for the option.
virtual Option &set_help(const std::string &) = 0;
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;
};
class Store
{
protected:
- Store() { }
+ Store() = default;
public:
- virtual ~Store() { }
+ virtual ~Store() = default;
virtual Store *clone() const = 0;
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 &);
};
{
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; }
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); }
};
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;
+++ /dev/null
-#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
#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
#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>
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 &);
#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 &);
--- /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;
private:
struct Private;
- Private *priv;
+ Private *priv = nullptr;
public:
Mutex();
/**
Locks the mutex for the lifetime of the object.
*/
-class MutexLock
+class MSPCORE_API MutexLock
{
private:
Mutex &mutex;
T &operator*() const { return *data; }
T *operator->() const { return data; }
- void clear() { mutex = 0; data = 0; }
+ void clear() { mutex = nullptr; data = nullptr; }
};
}
#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 = 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
argv[j++] = argv[i];
}
argc = j;
- argv[j] = 0;
+ argv[j] = nullptr;
return Msp::Application::run(argc, argv, data);
}
#include <msp/io/console.h>
+#include "except.h"
#include "process.h"
#include "process_private.h"
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()
{
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;
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();
#ifndef MSP_CORE_PROCESS_PRIVATE_H_
#define MSP_CORE_PROCESS_PRIVATE_H_
+#include "process.h"
#include "process_platform.h"
namespace Msp {
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>
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
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(); }
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); }
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(); }
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();
};
{
decref();
data = d;
- counts = (d ? new RefCounts : 0);
+ counts = (d ? new RefCounts : nullptr);
incref();
return *this;
}
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;
T *RefPtr<T>::release()
{
T *d = data;
- data = 0;
+ data = nullptr;
decref();
- counts = 0;
+ counts = nullptr;
return d;
}
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;
}
}
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;
}
if(!counts->weak_count && (!counts->count || counts->count==RefCounts::KEEP))
{
delete counts;
- data = 0;
- counts = 0;
+ data = nullptr;
+ counts = nullptr;
}
}
#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);
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
#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);
-#include <stdexcept>
+#include "except.h"
#include "thread.h"
#include "thread_private.h"
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)
Thread *thread = reinterpret_cast<Thread *>(arg);
thread->platform_setname();
thread->main();
- thread->state_ = FINISHED;
+ thread->_state = FINISHED;
return 0;
}
#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;
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. */
struct Thread::Private
{
- ThreadHandle handle;
-
- Private(): handle(0) { }
+ ThreadHandle handle = 0;
static ThreadReturn THREAD_CALL main_wrapper(void *);
};
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;
#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);
}
Mutex::Mutex():
priv(new Private)
{
- pthread_mutex_init(&priv->mutex, 0);
+ pthread_mutex_init(&priv->mutex, nullptr);
}
Mutex::~Mutex()
#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)
{
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)
{
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));
{
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()
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
}
#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
#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)
{
priv.info.hProcess = GetCurrentProcess();
- priv.info.hThread = 0;
+ priv.info.hThread = nullptr;
priv.info.dwProcessId = GetCurrentProcessId();
priv.info.dwThreadId = 0;
}
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;
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)
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)
Process::Private::Private()
{
- info.hProcess = 0;
- info.hThread = 0;
+ info.hProcess = nullptr;
+ info.hThread = nullptr;
info.dwProcessId = 0;
info.dwThreadId = 0;
}
#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"
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());
-#include <windows.h>
+#include "winapi.h"
#include "thread.h"
#include "thread_private.h"
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()
#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
{
- void *address;
+ void *address = nullptr;
std::string file;
std::string symbol;
};
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
{
#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)
#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
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
#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;
};
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);
}
#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
namespace Msp {
namespace Debug {
-Profiler::Profiler():
- period(0),
- inner(0)
-{ }
-
void Profiler::set_period(unsigned p)
{
if(p==period)
return get_item(scopes, sn);
}
-
-Profiler::ScopeInfo::ScopeInfo():
- calls(0),
- calls_per_sec(0),
- hist_pos(0),
- hist_full(false)
-{ }
-
} // 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;
+ 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);
#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;
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();
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
#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 &);
- 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
#include <msp/core/algorithm.h>
+#include <msp/core/except.h>
#include "filemonitor.h"
#include "filemonitor_platform.h"
namespace FS {
FileMonitor::FileMonitor():
- priv(new Private(*this)),
- event_disp(0)
+ priv(new Private(*this))
{ }
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();
{
MonitoredFile file;
file.path = path;
- file.modified = false;
prepare_file(file);
files.push_back(file);
}
#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;
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:
#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));
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;
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;
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; }
#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;
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),
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;
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;
}
#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"
SYMLINK
};
-typedef UInt64 FileSize;
+typedef uint64_t FileSize;
/**
Holds file information.
*/
-class Stat
+class MSPCORE_API Stat
{
private:
struct 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();
{ 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)
#ifndef MSP_FS_STAT_PRIVATE_H_
#define MSP_FS_STAT_PRIVATE_H_
+#include "stat.h"
#include "stat_platform.h"
namespace Msp {
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();
#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_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 {
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; }
};
{
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
typedef uid_t UserID;
typedef gid_t GroupID;
+const UserID INVALID_UID = -1;
+const GroupID INVALID_GID = -1;
+
} // namespace FS
} // namespace Msp
#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>
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();
#include <shlobj.h>
#include <msp/core/application.h>
+#include <msp/core/except.h>
#include "dir.h"
using namespace std;
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 ".";
}
{
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 ".";
}
+#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
#ifndef MSP_FS_FILEMONITOR_PLATFORM_H_
#define MSP_FS_FILEMONITOR_PLATFORM_H_
+#include "filemonitor.h"
+
namespace Msp {
namespace FS {
-#include <windows.h>
+#include <msp/core/winapi.h>
#include <aclapi.h>
#include <msp/core/systemerror.h>
#include <msp/strings/format.h>
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))
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);
}
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";
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();
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);
#ifndef MSP_FS_STAT_PLATFORM_H_
#define MSP_FS_STAT_PLATFORM_H_
-#include <windows.h>
+#include <msp/core/winapi.h>
namespace Msp {
namespace FS {
typedef PSID UserID;
typedef PSID GroupID;
+const UserID INVALID_UID = nullptr;
+const GroupID INVALID_GID = nullptr;
+
} // namespace FS
} // namespace Msp
-#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)
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");
+#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");
}
-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
#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;
- 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
namespace Msp {
namespace IO {
-Base::Base():
- mode(M_READ),
- eof_flag(false),
- mutex(0)
+Base::Base()
{ }
Base::~Base()
#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
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:
#include <cstring>
-#include <stdexcept>
+#include <msp/core/except.h>
#include "buffered.h"
#include "handle.h"
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));
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;
- 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);
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
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. */
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
}
-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;
namespace Msp {
namespace IO {
-EventObject::EventObject():
- events(P_NONE)
+EventObject::EventObject()
{ }
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)
#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
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;
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
+#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 "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() { }
};
Non-blocking mode is not supported on Win32.
*/
-class File: public Seekable
+class MSPCORE_API File: public Seekable
{
public:
enum CreateMode
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)
{ return File::CreateMode(~static_cast<int>(m)); }
-class BufferedFile: public Seekable
+class MSPCORE_API BufferedFile: public Seekable
{
private:
File file;
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
+++ /dev/null
-#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
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);
}
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;
}
#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();
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;
};
#include <algorithm>
#include <cstring>
+#include <msp/core/except.h>
#include "handle.h"
#include "memory.h"
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)
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;
- 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
#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() { }
};
} // namespace IO
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)
#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;
~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
-#include <stdexcept>
+#include <msp/core/except.h>
#include <msp/core/algorithm.h>
#include "eventobject.h"
#include "poll.h"
namespace IO {
Poller::Poller():
- priv(new Private),
- events_changed(false),
- objs_changed(false)
+ priv(new Private)
{ }
Poller::~Poller()
#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;
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:
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
#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 {
class Handle;
-typedef Int64 SeekOffset;
+typedef std::int64_t SeekOffset;
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. */
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;
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();
#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
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);
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
-#include <stdexcept>
+#include <msp/core/except.h>
#include "slice.h"
using namespace std;
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;
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;
- 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
namespace Msp {
namespace IO {
-EventReader::EventReader(Handle &h, unsigned):
- handle(h),
- priv(0)
+EventReader::EventReader(Handle &h, size_t):
+ handle(h)
{ }
EventReader::~EventReader()
void EventReader::wait()
{ }
-unsigned EventReader::read(char *buf, unsigned len)
+unsigned EventReader::read(char *buf, size_t len)
{
return sys_read(handle, buf, len);
}
typedef int PlatformHandle;
-#define INVALID_HANDLE_VALUE -1
+const PlatformHandle INVALID_HANDLE_VALUE = -1;
} // namespace IO
} // namespace Msp
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;
}
}
#include <poll.h>
#include <vector>
+#include "poll.h"
namespace Msp {
namespace IO {
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;
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);
#ifndef MSP_IO_UTILS_H_
#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. */
-unsigned read_all(Base &, char *, unsigned);
+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"
{
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()
}
}
-unsigned EventReader::read(char *buf, unsigned len)
+unsigned EventReader::read(char *buf, size_t len)
{
if(!priv->buf_avail)
{
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();
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;
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;
#ifndef MSP_IO_HANDLE_PLATFORM_H_
#define MSP_IO_HANDLE_PLATFORM_H_
-#include <windows.h>
+#include <msp/core/winapi.h>
namespace Msp {
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();
+#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"
namespace Msp {
namespace IO {
-#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");
}
}
{
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;
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;
#else
runtime_error(w),
#endif
- code_(c)
+ m_code(c)
{ }
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)
{
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)
(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 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; }
};
/**
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
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
#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
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;
+ 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. */
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
};
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;
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) { }
{ 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)); }
};
/** 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) { }
- 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 &);
+#include <msp/core/except.h>
#include "ascii.h"
#include "iso2022jp.h"
#include "jisx0201.h"
Iso2022Jp::Decoder::Decoder(ErrorMode em):
Codec::Decoder(em),
- mode(ASCII),
dec(new Ascii::Decoder)
{ }
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;
+ 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
#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
#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
#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
#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
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
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;
#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) { }
- 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
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)
#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;
- 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):
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); }
};
#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
#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
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
#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() { }
};
b/B Binary integer conversion
P Uppercase pointer conversion (like %#X)
*/
-class Fmt
+class MSPCORE_API Fmt
{
public:
enum Type
};
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 *);
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;
#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
#include <cmath>
+#include <cstdint>
#include <limits>
-#include <msp/core/inttypes.h>
#include "format.h"
#include "lexicalcast.h"
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())); }
{ 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>> ***/
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) { }
- 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; }
};
-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"
Regex::Regex(const string &expr)
{
- n_groups = 0;
auto iter = expr.begin();
code = compile(expr, iter, n_groups, false);
++n_groups;
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 &);
- virtual ~bad_regex() throw() { }
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;
};
Code code;
- unsigned n_groups;
+ unsigned n_groups = 0;
public:
/** Constructs a new Regex object from a string representation. */
#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:
/**
{
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:
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
/** 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
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
}
template<typename T>
-inline int cmp_(T a, T b)
+inline int _cmp(T a, T b)
{
if(a<b)
return -1;
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)
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;
}
#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;
- 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:
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; }
#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
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;
+ 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. */
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;
namespace Time {
Timer::Timer():
- sem(1),
- blocking(false)
+ sem(1)
{ }
Timer::~Timer()
{
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(timeout>=zero)
deadline = now()+timeout;
- Slot *next = 0;
+ Slot *next = nullptr;
{
MutexLock l(mutex);
while(1)
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
{
Slot *slot;
- SlotProxy(Slot *);
bool operator<(const SlotProxy &) const;
};
std::vector<SlotProxy> slots;
Semaphore sem;
Mutex mutex;
- bool blocking;
+ bool blocking = false;
public:
Timer();
#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;
+ 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. */
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); }
};
#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;
TimeStamp now()
{
timeval tv;
- gettimeofday(&tv, 0);
+ gettimeofday(&tv, nullptr);
return TimeStamp(timeval_to_rawtime(tv));
}
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");
}
#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()