package parser import ( "reflect" "strconv" "strings" ) // getDynamicLength gets length from another field with stack support and array index resolution func (p *Parser) getDynamicLength(fieldName string) int { // Handle %i patterns by replacing with current array index if strings.Contains(fieldName, "%i") { currentIndex := p.GetCurrentArrayIndex() if currentIndex >= 0 { fieldName = strings.ReplaceAll(fieldName, "%i", strconv.Itoa(currentIndex)) } } // Check field cache first if cachedValue, exists := p.fieldCache[fieldName]; exists { return p.valueToInt(cachedValue) } // Handle array index patterns like "header_info_mod_need_0" if strings.Contains(fieldName, "_") { if value, exists := p.resolveArrayIndexVariableForLength(fieldName); exists { return p.valueToInt(value) } } // Check current struct if p.currentStruct.IsValid() { if field := p.currentStruct.FieldByName(fieldName); field.IsValid() { return p.valueToInt(field.Interface()) } } // Check struct stack for nested resolution 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 } // resolveArrayIndexVariableForLength handles array index variable resolution for length calculations func (p *Parser) resolveArrayIndexVariableForLength(variable string) (any, bool) { parts := strings.Split(variable, "_") if len(parts) < 2 { return nil, false } // Try to extract index from last part lastPart := parts[len(parts)-1] if index, err := strconv.Atoi(lastPart); err == nil { // Reconstruct base variable name without index baseVar := strings.Join(parts[:len(parts)-1], "_") // Look for array/slice field with this base name if cachedValue, exists := p.fieldCache[baseVar]; exists { return p.getArrayElementSafe(cachedValue, index) } // Check current struct for array field if p.currentStruct.IsValid() { if field := p.currentStruct.FieldByName(baseVar); field.IsValid() { return p.getArrayElementSafe(field.Interface(), index) } } // Check struct stack for i := len(p.structStack) - 1; i >= 0; i-- { if field := p.structStack[i].FieldByName(baseVar); field.IsValid() { return p.getArrayElementSafe(field.Interface(), index) } } } return nil, false } // getArrayElementSafe safely extracts element from array/slice with bounds checking func (p *Parser) getArrayElementSafe(value any, index int) (any, bool) { val := reflect.ValueOf(value) switch val.Kind() { case reflect.Slice, reflect.Array: if index >= 0 && index < val.Len() { return val.Index(index).Interface(), true } } return nil, false } // convertValue converts string to appropriate type for comparison with enhanced string support 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 } // Handle struct types with Data field (EQ2String types) if reflect.TypeOf(reference).Kind() == reflect.Struct { refVal := reflect.ValueOf(reference) if dataField := refVal.FieldByName("Data"); dataField.IsValid() && dataField.Kind() == reflect.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 with enhanced string support func (p *Parser) compareValues(a, b any, op string) bool { // Handle string comparisons first if p.isStringValue(a) && p.isStringValue(b) { aStr := p.extractStringValue(a) bStr := p.extractStringValue(b) return p.compareStrings(aStr, bStr, op) } // Fall back to numeric comparison 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 } // isStringValue checks if a value is or contains a string func (p *Parser) isStringValue(value any) bool { switch value.(type) { case string: return true default: if reflect.TypeOf(value).Kind() == reflect.Struct { val := reflect.ValueOf(value) if dataField := val.FieldByName("Data"); dataField.IsValid() && dataField.Kind() == reflect.String { return true } } return false } } // extractStringValue extracts string from value or struct Data field func (p *Parser) extractStringValue(value any) string { switch v := value.(type) { case string: return v default: if reflect.TypeOf(value).Kind() == reflect.Struct { val := reflect.ValueOf(value) if dataField := val.FieldByName("Data"); dataField.IsValid() && dataField.Kind() == reflect.String { return dataField.String() } } return "" } } // compareStrings performs string comparison operations func (p *Parser) compareStrings(a, b, op string) bool { switch op { case "==": return a == b case "!=": return a != b case ">": return a > b case ">=": return a >= b case "<": return a < b case "<=": return a <= b default: return false } } // valueToInt converts various types to int with enhanced type support 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 case bool: if val { return 1 } return 0 default: // Handle struct types that might have numeric fields if reflect.TypeOf(v).Kind() == reflect.Struct { refVal := reflect.ValueOf(v) // Try common numeric field names for _, fieldName := range []string{"Value", "Size", "Length", "Count"} { if field := refVal.FieldByName(fieldName); field.IsValid() { return p.valueToInt(field.Interface()) } } } } return 0 } // valueToInt64 converts various types to int64 for comparison with enhanced support 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) case bool: if val { return 1 } return 0 default: // Handle struct types that might have numeric fields if reflect.TypeOf(v).Kind() == reflect.Struct { refVal := reflect.ValueOf(v) // Try common numeric field names for _, fieldName := range []string{"Value", "Size", "Length", "Count"} { if field := refVal.FieldByName(fieldName); field.IsValid() { return p.valueToInt64(field.Interface()) } } } } return 0 } // isTruthy checks if a value is truthy with enhanced type support 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 != "" default: // Handle struct types if reflect.TypeOf(v).Kind() == reflect.Struct { refVal := reflect.ValueOf(v) // Check for Data field (string types) if dataField := refVal.FieldByName("Data"); dataField.IsValid() && dataField.Kind() == reflect.String { return dataField.String() != "" } // Check for numeric fields for _, fieldName := range []string{"Value", "Size", "Length", "Count"} { if field := refVal.FieldByName(fieldName); field.IsValid() { return p.valueToInt64(field.Interface()) != 0 } } } } 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 }