101 lines
2.2 KiB
V
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}
|
|
}
|