]>
Commit | Line | Data |
---|---|---|
20effc67 TL |
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_HPP | |
11 | #define BOOST_JSON_IMPL_STRING_HPP | |
12 | ||
13 | #include <utility> | |
14 | ||
15 | BOOST_JSON_NS_BEGIN | |
16 | ||
17 | string:: | |
18 | string( | |
19 | detail::key_t const&, | |
20 | string_view s, | |
21 | storage_ptr sp) | |
22 | : sp_(std::move(sp)) | |
23 | , impl_(detail::key_t{}, | |
24 | s, sp_) | |
25 | { | |
26 | } | |
27 | ||
28 | string:: | |
29 | string( | |
30 | detail::key_t const&, | |
31 | string_view s1, | |
32 | string_view s2, | |
33 | storage_ptr sp) | |
34 | : sp_(std::move(sp)) | |
35 | , impl_(detail::key_t{}, | |
36 | s1, s2, sp_) | |
37 | { | |
38 | } | |
39 | ||
40 | template<class InputIt, class> | |
41 | string:: | |
42 | string( | |
43 | InputIt first, | |
44 | InputIt last, | |
45 | storage_ptr sp) | |
46 | : sp_(std::move(sp)) | |
47 | , impl_(first, last, sp_, | |
48 | iter_cat<InputIt>{}) | |
49 | { | |
50 | } | |
51 | ||
52 | template<class InputIt, class> | |
53 | string& | |
54 | string:: | |
55 | assign( | |
56 | InputIt first, | |
57 | InputIt last) | |
58 | { | |
59 | assign(first, last, | |
60 | iter_cat<InputIt>{}); | |
61 | return *this; | |
62 | } | |
63 | ||
64 | template<class InputIt, class> | |
65 | string& | |
66 | string:: | |
67 | append(InputIt first, InputIt last) | |
68 | { | |
69 | append(first, last, | |
70 | iter_cat<InputIt>{}); | |
71 | return *this; | |
72 | } | |
73 | ||
74 | // KRYSTIAN TODO: this can be done without copies when | |
1e59de90 | 75 | // reallocation is not needed, when the iterator is a |
20effc67 TL |
76 | // FowardIterator or better, as we can use std::distance |
77 | template<class InputIt, class> | |
78 | auto | |
79 | string:: | |
80 | insert( | |
81 | size_type pos, | |
82 | InputIt first, | |
83 | InputIt last) -> | |
84 | string& | |
85 | { | |
86 | struct cleanup | |
87 | { | |
88 | detail::string_impl& s; | |
89 | storage_ptr const& sp; | |
90 | ||
91 | ~cleanup() | |
92 | { | |
93 | s.destroy(sp); | |
94 | } | |
95 | }; | |
96 | ||
97 | // We use the default storage because | |
98 | // the allocation is immediately freed. | |
99 | storage_ptr dsp; | |
100 | detail::string_impl tmp( | |
101 | first, last, dsp, | |
102 | iter_cat<InputIt>{}); | |
103 | cleanup c{tmp, dsp}; | |
104 | std::memcpy( | |
105 | impl_.insert_unchecked(pos, tmp.size(), sp_), | |
106 | tmp.data(), | |
107 | tmp.size()); | |
108 | return *this; | |
109 | } | |
110 | ||
111 | // KRYSTIAN TODO: this can be done without copies when | |
1e59de90 | 112 | // reallocation is not needed, when the iterator is a |
20effc67 TL |
113 | // FowardIterator or better, as we can use std::distance |
114 | template<class InputIt, class> | |
115 | auto | |
116 | string:: | |
117 | replace( | |
118 | const_iterator first, | |
119 | const_iterator last, | |
120 | InputIt first2, | |
121 | InputIt last2) -> | |
122 | string& | |
123 | { | |
124 | struct cleanup | |
125 | { | |
126 | detail::string_impl& s; | |
127 | storage_ptr const& sp; | |
128 | ||
129 | ~cleanup() | |
130 | { | |
131 | s.destroy(sp); | |
132 | } | |
133 | }; | |
134 | ||
135 | // We use the default storage because | |
136 | // the allocation is immediately freed. | |
137 | storage_ptr dsp; | |
138 | detail::string_impl tmp( | |
139 | first2, last2, dsp, | |
140 | iter_cat<InputIt>{}); | |
141 | cleanup c{tmp, dsp}; | |
142 | std::memcpy( | |
143 | impl_.replace_unchecked( | |
1e59de90 TL |
144 | first - begin(), |
145 | last - first, | |
146 | tmp.size(), | |
20effc67 TL |
147 | sp_), |
148 | tmp.data(), | |
149 | tmp.size()); | |
150 | return *this; | |
151 | } | |
152 | ||
153 | //---------------------------------------------------------- | |
154 | ||
155 | template<class InputIt> | |
156 | void | |
157 | string:: | |
158 | assign( | |
159 | InputIt first, | |
160 | InputIt last, | |
161 | std::random_access_iterator_tag) | |
162 | { | |
163 | auto dest = impl_.assign(static_cast< | |
164 | size_type>(last - first), sp_); | |
165 | while(first != last) | |
166 | *dest++ = *first++; | |
167 | } | |
168 | ||
169 | template<class InputIt> | |
170 | void | |
171 | string:: | |
172 | assign( | |
173 | InputIt first, | |
174 | InputIt last, | |
175 | std::input_iterator_tag) | |
176 | { | |
177 | if(first == last) | |
178 | { | |
179 | impl_.term(0); | |
180 | return; | |
181 | } | |
182 | detail::string_impl tmp( | |
183 | first, last, sp_, | |
184 | std::input_iterator_tag{}); | |
185 | impl_.destroy(sp_); | |
186 | impl_ = tmp; | |
187 | } | |
188 | ||
189 | template<class InputIt> | |
190 | void | |
191 | string:: | |
192 | append( | |
193 | InputIt first, | |
194 | InputIt last, | |
195 | std::random_access_iterator_tag) | |
196 | { | |
197 | auto const n = static_cast< | |
198 | size_type>(last - first); | |
199 | std::copy(first, last, | |
200 | impl_.append(n, sp_)); | |
201 | } | |
202 | ||
203 | template<class InputIt> | |
204 | void | |
205 | string:: | |
206 | append( | |
207 | InputIt first, | |
208 | InputIt last, | |
209 | std::input_iterator_tag) | |
210 | { | |
211 | struct cleanup | |
212 | { | |
213 | detail::string_impl& s; | |
214 | storage_ptr const& sp; | |
215 | ||
216 | ~cleanup() | |
217 | { | |
218 | s.destroy(sp); | |
219 | } | |
220 | }; | |
221 | ||
222 | // We use the default storage because | |
223 | // the allocation is immediately freed. | |
224 | storage_ptr dsp; | |
225 | detail::string_impl tmp( | |
226 | first, last, dsp, | |
227 | std::input_iterator_tag{}); | |
228 | cleanup c{tmp, dsp}; | |
229 | std::memcpy( | |
230 | impl_.append(tmp.size(), sp_), | |
231 | tmp.data(), tmp.size()); | |
232 | } | |
233 | ||
234 | BOOST_JSON_NS_END | |
235 | ||
236 | #endif |