Created
October 30, 2020 16:50
-
-
Save royvandam/7d781a0a93a0648e9d9bd36a69f55fba to your computer and use it in GitHub Desktop.
O(n) time / O(1) memory C++ std::string_view based path iterator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <string_view> | |
#include <iostream> | |
using namespace std::literals; | |
struct Path { | |
class Iterator { | |
protected: | |
std::string_view _path; | |
char _separator; | |
std::size_t _pos; | |
public: | |
using value_type = std::string_view; | |
using reference = value_type; | |
Iterator(std::string_view path, char separator, std::size_t pos = 0) | |
: _path(path) | |
, _separator(separator) | |
, _pos(pos) {} | |
Iterator(const Iterator& other) | |
: _path(other._path) | |
, _separator(other._separator) | |
, _pos(other._pos) {} | |
Iterator& operator++() { | |
_pos = _path.find_first_of(_separator, _pos); | |
if (_pos != _path.npos) { | |
_pos++; | |
} | |
return *this; | |
} | |
reference operator*() { | |
if (_pos == _path.npos) { | |
return {}; | |
} | |
auto next = _path.find_first_of(_separator, _pos); | |
if (next != _path.npos) { | |
return _path.substr(_pos, next - _pos); | |
} | |
return _path.substr(_pos); | |
} | |
bool operator==(const Iterator& other) const { | |
return (_pos == other._pos) && (_path == other._path); | |
} | |
bool operator!=(const Iterator& other) const { | |
return !(*this == other); | |
} | |
}; | |
protected: | |
std::string_view _path; | |
char _separator; | |
public: | |
Path(std::string_view path, char separator = '/') | |
: _path(path) | |
, _separator(separator) | |
{} | |
Path(Path& other) | |
: _path(other._path) | |
{} | |
bool isRelative() { | |
return _path[0] != _separator; | |
} | |
bool isAbsolute() { | |
return _path[0] == _separator; | |
} | |
void stripBegin() { | |
if (!_path.empty() && _path[0] == _separator && _path[1] == _separator) { | |
_path = _path.substr(_path.find_first_not_of(_separator) - 1); | |
} | |
} | |
void stripEnd() { | |
if (!_path.empty() && _path[_path.size() - 1] == _separator) { | |
_path = _path.substr(0, _path.find_last_not_of(_separator) + 1); | |
} | |
} | |
void strip() { | |
stripBegin(); | |
stripEnd(); | |
} | |
std::string_view get() const { | |
return _path; | |
} | |
operator std::string_view() const { | |
return _path; | |
} | |
[[nodiscard]] Iterator begin() const { | |
return {_path, _separator, 0}; | |
} | |
[[nodiscard]] Iterator end() const { | |
return {_path, _separator, std::string_view::npos}; | |
} | |
}; | |
int main(int argc, char** argv) { | |
Path path = "////home/roy///foobar///"sv; | |
path.strip(); | |
std::cout << path.get() << std::endl; | |
for (auto part : path) { | |
std::cout << part << std::endl; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment