brpc/include/butil/iobuf_inl.h
2022-12-14 19:05:52 +08:00

431 lines
11 KiB
C++

// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
// iobuf - A non-continuous zero-copied buffer
// Date: Thu Nov 22 13:57:56 CST 2012
// Inlined implementations of some methods defined in iobuf.h
#ifndef BUTIL_IOBUF_INL_H
#define BUTIL_IOBUF_INL_H
void* fast_memcpy(void *__restrict dest, const void *__restrict src, size_t n);
namespace butil {
inline ssize_t IOBuf::cut_into_file_descriptor(int fd, size_t size_hint) {
return pcut_into_file_descriptor(fd, -1, size_hint);
}
inline ssize_t IOBuf::cut_multiple_into_file_descriptor(
int fd, IOBuf* const* pieces, size_t count) {
return pcut_multiple_into_file_descriptor(fd, -1, pieces, count);
}
inline int IOBuf::append_user_data(void* data, size_t size, void (*deleter)(void*)) {
return append_user_data_with_meta(data, size, deleter, 0);
}
inline ssize_t IOPortal::append_from_file_descriptor(int fd, size_t max_count) {
return pappend_from_file_descriptor(fd, -1, max_count);
}
inline void IOPortal::return_cached_blocks() {
if (_block) {
return_cached_blocks_impl(_block);
_block = NULL;
}
}
inline void reset_block_ref(IOBuf::BlockRef& ref) {
ref.offset = 0;
ref.length = 0;
ref.block = NULL;
}
inline IOBuf::IOBuf() {
reset_block_ref(_sv.refs[0]);
reset_block_ref(_sv.refs[1]);
}
inline IOBuf::IOBuf(const Movable& rhs) {
_sv = rhs.value()._sv;
new (&rhs.value()) IOBuf;
}
inline void IOBuf::operator=(const Movable& rhs) {
clear();
_sv = rhs.value()._sv;
new (&rhs.value()) IOBuf;
}
inline void IOBuf::operator=(const char* s) {
clear();
append(s);
}
inline void IOBuf::operator=(const std::string& s) {
clear();
append(s);
}
inline void IOBuf::swap(IOBuf& other) {
const SmallView tmp = other._sv;
other._sv = _sv;
_sv = tmp;
}
inline int IOBuf::cut_until(IOBuf* out, char const* delim) {
if (*delim) {
if (!*(delim+1)) {
return _cut_by_char(out, *delim);
} else {
return _cut_by_delim(out, delim, strlen(delim));
}
}
return -1;
}
inline int IOBuf::cut_until(IOBuf* out, const std::string& delim) {
if (delim.length() == 1UL) {
return _cut_by_char(out, delim[0]);
} else if (delim.length() > 1UL) {
return _cut_by_delim(out, delim.data(), delim.length());
} else {
return -1;
}
}
inline int IOBuf::append(const std::string& s) {
return append(s.data(), s.length());
}
inline std::string IOBuf::to_string() const {
std::string s;
copy_to(&s);
return s;
}
inline bool IOBuf::empty() const {
return _small() ? !_sv.refs[0].block : !_bv.nbytes;
}
inline size_t IOBuf::length() const {
return _small() ?
(_sv.refs[0].length + _sv.refs[1].length) : _bv.nbytes;
}
inline bool IOBuf::_small() const {
return _bv.magic >= 0;
}
inline size_t IOBuf::_ref_num() const {
return _small()
? (!!_sv.refs[0].block + !!_sv.refs[1].block) : _bv.nref;
}
inline IOBuf::BlockRef& IOBuf::_front_ref() {
return _small() ? _sv.refs[0] : _bv.refs[_bv.start];
}
inline const IOBuf::BlockRef& IOBuf::_front_ref() const {
return _small() ? _sv.refs[0] : _bv.refs[_bv.start];
}
inline IOBuf::BlockRef& IOBuf::_back_ref() {
return _small() ? _sv.refs[!!_sv.refs[1].block] : _bv.ref_at(_bv.nref - 1);
}
inline const IOBuf::BlockRef& IOBuf::_back_ref() const {
return _small() ? _sv.refs[!!_sv.refs[1].block] : _bv.ref_at(_bv.nref - 1);
}
inline IOBuf::BlockRef& IOBuf::_ref_at(size_t i) {
return _small() ? _sv.refs[i] : _bv.ref_at(i);
}
inline const IOBuf::BlockRef& IOBuf::_ref_at(size_t i) const {
return _small() ? _sv.refs[i] : _bv.ref_at(i);
}
inline const IOBuf::BlockRef* IOBuf::_pref_at(size_t i) const {
if (_small()) {
return i < (size_t)(!!_sv.refs[0].block + !!_sv.refs[1].block) ? &_sv.refs[i] : NULL;
} else {
return i < _bv.nref ? &_bv.ref_at(i) : NULL;
}
}
inline bool operator==(const IOBuf::BlockRef& r1, const IOBuf::BlockRef& r2) {
return r1.offset == r2.offset && r1.length == r2.length &&
r1.block == r2.block;
}
inline bool operator!=(const IOBuf::BlockRef& r1, const IOBuf::BlockRef& r2) {
return !(r1 == r2);
}
inline void IOBuf::_push_back_ref(const BlockRef& r) {
if (_small()) {
return _push_or_move_back_ref_to_smallview<false>(r);
} else {
return _push_or_move_back_ref_to_bigview<false>(r);
}
}
inline void IOBuf::_move_back_ref(const BlockRef& r) {
if (_small()) {
return _push_or_move_back_ref_to_smallview<true>(r);
} else {
return _push_or_move_back_ref_to_bigview<true>(r);
}
}
//////////////// IOBufCutter ////////////////
inline size_t IOBufCutter::remaining_bytes() const {
if (_block) {
return (char*)_data_end - (char*)_data + _buf->size() - _buf->_front_ref().length;
} else {
return _buf->size();
}
}
inline bool IOBufCutter::cut1(void* c) {
if (_data == _data_end) {
if (!load_next_ref()) {
return false;
}
}
*(char*)c = *(const char*)_data;
_data = (char*)_data + 1;
return true;
}
inline const void* IOBufCutter::fetch1() {
if (_data == _data_end) {
if (!load_next_ref()) {
return NULL;
}
}
return _data;
}
inline size_t IOBufCutter::copy_to(void* out, size_t n) {
size_t size = (char*)_data_end - (char*)_data;
if (n <= size) {
memcpy(out, _data, n);
return n;
}
return slower_copy_to(out, n);
}
inline size_t IOBufCutter::pop_front(size_t n) {
const size_t saved_n = n;
do {
const size_t size = (char*)_data_end - (char*)_data;
if (n <= size) {
_data = (char*)_data + n;
return saved_n;
}
n -= size;
if (!load_next_ref()) {
return saved_n - n;
}
} while (true);
}
inline size_t IOBufCutter::cutn(std::string* out, size_t n) {
if (n == 0) {
return 0;
}
const size_t len = remaining_bytes();
if (n > len) {
n = len;
}
const size_t old_size = out->size();
out->resize(out->size() + n);
return cutn(&(*out)[old_size], n);
}
/////////////// IOBufAppender /////////////////
inline int IOBufAppender::append(const void* src, size_t n) {
do {
const size_t size = (char*)_data_end - (char*)_data;
if (n <= size) {
memcpy(_data, src, n);
_data = (char*)_data + n;
return 0;
}
if (size != 0) {
memcpy(_data, src, size);
src = (const char*)src + size;
n -= size;
}
if (add_block() != 0) {
return -1;
}
} while (true);
}
inline int IOBufAppender::append(const StringPiece& str) {
return append(str.data(), str.size());
}
inline int IOBufAppender::append_decimal(long d) {
char buf[24]; // enough for decimal 64-bit integers
size_t n = sizeof(buf);
bool negative = false;
if (d < 0) {
negative = true;
d = -d;
}
do {
const long q = d / 10;
buf[--n] = d - q * 10 + '0';
d = q;
} while (d);
if (negative) {
buf[--n] = '-';
}
return append(buf + n, sizeof(buf) - n);
}
inline int IOBufAppender::push_back(char c) {
if (_data == _data_end) {
if (add_block() != 0) {
return -1;
}
}
char* const p = (char*)_data;
*p = c;
_data = p + 1;
return 0;
}
inline int IOBufAppender::add_block() {
int size = 0;
if (_zc_stream.Next(&_data, &size)) {
_data_end = (char*)_data + size;
return 0;
}
_data = NULL;
_data_end = NULL;
return -1;
}
inline void IOBufAppender::shrink() {
const size_t size = (char*)_data_end - (char*)_data;
if (size != 0) {
_zc_stream.BackUp(size);
_data = NULL;
_data_end = NULL;
}
}
inline IOBufBytesIterator::IOBufBytesIterator(const butil::IOBuf& buf)
: _block_begin(NULL), _block_end(NULL), _block_count(0),
_bytes_left(buf.length()), _buf(&buf) {
try_next_block();
}
inline IOBufBytesIterator::IOBufBytesIterator(const IOBufBytesIterator& it)
: _block_begin(it._block_begin)
, _block_end(it._block_end)
, _block_count(it._block_count)
, _bytes_left(it._bytes_left)
, _buf(it._buf) {
}
inline IOBufBytesIterator::IOBufBytesIterator(
const IOBufBytesIterator& it, size_t bytes_left)
: _block_begin(it._block_begin)
, _block_end(it._block_end)
, _block_count(it._block_count)
, _bytes_left(bytes_left)
, _buf(it._buf) {
//CHECK_LE(_bytes_left, it._bytes_left);
if (_block_end > _block_begin + _bytes_left) {
_block_end = _block_begin + _bytes_left;
}
}
inline void IOBufBytesIterator::try_next_block() {
if (_bytes_left == 0) {
return;
}
butil::StringPiece s = _buf->backing_block(_block_count++);
_block_begin = s.data();
_block_end = s.data() + std::min(s.size(), (size_t)_bytes_left);
}
inline void IOBufBytesIterator::operator++() {
++_block_begin;
--_bytes_left;
if (_block_begin == _block_end) {
try_next_block();
}
}
inline size_t IOBufBytesIterator::copy_and_forward(void* buf, size_t n) {
size_t nc = 0;
while (nc < n && _bytes_left != 0) {
const size_t block_size = _block_end - _block_begin;
const size_t to_copy = std::min(block_size, n - nc);
memcpy((char*)buf + nc, _block_begin, to_copy);
_block_begin += to_copy;
_bytes_left -= to_copy;
nc += to_copy;
if (_block_begin == _block_end) {
try_next_block();
}
}
return nc;
}
inline size_t IOBufBytesIterator::copy_and_forward(std::string* s, size_t n) {
bool resized = false;
if (s->size() < n) {
resized = true;
s->resize(n);
}
const size_t nc = copy_and_forward(const_cast<char*>(s->data()), n);
if (nc < n && resized) {
s->resize(nc);
}
return nc;
}
inline size_t IOBufBytesIterator::forward(size_t n) {
size_t nc = 0;
while (nc < n && _bytes_left != 0) {
const size_t block_size = _block_end - _block_begin;
const size_t to_copy = std::min(block_size, n - nc);
_block_begin += to_copy;
_bytes_left -= to_copy;
nc += to_copy;
if (_block_begin == _block_end) {
try_next_block();
}
}
return nc;
}
} // namespace butil
#endif // BUTIL_IOBUF_INL_H