// strings/base.tcc - Inline functions for strings/base.hpp // // Copyright © 2013 Ben Longbons // // This file is part of The Mana World (Athena server) // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . #include #include #include "pair.hpp" namespace tmwa { namespace strings { namespace detail { constexpr bool is_print(char c) { return ' ' <= c && c <= '~'; } constexpr bool is_graph(char c) { return is_print(c) && c != ' '; } constexpr bool is_lower(char c) { return 'a' <= c && c <= 'z'; } constexpr bool is_upper(char c) { return 'A' <= c && c <= 'Z'; } constexpr bool is_alpha(char c) { return is_lower(c) || is_upper(c); } constexpr bool is_digit2(char c) { return '0' <= c && c <= '1'; } constexpr bool is_digit8(char c) { return '0' <= c && c <= '7'; } constexpr bool is_digit10(char c) { return '0' <= c && c <= '9'; } constexpr bool is_digit16(char c) { return ('0' <= c && c <= '9') || ('A' <= c && c <= 'F') || ('a' <= c && c <= 'f'); } constexpr bool is_alnum(char c) { return is_alpha(c) || is_digit10(c); } constexpr char to_lower(char c) { return is_upper(c) ? c | ' ' : c; } constexpr char to_upper(char c) { return is_lower(c) ? c & ~' ' : c; } } // namespace detail template const T& _crtp_string::_ref() const { return static_cast(*this); } template typename _crtp_string::iterator _crtp_string::begin() const { return _ref().begin(); } template typename _crtp_string::iterator _crtp_string::end() const { return _ref().end(); } template const RString *_crtp_string::base() const { return _ref().base(); } template size_t _crtp_string::size() const { return end() - begin(); } template typename _crtp_string::reverse_iterator _crtp_string::rbegin() const { return reverse_iterator(end()); } template typename _crtp_string::reverse_iterator _crtp_string::rend() const { return reverse_iterator(begin()); } template _crtp_string::operator bool() const { return size(); } template bool _crtp_string::operator !() const { return !size(); } template _crtp_string::operator P() const { return {&*begin(), &*end()}; } template char _crtp_string::operator[](size_t i) const { return begin()[i]; } template char _crtp_string::front() const { return *begin(); } template char _crtp_string::back() const { return end()[-1]; } template const char *_crtp_string::data() { return &*begin(); } template typename P::TailSlice _crtp_string::xslice_t(size_t o) const { return typename P::TailSlice(&begin()[o], &*end(), base()); } template typename P::FullSlice _crtp_string::xslice_h(size_t o) const { return typename P::FullSlice(&*begin(), &begin()[o], base()); } template typename P::TailSlice _crtp_string::xrslice_t(size_t no) const { return typename P::TailSlice(&end()[-no], &*end(), base()); } template typename P::FullSlice _crtp_string::xrslice_h(size_t no) const { return typename P::FullSlice(&*begin(), &end()[-no], base()); } template typename P::TailSlice _crtp_string::xislice_t(iterator it) const { return typename P::TailSlice(&*it, &*end(), base()); } template typename P::FullSlice _crtp_string::xislice_h(iterator it) const { return typename P::FullSlice(&*begin(), &*it, base()); } template typename P::FullSlice _crtp_string::xlslice(size_t o, size_t l) const { return typename P::FullSlice(&begin()[o], &begin()[o + l], base()); } template typename P::FullSlice _crtp_string::xpslice(size_t b, size_t e) const { return typename P::FullSlice(&begin()[b], &begin()[e], base()); } template typename P::FullSlice _crtp_string::xislice(iterator b, iterator e) const { return typename P::FullSlice(&*b, &*e, base()); } template typename P::TailSlice _crtp_string::lstrip() const { typename P::TailSlice z = _ref(); while (z.startswith(' ')) z = z.xslice_t(1); return z; } template typename P::FullSlice _crtp_string::rstrip() const { typename P::FullSlice x = _ref(); while (x.endswith(' ')) x = x.xrslice_h(1); return x; } template typename P::FullSlice _crtp_string::strip() const { return lstrip().rstrip(); } template bool _crtp_string::startswith(XPair x) const { return size() >= x.size() && pair_compare(xslice_h(x.size()), x) == 0; } template bool _crtp_string::endswith(XPair x) const { return size() > x.size() && pair_compare(xrslice_t(x.size()), x) == 0; } template bool _crtp_string::startswith(char c) const { return size() && front() == c; } template bool _crtp_string::endswith(char c) const { return size() && back() == c; } template bool _crtp_string::contains(char c) const { return std::find(begin(), end(), c) != end(); } template bool _crtp_string::contains_seq(XPair s) const { return std::search(begin(), end(), s.begin(), s.end()) != end(); } template bool _crtp_string::contains_any(XPair s) const { return std::find_if(s.begin(), s.end(), [this](char c) { return this->contains(c); }) != s.end(); } template bool _crtp_string::has_print() const { return std::find_if(begin(), end(), detail::is_print) != end(); } template bool _crtp_string::is_print() const { return std::find_if_not(begin(), end(), detail::is_print) == end(); } template O _crtp_string::to_print() const { if (is_print()) return _ref(); char buf[size()]; char *const b = buf; char *const e = std::transform(begin(), end(), b, [](char c) { return detail::is_print(c) ? c : '_'; }); return XPair(b, e); } template bool _crtp_string::has_graph() const { return std::find_if(begin(), end(), detail::is_graph) != end(); } template bool _crtp_string::is_graph() const { return std::find_if_not(begin(), end(), detail::is_graph) == end(); } template bool _crtp_string::has_lower() const { return std::find_if(begin(), end(), detail::is_lower) != end(); } template bool _crtp_string::is_lower() const { return std::find_if_not(begin(), end(), detail::is_lower) == end(); } template O _crtp_string::to_lower() const { if (!has_upper()) return _ref(); char buf[size()]; char *const b = buf; char *const e = std::transform(begin(), end(), b, detail::to_lower); return XPair(b, e); } template bool _crtp_string::has_upper() const { return std::find_if(begin(), end(), detail::is_upper) != end(); } template bool _crtp_string::is_upper() const { return std::find_if_not(begin(), end(), detail::is_upper) == end(); } template O _crtp_string::to_upper() const { if (!has_lower()) return _ref(); char buf[size()]; char *const b = buf; char *const e = std::transform(begin(), end(), b, detail::to_upper); return XPair(b, e); } template bool _crtp_string::has_alpha() const { return std::find_if(begin(), end(), detail::is_alpha) != end(); } template bool _crtp_string::is_alpha() const { return std::find_if_not(begin(), end(), detail::is_alpha) == end(); } template bool _crtp_string::has_digit2() const { return std::find_if(begin(), end(), detail::is_digit2) != end(); } template bool _crtp_string::is_digit2() const { return std::find_if_not(begin(), end(), detail::is_digit2) == end(); } template bool _crtp_string::has_digit8() const { return std::find_if(begin(), end(), detail::is_digit8) != end(); } template bool _crtp_string::is_digit8() const { return std::find_if_not(begin(), end(), detail::is_digit8) == end(); } template bool _crtp_string::has_digit10() const { return std::find_if(begin(), end(), detail::is_digit10) != end(); } template bool _crtp_string::is_digit10() const { return std::find_if_not(begin(), end(), detail::is_digit10) == end(); } template bool _crtp_string::has_digit16() const { return std::find_if(begin(), end(), detail::is_digit16) != end(); } template bool _crtp_string::is_digit16() const { return std::find_if_not(begin(), end(), detail::is_digit16) == end(); } template bool _crtp_string::has_alnum() const { return std::find_if(begin(), end(), detail::is_alnum) != end(); } template bool _crtp_string::is_alnum() const { return std::find_if_not(begin(), end(), detail::is_alnum) == end(); } // not really intended for public use inline int pair_compare(XPair l, XPair r) { bool less = std::lexicographical_compare( l.begin(), l.end(), r.begin(), r.end()); bool greater = std::lexicographical_compare( r.begin(), r.end(), l.begin(), l.end()); return greater - less; } template auto operator == (const L& l, const R& r) -> decltype((pair_compare(l, r), true)) { return pair_compare(l, r) == 0; } template auto operator != (const L& l, const R& r) -> decltype((pair_compare(l, r), true)) { return pair_compare(l, r) != 0; } template auto operator < (const L& l, const R& r) -> decltype((pair_compare(l, r), true)) { return pair_compare(l, r) < 0; } template auto operator <= (const L& l, const R& r) -> decltype((pair_compare(l, r), true)) { return pair_compare(l, r) <= 0; } template auto operator > (const L& l, const R& r) -> decltype((pair_compare(l, r), true)) { return pair_compare(l, r) > 0; } template auto operator >= (const L& l, const R& r) -> decltype((pair_compare(l, r), true)) { return pair_compare(l, r) >= 0; } } // namespace strings } // namespace tmwa