1  
//
1  
//
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3  
//
3  
//
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
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)
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
//
6  
//
7  
// Official repository: https://github.com/boostorg/json
7  
// Official repository: https://github.com/boostorg/json
8  
//
8  
//
9  

9  

10  
#ifndef BOOST_JSON_IMPL_STRING_IPP
10  
#ifndef BOOST_JSON_IMPL_STRING_IPP
11  
#define BOOST_JSON_IMPL_STRING_IPP
11  
#define BOOST_JSON_IMPL_STRING_IPP
12  

12  

13  
#include <boost/json/detail/except.hpp>
13  
#include <boost/json/detail/except.hpp>
14  
#include <algorithm>
14  
#include <algorithm>
15  
#include <new>
15  
#include <new>
16  
#include <ostream>
16  
#include <ostream>
17  
#include <stdexcept>
17  
#include <stdexcept>
18  
#include <string>
18  
#include <string>
19  
#include <utility>
19  
#include <utility>
20  

20  

21  
namespace boost {
21  
namespace boost {
22  
namespace json {
22  
namespace json {
23  

23  

24  
//----------------------------------------------------------
24  
//----------------------------------------------------------
25  
//
25  
//
26  
// Construction
26  
// Construction
27  
//
27  
//
28  
//----------------------------------------------------------
28  
//----------------------------------------------------------
29  

29  

30  
string::
30  
string::
31  
string(
31  
string(
32  
    std::size_t count,
32  
    std::size_t count,
33  
    char ch,
33  
    char ch,
34  
    storage_ptr sp)
34  
    storage_ptr sp)
35  
    : sp_(std::move(sp))
35  
    : sp_(std::move(sp))
36  
{
36  
{
37  
    assign(count, ch);
37  
    assign(count, ch);
38  
}
38  
}
39  

39  

40  
string::
40  
string::
41  
string(
41  
string(
42  
    char const* s,
42  
    char const* s,
43  
    storage_ptr sp)
43  
    storage_ptr sp)
44  
    : sp_(std::move(sp))
44  
    : sp_(std::move(sp))
45  
{
45  
{
46  
    assign(s);
46  
    assign(s);
47  
}
47  
}
48  

48  

49  
string::
49  
string::
50  
string(
50  
string(
51  
    char const* s,
51  
    char const* s,
52  
    std::size_t count,
52  
    std::size_t count,
53  
    storage_ptr sp)
53  
    storage_ptr sp)
54  
    : sp_(std::move(sp))
54  
    : sp_(std::move(sp))
55  
{
55  
{
56  
    assign(s, count);
56  
    assign(s, count);
57  
}
57  
}
58  

58  

59  
string::
59  
string::
60  
string(string const& other)
60  
string(string const& other)
61  
    : sp_(other.sp_)
61  
    : sp_(other.sp_)
62  
{
62  
{
63  
    assign(other);
63  
    assign(other);
64  
}
64  
}
65  

65  

66  
string::
66  
string::
67  
string(
67  
string(
68  
    string const& other,
68  
    string const& other,
69  
    storage_ptr sp)
69  
    storage_ptr sp)
70  
    : sp_(std::move(sp))
70  
    : sp_(std::move(sp))
71  
{
71  
{
72  
    assign(other);
72  
    assign(other);
73  
}
73  
}
74  

74  

75  
string::
75  
string::
76  
string(
76  
string(
77  
    string&& other,
77  
    string&& other,
78  
    storage_ptr sp)
78  
    storage_ptr sp)
79  
    : sp_(std::move(sp))
79  
    : sp_(std::move(sp))
80  
{
80  
{
81  
    assign(std::move(other));
81  
    assign(std::move(other));
82  
}
82  
}
83  

83  

84  
string::
84  
string::
85  
string(
85  
string(
86  
    string_view s,
86  
    string_view s,
87  
    storage_ptr sp)
87  
    storage_ptr sp)
88  
    : sp_(std::move(sp))
88  
    : sp_(std::move(sp))
89  
{
89  
{
90  
    assign(s);
90  
    assign(s);
91  
}
91  
}
92  

92  

93  
//----------------------------------------------------------
93  
//----------------------------------------------------------
94  
//
94  
//
95  
// Assignment
95  
// Assignment
96  
//
96  
//
97  
//----------------------------------------------------------
97  
//----------------------------------------------------------
98  

98  

99  
string&
99  
string&
100  
string::
100  
string::
101  
operator=(string const& other)
101  
operator=(string const& other)
102  
{
102  
{
103  
    return assign(other);
103  
    return assign(other);
104  
}
104  
}
105  

105  

106  
string&
106  
string&
107  
string::
107  
string::
108  
operator=(string&& other)
108  
operator=(string&& other)
109  
{
109  
{
110  
    return assign(std::move(other));
110  
    return assign(std::move(other));
111  
}
111  
}
112  

112  

113  
string&
113  
string&
114  
string::
114  
string::
115  
operator=(char const* s)
115  
operator=(char const* s)
116  
{
116  
{
117  
    return assign(s);
117  
    return assign(s);
118  
}
118  
}
119  

119  

120  
string&
120  
string&
121  
string::
121  
string::
122  
operator=(string_view s)
122  
operator=(string_view s)
123  
{
123  
{
124  
    return assign(s);
124  
    return assign(s);
125  
}
125  
}
126  

126  

127  

127  

128  

128  

129  
string&
129  
string&
130  
string::
130  
string::
131  
assign(
131  
assign(
132  
    size_type count,
132  
    size_type count,
133  
    char ch)
133  
    char ch)
134  
{
134  
{
135  
    std::char_traits<char>::assign(
135  
    std::char_traits<char>::assign(
136  
        impl_.assign(count, sp_),
136  
        impl_.assign(count, sp_),
137  
        count,
137  
        count,
138  
        ch);
138  
        ch);
139  
    return *this;
139  
    return *this;
140  
}
140  
}
141  

141  

142  
string&
142  
string&
143  
string::
143  
string::
144  
assign(
144  
assign(
145  
    string const& other)
145  
    string const& other)
146  
{
146  
{
147  
    if(this == &other)
147  
    if(this == &other)
148  
        return *this;
148  
        return *this;
149  
    return assign(
149  
    return assign(
150  
        other.data(),
150  
        other.data(),
151  
        other.size());
151  
        other.size());
152  
}
152  
}
153  

153  

154  
string&
154  
string&
155  
string::
155  
string::
156  
assign(string&& other)
156  
assign(string&& other)
157  
{
157  
{
158  
    if( &other == this )
158  
    if( &other == this )
159  
        return *this;
159  
        return *this;
160  

160  

161  
    if(*sp_ == *other.sp_)
161  
    if(*sp_ == *other.sp_)
162  
    {
162  
    {
163  
        impl_.destroy(sp_);
163  
        impl_.destroy(sp_);
164  
        impl_ = other.impl_;
164  
        impl_ = other.impl_;
165  
        ::new(&other.impl_) detail::string_impl();
165  
        ::new(&other.impl_) detail::string_impl();
166  
        return *this;
166  
        return *this;
167  
    }
167  
    }
168  

168  

169  
    // copy
169  
    // copy
170  
    return assign(other);
170  
    return assign(other);
171  
}
171  
}
172  

172  

173  
string&
173  
string&
174  
string::
174  
string::
175  
assign(
175  
assign(
176  
    char const* s,
176  
    char const* s,
177  
    size_type count)
177  
    size_type count)
178  
{
178  
{
179  
    std::char_traits<char>::copy(
179  
    std::char_traits<char>::copy(
180  
        impl_.assign(count, sp_),
180  
        impl_.assign(count, sp_),
181  
        s, count);
181  
        s, count);
182  
    return *this;
182  
    return *this;
183  
}
183  
}
184  

184  

185  
string&
185  
string&
186  
string::
186  
string::
187  
assign(
187  
assign(
188  
    char const* s)
188  
    char const* s)
189  
{
189  
{
190  
    return assign(s, std::char_traits<
190  
    return assign(s, std::char_traits<
191  
        char>::length(s));
191  
        char>::length(s));
192  
}
192  
}
193  

193  

194  
//----------------------------------------------------------
194  
//----------------------------------------------------------
195  
//
195  
//
196  
// Capacity
196  
// Capacity
197  
//
197  
//
198  
//----------------------------------------------------------
198  
//----------------------------------------------------------
199  

199  

200  
void
200  
void
201  
string::
201  
string::
202  
shrink_to_fit()
202  
shrink_to_fit()
203  
{
203  
{
204  
    impl_.shrink_to_fit(sp_);
204  
    impl_.shrink_to_fit(sp_);
205  
}
205  
}
206  

206  

207  
//----------------------------------------------------------
207  
//----------------------------------------------------------
208  
//
208  
//
209  
// Access
209  
// Access
210  
//
210  
//
211  
//----------------------------------------------------------
211  
//----------------------------------------------------------
212  

212  

213  
system::result<char&>
213  
system::result<char&>
214  
string::try_at(std::size_t pos) noexcept
214  
string::try_at(std::size_t pos) noexcept
215  
{
215  
{
216  
    if( pos < size() )
216  
    if( pos < size() )
217  
        return impl_.data()[pos];
217  
        return impl_.data()[pos];
218  

218  

219  
    system::error_code ec;
219  
    system::error_code ec;
220  
    BOOST_JSON_FAIL(ec, error::out_of_range);
220  
    BOOST_JSON_FAIL(ec, error::out_of_range);
221  
    return ec;
221  
    return ec;
222  
}
222  
}
223  

223  

224  
system::result<char const&>
224  
system::result<char const&>
225  
string::try_at(std::size_t pos) const noexcept
225  
string::try_at(std::size_t pos) const noexcept
226  
{
226  
{
227  
    if( pos < size() )
227  
    if( pos < size() )
228  
        return impl_.data()[pos];
228  
        return impl_.data()[pos];
229  

229  

230  
    system::error_code ec;
230  
    system::error_code ec;
231  
    BOOST_JSON_FAIL(ec, error::out_of_range);
231  
    BOOST_JSON_FAIL(ec, error::out_of_range);
232  
    return ec;
232  
    return ec;
233  
}
233  
}
234  

234  

235  
char const&
235  
char const&
236  
string::at(std::size_t pos, source_location const& loc) const
236  
string::at(std::size_t pos, source_location const& loc) const
237  
{
237  
{
238  
    return try_at(pos).value(loc);
238  
    return try_at(pos).value(loc);
239  
}
239  
}
240  

240  

241  
//----------------------------------------------------------
241  
//----------------------------------------------------------
242  
//
242  
//
243  
// Operations
243  
// Operations
244  
//
244  
//
245  
//----------------------------------------------------------
245  
//----------------------------------------------------------
246  

246  

247  
void
247  
void
248  
string::
248  
string::
249  
clear() noexcept
249  
clear() noexcept
250  
{
250  
{
251  
    impl_.term(0);
251  
    impl_.term(0);
252  
}
252  
}
253  

253  

254  
//----------------------------------------------------------
254  
//----------------------------------------------------------
255  

255  

256  
void
256  
void
257  
string::
257  
string::
258  
push_back(char ch)
258  
push_back(char ch)
259  
{
259  
{
260  
    *impl_.append(1, sp_) = ch;
260  
    *impl_.append(1, sp_) = ch;
261  
}
261  
}
262  

262  

263  
void
263  
void
264  
string::
264  
string::
265  
pop_back()
265  
pop_back()
266  
{
266  
{
267  
    back() = 0;
267  
    back() = 0;
268  
    impl_.size(impl_.size() - 1);
268  
    impl_.size(impl_.size() - 1);
269  
}
269  
}
270  

270  

271  
//----------------------------------------------------------
271  
//----------------------------------------------------------
272  

272  

273  
string&
273  
string&
274  
string::
274  
string::
275  
append(size_type count, char ch)
275  
append(size_type count, char ch)
276  
{
276  
{
277  
    std::char_traits<char>::assign(
277  
    std::char_traits<char>::assign(
278  
        impl_.append(count, sp_),
278  
        impl_.append(count, sp_),
279  
        count, ch);
279  
        count, ch);
280  
    return *this;
280  
    return *this;
281  
}
281  
}
282  

282  

283  
string&
283  
string&
284  
string::
284  
string::
285  
append(string_view sv)
285  
append(string_view sv)
286  
{
286  
{
287  
    std::char_traits<char>::copy(
287  
    std::char_traits<char>::copy(
288  
        impl_.append(sv.size(), sp_),
288  
        impl_.append(sv.size(), sp_),
289  
        sv.data(), sv.size());
289  
        sv.data(), sv.size());
290  
    return *this;
290  
    return *this;
291  
}
291  
}
292  

292  

293  
//----------------------------------------------------------
293  
//----------------------------------------------------------
294  

294  

295  
string&
295  
string&
296  
string::
296  
string::
297  
insert(
297  
insert(
298  
    size_type pos,
298  
    size_type pos,
299  
    string_view sv)
299  
    string_view sv)
300  
{
300  
{
301  
    impl_.insert(pos, sv.data(), sv.size(), sp_);
301  
    impl_.insert(pos, sv.data(), sv.size(), sp_);
302  
    return *this;
302  
    return *this;
303  
}
303  
}
304  

304  

305  
string&
305  
string&
306  
string::
306  
string::
307  
insert(
307  
insert(
308  
    std::size_t pos,
308  
    std::size_t pos,
309  
    std::size_t count,
309  
    std::size_t count,
310  
    char ch)
310  
    char ch)
311  
{
311  
{
312  
    std::char_traits<char>::assign(
312  
    std::char_traits<char>::assign(
313  
        impl_.insert_unchecked(pos, count, sp_),
313  
        impl_.insert_unchecked(pos, count, sp_),
314  
        count, ch);
314  
        count, ch);
315  
    return *this;
315  
    return *this;
316  
}
316  
}
317  

317  

318  
//----------------------------------------------------------
318  
//----------------------------------------------------------
319  

319  

320  
string&
320  
string&
321  
string::
321  
string::
322  
replace(
322  
replace(
323  
    std::size_t pos,
323  
    std::size_t pos,
324  
    std::size_t count,
324  
    std::size_t count,
325  
    string_view sv)
325  
    string_view sv)
326  
{
326  
{
327  
    impl_.replace(pos, count, sv.data(), sv.size(), sp_);
327  
    impl_.replace(pos, count, sv.data(), sv.size(), sp_);
328  
    return *this;
328  
    return *this;
329  
}
329  
}
330  

330  

331  
string&
331  
string&
332  
string::
332  
string::
333  
replace(
333  
replace(
334  
    std::size_t pos,
334  
    std::size_t pos,
335  
    std::size_t count,
335  
    std::size_t count,
336  
    std::size_t count2,
336  
    std::size_t count2,
337  
    char ch)
337  
    char ch)
338  
{
338  
{
339  
    std::char_traits<char>::assign(
339  
    std::char_traits<char>::assign(
340  
        impl_.replace_unchecked(pos, count, count2, sp_),
340  
        impl_.replace_unchecked(pos, count, count2, sp_),
341  
        count2, ch);
341  
        count2, ch);
342  
    return *this;
342  
    return *this;
343  
}
343  
}
344  

344  

345  
//----------------------------------------------------------
345  
//----------------------------------------------------------
346  

346  

347  
string&
347  
string&
348  
string::
348  
string::
349  
erase(
349  
erase(
350  
    size_type pos,
350  
    size_type pos,
351  
    size_type count)
351  
    size_type count)
352  
{
352  
{
353  
    if(pos > impl_.size())
353  
    if(pos > impl_.size())
354  
    {
354  
    {
355  
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
355  
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
356  
        detail::throw_system_error( error::out_of_range, &loc );
356  
        detail::throw_system_error( error::out_of_range, &loc );
357  
    }
357  
    }
358  
    if( count > impl_.size() - pos)
358  
    if( count > impl_.size() - pos)
359  
        count = impl_.size() - pos;
359  
        count = impl_.size() - pos;
360  
    std::char_traits<char>::move(
360  
    std::char_traits<char>::move(
361  
        impl_.data() + pos,
361  
        impl_.data() + pos,
362  
        impl_.data() + pos + count,
362  
        impl_.data() + pos + count,
363  
        impl_.size() - pos - count + 1);
363  
        impl_.size() - pos - count + 1);
364  
    impl_.term(impl_.size() - count);
364  
    impl_.term(impl_.size() - count);
365  
    return *this;
365  
    return *this;
366  
}
366  
}
367  

367  

368  
auto
368  
auto
369  
string::
369  
string::
370  
erase(const_iterator pos) ->
370  
erase(const_iterator pos) ->
371  
    iterator
371  
    iterator
372  
{
372  
{
373  
    return erase(pos, pos+1);
373  
    return erase(pos, pos+1);
374  
}
374  
}
375  

375  

376  
auto
376  
auto
377  
string::
377  
string::
378  
erase(
378  
erase(
379  
    const_iterator first,
379  
    const_iterator first,
380  
    const_iterator last) ->
380  
    const_iterator last) ->
381  
        iterator
381  
        iterator
382  
{
382  
{
383  
    auto const pos = first - begin();
383  
    auto const pos = first - begin();
384  
    auto const count = last - first;
384  
    auto const count = last - first;
385  
    erase(pos, count);
385  
    erase(pos, count);
386  
    return data() + pos;
386  
    return data() + pos;
387  
}
387  
}
388  

388  

389  
//----------------------------------------------------------
389  
//----------------------------------------------------------
390  

390  

391  
void
391  
void
392  
string::
392  
string::
393  
resize(size_type count, char ch)
393  
resize(size_type count, char ch)
394  
{
394  
{
395  
    if(count <= impl_.size())
395  
    if(count <= impl_.size())
396  
    {
396  
    {
397  
        impl_.term(count);
397  
        impl_.term(count);
398  
        return;
398  
        return;
399  
    }
399  
    }
400  

400  

401  
    reserve(count);
401  
    reserve(count);
402  
    std::char_traits<char>::assign(
402  
    std::char_traits<char>::assign(
403  
        impl_.end(),
403  
        impl_.end(),
404  
        count - impl_.size(),
404  
        count - impl_.size(),
405  
        ch);
405  
        ch);
406  
    grow(count - size());
406  
    grow(count - size());
407  
}
407  
}
408  

408  

409  
//----------------------------------------------------------
409  
//----------------------------------------------------------
410  

410  

411  
void
411  
void
412  
string::
412  
string::
413  
swap(string& other)
413  
swap(string& other)
414  
{
414  
{
415  
    if(*sp_ == *other.sp_)
415  
    if(*sp_ == *other.sp_)
416  
    {
416  
    {
417  
        std::swap(impl_, other.impl_);
417  
        std::swap(impl_, other.impl_);
418  
        return;
418  
        return;
419  
    }
419  
    }
420  
    string temp1(
420  
    string temp1(
421  
        std::move(*this), other.sp_);
421  
        std::move(*this), other.sp_);
422  
    string temp2(
422  
    string temp2(
423  
        std::move(other), sp_);
423  
        std::move(other), sp_);
424  
    this->~string();
424  
    this->~string();
425  
    ::new(this) string(pilfer(temp2));
425  
    ::new(this) string(pilfer(temp2));
426  
    other.~string();
426  
    other.~string();
427  
    ::new(&other) string(pilfer(temp1));
427  
    ::new(&other) string(pilfer(temp1));
428  
}
428  
}
429  

429  

430  
//----------------------------------------------------------
430  
//----------------------------------------------------------
431  

431  

432  
void
432  
void
433  
string::
433  
string::
434  
reserve_impl(size_type new_cap)
434  
reserve_impl(size_type new_cap)
435  
{
435  
{
436  
    BOOST_ASSERT(
436  
    BOOST_ASSERT(
437  
        new_cap >= impl_.capacity());
437  
        new_cap >= impl_.capacity());
438  
    if(new_cap > impl_.capacity())
438  
    if(new_cap > impl_.capacity())
439  
    {
439  
    {
440  
        // grow
440  
        // grow
441  
        new_cap = detail::string_impl::growth(
441  
        new_cap = detail::string_impl::growth(
442  
            new_cap, impl_.capacity());
442  
            new_cap, impl_.capacity());
443  
        detail::string_impl tmp(new_cap, sp_);
443  
        detail::string_impl tmp(new_cap, sp_);
444  
        std::char_traits<char>::copy(tmp.data(),
444  
        std::char_traits<char>::copy(tmp.data(),
445  
            impl_.data(), impl_.size() + 1);
445  
            impl_.data(), impl_.size() + 1);
446  
        tmp.size(impl_.size());
446  
        tmp.size(impl_.size());
447  
        impl_.destroy(sp_);
447  
        impl_.destroy(sp_);
448  
        impl_ = tmp;
448  
        impl_ = tmp;
449  
        return;
449  
        return;
450  
    }
450  
    }
451  
}
451  
}
452  

452  

453  
} // namespace json
453  
} // namespace json
454  
} // namespace boost
454  
} // namespace boost
455  

455  

456  
//----------------------------------------------------------
456  
//----------------------------------------------------------
457  

457  

458  
std::size_t
458  
std::size_t
459  
std::hash< ::boost::json::string >::operator()(
459  
std::hash< ::boost::json::string >::operator()(
460  
    ::boost::json::string const& js ) const noexcept
460  
    ::boost::json::string const& js ) const noexcept
461  
{
461  
{
462  
    return ::boost::hash< ::boost::json::string >()( js );
462  
    return ::boost::hash< ::boost::json::string >()( js );
463  
}
463  
}
464  

464  

465  
#endif
465  
#endif