Kylin/Universal/BufferUtility.h

214 lines
6.1 KiB
C
Raw Permalink Normal View History

2023-07-25 10:40:14 +08:00
#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__