ResourcePath.cpp
Go to the documentation of this file.
1 #include "ResourcePath.hpp"
2 #include "../fs.hpp"
3 
4 #include <optional>
5 
6 namespace iv
7 {
8 
9 void ResourcePath::Clean( std::string & path )
10 {
11  int from = 0;
12  int to = 0;
13  bool keep_root_slash = path.size() > 0 && path[ 0 ] == '/';
14 
15  std::optional< size_t > dots = 0;
16 
17  while( true )
18  {
19  if( path[ from ] == '.' )
20  {
21  if( dots.has_value() )
22  dots = dots.value() + 1;
23  }
24  else if( path[ from ] == '/' || from == path.size() )
25  {
26  if( dots.has_value() )
27  {
28  if( dots.value() == 0 )
29  {
30  if( !keep_root_slash || to > 0 )
31  to--;
32  }
33  else if( dots.value() == 1 )
34  {
35  to -= 2;
36  }
37  else if( dots.value() == 2 )
38  {
39  // trace back until I locate previous descriptor and move 'to' to it
40  int newto = to - 1;
41  size_t slash_cnt = 0;
42 
43  while( true )
44  {
45  if( ( newto == -1 && path[ 0 ] != '/' ) || path[ newto ] == '/' )
46  {
47  slash_cnt++;
48  if( slash_cnt == 2 )
49  {
50  to = newto;
51  break;
52  }
53  }
54 
55  if( newto == -1 )
56  break;
57 
58  newto--;
59  }
60  }
61  }
62 
63  // next path fraction
64  dots = 0;
65  }
66  else
67  {
68  dots = std::nullopt;
69  }
70 
71  //
72  if( from == path.size() )
73  {
74  if( path.size() && path[ 0 ] == '/' )
75  to = std::max( to, 1 );
76 
77  path.resize( std::max( to, 0 ) );
78  break;
79  }
80 
81  // next iteration
82  if( to >= 0 )
83  path[ to ] = path[ from ];
84  to++;
85  from++;
86  }
87 }
88 
90  path("")
91 {
92 }
93 
94 ResourcePath::ResourcePath( const char * path ) :
95  //path( ( memset( this, 0, sizeof( ResourcePath ) ), std::string( "/" ) + path ) )
96  path( std::string( "/" ) + path )
97 {
98 }
99 
100 ResourcePath::ResourcePath( std::string const & path ) :
101  //path( ( memset( this, 0, sizeof( ResourcePath ) ), std::string( "/" ) + path ) )
102  path( std::string( "/" ) + path )
103 {
104 }
105 
106 ResourcePath & ResourcePath::operator=( std::string const & path )
107 {
108  this->path = std::string( "/" ) + path;
109  return *this;
110 }
111 
112 ResourcePath & ResourcePath::operator=( const char * path )
113 {
114  this->path = std::string( "/" ) + path;
115  return *this;
116 }
117 
118 ResourcePath ResourcePath::operator+( std::string const & append ) const
119 {
120  return ResourcePath( this->path + append );
121 }
122 
123 ResourcePath & ResourcePath::operator+=( std::string const & append )
124 {
125  this->path += append;
126  return *this;
127 }
128 
129 ResourcePath ResourcePath::operator/( std::string const & join ) const
130 {
131  ResourcePath res( this->path + "/" + join );
132  return res;
133 }
134 
135 ResourcePath & ResourcePath::operator/=( std::string const & join )
136 {
137  this->path += "/";
138  this->path += join;
139  return *this;
140 }
141 
142 std::string const & ResourcePath::string() const
143 {
144  ResourcePath::Clean( this->path );
145  return this->path;
146 }
147 
149 {
150  return (*this) == ResourcePath();
151 }
152 
153 std::string ResourcePath::to_real_path( const char * vroot ) const
154 {
155  std::string result = vroot;
156 
157  if( result.size() == 0 )
158  result = ".";
159 
160  result = result + "/" + this->path;
161 
162  ResourcePath::Clean( result );
163 
164 
165 #if IV_CONFIG_FS_ENABLED
166  fs::path absolute = fs::absolute( fs::path( result ) );
167  return absolute.string();
168 #else
169  return result;
170 #endif
171 }
172 
173 bool ResourcePath::operator==( ResourcePath const & other ) const
174 {
175  ResourcePath::Clean( this->path );
176  ResourcePath::Clean( other.path );
177  return this->path == other.path;
178 }
179 
180 bool ResourcePath::operator!=( ResourcePath const & other ) const
181 {
182  ResourcePath::Clean( this->path );
183  ResourcePath::Clean( other.path );
184  return this->path != other.path;
185 }
186 
187 bool ResourcePath::operator<( ResourcePath const & other ) const
188 {
189  ResourcePath::Clean( this->path );
190  ResourcePath::Clean( other.path );
191  return this->path < other.path;
192 }
193 
194 ResourcePath ResourcePath::get_neighbour_path( const char * relative ) const
195 {
196  return (*this) / ".." / relative;
197 }
198 
200 {
201  if( this->path.size() == 0 )
202  return *this;
203 
204  if( this->path[ this->path.size() - 1 ] == '/' )
205  return *this;
206 
207  return (*this) / "..";
208 }
209 
210 }