192 lines
4.0 KiB
Go
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
|
|
}
|