1 | // Licensed to the Apache Software Foundation (ASF) under one |
2 | // or more contributor license agreements. See the NOTICE file |
3 | // distributed with this work for additional information |
4 | // regarding copyright ownership. The ASF licenses this file |
5 | // to you under the Apache License, Version 2.0 (the |
6 | // "License"); you may not use this file except in compliance |
7 | // with the License. You may obtain a copy of the License at |
8 | // |
9 | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | // |
11 | // Unless required by applicable law or agreed to in writing, |
12 | // software distributed under the License is distributed on an |
13 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | // KIND, either express or implied. See the License for the |
15 | // specific language governing permissions and limitations |
16 | // under the License. |
17 | |
18 | // iobuf - A non-continuous zero-copied buffer |
19 | |
20 | // Date: Thu Nov 22 13:57:56 CST 2012 |
21 | |
22 | // Inlined implementations of some methods defined in iobuf.h |
23 | |
24 | #ifndef BUTIL_IOBUF_INL_H |
25 | #define BUTIL_IOBUF_INL_H |
26 | |
27 | void* fast_memcpy(void *__restrict dest, const void *__restrict src, size_t n); |
28 | |
29 | namespace butil { |
30 | |
31 | inline ssize_t IOBuf::cut_into_file_descriptor(int fd, size_t size_hint) { |
32 | return pcut_into_file_descriptor(fd, -1, size_hint); |
33 | } |
34 | |
35 | inline ssize_t IOBuf::cut_multiple_into_file_descriptor( |
36 | int fd, IOBuf* const* pieces, size_t count) { |
37 | return pcut_multiple_into_file_descriptor(fd, -1, pieces, count); |
38 | } |
39 | |
40 | inline ssize_t IOPortal::append_from_file_descriptor(int fd, size_t max_count) { |
41 | return pappend_from_file_descriptor(fd, -1, max_count); |
42 | } |
43 | |
44 | inline void IOPortal::return_cached_blocks() { |
45 | if (_block) { |
46 | return_cached_blocks_impl(_block); |
47 | _block = NULL; |
48 | } |
49 | } |
50 | |
51 | inline void reset_block_ref(IOBuf::BlockRef& ref) { |
52 | ref.offset = 0; |
53 | ref.length = 0; |
54 | ref.block = NULL; |
55 | } |
56 | |
57 | inline IOBuf::IOBuf() { |
58 | reset_block_ref(_sv.refs[0]); |
59 | reset_block_ref(_sv.refs[1]); |
60 | } |
61 | |
62 | inline IOBuf::IOBuf(const Movable& rhs) { |
63 | _sv = rhs.value()._sv; |
64 | new (&rhs.value()) IOBuf; |
65 | } |
66 | |
67 | inline void IOBuf::operator=(const Movable& rhs) { |
68 | clear(); |
69 | _sv = rhs.value()._sv; |
70 | new (&rhs.value()) IOBuf; |
71 | } |
72 | |
73 | inline void IOBuf::operator=(const char* s) { |
74 | clear(); |
75 | append(s); |
76 | } |
77 | |
78 | inline void IOBuf::operator=(const std::string& s) { |
79 | clear(); |
80 | append(s); |
81 | } |
82 | |
83 | inline void IOBuf::swap(IOBuf& other) { |
84 | const SmallView tmp = other._sv; |
85 | other._sv = _sv; |
86 | _sv = tmp; |
87 | } |
88 | |
89 | inline int IOBuf::cut_until(IOBuf* out, char const* delim) { |
90 | if (*delim) { |
91 | if (!*(delim+1)) { |
92 | return _cut_by_char(out, *delim); |
93 | } else { |
94 | return _cut_by_delim(out, delim, strlen(delim)); |
95 | } |
96 | } |
97 | return -1; |
98 | } |
99 | |
100 | inline int IOBuf::cut_until(IOBuf* out, const std::string& delim) { |
101 | if (delim.length() == 1UL) { |
102 | return _cut_by_char(out, delim[0]); |
103 | } else if (delim.length() > 1UL) { |
104 | return _cut_by_delim(out, delim.data(), delim.length()); |
105 | } else { |
106 | return -1; |
107 | } |
108 | } |
109 | |
110 | inline int IOBuf::append(const std::string& s) { |
111 | return append(s.data(), s.length()); |
112 | } |
113 | |
114 | inline std::string IOBuf::to_string() const { |
115 | std::string s; |
116 | copy_to(&s); |
117 | return s; |
118 | } |
119 | |
120 | inline bool IOBuf::empty() const { |
121 | return _small() ? !_sv.refs[0].block : !_bv.nbytes; |
122 | } |
123 | |
124 | inline size_t IOBuf::length() const { |
125 | return _small() ? |
126 | (_sv.refs[0].length + _sv.refs[1].length) : _bv.nbytes; |
127 | } |
128 | |
129 | inline bool IOBuf::_small() const { |
130 | return _bv.magic >= 0; |
131 | } |
132 | |
133 | inline size_t IOBuf::_ref_num() const { |
134 | return _small() |
135 | ? (!!_sv.refs[0].block + !!_sv.refs[1].block) : _bv.nref; |
136 | } |
137 | |
138 | inline IOBuf::BlockRef& IOBuf::_front_ref() { |
139 | return _small() ? _sv.refs[0] : _bv.refs[_bv.start]; |
140 | } |
141 | |
142 | inline const IOBuf::BlockRef& IOBuf::_front_ref() const { |
143 | return _small() ? _sv.refs[0] : _bv.refs[_bv.start]; |
144 | } |
145 | |
146 | inline IOBuf::BlockRef& IOBuf::_back_ref() { |
147 | return _small() ? _sv.refs[!!_sv.refs[1].block] : _bv.ref_at(_bv.nref - 1); |
148 | } |
149 | |
150 | inline const IOBuf::BlockRef& IOBuf::_back_ref() const { |
151 | return _small() ? _sv.refs[!!_sv.refs[1].block] : _bv.ref_at(_bv.nref - 1); |
152 | } |
153 | |
154 | inline IOBuf::BlockRef& IOBuf::_ref_at(size_t i) { |
155 | return _small() ? _sv.refs[i] : _bv.ref_at(i); |
156 | } |
157 | |
158 | inline const IOBuf::BlockRef& IOBuf::_ref_at(size_t i) const { |
159 | return _small() ? _sv.refs[i] : _bv.ref_at(i); |
160 | } |
161 | |
162 | inline const IOBuf::BlockRef* IOBuf::_pref_at(size_t i) const { |
163 | if (_small()) { |
164 | return i < (size_t)(!!_sv.refs[0].block + !!_sv.refs[1].block) ? &_sv.refs[i] : NULL; |
165 | } else { |
166 | return i < _bv.nref ? &_bv.ref_at(i) : NULL; |
167 | } |
168 | } |
169 | |
170 | inline bool operator==(const IOBuf::BlockRef& r1, const IOBuf::BlockRef& r2) { |
171 | return r1.offset == r2.offset && r1.length == r2.length && |
172 | r1.block == r2.block; |
173 | } |
174 | |
175 | inline bool operator!=(const IOBuf::BlockRef& r1, const IOBuf::BlockRef& r2) { |
176 | return !(r1 == r2); |
177 | } |
178 | |
179 | inline void IOBuf::_push_back_ref(const BlockRef& r) { |
180 | if (_small()) { |
181 | return _push_or_move_back_ref_to_smallview<false>(r); |
182 | } else { |
183 | return _push_or_move_back_ref_to_bigview<false>(r); |
184 | } |
185 | } |
186 | |
187 | inline void IOBuf::_move_back_ref(const BlockRef& r) { |
188 | if (_small()) { |
189 | return _push_or_move_back_ref_to_smallview<true>(r); |
190 | } else { |
191 | return _push_or_move_back_ref_to_bigview<true>(r); |
192 | } |
193 | } |
194 | |
195 | //////////////// IOBufCutter //////////////// |
196 | inline size_t IOBufCutter::remaining_bytes() const { |
197 | if (_block) { |
198 | return (char*)_data_end - (char*)_data + _buf->size() - _buf->_front_ref().length; |
199 | } else { |
200 | return _buf->size(); |
201 | } |
202 | } |
203 | |
204 | inline bool IOBufCutter::cut1(void* c) { |
205 | if (_data == _data_end) { |
206 | if (!load_next_ref()) { |
207 | return false; |
208 | } |
209 | } |
210 | *(char*)c = *(const char*)_data; |
211 | _data = (char*)_data + 1; |
212 | return true; |
213 | } |
214 | |
215 | inline const void* IOBufCutter::fetch1() { |
216 | if (_data == _data_end) { |
217 | if (!load_next_ref()) { |
218 | return NULL; |
219 | } |
220 | } |
221 | return _data; |
222 | } |
223 | |
224 | inline size_t IOBufCutter::copy_to(void* out, size_t n) { |
225 | size_t size = (char*)_data_end - (char*)_data; |
226 | if (n <= size) { |
227 | memcpy(out, _data, n); |
228 | return n; |
229 | } |
230 | return slower_copy_to(out, n); |
231 | } |
232 | |
233 | inline size_t IOBufCutter::pop_front(size_t n) { |
234 | const size_t saved_n = n; |
235 | do { |
236 | const size_t size = (char*)_data_end - (char*)_data; |
237 | if (n <= size) { |
238 | _data = (char*)_data + n; |
239 | return saved_n; |
240 | } |
241 | if (size != 0) { |
242 | n -= size; |
243 | } |
244 | if (!load_next_ref()) { |
245 | return saved_n; |
246 | } |
247 | } while (true); |
248 | } |
249 | |
250 | inline size_t IOBufCutter::cutn(std::string* out, size_t n) { |
251 | if (n == 0) { |
252 | return 0; |
253 | } |
254 | const size_t len = remaining_bytes(); |
255 | if (n > len) { |
256 | n = len; |
257 | } |
258 | const size_t old_size = out->size(); |
259 | out->resize(out->size() + n); |
260 | return cutn(&(*out)[old_size], n); |
261 | } |
262 | |
263 | /////////////// IOBufAppender ///////////////// |
264 | inline int IOBufAppender::append(const void* src, size_t n) { |
265 | do { |
266 | const size_t size = (char*)_data_end - (char*)_data; |
267 | if (n <= size) { |
268 | memcpy(_data, src, n); |
269 | _data = (char*)_data + n; |
270 | return 0; |
271 | } |
272 | if (size != 0) { |
273 | memcpy(_data, src, size); |
274 | src = (const char*)src + size; |
275 | n -= size; |
276 | } |
277 | if (add_block() != 0) { |
278 | return -1; |
279 | } |
280 | } while (true); |
281 | } |
282 | |
283 | inline int IOBufAppender::append(const StringPiece& str) { |
284 | return append(str.data(), str.size()); |
285 | } |
286 | |
287 | inline int IOBufAppender::append_decimal(long d) { |
288 | char buf[24]; // enough for decimal 64-bit integers |
289 | size_t n = sizeof(buf); |
290 | bool negative = false; |
291 | if (d < 0) { |
292 | negative = true; |
293 | d = -d; |
294 | } |
295 | do { |
296 | const long q = d / 10; |
297 | buf[--n] = d - q * 10 + '0'; |
298 | d = q; |
299 | } while (d); |
300 | if (negative) { |
301 | buf[--n] = '-'; |
302 | } |
303 | return append(buf + n, sizeof(buf) - n); |
304 | } |
305 | |
306 | inline int IOBufAppender::push_back(char c) { |
307 | if (_data == _data_end) { |
308 | if (add_block() != 0) { |
309 | return -1; |
310 | } |
311 | } |
312 | char* const p = (char*)_data; |
313 | *p = c; |
314 | _data = p + 1; |
315 | return 0; |
316 | } |
317 | |
318 | inline int IOBufAppender::add_block() { |
319 | int size = 0; |
320 | if (_zc_stream.Next(&_data, &size)) { |
321 | _data_end = (char*)_data + size; |
322 | return 0; |
323 | } |
324 | _data = NULL; |
325 | _data_end = NULL; |
326 | return -1; |
327 | } |
328 | |
329 | inline void IOBufAppender::shrink() { |
330 | const size_t size = (char*)_data_end - (char*)_data; |
331 | if (size != 0) { |
332 | _zc_stream.BackUp(size); |
333 | _data = NULL; |
334 | _data_end = NULL; |
335 | } |
336 | } |
337 | |
338 | inline IOBufBytesIterator::IOBufBytesIterator(const butil::IOBuf& buf) |
339 | : _block_begin(NULL), _block_end(NULL), _block_count(0), |
340 | _bytes_left(buf.length()), _buf(&buf) { |
341 | try_next_block(); |
342 | } |
343 | |
344 | inline IOBufBytesIterator::IOBufBytesIterator(const IOBufBytesIterator& it) |
345 | : _block_begin(it._block_begin) |
346 | , _block_end(it._block_end) |
347 | , _block_count(it._block_count) |
348 | , _bytes_left(it._bytes_left) |
349 | , _buf(it._buf) { |
350 | } |
351 | |
352 | inline IOBufBytesIterator::IOBufBytesIterator( |
353 | const IOBufBytesIterator& it, size_t bytes_left) |
354 | : _block_begin(it._block_begin) |
355 | , _block_end(it._block_end) |
356 | , _block_count(it._block_count) |
357 | , _bytes_left(bytes_left) |
358 | , _buf(it._buf) { |
359 | //CHECK_LE(_bytes_left, it._bytes_left); |
360 | if (_block_end > _block_begin + _bytes_left) { |
361 | _block_end = _block_begin + _bytes_left; |
362 | } |
363 | } |
364 | |
365 | inline void IOBufBytesIterator::try_next_block() { |
366 | if (_bytes_left == 0) { |
367 | return; |
368 | } |
369 | butil::StringPiece s = _buf->backing_block(_block_count++); |
370 | _block_begin = s.data(); |
371 | _block_end = s.data() + std::min(s.size(), (size_t)_bytes_left); |
372 | } |
373 | |
374 | inline void IOBufBytesIterator::operator++() { |
375 | ++_block_begin; |
376 | --_bytes_left; |
377 | if (_block_begin == _block_end) { |
378 | try_next_block(); |
379 | } |
380 | } |
381 | |
382 | inline size_t IOBufBytesIterator::copy_and_forward(void* buf, size_t n) { |
383 | size_t nc = 0; |
384 | while (nc < n && _bytes_left != 0) { |
385 | const size_t block_size = _block_end - _block_begin; |
386 | const size_t to_copy = std::min(block_size, n - nc); |
387 | memcpy((char*)buf + nc, _block_begin, to_copy); |
388 | _block_begin += to_copy; |
389 | _bytes_left -= to_copy; |
390 | nc += to_copy; |
391 | if (_block_begin == _block_end) { |
392 | try_next_block(); |
393 | } |
394 | } |
395 | return nc; |
396 | } |
397 | |
398 | inline size_t IOBufBytesIterator::copy_and_forward(std::string* s, size_t n) { |
399 | bool resized = false; |
400 | if (s->size() < n) { |
401 | resized = true; |
402 | s->resize(n); |
403 | } |
404 | const size_t nc = copy_and_forward(const_cast<char*>(s->data()), n); |
405 | if (nc < n && resized) { |
406 | s->resize(nc); |
407 | } |
408 | return nc; |
409 | } |
410 | |
411 | inline size_t IOBufBytesIterator::forward(size_t n) { |
412 | size_t nc = 0; |
413 | while (nc < n && _bytes_left != 0) { |
414 | const size_t block_size = _block_end - _block_begin; |
415 | const size_t to_copy = std::min(block_size, n - nc); |
416 | _block_begin += to_copy; |
417 | _bytes_left -= to_copy; |
418 | nc += to_copy; |
419 | if (_block_begin == _block_end) { |
420 | try_next_block(); |
421 | } |
422 | } |
423 | return nc; |
424 | } |
425 | |
426 | } // namespace butil |
427 | |
428 | #endif // BUTIL_IOBUF_INL_H |
429 | |