Older/ToolKit/Network/Buffer.h
amass 9de3af15eb
All checks were successful
Deploy / PullDocker (push) Successful in 12s
Deploy / Build (push) Successful in 1m51s
add ZLMediaKit code for learning.
2024-09-28 23:55:00 +08:00

450 lines
11 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (c) 2016 The ZLToolKit project authors. All Rights Reserved.
*
* This file is part of ZLToolKit(https://github.com/ZLMediaKit/ZLToolKit).
*
* Use of this source code is governed by MIT license that can be found in the
* LICENSE file in the root of the source tree. All contributing project authors
* may be found in the AUTHORS file in the root of the source tree.
*/
#ifndef ZLTOOLKIT_BUFFER_H
#define ZLTOOLKIT_BUFFER_H
#include <cassert>
#include <memory>
#include <string>
#include <vector>
#include <type_traits>
#include <functional>
#include "Util/util.h"
#include "Util/ResourcePool.h"
namespace toolkit {
template <typename T> struct is_pointer : public std::false_type {};
template <typename T> struct is_pointer<std::shared_ptr<T> > : public std::true_type {};
template <typename T> struct is_pointer<std::shared_ptr<T const> > : public std::true_type {};
template <typename T> struct is_pointer<T*> : public std::true_type {};
template <typename T> struct is_pointer<const T*> : public std::true_type {};
//缓存基类
class Buffer : public noncopyable {
public:
using Ptr = std::shared_ptr<Buffer>;
Buffer() = default;
virtual ~Buffer() = default;
//返回数据长度
virtual char *data() const = 0;
virtual size_t size() const = 0;
virtual std::string toString() const {
return std::string(data(), size());
}
virtual size_t getCapacity() const {
return size();
}
private:
//对象个数统计
ObjectStatistic<Buffer> _statistic;
};
template <typename C>
class BufferOffset : public Buffer {
public:
using Ptr = std::shared_ptr<BufferOffset>;
BufferOffset(C data, size_t offset = 0, size_t len = 0) : _data(std::move(data)) {
setup(offset, len);
}
~BufferOffset() override = default;
char *data() const override {
return const_cast<char *>(getPointer<C>(_data)->data()) + _offset;
}
size_t size() const override {
return _size;
}
std::string toString() const override {
return std::string(data(), size());
}
private:
void setup(size_t offset = 0, size_t size = 0) {
auto max_size = getPointer<C>(_data)->size();
assert(offset + size <= max_size);
if (!size) {
size = max_size - offset;
}
_size = size;
_offset = offset;
}
template<typename T>
static typename std::enable_if<::toolkit::is_pointer<T>::value, const T &>::type
getPointer(const T &data) {
return data;
}
template<typename T>
static typename std::enable_if<!::toolkit::is_pointer<T>::value, const T *>::type
getPointer(const T &data) {
return &data;
}
private:
C _data;
size_t _size;
size_t _offset;
};
using BufferString = BufferOffset<std::string>;
//指针式缓存对象,
class BufferRaw : public Buffer {
public:
using Ptr = std::shared_ptr<BufferRaw>;
static Ptr create();
~BufferRaw() override {
if (_data) {
delete[] _data;
}
}
//在写入数据时请确保内存是否越界
char *data() const override {
return _data;
}
//有效数据大小
size_t size() const override {
return _size;
}
//分配内存大小
void setCapacity(size_t capacity) {
if (_data) {
do {
if (capacity > _capacity) {
//请求的内存大于当前内存,那么重新分配
break;
}
if (_capacity < 2 * 1024) {
//2K以下不重复开辟内存直接复用
return;
}
if (2 * capacity > _capacity) {
//如果请求的内存大于当前内存的一半,那么也复用
return;
}
} while (false);
delete[] _data;
}
_data = new char[capacity];
_capacity = capacity;
}
//设置有效数据大小
virtual void setSize(size_t size) {
if (size > _capacity) {
throw std::invalid_argument("Buffer::setSize out of range");
}
_size = size;
}
//赋值数据
void assign(const char *data, size_t size = 0) {
if (size <= 0) {
size = strlen(data);
}
setCapacity(size + 1);
memcpy(_data, data, size);
_data[size] = '\0';
setSize(size);
}
size_t getCapacity() const override {
return _capacity;
}
protected:
friend class ResourcePool_l<BufferRaw>;
BufferRaw(size_t capacity = 0) {
if (capacity) {
setCapacity(capacity);
}
}
BufferRaw(const char *data, size_t size = 0) {
assign(data, size);
}
private:
size_t _size = 0;
size_t _capacity = 0;
char *_data = nullptr;
//对象个数统计
ObjectStatistic<BufferRaw> _statistic;
};
class BufferLikeString : public Buffer {
public:
~BufferLikeString() override = default;
BufferLikeString() {
_erase_head = 0;
_erase_tail = 0;
}
BufferLikeString(std::string str) {
_str = std::move(str);
_erase_head = 0;
_erase_tail = 0;
}
BufferLikeString &operator=(std::string str) {
_str = std::move(str);
_erase_head = 0;
_erase_tail = 0;
return *this;
}
BufferLikeString(const char *str) {
_str = str;
_erase_head = 0;
_erase_tail = 0;
}
BufferLikeString &operator=(const char *str) {
_str = str;
_erase_head = 0;
_erase_tail = 0;
return *this;
}
BufferLikeString(BufferLikeString &&that) {
_str = std::move(that._str);
_erase_head = that._erase_head;
_erase_tail = that._erase_tail;
that._erase_head = 0;
that._erase_tail = 0;
}
BufferLikeString &operator=(BufferLikeString &&that) {
_str = std::move(that._str);
_erase_head = that._erase_head;
_erase_tail = that._erase_tail;
that._erase_head = 0;
that._erase_tail = 0;
return *this;
}
BufferLikeString(const BufferLikeString &that) {
_str = that._str;
_erase_head = that._erase_head;
_erase_tail = that._erase_tail;
}
BufferLikeString &operator=(const BufferLikeString &that) {
_str = that._str;
_erase_head = that._erase_head;
_erase_tail = that._erase_tail;
return *this;
}
char *data() const override {
return (char *) _str.data() + _erase_head;
}
size_t size() const override {
return _str.size() - _erase_tail - _erase_head;
}
BufferLikeString &erase(size_t pos = 0, size_t n = std::string::npos) {
if (pos == 0) {
//移除前面的数据
if (n != std::string::npos) {
//移除部分
if (n > size()) {
//移除太多数据了
throw std::out_of_range("BufferLikeString::erase out_of_range in head");
}
//设置起始便宜量
_erase_head += n;
data()[size()] = '\0';
return *this;
}
//移除全部数据
_erase_head = 0;
_erase_tail = _str.size();
data()[0] = '\0';
return *this;
}
if (n == std::string::npos || pos + n >= size()) {
//移除末尾所有数据
if (pos >= size()) {
//移除太多数据
throw std::out_of_range("BufferLikeString::erase out_of_range in tail");
}
_erase_tail += size() - pos;
data()[size()] = '\0';
return *this;
}
//移除中间的
if (pos + n > size()) {
//超过长度限制
throw std::out_of_range("BufferLikeString::erase out_of_range in middle");
}
_str.erase(_erase_head + pos, n);
return *this;
}
BufferLikeString &append(const BufferLikeString &str) {
return append(str.data(), str.size());
}
BufferLikeString &append(const std::string &str) {
return append(str.data(), str.size());
}
BufferLikeString &append(const char *data) {
return append(data, strlen(data));
}
BufferLikeString &append(const char *data, size_t len) {
if (len <= 0) {
return *this;
}
if (_erase_head > _str.capacity() / 2) {
moveData();
}
if (_erase_tail == 0) {
_str.append(data, len);
return *this;
}
_str.insert(_erase_head + size(), data, len);
return *this;
}
void push_back(char c) {
if (_erase_tail == 0) {
_str.push_back(c);
return;
}
data()[size()] = c;
--_erase_tail;
data()[size()] = '\0';
}
BufferLikeString &insert(size_t pos, const char *s, size_t n) {
_str.insert(_erase_head + pos, s, n);
return *this;
}
BufferLikeString &assign(const char *data) {
return assign(data, strlen(data));
}
BufferLikeString &assign(const char *data, size_t len) {
if (len <= 0) {
return *this;
}
if (data >= _str.data() && data < _str.data() + _str.size()) {
_erase_head = data - _str.data();
if (data + len > _str.data() + _str.size()) {
throw std::out_of_range("BufferLikeString::assign out_of_range");
}
_erase_tail = _str.data() + _str.size() - (data + len);
return *this;
}
_str.assign(data, len);
_erase_head = 0;
_erase_tail = 0;
return *this;
}
void clear() {
_erase_head = 0;
_erase_tail = 0;
_str.clear();
}
char &operator[](size_t pos) {
if (pos >= size()) {
throw std::out_of_range("BufferLikeString::operator[] out_of_range");
}
return data()[pos];
}
const char &operator[](size_t pos) const {
return (*const_cast<BufferLikeString *>(this))[pos];
}
size_t capacity() const {
return _str.capacity();
}
void reserve(size_t size) {
_str.reserve(size);
}
void resize(size_t size, char c = '\0') {
_str.resize(size, c);
_erase_head = 0;
_erase_tail = 0;
}
bool empty() const {
return size() <= 0;
}
std::string substr(size_t pos, size_t n = std::string::npos) const {
if (n == std::string::npos) {
//获取末尾所有的
if (pos >= size()) {
throw std::out_of_range("BufferLikeString::substr out_of_range");
}
return _str.substr(_erase_head + pos, size() - pos);
}
//获取部分
if (pos + n > size()) {
throw std::out_of_range("BufferLikeString::substr out_of_range");
}
return _str.substr(_erase_head + pos, n);
}
private:
void moveData() {
if (_erase_head) {
_str.erase(0, _erase_head);
_erase_head = 0;
}
}
private:
size_t _erase_head;
size_t _erase_tail;
std::string _str;
//对象个数统计
ObjectStatistic<BufferLikeString> _statistic;
};
}//namespace toolkit
#endif //ZLTOOLKIT_BUFFER_H