#ifndef __BUFFERUTILITY_H__ #define __BUFFERUTILITY_H__ #include #include #include #include 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 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 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) { 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])); } 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 * @return */ template typename std::conditional_t, void, ReturnType> retrieveAll() { if constexpr (std::is_same_v) { std::string data(m_buffer.cbegin() + static_cast(m_readerIndex), m_buffer.cbegin() + static_cast(m_writerIndex)); m_readerIndex = 0; m_writerIndex = 0; m_buffer[m_readerIndex] = '\0'; return data; } else if constexpr (std::is_same_v>) { std::vector data(m_buffer.cbegin() + static_cast(m_readerIndex), m_buffer.cbegin() + static_cast(m_writerIndex)); m_readerIndex = 0; m_writerIndex = 0; m_buffer[m_readerIndex] = '\0'; return data; } else if constexpr (std::is_same_v) { 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 m_buffer; size_t m_readerIndex = 0; size_t m_writerIndex = 0; int m_lastError; }; template 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 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__