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 <functional> 14 : 15 : namespace boost { 16 : namespace http_proto { 17 : namespace detail { 18 : 19 : // Makes copies of string_view parameters as 20 : // needed when the storage for the parameters 21 : // overlap the container being modified. 22 : class basic_copied_strings 23 : { 24 : struct dynamic_buf 25 : { 26 : dynamic_buf* next; 27 : }; 28 : 29 : core::string_view s_; 30 : char* local_buf_; 31 : std::size_t local_remain_; 32 : dynamic_buf* dynamic_list_ = nullptr; 33 : 34 : bool 35 20 : is_overlapping( 36 : core::string_view s) const noexcept 37 : { 38 20 : auto const b1 = s_.data(); 39 20 : auto const e1 = b1 + s_.size(); 40 20 : auto const b2 = s.data(); 41 20 : auto const e2 = b2 + s.size(); 42 : auto const less_equal = 43 : std::less_equal<char const*>(); 44 20 : if(less_equal(e1, b2)) 45 3 : return false; 46 17 : if(less_equal(e2, b1)) 47 6 : return false; 48 11 : return true; 49 : } 50 : 51 : public: 52 10 : ~basic_copied_strings() 53 10 : { 54 10 : while(dynamic_list_) 55 : { 56 0 : auto p = dynamic_list_; 57 0 : dynamic_list_ = 58 0 : dynamic_list_->next; 59 0 : delete[] p; 60 : } 61 10 : } 62 : 63 10 : basic_copied_strings( 64 : core::string_view s, 65 : char* local_buf, 66 : std::size_t local_size) noexcept 67 10 : : s_(s) 68 : , local_buf_(local_buf) 69 10 : , local_remain_(local_size) 70 : { 71 10 : } 72 : 73 : core::string_view 74 20 : maybe_copy( 75 : core::string_view s) 76 : { 77 20 : if(! is_overlapping(s)) 78 9 : return s; 79 11 : if(local_remain_ >= s.size()) 80 : { 81 11 : std::memcpy(local_buf_, 82 11 : s.data(), s.size()); 83 11 : s = core::string_view( 84 11 : local_buf_, s.size()); 85 11 : local_buf_ += s.size(); 86 11 : local_remain_ -= s.size(); 87 11 : return s; 88 : } 89 0 : auto const n = 90 : sizeof(dynamic_buf); 91 0 : auto p = new dynamic_buf[1 + 92 0 : sizeof(n) * ((s.size() + 93 0 : sizeof(n) - 1) / 94 0 : sizeof(n))]; 95 0 : std::memcpy(p + 1, 96 0 : s.data(), s.size()); 97 0 : s = core::string_view(reinterpret_cast< 98 0 : char const*>(p + 1), s.size()); 99 0 : p->next = dynamic_list_; 100 0 : dynamic_list_ = p; 101 0 : return s; 102 : } 103 : }; 104 : 105 : class copied_strings 106 : : public basic_copied_strings 107 : { 108 : char buf_[4096]; 109 : 110 : public: 111 10 : copied_strings( 112 : core::string_view s) 113 10 : : basic_copied_strings( 114 10 : s, buf_, sizeof(buf_)) 115 : { 116 10 : } 117 : }; 118 : 119 : } // detail 120 : } // http_proto 121 : } // boost 122 : 123 : #endif