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