2021-01-12 22:35:57 +00:00
|
|
|
// Use the top level Evaluator or StreamEvaluator to evaluate expressions and return matches.
|
2020-11-03 23:48:43 +00:00
|
|
|
package yqlib
|
2020-10-08 23:59:03 +00:00
|
|
|
|
|
|
|
import (
|
2020-10-21 01:54:58 +00:00
|
|
|
"container/list"
|
2020-10-08 23:59:03 +00:00
|
|
|
"fmt"
|
2022-05-06 03:46:14 +00:00
|
|
|
"math"
|
2021-09-02 05:26:44 +00:00
|
|
|
"strconv"
|
|
|
|
"strings"
|
2020-10-08 23:59:03 +00:00
|
|
|
|
2020-11-14 02:38:44 +00:00
|
|
|
logging "gopkg.in/op/go-logging.v1"
|
2020-10-08 23:59:03 +00:00
|
|
|
)
|
|
|
|
|
2022-02-01 03:47:51 +00:00
|
|
|
var ExpressionParser ExpressionParserInterface
|
|
|
|
|
|
|
|
func InitExpressionParser() {
|
|
|
|
if ExpressionParser == nil {
|
|
|
|
ExpressionParser = newExpressionParser()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-30 05:05:07 +00:00
|
|
|
var log = logging.MustGetLogger("yq-lib")
|
|
|
|
|
2022-01-21 09:26:09 +00:00
|
|
|
var PrettyPrintExp = `(... | (select(tag != "!!str"), select(tag == "!!str") | select(test("(?i)^(y|yes|n|no|on|off)$") | not)) ) style=""`
|
|
|
|
|
2021-11-29 23:51:49 +00:00
|
|
|
// GetLogger returns the yq logger instance.
|
|
|
|
func GetLogger() *logging.Logger {
|
|
|
|
return log
|
|
|
|
}
|
|
|
|
|
2021-01-11 06:13:48 +00:00
|
|
|
type operationType struct {
|
2020-10-11 23:44:33 +00:00
|
|
|
Type string
|
|
|
|
NumArgs uint // number of arguments to the op
|
|
|
|
Precedence uint
|
2021-01-11 06:13:48 +00:00
|
|
|
Handler operatorHandler
|
2020-10-11 23:44:33 +00:00
|
|
|
}
|
|
|
|
|
2021-01-11 06:13:48 +00:00
|
|
|
var orOpType = &operationType{Type: "OR", NumArgs: 2, Precedence: 20, Handler: orOperator}
|
|
|
|
var andOpType = &operationType{Type: "AND", NumArgs: 2, Precedence: 20, Handler: andOperator}
|
2021-02-15 06:31:12 +00:00
|
|
|
var reduceOpType = &operationType{Type: "REDUCE", NumArgs: 2, Precedence: 35, Handler: reduceOperator}
|
2021-02-15 03:27:00 +00:00
|
|
|
|
|
|
|
var blockOpType = &operationType{Type: "BLOCK", Precedence: 10, NumArgs: 2, Handler: emptyOperator}
|
2020-10-17 11:10:47 +00:00
|
|
|
|
2021-01-11 06:13:48 +00:00
|
|
|
var unionOpType = &operationType{Type: "UNION", NumArgs: 2, Precedence: 10, Handler: unionOperator}
|
2020-10-16 01:29:26 +00:00
|
|
|
|
2021-01-11 06:13:48 +00:00
|
|
|
var pipeOpType = &operationType{Type: "PIPE", NumArgs: 2, Precedence: 30, Handler: pipeOperator}
|
2020-12-01 06:58:07 +00:00
|
|
|
|
2021-01-11 06:13:48 +00:00
|
|
|
var assignOpType = &operationType{Type: "ASSIGN", NumArgs: 2, Precedence: 40, Handler: assignUpdateOperator}
|
|
|
|
var addAssignOpType = &operationType{Type: "ADD_ASSIGN", NumArgs: 2, Precedence: 40, Handler: addAssignOperator}
|
2021-03-24 21:12:01 +00:00
|
|
|
var subtractAssignOpType = &operationType{Type: "SUBTRACT_ASSIGN", NumArgs: 2, Precedence: 40, Handler: subtractAssignOperator}
|
2020-11-19 05:45:05 +00:00
|
|
|
|
2021-01-11 06:13:48 +00:00
|
|
|
var assignAttributesOpType = &operationType{Type: "ASSIGN_ATTRIBUTES", NumArgs: 2, Precedence: 40, Handler: assignAttributesOperator}
|
|
|
|
var assignStyleOpType = &operationType{Type: "ASSIGN_STYLE", NumArgs: 2, Precedence: 40, Handler: assignStyleOperator}
|
2023-02-28 05:40:38 +00:00
|
|
|
var assignVariableOpType = &operationType{Type: "ASSIGN_VARIABLE", NumArgs: 2, Precedence: 40, Handler: useWithPipe}
|
2021-01-11 06:13:48 +00:00
|
|
|
var assignTagOpType = &operationType{Type: "ASSIGN_TAG", NumArgs: 2, Precedence: 40, Handler: assignTagOperator}
|
|
|
|
var assignCommentOpType = &operationType{Type: "ASSIGN_COMMENT", NumArgs: 2, Precedence: 40, Handler: assignCommentsOperator}
|
|
|
|
var assignAnchorOpType = &operationType{Type: "ASSIGN_ANCHOR", NumArgs: 2, Precedence: 40, Handler: assignAnchorOperator}
|
|
|
|
var assignAliasOpType = &operationType{Type: "ASSIGN_ALIAS", NumArgs: 2, Precedence: 40, Handler: assignAliasOperator}
|
2020-11-02 00:20:38 +00:00
|
|
|
|
2021-01-14 00:16:04 +00:00
|
|
|
var multiplyOpType = &operationType{Type: "MULTIPLY", NumArgs: 2, Precedence: 42, Handler: multiplyOperator}
|
2022-01-22 05:40:17 +00:00
|
|
|
var multiplyAssignOpType = &operationType{Type: "MULTIPLY_ASSIGN", NumArgs: 2, Precedence: 42, Handler: multiplyAssignOperator}
|
|
|
|
|
2023-03-15 09:14:23 +00:00
|
|
|
var divideOpType = &operationType{Type: "DIVIDE", NumArgs: 2, Precedence: 42, Handler: divideOperator}
|
|
|
|
|
|
|
|
var moduloOpType = &operationType{Type: "MODULO", NumArgs: 2, Precedence: 42, Handler: moduloOperator}
|
|
|
|
|
2021-01-14 00:16:04 +00:00
|
|
|
var addOpType = &operationType{Type: "ADD", NumArgs: 2, Precedence: 42, Handler: addOperator}
|
2021-03-24 21:12:01 +00:00
|
|
|
var subtractOpType = &operationType{Type: "SUBTRACT", NumArgs: 2, Precedence: 42, Handler: subtractOperator}
|
2021-01-14 00:16:04 +00:00
|
|
|
var alternativeOpType = &operationType{Type: "ALTERNATIVE", NumArgs: 2, Precedence: 42, Handler: alternativeOperator}
|
2020-10-18 21:36:33 +00:00
|
|
|
|
2021-01-11 06:13:48 +00:00
|
|
|
var equalsOpType = &operationType{Type: "EQUALS", NumArgs: 2, Precedence: 40, Handler: equalsOperator}
|
2022-03-17 03:08:08 +00:00
|
|
|
var notEqualsOpType = &operationType{Type: "NOT_EQUALS", NumArgs: 2, Precedence: 40, Handler: notEqualsOperator}
|
|
|
|
|
|
|
|
var compareOpType = &operationType{Type: "COMPARE", NumArgs: 2, Precedence: 40, Handler: compareOperator}
|
2021-03-19 01:09:32 +00:00
|
|
|
|
2022-08-29 04:13:15 +00:00
|
|
|
// createmap needs to be above union, as we use union to build the components of the objects
|
2021-03-19 01:09:32 +00:00
|
|
|
var createMapOpType = &operationType{Type: "CREATE_MAP", NumArgs: 2, Precedence: 15, Handler: createMapOperator}
|
2020-12-01 06:58:07 +00:00
|
|
|
|
2021-01-11 06:13:48 +00:00
|
|
|
var shortPipeOpType = &operationType{Type: "SHORT_PIPE", NumArgs: 2, Precedence: 45, Handler: pipeOperator}
|
2020-10-16 01:29:26 +00:00
|
|
|
|
2021-01-11 06:13:48 +00:00
|
|
|
var lengthOpType = &operationType{Type: "LENGTH", NumArgs: 0, Precedence: 50, Handler: lengthOperator}
|
2022-02-27 00:56:46 +00:00
|
|
|
var lineOpType = &operationType{Type: "LINE", NumArgs: 0, Precedence: 50, Handler: lineOperator}
|
|
|
|
var columnOpType = &operationType{Type: "LINE", NumArgs: 0, Precedence: 50, Handler: columnOperator}
|
|
|
|
|
2022-11-08 02:40:00 +00:00
|
|
|
var expressionOpType = &operationType{Type: "EXP", NumArgs: 0, Precedence: 50, Handler: expressionOperator}
|
|
|
|
|
2021-11-30 02:19:30 +00:00
|
|
|
var collectOpType = &operationType{Type: "COLLECT", NumArgs: 1, Precedence: 50, Handler: collectOperator}
|
2021-11-30 23:32:36 +00:00
|
|
|
var mapOpType = &operationType{Type: "MAP", NumArgs: 1, Precedence: 50, Handler: mapOperator}
|
2023-03-08 23:30:47 +00:00
|
|
|
var filterOpType = &operationType{Type: "FILTER", NumArgs: 1, Precedence: 50, Handler: filterOperator}
|
2022-06-25 02:46:24 +00:00
|
|
|
var errorOpType = &operationType{Type: "ERROR", NumArgs: 1, Precedence: 50, Handler: errorOperator}
|
2022-03-09 03:38:02 +00:00
|
|
|
var pickOpType = &operationType{Type: "PICK", NumArgs: 1, Precedence: 50, Handler: pickOperator}
|
2022-02-01 03:47:51 +00:00
|
|
|
var evalOpType = &operationType{Type: "EVAL", NumArgs: 1, Precedence: 50, Handler: evalOperator}
|
2021-11-30 23:32:36 +00:00
|
|
|
var mapValuesOpType = &operationType{Type: "MAP_VALUES", NumArgs: 1, Precedence: 50, Handler: mapValuesOperator}
|
2022-02-14 04:37:43 +00:00
|
|
|
|
|
|
|
var formatDateTimeOpType = &operationType{Type: "FORMAT_DATE_TIME", NumArgs: 1, Precedence: 50, Handler: formatDateTime}
|
|
|
|
var withDtFormatOpType = &operationType{Type: "WITH_DATE_TIME_FORMAT", NumArgs: 1, Precedence: 50, Handler: withDateTimeFormat}
|
|
|
|
var nowOpType = &operationType{Type: "NOW", NumArgs: 0, Precedence: 50, Handler: nowOp}
|
|
|
|
var tzOpType = &operationType{Type: "TIMEZONE", NumArgs: 1, Precedence: 50, Handler: tzOp}
|
2023-02-02 01:42:36 +00:00
|
|
|
var fromUnixOpType = &operationType{Type: "FROM_UNIX", NumArgs: 0, Precedence: 50, Handler: fromUnixOp}
|
2023-02-02 01:56:16 +00:00
|
|
|
var toUnixOpType = &operationType{Type: "TO_UNIX", NumArgs: 0, Precedence: 50, Handler: toUnixOp}
|
2022-02-14 04:37:43 +00:00
|
|
|
|
2021-10-22 01:37:47 +00:00
|
|
|
var encodeOpType = &operationType{Type: "ENCODE", NumArgs: 0, Precedence: 50, Handler: encodeOperator}
|
|
|
|
var decodeOpType = &operationType{Type: "DECODE", NumArgs: 0, Precedence: 50, Handler: decodeOperator}
|
2021-05-09 05:12:50 +00:00
|
|
|
|
2021-05-14 04:29:55 +00:00
|
|
|
var anyOpType = &operationType{Type: "ANY", NumArgs: 0, Precedence: 50, Handler: anyOperator}
|
|
|
|
var allOpType = &operationType{Type: "ALL", NumArgs: 0, Precedence: 50, Handler: allOperator}
|
2021-09-15 05:18:10 +00:00
|
|
|
var containsOpType = &operationType{Type: "CONTAINS", NumArgs: 1, Precedence: 50, Handler: containsOperator}
|
2021-05-14 05:01:44 +00:00
|
|
|
var anyConditionOpType = &operationType{Type: "ANY_CONDITION", NumArgs: 1, Precedence: 50, Handler: anyOperator}
|
|
|
|
var allConditionOpType = &operationType{Type: "ALL_CONDITION", NumArgs: 1, Precedence: 50, Handler: allOperator}
|
2021-05-14 04:29:55 +00:00
|
|
|
|
2021-05-09 03:59:23 +00:00
|
|
|
var toEntriesOpType = &operationType{Type: "TO_ENTRIES", NumArgs: 0, Precedence: 50, Handler: toEntriesOperator}
|
2021-05-09 05:12:50 +00:00
|
|
|
var fromEntriesOpType = &operationType{Type: "FROM_ENTRIES", NumArgs: 0, Precedence: 50, Handler: fromEntriesOperator}
|
|
|
|
var withEntriesOpType = &operationType{Type: "WITH_ENTRIES", NumArgs: 1, Precedence: 50, Handler: withEntriesOperator}
|
|
|
|
|
2021-09-12 11:52:02 +00:00
|
|
|
var withOpType = &operationType{Type: "WITH", NumArgs: 1, Precedence: 50, Handler: withOperator}
|
|
|
|
|
2021-01-14 03:25:31 +00:00
|
|
|
var splitDocumentOpType = &operationType{Type: "SPLIT_DOC", NumArgs: 0, Precedence: 50, Handler: splitDocumentOperator}
|
2021-02-04 01:39:04 +00:00
|
|
|
var getVariableOpType = &operationType{Type: "GET_VARIABLE", NumArgs: 0, Precedence: 55, Handler: getVariableOperator}
|
2021-01-11 06:13:48 +00:00
|
|
|
var getStyleOpType = &operationType{Type: "GET_STYLE", NumArgs: 0, Precedence: 50, Handler: getStyleOperator}
|
|
|
|
var getTagOpType = &operationType{Type: "GET_TAG", NumArgs: 0, Precedence: 50, Handler: getTagOperator}
|
2023-10-02 03:43:12 +00:00
|
|
|
var getKindOpType = &operationType{Type: "GET_KIND", NumArgs: 0, Precedence: 50, Handler: getKindOperator}
|
2021-11-23 22:57:35 +00:00
|
|
|
|
|
|
|
var getKeyOpType = &operationType{Type: "GET_KEY", NumArgs: 0, Precedence: 50, Handler: getKeyOperator}
|
2022-09-30 00:27:35 +00:00
|
|
|
var isKeyOpType = &operationType{Type: "IS_KEY", NumArgs: 0, Precedence: 50, Handler: isKeyOperator}
|
2021-11-23 23:16:48 +00:00
|
|
|
var getParentOpType = &operationType{Type: "GET_PARENT", NumArgs: 0, Precedence: 50, Handler: getParentOperator}
|
2021-11-23 22:57:35 +00:00
|
|
|
|
2021-01-11 06:13:48 +00:00
|
|
|
var getCommentOpType = &operationType{Type: "GET_COMMENT", NumArgs: 0, Precedence: 50, Handler: getCommentsOperator}
|
|
|
|
var getAnchorOpType = &operationType{Type: "GET_ANCHOR", NumArgs: 0, Precedence: 50, Handler: getAnchorOperator}
|
2022-07-13 04:45:28 +00:00
|
|
|
var getAliasOpType = &operationType{Type: "GET_ALIAS", NumArgs: 0, Precedence: 50, Handler: getAliasOperator}
|
2021-01-11 06:13:48 +00:00
|
|
|
var getDocumentIndexOpType = &operationType{Type: "GET_DOCUMENT_INDEX", NumArgs: 0, Precedence: 50, Handler: getDocumentIndexOperator}
|
|
|
|
var getFilenameOpType = &operationType{Type: "GET_FILENAME", NumArgs: 0, Precedence: 50, Handler: getFilenameOperator}
|
|
|
|
var getFileIndexOpType = &operationType{Type: "GET_FILE_INDEX", NumArgs: 0, Precedence: 50, Handler: getFileIndexOperator}
|
2022-10-05 03:12:08 +00:00
|
|
|
|
2021-01-11 06:13:48 +00:00
|
|
|
var getPathOpType = &operationType{Type: "GET_PATH", NumArgs: 0, Precedence: 50, Handler: getPathOperator}
|
2022-10-05 03:12:08 +00:00
|
|
|
var setPathOpType = &operationType{Type: "SET_PATH", NumArgs: 1, Precedence: 50, Handler: setPathOperator}
|
2022-10-05 09:09:53 +00:00
|
|
|
var delPathsOpType = &operationType{Type: "DEL_PATHS", NumArgs: 1, Precedence: 50, Handler: delPathsOperator}
|
2020-11-02 00:20:38 +00:00
|
|
|
|
2021-01-11 06:13:48 +00:00
|
|
|
var explodeOpType = &operationType{Type: "EXPLODE", NumArgs: 1, Precedence: 50, Handler: explodeOperator}
|
2021-11-28 02:25:22 +00:00
|
|
|
var sortByOpType = &operationType{Type: "SORT_BY", NumArgs: 1, Precedence: 50, Handler: sortByOperator}
|
2022-02-22 03:15:31 +00:00
|
|
|
var reverseOpType = &operationType{Type: "REVERSE", NumArgs: 0, Precedence: 50, Handler: reverseOperator}
|
2021-12-04 02:54:12 +00:00
|
|
|
var sortOpType = &operationType{Type: "SORT", NumArgs: 0, Precedence: 50, Handler: sortOperator}
|
2023-02-10 18:08:20 +00:00
|
|
|
var shuffleOpType = &operationType{Type: "SHUFFLE", NumArgs: 0, Precedence: 50, Handler: shuffleOperator}
|
2022-02-22 05:17:23 +00:00
|
|
|
|
2021-01-11 06:13:48 +00:00
|
|
|
var sortKeysOpType = &operationType{Type: "SORT_KEYS", NumArgs: 1, Precedence: 50, Handler: sortKeysOperator}
|
2022-02-22 05:17:23 +00:00
|
|
|
|
2021-01-14 03:46:50 +00:00
|
|
|
var joinStringOpType = &operationType{Type: "JOIN", NumArgs: 1, Precedence: 50, Handler: joinStringOperator}
|
2021-04-15 00:09:41 +00:00
|
|
|
var subStringOpType = &operationType{Type: "SUBSTR", NumArgs: 1, Precedence: 50, Handler: substituteStringOperator}
|
2021-07-07 12:40:46 +00:00
|
|
|
var matchOpType = &operationType{Type: "MATCH", NumArgs: 1, Precedence: 50, Handler: matchOperator}
|
2021-07-11 01:08:18 +00:00
|
|
|
var captureOpType = &operationType{Type: "CAPTURE", NumArgs: 1, Precedence: 50, Handler: captureOperator}
|
|
|
|
var testOpType = &operationType{Type: "TEST", NumArgs: 1, Precedence: 50, Handler: testOperator}
|
2021-01-14 04:05:50 +00:00
|
|
|
var splitStringOpType = &operationType{Type: "SPLIT", NumArgs: 1, Precedence: 50, Handler: splitStringOperator}
|
2022-02-22 05:17:23 +00:00
|
|
|
var changeCaseOpType = &operationType{Type: "CHANGE_CASE", NumArgs: 0, Precedence: 50, Handler: changeCaseOperator}
|
2022-08-08 03:35:57 +00:00
|
|
|
var trimOpType = &operationType{Type: "TRIM", NumArgs: 0, Precedence: 50, Handler: trimSpaceOperator}
|
2020-11-02 00:20:38 +00:00
|
|
|
|
2021-11-16 04:29:16 +00:00
|
|
|
var loadOpType = &operationType{Type: "LOAD", NumArgs: 1, Precedence: 50, Handler: loadYamlOperator}
|
|
|
|
|
2021-01-14 04:45:07 +00:00
|
|
|
var keysOpType = &operationType{Type: "KEYS", NumArgs: 0, Precedence: 50, Handler: keysOperator}
|
|
|
|
|
2021-01-11 06:13:48 +00:00
|
|
|
var collectObjectOpType = &operationType{Type: "COLLECT_OBJECT", NumArgs: 0, Precedence: 50, Handler: collectObjectOperator}
|
2021-02-04 01:39:04 +00:00
|
|
|
var traversePathOpType = &operationType{Type: "TRAVERSE_PATH", NumArgs: 0, Precedence: 55, Handler: traversePathOperator}
|
2021-02-03 04:51:26 +00:00
|
|
|
var traverseArrayOpType = &operationType{Type: "TRAVERSE_ARRAY", NumArgs: 2, Precedence: 50, Handler: traverseArrayOperator}
|
2020-10-20 02:53:26 +00:00
|
|
|
|
2021-02-04 01:39:04 +00:00
|
|
|
var selfReferenceOpType = &operationType{Type: "SELF", NumArgs: 0, Precedence: 55, Handler: selfOperator}
|
2021-01-11 06:13:48 +00:00
|
|
|
var valueOpType = &operationType{Type: "VALUE", NumArgs: 0, Precedence: 50, Handler: valueOperator}
|
2023-01-12 04:11:45 +00:00
|
|
|
var referenceOpType = &operationType{Type: "REF", NumArgs: 0, Precedence: 50, Handler: referenceOperator}
|
2021-01-11 06:13:48 +00:00
|
|
|
var envOpType = &operationType{Type: "ENV", NumArgs: 0, Precedence: 50, Handler: envOperator}
|
|
|
|
var notOpType = &operationType{Type: "NOT", NumArgs: 0, Precedence: 50, Handler: notOperator}
|
2023-10-05 04:13:46 +00:00
|
|
|
var toNumberOpType = &operationType{Type: "TO_NUMBER", NumArgs: 0, Precedence: 50, Handler: toNumberOperator}
|
2021-02-15 03:27:00 +00:00
|
|
|
var emptyOpType = &operationType{Type: "EMPTY", Precedence: 50, Handler: emptyOperator}
|
2020-10-20 02:53:26 +00:00
|
|
|
|
2022-01-25 08:33:30 +00:00
|
|
|
var envsubstOpType = &operationType{Type: "ENVSUBST", NumArgs: 0, Precedence: 50, Handler: envsubstOperator}
|
|
|
|
|
2021-01-11 06:13:48 +00:00
|
|
|
var recursiveDescentOpType = &operationType{Type: "RECURSIVE_DESCENT", NumArgs: 0, Precedence: 50, Handler: recursiveDescentOperator}
|
2020-10-11 23:44:33 +00:00
|
|
|
|
2021-01-11 06:13:48 +00:00
|
|
|
var selectOpType = &operationType{Type: "SELECT", NumArgs: 1, Precedence: 50, Handler: selectOperator}
|
|
|
|
var hasOpType = &operationType{Type: "HAS", NumArgs: 1, Precedence: 50, Handler: hasOperator}
|
2021-05-13 23:43:52 +00:00
|
|
|
var uniqueOpType = &operationType{Type: "UNIQUE", NumArgs: 0, Precedence: 50, Handler: unique}
|
|
|
|
var uniqueByOpType = &operationType{Type: "UNIQUE_BY", NumArgs: 1, Precedence: 50, Handler: uniqueBy}
|
2021-10-26 04:07:50 +00:00
|
|
|
var groupByOpType = &operationType{Type: "GROUP_BY", NumArgs: 1, Precedence: 50, Handler: groupBy}
|
2021-10-26 04:42:25 +00:00
|
|
|
var flattenOpType = &operationType{Type: "FLATTEN_BY", NumArgs: 0, Precedence: 50, Handler: flattenOp}
|
2021-01-11 06:13:48 +00:00
|
|
|
var deleteChildOpType = &operationType{Type: "DELETE", NumArgs: 1, Precedence: 40, Handler: deleteChildOperator}
|
2020-10-12 01:24:59 +00:00
|
|
|
|
2020-10-20 04:33:20 +00:00
|
|
|
type Operation struct {
|
2021-01-11 06:13:48 +00:00
|
|
|
OperationType *operationType
|
2020-10-20 02:53:26 +00:00
|
|
|
Value interface{}
|
|
|
|
StringValue string
|
|
|
|
CandidateNode *CandidateNode // used for Value Path elements
|
2020-10-29 23:56:45 +00:00
|
|
|
Preferences interface{}
|
2021-01-11 22:55:55 +00:00
|
|
|
UpdateAssign bool // used for assign ops, when true it means we evaluate the rhs given the lhs
|
2020-10-11 23:44:33 +00:00
|
|
|
}
|
|
|
|
|
2023-10-18 01:11:53 +00:00
|
|
|
func recurseNodeArrayEqual(lhs *CandidateNode, rhs *CandidateNode) bool {
|
2021-09-07 06:58:34 +00:00
|
|
|
if len(lhs.Content) != len(rhs.Content) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
for index := 0; index < len(lhs.Content); index = index + 1 {
|
|
|
|
if !recursiveNodeEqual(lhs.Content[index], rhs.Content[index]) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2023-10-18 01:11:53 +00:00
|
|
|
func findInArray(array *CandidateNode, item *CandidateNode) int {
|
2021-09-07 06:58:34 +00:00
|
|
|
|
|
|
|
for index := 0; index < len(array.Content); index = index + 1 {
|
|
|
|
if recursiveNodeEqual(array.Content[index], item) {
|
|
|
|
return index
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1
|
|
|
|
}
|
|
|
|
|
2023-10-18 01:11:53 +00:00
|
|
|
func findKeyInMap(dataMap *CandidateNode, item *CandidateNode) int {
|
2022-03-09 03:38:02 +00:00
|
|
|
|
2022-08-01 00:28:34 +00:00
|
|
|
for index := 0; index < len(dataMap.Content); index = index + 2 {
|
|
|
|
if recursiveNodeEqual(dataMap.Content[index], item) {
|
2022-03-09 03:38:02 +00:00
|
|
|
return index
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1
|
|
|
|
}
|
|
|
|
|
2023-10-18 01:11:53 +00:00
|
|
|
func recurseNodeObjectEqual(lhs *CandidateNode, rhs *CandidateNode) bool {
|
2021-09-07 06:58:34 +00:00
|
|
|
if len(lhs.Content) != len(rhs.Content) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
for index := 0; index < len(lhs.Content); index = index + 2 {
|
|
|
|
key := lhs.Content[index]
|
|
|
|
value := lhs.Content[index+1]
|
|
|
|
|
2022-02-07 00:55:55 +00:00
|
|
|
indexInRHS := findInArray(rhs, key)
|
2021-09-07 06:58:34 +00:00
|
|
|
|
2022-02-07 00:55:55 +00:00
|
|
|
if indexInRHS == -1 || !recursiveNodeEqual(value, rhs.Content[indexInRHS+1]) {
|
2021-09-07 06:58:34 +00:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2023-10-18 01:11:53 +00:00
|
|
|
func parseSnippet(value string) (*CandidateNode, error) {
|
2022-10-30 05:29:42 +00:00
|
|
|
if value == "" {
|
2023-10-18 01:11:53 +00:00
|
|
|
return &CandidateNode{
|
|
|
|
Kind: ScalarNode,
|
2022-10-30 05:29:42 +00:00
|
|
|
Tag: "!!null",
|
|
|
|
}, nil
|
|
|
|
}
|
2022-10-28 03:16:46 +00:00
|
|
|
decoder := NewYamlDecoder(ConfiguredYamlPreferences)
|
|
|
|
err := decoder.Init(strings.NewReader(value))
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2023-10-18 01:11:53 +00:00
|
|
|
result, err := decoder.Decode()
|
2022-11-09 10:36:53 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2022-11-15 00:35:31 +00:00
|
|
|
result.Line = 0
|
|
|
|
result.Column = 0
|
|
|
|
return result, err
|
2022-07-27 02:26:22 +00:00
|
|
|
}
|
|
|
|
|
2023-10-18 01:11:53 +00:00
|
|
|
func recursiveNodeEqual(lhs *CandidateNode, rhs *CandidateNode) bool {
|
2022-01-22 02:47:22 +00:00
|
|
|
if lhs.Kind != rhs.Kind {
|
2021-09-07 06:58:34 +00:00
|
|
|
return false
|
2022-01-22 02:47:22 +00:00
|
|
|
}
|
|
|
|
|
2023-10-18 01:11:53 +00:00
|
|
|
if lhs.Kind == ScalarNode {
|
2022-01-22 02:47:22 +00:00
|
|
|
//process custom tags of scalar nodes.
|
|
|
|
//dont worry about matching tags of maps or arrays.
|
|
|
|
|
2023-10-18 01:11:53 +00:00
|
|
|
lhsTag := lhs.guessTagFromCustomType()
|
|
|
|
rhsTag := rhs.guessTagFromCustomType()
|
2022-01-22 02:47:22 +00:00
|
|
|
|
|
|
|
if lhsTag != rhsTag {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if lhs.Tag == "!!null" {
|
2021-09-07 06:58:34 +00:00
|
|
|
return true
|
|
|
|
|
2023-10-18 01:11:53 +00:00
|
|
|
} else if lhs.Kind == ScalarNode {
|
2021-09-07 06:58:34 +00:00
|
|
|
return lhs.Value == rhs.Value
|
2023-10-18 01:11:53 +00:00
|
|
|
} else if lhs.Kind == SequenceNode {
|
2021-09-07 06:58:34 +00:00
|
|
|
return recurseNodeArrayEqual(lhs, rhs)
|
2023-10-18 01:11:53 +00:00
|
|
|
} else if lhs.Kind == MappingNode {
|
2021-09-07 06:58:34 +00:00
|
|
|
return recurseNodeObjectEqual(lhs, rhs)
|
|
|
|
}
|
|
|
|
return false
|
2022-02-20 03:29:52 +00:00
|
|
|
}
|
|
|
|
|
2023-10-18 01:11:53 +00:00
|
|
|
// yaml numbers can be hex and octal encoded...
|
2022-05-06 03:46:14 +00:00
|
|
|
func parseInt64(numberString string) (string, int64, error) {
|
2021-09-02 05:26:44 +00:00
|
|
|
if strings.HasPrefix(numberString, "0x") ||
|
|
|
|
strings.HasPrefix(numberString, "0X") {
|
2021-12-20 22:30:08 +00:00
|
|
|
num, err := strconv.ParseInt(numberString[2:], 16, 64)
|
2021-09-02 05:26:44 +00:00
|
|
|
return "0x%X", num, err
|
2023-10-18 01:11:53 +00:00
|
|
|
} else if strings.HasPrefix(numberString, "0o") {
|
|
|
|
num, err := strconv.ParseInt(numberString[2:], 8, 64)
|
|
|
|
return "0o%o", num, err
|
2021-09-02 05:26:44 +00:00
|
|
|
}
|
2021-12-20 22:30:08 +00:00
|
|
|
num, err := strconv.ParseInt(numberString, 10, 64)
|
2021-09-02 05:26:44 +00:00
|
|
|
return "%v", num, err
|
|
|
|
}
|
|
|
|
|
2022-05-22 11:19:59 +00:00
|
|
|
func parseInt(numberString string) (int, error) {
|
2023-10-18 01:11:53 +00:00
|
|
|
_, parsed, err := parseInt64(numberString)
|
2022-05-06 03:46:14 +00:00
|
|
|
|
|
|
|
if err != nil {
|
2022-05-22 11:19:59 +00:00
|
|
|
return 0, err
|
2022-10-29 07:15:21 +00:00
|
|
|
} else if parsed > math.MaxInt || parsed < math.MinInt {
|
|
|
|
return 0, fmt.Errorf("%v is not within [%v, %v]", parsed, math.MinInt, math.MaxInt)
|
2022-05-06 03:46:14 +00:00
|
|
|
}
|
|
|
|
|
2022-05-22 11:19:59 +00:00
|
|
|
return int(parsed), err
|
2022-05-06 03:46:14 +00:00
|
|
|
}
|
|
|
|
|
2023-10-18 01:11:53 +00:00
|
|
|
func headAndLineComment(node *CandidateNode) string {
|
2022-01-15 00:57:59 +00:00
|
|
|
return headComment(node) + lineComment(node)
|
|
|
|
}
|
|
|
|
|
2023-10-18 01:11:53 +00:00
|
|
|
func headComment(node *CandidateNode) string {
|
2022-01-15 00:57:59 +00:00
|
|
|
return strings.Replace(node.HeadComment, "#", "", 1)
|
|
|
|
}
|
|
|
|
|
2023-10-18 01:11:53 +00:00
|
|
|
func lineComment(node *CandidateNode) string {
|
2022-01-15 00:57:59 +00:00
|
|
|
return strings.Replace(node.LineComment, "#", "", 1)
|
|
|
|
}
|
|
|
|
|
2023-10-18 01:11:53 +00:00
|
|
|
func footComment(node *CandidateNode) string {
|
2022-01-15 00:57:59 +00:00
|
|
|
return strings.Replace(node.FootComment, "#", "", 1)
|
|
|
|
}
|
|
|
|
|
2021-07-07 12:40:46 +00:00
|
|
|
func createValueOperation(value interface{}, stringValue string) *Operation {
|
2023-01-12 04:11:45 +00:00
|
|
|
log.Debug("creating value op for string %v", stringValue)
|
2022-02-07 00:55:55 +00:00
|
|
|
var node = createScalarNode(value, stringValue)
|
2020-10-20 04:33:20 +00:00
|
|
|
|
|
|
|
return &Operation{
|
2021-01-11 06:13:48 +00:00
|
|
|
OperationType: valueOpType,
|
2020-10-20 04:33:20 +00:00
|
|
|
Value: value,
|
|
|
|
StringValue: stringValue,
|
2023-10-18 01:11:53 +00:00
|
|
|
CandidateNode: node,
|
2020-10-20 04:33:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-11 23:44:33 +00:00
|
|
|
// debugging purposes only
|
2020-10-20 04:33:20 +00:00
|
|
|
func (p *Operation) toString() string {
|
2021-09-05 01:39:11 +00:00
|
|
|
if p == nil {
|
|
|
|
return "OP IS NIL"
|
|
|
|
}
|
2021-01-11 06:13:48 +00:00
|
|
|
if p.OperationType == traversePathOpType {
|
2020-10-20 02:53:26 +00:00
|
|
|
return fmt.Sprintf("%v", p.Value)
|
2021-01-11 06:13:48 +00:00
|
|
|
} else if p.OperationType == selfReferenceOpType {
|
2020-10-20 02:53:26 +00:00
|
|
|
return "SELF"
|
2021-01-11 06:13:48 +00:00
|
|
|
} else if p.OperationType == valueOpType {
|
2020-10-20 02:53:26 +00:00
|
|
|
return fmt.Sprintf("%v (%T)", p.Value, p.Value)
|
|
|
|
} else {
|
|
|
|
return fmt.Sprintf("%v", p.OperationType.Type)
|
2020-10-11 23:44:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-29 04:13:15 +00:00
|
|
|
// use for debugging only
|
2020-10-21 01:54:58 +00:00
|
|
|
func NodesToString(collection *list.List) string {
|
2020-10-10 11:42:09 +00:00
|
|
|
if !log.IsEnabledFor(logging.DEBUG) {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
2021-09-05 01:07:40 +00:00
|
|
|
result := fmt.Sprintf("%v results\n", collection.Len())
|
2020-10-10 11:42:09 +00:00
|
|
|
for el := collection.Front(); el != nil; el = el.Next() {
|
|
|
|
result = result + "\n" + NodeToString(el.Value.(*CandidateNode))
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2020-10-08 23:59:03 +00:00
|
|
|
func NodeToString(node *CandidateNode) string {
|
|
|
|
if !log.IsEnabledFor(logging.DEBUG) {
|
|
|
|
return ""
|
|
|
|
}
|
2023-10-18 01:11:53 +00:00
|
|
|
if node == nil {
|
2020-10-17 11:10:47 +00:00
|
|
|
return "-- nil --"
|
2020-10-08 23:59:03 +00:00
|
|
|
}
|
2023-10-18 01:11:53 +00:00
|
|
|
tag := node.Tag
|
|
|
|
if node.Kind == AliasNode {
|
|
|
|
tag = "alias"
|
2020-10-08 23:59:03 +00:00
|
|
|
}
|
2023-10-18 01:11:53 +00:00
|
|
|
valueToUse := node.Value
|
|
|
|
if valueToUse == "" {
|
|
|
|
valueToUse = fmt.Sprintf("%v kids", len(node.Content))
|
2021-06-29 15:08:50 +00:00
|
|
|
}
|
2023-10-18 01:11:53 +00:00
|
|
|
return fmt.Sprintf(`D%v, P%v, %v (%v)::%v`, node.GetDocument(), node.GetNicePath(), KindString(node.Kind), tag, valueToUse)
|
|
|
|
}
|
|
|
|
|
|
|
|
func NodeContentToString(node *CandidateNode, depth int) string {
|
|
|
|
if !log.IsEnabledFor(logging.DEBUG) {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
var sb strings.Builder
|
|
|
|
for _, child := range node.Content {
|
|
|
|
for i := 0; i < depth; i++ {
|
|
|
|
sb.WriteString(" ")
|
|
|
|
}
|
|
|
|
sb.WriteString("- ")
|
|
|
|
sb.WriteString(NodeToString(child))
|
|
|
|
sb.WriteString("\n")
|
|
|
|
sb.WriteString(NodeContentToString(child, depth+1))
|
2020-10-27 05:45:16 +00:00
|
|
|
}
|
2023-10-18 01:11:53 +00:00
|
|
|
return sb.String()
|
2020-10-08 23:59:03 +00:00
|
|
|
}
|
|
|
|
|
2023-10-18 01:11:53 +00:00
|
|
|
func KindString(kind Kind) string {
|
2020-10-08 23:59:03 +00:00
|
|
|
switch kind {
|
2023-10-18 01:11:53 +00:00
|
|
|
case ScalarNode:
|
2020-10-08 23:59:03 +00:00
|
|
|
return "ScalarNode"
|
2023-10-18 01:11:53 +00:00
|
|
|
case SequenceNode:
|
2020-10-08 23:59:03 +00:00
|
|
|
return "SequenceNode"
|
2023-10-18 01:11:53 +00:00
|
|
|
case MappingNode:
|
2020-10-08 23:59:03 +00:00
|
|
|
return "MappingNode"
|
2023-10-18 01:11:53 +00:00
|
|
|
case AliasNode:
|
2020-10-08 23:59:03 +00:00
|
|
|
return "AliasNode"
|
|
|
|
default:
|
|
|
|
return "unknown!"
|
|
|
|
}
|
|
|
|
}
|