99 lines
3.4 KiB
C++
99 lines
3.4 KiB
C++
|
#include "BufferUtility.h"
|
|||
|
#include <cstring>
|
|||
|
#include <filesystem>
|
|||
|
#include <fstream>
|
|||
|
|
|||
|
namespace Amass {
|
|||
|
const char CRLF[] = "\r\n";
|
|||
|
const char CRLFCRLF[] = "\r\n\r\n";
|
|||
|
|
|||
|
Buffer::Buffer(size_t initialSize) : m_buffer(initialSize) {
|
|||
|
}
|
|||
|
|
|||
|
void Buffer::swap(Buffer &buffer) {
|
|||
|
m_buffer.swap(buffer.m_buffer);
|
|||
|
std::swap(m_readerIndex, buffer.m_readerIndex);
|
|||
|
std::swap(m_writerIndex, buffer.m_writerIndex);
|
|||
|
}
|
|||
|
|
|||
|
int Buffer::lastError() {
|
|||
|
return m_lastError;
|
|||
|
}
|
|||
|
|
|||
|
void Buffer::append(const char *data, size_t len) {
|
|||
|
if (writableBytes() < len + 1)
|
|||
|
makeSpace(len + 1); // 剩下的可写空间如果小于需要的空间len+1,则增加len+1长度个空间,[len+1]用来加上\0进行截断
|
|||
|
std::memcpy(writableAddress(), data, len);
|
|||
|
std::copy(data, data + len, writableAddress()); // 其实相当于把已有数据往前挪动
|
|||
|
m_writerIndex += len;
|
|||
|
// 当Buffer以readableAddress()开始直接作为字符串直接使用时,在此加上\0截断,否则随机会打印出writableAddress()后的内容
|
|||
|
m_buffer[m_writerIndex] = '\0';
|
|||
|
}
|
|||
|
|
|||
|
void Buffer::appendFileContent(const std::string_view &path) {
|
|||
|
if (path.empty() || !std::filesystem::exists(path)) return;
|
|||
|
std::ifstream ifs(path.data(), std::ifstream::binary);
|
|||
|
char buffer[512];
|
|||
|
while (ifs.read(buffer, sizeof(buffer))) {
|
|||
|
append(buffer, ifs.gcount());
|
|||
|
}
|
|||
|
auto size = ifs.gcount();
|
|||
|
if (size > 0) append(buffer, size);
|
|||
|
}
|
|||
|
|
|||
|
void Buffer::makeSpace(size_t needSize) {
|
|||
|
if ((writableBytes() + m_readerIndex) < needSize) { // 即使数据前移,空间还是不足
|
|||
|
auto remainSize = readableBytes();
|
|||
|
auto newSize = remainSize + needSize + 1024;
|
|||
|
std::vector<char> newBuffer(newSize);
|
|||
|
memcpy(newBuffer.data(), readableAddress(), remainSize);
|
|||
|
m_buffer.swap(newBuffer);
|
|||
|
m_readerIndex = 0;
|
|||
|
m_writerIndex = remainSize;
|
|||
|
} else { // 将数据前移,空间满足要求
|
|||
|
auto remainSize = readableBytes();
|
|||
|
auto dst = m_buffer.data();
|
|||
|
auto src = readableAddress();
|
|||
|
for (size_t i = 0; i < remainSize; i++) {
|
|||
|
*dst++ = *src++;
|
|||
|
}
|
|||
|
m_readerIndex = 0;
|
|||
|
m_writerIndex = remainSize;
|
|||
|
}
|
|||
|
}
|
|||
|
const char *Buffer::findCRLF() const {
|
|||
|
const char *crlf = std::search(readableAddress(), writableAddress(), CRLF, CRLF + 2);
|
|||
|
return crlf == writableAddress() ? nullptr : crlf;
|
|||
|
}
|
|||
|
|
|||
|
const char *Buffer::findCRLFCRLF() const {
|
|||
|
auto crlf = std::search(readableAddress(), writableAddress(), CRLFCRLF, CRLFCRLF + 4);
|
|||
|
return crlf == writableAddress() ? nullptr : crlf;
|
|||
|
}
|
|||
|
|
|||
|
const char *Buffer::findEOL(const char *start) const {
|
|||
|
if (start == nullptr) start = readableAddress();
|
|||
|
if ((readableAddress() > start) || (start >= writableAddress())) return nullptr;
|
|||
|
|
|||
|
const void *eol = memchr(start, '\n', static_cast<size_t>(writableAddress() - start));
|
|||
|
return static_cast<const char *>(eol);
|
|||
|
}
|
|||
|
|
|||
|
bool Buffer::retrieve(size_t len) {
|
|||
|
if (len > readableBytes()) return false;
|
|||
|
if (len < readableBytes()) {
|
|||
|
m_readerIndex += len;
|
|||
|
} else {
|
|||
|
retrieveAll();
|
|||
|
}
|
|||
|
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
bool Buffer::retrieveUntil(const char *end) {
|
|||
|
if (((uint64_t)readableAddress() > (uint64_t)end) || ((uint64_t)end > (uint64_t)writableAddress())) return false;
|
|||
|
return retrieve(static_cast<size_t>(end - readableAddress()));
|
|||
|
}
|
|||
|
|
|||
|
} // namespace Amass
|