You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

475 lines
13 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* 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 {};
//缓存基类 [AUTO-TRANSLATED:d130ab72]
//Cache base class
class Buffer : public noncopyable {
public:
using Ptr = std::shared_ptr<Buffer>;
Buffer() = default;
virtual ~Buffer() = default;
//返回数据长度 [AUTO-TRANSLATED:955f731c]
//Return data length
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:
//对象个数统计 [AUTO-TRANSLATED:3b43e8c2]
//Object count statistics
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>;
//指针式缓存对象, [AUTO-TRANSLATED:c8403290]
//Pointer-style cache object,
class BufferRaw : public Buffer {
public:
using Ptr = std::shared_ptr<BufferRaw>;
static Ptr create();
~BufferRaw() override {
if (_data) {
delete[] _data;
}
}
//在写入数据时请确保内存是否越界 [AUTO-TRANSLATED:5602043e]
//When writing data, please ensure that the memory does not overflow
char *data() const override {
return _data;
}
//有效数据大小 [AUTO-TRANSLATED:b8dcbda7]
//Effective data size
size_t size() const override {
return _size;
}
//分配内存大小 [AUTO-TRANSLATED:cce87adf]
//Allocated memory size
void setCapacity(size_t capacity) {
if (_data) {
do {
if (capacity > _capacity) {
//请求的内存大于当前内存,那么重新分配 [AUTO-TRANSLATED:65306424]
//If the requested memory is greater than the current memory, reallocate
break;
}
if (_capacity < 2 * 1024) {
//2K以下不重复开辟内存直接复用 [AUTO-TRANSLATED:056416c0]
//Less than 2K, do not repeatedly allocate memory, reuse directly
return;
}
if (2 * capacity > _capacity) {
//如果请求的内存大于当前内存的一半,那么也复用 [AUTO-TRANSLATED:c189d660]
//If the requested memory is greater than half of the current memory, also reuse
return;
}
} while (false);
delete[] _data;
}
_data = new char[capacity];
_capacity = capacity;
}
//设置有效数据大小 [AUTO-TRANSLATED:efc4fb3e]
//Set valid data size
virtual void setSize(size_t size) {
if (size > _capacity) {
throw std::invalid_argument("Buffer::setSize out of range");
}
_size = size;
}
//赋值数据 [AUTO-TRANSLATED:0b91b213]
//Assign data
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;
//对象个数统计 [AUTO-TRANSLATED:3b43e8c2]
//Object count statistics
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) {
//移除前面的数据 [AUTO-TRANSLATED:b025d3c5]
//Remove data from the front
if (n != std::string::npos) {
//移除部分 [AUTO-TRANSLATED:a650bef2]
//Remove part
if (n > size()) {
//移除太多数据了 [AUTO-TRANSLATED:64460d15]
//Removed too much data
throw std::out_of_range("BufferLikeString::erase out_of_range in head");
}
//设置起始便宜量 [AUTO-TRANSLATED:7a0250bd]
//Set starting offset
_erase_head += n;
data()[size()] = '\0';
return *this;
}
//移除全部数据 [AUTO-TRANSLATED:3d016f79]
//Remove all data
_erase_head = 0;
_erase_tail = _str.size();
data()[0] = '\0';
return *this;
}
if (n == std::string::npos || pos + n >= size()) {
//移除末尾所有数据 [AUTO-TRANSLATED:efaf1165]
//Remove all data from the end
if (pos >= size()) {
//移除太多数据 [AUTO-TRANSLATED:dc9347c3]
//Removed too much data
throw std::out_of_range("BufferLikeString::erase out_of_range in tail");
}
_erase_tail += size() - pos;
data()[size()] = '\0';
return *this;
}
//移除中间的 [AUTO-TRANSLATED:fd25344c]
//Remove the middle
if (pos + n > size()) {
//超过长度限制 [AUTO-TRANSLATED:9ae84929]
//Exceeds the length limit
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) {
//获取末尾所有的 [AUTO-TRANSLATED:8a0b92b6]
//Get all at the end
if (pos >= size()) {
throw std::out_of_range("BufferLikeString::substr out_of_range");
}
return _str.substr(_erase_head + pos, size() - pos);
}
//获取部分 [AUTO-TRANSLATED:d01310a4]
//Get part
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;
//对象个数统计 [AUTO-TRANSLATED:3b43e8c2]
//Object count statistics
ObjectStatistic<BufferLikeString> _statistic;
};
}//namespace toolkit
#endif //ZLTOOLKIT_BUFFER_H