// Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com). // All rights reserved. // array-type.go package array import ( "fmt" "strings" "git.portale-stac.it/go-pkg/expr/kern" ) type ArrayType []any func IsArray(v any) (ok bool) { _, ok = v.(*ArrayType) return ok } func NewIntArrayA(listInt ...int) (aRef *ArrayType) { a := make(ArrayType, len(listInt)) for i, v := range listInt { a[i] = int64(v) } return &a } func NewArrayA(listAny ...any) (aRef *ArrayType) { if listAny == nil { listAny = []any{} } return NewArray(listAny) } func NewArray(arrayAny []any) (aRef *ArrayType) { if arrayAny != nil { a := make(ArrayType, len(arrayAny)) copy(a, arrayAny) aRef = &a } return } func MakeArray(length, capacity int) (list *ArrayType) { if capacity < length { capacity = length } ls := make(ArrayType, length, capacity) list = &ls return } func ArrayFromStrings(stringSlice []string) (aRef *ArrayType) { aRef = MakeArray(len(stringSlice), 0) for i, s := range stringSlice { (*aRef)[i] = s } return } func ArrayFromIntsA(ints ...int) (aRef *ArrayType) { return ArrayFromInts(ints) } func ArrayFromInts(intSlice []int) (aRef *ArrayType) { aRef = MakeArray(len(intSlice), 0) for i, s := range intSlice { (*aRef)[i] = int64(s) } return } func (aRef *ArrayType) ToString(opt kern.FmtOpt) (s string) { indent := kern.GetFormatIndent(opt) flags := kern.GetFormatFlags(opt) var sb strings.Builder sb.WriteByte('[') if len(*aRef) > 0 { innerOpt := kern.MakeFormatOptions(flags, indent+1) nest := strings.Repeat(" ", indent+1) if flags&kern.MultiLine != 0 { sb.WriteByte('\n') sb.WriteString(nest) } for i, item := range []any(*aRef) { if i > 0 { if flags&kern.MultiLine != 0 { sb.WriteString(",\n") sb.WriteString(nest) } else { sb.WriteString(", ") } } kern.Format(&sb, item, innerOpt) } if flags&kern.MultiLine != 0 { sb.WriteByte('\n') sb.WriteString(strings.Repeat(" ", indent)) } } sb.WriteByte(']') s = sb.String() if flags&kern.Truncate != 0 && len(s) > kern.TruncateSize { s = kern.TruncateString(s) } return } func (aRef *ArrayType) String() string { return aRef.ToString(0) } func (aRef *ArrayType) TypeName() string { return kern.TypeArray } func (aRef *ArrayType) Contains(t *ArrayType) (answer bool) { if len(*aRef) >= len(*t) { answer = true for _, item := range *t { if answer = aRef.IndexDeepSameCmp(item) >= 0; !answer { break } } } return } func (aRef *ArrayType) EqualTo(other kern.Equaler) (equal bool) { if otherList, ok := other.(*ArrayType); ok { equal = aRef.Equals(*otherList) } return } func (aRef *ArrayType) Equals(ls2 ArrayType) (answer bool) { if ls2 != nil && len(*aRef) == len(ls2) { answer = true for index, i1 := range *aRef { // if !reflect.DeepEqual(i1, ls2[index]) { // answer = false // break // } if !kern.Equal(i1, ls2[index]) { answer = false break } } } return } func (aRef *ArrayType) Clone() kern.Cloner { ls := make(ArrayType, len(*aRef)) for i, item := range *aRef { ls[i] = kern.Clone(item) } return &ls } func (aRef *ArrayType) IndexDeepSameCmp(target any) (index int64) { index = -1 for i, item := range *aRef { if kern.Equal(item, target) { index = int64(i) break } } return } // func (ls *ListType) IndexDeepSameCmp(target any) (index int) { // var eq bool // var err error // index = -1 // for i, item := range *ls { // if eq, err = deepSame(item, target, SameContent); err != nil { // break // } else if eq { // index = i // break // } // } // return // } func SameContent(a, b any) (same bool, err error) { aRef, aValid := a.(*ArrayType) bRef, bValid := b.(*ArrayType) if !aValid || !bValid { err = fmt.Errorf("invalid type for comparison") return } if len(*aRef) == len(*bRef) { same = true for _, item := range *aRef { if pos := bRef.IndexDeepSameCmp(item); pos < 0 { same = false break } } } return } // func deepSame(a, b any, deepCmp kern.DeepFuncTemplate) (eq bool, err error) { // if IsNumOrFract(a) && IsNumOrFract(b) { // if IsNumber(a) && IsNumber(b) { // if IsInteger(a) && IsInteger(b) { // li, _ := a.(int64) // ri, _ := b.(int64) // eq = li == ri // } else { // eq = NumAsFloat(a) == NumAsFloat(b) // } // } else { // var cmp int // if cmp, err = fract.CmpAnyFract(a, b); err == nil { // eq = cmp == 0 // } // } // } else if deepCmp != nil && IsList(a) && IsList(b) { // eq, err = deepCmp(a, b) // } else { // eq = reflect.DeepEqual(a, b) // } // return // } func (aRef *ArrayType) SetItem(index int64, value any) (err error) { if index >= 0 && index < int64(len(*aRef)) { (*aRef)[index] = value } else { err = fmt.Errorf("index %d out of bounds (0, %d)", index, len(*aRef)-1) } return } func (aRef *ArrayType) AppendItem(value any) { *aRef = append(*aRef, value) }