450 lines
11 KiB
C++
450 lines
11 KiB
C++
/*
|
||
* 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
|