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/boostorg/json
8 : //
9 :
10 : #ifndef BOOST_JSON_IMPL_STRING_IPP
11 : #define BOOST_JSON_IMPL_STRING_IPP
12 :
13 : #include <boost/json/detail/except.hpp>
14 : #include <algorithm>
15 : #include <new>
16 : #include <ostream>
17 : #include <stdexcept>
18 : #include <string>
19 : #include <utility>
20 :
21 : namespace boost {
22 : namespace json {
23 :
24 : //----------------------------------------------------------
25 : //
26 : // Construction
27 : //
28 : //----------------------------------------------------------
29 :
30 78 : string::
31 : string(
32 : std::size_t count,
33 : char ch,
34 78 : storage_ptr sp)
35 78 : : sp_(std::move(sp))
36 : {
37 78 : assign(count, ch);
38 78 : }
39 :
40 203 : string::
41 : string(
42 : char const* s,
43 203 : storage_ptr sp)
44 203 : : sp_(std::move(sp))
45 : {
46 203 : assign(s);
47 203 : }
48 :
49 4 : string::
50 : string(
51 : char const* s,
52 : std::size_t count,
53 4 : storage_ptr sp)
54 4 : : sp_(std::move(sp))
55 : {
56 4 : assign(s, count);
57 4 : }
58 :
59 8 : string::
60 8 : string(string const& other)
61 8 : : sp_(other.sp_)
62 : {
63 8 : assign(other);
64 8 : }
65 :
66 151 : string::
67 : string(
68 : string const& other,
69 151 : storage_ptr sp)
70 151 : : sp_(std::move(sp))
71 : {
72 151 : assign(other);
73 151 : }
74 :
75 469 : string::
76 : string(
77 : string&& other,
78 469 : storage_ptr sp)
79 469 : : sp_(std::move(sp))
80 : {
81 469 : assign(std::move(other));
82 469 : }
83 :
84 17954 : string::
85 : string(
86 : string_view s,
87 17954 : storage_ptr sp)
88 17954 : : sp_(std::move(sp))
89 : {
90 17954 : assign(s);
91 17954 : }
92 :
93 : //----------------------------------------------------------
94 : //
95 : // Assignment
96 : //
97 : //----------------------------------------------------------
98 :
99 : string&
100 6 : string::
101 : operator=(string const& other)
102 : {
103 6 : return assign(other);
104 : }
105 :
106 : string&
107 10 : string::
108 : operator=(string&& other)
109 : {
110 10 : return assign(std::move(other));
111 : }
112 :
113 : string&
114 9 : string::
115 : operator=(char const* s)
116 : {
117 9 : return assign(s);
118 : }
119 :
120 : string&
121 8 : string::
122 : operator=(string_view s)
123 : {
124 8 : return assign(s);
125 : }
126 :
127 :
128 :
129 : string&
130 83 : string::
131 : assign(
132 : size_type count,
133 : char ch)
134 : {
135 64 : std::char_traits<char>::assign(
136 83 : impl_.assign(count, sp_),
137 : count,
138 : ch);
139 64 : return *this;
140 : }
141 :
142 : string&
143 199 : string::
144 : assign(
145 : string const& other)
146 : {
147 199 : if(this == &other)
148 1 : return *this;
149 198 : return assign(
150 : other.data(),
151 171 : other.size());
152 : }
153 :
154 : string&
155 493 : string::
156 : assign(string&& other)
157 : {
158 493 : if( &other == this )
159 1 : return *this;
160 :
161 492 : if(*sp_ == *other.sp_)
162 : {
163 458 : impl_.destroy(sp_);
164 458 : impl_ = other.impl_;
165 458 : ::new(&other.impl_) detail::string_impl();
166 458 : return *this;
167 : }
168 :
169 : // copy
170 34 : return assign(other);
171 : }
172 :
173 : string&
174 18525 : string::
175 : assign(
176 : char const* s,
177 : size_type count)
178 : {
179 18404 : std::char_traits<char>::copy(
180 18525 : impl_.assign(count, sp_),
181 : s, count);
182 18404 : return *this;
183 : }
184 :
185 : string&
186 217 : string::
187 : assign(
188 : char const* s)
189 : {
190 217 : return assign(s, std::char_traits<
191 214 : char>::length(s));
192 : }
193 :
194 : //----------------------------------------------------------
195 : //
196 : // Capacity
197 : //
198 : //----------------------------------------------------------
199 :
200 : void
201 7 : string::
202 : shrink_to_fit()
203 : {
204 7 : impl_.shrink_to_fit(sp_);
205 7 : }
206 :
207 : //----------------------------------------------------------
208 : //
209 : // Access
210 : //
211 : //----------------------------------------------------------
212 :
213 : system::result<char&>
214 12 : string::try_at(std::size_t pos) noexcept
215 : {
216 12 : if( pos < size() )
217 10 : return impl_.data()[pos];
218 :
219 2 : system::error_code ec;
220 2 : BOOST_JSON_FAIL(ec, error::out_of_range);
221 2 : return ec;
222 : }
223 :
224 : system::result<char const&>
225 20 : string::try_at(std::size_t pos) const noexcept
226 : {
227 20 : if( pos < size() )
228 18 : return impl_.data()[pos];
229 :
230 2 : system::error_code ec;
231 2 : BOOST_JSON_FAIL(ec, error::out_of_range);
232 2 : return ec;
233 : }
234 :
235 : char const&
236 18 : string::at(std::size_t pos, source_location const& loc) const
237 : {
238 18 : return try_at(pos).value(loc);
239 : }
240 :
241 : //----------------------------------------------------------
242 : //
243 : // Operations
244 : //
245 : //----------------------------------------------------------
246 :
247 : void
248 2 : string::
249 : clear() noexcept
250 : {
251 2 : impl_.term(0);
252 2 : }
253 :
254 : //----------------------------------------------------------
255 :
256 : void
257 88 : string::
258 : push_back(char ch)
259 : {
260 88 : *impl_.append(1, sp_) = ch;
261 86 : }
262 :
263 : void
264 29 : string::
265 : pop_back()
266 : {
267 29 : back() = 0;
268 29 : impl_.size(impl_.size() - 1);
269 29 : }
270 :
271 : //----------------------------------------------------------
272 :
273 : string&
274 4 : string::
275 : append(size_type count, char ch)
276 : {
277 2 : std::char_traits<char>::assign(
278 4 : impl_.append(count, sp_),
279 : count, ch);
280 2 : return *this;
281 : }
282 :
283 : string&
284 45 : string::
285 : append(string_view sv)
286 : {
287 90 : std::char_traits<char>::copy(
288 45 : impl_.append(sv.size(), sp_),
289 : sv.data(), sv.size());
290 34 : return *this;
291 : }
292 :
293 : //----------------------------------------------------------
294 :
295 : string&
296 27 : string::
297 : insert(
298 : size_type pos,
299 : string_view sv)
300 : {
301 27 : impl_.insert(pos, sv.data(), sv.size(), sp_);
302 17 : return *this;
303 : }
304 :
305 : string&
306 11 : string::
307 : insert(
308 : std::size_t pos,
309 : std::size_t count,
310 : char ch)
311 : {
312 6 : std::char_traits<char>::assign(
313 11 : impl_.insert_unchecked(pos, count, sp_),
314 : count, ch);
315 6 : return *this;
316 : }
317 :
318 : //----------------------------------------------------------
319 :
320 : string&
321 19 : string::
322 : replace(
323 : std::size_t pos,
324 : std::size_t count,
325 : string_view sv)
326 : {
327 19 : impl_.replace(pos, count, sv.data(), sv.size(), sp_);
328 15 : return *this;
329 : }
330 :
331 : string&
332 7 : string::
333 : replace(
334 : std::size_t pos,
335 : std::size_t count,
336 : std::size_t count2,
337 : char ch)
338 : {
339 4 : std::char_traits<char>::assign(
340 7 : impl_.replace_unchecked(pos, count, count2, sp_),
341 : count2, ch);
342 4 : return *this;
343 : }
344 :
345 : //----------------------------------------------------------
346 :
347 : string&
348 10 : string::
349 : erase(
350 : size_type pos,
351 : size_type count)
352 : {
353 10 : if(pos > impl_.size())
354 : {
355 : BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
356 1 : detail::throw_system_error( error::out_of_range, &loc );
357 : }
358 9 : if( count > impl_.size() - pos)
359 4 : count = impl_.size() - pos;
360 9 : std::char_traits<char>::move(
361 9 : impl_.data() + pos,
362 9 : impl_.data() + pos + count,
363 9 : impl_.size() - pos - count + 1);
364 9 : impl_.term(impl_.size() - count);
365 9 : return *this;
366 : }
367 :
368 : auto
369 2 : string::
370 : erase(const_iterator pos) ->
371 : iterator
372 : {
373 2 : return erase(pos, pos+1);
374 : }
375 :
376 : auto
377 3 : string::
378 : erase(
379 : const_iterator first,
380 : const_iterator last) ->
381 : iterator
382 : {
383 3 : auto const pos = first - begin();
384 3 : auto const count = last - first;
385 3 : erase(pos, count);
386 3 : return data() + pos;
387 : }
388 :
389 : //----------------------------------------------------------
390 :
391 : void
392 66 : string::
393 : resize(size_type count, char ch)
394 : {
395 66 : if(count <= impl_.size())
396 : {
397 25 : impl_.term(count);
398 25 : return;
399 : }
400 :
401 41 : reserve(count);
402 35 : std::char_traits<char>::assign(
403 : impl_.end(),
404 35 : count - impl_.size(),
405 : ch);
406 35 : grow(count - size());
407 : }
408 :
409 : //----------------------------------------------------------
410 :
411 : void
412 4 : string::
413 : swap(string& other)
414 : {
415 4 : if(*sp_ == *other.sp_)
416 : {
417 3 : std::swap(impl_, other.impl_);
418 3 : return;
419 : }
420 : string temp1(
421 1 : std::move(*this), other.sp_);
422 : string temp2(
423 1 : std::move(other), sp_);
424 1 : this->~string();
425 1 : ::new(this) string(pilfer(temp2));
426 1 : other.~string();
427 1 : ::new(&other) string(pilfer(temp1));
428 1 : }
429 :
430 : //----------------------------------------------------------
431 :
432 : void
433 9686 : string::
434 : reserve_impl(size_type new_cap)
435 : {
436 9686 : BOOST_ASSERT(
437 : new_cap >= impl_.capacity());
438 9686 : if(new_cap > impl_.capacity())
439 : {
440 : // grow
441 9686 : new_cap = detail::string_impl::growth(
442 : new_cap, impl_.capacity());
443 9685 : detail::string_impl tmp(new_cap, sp_);
444 9675 : std::char_traits<char>::copy(tmp.data(),
445 9675 : impl_.data(), impl_.size() + 1);
446 9675 : tmp.size(impl_.size());
447 9675 : impl_.destroy(sp_);
448 9675 : impl_ = tmp;
449 9675 : return;
450 : }
451 : }
452 :
453 : } // namespace json
454 : } // namespace boost
455 :
456 : //----------------------------------------------------------
457 :
458 : std::size_t
459 3 : std::hash< ::boost::json::string >::operator()(
460 : ::boost::json::string const& js ) const noexcept
461 : {
462 3 : return ::boost::hash< ::boost::json::string >()( js );
463 : }
464 :
465 : #endif
|