Skip to content

Commit

Permalink
add cpp basic io interaction
Browse files Browse the repository at this point in the history
  • Loading branch information
Brat-vseznamus committed Nov 15, 2024
1 parent f18ca08 commit b82be3f
Show file tree
Hide file tree
Showing 4 changed files with 514 additions and 0 deletions.
329 changes: 329 additions & 0 deletions pkg/basictl/cpp/basictl.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,329 @@
// Code generated by vktl/cmd/tlgen2; DO NOT EDIT.
#include "basictl.h"

#define TLGEN2_UNLIKELY(x) \
(x) // __builtin_expect((x), 0) // could improve performance on your platform
#define TLGEN2_NOINLINE // __attribute__ ((noinline)) // could improve performance on your platform

namespace basictl {
tl_istream::tl_istream(tl_istream_interface *provider) : provider(provider) {}

tl_istream::~tl_istream() {
this->last_release();
}

bool tl_istream::nat_read(uint32_t &value) { return fetch_data(&value, 4); }

bool tl_istream::nat_read_exact_tag(uint32_t tag) {
uint32_t actual_tag = 0;
if (TLGEN2_UNLIKELY(!nat_read(actual_tag))) {
return false;
}
if (TLGEN2_UNLIKELY(tag != actual_tag)) {
return set_error_expected_tag();
}
return true;
}

bool tl_istream::int_read(int32_t &value) { return fetch_data(&value, 4); }

bool tl_istream::long_read(int64_t &value) { return fetch_data(&value, 8); }

bool tl_istream::float_read(float &value) { return fetch_data(&value, 4); }

bool tl_istream::double_read(double &value) { return fetch_data(&value, 8); }

bool tl_istream::bool_read(bool &value, uint32_t f, uint32_t t) {
uint32_t tag = 0;
if (TLGEN2_UNLIKELY(!nat_read(tag))) {
return false;
}
if (tag == t) {
value = true;
return true;
}
if (TLGEN2_UNLIKELY(tag != f)) {
set_error_bool_tag();
}
value = false;
return true;
}

bool tl_istream::string_read(std::string &value) {
if (TLGEN2_UNLIKELY(!ensure_byte())) {
return false;
}
auto len = size_t(static_cast<unsigned char>(*ptr));
if (TLGEN2_UNLIKELY(len >= TL_BIG_STRING_MARKER)) {
if (TLGEN2_UNLIKELY(len > TL_BIG_STRING_MARKER)) {
return set_error("TODO - huge string");
}
uint32_t len32 = 0;
if (TLGEN2_UNLIKELY(!nat_read(len32))) {
return false;
}
len = len32 >> 8U;
value.clear();
if (TLGEN2_UNLIKELY(!fetch_data_append(value, len))) {
return false;
}
if (TLGEN2_UNLIKELY(!fetch_pad((-len) & 3))) {
return false;
}
return true;
}
auto pad = ((-(len + 1)) & 3);
auto fullLen = 1 + len + pad;
if (TLGEN2_UNLIKELY(ptr + fullLen > end_block)) {
ptr += 1;
value.clear();
if (TLGEN2_UNLIKELY(!fetch_data_append(value, len))) {
return false;
}
if (TLGEN2_UNLIKELY(!fetch_pad(pad))) {
return false;
}
return true;
}
// fast path for short strings that fully fit in buffer
uint32_t x = 0;
std::memcpy(&x, ptr + fullLen - 4, 4);
if (TLGEN2_UNLIKELY((x & ~(0xFFFFFFFFU >> (8 * pad))) != 0)) {
return set_error_string_padding();
}
value.assign(ptr + 1, len);
ptr += fullLen;
return true;
}

void tl_istream::last_release() {
provider->release_buffer(ptr - start_block);
start_block = ptr;
}

bool tl_istream::has_error() {
return hasError;
}

bool tl_istream::set_error(const char *e) {
hasError = true;
return false;
} // TODO - set error field

bool tl_istream::set_error_eof() { return set_error("EOF"); }

bool tl_istream::set_error_sequence_length() { return set_error("sequence_length"); }

bool tl_istream::set_error_string_padding() { return set_error("string_padding"); }

bool tl_istream::set_error_bool_tag() { return set_error("bool_tag"); }

bool tl_istream::set_error_expected_tag() { return set_error("expected_tag"); }

bool tl_istream::set_error_union_tag() { return set_error("union_tag"); }

void tl_istream::grow_buffer() {
ptr = end_block;
provider->release_buffer(ptr - start_block);
auto new_buffer = provider->get_buffer();
ptr = reinterpret_cast<const char *>(new_buffer.data());
start_block = ptr;
end_block = ptr + new_buffer.size();
}

bool tl_istream::ensure_byte() {
if (TLGEN2_UNLIKELY(ptr >= end_block)) {
// assert(ptr <= end)
grow_buffer();
// assert(ptr <= end)
if (TLGEN2_UNLIKELY(ptr == end_block)) {
return set_error_eof();
}
}
return true;
}

bool tl_istream::fetch_data(void *vdata, size_t size) {
char *data = reinterpret_cast<char *>(vdata);
if (TLGEN2_UNLIKELY(ptr + size > end_block)) {
return fetch_data2(vdata, size);
}
std::memcpy(data, ptr, size);
ptr += size;
return true;
}

bool tl_istream::fetch_data2(void *vdata, size_t size) {
char *data = reinterpret_cast<char *>(vdata);
for (; TLGEN2_UNLIKELY(ptr + size > end_block);) {
// assert(ptr <= end)
std::memcpy(data, ptr, end_block - ptr);
data += end_block - ptr;
size -= end_block - ptr;
grow_buffer();
// assert(ptr <= end)
if (TLGEN2_UNLIKELY(ptr == end_block)) {
return set_error_eof();
}
}
std::memcpy(data, ptr, size);
ptr += size;
return true;
}

bool tl_istream::fetch_data_append(std::string &value, size_t size) {
for (; TLGEN2_UNLIKELY(ptr + size > end_block);) {
// assert(ptr <= end)
value.append(ptr, end_block - ptr);
size -= end_block - ptr;
grow_buffer();
// assert(ptr <= end)
if (TLGEN2_UNLIKELY(ptr == end_block)) {
return set_error_eof();
}
}
value.append(ptr, size);
ptr += size;
return true;
}

bool tl_istream::fetch_pad(size_t len) {
uint32_t x = 0;
if (TLGEN2_UNLIKELY(!fetch_data(&x, len))) {
return false;
}
if (TLGEN2_UNLIKELY(x != 0)) {
return set_error_string_padding();
}
return true;
}


tl_ostream::tl_ostream(tl_ostream_interface *provider) {
this->provider = provider;
}

tl_ostream::~tl_ostream() {
this->last_release();
}

bool tl_ostream::nat_write(uint32_t value) { return store_data(&value, 4); }

bool tl_ostream::int_write(int32_t value) { return store_data(&value, 4); }

bool tl_ostream::long_write(int64_t value) { return store_data(&value, 8); }

bool tl_ostream::float_write(float value) { return store_data(&value, 4); }

bool tl_ostream::double_write(double value) { return store_data(&value, 8); }

bool tl_ostream::string_write(const std::string &value) {
auto len = value.size();
if (TLGEN2_UNLIKELY(len > TL_MAX_TINY_STRING_LEN)) {
if (TLGEN2_UNLIKELY(len > TL_BIG_STRING_LEN)) {
return set_error("TODO - huge string");
}
uint32_t p = (len << 8U) | TL_BIG_STRING_MARKER;
if (TLGEN2_UNLIKELY(!store_data(&p, 4))) {
return false;
}
if (TLGEN2_UNLIKELY(!store_data(value.data(), value.size()))) {
return false;
}
if (TLGEN2_UNLIKELY(!store_pad((-len) & 3))) {
return false;
}
return true;
}
auto pad = ((-(len + 1)) & 3);
auto fullLen = 1 + len + pad;
if (TLGEN2_UNLIKELY(ptr + fullLen > end_block)) {
auto p = static_cast<unsigned char>(len);
if (TLGEN2_UNLIKELY(!store_data(&p, 1))) {
return false;
}
if (TLGEN2_UNLIKELY(!store_data(value.data(), value.size()))) {
return false;
}
if (TLGEN2_UNLIKELY(!store_pad(pad))) {
return false;
}
return true;
}
// fast path for short strings that fully fit in buffer
uint32_t x = 0;
std::memcpy(ptr + fullLen - 4, &x, 4); // padding first
*ptr = static_cast<char>(len);
std::memcpy(ptr + 1, value.data(), len);
ptr += fullLen;
return true;
}

void tl_ostream::last_release() {
provider->release_buffer(ptr - start_block);
start_block = ptr;
}

bool tl_ostream::has_error() {
return hasError;
}

bool tl_ostream::set_error(const char *e) {
hasError = true;
return false;
} // TODO - set error field

bool tl_ostream::set_error_eof() { return set_error("EOF"); }

bool tl_ostream::set_error_sequence_length() { return set_error("sequence_length"); }

void tl_ostream::grow_buffer() {
ptr = end_block;
provider->release_buffer(ptr - start_block);
auto new_buffer = provider->get_buffer();
ptr = reinterpret_cast<char *>(new_buffer.data());
start_block = ptr;
end_block = ptr + new_buffer.size();
}

bool tl_ostream::store_data(const void *vdata, size_t size) {
const char *data = reinterpret_cast<const char *>(vdata);
for (; TLGEN2_UNLIKELY(ptr + size > end_block);) {
// assert(ptr <= end)
std::memcpy(ptr, data, end_block - ptr);
data += end_block - ptr;
size -= end_block - ptr;
grow_buffer();
// assert(ptr <= end)
if (TLGEN2_UNLIKELY(ptr == end_block)) {
return set_error_eof();
}
}
std::memcpy(ptr, data, size);
ptr += size;
return true;
}

bool tl_ostream::store_pad(size_t size) {
for (; TLGEN2_UNLIKELY(ptr + size > end_block);) {
// assert(ptr <= end)
std::memset(ptr, 0, end_block - ptr);
size -= end_block - ptr;
grow_buffer();
// assert(ptr <= end)
if (TLGEN2_UNLIKELY(ptr == end_block)) {
return set_error_eof();
}
}
if (size != 0) {
ptr[0] = 0;
ptr[size - 1] = 0;
ptr[size / 2] = 0;
ptr += size;
}
return true;
}
} // namespace basictl

#undef TLGEN2_NOINLINE
#undef TLGEN2_UNLIKELY
Loading

0 comments on commit b82be3f

Please sign in to comment.