Skip to content

Instantly share code, notes, and snippets.

@royvandam
Created October 30, 2020 16:50
Show Gist options
  • Save royvandam/7d781a0a93a0648e9d9bd36a69f55fba to your computer and use it in GitHub Desktop.
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
#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