Skip to content

Instantly share code, notes, and snippets.

@klemens-morgenstern
Created May 11, 2022 03:03
Show Gist options
  • Save klemens-morgenstern/fc02dab8b37fc77ac80efbca30f297cf to your computer and use it in GitHub Desktop.
Save klemens-morgenstern/fc02dab8b37fc77ac80efbca30f297cf to your computer and use it in GitHub Desktop.
//
// boost/utility/cstring_view.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2022 Klemens D. Morgenstern
// (klemens dot morgenstern at gmx dot net)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_UTILITY_CSTRING_VIEW_HPP
#define BOOST_UTILITY_CSTRING_VIEW_HPP
#include <boost/core/detail/string_view.hpp>
#include <type_traits>
#include <limits>
namespace boost
{
//based on http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1402r0.pdf
///cstring_view is simply a forwarding adapter around string_view.
/** Operations are delegated to a private member string_view, with some minor modifications
to the interface to maintain the null-terminated class invariant. */
template<typename CharT, typename Traits = std::char_traits<CharT>>
struct basic_cstring_view
{
using value_type = CharT;
using traits_type = Traits;
BOOST_CONSTEXPR basic_cstring_view() : view_(null_char_(value_type{})) {};
BOOST_CONSTEXPR basic_cstring_view(std::nullptr_t) = delete;
BOOST_CONSTEXPR basic_cstring_view( const value_type* s ) : view_(s) {}
template<typename Source,
typename =
typename std::enable_if<
std::is_same<const value_type,
typename std::remove_pointer<decltype(std::declval<Source>().c_str())>::type
>::value>::type>
BOOST_CONSTEXPR basic_cstring_view(Source && src) : view_(src.c_str()) {}
BOOST_CONSTEXPR typename std::basic_string_view<value_type, Traits>::const_pointer c_str() const BOOST_NOEXCEPT
{
return this->data();
}
using string_view_type = basic_string_view<value_type, Traits>;
operator string_view_type() const {return view_;}
using pointer = CharT *;
using const_pointer = const CharT *;
using reference = CharT &;
using const_reference = const CharT &;
using const_iterator = const_pointer;
using iterator = const_iterator;
using const_reverse_iterator = typename std::reverse_iterator<const_iterator>;
using reverse_iterator = typename std::reverse_iterator<iterator>;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
static BOOST_CONSTEXPR size_type npos = -1;
BOOST_CONSTEXPR const_iterator begin() const BOOST_NOEXCEPT {return view_;};
BOOST_CONSTEXPR const_iterator end() const BOOST_NOEXCEPT {return view_ + length();};
BOOST_CONSTEXPR const_iterator cbegin() const BOOST_NOEXCEPT {return view_;};
BOOST_CONSTEXPR const_iterator cend() const BOOST_NOEXCEPT {return view_ + length();};
BOOST_CONSTEXPR const_reverse_iterator rbegin() const BOOST_NOEXCEPT {return std::make_reverse_iterator(view_ + length());};
BOOST_CONSTEXPR const_reverse_iterator rend() const BOOST_NOEXCEPT {return std::make_reverse_iterator(view_);};
BOOST_CONSTEXPR const_reverse_iterator crbegin() const BOOST_NOEXCEPT {return std::make_reverse_iterator(view_ + length());};
BOOST_CONSTEXPR const_reverse_iterator crend() const BOOST_NOEXCEPT {return std::make_reverse_iterator(view_);};
BOOST_CONSTEXPR size_type size() const BOOST_NOEXCEPT {return length(); }
BOOST_CONSTEXPR size_type length() const BOOST_NOEXCEPT {return traits_type::length(view_); }
BOOST_CONSTEXPR size_type max_size() const BOOST_NOEXCEPT {return std::numeric_limits<int64_t>::max() / sizeof(CharT); }
BOOST_ATTRIBUTE_NODISCARD BOOST_CONSTEXPR bool empty() const BOOST_NOEXCEPT {return *view_ == *null_char_(CharT{}); }
BOOST_CONSTEXPR const_reference operator[](size_type pos) const {return view_[pos] ;}
BOOST_CONSTEXPR const_reference at(size_type pos) const
{
if (pos >= size())
throw std::out_of_range("cstring-view out of range");
return view_[pos];
}
BOOST_CONSTEXPR const_reference front() const {return *view_;}
BOOST_CONSTEXPR const_reference back() const {return view_[length() - 1];}
BOOST_CONSTEXPR const_pointer data() const BOOST_NOEXCEPT {return view_;}
BOOST_CONSTEXPR void remove_prefix(size_type n) {view_ = view_ + n;}
BOOST_CONSTEXPR void swap(basic_cstring_view& s) BOOST_NOEXCEPT {std::swap(view_, s.view_);}
BOOST_CONSTEXPR size_type copy(value_type* s, size_type n, size_type pos = 0) const
{
return traits_type::copy(s, view_ + pos, n) - view_;
}
BOOST_CONSTEXPR basic_cstring_view substr(size_type pos = 0) const
{
return basic_cstring_view(view_ + pos);
}
BOOST_CONSTEXPR string_view_type substr(size_type pos , size_type n) const {return string_view_type(view_+ pos, n);}
BOOST_CONSTEXPR int compare(string_view_type s) const BOOST_NOEXCEPT
{
return traits_type::compare(view_, s.data(), std::min(length(), s.length()));
}
BOOST_CONSTEXPR int compare(size_type pos1, size_type n1, string_view_type s) const
{
return traits_type::compare(view_ + pos1, s.data(), std::min(n1, s.length()));
}
BOOST_CONSTEXPR int compare(size_type pos1, size_type n1, string_view_type s, size_type pos2, size_type n2) const
{
return traits_type::compare(view_ + pos1, s.data() + pos2, std::min(n1, n2));
}
#if (__cplusplus >= 202002)
BOOST_CONSTEXPR bool starts_with(string_view_type x) const BOOST_NOEXCEPT
{
return std::equal(view_, view_ + x.size(), x.begin(), x.end(), &traits_type::eq);
}
BOOST_CONSTEXPR bool starts_with(value_type x) const BOOST_NOEXCEPT
{
return traits_type::eq(view_[0], x);
}
BOOST_CONSTEXPR bool ends_with(string_view_type x) const BOOST_NOEXCEPT
{
return std::equal(view_ + x.size() - length(), view_ + length(), x.begin(), x.end(), &traits_type::eq);
}
BOOST_CONSTEXPR bool ends_with(value_type x) const BOOST_NOEXCEPT
{
return !empty() && traits_type::eq(view_[length() - 1], x);
}
#endif
BOOST_CONSTEXPR size_type find(basic_cstring_view s, size_type pos = 0) const BOOST_NOEXCEPT
{
const auto e = end();
const auto itr = std::search(begin(), e, s.begin(), s.end(), &traits_type::eq);
return (itr != e) ? (itr - begin()) : npos;
}
BOOST_CONSTEXPR size_type find(value_type c, size_type pos = 0) const BOOST_NOEXCEPT
{
const auto e = end();
const auto itr = std::find_if(begin(), e, [c](value_type cc) {return traits_type::eq(c, cc);});
return (itr != e) ? (itr - begin()) : npos;
}
BOOST_CONSTEXPR size_type rfind(basic_cstring_view s, size_type pos = npos) const BOOST_NOEXCEPT
{
const auto b = rbegin();
const auto itr = std::search(b, rend(), s.rbegin(), s.rend(), &traits_type::eq);
return (itr != rend()) ? (itr - b) : npos;
}
BOOST_CONSTEXPR size_type rfind(value_type c, size_type pos = npos) const BOOST_NOEXCEPT
{
const auto b = rbegin();
const auto itr = std::find_if(b, rend(), [c](value_type cc) {return traits_type::eq(c, cc);});
return (itr != rend()) ? (itr - b) : npos;
}
friend BOOST_CONSTEXPR bool operator==(basic_cstring_view x, basic_cstring_view y) BOOST_NOEXCEPT {return x.compare(y) == 0;}
friend BOOST_CONSTEXPR bool operator!=(basic_cstring_view x, basic_cstring_view y) BOOST_NOEXCEPT {return x.compare(y) != 0;}
friend BOOST_CONSTEXPR bool operator< (basic_cstring_view x, basic_cstring_view y) BOOST_NOEXCEPT {return x.compare(y) < 0;}
friend BOOST_CONSTEXPR bool operator> (basic_cstring_view x, basic_cstring_view y) BOOST_NOEXCEPT {return x.compare(y) > 0;}
friend BOOST_CONSTEXPR bool operator<=(basic_cstring_view x, basic_cstring_view y) BOOST_NOEXCEPT {return x.compare(y) <= 0;}
friend BOOST_CONSTEXPR bool operator>=(basic_cstring_view x, basic_cstring_view y) BOOST_NOEXCEPT {return x.compare(y) >= 0;}
private:
friend struct std::hash<basic_cstring_view>;
BOOST_CONSTEXPR static const_pointer null_char_() {return null_char_(CharT{});}
BOOST_CONSTEXPR static const char* null_char_(char) {return "\0";}
BOOST_CONSTEXPR static const wchar_t* null_char_(wchar_t) {return L"\0";}
BOOST_CONSTEXPR static const char16_t* null_char_(char16_t) {return u"\0";}
BOOST_CONSTEXPR static const char32_t* null_char_(char32_t) {return U"\0";}
#if ASIO_HAS_CHAR8_T
BOOST_CONSTEXPR static const char8_t* null_char_(char8_t) {return u8"\0";}
#endif
const_pointer view_;
};
using cstring_view = basic_cstring_view<char>;
using wcstring_view = basic_cstring_view<wchar_t>;
#if !defined(BOOST_NO_CXX11_CHAR16_T)
using u16cstring_view = basic_cstring_view<char16_t>;
#endif
#if !defined(BOOST_NO_CXX11_CHAR32_T)
using u32cstring_view = basic_cstring_view<char32_t>;
#endif
#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L
using u8cstring_view = basic_cstring_view<char8_t>;
#endif
}
#endif //BOOST_UTILITY_CSTRING_VIEW_HPP
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment