99.12% Lines (225/227)
100.00% Functions (12/12)
| TLA | Baseline | Branch | ||||||
|---|---|---|---|---|---|---|---|---|
| Line | Hits | Code | Line | Hits | Code | |||
| 1 | // | 1 | // | |||||
| 2 | // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) | 2 | // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) | |||||
| 3 | // Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com) | 3 | // Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com) | |||||
| 4 | // | 4 | // | |||||
| 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |||||
| 6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | 6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |||||
| 7 | // | 7 | // | |||||
| 8 | // Official repository: https://github.com/boostorg/json | 8 | // Official repository: https://github.com/boostorg/json | |||||
| 9 | // | 9 | // | |||||
| 10 | 10 | |||||||
| 11 | #ifndef BOOST_JSON_DETAIL_IMPL_STRING_IMPL_IPP | 11 | #ifndef BOOST_JSON_DETAIL_IMPL_STRING_IMPL_IPP | |||||
| 12 | #define BOOST_JSON_DETAIL_IMPL_STRING_IMPL_IPP | 12 | #define BOOST_JSON_DETAIL_IMPL_STRING_IMPL_IPP | |||||
| 13 | 13 | |||||||
| 14 | #include <boost/json/detail/string_impl.hpp> | 14 | #include <boost/json/detail/string_impl.hpp> | |||||
| 15 | #include <boost/json/detail/except.hpp> | 15 | #include <boost/json/detail/except.hpp> | |||||
| 16 | #include <cstring> | 16 | #include <cstring> | |||||
| 17 | #include <functional> | 17 | #include <functional> | |||||
| 18 | 18 | |||||||
| 19 | namespace boost { | 19 | namespace boost { | |||||
| 20 | namespace json { | 20 | namespace json { | |||||
| 21 | namespace detail { | 21 | namespace detail { | |||||
| 22 | 22 | |||||||
| HITCBC | 23 | 30961 | string_impl:: | 23 | 30961 | string_impl:: | ||
| HITCBC | 24 | 30961 | string_impl() noexcept | 24 | 30961 | string_impl() noexcept | ||
| 25 | { | 25 | { | |||||
| HITCBC | 26 | 30961 | s_.k = short_string_; | 26 | 30961 | s_.k = short_string_; | ||
| HITCBC | 27 | 30961 | s_.buf[sbo_chars_] = | 27 | 30961 | s_.buf[sbo_chars_] = | ||
| 28 | static_cast<char>( | 28 | static_cast<char>( | |||||
| 29 | sbo_chars_); | 29 | sbo_chars_); | |||||
| HITCBC | 30 | 30961 | s_.buf[0] = 0; | 30 | 30961 | s_.buf[0] = 0; | ||
| HITCBC | 31 | 30961 | } | 31 | 30961 | } | ||
| 32 | 32 | |||||||
| HITCBC | 33 | 26932 | string_impl:: | 33 | 26932 | string_impl:: | ||
| 34 | string_impl( | 34 | string_impl( | |||||
| 35 | std::size_t size, | 35 | std::size_t size, | |||||
| HITCBC | 36 | 26932 | storage_ptr const& sp) | 36 | 26932 | storage_ptr const& sp) | ||
| 37 | { | 37 | { | |||||
| HITCBC | 38 | 26932 | if(size <= sbo_chars_) | 38 | 26932 | if(size <= sbo_chars_) | ||
| 39 | { | 39 | { | |||||
| HITCBC | 40 | 41 | s_.k = short_string_; | 40 | 41 | s_.k = short_string_; | ||
| HITCBC | 41 | 41 | s_.buf[sbo_chars_] = | 41 | 41 | s_.buf[sbo_chars_] = | ||
| 42 | static_cast<char>( | 42 | static_cast<char>( | |||||
| HITCBC | 43 | 41 | sbo_chars_ - size); | 43 | 41 | sbo_chars_ - size); | ||
| HITCBC | 44 | 41 | s_.buf[size] = 0; | 44 | 41 | s_.buf[size] = 0; | ||
| 45 | } | 45 | } | |||||
| 46 | else | 46 | else | |||||
| 47 | { | 47 | { | |||||
| HITCBC | 48 | 26891 | s_.k = kind::string; | 48 | 26891 | s_.k = kind::string; | ||
| HITCBC | 49 | 26891 | auto const n = growth( | 49 | 26891 | auto const n = growth( | ||
| 50 | size, sbo_chars_ + 1); | 50 | size, sbo_chars_ + 1); | |||||
| HITCBC | 51 | 26891 | p_.t = ::new(sp->allocate( | 51 | 26891 | p_.t = ::new(sp->allocate( | ||
| 52 | sizeof(table) + | 52 | sizeof(table) + | |||||
| HITCBC | 53 | 26891 | n + 1, | 53 | 26891 | n + 1, | ||
| 54 | alignof(table))) table{ | 54 | alignof(table))) table{ | |||||
| 55 | static_cast< | 55 | static_cast< | |||||
| 56 | std::uint32_t>(size), | 56 | std::uint32_t>(size), | |||||
| 57 | static_cast< | 57 | static_cast< | |||||
| HITCBC | 58 | 26696 | std::uint32_t>(n)}; | 58 | 26696 | std::uint32_t>(n)}; | ||
| HITCBC | 59 | 26696 | data()[n] = 0; | 59 | 26696 | data()[n] = 0; | ||
| 60 | } | 60 | } | |||||
| HITCBC | 61 | 26737 | } | 61 | 26737 | } | ||
| 62 | 62 | |||||||
| 63 | // construct a key, unchecked | 63 | // construct a key, unchecked | |||||
| HITCBC | 64 | 30296 | string_impl:: | 64 | 30296 | string_impl:: | ||
| 65 | string_impl( | 65 | string_impl( | |||||
| 66 | key_t, | 66 | key_t, | |||||
| 67 | string_view s, | 67 | string_view s, | |||||
| HITCBC | 68 | 30296 | storage_ptr const& sp) | 68 | 30296 | storage_ptr const& sp) | ||
| 69 | { | 69 | { | |||||
| HITCBC | 70 | 30296 | BOOST_ASSERT( | 70 | 30296 | BOOST_ASSERT( | ||
| 71 | s.size() <= max_size()); | 71 | s.size() <= max_size()); | |||||
| HITCBC | 72 | 30296 | k_.k = key_string_; | 72 | 30296 | k_.k = key_string_; | ||
| HITCBC | 73 | 30296 | k_.n = static_cast< | 73 | 30296 | k_.n = static_cast< | ||
| HITCBC | 74 | 30296 | std::uint32_t>(s.size()); | 74 | 30296 | std::uint32_t>(s.size()); | ||
| HITCBC | 75 | 30236 | k_.s = reinterpret_cast<char*>( | 75 | 30236 | k_.s = reinterpret_cast<char*>( | ||
| HITCBC | 76 | 30296 | sp->allocate(s.size() + 1, | 76 | 30296 | sp->allocate(s.size() + 1, | ||
| 77 | alignof(char))); | 77 | alignof(char))); | |||||
| HITCBC | 78 | 30236 | k_.s[s.size()] = 0; // null term | 78 | 30236 | k_.s[s.size()] = 0; // null term | ||
| HITCBC | 79 | 30236 | std::memcpy(&k_.s[0], | 79 | 30236 | std::memcpy(&k_.s[0], | ||
| HITCBC | 80 | 30236 | s.data(), s.size()); | 80 | 30236 | s.data(), s.size()); | ||
| HITCBC | 81 | 30236 | } | 81 | 30236 | } | ||
| 82 | 82 | |||||||
| 83 | // construct a key, unchecked | 83 | // construct a key, unchecked | |||||
| HITCBC | 84 | 8060 | string_impl:: | 84 | 8060 | string_impl:: | ||
| 85 | string_impl( | 85 | string_impl( | |||||
| 86 | key_t, | 86 | key_t, | |||||
| 87 | string_view s1, | 87 | string_view s1, | |||||
| 88 | string_view s2, | 88 | string_view s2, | |||||
| HITCBC | 89 | 8060 | storage_ptr const& sp) | 89 | 8060 | storage_ptr const& sp) | ||
| 90 | { | 90 | { | |||||
| HITCBC | 91 | 8060 | auto len = s1.size() + s2.size(); | 91 | 8060 | auto len = s1.size() + s2.size(); | ||
| HITCBC | 92 | 8060 | BOOST_ASSERT(len <= max_size()); | 92 | 8060 | BOOST_ASSERT(len <= max_size()); | ||
| HITCBC | 93 | 8060 | k_.k = key_string_; | 93 | 8060 | k_.k = key_string_; | ||
| HITCBC | 94 | 8060 | k_.n = static_cast< | 94 | 8060 | k_.n = static_cast< | ||
| 95 | std::uint32_t>(len); | 95 | std::uint32_t>(len); | |||||
| HITCBC | 96 | 8060 | k_.s = reinterpret_cast<char*>( | 96 | 8060 | k_.s = reinterpret_cast<char*>( | ||
| HITCBC | 97 | 8060 | sp->allocate(len + 1, | 97 | 8060 | sp->allocate(len + 1, | ||
| 98 | alignof(char))); | 98 | alignof(char))); | |||||
| HITCBC | 99 | 8060 | k_.s[len] = 0; // null term | 99 | 8060 | k_.s[len] = 0; // null term | ||
| HITCBC | 100 | 8060 | std::memcpy(&k_.s[0], | 100 | 8060 | std::memcpy(&k_.s[0], | ||
| HITCBC | 101 | 8060 | s1.data(), s1.size()); | 101 | 8060 | s1.data(), s1.size()); | ||
| HITCBC | 102 | 16120 | std::memcpy(&k_.s[s1.size()], | 102 | 16120 | std::memcpy(&k_.s[s1.size()], | ||
| HITCBC | 103 | 8060 | s2.data(), s2.size()); | 103 | 8060 | s2.data(), s2.size()); | ||
| HITCBC | 104 | 8060 | } | 104 | 8060 | } | ||
| 105 | 105 | |||||||
| 106 | std::uint32_t | 106 | std::uint32_t | |||||
| HITCBC | 107 | 53776 | string_impl:: | 107 | 53776 | string_impl:: | ||
| 108 | growth( | 108 | growth( | |||||
| 109 | std::size_t new_size, | 109 | std::size_t new_size, | |||||
| 110 | std::size_t capacity) | 110 | std::size_t capacity) | |||||
| 111 | { | 111 | { | |||||
| HITCBC | 112 | 53776 | if(new_size > max_size()) | 112 | 53776 | if(new_size > max_size()) | ||
| 113 | { | 113 | { | |||||
| 114 | BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; | 114 | BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; | |||||
| HITCBC | 115 | 1 | detail::throw_system_error( error::string_too_large, &loc ); | 115 | 1 | detail::throw_system_error( error::string_too_large, &loc ); | ||
| 116 | } | 116 | } | |||||
| 117 | // growth factor 2 | 117 | // growth factor 2 | |||||
| HITCBC | 118 | 53775 | if( capacity > | 118 | 53775 | if( capacity > | ||
| HITCBC | 119 | 53775 | max_size() - capacity) | 119 | 53775 | max_size() - capacity) | ||
| 120 | return static_cast< | 120 | return static_cast< | |||||
| MISUBC | 121 | ✗ | std::uint32_t>(max_size()); // overflow | 121 | ✗ | std::uint32_t>(max_size()); // overflow | ||
| 122 | return static_cast<std::uint32_t>( | 122 | return static_cast<std::uint32_t>( | |||||
| HITCBC | 123 | 53775 | (std::max)(capacity * 2, new_size)); | 123 | 53775 | (std::max)(capacity * 2, new_size)); | ||
| 124 | } | 124 | } | |||||
| 125 | 125 | |||||||
| 126 | char* | 126 | char* | |||||
| HITCBC | 127 | 18470 | string_impl:: | 127 | 18470 | string_impl:: | ||
| 128 | assign( | 128 | assign( | |||||
| 129 | std::size_t new_size, | 129 | std::size_t new_size, | |||||
| 130 | storage_ptr const& sp) | 130 | storage_ptr const& sp) | |||||
| 131 | { | 131 | { | |||||
| HITCBC | 132 | 18470 | if(new_size > capacity()) | 132 | 18470 | if(new_size > capacity()) | ||
| 133 | { | 133 | { | |||||
| HITCBC | 134 | 17111 | string_impl tmp(growth( | 134 | 17111 | string_impl tmp(growth( | ||
| 135 | new_size, | 135 | new_size, | |||||
| HITCBC | 136 | 17111 | capacity()), sp); | 136 | 17111 | capacity()), sp); | ||
| HITCBC | 137 | 16967 | destroy(sp); | 137 | 16967 | destroy(sp); | ||
| HITCBC | 138 | 16967 | *this = tmp; | 138 | 16967 | *this = tmp; | ||
| 139 | } | 139 | } | |||||
| HITCBC | 140 | 18326 | term(new_size); | 140 | 18326 | term(new_size); | ||
| HITCBC | 141 | 18326 | return data(); | 141 | 18326 | return data(); | ||
| 142 | } | 142 | } | |||||
| 143 | 143 | |||||||
| 144 | char* | 144 | char* | |||||
| HITCBC | 145 | 224 | string_impl:: | 145 | 224 | string_impl:: | ||
| 146 | append( | 146 | append( | |||||
| 147 | std::size_t n, | 147 | std::size_t n, | |||||
| 148 | storage_ptr const& sp) | 148 | storage_ptr const& sp) | |||||
| 149 | { | 149 | { | |||||
| HITCBC | 150 | 224 | if(n > max_size() - size()) | 150 | 224 | if(n > max_size() - size()) | ||
| 151 | { | 151 | { | |||||
| 152 | BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; | 152 | BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; | |||||
| HITCBC | 153 | 1 | detail::throw_system_error( error::string_too_large, &loc ); | 153 | 1 | detail::throw_system_error( error::string_too_large, &loc ); | ||
| 154 | } | 154 | } | |||||
| HITCBC | 155 | 223 | if(n <= capacity() - size()) | 155 | 223 | if(n <= capacity() - size()) | ||
| 156 | { | 156 | { | |||||
| HITCBC | 157 | 167 | term(size() + n); | 157 | 167 | term(size() + n); | ||
| HITCBC | 158 | 167 | return end() - n; | 158 | 167 | return end() - n; | ||
| 159 | } | 159 | } | |||||
| HITCBC | 160 | 112 | string_impl tmp(growth( | 160 | 112 | string_impl tmp(growth( | ||
| HITCBC | 161 | 112 | size() + n, capacity()), sp); | 161 | 112 | size() + n, capacity()), sp); | ||
| HITCBC | 162 | 33 | std::memcpy( | 162 | 33 | std::memcpy( | ||
| HITCBC | 163 | 33 | tmp.data(), data(), size()); | 163 | 33 | tmp.data(), data(), size()); | ||
| HITCBC | 164 | 33 | tmp.term(size() + n); | 164 | 33 | tmp.term(size() + n); | ||
| HITCBC | 165 | 33 | destroy(sp); | 165 | 33 | destroy(sp); | ||
| HITCBC | 166 | 33 | *this = tmp; | 166 | 33 | *this = tmp; | ||
| HITCBC | 167 | 33 | return end() - n; | 167 | 33 | return end() - n; | ||
| 168 | } | 168 | } | |||||
| 169 | 169 | |||||||
| 170 | void | 170 | void | |||||
| HITCBC | 171 | 27 | string_impl:: | 171 | 27 | string_impl:: | ||
| 172 | insert( | 172 | insert( | |||||
| 173 | std::size_t pos, | 173 | std::size_t pos, | |||||
| 174 | const char* s, | 174 | const char* s, | |||||
| 175 | std::size_t n, | 175 | std::size_t n, | |||||
| 176 | storage_ptr const& sp) | 176 | storage_ptr const& sp) | |||||
| 177 | { | 177 | { | |||||
| HITCBC | 178 | 27 | const auto curr_size = size(); | 178 | 27 | const auto curr_size = size(); | ||
| HITCBC | 179 | 27 | if(pos > curr_size) | 179 | 27 | if(pos > curr_size) | ||
| 180 | { | 180 | { | |||||
| 181 | BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; | 181 | BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; | |||||
| HITCBC | 182 | 2 | detail::throw_system_error( error::out_of_range, &loc ); | 182 | 2 | detail::throw_system_error( error::out_of_range, &loc ); | ||
| 183 | } | 183 | } | |||||
| HITCBC | 184 | 25 | const auto curr_data = data(); | 184 | 25 | const auto curr_data = data(); | ||
| HITCBC | 185 | 25 | if(n <= capacity() - curr_size) | 185 | 25 | if(n <= capacity() - curr_size) | ||
| 186 | { | 186 | { | |||||
| HITCBC | 187 | 10 | const bool inside = detail::ptr_in_range(curr_data, curr_data + curr_size, s); | 187 | 10 | const bool inside = detail::ptr_in_range(curr_data, curr_data + curr_size, s); | ||
| HITCBC | 188 | 10 | if (!inside || (inside && ((s - curr_data) + n <= pos))) | 188 | 10 | if (!inside || (inside && ((s - curr_data) + n <= pos))) | ||
| 189 | { | 189 | { | |||||
| HITCBC | 190 | 8 | std::memmove(&curr_data[pos + n], &curr_data[pos], curr_size - pos + 1); | 190 | 8 | std::memmove(&curr_data[pos + n], &curr_data[pos], curr_size - pos + 1); | ||
| HITCBC | 191 | 8 | std::memcpy(&curr_data[pos], s, n); | 191 | 8 | std::memcpy(&curr_data[pos], s, n); | ||
| 192 | } | 192 | } | |||||
| 193 | else | 193 | else | |||||
| 194 | { | 194 | { | |||||
| HITCBC | 195 | 2 | const std::size_t offset = s - curr_data; | 195 | 2 | const std::size_t offset = s - curr_data; | ||
| HITCBC | 196 | 2 | std::memmove(&curr_data[pos + n], &curr_data[pos], curr_size - pos + 1); | 196 | 2 | std::memmove(&curr_data[pos + n], &curr_data[pos], curr_size - pos + 1); | ||
| HITCBC | 197 | 2 | if (offset < pos) | 197 | 2 | if (offset < pos) | ||
| 198 | { | 198 | { | |||||
| HITCBC | 199 | 1 | const std::size_t diff = pos - offset; | 199 | 1 | const std::size_t diff = pos - offset; | ||
| HITCBC | 200 | 1 | std::memcpy(&curr_data[pos], &curr_data[offset], diff); | 200 | 1 | std::memcpy(&curr_data[pos], &curr_data[offset], diff); | ||
| HITCBC | 201 | 1 | std::memcpy(&curr_data[pos + diff], &curr_data[pos + n], n - diff); | 201 | 1 | std::memcpy(&curr_data[pos + diff], &curr_data[pos + n], n - diff); | ||
| 202 | } | 202 | } | |||||
| 203 | else | 203 | else | |||||
| 204 | { | 204 | { | |||||
| HITCBC | 205 | 1 | std::memcpy(&curr_data[pos], &curr_data[offset + n], n); | 205 | 1 | std::memcpy(&curr_data[pos], &curr_data[offset + n], n); | ||
| 206 | } | 206 | } | |||||
| 207 | } | 207 | } | |||||
| HITCBC | 208 | 10 | size(curr_size + n); | 208 | 10 | size(curr_size + n); | ||
| 209 | } | 209 | } | |||||
| 210 | else | 210 | else | |||||
| 211 | { | 211 | { | |||||
| HITCBC | 212 | 15 | if(n > max_size() - curr_size) | 212 | 15 | if(n > max_size() - curr_size) | ||
| 213 | { | 213 | { | |||||
| 214 | BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; | 214 | BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; | |||||
| HITCBC | 215 | 1 | detail::throw_system_error( error::string_too_large, &loc ); | 215 | 1 | detail::throw_system_error( error::string_too_large, &loc ); | ||
| 216 | } | 216 | } | |||||
| HITCBC | 217 | 14 | string_impl tmp(growth( | 217 | 14 | string_impl tmp(growth( | ||
| HITCBC | 218 | 14 | curr_size + n, capacity()), sp); | 218 | 14 | curr_size + n, capacity()), sp); | ||
| HITCBC | 219 | 7 | tmp.size(curr_size + n); | 219 | 7 | tmp.size(curr_size + n); | ||
| HITCBC | 220 | 7 | std::memcpy( | 220 | 7 | std::memcpy( | ||
| HITCBC | 221 | 7 | tmp.data(), | 221 | 7 | tmp.data(), | ||
| 222 | curr_data, | 222 | curr_data, | |||||
| 223 | pos); | 223 | pos); | |||||
| HITCBC | 224 | 14 | std::memcpy( | 224 | 14 | std::memcpy( | ||
| HITCBC | 225 | 14 | tmp.data() + pos + n, | 225 | 14 | tmp.data() + pos + n, | ||
| 226 | curr_data + pos, | 226 | curr_data + pos, | |||||
| HITCBC | 227 | 7 | curr_size + 1 - pos); | 227 | 7 | curr_size + 1 - pos); | ||
| HITCBC | 228 | 7 | std::memcpy( | 228 | 7 | std::memcpy( | ||
| HITCBC | 229 | 7 | tmp.data() + pos, | 229 | 7 | tmp.data() + pos, | ||
| 230 | s, | 230 | s, | |||||
| 231 | n); | 231 | n); | |||||
| HITCBC | 232 | 7 | destroy(sp); | 232 | 7 | destroy(sp); | ||
| HITCBC | 233 | 7 | *this = tmp; | 233 | 7 | *this = tmp; | ||
| 234 | } | 234 | } | |||||
| HITCBC | 235 | 17 | } | 235 | 17 | } | ||
| 236 | 236 | |||||||
| 237 | char* | 237 | char* | |||||
| HITCBC | 238 | 17 | string_impl:: | 238 | 17 | string_impl:: | ||
| 239 | insert_unchecked( | 239 | insert_unchecked( | |||||
| 240 | std::size_t pos, | 240 | std::size_t pos, | |||||
| 241 | std::size_t n, | 241 | std::size_t n, | |||||
| 242 | storage_ptr const& sp) | 242 | storage_ptr const& sp) | |||||
| 243 | { | 243 | { | |||||
| HITCBC | 244 | 17 | const auto curr_size = size(); | 244 | 17 | const auto curr_size = size(); | ||
| HITCBC | 245 | 17 | if(pos > curr_size) | 245 | 17 | if(pos > curr_size) | ||
| 246 | { | 246 | { | |||||
| 247 | BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; | 247 | BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; | |||||
| HITCBC | 248 | 1 | detail::throw_system_error( error::out_of_range, &loc ); | 248 | 1 | detail::throw_system_error( error::out_of_range, &loc ); | ||
| 249 | } | 249 | } | |||||
| HITCBC | 250 | 16 | const auto curr_data = data(); | 250 | 16 | const auto curr_data = data(); | ||
| HITCBC | 251 | 16 | if(n <= capacity() - size()) | 251 | 16 | if(n <= capacity() - size()) | ||
| 252 | { | 252 | { | |||||
| HITCBC | 253 | 5 | auto const dest = | 253 | 5 | auto const dest = | ||
| 254 | curr_data + pos; | 254 | curr_data + pos; | |||||
| HITCBC | 255 | 5 | std::memmove( | 255 | 5 | std::memmove( | ||
| 256 | dest + n, | 256 | dest + n, | |||||
| 257 | dest, | 257 | dest, | |||||
| HITCBC | 258 | 5 | curr_size + 1 - pos); | 258 | 5 | curr_size + 1 - pos); | ||
| HITCBC | 259 | 5 | size(curr_size + n); | 259 | 5 | size(curr_size + n); | ||
| HITCBC | 260 | 5 | return dest; | 260 | 5 | return dest; | ||
| 261 | } | 261 | } | |||||
| HITCBC | 262 | 11 | if(n > max_size() - curr_size) | 262 | 11 | if(n > max_size() - curr_size) | ||
| 263 | { | 263 | { | |||||
| 264 | BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; | 264 | BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; | |||||
| HITCBC | 265 | 1 | detail::throw_system_error( error::string_too_large, &loc ); | 265 | 1 | detail::throw_system_error( error::string_too_large, &loc ); | ||
| 266 | } | 266 | } | |||||
| HITCBC | 267 | 10 | string_impl tmp(growth( | 267 | 10 | string_impl tmp(growth( | ||
| HITCBC | 268 | 10 | curr_size + n, capacity()), sp); | 268 | 10 | curr_size + n, capacity()), sp); | ||
| HITCBC | 269 | 5 | tmp.size(curr_size + n); | 269 | 5 | tmp.size(curr_size + n); | ||
| HITCBC | 270 | 5 | std::memcpy( | 270 | 5 | std::memcpy( | ||
| HITCBC | 271 | 5 | tmp.data(), | 271 | 5 | tmp.data(), | ||
| 272 | curr_data, | 272 | curr_data, | |||||
| 273 | pos); | 273 | pos); | |||||
| HITCBC | 274 | 10 | std::memcpy( | 274 | 10 | std::memcpy( | ||
| HITCBC | 275 | 10 | tmp.data() + pos + n, | 275 | 10 | tmp.data() + pos + n, | ||
| 276 | curr_data + pos, | 276 | curr_data + pos, | |||||
| HITCBC | 277 | 5 | curr_size + 1 - pos); | 277 | 5 | curr_size + 1 - pos); | ||
| HITCBC | 278 | 5 | destroy(sp); | 278 | 5 | destroy(sp); | ||
| HITCBC | 279 | 5 | *this = tmp; | 279 | 5 | *this = tmp; | ||
| HITCBC | 280 | 5 | return data() + pos; | 280 | 5 | return data() + pos; | ||
| 281 | } | 281 | } | |||||
| 282 | 282 | |||||||
| 283 | void | 283 | void | |||||
| HITCBC | 284 | 19 | string_impl:: | 284 | 19 | string_impl:: | ||
| 285 | replace( | 285 | replace( | |||||
| 286 | std::size_t pos, | 286 | std::size_t pos, | |||||
| 287 | std::size_t n1, | 287 | std::size_t n1, | |||||
| 288 | const char* s, | 288 | const char* s, | |||||
| 289 | std::size_t n2, | 289 | std::size_t n2, | |||||
| 290 | storage_ptr const& sp) | 290 | storage_ptr const& sp) | |||||
| 291 | { | 291 | { | |||||
| HITCBC | 292 | 19 | const auto curr_size = size(); | 292 | 19 | const auto curr_size = size(); | ||
| HITCBC | 293 | 19 | if (pos > curr_size) | 293 | 19 | if (pos > curr_size) | ||
| 294 | { | 294 | { | |||||
| 295 | BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; | 295 | BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; | |||||
| HITCBC | 296 | 1 | detail::throw_system_error( error::out_of_range, &loc ); | 296 | 1 | detail::throw_system_error( error::out_of_range, &loc ); | ||
| 297 | } | 297 | } | |||||
| HITCBC | 298 | 18 | const auto curr_data = data(); | 298 | 18 | const auto curr_data = data(); | ||
| HITCBC | 299 | 18 | n1 = (std::min)(n1, curr_size - pos); | 299 | 18 | n1 = (std::min)(n1, curr_size - pos); | ||
| HITCBC | 300 | 18 | const auto delta = (std::max)(n1, n2) - | 300 | 18 | const auto delta = (std::max)(n1, n2) - | ||
| HITCBC | 301 | 18 | (std::min)(n1, n2); | 301 | 18 | (std::min)(n1, n2); | ||
| 302 | // if we are shrinking in size or we have enough | 302 | // if we are shrinking in size or we have enough | |||||
| 303 | // capacity, dont reallocate | 303 | // capacity, dont reallocate | |||||
| HITCBC | 304 | 18 | if (n1 > n2 || delta <= capacity() - curr_size) | 304 | 18 | if (n1 > n2 || delta <= capacity() - curr_size) | ||
| 305 | { | 305 | { | |||||
| HITCBC | 306 | 13 | const bool inside = detail::ptr_in_range(curr_data, curr_data + curr_size, s); | 306 | 13 | const bool inside = detail::ptr_in_range(curr_data, curr_data + curr_size, s); | ||
| 307 | // there is nothing to replace; return | 307 | // there is nothing to replace; return | |||||
| HITCBC | 308 | 13 | if (inside && s == curr_data + pos && n1 == n2) | 308 | 13 | if (inside && s == curr_data + pos && n1 == n2) | ||
| HITCBC | 309 | 1 | return; | 309 | 1 | return; | ||
| HITCBC | 310 | 12 | if (!inside || (inside && ((s - curr_data) + n2 <= pos))) | 310 | 12 | if (!inside || (inside && ((s - curr_data) + n2 <= pos))) | ||
| 311 | { | 311 | { | |||||
| 312 | // source outside | 312 | // source outside | |||||
| HITCBC | 313 | 6 | std::memmove(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1); | 313 | 6 | std::memmove(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1); | ||
| HITCBC | 314 | 6 | std::memcpy(&curr_data[pos], s, n2); | 314 | 6 | std::memcpy(&curr_data[pos], s, n2); | ||
| 315 | } | 315 | } | |||||
| 316 | else | 316 | else | |||||
| 317 | { | 317 | { | |||||
| 318 | // source inside | 318 | // source inside | |||||
| HITCBC | 319 | 6 | const std::size_t offset = s - curr_data; | 319 | 6 | const std::size_t offset = s - curr_data; | ||
| HITCBC | 320 | 6 | if (n2 >= n1) | 320 | 6 | if (n2 >= n1) | ||
| 321 | { | 321 | { | |||||
| 322 | // grow/unchanged | 322 | // grow/unchanged | |||||
| HITCBC | 323 | 4 | const std::size_t diff = offset <= pos + n1 ? (std::min)((pos + n1) - offset, n2) : 0; | 323 | 4 | const std::size_t diff = offset <= pos + n1 ? (std::min)((pos + n1) - offset, n2) : 0; | ||
| 324 | // shift all right of splice point by n2 - n1 to the right | 324 | // shift all right of splice point by n2 - n1 to the right | |||||
| HITCBC | 325 | 4 | std::memmove(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1); | 325 | 4 | std::memmove(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1); | ||
| 326 | // copy all before splice point | 326 | // copy all before splice point | |||||
| HITCBC | 327 | 4 | std::memmove(&curr_data[pos], &curr_data[offset], diff); | 327 | 4 | std::memmove(&curr_data[pos], &curr_data[offset], diff); | ||
| 328 | // copy all after splice point | 328 | // copy all after splice point | |||||
| HITCBC | 329 | 4 | std::memmove(&curr_data[pos + diff], &curr_data[(offset - n1) + n2 + diff], n2 - diff); | 329 | 4 | std::memmove(&curr_data[pos + diff], &curr_data[(offset - n1) + n2 + diff], n2 - diff); | ||
| 330 | } | 330 | } | |||||
| 331 | else | 331 | else | |||||
| 332 | { | 332 | { | |||||
| 333 | // shrink | 333 | // shrink | |||||
| 334 | // copy all elements into place | 334 | // copy all elements into place | |||||
| HITCBC | 335 | 2 | std::memmove(&curr_data[pos], &curr_data[offset], n2); | 335 | 2 | std::memmove(&curr_data[pos], &curr_data[offset], n2); | ||
| 336 | // shift all elements after splice point left | 336 | // shift all elements after splice point left | |||||
| HITCBC | 337 | 2 | std::memmove(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1); | 337 | 2 | std::memmove(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1); | ||
| 338 | } | 338 | } | |||||
| 339 | } | 339 | } | |||||
| HITCBC | 340 | 12 | size((curr_size - n1) + n2); | 340 | 12 | size((curr_size - n1) + n2); | ||
| 341 | } | 341 | } | |||||
| 342 | else | 342 | else | |||||
| 343 | { | 343 | { | |||||
| HITCBC | 344 | 5 | if (delta > max_size() - curr_size) | 344 | 5 | if (delta > max_size() - curr_size) | ||
| 345 | { | 345 | { | |||||
| 346 | BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; | 346 | BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; | |||||
| HITCBC | 347 | 1 | detail::throw_system_error( error::string_too_large, &loc ); | 347 | 1 | detail::throw_system_error( error::string_too_large, &loc ); | ||
| 348 | } | 348 | } | |||||
| 349 | // would exceed capacity, reallocate | 349 | // would exceed capacity, reallocate | |||||
| HITCBC | 350 | 4 | string_impl tmp(growth( | 350 | 4 | string_impl tmp(growth( | ||
| HITCBC | 351 | 4 | curr_size + delta, capacity()), sp); | 351 | 4 | curr_size + delta, capacity()), sp); | ||
| HITCBC | 352 | 2 | tmp.size(curr_size + delta); | 352 | 2 | tmp.size(curr_size + delta); | ||
| HITCBC | 353 | 2 | std::memcpy( | 353 | 2 | std::memcpy( | ||
| HITCBC | 354 | 2 | tmp.data(), | 354 | 2 | tmp.data(), | ||
| 355 | curr_data, | 355 | curr_data, | |||||
| 356 | pos); | 356 | pos); | |||||
| HITCBC | 357 | 4 | std::memcpy( | 357 | 4 | std::memcpy( | ||
| HITCBC | 358 | 4 | tmp.data() + pos + n2, | 358 | 4 | tmp.data() + pos + n2, | ||
| HITCBC | 359 | 2 | curr_data + pos + n1, | 359 | 2 | curr_data + pos + n1, | ||
| HITCBC | 360 | 2 | curr_size - pos - n1 + 1); | 360 | 2 | curr_size - pos - n1 + 1); | ||
| HITCBC | 361 | 4 | std::memcpy( | 361 | 4 | std::memcpy( | ||
| HITCBC | 362 | 2 | tmp.data() + pos, | 362 | 2 | tmp.data() + pos, | ||
| 363 | s, | 363 | s, | |||||
| 364 | n2); | 364 | n2); | |||||
| HITCBC | 365 | 2 | destroy(sp); | 365 | 2 | destroy(sp); | ||
| HITCBC | 366 | 2 | *this = tmp; | 366 | 2 | *this = tmp; | ||
| 367 | } | 367 | } | |||||
| 368 | } | 368 | } | |||||
| 369 | 369 | |||||||
| 370 | // unlike the replace overload, this function does | 370 | // unlike the replace overload, this function does | |||||
| 371 | // not move any characters | 371 | // not move any characters | |||||
| 372 | char* | 372 | char* | |||||
| HITCBC | 373 | 11 | string_impl:: | 373 | 11 | string_impl:: | ||
| 374 | replace_unchecked( | 374 | replace_unchecked( | |||||
| 375 | std::size_t pos, | 375 | std::size_t pos, | |||||
| 376 | std::size_t n1, | 376 | std::size_t n1, | |||||
| 377 | std::size_t n2, | 377 | std::size_t n2, | |||||
| 378 | storage_ptr const& sp) | 378 | storage_ptr const& sp) | |||||
| 379 | { | 379 | { | |||||
| HITCBC | 380 | 11 | const auto curr_size = size(); | 380 | 11 | const auto curr_size = size(); | ||
| HITCBC | 381 | 11 | if(pos > curr_size) | 381 | 11 | if(pos > curr_size) | ||
| 382 | { | 382 | { | |||||
| 383 | BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; | 383 | BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; | |||||
| HITCBC | 384 | 1 | detail::throw_system_error( error::out_of_range, &loc ); | 384 | 1 | detail::throw_system_error( error::out_of_range, &loc ); | ||
| 385 | } | 385 | } | |||||
| HITCBC | 386 | 10 | const auto curr_data = data(); | 386 | 10 | const auto curr_data = data(); | ||
| HITCBC | 387 | 10 | n1 = (std::min)(n1, curr_size - pos); | 387 | 10 | n1 = (std::min)(n1, curr_size - pos); | ||
| HITCBC | 388 | 10 | const auto delta = (std::max)(n1, n2) - | 388 | 10 | const auto delta = (std::max)(n1, n2) - | ||
| HITCBC | 389 | 10 | (std::min)(n1, n2); | 389 | 10 | (std::min)(n1, n2); | ||
| 390 | // if the size doesn't change, we don't need to | 390 | // if the size doesn't change, we don't need to | |||||
| 391 | // do anything | 391 | // do anything | |||||
| HITCBC | 392 | 10 | if (!delta) | 392 | 10 | if (!delta) | ||
| HITCBC | 393 | 1 | return curr_data + pos; | 393 | 1 | return curr_data + pos; | ||
| 394 | // if we are shrinking in size or we have enough | 394 | // if we are shrinking in size or we have enough | |||||
| 395 | // capacity, dont reallocate | 395 | // capacity, dont reallocate | |||||
| HITCBC | 396 | 9 | if(n1 > n2 || delta <= capacity() - curr_size) | 396 | 9 | if(n1 > n2 || delta <= capacity() - curr_size) | ||
| 397 | { | 397 | { | |||||
| HITCBC | 398 | 4 | auto const replace_pos = curr_data + pos; | 398 | 4 | auto const replace_pos = curr_data + pos; | ||
| HITCBC | 399 | 4 | std::memmove( | 399 | 4 | std::memmove( | ||
| HITCBC | 400 | 4 | replace_pos + n2, | 400 | 4 | replace_pos + n2, | ||
| HITCBC | 401 | 4 | replace_pos + n1, | 401 | 4 | replace_pos + n1, | ||
| HITCBC | 402 | 4 | curr_size - pos - n1 + 1); | 402 | 4 | curr_size - pos - n1 + 1); | ||
| HITCBC | 403 | 4 | size((curr_size - n1) + n2); | 403 | 4 | size((curr_size - n1) + n2); | ||
| HITCBC | 404 | 4 | return replace_pos; | 404 | 4 | return replace_pos; | ||
| 405 | } | 405 | } | |||||
| HITCBC | 406 | 5 | if(delta > max_size() - curr_size) | 406 | 5 | if(delta > max_size() - curr_size) | ||
| 407 | { | 407 | { | |||||
| 408 | BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; | 408 | BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; | |||||
| HITCBC | 409 | 1 | detail::throw_system_error( error::string_too_large, &loc ); | 409 | 1 | detail::throw_system_error( error::string_too_large, &loc ); | ||
| 410 | } | 410 | } | |||||
| 411 | // would exceed capacity, reallocate | 411 | // would exceed capacity, reallocate | |||||
| HITCBC | 412 | 4 | string_impl tmp(growth( | 412 | 4 | string_impl tmp(growth( | ||
| HITCBC | 413 | 4 | curr_size + delta, capacity()), sp); | 413 | 4 | curr_size + delta, capacity()), sp); | ||
| HITCBC | 414 | 2 | tmp.size(curr_size + delta); | 414 | 2 | tmp.size(curr_size + delta); | ||
| HITCBC | 415 | 2 | std::memcpy( | 415 | 2 | std::memcpy( | ||
| HITCBC | 416 | 2 | tmp.data(), | 416 | 2 | tmp.data(), | ||
| 417 | curr_data, | 417 | curr_data, | |||||
| 418 | pos); | 418 | pos); | |||||
| HITCBC | 419 | 4 | std::memcpy( | 419 | 4 | std::memcpy( | ||
| HITCBC | 420 | 4 | tmp.data() + pos + n2, | 420 | 4 | tmp.data() + pos + n2, | ||
| HITCBC | 421 | 2 | curr_data + pos + n1, | 421 | 2 | curr_data + pos + n1, | ||
| HITCBC | 422 | 2 | curr_size - pos - n1 + 1); | 422 | 2 | curr_size - pos - n1 + 1); | ||
| HITCBC | 423 | 2 | destroy(sp); | 423 | 2 | destroy(sp); | ||
| HITCBC | 424 | 2 | *this = tmp; | 424 | 2 | *this = tmp; | ||
| HITCBC | 425 | 2 | return data() + pos; | 425 | 2 | return data() + pos; | ||
| 426 | } | 426 | } | |||||
| 427 | 427 | |||||||
| 428 | void | 428 | void | |||||
| HITCBC | 429 | 7 | string_impl:: | 429 | 7 | string_impl:: | ||
| 430 | shrink_to_fit( | 430 | shrink_to_fit( | |||||
| 431 | storage_ptr const& sp) noexcept | 431 | storage_ptr const& sp) noexcept | |||||
| 432 | { | 432 | { | |||||
| HITCBC | 433 | 7 | if(s_.k == short_string_) | 433 | 7 | if(s_.k == short_string_) | ||
| HITCBC | 434 | 3 | return; | 434 | 3 | return; | ||
| HITCBC | 435 | 4 | auto const t = p_.t; | 435 | 4 | auto const t = p_.t; | ||
| HITCBC | 436 | 4 | if(t->size <= sbo_chars_) | 436 | 4 | if(t->size <= sbo_chars_) | ||
| 437 | { | 437 | { | |||||
| HITCBC | 438 | 2 | s_.k = short_string_; | 438 | 2 | s_.k = short_string_; | ||
| HITCBC | 439 | 4 | std::memcpy( | 439 | 4 | std::memcpy( | ||
| HITCBC | 440 | 2 | s_.buf, data(), t->size); | 440 | 2 | s_.buf, data(), t->size); | ||
| HITCBC | 441 | 2 | s_.buf[sbo_chars_] = | 441 | 2 | s_.buf[sbo_chars_] = | ||
| 442 | static_cast<char>( | 442 | static_cast<char>( | |||||
| HITCBC | 443 | 2 | sbo_chars_ - t->size); | 443 | 2 | sbo_chars_ - t->size); | ||
| HITCBC | 444 | 2 | s_.buf[t->size] = 0; | 444 | 2 | s_.buf[t->size] = 0; | ||
| HITCBC | 445 | 2 | sp->deallocate(t, | 445 | 2 | sp->deallocate(t, | ||
| 446 | sizeof(table) + | 446 | sizeof(table) + | |||||
| HITCBC | 447 | 2 | t->capacity + 1, | 447 | 2 | t->capacity + 1, | ||
| 448 | alignof(table)); | 448 | alignof(table)); | |||||
| HITCBC | 449 | 2 | return; | 449 | 2 | return; | ||
| 450 | } | 450 | } | |||||
| HITCBC | 451 | 2 | if(t->size >= t->capacity) | 451 | 2 | if(t->size >= t->capacity) | ||
| MISUBC | 452 | ✗ | return; | 452 | ✗ | return; | ||
| 453 | #ifndef BOOST_NO_EXCEPTIONS | 453 | #ifndef BOOST_NO_EXCEPTIONS | |||||
| 454 | try | 454 | try | |||||
| 455 | { | 455 | { | |||||
| 456 | #endif | 456 | #endif | |||||
| HITCBC | 457 | 2 | string_impl tmp(t->size, sp); | 457 | 2 | string_impl tmp(t->size, sp); | ||
| HITCBC | 458 | 1 | std::memcpy( | 458 | 1 | std::memcpy( | ||
| HITCBC | 459 | 1 | tmp.data(), | 459 | 1 | tmp.data(), | ||
| HITCBC | 460 | 1 | data(), | 460 | 1 | data(), | ||
| 461 | size()); | 461 | size()); | |||||
| HITCBC | 462 | 1 | destroy(sp); | 462 | 1 | destroy(sp); | ||
| HITCBC | 463 | 1 | *this = tmp; | 463 | 1 | *this = tmp; | ||
| 464 | #ifndef BOOST_NO_EXCEPTIONS | 464 | #ifndef BOOST_NO_EXCEPTIONS | |||||
| 465 | } | 465 | } | |||||
| HITCBC | 466 | 1 | catch(std::exception const&) | 466 | 1 | catch(std::exception const&) | ||
| 467 | { | 467 | { | |||||
| 468 | // eat the exception | 468 | // eat the exception | |||||
| HITCBC | 469 | 1 | } | 469 | 1 | } | ||
| 470 | #endif | 470 | #endif | |||||
| 471 | } | 471 | } | |||||
| 472 | 472 | |||||||
| 473 | } // detail | 473 | } // detail | |||||
| 474 | } // namespace json | 474 | } // namespace json | |||||
| 475 | } // namespace boost | 475 | } // namespace boost | |||||
| 476 | 476 | |||||||
| 477 | #endif | 477 | #endif | |||||