Line data Source code
1 : // 2 : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) 3 : // 4 : // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 : // 7 : // Official repository: https://github.com/CPPAlliance/http_proto 8 : // 9 : 10 : #ifndef BOOST_HTTP_PROTO_DETAIL_COPIED_STRINGS_HPP 11 : #define BOOST_HTTP_PROTO_DETAIL_COPIED_STRINGS_HPP 12 : 13 : #include <boost/http_proto/string_view.hpp> 14 : #include <functional> 15 : 16 : namespace boost { 17 : namespace http_proto { 18 : namespace detail { 19 : 20 : // Makes copies of string_view parameters as 21 : // needed when the storage for the parameters 22 : // overlap the container being modified. 23 : class basic_copied_strings 24 : { 25 : struct dynamic_buf 26 : { 27 : dynamic_buf* next; 28 : }; 29 : 30 : string_view s_; 31 : char* local_buf_; 32 : std::size_t local_remain_; 33 : dynamic_buf* dynamic_list_ = nullptr; 34 : 35 : bool 36 380 : is_overlapping( 37 : string_view s) const noexcept 38 : { 39 380 : auto const b1 = s_.data(); 40 380 : auto const e1 = b1 + s_.size(); 41 380 : auto const b2 = s.data(); 42 380 : auto const e2 = b2 + s.size(); 43 : auto const less_equal = 44 : std::less_equal<char const*>(); 45 380 : if(less_equal(e1, b2)) 46 3 : return false; 47 377 : if(less_equal(e2, b1)) 48 366 : return false; 49 11 : return true; 50 : } 51 : 52 : public: 53 190 : ~basic_copied_strings() 54 190 : { 55 190 : while(dynamic_list_) 56 : { 57 0 : auto p = dynamic_list_; 58 0 : dynamic_list_ = 59 0 : dynamic_list_->next; 60 0 : delete[] p; 61 : } 62 190 : } 63 : 64 190 : basic_copied_strings( 65 : string_view s, 66 : char* local_buf, 67 : std::size_t local_size) noexcept 68 190 : : s_(s) 69 : , local_buf_(local_buf) 70 190 : , local_remain_(local_size) 71 : { 72 190 : } 73 : 74 : string_view 75 380 : maybe_copy( 76 : string_view s) 77 : { 78 380 : if(! is_overlapping(s)) 79 369 : return s; 80 11 : if(local_remain_ >= s.size()) 81 : { 82 11 : std::memcpy(local_buf_, 83 11 : s.data(), s.size()); 84 11 : s = string_view( 85 11 : local_buf_, s.size()); 86 11 : local_buf_ += s.size(); 87 11 : local_remain_ -= s.size(); 88 11 : return s; 89 : } 90 0 : auto const n = 91 : sizeof(dynamic_buf); 92 0 : auto p = new dynamic_buf[1 + 93 0 : sizeof(n) * ((s.size() + 94 0 : sizeof(n) - 1) / 95 0 : sizeof(n))]; 96 0 : std::memcpy(p + 1, 97 0 : s.data(), s.size()); 98 0 : s = string_view(reinterpret_cast< 99 0 : char const*>(p + 1), s.size()); 100 0 : p->next = dynamic_list_; 101 0 : dynamic_list_ = p; 102 0 : return s; 103 : } 104 : }; 105 : 106 : class copied_strings 107 : : public basic_copied_strings 108 : { 109 : char buf_[4096]; 110 : 111 : public: 112 190 : copied_strings( 113 : string_view s) 114 190 : : basic_copied_strings( 115 190 : s, buf_, sizeof(buf_)) 116 : { 117 190 : } 118 : }; 119 : 120 : } // detail 121 : } // http_proto 122 : } // boost 123 : 124 : #endif