/* * 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 #include #include #include #include #include #include "Util/util.h" #include "Util/ResourcePool.h" namespace toolkit { template struct is_pointer : public std::false_type {}; template struct is_pointer > : public std::true_type {}; template struct is_pointer > : public std::true_type {}; template struct is_pointer : public std::true_type {}; template struct is_pointer : public std::true_type {}; //缓存基类 class Buffer : public noncopyable { public: using Ptr = std::shared_ptr; 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 _statistic; }; template class BufferOffset : public Buffer { public: using Ptr = std::shared_ptr; 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(getPointer(_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(_data)->size(); assert(offset + size <= max_size); if (!size) { size = max_size - offset; } _size = size; _offset = offset; } template static typename std::enable_if<::toolkit::is_pointer::value, const T &>::type getPointer(const T &data) { return data; } template static typename std::enable_if::value, const T *>::type getPointer(const T &data) { return &data; } private: C _data; size_t _size; size_t _offset; }; using BufferString = BufferOffset; //指针式缓存对象, class BufferRaw : public Buffer { public: using Ptr = std::shared_ptr; 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(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 _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(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 _statistic; }; }//namespace toolkit #endif //ZLTOOLKIT_BUFFER_H