Polish the streambuffer API a bit

This commit is contained in:
2021-07-19 17:32:24 -04:00
parent f8f8a9843f
commit 08ca274444
5 changed files with 303 additions and 195 deletions

View File

@@ -103,38 +103,115 @@ void StreamBuffer::clear() {
lua_reader_size_ = 0;
}
char *StreamBuffer::alloc_space(int64_t bytes) {
assert(bytes >= 0);
make_space(bytes);
return write_cursor_;
// These routines return true if you can losslessly cast the
// specified value to the specified type.
static inline bool safe_to_cast_to_int8(int64_t vv) {
return ((vv + 0x80LL) & 0xFFFFFFFFFFFFFF00LL) == 0;
}
void StreamBuffer::wrote_space(int64_t bytes) {
int64_t maxbuf = buf_hi_ - write_cursor_;
assert(bytes >= 0);
assert(bytes <= maxbuf);
write_cursor_ += bytes;
static inline bool safe_to_cast_to_int16(int64_t vv) {
return ((vv + 0x8000LL) & 0xFFFFFFFFFFFF0000LL) == 0;
}
void StreamBuffer::write_int8(int8_t v) {
static inline bool safe_to_cast_to_int32(int64_t vv) {
return ((vv + 0x80000000LL) & 0xFFFFFFFF00000000LL) == 0;
}
static inline bool safe_to_cast_to_int64(int64_t vv) {
return true;
}
static inline bool safe_to_cast_to_uint8(uint64_t vv) {
return (vv & 0xFFFFFFFFFFFFFF00LL) == 0;
}
static inline bool safe_to_cast_to_uint16(uint64_t vv) {
return (vv & 0xFFFFFFFFFFFF0000LL) == 0;
}
static inline bool safe_to_cast_to_uint32(uint64_t vv) {
return (vv & 0xFFFFFFFF00000000LL) == 0;
}
static inline bool safe_to_cast_to_uint64(uint64_t vv) {
return true;
}
void StreamBuffer::write_bytes(const char *s, int64_t len) {
make_space(len);
memcpy(write_cursor_, s, len);
write_cursor_ += len;
}
const char *StreamBuffer::read_bytes(int64_t bytes) {
check_available(bytes);
char *data = read_cursor_;
read_cursor_ += bytes;
return data;
}
void StreamBuffer::write_int8(int64_t vv) {
assert(safe_to_cast_to_int8(vv));
int8_t v = vv;
make_space(1);
memcpy(write_cursor_, &v, 1);
write_cursor_ += 1;
}
void StreamBuffer::write_int16(int16_t v) {
void StreamBuffer::write_int16(int64_t vv) {
assert(safe_to_cast_to_int16(vv));
int16_t v = vv;
make_space(2);
memcpy(write_cursor_, &v, 2);
write_cursor_ += 2;
}
void StreamBuffer::write_int32(int32_t v) {
void StreamBuffer::write_int32(int64_t vv) {
assert(safe_to_cast_to_int32(vv));
int32_t v = vv;
make_space(4);
memcpy(write_cursor_, &v, 4);
write_cursor_ += 4;
}
void StreamBuffer::write_int64(int64_t v) {
void StreamBuffer::write_int64(int64_t vv) {
assert(safe_to_cast_to_int64(vv));
int64_t v = vv;
make_space(8);
memcpy(write_cursor_, &v, 8);
write_cursor_ += 8;
}
void StreamBuffer::write_uint8(uint64_t vv) {
assert(safe_to_cast_to_uint8(vv));
uint8_t v = vv;
make_space(1);
memcpy(write_cursor_, &v, 1);
write_cursor_ += 1;
}
void StreamBuffer::write_uint16(uint64_t vv) {
assert(safe_to_cast_to_uint16(vv));
uint16_t v = vv;
make_space(2);
memcpy(write_cursor_, &v, 2);
write_cursor_ += 2;
}
void StreamBuffer::write_uint32(uint64_t vv) {
assert(safe_to_cast_to_uint32(vv));
uint32_t v = vv;
make_space(4);
memcpy(write_cursor_, &v, 4);
write_cursor_ += 4;
}
void StreamBuffer::write_uint64(uint64_t vv) {
assert(safe_to_cast_to_uint64(vv));
uint64_t v = vv;
make_space(8);
memcpy(write_cursor_, &v, 8);
write_cursor_ += 8;
@@ -152,53 +229,6 @@ void StreamBuffer::write_double(double d) {
write_cursor_ += 8;
}
void StreamBuffer::write_hashvalue(const util::HashValue &hv) {
make_space(16);
memcpy(write_cursor_, &hv, 16);
write_cursor_ += 16;
}
void StreamBuffer::write_bytes(const char *s, int64_t len) {
make_space(len);
memcpy(write_cursor_, s, len);
write_cursor_ += len;
}
void StreamBuffer::write_ztbytes(const char *s) {
write_bytes(s, strlen(s));
}
void StreamBuffer::write_string(const std::string &s) {
if (s.size() >= 255) {
write_uint8(0xFF);
write_uint64(s.size());
write_bytes(s.c_str(), s.size());
} else {
write_uint8(s.size());
write_bytes(s.c_str(), s.size());
}
}
void StreamBuffer::overwrite_int8(int64_t write_count_after, int8_t v) {
char *target = get_overwrite(1, write_count_after);
memcpy(target, &v, 1);
}
void StreamBuffer::overwrite_int16(int64_t write_count_after, int16_t v) {
char *target = get_overwrite(2, write_count_after);
memcpy(target, &v, 2);
}
void StreamBuffer::overwrite_int32(int64_t write_count_after, int32_t v) {
char *target = get_overwrite(4, write_count_after);
memcpy(target, &v, 4);
}
void StreamBuffer::overwrite_int64(int64_t write_count_after, int64_t v) {
char *target = get_overwrite(8, write_count_after);
memcpy(target, &v, 8);
}
int8_t StreamBuffer::read_int8() {
check_available(1);
int8_t v;
@@ -231,14 +261,6 @@ int64_t StreamBuffer::read_int64() {
return v;
}
util::HashValue StreamBuffer::read_hashvalue() {
check_available(16);
util::HashValue hv;
memcpy(&hv, read_cursor_, 16);
read_cursor_ += 16;
return hv;
}
float StreamBuffer::read_float() {
check_available(4);
float f;
@@ -255,23 +277,29 @@ double StreamBuffer::read_double() {
return d;
}
size_t StreamBuffer::read_size() {
return read_size_limit(0xFFFFFFF);
void StreamBuffer::write_hashvalue(const util::HashValue &hv) {
make_space(16);
memcpy(write_cursor_, &hv, 16);
write_cursor_ += 16;
}
size_t StreamBuffer::read_size_limit(size_t limit) {
int64_t value = read_int64();
if ((value < 0)||(value > int64_t(limit))) {
throw StreamCorruption();
void StreamBuffer::write_string(const std::string &s) {
if (s.size() >= 255) {
write_uint8(0xFF);
write_uint64(s.size());
write_bytes(s.c_str(), s.size());
} else {
write_uint8(s.size());
write_bytes(s.c_str(), s.size());
}
return size_t(value);
}
const char *StreamBuffer::read_bytes(int64_t bytes) {
check_available(bytes);
char *data = read_cursor_;
read_cursor_ += bytes;
return data;
util::HashValue StreamBuffer::read_hashvalue() {
check_available(16);
util::HashValue hv;
memcpy(&hv, read_cursor_, 16);
read_cursor_ += 16;
return hv;
}
std::string StreamBuffer::read_string() {
@@ -289,6 +317,63 @@ std::string StreamBuffer::read_string_limit(int64_t max_allowed) {
return std::string(bytes, len);
}
void StreamBuffer::overwrite_int8(int64_t write_count_after, int64_t vv) {
assert(safe_to_cast_to_int8(vv));
int8_t v = vv;
char *target = get_overwrite(1, write_count_after);
memcpy(target, &v, 1);
}
void StreamBuffer::overwrite_int16(int64_t write_count_after, int64_t vv) {
assert(safe_to_cast_to_int16(vv));
int16_t v = vv;
char *target = get_overwrite(2, write_count_after);
memcpy(target, &v, 2);
}
void StreamBuffer::overwrite_int32(int64_t write_count_after, int64_t vv) {
assert(safe_to_cast_to_int32(vv));
int32_t v = vv;
char *target = get_overwrite(4, write_count_after);
memcpy(target, &v, 4);
}
void StreamBuffer::overwrite_int64(int64_t write_count_after, int64_t vv) {
assert(safe_to_cast_to_int64(vv));
int64_t v = vv;
char *target = get_overwrite(8, write_count_after);
memcpy(target, &v, 8);
}
void StreamBuffer::overwrite_uint8(int64_t write_count_after, uint64_t vv) {
assert(safe_to_cast_to_uint8(vv));
uint8_t v = vv;
char *target = get_overwrite(1, write_count_after);
memcpy(target, &v, 1);
}
void StreamBuffer::overwrite_uint16(int64_t write_count_after, uint64_t vv) {
assert(safe_to_cast_to_uint16(vv));
uint16_t v = vv;
char *target = get_overwrite(2, write_count_after);
memcpy(target, &v, 2);
}
void StreamBuffer::overwrite_uint32(int64_t write_count_after, uint64_t vv) {
assert(safe_to_cast_to_uint32(vv));
uint32_t v = vv;
char *target = get_overwrite(4, write_count_after);
memcpy(target, &v, 4);
}
void StreamBuffer::overwrite_uint64(int64_t write_count_after, uint64_t vv) {
assert(safe_to_cast_to_uint64(vv));
uint64_t v = vv;
char *target = get_overwrite(8, write_count_after);
memcpy(target, &v, 8);
}
bool StreamBuffer::at_eof() {
return (read_cursor_ == write_cursor_);
}
@@ -350,6 +435,10 @@ static bool streq(const char *str, const char *data) {
return memcmp(str, data, len) == 0;
}
static void write_ztbytes(StreamBuffer *sb, const char *bytes) {
sb->write_bytes(bytes, strlen(bytes));
}
LuaDefine(unittests_streambuffer, "c") {
// An 11-byte fixed-size stream buffer.
StreamBuffer sb11(11, true);
@@ -358,7 +447,7 @@ LuaDefine(unittests_streambuffer, "c") {
assert(sb11.layout_is(0, 0, 11));
// Write a few bytes.
sb11.write_ztbytes("abcdef");
write_ztbytes(&sb11, "abcdef");
assert(sb11.layout_is(0, 6, 5));
// Try reading some bytes.
@@ -381,13 +470,13 @@ LuaDefine(unittests_streambuffer, "c") {
assert(sb11.layout_is(6, 0, 5));
// Write some more bytes into the stream, forcing a shift-left
sb11.write_ztbytes("ghijkl");
write_ztbytes(&sb11, "ghijkl");
assert(sb11.layout_is(0, 6, 5));
// Test buffer wrapping a little more.
assert(streq("ghi", sb11.read_bytes(3)));
assert(sb11.layout_is(3, 3, 5));
sb11.write_ztbytes("mnopqr");
write_ztbytes(&sb11, "mnopqr");
assert(sb11.layout_is(0, 9, 2));
assert(streq("jklmnopqr", sb11.read_bytes(9)));
assert(sb11.layout_is(9, 0, 2));