// // Copyright (c) 2013-2016 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_HTTP_IMPL_BASIC_HEADERS_IPP #define BEAST_HTTP_IMPL_BASIC_HEADERS_IPP #include namespace beast { namespace http { namespace detail { inline auto basic_headers_base::begin() const -> const_iterator { return list_.cbegin(); } inline auto basic_headers_base::end() const -> const_iterator { return list_.cend(); } inline auto basic_headers_base::cbegin() const -> const_iterator { return list_.cbegin(); } inline auto basic_headers_base::cend() const -> const_iterator { return list_.cend(); } } // detail //------------------------------------------------------------------------------ template void basic_headers:: delete_all() { for(auto it = list_.begin(); it != list_.end();) { auto& e = *it++; alloc_traits::destroy(this->member(), &e); alloc_traits::deallocate( this->member(), &e, 1); } } template inline void basic_headers:: move_assign(basic_headers& other, std::false_type) { if(this->member() != other.member()) { copy_from(other); other.clear(); } else { set_ = std::move(other.set_); list_ = std::move(other.list_); } } template inline void basic_headers:: move_assign(basic_headers& other, std::true_type) { this->member() = std::move(other.member()); set_ = std::move(other.set_); list_ = std::move(other.list_); } template inline void basic_headers:: copy_assign(basic_headers const& other, std::false_type) { copy_from(other); } template inline void basic_headers:: copy_assign(basic_headers const& other, std::true_type) { this->member() = other.member(); copy_from(other); } //------------------------------------------------------------------------------ template basic_headers:: ~basic_headers() { delete_all(); } template basic_headers:: basic_headers(Allocator const& alloc) : beast::detail::empty_base_optimization< alloc_type>(alloc) { } template basic_headers:: basic_headers(basic_headers&& other) : beast::detail::empty_base_optimization( std::move(other.member())) , detail::basic_headers_base( std::move(other.set_), std::move(other.list_)) { } template auto basic_headers:: operator=(basic_headers&& other) -> basic_headers& { if(this == &other) return *this; clear(); move_assign(other, std::integral_constant{}); return *this; } template basic_headers:: basic_headers(basic_headers const& other) : basic_headers(alloc_traits:: select_on_container_copy_construction(other.member())) { copy_from(other); } template auto basic_headers:: operator=(basic_headers const& other) -> basic_headers& { clear(); copy_assign(other, std::integral_constant{}); return *this; } template template basic_headers:: basic_headers(basic_headers const& other) { copy_from(other); } template template auto basic_headers:: operator=(basic_headers const& other) -> basic_headers& { clear(); copy_from(other); return *this; } template template basic_headers:: basic_headers(FwdIt first, FwdIt last) { for(;first != last; ++first) insert(first->name(), first->value()); } template auto basic_headers:: find(boost::string_ref const& name) const -> iterator { auto const it = set_.find(name, less{}); if(it == set_.end()) return list_.end(); return list_.iterator_to(*it); } template boost::string_ref basic_headers:: operator[](boost::string_ref const& name) const { // VFALCO This none object looks sketchy static boost::string_ref const none; auto const it = find(name); if(it == end()) return none; return it->second; } template void basic_headers:: clear() noexcept { delete_all(); list_.clear(); set_.clear(); } template std::size_t basic_headers:: erase(boost::string_ref const& name) { auto const it = set_.find(name, less{}); if(it == set_.end()) return 0; auto& e = *it; set_.erase(set_.iterator_to(e)); list_.erase(list_.iterator_to(e)); alloc_traits::destroy(this->member(), &e); alloc_traits::deallocate(this->member(), &e, 1); return 1; } template void basic_headers:: insert(boost::string_ref const& name, boost::string_ref value) { value = detail::trim(value); typename set_t::insert_commit_data d; auto const result = set_.insert_check(name, less{}, d); if(result.second) { auto const p = alloc_traits::allocate( this->member(), 1); alloc_traits::construct( this->member(), p, name, value); list_.push_back(*p); set_.insert_commit(*p, d); return; } // If field already exists, insert comma // separated value as per RFC2616 section 4.2 auto& cur = result.first->data.second; cur.reserve(cur.size() + 1 + value.size()); cur.append(1, ','); cur.append(value.data(), value.size()); } template void basic_headers:: replace(boost::string_ref const& name, boost::string_ref value) { value = detail::trim(value); erase(name); insert(name, value); } } // http } // beast #endif