vua/multiarray.v
2025-06-19 22:38:38 -05:00

101 lines
2.2 KiB
V

module multiarray
struct MultiArray[T] {
mut:
len int
cap int
tags map[int]string
fields map[string]MultiArrayField
}
struct MultiArrayField {
data voidptr
}
fn MultiArray.new[T](len int, cap int, init T) MultiArray[T] {
mut result := MultiArray[T]{len: len, cap: cap}
$for field in T.fields {
result.fields[field.name + 's'] = MultiArrayField{
data: unsafe { vcalloc(u64(cap) * sizeof(T)) }
}
}
return result
}
fn (mut ma MultiArray[T]) add[T](table string, item T) {
if ma.len >= ma.cap {
unsafe { ma.grow() }
}
$for field in T.fields {
if field.name == table {
ma.tags[ma.len] = table
ma.len++
}
field_name := field.name + 's'
mut field_data_ptr := unsafe { ma.fields[field_name].data }
unsafe { vmemcpy(&u8(field_data_ptr) + sizeof(T) * u64(ma.len), item, sizeof(T)) }
}
}
@[unsafe]
fn (mut ma MultiArray[T]) grow() {
new_cap := if ma.cap == 0 { 1 } else { ma.cap * 2 }
$for field in T.fields {
field_name := field.name + 's'
old_data := &T(ma.fields[field_name].data)
new_data := vcalloc(u64(new_cap) * sizeof(T))
vmemcpy(new_data, old_data, u64(ma.len) * sizeof(T))
ma.fields[field_name] = MultiArrayField{ data: new_data }
}
ma.cap = new_cap
}
fn (ma MultiArray[T]) get(index int) ?T {
if index < 0 || index >= ma.len {
return none
}
mut result := T{}
$for field in T.fields {
field_name := field.name + 's'
field_data_ptr := unsafe { ma.fields[field_name].data }
unsafe { vmemcpy(&result, &u8(field_data_ptr) + sizeof(T) * u64(index), sizeof(T)) }
}
return result
}
@[unsafe]
fn (mut ma MultiArray[T]) free() {
$for field in T.fields {
field_name := field.name + 's'
if ma.fields[field_name].data != nil {
free( ma.fields[field_name].data )
ma.fields[field_name] = MultiArrayField{nil}
}
}
ma.len = 0; ma.cap = 0
}
fn (mut ma MultiArray[T]) iter() Iterator[T] {
return Iterator[T]{ma,0}
}
struct Iterator[T] {
mut:
ma MultiArray[T]
i int
}
struct IteratorEntry[T] {
tag string
data T
}
fn (mut it Iterator[T]) next() ?IteratorEntry[T] {
defer { it.i++ }
if it.i >= it.ma.len {
return none
}
val := it.ma.get(it.i) or {
return none
}
return IteratorEntry[T]{it.ma.tags[it.i],val}
}