/* Copyright: © 2018 SIL International. Description: Internal keyboard class and adaptor class for the API. Create Date: 2 Oct 2018 Authors: Tim Eves (TSE) History: 2 Oct 2018 - TSE - Refactored out of km_kbp_keyboard_api.cpp */ #pragma once #include #include #include #include #include "json.hpp" #include "utfcodec.hpp" // Forward declarations namespace km { namespace kbp { class path { public: using char_type = std::remove_const_t< std::remove_pointer_t>; using string_type = std::basic_string; static constexpr char_type const parent_separator = _KM_KBP_PATH_SEPARATOR, suffix_separator = _KM_KBP_EXT_SEPARATOR; private: string_type _path; void normalise() { #if '/' != _KM_KBP_PATH_SEPARATOR std::replace(_path.begin(), _path.end(), char_type('/'), _KM_KBP_PATH_SEPARATOR); #endif } public: template static path join(path const &start, Args&&... args) { auto r = start; for (path p: {args...}) r._path.append(1, path::parent_separator).append(p); return r; } path() = default; path(path const &) = default; path(path &&) = default; path & operator = (path const &) = default; path & operator = (path &&) = default; path(std::string const & p): _path(convert(p)) { normalise(); } path(std::u16string const & p): _path(convert(p)) { normalise(); } path(std::wstring const & p): _path(convert(p)) { normalise(); } template path(C const * p): path(std::basic_string(p)) {} path parent() const { auto i = _path.find_last_of(parent_separator); return _path.substr(0, i == string_type::npos ? 0UL : i); } path name() const { auto i = _path.find_last_of(parent_separator); return _path.substr(i == string_type::npos ? 0UL : i+1); } path suffix() const { auto i = _path.find_last_of(suffix_separator); return _path.substr(i == string_type::npos ? _path.size() : i); } path stem() const { auto psep = _path.find_last_of(parent_separator), ssep = _path.find_last_of(suffix_separator); return _path.substr(psep == string_type::npos ? 0UL : psep+1, ssep == string_type::npos ? _path.size() : ssep); } void replace_extension(path const & replacment = path()) { _path.resize(std::min(_path.find_last_of(suffix_separator), _path.size())); _path += replacment; } // template // bool operator == (T const * rhs) const { return _path == rhs; } bool operator == (path const &rhs) const { return _path == rhs._path; } // template // bool operator != (T const * rhs) const { return _path != rhs; } bool operator != (path const &rhs) const { return _path != rhs._path; } string_type const & native() const noexcept { return _path; } operator std::wstring () const { return convert(_path); } operator std::string() const { return convert(_path); }; operator std::u16string() const {return convert(_path); }; char_type const * c_str() const { return _path.c_str(); } path & operator += (path const & rhs) { _path += rhs._path; return *this; } path operator + (path const & rhs) const { auto r = *this; return r += rhs; } path & operator /= (path const & rhs) { _path.append(1,path::parent_separator).append(rhs._path); return *this; } path operator / (path const & rhs) const { auto r = *this; return r /= rhs; } friend json & operator << (json &, path const &); }; template bool operator == (T const * lhs, path const & rhs) { return rhs == lhs; } template bool operator != (T const * lhs, path const & rhs) { return rhs != lhs; } inline json & operator << (json &j, path const &p) { return j << static_cast(p); } template auto & operator << (std::basic_ostream &os, path const &p) { os << static_cast>(p); return os; } } // namespace kbp } // namespace km