Kylin/Universal/BufferUtility.h
2023-07-25 10:40:14 +08:00

214 lines
6.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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__