feat: implement std.splitLimitR (#745)

This commit is contained in:
itchyny 2024-06-10 03:25:22 +09:00 committed by GitHub
parent e544339880
commit fa70aa4711
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 94 additions and 0 deletions

View File

@ -1324,6 +1324,47 @@ func builtinSplitLimit(i *interpreter, strv, cv, maxSplitsV value) (value, error
return makeValueArray(res), nil
}
func builtinSplitLimitR(i *interpreter, strv, cv, maxSplitsV value) (value, error) {
str, err := i.getString(strv)
if err != nil {
return nil, err
}
c, err := i.getString(cv)
if err != nil {
return nil, err
}
maxSplits, err := i.getInt(maxSplitsV)
if err != nil {
return nil, err
}
if maxSplits < -1 {
return nil, i.Error(fmt.Sprintf("std.splitLimitR third parameter should be -1 or non-negative, got %v", maxSplits))
}
sStr := str.getGoString()
sC := c.getGoString()
if len(sC) < 1 {
return nil, i.Error(fmt.Sprintf("std.splitLimitR second parameter should have length 1 or greater, got %v", len(sC)))
}
count := strings.Count(sStr, sC)
if maxSplits > -1 && count > maxSplits {
count = maxSplits
}
strs := make([]string, count+1)
for i := count; i > 0; i-- {
index := strings.LastIndex(sStr, sC)
strs[i] = sStr[index+len(sC):]
sStr = sStr[:index]
}
strs[0] = sStr
res := make([]*cachedThunk, len(strs))
for i := range strs {
res[i] = readyThunk(makeValueString(strs[i]))
}
return makeValueArray(res), nil
}
func builtinStrReplace(i *interpreter, strv, fromv, tov value) (value, error) {
str, err := i.getString(strv)
if err != nil {
@ -2511,6 +2552,7 @@ var funcBuiltins = buildBuiltinMap([]builtin{
&binaryBuiltin{name: "stripChars", function: builtinStripChars, params: ast.Identifiers{"str", "chars"}},
&ternaryBuiltin{name: "substr", function: builtinSubstr, params: ast.Identifiers{"str", "from", "len"}},
&ternaryBuiltin{name: "splitLimit", function: builtinSplitLimit, params: ast.Identifiers{"str", "c", "maxsplits"}},
&ternaryBuiltin{name: "splitLimitR", function: builtinSplitLimitR, params: ast.Identifiers{"str", "c", "maxsplits"}},
&ternaryBuiltin{name: "strReplace", function: builtinStrReplace, params: ast.Identifiers{"str", "from", "to"}},
&unaryBuiltin{name: "isEmpty", function: builtinIsEmpty, params: ast.Identifiers{"str"}},
&binaryBuiltin{name: "equalsIgnoreCase", function: builtinEqualsIgnoreCase, params: ast.Identifiers{"str1", "str2"}},

View File

@ -90,6 +90,7 @@ func prepareStdlib(g *typeGraph) {
"rstripChars": g.newSimpleFuncType(stringType, "str", "chars"),
"split": g.newSimpleFuncType(arrayOfString, "str", "c"),
"splitLimit": g.newSimpleFuncType(arrayOfString, "str", "c", "maxsplits"),
"splitLimitR": g.newSimpleFuncType(arrayOfString, "str", "c", "maxsplits"),
"strReplace": g.newSimpleFuncType(stringType, "str", "from", "to"),
"asciiUpper": g.newSimpleFuncType(stringType, "str"),
"asciiLower": g.newSimpleFuncType(stringType, "str"),

5
testdata/builtinSplitLimitR.golden vendored Normal file
View File

@ -0,0 +1,5 @@
[
"foo,bar",
"baz",
"qux"
]

1
testdata/builtinSplitLimitR.jsonnet vendored Normal file
View File

@ -0,0 +1 @@
std.splitLimitR('foo,bar,baz,qux', ',', 2)

View File

3
testdata/builtinSplitLimitR2.golden vendored Normal file
View File

@ -0,0 +1,3 @@
[
"foo,bar,baz,qux"
]

1
testdata/builtinSplitLimitR2.jsonnet vendored Normal file
View File

@ -0,0 +1 @@
std.splitLimitR('foo,bar,baz,qux', ',', 0)

View File

6
testdata/builtinSplitLimitR3.golden vendored Normal file
View File

@ -0,0 +1,6 @@
[
"foo",
"bar",
"baz",
"qux"
]

1
testdata/builtinSplitLimitR3.jsonnet vendored Normal file
View File

@ -0,0 +1 @@
std.splitLimitR('foo,bar,baz,qux', ',', -1)

View File

6
testdata/builtinSplitLimitR4.golden vendored Normal file
View File

@ -0,0 +1,6 @@
[
"foo",
"bar",
"baz",
"qux"
]

1
testdata/builtinSplitLimitR4.jsonnet vendored Normal file
View File

@ -0,0 +1 @@
std.splitLimitR('foo,bar,baz,qux', ',', 4)

View File

10
testdata/builtinSplitLimitR5.golden vendored Normal file
View File

@ -0,0 +1,10 @@
RUNTIME ERROR: std.splitLimitR third parameter should be -1 or non-negative, got -2
-------------------------------------------------
testdata/builtinSplitLimitR5:1:1-44 $
std.splitLimitR('foo,bar,baz,qux', ',', -2)
-------------------------------------------------
During evaluation

1
testdata/builtinSplitLimitR5.jsonnet vendored Normal file
View File

@ -0,0 +1 @@
std.splitLimitR('foo,bar,baz,qux', ',', -2)

View File

10
testdata/builtinSplitLimitR6.golden vendored Normal file
View File

@ -0,0 +1,10 @@
RUNTIME ERROR: std.splitLimitR second parameter should have length 1 or greater, got 0
-------------------------------------------------
testdata/builtinSplitLimitR6:1:1-43 $
std.splitLimitR('foo,bar,baz,qux', '', -1)
-------------------------------------------------
During evaluation

1
testdata/builtinSplitLimitR6.jsonnet vendored Normal file
View File

@ -0,0 +1 @@
std.splitLimitR('foo,bar,baz,qux', '', -1)

View File

View File

@ -243,6 +243,10 @@
"a",
"b,c"
],
"splitLimitR": [
"a,b",
"c"
],
"sqrt": 2.2360679774997898,
"startsWith": true,
"strReplace": "bba",

View File

@ -72,6 +72,7 @@
rstripChars: std.rstripChars(str="aaabbbbcccc", chars="c"),
split: std.split(str="a,b,c", c=","),
splitLimit: std.splitLimit(str="a,b,c", c=",", maxsplits=1),
splitLimitR: std.splitLimitR(str="a,b,c", c=",", maxsplits=1),
strReplace: std.strReplace(str="aaa", from="aa", to="bb"),
asciiUpper: std.asciiUpper(str="Blah"),
asciiLower: std.asciiLower(str="Blah"),