Kylin/Universal/BufferUtility.cpp

99 lines
3.4 KiB
C++
Raw Normal View History

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