path.hpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  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. 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. while (len-- && *str) {
  50. if (*str == '/') {
  51. if (m_vec.empty() || str != start)
  52. m_vec.emplace_back(start, str - start);
  53. start = str + 1;
  54. }
  55. ++str;
  56. }
  57. if (str != start || m_vec.size() != 1 || !m_vec.front().empty())
  58. m_vec.emplace_back(start, str - start);
  59. return *this;
  60. }
  61. constexpr path& append(const path& val)
  62. {
  63. m_vec.insert(m_vec.end(), val.m_vec.begin(), val.m_vec.end());
  64. return *this;
  65. }
  66. constexpr void clear() { m_vec.clear(); }
  67. constexpr void remove_last()
  68. {
  69. if (m_vec.size() > 1)
  70. m_vec.pop_back();
  71. }
  72. constexpr path& operator+=(const char* str)
  73. { return append(str); }
  74. constexpr path& operator+=(const path& val)
  75. { return append(val); }
  76. constexpr bool operator==(const char* str) const
  77. {
  78. return full_path() == str;
  79. }
  80. constexpr iterator begin() const { return m_vec.cbegin(); }
  81. constexpr iterator end() const { return m_vec.cend(); }
  82. };
  83. constexpr path make_path(const char* pathstr, const char* pwd)
  84. {
  85. if (*pathstr && pathstr[0] == '/')
  86. return pathstr;
  87. else
  88. return path { pwd }.append(pathstr);
  89. }
  90. constexpr path make_path(const char* pathstr, const path& pwd)
  91. {
  92. if (*pathstr && pathstr[0] == '/')
  93. return pathstr;
  94. else
  95. return path{pwd}.append(pathstr);
  96. }
  97. } // namespace types