path.hpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. #pragma once
  2. #include <types/string.hpp>
  3. #include <vector>
  4. #include <cstddef>
  5. namespace types {
  6. class path {
  7. public:
  8. using item_string = types::string<>;
  9. using item_vector = std::vector<item_string>;
  10. using string_type = types::string<>;
  11. using size_type = std::size_t;
  12. using iterator = item_vector::const_iterator;
  13. private:
  14. item_vector m_vec;
  15. public:
  16. constexpr path() = default;
  17. constexpr path(const path& val) = default;
  18. constexpr path(path&& val) = default;
  19. explicit constexpr path(const char* str, size_type len = -1U)
  20. { append(str, len); }
  21. constexpr path& operator=(const path& val) = default;
  22. constexpr path& operator=(path&& val) = default;
  23. constexpr path& operator=(const char* str)
  24. {
  25. m_vec.clear();
  26. append(str);
  27. return *this;
  28. }
  29. constexpr string_type full_path() const
  30. {
  31. string_type str;
  32. for (auto iter = m_vec.begin(); iter != m_vec.end(); ++iter) {
  33. if (iter != m_vec.begin()
  34. || (m_vec.front().empty() && m_vec.size() == 1))
  35. str += '/';
  36. str += *iter;
  37. }
  38. return str;
  39. }
  40. constexpr item_string last_name() const
  41. { return m_vec.empty() ? item_string {} : m_vec.back(); }
  42. constexpr bool empty() const
  43. { return m_vec.empty(); }
  44. constexpr bool is_absolute() const { return !empty() && !m_vec[0][0]; }
  45. constexpr bool is_relative() const { return !empty() && !is_absolute(); }
  46. constexpr path& append(const char* str, size_type len = -1U)
  47. {
  48. const char* start = str;
  49. if (len && *start == '/')
  50. clear();
  51. while (len-- && *str) {
  52. if (*str == '/') {
  53. if (m_vec.empty() || str != start)
  54. m_vec.emplace_back(start, str - start);
  55. start = str + 1;
  56. }
  57. ++str;
  58. }
  59. if (str != start || m_vec.size() != 1 || !m_vec.front().empty())
  60. m_vec.emplace_back(start, str - start);
  61. return *this;
  62. }
  63. constexpr path& append(const path& val)
  64. {
  65. if (&val == this)
  66. return *this;
  67. if (val.is_absolute()) {
  68. *this = val;
  69. return *this;
  70. }
  71. m_vec.insert(m_vec.end(), val.m_vec.begin(), val.m_vec.end());
  72. return *this;
  73. }
  74. constexpr void clear() { m_vec.clear(); }
  75. constexpr void remove_last()
  76. {
  77. if (m_vec.size() > 1)
  78. m_vec.pop_back();
  79. }
  80. constexpr path& operator+=(const char* str)
  81. { return append(str); }
  82. constexpr path& operator+=(const path& val)
  83. { return append(val); }
  84. constexpr path operator+(const char* str) const
  85. { return path{*this}.append(str); }
  86. constexpr path operator+(const path& val)
  87. { return path{*this}.append(val); }
  88. constexpr bool operator==(const char* str) const
  89. {
  90. return full_path() == str;
  91. }
  92. constexpr iterator begin() const { return m_vec.cbegin(); }
  93. constexpr iterator end() const { return m_vec.cend(); }
  94. };
  95. } // namespace types