723 lines
20 KiB
C++
723 lines
20 KiB
C++
#include "lib.h"
|
|
#include "rawlist.cc"
|
|
|
|
TypeTree DB_TYPE;
|
|
NameTree DB_NAME;
|
|
//Pool<Type::Schema> DB_SCHEMA;
|
|
Pool<Reference> DB_DATA;
|
|
|
|
extern "C" size_t type_outer(size_t type_id, size_t key)
|
|
{
|
|
return DB_TYPE.outer(type_id, key);
|
|
}
|
|
|
|
extern "C" size_t type_inner(size_t type_id)
|
|
{
|
|
return DB_TYPE.inner(type_id);
|
|
}
|
|
|
|
extern "C" size_t type_key(size_t type_id)
|
|
{
|
|
return DB_TYPE.key(type_id);
|
|
}
|
|
|
|
extern "C" size_t type_size(size_t type_id)
|
|
{
|
|
if(DB_TYPE.has(type_id)) {
|
|
size_t type = DB_TYPE.key(type_id);
|
|
|
|
switch(type) {
|
|
case Type::Tag::Null: return 0;
|
|
case Type::Tag::Varying: return sizeof(Reference);
|
|
case Type::Tag::Boolean: return sizeof(Type::Boolean);
|
|
case Type::Tag::Natural: return sizeof(Type::Natural);
|
|
case Type::Tag::Integer: return sizeof(Type::Integer);
|
|
case Type::Tag::Block: return DB_TYPE.key(DB_TYPE.inner(type_id));
|
|
case Type::Tag::Sequence: return sizeof(Type::Sequence);
|
|
case Type::Tag::Array: {
|
|
size_t length = DB_TYPE.inner(type_id);
|
|
size_t inner = DB_TYPE.inner(length);
|
|
return static_cast<size_t>(DB_TYPE.key(length)) * type_size(inner);
|
|
};
|
|
case Type::Tag::List: return sizeof(Type::List);
|
|
case Type::Tag::Record: {
|
|
//if(DB_SCHEMA.has(type_key(type_inner(type_id)))) {
|
|
// return DB_SCHEMA.get().size;
|
|
//}
|
|
return 0;
|
|
}
|
|
case Type::Tag::Schema: return sizeof(Type::Schema);
|
|
default: return 0;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
extern "C" size_t name_indexof(const uint8_t* bytes, size_t length)
|
|
{
|
|
std::string str(reinterpret_cast<const char*>(bytes), length);
|
|
return DB_NAME.indexof(str);
|
|
}
|
|
|
|
extern "C" Str name_keyof(size_t index)
|
|
{
|
|
Str result {0};
|
|
std::string str = DB_NAME.keyof(index);
|
|
if(str.length() > 0) {
|
|
result.bytes = new uint8_t[str.length()];
|
|
}
|
|
for(size_t i = 0; i < str.length(); ++i) {
|
|
result.bytes[i] = str[i];
|
|
}
|
|
result.length = str.length();
|
|
return result;
|
|
}
|
|
|
|
std::string name_keyof_internal(size_t index)
|
|
{
|
|
return DB_NAME.keyof(index);
|
|
}
|
|
|
|
extern "C" void name_release(Str data)
|
|
{
|
|
if(data.bytes != nullptr) {
|
|
delete[] data.bytes;
|
|
}
|
|
}
|
|
|
|
void* allocate(size_t type_id, size_t count)
|
|
{
|
|
void* mem = nullptr;
|
|
size_t size = type_size(type_id) * count;
|
|
if(size > 0) {
|
|
mem = malloc(size);
|
|
if(mem != nullptr) {
|
|
memset(mem, 0, size);
|
|
}
|
|
return mem;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
extern "C" Reference acquire(size_t type_id)
|
|
{
|
|
Reference addr {0};
|
|
addr.address = allocate(type_id, 1);
|
|
if(addr.address != nullptr) {
|
|
addr.type = type_id;
|
|
}
|
|
return addr;
|
|
}
|
|
|
|
void drop(Reference addr)
|
|
{
|
|
if(addr.address != nullptr) {
|
|
switch(type_key(addr.type)) {
|
|
case Type::Tag::Boolean:
|
|
case Type::Tag::Natural:
|
|
case Type::Tag::Integer:
|
|
case Type::Tag::Block:
|
|
break;
|
|
|
|
case Type::Tag::Varying: {
|
|
auto& var = *reinterpret_cast<Reference*>(addr.address);
|
|
if(var.address != nullptr) {
|
|
drop(var);
|
|
}
|
|
var.type = 0;
|
|
var.address = nullptr;
|
|
} break;
|
|
|
|
case Type::Tag::Sequence: {
|
|
auto& seq = *reinterpret_cast<Type::Sequence*>(addr.address);
|
|
rawlist_clear(seq.data);
|
|
} break;
|
|
|
|
case Type::Tag::List: {
|
|
Type::List& list = *reinterpret_cast<Type::List*>(addr.address);
|
|
for(size_t i = 0; i < list.data.length; ++i) {
|
|
drop(list_cell(addr, i));
|
|
}
|
|
rawlist_clear(list.data);
|
|
} break;
|
|
}
|
|
memset(addr.address, 0, type_size(addr.type));
|
|
}
|
|
}
|
|
|
|
extern "C" void release(Reference addr)
|
|
{
|
|
if(addr.address != nullptr) {
|
|
drop(addr);
|
|
free(addr.address);
|
|
}
|
|
}
|
|
|
|
bool copy(Reference src, Reference dst)
|
|
{
|
|
Reference source = src;
|
|
Reference destination = dst;
|
|
|
|
// dereference varying data
|
|
if(type_key(src.type) == Type::Tag::Varying) {
|
|
source = *reinterpret_cast<Reference*>(src.address);
|
|
}
|
|
|
|
// prepare destination for varying data
|
|
if(type_key(dst.type) == Type::Tag::Varying) {
|
|
auto& dest_ref = *reinterpret_cast<Reference*>(dst.address);
|
|
|
|
// determine if memory can be reused, otherwise free and reallocate
|
|
if(source.type != dest_ref.type) {
|
|
if(dest_ref.address != nullptr) {
|
|
free(dest_ref.address);
|
|
dest_ref.type = Type::Tag::Null;
|
|
dest_ref.address = nullptr;
|
|
}
|
|
dest_ref = acquire(source.type);
|
|
}
|
|
}
|
|
|
|
// copy data into destination
|
|
if(source.type == destination.type) {
|
|
switch(type_key(destination.type)) {
|
|
case Type::Tag::Null: { } break;
|
|
|
|
case Type::Tag::Boolean:
|
|
case Type::Tag::Natural:
|
|
case Type::Tag::Integer:
|
|
case Type::Tag::Block:
|
|
{
|
|
memcpy(destination.address, source.address, type_size(source.type));
|
|
} break;
|
|
|
|
case Type::Tag::List: {
|
|
auto& src_list = *reinterpret_cast<Type::List*>(source.address);
|
|
auto& dst_list = *reinterpret_cast<Type::List*>(destination.address);
|
|
|
|
rawlist_reserve(dst_list.data, type_size(type_inner(source.type)), src_list.data.capacity);
|
|
dst_list.data.length = src_list.data.length;
|
|
//dst_list.data = allocate(type_inner(source.type), src_list.capacity);
|
|
|
|
for(size_t i = 0; i < src_list.data.length; ++i) {
|
|
copy(list_at(source, i), list_at(destination, i));
|
|
}
|
|
} break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
// Varying //
|
|
|
|
extern "C" Reference varying_get(Reference addr)
|
|
{
|
|
Reference result {0};
|
|
result = *reinterpret_cast<Reference*>(addr.address);
|
|
return result;
|
|
}
|
|
|
|
extern "C" void varying_set(Reference addr, Reference source)
|
|
{
|
|
Reference& var = *reinterpret_cast<Reference*>(addr.address);
|
|
|
|
if(var.address != nullptr) {
|
|
drop(var);
|
|
}
|
|
|
|
if(var.type != source.type || var.address == nullptr) {
|
|
if(var.address != nullptr) {
|
|
free(var.address);
|
|
}
|
|
var.type = source.type;
|
|
var.address = allocate(source.type, 1);
|
|
}
|
|
|
|
copy(source, var);
|
|
}
|
|
|
|
extern "C" void varying_clear(Reference addr)
|
|
{
|
|
Reference& var = *reinterpret_cast<Reference*>(addr.address);
|
|
|
|
if(var.address != nullptr) {
|
|
drop(var);
|
|
free(var.address);
|
|
var.type = 0;
|
|
var.address = nullptr;
|
|
}
|
|
}
|
|
|
|
|
|
// Boolean //
|
|
|
|
extern "C" void bool_set(Reference addr, Type::Boolean value)
|
|
{
|
|
*(reinterpret_cast<Type::Boolean*>(addr.address)) = value;
|
|
}
|
|
|
|
extern "C" Type::Boolean bool_get(Reference addr)
|
|
{
|
|
return *(reinterpret_cast<Type::Boolean*>(addr.address));
|
|
}
|
|
|
|
|
|
// Natural //
|
|
|
|
extern "C" void natural_set(Reference addr, Type::Natural value)
|
|
{
|
|
*(reinterpret_cast<Type::Natural*>(addr.address)) = value;
|
|
}
|
|
|
|
extern "C" Type::Natural natural_get(Reference addr)
|
|
{
|
|
return *(reinterpret_cast<Type::Natural*>(addr.address));
|
|
}
|
|
|
|
|
|
// Integer //
|
|
|
|
extern "C" void integer_set(Reference addr, Type::Integer value)
|
|
{
|
|
*(reinterpret_cast<Type::Integer*>(addr.address)) = value;
|
|
}
|
|
|
|
extern "C" Type::Integer integer_get(Reference addr)
|
|
{
|
|
return *(reinterpret_cast<Type::Integer*>(addr.address));
|
|
}
|
|
|
|
|
|
// Block //
|
|
|
|
extern "C" size_t block_length(Reference addr)
|
|
{
|
|
return type_key(type_inner(addr.type));
|
|
}
|
|
|
|
extern "C" uint8_t block_get(Reference addr, size_t index)
|
|
{
|
|
size_t length = type_key(type_inner(addr.type));
|
|
if(index < length) {
|
|
return reinterpret_cast<uint8_t*>(addr.address)[index];
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
extern "C" void block_set(Reference addr, size_t index, uint8_t value)
|
|
{
|
|
size_t length = type_key(type_inner(addr.type));
|
|
if(index < length) {
|
|
reinterpret_cast<uint8_t*>(addr.address)[index] = value;
|
|
}
|
|
}
|
|
|
|
|
|
// Sequence //
|
|
|
|
extern "C" size_t sequence_length(Reference addr)
|
|
{
|
|
Type::Sequence& seq = *reinterpret_cast<Type::Sequence*>(addr.address);
|
|
return seq.data.length;
|
|
}
|
|
|
|
extern "C" uint8_t sequence_get(Reference addr, size_t index)
|
|
{
|
|
Type::Sequence& seq = *reinterpret_cast<Type::Sequence*>(addr.address);
|
|
if(index < seq.data.length) {
|
|
return *reinterpret_cast<uint8_t*>(rawlist_cell(seq.data, 1, index));
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
extern "C" void sequence_clear(Reference addr)
|
|
{
|
|
Type::Sequence& seq = *reinterpret_cast<Type::Sequence*>(addr.address);
|
|
rawlist_clear(seq.data);
|
|
}
|
|
|
|
extern "C" void sequence_set(Reference addr, size_t index, uint8_t value)
|
|
{
|
|
Type::Sequence& seq = *reinterpret_cast<Type::Sequence*>(addr.address);
|
|
auto cell = reinterpret_cast<uint8_t*>(rawlist_cell(seq.data, 1, index));
|
|
if(cell != nullptr) {
|
|
*cell = value;
|
|
}
|
|
}
|
|
|
|
extern "C" void sequence_insert(Reference addr, size_t index, uint8_t value)
|
|
{
|
|
Type::Sequence& seq = *reinterpret_cast<Type::Sequence*>(addr.address);
|
|
auto cell = reinterpret_cast<uint8_t*>(rawlist_insert(seq.data, 1, index));
|
|
if(cell != nullptr) {
|
|
*cell = value;
|
|
}
|
|
}
|
|
|
|
extern "C" void sequence_reserve(Reference addr, size_t capacity)
|
|
{
|
|
Type::Sequence& seq = *reinterpret_cast<Type::Sequence*>(addr.address);
|
|
rawlist_reserve(seq.data, 1, capacity);
|
|
}
|
|
|
|
|
|
// Array //
|
|
|
|
extern "C" size_t array_length(Reference addr)
|
|
{
|
|
return type_key(type_inner(addr.type));
|
|
}
|
|
|
|
Reference array_cell(Reference addr, size_t index)
|
|
{
|
|
Reference result {0};
|
|
size_t length_n = type_inner(addr.type);
|
|
size_t length = type_key(length_n);
|
|
size_t type = type_inner(length_n);
|
|
size_t offset = type_size(type);
|
|
|
|
// validate for overflow
|
|
if(addr.address != nullptr && offset > 0 && index < length) {
|
|
result.type = type;
|
|
result.address = reinterpret_cast<void*>(reinterpret_cast<size_t>(addr.address) + (offset * index));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
extern "C" Reference array_at(Reference addr, size_t index)
|
|
{
|
|
Reference result {0};
|
|
Reference cell = array_cell(addr, index);
|
|
if(cell.address != nullptr) {
|
|
if(type_key(cell.type) == Type::Tag::Varying) {
|
|
result = varying_get(cell);
|
|
}
|
|
else {
|
|
result = cell;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
extern "C" void array_update(Reference addr, size_t index, Reference source)
|
|
{
|
|
Reference cell = array_cell(addr, index);
|
|
if(type_key(cell.type) == Type::Tag::Varying) {
|
|
varying_set(cell, source);
|
|
}
|
|
else {
|
|
copy(source, cell);
|
|
}
|
|
}
|
|
|
|
|
|
// List //
|
|
|
|
extern "C" size_t list_capacity(Reference addr)
|
|
{
|
|
return (*reinterpret_cast<Type::List*>(addr.address)).data.capacity;
|
|
}
|
|
|
|
extern "C" size_t list_length(Reference addr)
|
|
{
|
|
return (*reinterpret_cast<Type::List*>(addr.address)).data.length;
|
|
}
|
|
|
|
Reference list_cell(Reference addr, size_t index)
|
|
{
|
|
Reference result {0};
|
|
Type::List& list = *reinterpret_cast<Type::List*>(addr.address);
|
|
size_t inner = type_inner(addr.type);
|
|
size_t offset = type_size(inner);
|
|
|
|
// validate for overflow
|
|
if(list.data.data != nullptr && offset > 0 && index < list.data.capacity) {
|
|
result.type = inner;
|
|
result.address = rawlist_cell(list.data, offset, index);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
extern "C" Reference list_at(Reference addr, size_t index)
|
|
{
|
|
Reference result {0};
|
|
Reference cell = list_cell(addr, index);
|
|
|
|
if(cell.address != nullptr) {
|
|
if(type_key(cell.type) == Type::Tag::Varying) {
|
|
result = *reinterpret_cast<Reference*>(cell.address);
|
|
} else {
|
|
result = cell;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/*extern "C" Reference list_first(Reference addr)
|
|
{
|
|
Reference result {0};
|
|
if(type_key(addr.type) == Type::Tag::List) {
|
|
auto& list = (*reinterpret_cast<Type::List*>(addr.address));
|
|
if(list.length > 0) {
|
|
result = list_at(addr, 0);
|
|
}
|
|
}
|
|
return result;
|
|
}*/
|
|
|
|
/*extern "C" Reference list_last(Reference addr)
|
|
{
|
|
Reference result {0};
|
|
if(type_key(addr.type) == Type::Tag::List) {
|
|
auto& list = (*reinterpret_cast<Type::List*>(addr.address));
|
|
if(list.length > 0) {
|
|
result = list_at(addr, list.length - 1);
|
|
}
|
|
}
|
|
return result;
|
|
}*/
|
|
|
|
extern "C" void list_clear(Reference addr)
|
|
{
|
|
drop(addr);
|
|
}
|
|
|
|
/*extern "C" void list_prepend(Reference addr, Reference source)
|
|
{
|
|
if(type_key(addr.type) == Type::Tag::List) {
|
|
size_t inner = type_inner(addr.type);
|
|
//size_t offset = type_size(inner);
|
|
|
|
// validate list can store value
|
|
if(type_key(inner) == Type::Tag::Varying || source.type == inner) {
|
|
auto& list = (*reinterpret_cast<Type::List*>(addr.address));
|
|
|
|
if(list.length == list.capacity) {
|
|
list_reserve(addr, list.capacity * 2);
|
|
}
|
|
|
|
// copy source to cell
|
|
|
|
list.length++;
|
|
}
|
|
}
|
|
}*/
|
|
|
|
/*extern "C" void list_append(Reference addr, Reference source)
|
|
{
|
|
if(type_key(addr.type) == Type::Tag::List) {
|
|
Type::List& list = *reinterpret_cast<Type::List*>(addr.address);
|
|
size_t inner = type_inner(addr.type);
|
|
//size_t offset = type_size(inner);
|
|
|
|
// validate list can store value
|
|
if(type_key(inner) == Type::Tag::Varying || source.type == inner) {
|
|
if(list.length == list.capacity) {
|
|
list_reserve(addr, list.capacity * 2);
|
|
}
|
|
|
|
// copy source to cell
|
|
|
|
list.length++;
|
|
}
|
|
}
|
|
}*/
|
|
|
|
extern "C" void list_insert(Reference addr, size_t index, Reference source)
|
|
{
|
|
auto& list = (*reinterpret_cast<Type::List*>(addr.address));
|
|
size_t inner = type_inner(addr.type);
|
|
size_t offset = type_size(inner);
|
|
|
|
if(index > list.data.length) { index = list.data.length; }
|
|
|
|
void* cell = rawlist_insert(list.data, offset, index);
|
|
|
|
if(type_key(inner) == Type::Tag::Varying) {
|
|
varying_set(list_cell(addr, index), source);
|
|
}
|
|
else {
|
|
copy(source, list_cell(addr, index));
|
|
}
|
|
}
|
|
|
|
extern "C" void list_update(Reference addr, size_t index, Reference source)
|
|
{
|
|
auto& list = (*reinterpret_cast<Type::List*>(addr.address));
|
|
if(index < list.data.length) {
|
|
size_t inner = type_inner(addr.type);
|
|
size_t offset = type_size(inner);
|
|
|
|
if(type_key(inner) == Type::Tag::Varying) {
|
|
varying_set(list_cell(addr, index), source);
|
|
}
|
|
else {
|
|
copy(source, list_cell(addr, index));
|
|
}
|
|
}
|
|
}
|
|
|
|
/*extern "C" void list_truncate(Reference addr, size_t maximum)
|
|
{
|
|
if(type_key(addr.type) == Type::Tag::List) {
|
|
//auto& list = (*reinterpret_cast<Type::List*>(addr.address));
|
|
|
|
}
|
|
}*/
|
|
|
|
/*extern "C" void list_shift(Reference addr)
|
|
{
|
|
if(type_key(addr.type) == Type::Tag::List) {
|
|
//auto& list = (*reinterpret_cast<Type::List*>(addr.address));
|
|
|
|
}
|
|
}*/
|
|
|
|
extern "C" void list_remove(Reference addr, size_t index)
|
|
{
|
|
auto& list = (*reinterpret_cast<Type::List*>(addr.address));
|
|
size_t inner = type_inner(addr.type);
|
|
size_t offset = type_size(inner);
|
|
|
|
|
|
drop(list_at(addr, index));
|
|
rawlist_remove(list.data, offset, index);
|
|
}
|
|
|
|
extern "C" void list_reserve(Reference addr, size_t capacity)
|
|
{
|
|
auto& list = (*reinterpret_cast<Type::List*>(addr.address));
|
|
size_t inner = type_inner(addr.type);
|
|
size_t offset = type_size(inner);
|
|
|
|
rawlist_reserve(list.data, offset, capacity);
|
|
}
|
|
|
|
/*extern "C" void list_resize(Reference addr, size_t length)
|
|
{
|
|
if(type_key(addr.type) == Type::Tag::List) {
|
|
//auto& list = (*reinterpret_cast<Type::List*>(addr.address));
|
|
|
|
}
|
|
}*/
|
|
|
|
|
|
// Schema //
|
|
|
|
extern "C" size_t schema_length(Reference addr)
|
|
{
|
|
auto& object = (*reinterpret_cast<Type::Schema*>(addr.address));
|
|
return object.data.length;
|
|
}
|
|
|
|
extern "C" size_t schema_add(Reference addr, size_t type_id)
|
|
{
|
|
auto& object = (*reinterpret_cast<Type::Schema*>(addr.address));
|
|
void* cell = rawlist_insert(object.data, sizeof(size_t), object.data.length);
|
|
*reinterpret_cast<size_t*>(cell) = type_id;
|
|
return object.data.length - 1;
|
|
}
|
|
|
|
extern "C" void schema_remove(Reference addr, size_t index)
|
|
{
|
|
auto& object = (*reinterpret_cast<Type::Schema*>(addr.address));
|
|
if(index < object.data.length) {
|
|
|
|
}
|
|
}
|
|
|
|
extern "C" void schema_reorder(Reference addr, size_t index_from, size_t index_to)
|
|
{
|
|
auto& object = (*reinterpret_cast<Type::Schema*>(addr.address));
|
|
if(index_from < object.data.length && index_to <= object.data.length) {
|
|
if(index_from > index_to) {
|
|
|
|
}
|
|
else {
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
extern "C" void schema_map(Reference addr, size_t key, size_t index)
|
|
{
|
|
auto& object = (*reinterpret_cast<Type::Schema*>(addr.address));
|
|
if(index < object.data.length) {
|
|
size_t find_index = 0;
|
|
for(; find_index < object.map.length; find_index++) {
|
|
auto cell = reinterpret_cast<Type::Schema::Mapping*>(rawlist_cell(object.map, sizeof(Type::Schema::Mapping), find_index));
|
|
if(cell != nullptr) {
|
|
if(cell->key == key) { break; }
|
|
}
|
|
}
|
|
|
|
// if key is not found, add new mapping
|
|
if(find_index == object.map.length) {
|
|
auto cell = reinterpret_cast<Type::Schema::Mapping*>(rawlist_insert(object.map, sizeof(Type::Schema::Mapping), object.map.length));
|
|
cell->key = key;
|
|
cell->index = index;
|
|
}
|
|
// otherwise, update existing key
|
|
else {
|
|
auto cell = reinterpret_cast<Type::Schema::Mapping*>(rawlist_cell(object.map, sizeof(Type::Schema::Mapping), find_index));
|
|
cell->index = index;
|
|
}
|
|
}
|
|
}
|
|
|
|
extern "C" void schema_unmap(Reference addr, size_t key)
|
|
{
|
|
auto& object = (*reinterpret_cast<Type::Schema*>(addr.address));
|
|
for(size_t i; i < object.map.length; i++) {
|
|
auto cell = reinterpret_cast<Type::Schema::Mapping*>(rawlist_cell(object.map, sizeof(Type::Schema::Mapping), i));
|
|
if(cell != nullptr) {
|
|
if(cell->key == key) {
|
|
rawlist_remove(object.map, sizeof(Type::Schema::Mapping), i);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
extern "C" size_t schema_index(Reference addr, size_t key)
|
|
{
|
|
auto& object = (*reinterpret_cast<Type::Schema*>(addr.address));
|
|
for(size_t i = 0; i < object.map.length; i++) {
|
|
auto cell = reinterpret_cast<Type::Schema::Mapping*>(rawlist_cell(object.map, sizeof(Type::Schema::Mapping), i));
|
|
if(cell != nullptr) {
|
|
if(cell->key == key) {
|
|
return cell->index;
|
|
}
|
|
}
|
|
}
|
|
return object.data.length;
|
|
}
|
|
|
|
extern "C" size_t schema_bind(Reference addr, size_t id)
|
|
{
|
|
Type::SchemaBinding binding {0};
|
|
auto& object = (*reinterpret_cast<Type::Schema*>(addr.address));
|
|
|
|
// prepare binding
|
|
binding.schema = object;
|
|
binding.binding = id;
|
|
for(size_t i = 0; i < object.data.length; ++i) {
|
|
size_t type_id = *reinterpret_cast<size_t*>(rawlist_cell(object.data, sizeof(size_t), i));
|
|
size_t size = type_size(type_id);
|
|
size_t alignment = size;
|
|
binding.alignment = std::max(alignment, binding.alignment);
|
|
size_t position = ((binding.size + (alignment - 1)) & ~(alignment - 1));
|
|
binding.size = size + position;
|
|
}
|
|
binding.size = ((binding.size + (binding.alignment - 1)) & ~(binding.alignment - 1));
|
|
|
|
// add binding to pool
|
|
//DB_SCHEMA.add(id, binding);
|
|
|
|
return id;
|
|
}
|