From 80eb5af58423022568c30c70de49fc7e4fb03316 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Sat, 8 Jul 2017 15:34:07 -0700 Subject: [PATCH] Add span --- CHANGELOG.md | 2 + doc/quickref.xml | 1 + include/beast/core.hpp | 1 + include/beast/core/detail/type_traits.hpp | 22 +++ include/beast/core/span.hpp | 211 ++++++++++++++++++++++ test/core/CMakeLists.txt | 1 + test/core/Jamfile | 1 + test/core/span.cpp | 51 ++++++ 8 files changed, 290 insertions(+) create mode 100644 include/beast/core/span.hpp create mode 100644 test/core/span.cpp diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ed56e67..54e4fa72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ Version 78: +* Add span + HTTP: * Tidy up basic_string_body diff --git a/doc/quickref.xml b/doc/quickref.xml index 7d80de55..d49491ba 100644 --- a/doc/quickref.xml +++ b/doc/quickref.xml @@ -192,6 +192,7 @@ iequal iless multi_buffer + span static_buffer static_buffer_n static_string diff --git a/include/beast/core.hpp b/include/beast/core.hpp index 1a1c49c6..9e63e6df 100644 --- a/include/beast/core.hpp +++ b/include/beast/core.hpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include diff --git a/include/beast/core/detail/type_traits.hpp b/include/beast/core/detail/type_traits.hpp index f80f6fe4..e375b976 100644 --- a/include/beast/core/detail/type_traits.hpp +++ b/include/beast/core/detail/type_traits.hpp @@ -138,6 +138,28 @@ struct is_invocable }; /** @} */ +// for span +template +struct is_contiguous_container: std::false_type {}; + +template +struct is_contiguous_container() = std::declval().size(), + std::declval() = std::declval().data(), + (void)0), + typename std::enable_if< + std::is_same< + typename std::remove_cv::type, + typename std::remove_cv< + typename std::remove_pointer< + decltype(std::declval().data()) + >::type + >::type + >::value + >::type>>: std::true_type +{}; + //------------------------------------------------------------------------------ // diff --git a/include/beast/core/span.hpp b/include/beast/core/span.hpp new file mode 100644 index 00000000..d6998ea8 --- /dev/null +++ b/include/beast/core/span.hpp @@ -0,0 +1,211 @@ +// +// Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com) +// +// 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 BEAST_CORE_SPAN_HPP +#define BEAST_CORE_SPAN_HPP + +#include +#include +#include +#include +#include +#include + +namespace beast { + +/** A range of bytes expressed as a ContiguousContainer + + This class implements a non-owning reference to a storage + area of a certain size and having an underlying integral + type with size of 1. + + @tparam T The type pointed to by span iterators +*/ +template +class span +{ + T* data_ = nullptr; + std::size_t size_ = 0; + +public: + /// The type of value, including cv qualifiers + using element_type = T; + + /// The type of value of each span element + using value_type = typename std::remove_const::type; + + /// The type of integer used to index the span + using index_type = std::ptrdiff_t; + + /// A pointer to a span element + using pointer = T*; + + /// A reference to a span element + using reference = T&; + + /// The iterator used by the container + using iterator = pointer; + + /// The const pointer used by the container + using const_pointer = T const*; + + /// The const reference used by the container + using const_reference = T const&; + + /// The const iterator used by the container + using const_iterator = const_pointer; + + /// Constructor + span() = default; + + /// Constructor + span(span const&) = default; + + /// Assignment + span& operator=(span const&) = default; + + /** Constructor + + @param data A pointer to the beginning of the range of elements + + @param size The number of elements pointed to by `data` + */ + span(T* data, std::size_t size) + : data_(data), size_(size) + { + } + + /** Constructor + + @param container The container to construct from + */ + template::value>::type +#endif + > + explicit + span(ContiguousContainer&& container) + : data_(container.data()) + , size_(container.size()) + { + } + +#if ! BEAST_DOXYGEN + template + explicit + span(std::basic_string& s) + : data_(&s[0]) + , size_(s.size()) + { + } + + template + explicit + span(std::basic_string const& s) + : data_(s.data()) + , size_(s.size()) + { + } +#endif + + /** Assignment + + @param container The container to assign from + */ + template +#if BEAST_DOXYGEN + span& +#else + typename std::enable_if::value, + span&>::type +#endif + operator=(ContiguousContainer&& container) + { + data_ = container.data(); + size_ = container.size(); + return *this; + } + +#if ! BEAST_DOXYGEN + template + span& + operator=(std::basic_string< + CharT, Traits, Allocator>& s) + { + data_ = &s[0]; + size_ = s.size(); + return *this; + } + + template + span& + operator=(std::basic_string< + CharT, Traits, Allocator> const& s) + { + data_ = s.data(); + size_ = s.size(); + return *this; + } +#endif + + /// Returns `true` if the span is empty + bool + empty() const + { + return size_ == 0; + } + + /// Returns a pointer to the beginning of the span + T* + data() const + { + return data_; + } + + /// Returns the number of elements in the span + std::size_t + size() const + { + return size_; + } + + /// Returns an iterator to the beginning of the span + const_iterator + begin() const + { + return data_; + } + + /// Returns an iterator to the beginning of the span + const_iterator + cbegin() const + { + return data_; + } + + /// Returns an iterator to one past the end of the span + const_iterator + end() const + { + return data_ + size_; + } + + /// Returns an iterator to one past the end of the span + const_iterator + cend() const + { + return data_ + size_; + } +}; + +} // beast + +#endif diff --git a/test/core/CMakeLists.txt b/test/core/CMakeLists.txt index 595032bc..39749c57 100644 --- a/test/core/CMakeLists.txt +++ b/test/core/CMakeLists.txt @@ -35,6 +35,7 @@ add_executable (core-tests multi_buffer.cpp ostream.cpp read_size.cpp + span.cpp static_buffer.cpp static_string.cpp string.cpp diff --git a/test/core/Jamfile b/test/core/Jamfile index 52218baa..159b7ae5 100644 --- a/test/core/Jamfile +++ b/test/core/Jamfile @@ -29,6 +29,7 @@ unit-test core-tests : multi_buffer.cpp ostream.cpp read_size.cpp + span.cpp static_buffer.cpp static_string.cpp string.cpp diff --git a/test/core/span.cpp b/test/core/span.cpp new file mode 100644 index 00000000..32892de3 --- /dev/null +++ b/test/core/span.cpp @@ -0,0 +1,51 @@ +// +// Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com) +// +// 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) +// + +// Test that header file is self-contained. +#include + +#include + +namespace beast { + +class span_test : public beast::unit_test::suite +{ +public: + struct base {}; + struct derived : base {}; + + BOOST_STATIC_ASSERT(detail::is_contiguous_container< + std::vector, char>::value); + + BOOST_STATIC_ASSERT(detail::is_contiguous_container< + std::vector, char const>::value); + + BOOST_STATIC_ASSERT(! detail::is_contiguous_container< + std::vector, base>::value); + + BOOST_STATIC_ASSERT(! detail::is_contiguous_container< + std::vector, base const>::value); + + void + testSpan() + { + span sp{"hello", 5}; + BEAST_EXPECT(sp.size() == 5); + std::string s("world"); + sp = s; + } + + void + run() override + { + testSpan(); + } +}; + +BEAST_DEFINE_TESTSUITE(span,core,beast); + +} // beast