| 14 | |
| 15 | namespace xgboost { |
| 16 | struct StringView { |
| 17 | private: |
| 18 | using CharT = char; |
| 19 | using Traits = std::char_traits<CharT>; |
| 20 | CharT const* str_{nullptr}; |
| 21 | std::size_t size_{0}; |
| 22 | |
| 23 | public: |
| 24 | using value_type = CharT; // NOLINT |
| 25 | using iterator = const CharT*; // NOLINT |
| 26 | using const_iterator = iterator; // NOLINT |
| 27 | using reverse_iterator = std::reverse_iterator<const_iterator>; // NOLINT |
| 28 | using const_reverse_iterator = reverse_iterator; // NOLINT |
| 29 | |
| 30 | public: |
| 31 | constexpr StringView() = default; |
| 32 | constexpr StringView(value_type const* str, std::size_t size) : str_{str}, size_{size} {} |
| 33 | StringView(std::string const& str) : str_{str.c_str()}, size_{str.size()} {} // NOLINT |
| 34 | constexpr StringView(value_type const* str) // NOLINT |
| 35 | : str_{str}, size_{str == nullptr ? 0ul : Traits::length(str)} {} |
| 36 | |
| 37 | [[nodiscard]] value_type const& operator[](std::size_t p) const { return str_[p]; } |
| 38 | [[nodiscard]] explicit operator std::string() const { return {this->c_str(), this->size()}; } |
| 39 | [[nodiscard]] value_type const& at(std::size_t p) const { // NOLINT |
| 40 | CHECK_LT(p, size_); |
| 41 | return str_[p]; |
| 42 | } |
| 43 | [[nodiscard]] constexpr std::size_t size() const { return size_; } // NOLINT |
| 44 | [[nodiscard]] constexpr bool empty() const { return size() == 0; } // NOLINT |
| 45 | [[nodiscard]] StringView substr(std::size_t beg, std::size_t n) const { // NOLINT |
| 46 | CHECK_LE(beg, size_); |
| 47 | std::size_t len = std::min(n, size_ - beg); |
| 48 | return {str_ + beg, len}; |
| 49 | } |
| 50 | [[nodiscard]] value_type const* c_str() const { return str_; } // NOLINT |
| 51 | |
| 52 | [[nodiscard]] constexpr const_iterator cbegin() const { return str_; } // NOLINT |
| 53 | [[nodiscard]] constexpr const_iterator cend() const { return str_ + size(); } // NOLINT |
| 54 | [[nodiscard]] constexpr iterator begin() const { return str_; } // NOLINT |
| 55 | [[nodiscard]] constexpr iterator end() const { return str_ + size(); } // NOLINT |
| 56 | |
| 57 | [[nodiscard]] const_reverse_iterator rbegin() const noexcept { // NOLINT |
| 58 | return const_reverse_iterator(this->end()); |
| 59 | } |
| 60 | [[nodiscard]] const_reverse_iterator crbegin() const noexcept { // NOLINT |
| 61 | return const_reverse_iterator(this->end()); |
| 62 | } |
| 63 | [[nodiscard]] const_reverse_iterator rend() const noexcept { // NOLINT |
| 64 | return const_reverse_iterator(this->begin()); |
| 65 | } |
| 66 | [[nodiscard]] const_reverse_iterator crend() const noexcept { // NOLINT |
| 67 | return const_reverse_iterator(this->begin()); |
| 68 | } |
| 69 | }; |
| 70 | |
| 71 | inline std::ostream& operator<<(std::ostream& os, StringView const v) { |
| 72 | for (auto c : v) { |