diff options
author | John Hodge <tpg@mutabah.net> | 2018-03-18 10:48:26 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2018-04-01 14:02:32 +0800 |
commit | 5701df58fa8c9e067474659e6c54e47856cef7f0 (patch) | |
tree | c288493eb4ed7f9fe7ae998bde3c553484a989b2 /tools/common/path.h | |
parent | c643adf22ea365bd7c8ed40f971c0cc99c9cf2a6 (diff) | |
download | mrust-5701df58fa8c9e067474659e6c54e47856cef7f0.tar.gz |
All - Move toml parser and path header to a common library, start on custom target specs.
Diffstat (limited to 'tools/common/path.h')
-rw-r--r-- | tools/common/path.h | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/tools/common/path.h b/tools/common/path.h new file mode 100644 index 00000000..dd97f9be --- /dev/null +++ b/tools/common/path.h @@ -0,0 +1,181 @@ +#pragma once + +#include <string> +#include <stdexcept> +#include "helpers.h" + +namespace helpers { + +/// Path helper class (because I don't want to include boost) +class path +{ +#ifdef _WIN32 + static const char SEP = '\\'; +#else + static const char SEP = '/'; +#endif + + ::std::string m_str; + +public: + path() + { + } + path(const ::std::string& s): + path(s.c_str()) + { + } + path(const char* s); + + bool is_valid() const { + return m_str != ""; + } + + path& operator/=(const path& p) + { + if(!p.is_valid()) + throw ::std::runtime_error("Appending from an invalid path"); + + return *this /= p.m_str.c_str(); + } + path& operator/=(const char* o) + { + if(!this->is_valid()) + throw ::std::runtime_error("Appending to an invalid path"); + if(o[0] == '/') + throw ::std::runtime_error("Appending an absolute path to another path"); + this->m_str.push_back(SEP); + this->m_str.append(o); + return *this; + } + path& operator/=(const string_view& o) + { + if(!this->is_valid()) + throw ::std::runtime_error("Appending to an invalid path"); + if(o[0] == '/') + throw ::std::runtime_error("Appending an absolute path to another path"); + this->m_str.push_back(SEP); + this->m_str += o; + return *this; + } + + path operator/(const path& p) const + { + auto rv = *this; + rv /= p; + return rv; + } + /// Append a relative path + path operator/(const char* o) const + { + auto rv = *this; + rv /= o; + return rv; + } + /// Add an arbitary string to the final component + path operator+(const char* o) const + { + if(!this->is_valid()) + throw ::std::runtime_error("Appending a string to an invalid path"); + if( ::std::strchr(o, SEP) != nullptr ) + throw ::std::runtime_error("Appending a string containing the path separator (with operator+)"); + auto rv = *this; + rv.m_str.append(o); + return rv; + } + + bool pop_component() + { + if(!this->is_valid()) + throw ::std::runtime_error("Calling pop_component() on an invalid path"); + auto pos = m_str.find_last_of(SEP); + if(pos == ::std::string::npos || pos == 0) + { + return false; + } + else + { + this->m_str.resize(pos); + return true; + } + } + path parent() const + { + if(!this->is_valid()) + throw ::std::runtime_error("Calling parent() on an invalid path"); + auto pos = m_str.find_last_of(SEP); + if(pos == ::std::string::npos) + { + return *this; + } + else + { + path rv; + rv.m_str = m_str.substr(0, pos); + return rv; + } + } + path to_absolute() const; + ::std::string basename() const + { + if(!this->is_valid()) + throw ::std::runtime_error("Calling basename() on an invalid path"); + + auto pos = m_str.find_last_of(SEP); + if(pos == ::std::string::npos) + { + return m_str; + } + else + { + return m_str.substr(pos+1); + } + } + + const ::std::string& str() const + { + return m_str; + } + operator ::std::string() const + { + return m_str; + } + + class ComponentsIter + { + const path& p; + size_t pos; + size_t end; + + friend class path; + ComponentsIter(const path& p, size_t i): p(p), pos(i) { + end = p.m_str.find(SEP, pos); + if(end == ::std::string::npos) + end = p.m_str.size(); + } + public: + string_view operator*() const { + return string_view(p.m_str.c_str() + pos, end - pos); + } + void operator++(); + bool operator!=(const ComponentsIter& x) const { + return pos != x.pos; + } + }; + ComponentsIter begin() const { + return ComponentsIter(*this, 0); + } + ComponentsIter end() const { + return ComponentsIter(*this, m_str.size()); + } + + path normalise() const; + //void normalise_in_place(); + + friend ::std::ostream& operator<<(::std::ostream& os, const path& p) + { + return os << p.m_str; + } +}; + +} |