summaryrefslogtreecommitdiff
path: root/tools/minicargo/path.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/minicargo/path.cpp')
-rw-r--r--tools/minicargo/path.cpp157
1 files changed, 157 insertions, 0 deletions
diff --git a/tools/minicargo/path.cpp b/tools/minicargo/path.cpp
new file mode 100644
index 00000000..d0316548
--- /dev/null
+++ b/tools/minicargo/path.cpp
@@ -0,0 +1,157 @@
+/*
+ */
+#include "path.h"
+
+helpers::path::path(const char* s):
+ m_str(s)
+{
+ // 1. Normalise path separators to the system specified separator
+ for(size_t i = 0; i < m_str.size(); i ++)
+ {
+ if( m_str[i] == '/' || m_str[i] == '\\' )
+ m_str[i] = SEP;
+ }
+
+ // 2. Remove any trailing separators
+ if( !m_str.empty() )
+ {
+ while(!m_str.empty() && m_str.back() == SEP )
+ m_str.pop_back();
+ if(m_str.empty())
+ {
+ m_str.push_back(SEP);
+ }
+ }
+ else
+ {
+ throw ::std::runtime_error("Empty path being constructed");
+ }
+}
+
+helpers::path helpers::path::normalise() const
+{
+ path rv;
+ rv.m_str.reserve( m_str.size()+1 );
+
+ for(auto comp : *this)
+ {
+ if( comp == "." ) {
+ // Ignore.
+ }
+ else if( comp == ".." )
+ {
+ // If the path is empty, OR the last element is a "..", push the element
+ if( rv.m_str.empty()
+ || (rv.m_str.size() == 3 && rv.m_str[0] == '.' && rv.m_str[1] == '.' && rv.m_str[2] == SEP)
+ || (rv.m_str.size() > 4 && *(rv.m_str.end()-4) == SEP && *(rv.m_str.end()-3) == '.' && *(rv.m_str.end()-2) == '.' && *(rv.m_str.end()-1) == SEP )
+ )
+ {
+ // Push
+ rv.m_str += comp;
+ rv.m_str += SEP;
+ }
+ else
+ {
+ rv.m_str.pop_back();
+ auto pos = rv.m_str.find_last_of(SEP);
+ if(pos == ::std::string::npos)
+ {
+ rv.m_str.resize(0);
+ }
+ else if( pos == 0 )
+ {
+ // Keep.
+ }
+ else
+ {
+ rv.m_str.resize(pos+1);
+ }
+ }
+ }
+ else
+ {
+ rv.m_str += comp;
+ rv.m_str += SEP;
+ }
+ }
+ rv.m_str.pop_back();
+ return rv;
+}
+
+#if 0
+void helpers::path::normalise_in_place()
+{
+ size_t insert_point = 0;
+
+ for(size_t read_pos = 0; read_pos < m_str.size(); read_pos ++)
+ {
+ auto pos = m_str.find_first_of(SEP, read_pos);
+ if(pos == ::std::string::npos)
+ pos = m_str.size();
+ auto comp = string_view(m_str.c_str() + read_pos, pos - read_pos);
+
+ bool append;
+ if(comp == ".")
+ {
+ // Advance read without touching insert
+ append = false;
+ }
+ else if( comp == ".." )
+ {
+ // Consume parent (if not a relative component already)
+ // Move insertion point back to the previous separator
+ auto pos = m_str.find_last_of(SEP, insert_point);
+ if(pos == ::std::string::npos)
+ {
+ // Only one component currently (or empty)
+ append = true;
+ }
+ else if(string_view(m_str.c_str() + pos+1, insert_point - pos-1) == "..")
+ {
+ // Last component is ".." - keep adding
+ append = true;
+ }
+ else
+ {
+ insert_point = pos;
+ append = false;
+ }
+ }
+ else
+ {
+ append = true;
+ }
+
+ if(append)
+ {
+ if( read_pos != insert_point )
+ {
+ //assert(read_pos > insert_point);
+ while(read_pos < pos)
+ {
+ m_str[insert_point++] = m_str[read_pos++];
+ }
+ }
+ }
+ else
+ {
+ read_pos = pos;
+ }
+ }
+}
+#endif
+
+void helpers::path::ComponentsIter::operator++()
+{
+ if(end == p.m_str.size())
+ {
+ pos = end;
+ }
+ else
+ {
+ pos = end+1;
+ end = p.m_str.find(SEP, pos);
+ if(end == ::std::string::npos)
+ end = p.m_str.size();
+ }
+} \ No newline at end of file