diff --git a/libluna/CMakeLists.txt b/libluna/CMakeLists.txt index b3eba9a3..2ce5bb85 100644 --- a/libluna/CMakeLists.txt +++ b/libluna/CMakeLists.txt @@ -17,6 +17,7 @@ set(FREESTANDING_SOURCES src/DebugLog.cpp src/Heap.cpp src/Spinlock.cpp + src/PathParser.cpp src/UBSAN.cpp ) diff --git a/libluna/include/luna/PathParser.h b/libluna/include/luna/PathParser.h new file mode 100644 index 00000000..a1da5ee5 --- /dev/null +++ b/libluna/include/luna/PathParser.h @@ -0,0 +1,28 @@ +#pragma once +#include +#include + +class PathParser +{ + public: + static Result create(const char* path); + + PathParser(PathParser&& other); + PathParser(const PathParser&) = delete; + + ~PathParser(); + + bool is_absolute() const + { + return *m_original == '/'; + } + + Option next(); + + private: + PathParser(const char* original, char* copy); + + const char* m_original { nullptr }; + char* m_copy { nullptr }; + bool m_already_called_next { false }; +}; diff --git a/libluna/src/PathParser.cpp b/libluna/src/PathParser.cpp new file mode 100644 index 00000000..9d47c5f0 --- /dev/null +++ b/libluna/src/PathParser.cpp @@ -0,0 +1,33 @@ +#include + +Result PathParser::create(const char* path) +{ + char* copy = strdup(path); + if (!copy) return err(ENOMEM); + + return PathParser { path, copy }; +} + +PathParser::PathParser(const char* original, char* copy) : m_original(original), m_copy(copy) +{ +} + +PathParser::PathParser(PathParser&& other) : m_original(other.m_original), m_copy(other.m_copy) +{ + other.m_copy = nullptr; +} + +PathParser::~PathParser() +{ + if (m_copy) free_impl(m_copy); +} + +Option PathParser::next() +{ + char* result = strtok(m_already_called_next ? nullptr : m_copy, "/"); + m_already_called_next = true; + + if (!result) return {}; + + return result; +}