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_HPP
10  
#ifndef BOOST_JSON_IMPL_STRING_HPP
11  
#define BOOST_JSON_IMPL_STRING_HPP
11  
#define BOOST_JSON_IMPL_STRING_HPP
12  

12  

13  
#include <utility>
13  
#include <utility>
14  

14  

15  
namespace boost {
15  
namespace boost {
16  
namespace json {
16  
namespace json {
17  

17  

18  
string::
18  
string::
19  
string(
19  
string(
20  
    detail::key_t const&,
20  
    detail::key_t const&,
21  
    string_view s,
21  
    string_view s,
22  
    storage_ptr sp)
22  
    storage_ptr sp)
23  
    : sp_(std::move(sp))
23  
    : sp_(std::move(sp))
24  
    , impl_(detail::key_t{},
24  
    , impl_(detail::key_t{},
25  
        s, sp_)
25  
        s, sp_)
26  
{
26  
{
27  
}
27  
}
28  

28  

29  
string::
29  
string::
30  
string(
30  
string(
31  
    detail::key_t const&,
31  
    detail::key_t const&,
32  
    string_view s1,
32  
    string_view s1,
33  
    string_view s2,
33  
    string_view s2,
34  
    storage_ptr sp)
34  
    storage_ptr sp)
35  
    : sp_(std::move(sp))
35  
    : sp_(std::move(sp))
36  
    , impl_(detail::key_t{},
36  
    , impl_(detail::key_t{},
37  
        s1, s2, sp_)
37  
        s1, s2, sp_)
38  
{
38  
{
39  
}
39  
}
40  

40  

41  
template<class InputIt, class>
41  
template<class InputIt, class>
42  
string::
42  
string::
43  
string(
43  
string(
44  
    InputIt first,
44  
    InputIt first,
45  
    InputIt last,
45  
    InputIt last,
46  
    storage_ptr sp)
46  
    storage_ptr sp)
47  
    : sp_(std::move(sp))
47  
    : sp_(std::move(sp))
48  
    , impl_(first, last, sp_,
48  
    , impl_(first, last, sp_,
49  
        iter_cat<InputIt>{})
49  
        iter_cat<InputIt>{})
50  
{
50  
{
51  
}
51  
}
52  

52  

53  
template<class InputIt, class>
53  
template<class InputIt, class>
54  
string&
54  
string&
55  
string::
55  
string::
56  
assign(
56  
assign(
57  
    InputIt first,
57  
    InputIt first,
58  
    InputIt last)
58  
    InputIt last)
59  
{
59  
{
60  
    assign(first, last,
60  
    assign(first, last,
61  
        iter_cat<InputIt>{});
61  
        iter_cat<InputIt>{});
62  
    return *this;
62  
    return *this;
63  
}
63  
}
64  

64  

65  
template<class InputIt, class>
65  
template<class InputIt, class>
66  
string&
66  
string&
67  
string::
67  
string::
68  
append(InputIt first, InputIt last)
68  
append(InputIt first, InputIt last)
69  
{
69  
{
70  
    append(first, last,
70  
    append(first, last,
71  
        iter_cat<InputIt>{});
71  
        iter_cat<InputIt>{});
72  
    return *this;
72  
    return *this;
73  
}
73  
}
74  

74  

75  
// KRYSTIAN TODO: this can be done without copies when
75  
// KRYSTIAN TODO: this can be done without copies when
76  
// reallocation is not needed, when the iterator is a
76  
// reallocation is not needed, when the iterator is a
77  
// FowardIterator or better, as we can use std::distance
77  
// FowardIterator or better, as we can use std::distance
78  
template<class InputIt, class>
78  
template<class InputIt, class>
79  
auto
79  
auto
80  
string::
80  
string::
81  
insert(
81  
insert(
82  
    size_type pos,
82  
    size_type pos,
83  
    InputIt first,
83  
    InputIt first,
84  
    InputIt last) ->
84  
    InputIt last) ->
85  
        string&
85  
        string&
86  
{
86  
{
87  
    struct cleanup
87  
    struct cleanup
88  
    {
88  
    {
89  
        detail::string_impl& s;
89  
        detail::string_impl& s;
90  
        storage_ptr const& sp;
90  
        storage_ptr const& sp;
91  

91  

92  
        ~cleanup()
92  
        ~cleanup()
93  
        {
93  
        {
94  
            s.destroy(sp);
94  
            s.destroy(sp);
95  
        }
95  
        }
96  
    };
96  
    };
97  

97  

98  
    // We use the default storage because
98  
    // We use the default storage because
99  
    // the allocation is immediately freed.
99  
    // the allocation is immediately freed.
100  
    storage_ptr dsp;
100  
    storage_ptr dsp;
101  
    detail::string_impl tmp(
101  
    detail::string_impl tmp(
102  
        first, last, dsp,
102  
        first, last, dsp,
103  
        iter_cat<InputIt>{});
103  
        iter_cat<InputIt>{});
104  
    cleanup c{tmp, dsp};
104  
    cleanup c{tmp, dsp};
105  
    std::memcpy(
105  
    std::memcpy(
106  
        impl_.insert_unchecked(pos, tmp.size(), sp_),
106  
        impl_.insert_unchecked(pos, tmp.size(), sp_),
107  
        tmp.data(),
107  
        tmp.data(),
108  
        tmp.size());
108  
        tmp.size());
109  
    return *this;
109  
    return *this;
110  
}
110  
}
111  

111  

112  
// KRYSTIAN TODO: this can be done without copies when
112  
// KRYSTIAN TODO: this can be done without copies when
113  
// reallocation is not needed, when the iterator is a
113  
// reallocation is not needed, when the iterator is a
114  
// FowardIterator or better, as we can use std::distance
114  
// FowardIterator or better, as we can use std::distance
115  
template<class InputIt, class>
115  
template<class InputIt, class>
116  
auto
116  
auto
117  
string::
117  
string::
118  
replace(
118  
replace(
119  
    const_iterator first,
119  
    const_iterator first,
120  
    const_iterator last,
120  
    const_iterator last,
121  
    InputIt first2,
121  
    InputIt first2,
122  
    InputIt last2) ->
122  
    InputIt last2) ->
123  
        string&
123  
        string&
124  
{
124  
{
125  
    struct cleanup
125  
    struct cleanup
126  
    {
126  
    {
127  
        detail::string_impl& s;
127  
        detail::string_impl& s;
128  
        storage_ptr const& sp;
128  
        storage_ptr const& sp;
129  

129  

130  
        ~cleanup()
130  
        ~cleanup()
131  
        {
131  
        {
132  
            s.destroy(sp);
132  
            s.destroy(sp);
133  
        }
133  
        }
134  
    };
134  
    };
135  

135  

136  
    // We use the default storage because
136  
    // We use the default storage because
137  
    // the allocation is immediately freed.
137  
    // the allocation is immediately freed.
138  
    storage_ptr dsp;
138  
    storage_ptr dsp;
139  
    detail::string_impl tmp(
139  
    detail::string_impl tmp(
140  
        first2, last2, dsp,
140  
        first2, last2, dsp,
141  
        iter_cat<InputIt>{});
141  
        iter_cat<InputIt>{});
142  
    cleanup c{tmp, dsp};
142  
    cleanup c{tmp, dsp};
143  
    std::memcpy(
143  
    std::memcpy(
144  
        impl_.replace_unchecked(
144  
        impl_.replace_unchecked(
145  
            first - begin(),
145  
            first - begin(),
146  
            last - first,
146  
            last - first,
147  
            tmp.size(),
147  
            tmp.size(),
148  
            sp_),
148  
            sp_),
149  
        tmp.data(),
149  
        tmp.data(),
150  
        tmp.size());
150  
        tmp.size());
151  
    return *this;
151  
    return *this;
152  
}
152  
}
153  

153  

154  
//----------------------------------------------------------
154  
//----------------------------------------------------------
155  

155  

156  
template<class InputIt>
156  
template<class InputIt>
157  
void
157  
void
158  
string::
158  
string::
159  
assign(
159  
assign(
160  
    InputIt first,
160  
    InputIt first,
161  
    InputIt last,
161  
    InputIt last,
162  
    std::random_access_iterator_tag)
162  
    std::random_access_iterator_tag)
163  
{
163  
{
164  
    auto dest = impl_.assign(static_cast<
164  
    auto dest = impl_.assign(static_cast<
165  
        size_type>(last - first), sp_);
165  
        size_type>(last - first), sp_);
166  
    while(first != last)
166  
    while(first != last)
167  
        *dest++ = *first++;
167  
        *dest++ = *first++;
168  
}
168  
}
169  

169  

170  
template<class InputIt>
170  
template<class InputIt>
171  
void
171  
void
172  
string::
172  
string::
173  
assign(
173  
assign(
174  
    InputIt first,
174  
    InputIt first,
175  
    InputIt last,
175  
    InputIt last,
176  
    std::input_iterator_tag)
176  
    std::input_iterator_tag)
177  
{
177  
{
178  
    if(first == last)
178  
    if(first == last)
179  
    {
179  
    {
180  
        impl_.term(0);
180  
        impl_.term(0);
181  
        return;
181  
        return;
182  
    }
182  
    }
183  
    detail::string_impl tmp(
183  
    detail::string_impl tmp(
184  
        first, last, sp_,
184  
        first, last, sp_,
185  
        std::input_iterator_tag{});
185  
        std::input_iterator_tag{});
186  
    impl_.destroy(sp_);
186  
    impl_.destroy(sp_);
187  
    impl_ = tmp;
187  
    impl_ = tmp;
188  
}
188  
}
189  

189  

190  
template<class InputIt>
190  
template<class InputIt>
191  
void
191  
void
192  
string::
192  
string::
193  
append(
193  
append(
194  
    InputIt first,
194  
    InputIt first,
195  
    InputIt last,
195  
    InputIt last,
196  
    std::random_access_iterator_tag)
196  
    std::random_access_iterator_tag)
197  
{
197  
{
198  

198  

199  
    auto const n = static_cast<
199  
    auto const n = static_cast<
200  
        size_type>(last - first);
200  
        size_type>(last - first);
201  
    char* out = impl_.append(n, sp_);
201  
    char* out = impl_.append(n, sp_);
202  
#if defined(_MSC_VER) && _MSC_VER <= 1900
202  
#if defined(_MSC_VER) && _MSC_VER <= 1900
203  
    while( first != last )
203  
    while( first != last )
204  
        *out++ = *first++;
204  
        *out++ = *first++;
205  
#else
205  
#else
206  
    std::copy(first, last, out);
206  
    std::copy(first, last, out);
207  
#endif
207  
#endif
208  
}
208  
}
209  

209  

210  
template<class InputIt>
210  
template<class InputIt>
211  
void
211  
void
212  
string::
212  
string::
213  
append(
213  
append(
214  
    InputIt first,
214  
    InputIt first,
215  
    InputIt last,
215  
    InputIt last,
216  
    std::input_iterator_tag)
216  
    std::input_iterator_tag)
217  
{
217  
{
218  
    struct cleanup
218  
    struct cleanup
219  
    {
219  
    {
220  
        detail::string_impl& s;
220  
        detail::string_impl& s;
221  
        storage_ptr const& sp;
221  
        storage_ptr const& sp;
222  

222  

223  
        ~cleanup()
223  
        ~cleanup()
224  
        {
224  
        {
225  
            s.destroy(sp);
225  
            s.destroy(sp);
226  
        }
226  
        }
227  
    };
227  
    };
228  

228  

229  
    // We use the default storage because
229  
    // We use the default storage because
230  
    // the allocation is immediately freed.
230  
    // the allocation is immediately freed.
231  
    storage_ptr dsp;
231  
    storage_ptr dsp;
232  
    detail::string_impl tmp(
232  
    detail::string_impl tmp(
233  
        first, last, dsp,
233  
        first, last, dsp,
234  
        std::input_iterator_tag{});
234  
        std::input_iterator_tag{});
235  
    cleanup c{tmp, dsp};
235  
    cleanup c{tmp, dsp};
236  
    std::memcpy(
236  
    std::memcpy(
237  
        impl_.append(tmp.size(), sp_),
237  
        impl_.append(tmp.size(), sp_),
238  
        tmp.data(), tmp.size());
238  
        tmp.data(), tmp.size());
239  
}
239  
}
240  

240  

241  
char&
241  
char&
242  
string::at(std::size_t pos, source_location const& loc)
242  
string::at(std::size_t pos, source_location const& loc)
243  
{
243  
{
244  

244  

245  
    auto const& self = *this;
245  
    auto const& self = *this;
246  
    return const_cast< char& >( self.at(pos, loc) );
246  
    return const_cast< char& >( self.at(pos, loc) );
247  
}
247  
}
248  

248  

249  
} // namespace json
249  
} // namespace json
250  
} // namespace boost
250  
} // namespace boost
251  

251  

252  
#endif
252  
#endif