You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

185 lines
3.4 KiB

// ------------------------------------------------------------------------
// 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 (
"activething.com/go/gogo/core/opts"
"activething.com/go/gogo/core/slices"
"bytes"
)
type (
BFields struct {
BFieldsAtt
fields []BField
}
BFieldsWalkFnc func(index int, field *BField) bool
)
func NewBFields (options ...opts.OptionErrFnc[BFields]) (*BFields,error) {
fs,er := opts.ApplyAndCheck(&BFields{},options...)
if er != nil {
return nil,er
}
if fs.IsReadOnly() {
}
return fs,nil
}
func (f BFields) Get(nme []byte) *BField {
if ix := findField(f.fields, 0, nme); ix != slices.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 != slices.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 == slices.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) != slices.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 slices.NotFound
}

Powered by TurnKey Linux.