Files
expr/types/dict/dict-type.go
T
2026-07-14 06:50:56 +02:00

220 lines
4.1 KiB
Go

// Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com).
// All rights reserved.
// dict-type.go
package dict
import (
"fmt"
"reflect"
"strings"
"git.portale-stac.it/go-pkg/expr/kern"
)
const DictTypeName = "dict"
type DictType map[any]any
func IsDict(v any) (ok bool) {
_, ok = v.(*DictType)
return ok
}
func MakeDict() (dict *DictType) {
d := make(DictType)
dict = &d
return
}
func NewDict(dictAny map[any]any) (dict *DictType) {
var d DictType
if dictAny != nil {
d = make(DictType, len(dictAny))
for i, item := range dictAny {
d[i] = item
}
} else {
d = make(DictType)
}
dict = &d
return
}
func newDict(dictAny map[any]kern.Term) (dict *DictType) {
// TODO Change with a call to NewDict()
var d DictType
if dictAny != nil {
d = make(DictType, len(dictAny))
for i, item := range dictAny {
d[i] = item
}
} else {
d = make(DictType)
}
dict = &d
return
}
func (dict *DictType) toMultiLine(sb *strings.Builder, opt kern.FmtOpt) {
indent := kern.GetFormatIndent(opt)
flags := kern.GetFormatFlags(opt)
//sb.WriteString(strings.Repeat(" ", indent))
sb.WriteByte('{')
if len(*dict) > 0 {
innerOpt := kern.MakeFormatOptions(flags, indent+1)
nest := strings.Repeat(" ", indent+1)
sb.WriteByte('\n')
first := true
for name, value := range *dict {
if first {
first = false
} else {
sb.WriteByte(',')
sb.WriteByte('\n')
}
sb.WriteString(nest)
if key, ok := name.(string); ok {
sb.WriteByte('"')
sb.WriteString(key)
sb.WriteByte('"')
} else {
fmt.Fprintf(sb, "%v", name)
}
sb.WriteString(": ")
if f, ok := value.(kern.Formatter); ok {
sb.WriteString(f.ToString(innerOpt))
} else if _, ok = value.(kern.Functor); ok {
sb.WriteString("func(){}")
} else {
fmt.Fprintf(sb, "%v", value)
}
}
sb.WriteByte('\n')
sb.WriteString(strings.Repeat(" ", indent))
}
sb.WriteString("}")
}
func (dict *DictType) ToString(opt kern.FmtOpt) string {
var sb strings.Builder
flags := kern.GetFormatFlags(opt)
if flags&kern.MultiLine != 0 {
dict.toMultiLine(&sb, opt)
} else {
sb.WriteByte('{')
first := true
for key, value := range *dict {
if first {
first = false
} else {
sb.WriteString(", ")
}
if s, ok := key.(string); ok {
sb.WriteByte('"')
sb.WriteString(s)
sb.WriteByte('"')
} else {
fmt.Fprintf(&sb, "%v", key)
}
sb.WriteString(": ")
if formatter, ok := value.(kern.Formatter); ok {
sb.WriteString(formatter.ToString(opt))
} else if t, ok := value.(kern.Term); ok {
sb.WriteString(t.String())
} else {
fmt.Fprintf(&sb, "%#v", value)
}
}
sb.WriteByte('}')
}
return sb.String()
}
func (dict *DictType) String() string {
return dict.ToString(0)
}
func (dict *DictType) TypeName() string {
return DictTypeName
}
func (dict *DictType) HasKey(target any) (ok bool) {
for key := range *dict {
if ok = reflect.DeepEqual(key, target); ok {
break
}
}
return
}
func (dict *DictType) SetItem(key any, value any) {
(*dict)[key] = value
}
func (dict *DictType) GetItem(key any) (value any, exists bool) {
value, exists = (*dict)[key]
return
}
func (dict *DictType) FindKey(item any) (key any, exists bool) {
for k, v := range *dict {
if kern.Equal(v, item) {
key = k
exists = true
break
}
}
return
}
func (dict *DictType) Clone() kern.Cloner {
c := newDict(nil)
for k, v := range *dict {
(*c)[k] = kern.Clone(v)
}
return c
}
func (dict *DictType) Merge(second *DictType) {
if second != nil {
for k, v := range *second {
(*dict)[k] = v
}
}
}
func (dict *DictType) EqualTo(other kern.Equaler) (answer bool) {
if dict2, ok := other.(*DictType); ok {
answer = dict.Equals(*dict2)
}
return
}
func (dict *DictType) Equals(dict2 DictType) (answer bool) {
if dict2 != nil && len(*dict) == len(dict2) {
answer = true
for key, value1 := range *dict {
if value2, exists := dict2.GetItem(key); exists {
if !kern.Equal(value1, value2) {
answer = false
break
}
} else {
answer = false
break
}
}
}
return
}
////////////////
// type DictFormat interface {
// ToDict() *DictType
// }