diff --git a/pkg/yqlib/compare_operators.go b/pkg/yqlib/compare_operators.go index 663a7a8a..d80a12a1 100644 --- a/pkg/yqlib/compare_operators.go +++ b/pkg/yqlib/compare_operators.go @@ -87,11 +87,11 @@ func compareScalars(context Context, prefs compareTypePref, lhs *yaml.Node, rhs if isDateTime { return compareDateTime(context.GetDateTimeLayout(), prefs, lhs, rhs) } else if lhsTag == "!!int" && rhsTag == "!!int" { - _, lhsNum, err := parseInt(lhs.Value) + _, lhsNum, err := parseInt64(lhs.Value) if err != nil { return false, err } - _, rhsNum, err := parseInt(rhs.Value) + _, rhsNum, err := parseInt64(rhs.Value) if err != nil { return false, err } diff --git a/pkg/yqlib/doc/operators/unique.md b/pkg/yqlib/doc/operators/unique.md index 9ea330f6..c7bd23ba 100644 --- a/pkg/yqlib/doc/operators/unique.md +++ b/pkg/yqlib/doc/operators/unique.md @@ -1,6 +1,7 @@ # Unique -This is used to filter out duplicated items in an array. +This is used to filter out duplicated items in an array. Note that the original order of the array is maintained. + {% hint style="warning" %} Note that versions prior to 4.18 require the 'eval/e' command to be specified. diff --git a/pkg/yqlib/lib.go b/pkg/yqlib/lib.go index 364554c7..174a059b 100644 --- a/pkg/yqlib/lib.go +++ b/pkg/yqlib/lib.go @@ -6,6 +6,7 @@ import ( "bytes" "container/list" "fmt" + "math" "strconv" "strings" @@ -320,7 +321,7 @@ func deepCloneWithOptions(node *yaml.Node, cloneContent bool) *yaml.Node { } // yaml numbers can be hex encoded... -func parseInt(numberString string) (string, int64, error) { +func parseInt64(numberString string) (string, int64, error) { if strings.HasPrefix(numberString, "0x") || strings.HasPrefix(numberString, "0X") { num, err := strconv.ParseInt(numberString[2:], 16, 64) @@ -330,6 +331,27 @@ func parseInt(numberString string) (string, int64, error) { return "%v", num, err } +func parseInt(numberString string) (string, int, error) { + var err error + var parsed int64 + format := "%v" + if strings.HasPrefix(numberString, "0x") || + strings.HasPrefix(numberString, "0X") { + format = "0x%X" + parsed, err = strconv.ParseInt(numberString[2:], 16, 64) + } else { + parsed, err = strconv.ParseInt(numberString, 10, 64) + } + + if err != nil { + return "", 0, err + } else if parsed > math.MaxInt { + return "", 0, fmt.Errorf("%v is too big (larger than %v)", parsed, math.MaxInt) + } + + return format, int(parsed), err +} + func createScalarNode(value interface{}, stringValue string) *yaml.Node { var node = &yaml.Node{Kind: yaml.ScalarNode} node.Value = stringValue diff --git a/pkg/yqlib/operator_add.go b/pkg/yqlib/operator_add.go index 90ccb9b5..a524b9ba 100644 --- a/pkg/yqlib/operator_add.go +++ b/pkg/yqlib/operator_add.go @@ -104,11 +104,11 @@ func addScalars(context Context, target *CandidateNode, lhs *yaml.Node, rhs *yam target.Node.Tag = lhs.Tag target.Node.Value = lhs.Value + rhs.Value } else if lhsTag == "!!int" && rhsTag == "!!int" { - format, lhsNum, err := parseInt(lhs.Value) + format, lhsNum, err := parseInt64(lhs.Value) if err != nil { return err } - _, rhsNum, err := parseInt(rhs.Value) + _, rhsNum, err := parseInt64(rhs.Value) if err != nil { return err } diff --git a/pkg/yqlib/operator_multiply.go b/pkg/yqlib/operator_multiply.go index c64e1c81..e1dfcd61 100644 --- a/pkg/yqlib/operator_multiply.go +++ b/pkg/yqlib/operator_multiply.go @@ -124,11 +124,11 @@ func multiplyIntegers(lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, e target.Node.Style = lhs.Node.Style target.Node.Tag = lhs.Node.Tag - format, lhsNum, err := parseInt(lhs.Node.Value) + format, lhsNum, err := parseInt64(lhs.Node.Value) if err != nil { return nil, err } - _, rhsNum, err := parseInt(rhs.Node.Value) + _, rhsNum, err := parseInt64(rhs.Node.Value) if err != nil { return nil, err } diff --git a/pkg/yqlib/operator_pick.go b/pkg/yqlib/operator_pick.go index d4ae88ae..2444c9b2 100644 --- a/pkg/yqlib/operator_pick.go +++ b/pkg/yqlib/operator_pick.go @@ -36,7 +36,7 @@ func pickSequence(original *yaml.Node, indices *yaml.Node) (*yaml.Node, error) { return nil, fmt.Errorf("cannot index array with %v", indices.Content[index].Value) } - if int(indexInArray) > -1 && int(indexInArray) < len(original.Content) { + if indexInArray > -1 && indexInArray < len(original.Content) { filteredContent = append(filteredContent, deepClone(original.Content[indexInArray])) } } diff --git a/pkg/yqlib/operator_sort.go b/pkg/yqlib/operator_sort.go index 66709f4c..5414960e 100644 --- a/pkg/yqlib/operator_sort.go +++ b/pkg/yqlib/operator_sort.go @@ -106,11 +106,11 @@ func (a sortableNodeArray) Less(i, j int) bool { } else if lhs.Tag != rhs.Tag || lhs.Tag == "!!str" { return strings.Compare(lhs.Value, rhs.Value) < 0 } else if lhs.Tag == "!!int" && rhs.Tag == "!!int" { - _, lhsNum, err := parseInt(lhs.Value) + _, lhsNum, err := parseInt64(lhs.Value) if err != nil { panic(err) } - _, rhsNum, err := parseInt(rhs.Value) + _, rhsNum, err := parseInt64(rhs.Value) if err != nil { panic(err) } diff --git a/pkg/yqlib/operator_subtract.go b/pkg/yqlib/operator_subtract.go index 781bf03f..31efd2d6 100644 --- a/pkg/yqlib/operator_subtract.go +++ b/pkg/yqlib/operator_subtract.go @@ -104,11 +104,11 @@ func subtractScalars(context Context, target *CandidateNode, lhs *yaml.Node, rhs } else if lhsTag == "!!str" { return fmt.Errorf("strings cannot be subtracted") } else if lhsTag == "!!int" && rhsTag == "!!int" { - format, lhsNum, err := parseInt(lhs.Value) + format, lhsNum, err := parseInt64(lhs.Value) if err != nil { return err } - _, rhsNum, err := parseInt(rhs.Value) + _, rhsNum, err := parseInt64(rhs.Value) if err != nil { return err } diff --git a/pkg/yqlib/operator_traverse_path.go b/pkg/yqlib/operator_traverse_path.go index b50aa3af..2aa9ef94 100644 --- a/pkg/yqlib/operator_traverse_path.go +++ b/pkg/yqlib/operator_traverse_path.go @@ -188,15 +188,15 @@ func traverseArrayWithIndices(candidate *CandidateNode, indices []*yaml.Node, pr for _, indexNode := range indices { log.Debug("traverseArrayWithIndices: '%v'", indexNode.Value) - index, err := strconv.ParseInt(indexNode.Value, 10, 64) + _, index, err := parseInt(indexNode.Value) if err != nil && prefs.OptionalTraverse { continue } if err != nil { - return nil, fmt.Errorf("Cannot index array with '%v' (%w)", indexNode.Value, err) + return nil, fmt.Errorf("cannot index array with '%v' (%w)", indexNode.Value, err) } indexToUse := index - contentLength := int64(len(node.Content)) + contentLength := len(node.Content) for contentLength <= index { if contentLength == 0 { // default to nice yaml formating @@ -204,7 +204,7 @@ func traverseArrayWithIndices(candidate *CandidateNode, indices []*yaml.Node, pr } node.Content = append(node.Content, &yaml.Node{Tag: "!!null", Kind: yaml.ScalarNode, Value: "null"}) - contentLength = int64(len(node.Content)) + contentLength = len(node.Content) } if indexToUse < 0 { @@ -215,7 +215,7 @@ func traverseArrayWithIndices(candidate *CandidateNode, indices []*yaml.Node, pr return nil, fmt.Errorf("index [%v] out of range, array size is %v", index, contentLength) } - newMatches.PushBack(candidate.CreateChildInArray(int(index), node.Content[indexToUse])) + newMatches.PushBack(candidate.CreateChildInArray(index, node.Content[indexToUse])) } return newMatches, nil } diff --git a/pkg/yqlib/operator_variables_test.go b/pkg/yqlib/operator_variables_test.go index 99fa5488..ad279490 100644 --- a/pkg/yqlib/operator_variables_test.go +++ b/pkg/yqlib/operator_variables_test.go @@ -17,7 +17,7 @@ var variableOperatorScenarios = []expressionScenario{ document: "a: [cat]", skipDoc: true, expression: "(.[] | {.name: .}) as $item", - expectedError: `Cannot index array with 'name' (strconv.ParseInt: parsing "name": invalid syntax)`, + expectedError: `cannot index array with 'name' (strconv.ParseInt: parsing "name": invalid syntax)`, }, { description: "Single value variable",