214 lines
6.1 KiB
C++
214 lines
6.1 KiB
C++
#ifndef __BUFFERUTILITY_H__
|
||
#define __BUFFERUTILITY_H__
|
||
|
||
#include <algorithm>
|
||
#include <cstdint>
|
||
#include <stdexcept>
|
||
#include <vector>
|
||
|
||
namespace Amass {
|
||
|
||
/**
|
||
* @brief The Buffer class A buffer class modeled after org.jboss.netty.buffer.ChannelBuffer
|
||
* +------------------+------------------+
|
||
* | readable bytes | writable bytes |
|
||
* | (CONTENT) | |
|
||
* +------------------+------------------+
|
||
* | | |
|
||
* 0 <=readerIndex <= writerIndex <= size
|
||
*/
|
||
class Buffer {
|
||
public:
|
||
Buffer(size_t initialSize = 1024);
|
||
void swap(Buffer &buffer);
|
||
|
||
int lastError();
|
||
|
||
inline const char *readableAddress() const {
|
||
return m_buffer.data() + m_readerIndex;
|
||
}
|
||
inline size_t readableBytes() const {
|
||
return m_writerIndex - m_readerIndex;
|
||
}
|
||
|
||
void append(const char *data, size_t len);
|
||
inline void append(std::string_view data) {
|
||
append(data.data(), data.size());
|
||
}
|
||
|
||
void appendFileContent(const std::string_view &path);
|
||
|
||
/**
|
||
* @brief peek must POD struct
|
||
* @param fd
|
||
* @return [errno,size]
|
||
*/
|
||
template <typename T>
|
||
T peek() {
|
||
T t;
|
||
memcpy(&t, readableAddress(), sizeof(T));
|
||
return t;
|
||
}
|
||
|
||
inline std::string peek(size_t size, bool retrieved = false) {
|
||
std::string ret(readableAddress(), size);
|
||
if (retrieved) retrieve(size);
|
||
return ret;
|
||
}
|
||
|
||
/**
|
||
* @brief findCRLF
|
||
* @param start if(start == nullptr),find CRLF from readableAddress.
|
||
* @return
|
||
*/
|
||
const char *findCRLF() const;
|
||
|
||
const char *findCRLFCRLF() const;
|
||
|
||
template <typename T>
|
||
const char *find(const T &data, size_t startPos = 0) {
|
||
if (startPos >= readableBytes()) return nullptr;
|
||
const char *pos = nullptr;
|
||
if constexpr (!std::is_array_v<T>) {
|
||
if (startPos + sizeof(T) > readableBytes()) return nullptr;
|
||
pos = std::search(readableAddress() + startPos, (const char *)writableAddress(), (const char *)(&data),
|
||
(const char *)(&data));
|
||
} else {
|
||
if (startPos + sizeof(T) * std::extent_v < T >> readableBytes()) return nullptr;
|
||
pos = std::search(readableAddress() + startPos, (const char *)writableAddress(), (const char *)(&data[0]),
|
||
(const char *)(&data[std::extent_v<T>]));
|
||
}
|
||
|
||
return pos == writableAddress() ? nullptr : pos;
|
||
}
|
||
|
||
/**
|
||
* @brief findEOL
|
||
* @param start if(start == nullptr),find EOL from readableAddress.
|
||
* @return
|
||
*/
|
||
const char *findEOL(const char *start = nullptr) const;
|
||
|
||
/**
|
||
* @brief retrieve retrieve returns void, to prevent string str(retrieve(readableBytes()),
|
||
* readableBytes()); the evaluation of two functions are unspecified
|
||
* @param len
|
||
* @return
|
||
*/
|
||
bool retrieve(size_t len);
|
||
|
||
/**
|
||
* @brief retrieveUntil retrive [begin,end)
|
||
* @param end
|
||
* @return
|
||
*/
|
||
bool retrieveUntil(const char *end);
|
||
|
||
/**
|
||
* @brief retrieveAll
|
||
* @param Return[template parameter] void,std::string,std::vector<char>
|
||
* @return
|
||
*/
|
||
template <typename ReturnType = void>
|
||
typename std::conditional_t<std::is_same_v<ReturnType, void>, void, ReturnType> retrieveAll() {
|
||
if constexpr (std::is_same_v<ReturnType, std::string>) {
|
||
std::string data(m_buffer.cbegin() + static_cast<int64_t>(m_readerIndex),
|
||
m_buffer.cbegin() + static_cast<int64_t>(m_writerIndex));
|
||
m_readerIndex = 0;
|
||
m_writerIndex = 0;
|
||
m_buffer[m_readerIndex] = '\0';
|
||
return data;
|
||
} else if constexpr (std::is_same_v<ReturnType, std::vector<char>>) {
|
||
std::vector<char> data(m_buffer.cbegin() + static_cast<int64_t>(m_readerIndex),
|
||
m_buffer.cbegin() + static_cast<int64_t>(m_writerIndex));
|
||
m_readerIndex = 0;
|
||
m_writerIndex = 0;
|
||
m_buffer[m_readerIndex] = '\0';
|
||
return data;
|
||
} else if constexpr (std::is_same_v<ReturnType, void>) {
|
||
m_readerIndex = 0;
|
||
m_writerIndex = 0;
|
||
m_buffer[m_readerIndex] = '\0';
|
||
}
|
||
}
|
||
|
||
protected:
|
||
/**
|
||
* @brief makeSpace 增加m_buffer的writeable区域容量,或者将可读数据前移
|
||
* @param len
|
||
*/
|
||
void makeSpace(size_t len);
|
||
|
||
inline size_t writableBytes() const {
|
||
return m_buffer.size() - m_writerIndex;
|
||
}
|
||
inline const char *writableAddress() const {
|
||
return m_buffer.data() + m_writerIndex;
|
||
}
|
||
inline char *writableAddress() {
|
||
return m_buffer.data() + m_writerIndex;
|
||
}
|
||
|
||
private:
|
||
std::vector<char> m_buffer;
|
||
size_t m_readerIndex = 0;
|
||
size_t m_writerIndex = 0;
|
||
int m_lastError;
|
||
};
|
||
|
||
template <typename T>
|
||
class VectorView {
|
||
public:
|
||
using size_type = std::size_t;
|
||
using const_reference = const T &;
|
||
VectorView(const T *ptr, size_type length) : m_data(ptr), m_length(length) {
|
||
}
|
||
constexpr size_type size() const noexcept {
|
||
return m_length;
|
||
}
|
||
constexpr size_type length() const noexcept {
|
||
return m_length;
|
||
}
|
||
constexpr const_reference front() const {
|
||
return m_data[0];
|
||
}
|
||
constexpr const_reference back() const {
|
||
return m_data[size() - 1];
|
||
}
|
||
constexpr const_reference at(size_type pos) const {
|
||
return m_data[pos];
|
||
}
|
||
|
||
private:
|
||
const T *m_data;
|
||
size_type m_length;
|
||
};
|
||
|
||
template <typename T>
|
||
class BufferView {
|
||
public:
|
||
BufferView() {
|
||
}
|
||
BufferView(const T *data, size_t size) : m_data(data), m_length(size), m_current(data) {
|
||
}
|
||
bool empty() const {
|
||
return m_data == nullptr || (m_current > (m_data + m_length));
|
||
}
|
||
size_t size() const {
|
||
return m_data + m_length - m_current;
|
||
}
|
||
void read(T *buffer, size_t size) {
|
||
std::copy(m_current, m_current + size, buffer);
|
||
m_current += size;
|
||
}
|
||
|
||
private:
|
||
const T *m_data = nullptr;
|
||
size_t m_length = 0;
|
||
const T *m_current = nullptr;
|
||
};
|
||
|
||
} // namespace Amass
|
||
|
||
#endif // __BUFFERUTILITY_H__
|