tile38/internal/field/list_struct.go

85 lines
1.8 KiB
Go

//go:build exclude
package field
type List struct {
entries []Field
}
// bsearch searches array for value.
func (fields List) bsearch(name string) (index int, found bool) {
i, j := 0, len(fields.entries)
for i < j {
h := i + (j-i)/2
if name >= fields.entries[h].name {
i = h + 1
} else {
j = h
}
}
if i > 0 && fields.entries[i-1].name >= name {
return i - 1, true
}
return i, false
}
func (fields List) Set(field Field) List {
var updated List
index, found := fields.bsearch(field.name)
if found {
if field.value.IsZero() {
// delete
if len(fields.entries) > 1 {
updated.entries = make([]Field, len(fields.entries)-1)
copy(updated.entries, fields.entries[:index])
copy(updated.entries[index:], fields.entries[index+1:])
}
} else if !fields.entries[index].value.Equals(field.value) {
// update
updated.entries = make([]Field, len(fields.entries))
copy(updated.entries, fields.entries)
updated.entries[index].value = field.value
} else {
// nothing changes
updated = fields
}
return updated
}
if field.Value().IsZero() {
return fields
}
updated.entries = make([]Field, len(fields.entries)+1)
copy(updated.entries, fields.entries[:index])
copy(updated.entries[index+1:], fields.entries[index:])
updated.entries[index] = field
return updated
}
func (fields List) Get(name string) Field {
index, found := fields.bsearch(name)
if !found {
return ZeroField
}
return fields.entries[index]
}
func (fields List) Scan(iter func(field Field) bool) {
for _, f := range fields.entries {
if !iter(f) {
return
}
}
}
func (fields List) Len() int {
return len(fields.entries)
}
func (fields List) Weight() int {
var weight int
for _, f := range fields.entries {
weight += f.Weight()
}
return weight
}