192 lines
4.0 KiB
Go

package parser
import (
"reflect"
"strconv"
)
// getDynamicLength gets length from another field with stack support
func (p *Parser) getDynamicLength(fieldName string) int {
if cachedValue, exists := p.fieldCache[fieldName]; exists {
return p.valueToInt(cachedValue)
}
if p.currentStruct.IsValid() {
if field := p.currentStruct.FieldByName(fieldName); field.IsValid() {
return p.valueToInt(field.Interface())
}
}
for i := len(p.structStack) - 1; i >= 0; i-- {
if field := p.structStack[i].FieldByName(fieldName); field.IsValid() {
return p.valueToInt(field.Interface())
}
}
return 0
}
// convertValue converts string to appropriate type for comparison
func (p *Parser) convertValue(valueStr string, reference any) (any, error) {
switch reference.(type) {
case uint8, int8:
if val, err := strconv.ParseInt(valueStr, 0, 8); err == nil {
return uint8(val), nil
}
case uint16, int16:
if val, err := strconv.ParseInt(valueStr, 0, 16); err == nil {
return uint16(val), nil
}
case uint32, int32:
if val, err := strconv.ParseInt(valueStr, 0, 32); err == nil {
return uint32(val), nil
}
case uint64, int64:
if val, err := strconv.ParseInt(valueStr, 0, 64); err == nil {
return uint64(val), nil
}
case float32:
if val, err := strconv.ParseFloat(valueStr, 32); err == nil {
return float32(val), nil
}
case float64:
if val, err := strconv.ParseFloat(valueStr, 64); err == nil {
return val, nil
}
case string:
return valueStr, nil
}
if val, err := strconv.ParseInt(valueStr, 0, 32); err == nil {
return int(val), nil
}
return valueStr, nil
}
// compareValues performs comparison between two values
func (p *Parser) compareValues(a, b any, op string) bool {
aVal := p.valueToInt64(a)
bVal := p.valueToInt64(b)
switch op {
case "==":
return aVal == bVal
case "!=":
return aVal != bVal
case ">":
return aVal > bVal
case ">=":
return aVal >= bVal
case "<":
return aVal < bVal
case "<=":
return aVal <= bVal
case "&":
return (aVal & bVal) != 0
case "|":
return (aVal | bVal) != 0
}
return false
}
// valueToInt converts various types to int
func (p *Parser) valueToInt(v any) int {
switch val := v.(type) {
case uint8:
return int(val)
case int8:
return int(val)
case uint16:
return int(val)
case int16:
return int(val)
case uint32:
return int(val)
case int32:
return int(val)
case uint64:
return int(val)
case int64:
return int(val)
case int:
return val
}
return 0
}
// valueToInt64 converts various types to int64 for comparison
func (p *Parser) valueToInt64(v any) int64 {
switch val := v.(type) {
case uint8:
return int64(val)
case int8:
return int64(val)
case uint16:
return int64(val)
case int16:
return int64(val)
case uint32:
return int64(val)
case int32:
return int64(val)
case uint64:
return int64(val)
case int64:
return val
case int:
return int64(val)
case float32:
return int64(val)
case float64:
return int64(val)
}
return 0
}
// isTruthy checks if a value is truthy
func (p *Parser) isTruthy(v any) bool {
switch val := v.(type) {
case bool:
return val
case uint8, int8, uint16, int16, uint32, int32, uint64, int64, int:
return p.valueToInt64(val) != 0
case string:
return val != ""
}
return false
}
// handleOversizedField handles fields that exceed their oversized value
func (p *Parser) handleOversizedField(field reflect.Value, oversizedByte byte, length int) error {
if field.Kind() == reflect.Slice {
slice := reflect.MakeSlice(field.Type(), 1, 1)
if slice.Len() > 0 {
elem := slice.Index(0)
if elem.CanSet() {
switch elem.Kind() {
case reflect.Uint8:
elem.SetUint(uint64(oversizedByte))
case reflect.Int8:
elem.SetInt(int64(int8(oversizedByte)))
default:
elem.SetUint(uint64(oversizedByte))
}
}
}
field.Set(slice)
} else {
switch field.Kind() {
case reflect.Uint8:
field.SetUint(uint64(oversizedByte))
case reflect.Int8:
field.SetInt(int64(int8(oversizedByte)))
default:
field.SetUint(uint64(oversizedByte))
}
}
return nil
}