blob: 968ef11bef850771a50cced63734d2ae2db59ca9 [file] [log] [blame]
// Components for manipulating non-owning sequences of characters -*- C++ -*-
#ifndef COMMON_GDB_STRING_VIEW_H
#define COMMON_GDB_STRING_VIEW_H
// Note: This file has been stolen from the gcc repo
// (libstdc++-v3/include/experimental/string_view) and has local modifications.
// Copyright (C) 2013-2023 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library 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, or (at your option)
// any later version.
// This library 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.
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
//
// N3762 basic_string_view library
//
#if __cplusplus >= 201703L
#include <string_view>
namespace gdb
{
using string_view = std::string_view;
} /* namespace gdb */
#else /* __cplusplus < 201703L */
#include <string>
#include <limits>
#include "gdb_assert.h"
namespace gdb
{
/**
* @class basic_string_view <experimental/string_view>
* @brief A non-owning reference to a string.
*
* @ingroup strings
* @ingroup sequences
* @ingroup experimental
*
* @tparam _CharT Type of character
* @tparam _Traits Traits for character type, defaults to
* char_traits<_CharT>.
*
* A basic_string_view looks like this:
*
* @code
* _CharT* _M_str
* size_t _M_len
* @endcode
*/
template<typename _CharT, typename _Traits = std::char_traits<_CharT>>
class basic_string_view
{
public:
// types
using traits_type = _Traits;
using value_type = _CharT;
using pointer = const _CharT *;
using const_pointer = const _CharT *;
using reference = const _CharT &;
using const_reference = const _CharT &;
using const_iterator = const _CharT *;
using iterator = const_iterator;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
using reverse_iterator = const_reverse_iterator;
using size_type = size_t;
using difference_type = ptrdiff_t;
static constexpr size_type npos = size_type (-1);
// [string.view.cons], construct/copy
constexpr basic_string_view () noexcept : _M_len { 0 }, _M_str { nullptr } {}
constexpr basic_string_view (const basic_string_view &) noexcept = default;
template<typename _Allocator>
basic_string_view (
const std::basic_string<_CharT, _Traits, _Allocator> &__str) noexcept
: _M_len { __str.length () },
_M_str { __str.data () }
{
}
/*constexpr*/ basic_string_view (const _CharT *__str)
: _M_len { __str == nullptr ? 0 : traits_type::length (__str) },
_M_str { __str }
{
}
constexpr basic_string_view (const _CharT *__str, size_type __len)
: _M_len { __len },
_M_str { __str }
{
}
basic_string_view &operator= (const basic_string_view &) noexcept = default;
// [string.view.iterators], iterators
constexpr const_iterator begin () const noexcept { return this->_M_str; }
constexpr const_iterator end () const noexcept
{
return this->_M_str + this->_M_len;
}
constexpr const_iterator cbegin () const noexcept { return this->_M_str; }
constexpr const_iterator cend () const noexcept
{
return this->_M_str + this->_M_len;
}
const_reverse_iterator rbegin () const noexcept
{
return const_reverse_iterator (this->end ());
}
const_reverse_iterator rend () const noexcept
{
return const_reverse_iterator (this->begin ());
}
const_reverse_iterator crbegin () const noexcept
{
return const_reverse_iterator (this->end ());
}
const_reverse_iterator crend () const noexcept
{
return const_reverse_iterator (this->begin ());
}
// [string.view.capacity], capacity
constexpr size_type size () const noexcept { return this->_M_len; }
constexpr size_type length () const noexcept { return _M_len; }
constexpr size_type max_size () const noexcept
{
return (npos - sizeof (size_type) - sizeof (void *)) / sizeof (value_type)
/ 4;
}
constexpr bool empty () const noexcept { return this->_M_len == 0; }
// [string.view.access], element access
constexpr const _CharT &operator[] (size_type __pos) const
{
// TODO: Assert to restore in a way compatible with the constexpr.
// __glibcxx_assert(__pos < this->_M_len);
return *(this->_M_str + __pos);
}
constexpr const _CharT &at (size_type __pos) const
{
return __pos < this->_M_len ? *(this->_M_str + __pos)
: (error (_ ("basic_string_view::at: __pos "
"(which is %zu) >= this->size() "
"(which is %zu)"),
__pos, this->size ()),
*this->_M_str);
}
constexpr const _CharT &front () const
{
// TODO: Assert to restore in a way compatible with the constexpr.
// __glibcxx_assert(this->_M_len > 0);
return *this->_M_str;
}
constexpr const _CharT &back () const
{
// TODO: Assert to restore in a way compatible with the constexpr.
// __glibcxx_assert(this->_M_len > 0);
return *(this->_M_str + this->_M_len - 1);
}
constexpr const _CharT *data () const noexcept { return this->_M_str; }
// [string.view.modifiers], modifiers:
/*constexpr*/ void remove_prefix (size_type __n)
{
gdb_assert (this->_M_len >= __n);
this->_M_str += __n;
this->_M_len -= __n;
}
/*constexpr*/ void remove_suffix (size_type __n) { this->_M_len -= __n; }
/*constexpr*/ void swap (basic_string_view &__sv) noexcept
{
auto __tmp = *this;
*this = __sv;
__sv = __tmp;
}
// [string.view.ops], string operations:
template<typename _Allocator>
explicit operator std::basic_string<_CharT, _Traits, _Allocator> () const
{
return { this->_M_str, this->_M_len };
}
size_type copy (_CharT *__str, size_type __n, size_type __pos = 0) const
{
gdb_assert (__str != nullptr || __n == 0);
if (__pos > this->_M_len)
error (_ ("basic_string_view::copy: __pos "
"(which is %zu) > this->size() "
"(which is %zu)"),
__pos, this->size ());
size_type __rlen { std::min (__n, size_type { this->_M_len - __pos }) };
for (auto __begin = this->_M_str + __pos, __end = __begin + __rlen;
__begin != __end;)
*__str++ = *__begin++;
return __rlen;
}
// [string.view.ops], string operations:
/*constexpr*/ basic_string_view substr (size_type __pos,
size_type __n = npos) const
{
return __pos <= this->_M_len
? basic_string_view { this->_M_str + __pos,
std::min (__n, size_type { this->_M_len
- __pos }) }
: (error (_ ("basic_string_view::substr: __pos "
"(which is %zu) > this->size() "
"(which is %zu)"),
__pos, this->size ()),
basic_string_view {});
}
/*constexpr*/ int compare (basic_string_view __str) const noexcept
{
int __ret = traits_type::compare (this->_M_str, __str._M_str,
std::min (this->_M_len, __str._M_len));
if (__ret == 0)
__ret = _S_compare (this->_M_len, __str._M_len);
return __ret;
}
/*constexpr*/ int compare (size_type __pos1, size_type __n1,
basic_string_view __str) const
{
return this->substr (__pos1, __n1).compare (__str);
}
/*constexpr*/ int compare (size_type __pos1, size_type __n1,
basic_string_view __str, size_type __pos2,
size_type __n2) const
{
return this->substr (__pos1, __n1).compare (__str.substr (__pos2, __n2));
}
/*constexpr*/ int compare (const _CharT *__str) const noexcept
{
return this->compare (basic_string_view { __str });
}
/*constexpr*/ int compare (size_type __pos1, size_type __n1,
const _CharT *__str) const
{
return this->substr (__pos1, __n1).compare (basic_string_view { __str });
}
/*constexpr*/ int compare (size_type __pos1, size_type __n1,
const _CharT *__str, size_type __n2) const
{
return this->substr (__pos1, __n1)
.compare (basic_string_view (__str, __n2));
}
/*constexpr*/ size_type find (basic_string_view __str,
size_type __pos = 0) const noexcept
{
return this->find (__str._M_str, __pos, __str._M_len);
}
/*constexpr*/ size_type find (_CharT __c,
size_type __pos = 0) const noexcept;
/*constexpr*/ size_type find (const _CharT *__str, size_type __pos,
size_type __n) const noexcept;
/*constexpr*/ size_type find (const _CharT *__str,
size_type __pos = 0) const noexcept
{
return this->find (__str, __pos, traits_type::length (__str));
}
/*constexpr*/ size_type rfind (basic_string_view __str,
size_type __pos = npos) const noexcept
{
return this->rfind (__str._M_str, __pos, __str._M_len);
}
/*constexpr*/ size_type rfind (_CharT __c,
size_type __pos = npos) const noexcept;
/*constexpr*/ size_type rfind (const _CharT *__str, size_type __pos,
size_type __n) const noexcept;
/*constexpr*/ size_type rfind (const _CharT *__str,
size_type __pos = npos) const noexcept
{
return this->rfind (__str, __pos, traits_type::length (__str));
}
/*constexpr*/ size_type find_first_of (basic_string_view __str,
size_type __pos = 0) const noexcept
{
return this->find_first_of (__str._M_str, __pos, __str._M_len);
}
/*constexpr*/ size_type find_first_of (_CharT __c,
size_type __pos = 0) const noexcept
{
return this->find (__c, __pos);
}
/*constexpr*/ size_type find_first_of (const _CharT *__str, size_type __pos,
size_type __n) const;
/*constexpr*/ size_type find_first_of (const _CharT *__str,
size_type __pos = 0) const noexcept
{
return this->find_first_of (__str, __pos, traits_type::length (__str));
}
/*constexpr*/ size_type find_last_of (basic_string_view __str,
size_type __pos = npos) const noexcept
{
return this->find_last_of (__str._M_str, __pos, __str._M_len);
}
size_type find_last_of (_CharT __c, size_type __pos = npos) const noexcept
{
return this->rfind (__c, __pos);
}
/*constexpr*/ size_type find_last_of (const _CharT *__str, size_type __pos,
size_type __n) const;
/*constexpr*/ size_type find_last_of (const _CharT *__str,
size_type __pos = npos) const noexcept
{
return this->find_last_of (__str, __pos, traits_type::length (__str));
}
/*constexpr*/ size_type find_first_not_of (basic_string_view __str,
size_type __pos
= 0) const noexcept
{
return this->find_first_not_of (__str._M_str, __pos, __str._M_len);
}
/*constexpr*/ size_type find_first_not_of (_CharT __c, size_type __pos
= 0) const noexcept;
/*constexpr*/ size_type find_first_not_of (const _CharT *__str,
size_type __pos,
size_type __n) const;
/*constexpr*/ size_type
find_first_not_of (const _CharT *__str, size_type __pos = 0) const noexcept
{
return this->find_first_not_of (__str, __pos, traits_type::length (__str));
}
/*constexpr*/ size_type find_last_not_of (basic_string_view __str,
size_type __pos
= npos) const noexcept
{
return this->find_last_not_of (__str._M_str, __pos, __str._M_len);
}
/*constexpr*/ size_type find_last_not_of (_CharT __c, size_type __pos
= npos) const noexcept;
/*constexpr*/ size_type
find_last_not_of (const _CharT *__str, size_type __pos, size_type __n) const;
/*constexpr*/ size_type
find_last_not_of (const _CharT *__str, size_type __pos = npos) const noexcept
{
return this->find_last_not_of (__str, __pos, traits_type::length (__str));
}
private:
static constexpr int _S_compare (size_type __n1, size_type __n2) noexcept
{
return difference_type (__n1 - __n2) > std::numeric_limits<int>::max ()
? std::numeric_limits<int>::max ()
: difference_type (__n1 - __n2) < std::numeric_limits<int>::min ()
? std::numeric_limits<int>::min ()
: static_cast<int> (difference_type (__n1 - __n2));
}
size_t _M_len;
const _CharT *_M_str;
};
// [string.view.comparison], non-member basic_string_view comparison functions
namespace __detail
{
// Identity transform to create a non-deduced context, so that only one
// argument participates in template argument deduction and the other
// argument gets implicitly converted to the deduced type. See n3766.html.
template<typename _Tp>
using __idt = typename std::common_type<_Tp>::type;
} // namespace __detail
template<typename _CharT, typename _Traits>
/*constexpr*/ bool
operator== (basic_string_view<_CharT, _Traits> __x,
basic_string_view<_CharT, _Traits> __y) noexcept
{
return __x.size () == __y.size () && __x.compare (__y) == 0;
}
template<typename _CharT, typename _Traits>
/*constexpr*/ bool
operator== (basic_string_view<_CharT, _Traits> __x,
__detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
{
return __x.size () == __y.size () && __x.compare (__y) == 0;
}
template<typename _CharT, typename _Traits>
/*constexpr*/ bool
operator== (__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
basic_string_view<_CharT, _Traits> __y) noexcept
{
return __x.size () == __y.size () && __x.compare (__y) == 0;
}
template<typename _CharT, typename _Traits>
/*constexpr*/ bool
operator!= (basic_string_view<_CharT, _Traits> __x,
basic_string_view<_CharT, _Traits> __y) noexcept
{
return !(__x == __y);
}
template<typename _CharT, typename _Traits>
/*constexpr*/ bool
operator!= (basic_string_view<_CharT, _Traits> __x,
__detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
{
return !(__x == __y);
}
template<typename _CharT, typename _Traits>
/*constexpr*/ bool
operator!= (__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
basic_string_view<_CharT, _Traits> __y) noexcept
{
return !(__x == __y);
}
template<typename _CharT, typename _Traits>
/*constexpr*/ bool
operator<(basic_string_view<_CharT, _Traits> __x,
basic_string_view<_CharT, _Traits> __y) noexcept
{
return __x.compare (__y) < 0;
}
template<typename _CharT, typename _Traits>
/*constexpr*/ bool
operator<(basic_string_view<_CharT, _Traits> __x,
__detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
{
return __x.compare (__y) < 0;
}
template<typename _CharT, typename _Traits>
/*constexpr*/ bool
operator<(__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
basic_string_view<_CharT, _Traits> __y) noexcept
{
return __x.compare (__y) < 0;
}
template<typename _CharT, typename _Traits>
/*constexpr*/ bool
operator> (basic_string_view<_CharT, _Traits> __x,
basic_string_view<_CharT, _Traits> __y) noexcept
{
return __x.compare (__y) > 0;
}
template<typename _CharT, typename _Traits>
/*constexpr*/ bool
operator> (basic_string_view<_CharT, _Traits> __x,
__detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
{
return __x.compare (__y) > 0;
}
template<typename _CharT, typename _Traits>
/*constexpr*/ bool
operator> (__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
basic_string_view<_CharT, _Traits> __y) noexcept
{
return __x.compare (__y) > 0;
}
template<typename _CharT, typename _Traits>
/*constexpr*/ bool
operator<= (basic_string_view<_CharT, _Traits> __x,
basic_string_view<_CharT, _Traits> __y) noexcept
{
return __x.compare (__y) <= 0;
}
template<typename _CharT, typename _Traits>
/*constexpr*/ bool
operator<= (basic_string_view<_CharT, _Traits> __x,
__detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
{
return __x.compare (__y) <= 0;
}
template<typename _CharT, typename _Traits>
/*constexpr*/ bool
operator<= (__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
basic_string_view<_CharT, _Traits> __y) noexcept
{
return __x.compare (__y) <= 0;
}
template<typename _CharT, typename _Traits>
/*constexpr*/ bool
operator>= (basic_string_view<_CharT, _Traits> __x,
basic_string_view<_CharT, _Traits> __y) noexcept
{
return __x.compare (__y) >= 0;
}
template<typename _CharT, typename _Traits>
/*constexpr*/ bool
operator>= (basic_string_view<_CharT, _Traits> __x,
__detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
{
return __x.compare (__y) >= 0;
}
template<typename _CharT, typename _Traits>
/*constexpr*/ bool
operator>= (__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
basic_string_view<_CharT, _Traits> __y) noexcept
{
return __x.compare (__y) >= 0;
}
// basic_string_view typedef names
using string_view = basic_string_view<char>;
} /* namespace gdb */
#include "gdb_string_view.tcc"
#endif // __cplusplus < 201703L
namespace gdb
{
static inline std::string
to_string (const gdb::string_view &view)
{
return { view.data (), view.size () };
}
} // namespace gdb
#endif /* COMMON_GDB_STRING_VIEW_H */