2021-05-01 15:36:25 +00:00
|
|
|
#include <cstdarg>
|
|
|
|
#include <cstdlib>
|
|
|
|
#include <cstring>
|
2012-06-03 17:01:08 +00:00
|
|
|
|
2020-09-29 11:02:02 +00:00
|
|
|
#include "Common/Buffer.h"
|
2021-05-15 05:46:03 +00:00
|
|
|
#include "Common/File/FileUtil.h"
|
|
|
|
#include "Common/File/Path.h"
|
2020-08-15 13:51:41 +00:00
|
|
|
#include "Common/Log.h"
|
|
|
|
|
2020-09-29 08:24:41 +00:00
|
|
|
char *Buffer::Append(size_t length) {
|
2020-02-06 23:09:42 +00:00
|
|
|
if (length > 0) {
|
2024-11-21 22:40:27 +00:00
|
|
|
return data_.push_back_write(length);
|
2020-02-06 23:09:42 +00:00
|
|
|
} else {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2012-06-03 17:01:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Buffer::Append(const std::string &str) {
|
2021-05-01 15:36:25 +00:00
|
|
|
char *ptr = Append(str.size());
|
2024-07-22 09:36:12 +00:00
|
|
|
if (ptr) {
|
|
|
|
memcpy(ptr, str.data(), str.size());
|
|
|
|
}
|
2012-06-03 17:01:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Buffer::Append(const char *str) {
|
2021-05-01 15:36:25 +00:00
|
|
|
size_t len = strlen(str);
|
|
|
|
char *dest = Append(len);
|
|
|
|
memcpy(dest, str, len);
|
2012-06-03 17:01:08 +00:00
|
|
|
}
|
|
|
|
|
2013-06-25 02:36:53 +00:00
|
|
|
void Buffer::Append(const Buffer &other) {
|
|
|
|
size_t len = other.size();
|
2020-02-06 23:09:42 +00:00
|
|
|
if (len > 0) {
|
2024-11-21 22:40:27 +00:00
|
|
|
// Append other to the current buffer.
|
|
|
|
other.data_.iterate_blocks([&](const char *data, size_t size) {
|
|
|
|
data_.push_back(data, size);
|
|
|
|
return true;
|
|
|
|
});
|
2020-02-06 23:09:42 +00:00
|
|
|
}
|
2013-06-25 02:36:53 +00:00
|
|
|
}
|
|
|
|
|
2012-06-03 17:01:08 +00:00
|
|
|
void Buffer::AppendValue(int value) {
|
2021-05-01 15:36:25 +00:00
|
|
|
char buf[16];
|
|
|
|
// This is slow.
|
2023-04-28 18:26:08 +00:00
|
|
|
snprintf(buf, sizeof(buf), "%i", value);
|
2021-05-01 15:36:25 +00:00
|
|
|
Append(buf);
|
2012-06-03 17:01:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Buffer::Take(size_t length, std::string *dest) {
|
2013-06-25 02:36:53 +00:00
|
|
|
if (length > data_.size()) {
|
2024-07-14 12:42:59 +00:00
|
|
|
ERROR_LOG(Log::IO, "Truncating length in Buffer::Take()");
|
2013-06-25 02:36:53 +00:00
|
|
|
length = data_.size();
|
|
|
|
}
|
|
|
|
dest->resize(length);
|
2013-06-04 20:05:17 +00:00
|
|
|
if (length > 0) {
|
2014-11-24 00:12:54 +00:00
|
|
|
Take(length, &(*dest)[0]);
|
2013-06-04 20:05:17 +00:00
|
|
|
}
|
2012-06-03 17:01:08 +00:00
|
|
|
}
|
|
|
|
|
2014-11-24 00:12:54 +00:00
|
|
|
void Buffer::Take(size_t length, char *dest) {
|
2024-11-21 22:40:27 +00:00
|
|
|
size_t retval = data_.pop_front_bulk(dest, length);
|
|
|
|
_dbg_assert_(retval == length);
|
2014-11-24 00:12:54 +00:00
|
|
|
}
|
|
|
|
|
2012-06-03 17:01:08 +00:00
|
|
|
int Buffer::TakeLineCRLF(std::string *dest) {
|
2021-05-01 15:36:25 +00:00
|
|
|
int after_next_line = OffsetToAfterNextCRLF();
|
|
|
|
if (after_next_line < 0) {
|
|
|
|
return after_next_line;
|
|
|
|
} else {
|
2022-12-11 05:12:36 +00:00
|
|
|
_dbg_assert_(after_next_line >= 2);
|
|
|
|
if (after_next_line != 2)
|
|
|
|
Take((size_t)after_next_line - 2, dest);
|
2021-05-01 15:36:25 +00:00
|
|
|
Skip(2); // Skip the CRLF
|
|
|
|
return after_next_line - 2;
|
|
|
|
}
|
2012-06-03 17:01:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Buffer::Skip(size_t length) {
|
2013-06-25 02:36:53 +00:00
|
|
|
if (length > data_.size()) {
|
2024-07-14 12:42:59 +00:00
|
|
|
ERROR_LOG(Log::IO, "Truncating length in Buffer::Skip()");
|
2013-06-25 02:36:53 +00:00
|
|
|
length = data_.size();
|
|
|
|
}
|
2024-11-21 22:40:27 +00:00
|
|
|
data_.skip(length);
|
2012-06-03 17:01:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int Buffer::SkipLineCRLF() {
|
2021-05-01 15:36:25 +00:00
|
|
|
int after_next_line = OffsetToAfterNextCRLF();
|
|
|
|
if (after_next_line < 0) {
|
|
|
|
return after_next_line;
|
|
|
|
} else {
|
|
|
|
Skip(after_next_line);
|
|
|
|
return after_next_line - 2;
|
|
|
|
}
|
2012-06-03 17:01:08 +00:00
|
|
|
}
|
|
|
|
|
2024-11-21 22:40:27 +00:00
|
|
|
// This relies on having buffered data!
|
2012-06-03 17:01:08 +00:00
|
|
|
int Buffer::OffsetToAfterNextCRLF() {
|
2024-11-22 09:13:41 +00:00
|
|
|
int offset = data_.next_crlf_offset();
|
|
|
|
if (offset >= 0) {
|
|
|
|
return offset + 2;
|
|
|
|
} else {
|
|
|
|
return -1;
|
2021-05-01 15:36:25 +00:00
|
|
|
}
|
2012-06-03 17:01:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Buffer::Printf(const char *fmt, ...) {
|
2024-10-10 13:54:23 +00:00
|
|
|
char buffer[4096];
|
2021-05-01 15:36:25 +00:00
|
|
|
va_list vl;
|
|
|
|
va_start(vl, fmt);
|
2024-10-10 13:54:23 +00:00
|
|
|
int retval = vsnprintf(buffer, sizeof(buffer), fmt, vl);
|
|
|
|
if (retval >= (int)sizeof(buffer)) {
|
2021-05-01 15:36:25 +00:00
|
|
|
// Output was truncated. TODO: Do something.
|
2024-07-14 12:42:59 +00:00
|
|
|
ERROR_LOG(Log::IO, "Buffer::Printf truncated output");
|
2021-05-01 15:36:25 +00:00
|
|
|
}
|
2024-10-10 13:54:23 +00:00
|
|
|
if (retval < 0) {
|
|
|
|
ERROR_LOG(Log::IO, "Buffer::Printf failed, bad args?");
|
|
|
|
return;
|
2021-05-01 15:36:25 +00:00
|
|
|
}
|
|
|
|
va_end(vl);
|
|
|
|
char *ptr = Append(retval);
|
|
|
|
memcpy(ptr, buffer, retval);
|
2012-06-03 17:01:08 +00:00
|
|
|
}
|
|
|
|
|
2021-05-15 05:46:03 +00:00
|
|
|
bool Buffer::FlushToFile(const Path &filename) {
|
|
|
|
FILE *f = File::OpenCFile(filename, "wb");
|
2013-05-31 21:04:42 +00:00
|
|
|
if (!f)
|
|
|
|
return false;
|
2024-10-10 09:55:07 +00:00
|
|
|
if (!data_.empty()) {
|
2024-11-21 22:40:27 +00:00
|
|
|
// Write the buffer to the file.
|
|
|
|
data_.iterate_blocks([=](const char *blockData, size_t blockSize) {
|
|
|
|
return fwrite(blockData, 1, blockSize, f) == blockSize;
|
|
|
|
});
|
|
|
|
data_.clear();
|
2013-05-31 21:04:42 +00:00
|
|
|
}
|
|
|
|
fclose(f);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-06-03 17:01:08 +00:00
|
|
|
void Buffer::PeekAll(std::string *dest) {
|
2013-06-03 23:24:49 +00:00
|
|
|
dest->resize(data_.size());
|
2024-11-21 22:40:27 +00:00
|
|
|
data_.iterate_blocks(([=](const char *blockData, size_t blockSize) {
|
|
|
|
dest->append(blockData, blockSize);
|
|
|
|
return true;
|
|
|
|
}));
|
2013-11-29 15:31:19 +00:00
|
|
|
}
|