// ------------------------------------------------------------------------ // Project atila // Active Thing (activething.com) git.activething.com/go // // File name bfield_list.go // Created by DEV // Modified 19/02/2024 // // Copyright 2024 activething.com // ------------------------------------------------------------------------ // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ------------------------------------------------------------------------ package bfields import ( "bytes" ) type ( BFields struct { Att fields []BField } BFieldsFnc func (bfls *BFields) error BFieldsWalkFnc func(index int, field *BField) bool ) func NewBFields (options ...BFieldsFnc) (*BFields,error) { fs := &BFields{} for _,o := range options { if er := o(fs); er != nil { return nil,er } } if fs.IsReadOnly() { //todo } return fs,nil } func (f BFields) Get(nme []byte) *BField { if ix := findField(f.fields, 0, nme); ix != notFound { f.get(ix) } return nil } func (f BFields) get(index int) *BField { if f.IsReadOnly() { vl := f.fields[index] return &vl } return &f.fields[index] } func (f *BFields) Add(nme, val []byte) error { if f.IsFixed() { return G.ErrFixed } if ix := findField(f.fields, 0, nme); ix != notFound { if !f.IsMultiple() { return G.ErrDuplicated } } fl, er := NewBField(nme, val) if er != nil { return er } f.fields = append(f.fields, *fl) return nil } func (f *BFields) Del(nme []byte) error { if f.IsFixed() { return G.ErrFixed } if f.IsReadOnly() { return G.ErrReadOnly } fm := 0 ix := -1 ln := len(f.fields) for { if ix = findField(f.fields, fm, nme); ix == notFound { break } f.fields[ix] = f.fields[ln-1] f.fields = f.fields[:ln-1] ln -= 1 if !f.IsMultiple() || ix == ln-1 { break } fm = ix } return nil } func (f *BFields) Upsert(nme, val []byte) error { if len(nme) == 0 { return nil } if f.IsReadOnly() { return G.ErrReadOnly } if ix := findField(f.fields, 0, nme); ix != -1 { f.fields[ix].SetValue(val) return nil } if f.IsFixed() { return G.ErrFixed } fl, er := NewBField(nme, val) if er != nil { return er } f.fields = append(f.fields, *fl) return nil } func (f BFields) Len() int { return len(f.fields) } func (f BFields) Has(nme []byte) bool { return findField(f.fields, 0, nme) != notFound } func (f BFields) Count(nme []byte) int { rs := 0 for _, fl := range f.fields { if bytes.Equal(fl.name, nme) { rs++ } } return rs } func (f BFields) Walk(walker BFieldsWalkFnc) { for ln, ix := len(f.fields), 0; ix < ln; ix++ { if !walker(ix, f.get(ix)) { return } } } func findField(list []BField, from int, name []byte) int { for ln, ix := len(list), from; ix < ln; ix++ { if bytes.Equal(list[ix].name, name) { return ix } } return notFound } func WithField(nme, val []byte) BFieldsFnc { return func(f *BFields) error { return f.Add(nme, val) }} func WithAtts(atts Att) BFieldsFnc { return func(f *BFields) error { f.Att = atts return nil } }