summaryrefslogtreecommitdiff
path: root/tools/common/path.h
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2018-03-18 10:48:26 +0800
committerJohn Hodge <tpg@mutabah.net>2018-04-01 14:02:32 +0800
commit5701df58fa8c9e067474659e6c54e47856cef7f0 (patch)
treec288493eb4ed7f9fe7ae998bde3c553484a989b2 /tools/common/path.h
parentc643adf22ea365bd7c8ed40f971c0cc99c9cf2a6 (diff)
downloadmrust-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.h181
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;
+ }
+};
+
+}