From ca68b80b38aaaec178855f4d722fb34eae91a04c Mon Sep 17 00:00:00 2001 From: Alexei Anoshenko Date: Fri, 22 May 2026 15:54:35 -0400 Subject: [PATCH] Optimisation --- CHANGELOG.md | 1 + animation.go | 9 +- background.go | 9 +- backgroundConicGradient.go | 3 +- backgroundLinearGradient.go | 13 +- backgroundRadialGradient.go | 26 +- bounds.go | 162 +++++++----- clipShape.go | 3 +- datePicker.go | 9 +- dragAndDrop.go | 108 ++++---- editView.go | 3 + propertySet.go | 475 +++++++++++++++++++----------------- range.go | 19 +- 13 files changed, 439 insertions(+), 401 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8865dd5..c49e3b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * Added GoogleFonts field to AppParams * Added functions: GetWhiteSpace, GetWordBreak, ScrollIntoViewIfNeeded * Added PopupShowAnimation and SetPopupShowAnimation methods to Session interface +* Added ToBoundsProperty method to Bounds struct # v0.20.0 diff --git a/animation.go b/animation.go index 53f65e8..c98775e 100644 --- a/animation.go +++ b/animation.go @@ -423,11 +423,9 @@ func animationSet(properties Properties, tag PropertyName, value any) []Property if text, ok := value.(string); ok { text = strings.Trim(text, " \t\n\r") if text == "" { - properties.setRaw(tag, nil) - } else { - properties.setRaw(tag, text) + return removeProperty(properties, tag) } - return []PropertyName{tag} + return setPropertyValue(properties, tag, text) } notCompatibleType(tag, value) return nil @@ -571,8 +569,7 @@ func animationSet(properties Properties, tag PropertyName, value any) []Property case TimingFunction: if text, ok := value.(string); ok { - properties.setRaw(tag, text) - return []PropertyName{tag} + return setPropertyValue(properties, tag, text) } case IterationCount: diff --git a/background.go b/background.go index 7e50655..28386f0 100644 --- a/background.go +++ b/background.go @@ -178,14 +178,11 @@ func setBackgroundProperty(properties Properties, tag PropertyName, value any) [ return nil } - if len(background) > 0 { - properties.setRaw(tag, background) - } else if properties.getRaw(tag) != nil { - properties.setRaw(tag, nil) - } else { - return []PropertyName{} + if len(background) == 0 { + return removeProperty(properties, tag) } + properties.setRaw(tag, background) return []PropertyName{tag} } diff --git a/backgroundConicGradient.go b/backgroundConicGradient.go index fdca691..207fcf5 100644 --- a/backgroundConicGradient.go +++ b/backgroundConicGradient.go @@ -167,8 +167,7 @@ func backgroundConicGradientSet(properties Properties, tag PropertyName, value a return []PropertyName{tag} } } else if ok, _ := isConstantName(value); ok { - properties.setRaw(Gradient, value) - return []PropertyName{tag} + return setPropertyValue(properties, Gradient, value) } ErrorLogF(`Invalid conic gradient: "%s"`, value) diff --git a/backgroundLinearGradient.go b/backgroundLinearGradient.go index ca0ef8b..b8838c9 100644 --- a/backgroundLinearGradient.go +++ b/backgroundLinearGradient.go @@ -104,8 +104,7 @@ func backgroundGradientSet(properties Properties, tag PropertyName, value any) [ switch value := value.(type) { case string: if ok, _ := isConstantName(value); ok { - properties.setRaw(Gradient, value) - return []PropertyName{tag} + return setPropertyValue(properties, tag, value) } if strings.ContainsAny(value, " ,") { @@ -319,16 +318,14 @@ func backgroundLinearGradientSet(properties Properties, tag PropertyName, value if tag == Direction { switch value := value.(type) { case AngleUnit: - properties.setRaw(Direction, value) - return []PropertyName{tag} + return setPropertyValue(properties, tag, value) case string: - if setSimpleProperty(properties, tag, value) { - return []PropertyName{tag} + if result := setSimpleProperty(properties, tag, value); result != nil { + return result } if angle, ok := StringToAngleUnit(value); ok { - properties.setRaw(Direction, angle) - return []PropertyName{tag} + return setPropertyValue(properties, tag, angle) } case LinearGradientDirectionType: diff --git a/backgroundRadialGradient.go b/backgroundRadialGradient.go index 9a1026e..d02ef3f 100644 --- a/backgroundRadialGradient.go +++ b/backgroundRadialGradient.go @@ -141,25 +141,23 @@ func backgroundRadialGradientSet(properties Properties, tag PropertyName, value case []SizeUnit: switch len(value) { case 0: - properties.setRaw(RadialGradientRadius, nil) + return removeProperty(properties, tag) case 1: if value[0].Type == Auto { - properties.setRaw(RadialGradientRadius, nil) - } else { - properties.setRaw(RadialGradientRadius, value[0]) + return removeProperty(properties, tag) } + return setPropertyValue(properties, tag, value[0]) default: properties.setRaw(RadialGradientRadius, value) + return []PropertyName{tag} } - return []PropertyName{tag} case []any: switch len(value) { case 0: - properties.setRaw(RadialGradientRadius, nil) - return []PropertyName{tag} + return removeProperty(properties, tag) case 1: return backgroundRadialGradientSet(properties, RadialGradientRadius, value[0]) @@ -170,26 +168,24 @@ func backgroundRadialGradientSet(properties Properties, tag PropertyName, value } case string: - if setSimpleProperty(properties, RadialGradientRadius, value) { - return []PropertyName{tag} + if result := setSimpleProperty(properties, tag, value); result != nil { + return result } if size, err := stringToSizeUnit(value); err == nil { if size.Type == Auto { - properties.setRaw(RadialGradientRadius, nil) + return removeProperty(properties, tag) } else { - properties.setRaw(RadialGradientRadius, size) + return setPropertyValue(properties, tag, size) } - return []PropertyName{tag} } return setEnumProperty(properties, RadialGradientRadius, value, enumProperties[RadialGradientRadius].values) case SizeUnit: if value.Type == Auto { - properties.setRaw(RadialGradientRadius, nil) + return removeProperty(properties, tag) } else { - properties.setRaw(RadialGradientRadius, value) + return setPropertyValue(properties, tag, value) } - return []PropertyName{tag} case RadialGradientRadiusType: return setEnumProperty(properties, RadialGradientRadius, int(value), enumProperties[RadialGradientRadius].values) diff --git a/bounds.go b/bounds.go index d7a288b..8d82570 100644 --- a/bounds.go +++ b/bounds.go @@ -107,6 +107,26 @@ func DefaultBounds() Bounds { } } +// ToBoundsProperty() convert Bounds to BoundsProperty. +// The fields with Auto value will not be set in the result BoundsProperty. +func (bounds *Bounds) ToBoundsProperty() BoundsProperty { + result := NewBoundsProperty(nil) + if bounds.Top.Type != Auto { + result.setRaw(Top, bounds.Top) + } + if bounds.Right.Type != Auto { + result.setRaw(Right, bounds.Right) + } + if bounds.Bottom.Type != Auto { + result.setRaw(Bottom, bounds.Bottom) + } + if bounds.Left.Type != Auto { + result.setRaw(Left, bounds.Left) + } + + return result +} + // SetAll set the Top, Right, Bottom and Left field to the equal value func (bounds *Bounds) SetAll(value SizeUnit) { bounds.Top = value @@ -179,80 +199,90 @@ func (bounds *Bounds) cssString(session Session) string { } func setBoundsProperty(properties Properties, tag PropertyName, value any) []PropertyName { - if !setSimpleProperty(properties, tag, value) { - switch value := value.(type) { - case string: - if strings.ContainsRune(value, ',') { - values := split4Values(value) - count := len(values) - switch count { - case 1: - value = values[0] + if result := setSimpleProperty(properties, tag, value); result != nil { + return result + } - case 4: - bounds := NewBoundsProperty(nil) - for i, tag := range []PropertyName{Top, Right, Bottom, Left} { - if !bounds.Set(tag, values[i]) { - return nil - } + switch value := value.(type) { + case string: + if strings.ContainsRune(value, ',') { + values := split4Values(value) + switch count := len(values); count { + case 1: + return setSizeProperty(properties, tag, value[0]) + + case 5: + text := strings.Trim(values[4], " \t\n\r") + if text != "" { + notCompatibleType(tag, value) + return nil + } + fallthrough + + case 4: + bounds := NewBoundsProperty(nil) + for i, tag := range []PropertyName{Top, Right, Bottom, Left} { + if !bounds.Set(tag, values[i]) { + return nil } - properties.setRaw(tag, bounds) - return []PropertyName{tag} + } - default: + if bounds.IsEmpty() { + return removeProperty(properties, tag) + } + properties.setRaw(tag, bounds) + return []PropertyName{tag} + + default: + notCompatibleType(tag, value) + return nil + } + } + return setSizeProperty(properties, tag, value) + + case SizeUnit: + return setPropertyValue(properties, tag, value) + + case float32: + return setPropertyValue(properties, tag, Px(float64(value))) + + case float64: + return setPropertyValue(properties, tag, Px(value)) + + case Bounds: + bounds := value.ToBoundsProperty() + if bounds.IsEmpty() { + return removeProperty(properties, tag) + } + properties.setRaw(tag, bounds) + + case BoundsProperty: + if value.IsEmpty() { + return removeProperty(properties, tag) + } + properties.setRaw(tag, value) + + case DataObject: + bounds := NewBoundsProperty(nil) + for _, tag := range []PropertyName{Top, Right, Bottom, Left} { + if text, ok := value.PropertyValue(string(tag)); ok { + if !bounds.Set(tag, text) { notCompatibleType(tag, value) return nil } } - return setSizeProperty(properties, tag, value) + } + if bounds.IsEmpty() { + return removeProperty(properties, tag) + } + properties.setRaw(tag, bounds) - case SizeUnit: - properties.setRaw(tag, value) - - case float32: - properties.setRaw(tag, Px(float64(value))) - - case float64: - properties.setRaw(tag, Px(value)) - - case Bounds: - bounds := NewBoundsProperty(nil) - if value.Top.Type != Auto { - bounds.setRaw(Top, value.Top) - } - if value.Right.Type != Auto { - bounds.setRaw(Right, value.Right) - } - if value.Bottom.Type != Auto { - bounds.setRaw(Bottom, value.Bottom) - } - if value.Left.Type != Auto { - bounds.setRaw(Left, value.Left) - } - properties.setRaw(tag, bounds) - - case BoundsProperty: - properties.setRaw(tag, value) - - case DataObject: - bounds := NewBoundsProperty(nil) - for _, tag := range []PropertyName{Top, Right, Bottom, Left} { - if text, ok := value.PropertyValue(string(tag)); ok { - if !bounds.Set(tag, text) { - notCompatibleType(tag, value) - return nil - } - } - } - properties.setRaw(tag, bounds) - - default: - if n, ok := isInt(value); ok { - properties.setRaw(tag, Px(float64(n))) - } else { - notCompatibleType(tag, value) - return nil - } + default: + if n, ok := isInt(value); ok { + return setPropertyValue(properties, tag, Px(float64(n))) + } else { + notCompatibleType(tag, value) + return nil } } diff --git a/clipShape.go b/clipShape.go index a43d99a..ba18ae5 100644 --- a/clipShape.go +++ b/clipShape.go @@ -635,8 +635,7 @@ func setClipShapePropertyProperty(properties Properties, tag PropertyName, value case string: if ok, _ := isConstantName(value); ok { - properties.setRaw(tag, value) - return []PropertyName{tag} + return setPropertyValue(properties, tag, value) } if obj := NewDataObject(value); obj == nil { diff --git a/datePicker.go b/datePicker.go index ddcbfaf..2cfef6a 100644 --- a/datePicker.go +++ b/datePicker.go @@ -214,18 +214,15 @@ func (picker *datePickerData) setFunc(tag PropertyName, value any) []PropertyNam setDateValue := func(tag PropertyName) []PropertyName { switch value := value.(type) { case time.Time: - picker.setRaw(tag, value) - return []PropertyName{tag} + return setPropertyValue(picker, tag, value) case string: if ok, _ := isConstantName(value); ok { - picker.setRaw(tag, value) - return []PropertyName{tag} + return setPropertyValue(picker, tag, value) } if date, ok := stringToDate(value); ok { - picker.setRaw(tag, date) - return []PropertyName{tag} + return setPropertyValue(picker, tag, date) } } diff --git a/dragAndDrop.go b/dragAndDrop.go index e37e1fb..b261cf0 100644 --- a/dragAndDrop.go +++ b/dragAndDrop.go @@ -285,43 +285,39 @@ func stringToDropEffect(text string) (int, bool) { } func (view *viewData) setDropEffect(value any) []PropertyName { - if !setSimpleProperty(view, DropEffect, value) { - if text, ok := value.(string); ok { + if result := setSimpleProperty(view, DropEffect, value); result != nil { + return result + } - if n, ok := stringToDropEffect(text); ok { - if n == DropEffectUndefined { - view.setRaw(DropEffect, nil) - } else { - view.setRaw(DropEffect, n) - } - } else { - invalidPropertyValue(DropEffect, value) - return nil - } + var newValue int + if text, ok := value.(string); ok { - } else if i, ok := isInt(value); ok { - - switch i { - case DropEffectUndefined: - view.setRaw(DropEffect, nil) - - case DropEffectCopy, DropEffectMove, DropEffectLink: - view.setRaw(DropEffect, i) - - default: - invalidPropertyValue(DropEffect, value) - return nil - } - - } else { - - notCompatibleType(DropEffect, value) + if newValue, ok = stringToDropEffect(text); !ok { + invalidPropertyValue(DropEffect, value) return nil } + } else if i, ok := isInt(value); ok { + + newValue = i + + } else { + + notCompatibleType(DropEffect, value) + return nil } - return []PropertyName{DropEffect} + switch newValue { + case DropEffectUndefined: + return removeProperty(view, DropEffect) + + case DropEffectCopy, DropEffectMove, DropEffectLink: + return setPropertyValue(view, DropEffect, newValue) + + default: + invalidPropertyValue(DropEffect, value) + return nil + } } func stringToDropEffectAllowed(text string) (int, bool) { @@ -348,39 +344,35 @@ func stringToDropEffectAllowed(text string) (int, bool) { } func (view *viewData) setDropEffectAllowed(value any) []PropertyName { - if !setSimpleProperty(view, DropEffectAllowed, value) { - if text, ok := value.(string); ok { - if n, ok := stringToDropEffectAllowed(text); ok { - if n == DropEffectUndefined { - view.setRaw(DropEffectAllowed, nil) - } else { - view.setRaw(DropEffectAllowed, n) - } - } else { - invalidPropertyValue(DropEffectAllowed, value) - return nil - } + if result := setSimpleProperty(view, DropEffectAllowed, value); result != nil { + return result + } - } else { - n, ok := isInt(value) - if !ok { - notCompatibleType(DropEffectAllowed, value) - return nil - } - - if n == DropEffectUndefined { - view.setRaw(DropEffectAllowed, nil) - } else if n > DropEffectUndefined && n <= DropEffectAll { - view.setRaw(DropEffectAllowed, n) - } else { - notCompatibleType(DropEffectAllowed, value) - return nil - } + var newValue int + if text, ok := value.(string); ok { + if newValue, ok = stringToDropEffectAllowed(text); !ok { + invalidPropertyValue(DropEffectAllowed, value) + return nil + } + } else { + var ok bool + if newValue, ok = isInt(value); !ok { + notCompatibleType(DropEffectAllowed, value) + return nil } } - return []PropertyName{DropEffectAllowed} + if newValue == DropEffectUndefined { + return removeProperty(view, DropEffectAllowed) + } + + if newValue < DropEffectUndefined || newValue > DropEffectAll { + notCompatibleType(DropEffectAllowed, value) + return nil + } + + return setPropertyValue(view, DropEffectAllowed, newValue) } func handleDragAndDropEvents(view View, tag PropertyName, data DataObject) { diff --git a/editView.go b/editView.go index 4279e2e..5634718 100644 --- a/editView.go +++ b/editView.go @@ -166,6 +166,9 @@ func (edit *editViewData) setFunc(tag PropertyName, value any) []PropertyName { old := "" if val := edit.getRaw(Text); val != nil { if txt, ok := val.(string); ok { + if txt == text { + return []PropertyName{} + } old = txt } } diff --git a/propertySet.go b/propertySet.go index d5c07e2..9e56a34 100644 --- a/propertySet.go +++ b/propertySet.go @@ -561,280 +561,309 @@ func isInt(value any) (int, bool) { return n, true } -func setSimpleProperty(properties Properties, tag PropertyName, value any) bool { - if value == nil { - properties.setRaw(tag, nil) - return true - } else if text, ok := value.(string); ok { - text = strings.Trim(text, " \t\n\r") - if text == "" { - properties.setRaw(tag, nil) - return true - } - if ok, _ := isConstantName(text); ok { - properties.setRaw(tag, text) - return true +func setPropertyValue[T comparable](properties Properties, tag PropertyName, value T) []PropertyName { + if oldValue := properties.getRaw(tag); oldValue != nil { + if oldTypedValue, ok := oldValue.(T); ok && oldTypedValue == value { + return []PropertyName{} } } - return false -} -func setStringPropertyValue(properties Properties, tag PropertyName, text any) []PropertyName { - if text != "" { - properties.setRaw(tag, text) - } else if properties.getRaw(tag) != nil { - properties.setRaw(tag, nil) - } else { - return []PropertyName{} - } + properties.setRaw(tag, value) return []PropertyName{tag} } -func setArrayPropertyValue[T any](properties Properties, tag PropertyName, value []T) []PropertyName { - if len(value) > 0 { - properties.setRaw(tag, value) - } else if properties.getRaw(tag) != nil { +func removeProperty(properties Properties, tag PropertyName) []PropertyName { + if properties.getRaw(tag) != nil { properties.setRaw(tag, nil) - } else { - return []PropertyName{} + return []PropertyName{tag} } + return []PropertyName{} +} + +func setSimpleProperty(properties Properties, tag PropertyName, value any) []PropertyName { + if value == nil { + return removeProperty(properties, tag) + } + + if text, ok := value.(string); ok { + text = strings.Trim(text, " \t\n\r") + if text == "" { + return removeProperty(properties, tag) + } + + if oldValue := properties.getRaw(tag); oldValue != nil { + if oldText, ok := oldValue.(string); ok && oldText == text { + return []PropertyName{} + } + } + + if ok, _ := isConstantName(text); ok { + properties.setRaw(tag, text) + return []PropertyName{tag} + } + } + return nil +} + +func setStringPropertyValue(properties Properties, tag PropertyName, text string) []PropertyName { + if text == "" { + return removeProperty(properties, tag) + } + + return setPropertyValue(properties, tag, text) +} + +func setArrayPropertyValue[T any](properties Properties, tag PropertyName, value []T) []PropertyName { + if len(value) == 0 { + return removeProperty(properties, tag) + } + /* + oldValue := properties.getRaw(tag) + if oldValue != nil { + if oldArray, ok := oldValue.([]T); ok && slices.Equal(oldArray, value) { + return []PropertyName{} + } + } + */ + properties.setRaw(tag, value) return []PropertyName{tag} } func setSizeProperty(properties Properties, tag PropertyName, value any) []PropertyName { - if !setSimpleProperty(properties, tag, value) { - var size SizeUnit - switch value := value.(type) { - case string: - var ok bool - if fn := parseSizeFunc(value); fn != nil { - size.Type = SizeFunction - size.Function = fn - } else if size, ok = StringToSizeUnit(value); !ok { - invalidPropertyValue(tag, value) - return nil - } - case SizeUnit: - size = value + if result := setSimpleProperty(properties, tag, value); result != nil { + return result + } - case SizeFunc: + var size SizeUnit + switch value := value.(type) { + case string: + var ok bool + if fn := parseSizeFunc(value); fn != nil { size.Type = SizeFunction - size.Function = value - - case float32: - size.Type = SizeInPixel - size.Value = float64(value) - - case float64: - size.Type = SizeInPixel - size.Value = value - - default: - if n, ok := isInt(value); ok { - size.Type = SizeInPixel - size.Value = float64(n) - } else { - notCompatibleType(tag, value) - return nil - } + size.Function = fn + } else if size, ok = StringToSizeUnit(value); !ok { + invalidPropertyValue(tag, value) + return nil } + case SizeUnit: + size = value - if size.Type == Auto { - properties.setRaw(tag, nil) + case SizeFunc: + size.Type = SizeFunction + size.Function = value + + case float32: + size.Type = SizeInPixel + size.Value = float64(value) + + case float64: + size.Type = SizeInPixel + size.Value = value + + default: + if n, ok := isInt(value); ok { + size.Type = SizeInPixel + size.Value = float64(n) } else { - properties.setRaw(tag, size) + notCompatibleType(tag, value) + return nil } } - return []PropertyName{tag} + if size.Type == Auto { + return removeProperty(properties, tag) + } + return setPropertyValue(properties, tag, size) } func setAngleProperty(properties Properties, tag PropertyName, value any) []PropertyName { - if !setSimpleProperty(properties, tag, value) { - var angle AngleUnit - switch value := value.(type) { - case string: - var ok bool - if angle, ok = StringToAngleUnit(value); !ok { - invalidPropertyValue(tag, value) - return nil - } - case AngleUnit: - angle = value - - case float32: - angle = Rad(float64(value)) - - case float64: - angle = Rad(value) - - default: - if n, ok := isInt(value); ok { - angle = Rad(float64(n)) - } else { - notCompatibleType(tag, value) - return nil - } - } - properties.setRaw(tag, angle) + if result := setSimpleProperty(properties, tag, value); result != nil { + return result } - return []PropertyName{tag} + var angle AngleUnit + switch value := value.(type) { + case string: + var ok bool + if angle, ok = StringToAngleUnit(value); !ok { + invalidPropertyValue(tag, value) + return nil + } + case AngleUnit: + angle = value + + case float32: + angle = Rad(float64(value)) + + case float64: + angle = Rad(value) + + default: + if n, ok := isInt(value); ok { + angle = Rad(float64(n)) + } else { + notCompatibleType(tag, value) + return nil + } + } + + return setPropertyValue(properties, tag, angle) } func setColorProperty(properties Properties, tag PropertyName, value any) []PropertyName { - if !setSimpleProperty(properties, tag, value) { - var result Color - switch value := value.(type) { - case string: - var err error - if result, err = stringToColor(value); err != nil { - invalidPropertyValue(tag, value) - return nil - } - case Color: - result = value - - default: - if color, ok := isInt(value); ok { - result = Color(color) - } else { - notCompatibleType(tag, value) - return nil - } - } - - properties.setRaw(tag, result) + if result := setSimpleProperty(properties, tag, value); result != nil { + return result } - return []PropertyName{tag} + var result Color + switch value := value.(type) { + case string: + var err error + if result, err = stringToColor(value); err != nil { + invalidPropertyValue(tag, value) + return nil + } + case Color: + result = value + + default: + if color, ok := isInt(value); ok { + result = Color(color) + } else { + notCompatibleType(tag, value) + return nil + } + } + + return setPropertyValue(properties, tag, result) } func setEnumProperty(properties Properties, tag PropertyName, value any, values []string) []PropertyName { - if !setSimpleProperty(properties, tag, value) { - var n int - if text, ok := value.(string); ok { - if n, ok = enumStringToInt(text, values, false); !ok { - invalidPropertyValue(tag, value) - return nil - } - } else if i, ok := isInt(value); ok { - if i < 0 || i >= len(values) { - invalidPropertyValue(tag, value) - return nil - } - n = i - } else { - notCompatibleType(tag, value) - return nil - } - - properties.setRaw(tag, n) + if result := setSimpleProperty(properties, tag, value); result != nil { + return result } - return []PropertyName{tag} + var n int + if text, ok := value.(string); ok { + if n, ok = enumStringToInt(text, values, false); !ok { + invalidPropertyValue(tag, value) + return nil + } + } else if i, ok := isInt(value); ok { + if i < 0 || i >= len(values) { + invalidPropertyValue(tag, value) + return nil + } + n = i + } else { + notCompatibleType(tag, value) + return nil + } + + return setPropertyValue(properties, tag, n) } func setBoolProperty(properties Properties, tag PropertyName, value any) []PropertyName { - if !setSimpleProperty(properties, tag, value) { - if text, ok := value.(string); ok { - switch strings.ToLower(strings.Trim(text, " \t")) { - case "true", "yes", "on", "1": - properties.setRaw(tag, true) - - case "false", "no", "off", "0": - properties.setRaw(tag, false) - - default: - invalidPropertyValue(tag, value) - return nil - } - } else if n, ok := isInt(value); ok { - switch n { - case 1: - properties.setRaw(tag, true) - - case 0: - properties.setRaw(tag, false) - - default: - invalidPropertyValue(tag, value) - return nil - } - } else if b, ok := value.(bool); ok { - properties.setRaw(tag, b) - } else { - notCompatibleType(tag, value) - return nil - } + if result := setSimpleProperty(properties, tag, value); result != nil { + return result } - return []PropertyName{tag} + var flag bool + if text, ok := value.(string); ok { + switch strings.ToLower(strings.Trim(text, " \t")) { + case "true", "yes", "on", "1": + flag = true + + case "false", "no", "off", "0": + flag = false + + default: + invalidPropertyValue(tag, value) + return nil + } + } else if n, ok := isInt(value); ok { + switch n { + case 1: + flag = true + + case 0: + flag = false + + default: + invalidPropertyValue(tag, value) + return nil + } + } else if b, ok := value.(bool); ok { + flag = b + } else { + notCompatibleType(tag, value) + return nil + } + + return setPropertyValue(properties, tag, flag) } func setIntProperty(properties Properties, tag PropertyName, value any) []PropertyName { - if !setSimpleProperty(properties, tag, value) { - if text, ok := value.(string); ok { - n, err := strconv.Atoi(strings.Trim(text, " \t")) - if err != nil { - invalidPropertyValue(tag, value) - ErrorLog(err.Error()) - return nil - } - properties.setRaw(tag, n) - } else if n, ok := isInt(value); ok { - properties.setRaw(tag, n) + if result := setSimpleProperty(properties, tag, value); result != nil { + return result + } + + var result int + if text, ok := value.(string); ok { + n, err := strconv.Atoi(strings.Trim(text, " \t")) + if err != nil { + invalidPropertyValue(tag, value) + ErrorLog(err.Error()) + return nil + } + result = n + } else if n, ok := isInt(value); ok { + result = n + } else { + notCompatibleType(tag, value) + return nil + } + + return setPropertyValue(properties, tag, result) +} + +func setFloatProperty(properties Properties, tag PropertyName, value any, min, max float64) []PropertyName { + if result := setSimpleProperty(properties, tag, value); result != nil { + return result + } + + var result float64 + switch value := value.(type) { + case string: + f, err := strconv.ParseFloat(strings.Trim(value, " \t"), 64) + if err != nil { + invalidPropertyValue(tag, value) + ErrorLog(err.Error()) + return nil + } + result = f + + case float32: + result = float64(value) + + case float64: + result = value + + default: + if n, ok := isInt(value); ok { + result = float64(n) } else { notCompatibleType(tag, value) return nil } } - return []PropertyName{tag} -} - -func setFloatProperty(properties Properties, tag PropertyName, value any, min, max float64) []PropertyName { - if !setSimpleProperty(properties, tag, value) { - f := float64(0) - switch value := value.(type) { - case string: - var err error - if f, err = strconv.ParseFloat(strings.Trim(value, " \t"), 64); err != nil { - invalidPropertyValue(tag, value) - ErrorLog(err.Error()) - return nil - } - if f < min || f > max { - ErrorLogF(`"%T" out of range of "%s" property`, value, tag) - return nil - } - properties.setRaw(tag, value) - return nil - - case float32: - f = float64(value) - - case float64: - f = value - - default: - if n, ok := isInt(value); ok { - f = float64(n) - } else { - notCompatibleType(tag, value) - return nil - } - } - - if f >= min && f <= max { - properties.setRaw(tag, f) - } else { - ErrorLogF(`"%T" out of range of "%s" property`, value, tag) - return nil - } + if result < min || result > max { + ErrorLogF(`"%T" out of range of "%s" property`, value, tag) + return nil } - return []PropertyName{tag} + return setPropertyValue(properties, tag, result) } func propertiesSet(properties Properties, tag PropertyName, value any) []PropertyName { diff --git a/range.go b/range.go index 68b90d0..8aa7858 100644 --- a/range.go +++ b/range.go @@ -47,29 +47,30 @@ func (r *Range) setValue(value string) bool { } func setRangeProperty(properties Properties, tag PropertyName, value any) []PropertyName { + if result := setSimpleProperty(properties, tag, value); result != nil { + return result + } + + var r Range switch value := value.(type) { case string: - if setSimpleProperty(properties, tag, value) { - return []PropertyName{tag} - } - - var r Range if !r.setValue(value) { invalidPropertyValue(tag, value) return nil } - properties.setRaw(tag, r) case Range: - properties.setRaw(tag, value) + r = value default: if n, ok := isInt(value); ok { - properties.setRaw(tag, Range{First: n, Last: n}) + r.First = n + r.Last = n } else { notCompatibleType(tag, value) return nil } } - return []PropertyName{tag} + + return setPropertyValue(properties, tag, r) }