Skip to content

Commit 997ecd9

Browse files
KetchupBombsbarzowski
authored andcommitted
split and splitLimit to support multi-character strings
1 parent a843200 commit 997ecd9

File tree

5 files changed

+62
-41
lines changed

5 files changed

+62
-41
lines changed

core/vm.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1466,11 +1466,11 @@ class Interpreter {
14661466
auto &elements = static_cast<HeapArray *>(scratch.v.h)->elements;
14671467
while (test < str->value.size() && (maxsplits == -1 ||
14681468
size_t(maxsplits) > elements.size())) {
1469-
if (c->value[0] == str->value[test]) {
1469+
if (c->value == str->value.substr(test, c->value.size())) {
14701470
auto *th = makeHeap<HeapThunk>(idArrayElement, nullptr, 0, nullptr);
14711471
elements.push_back(th);
14721472
th->fill(makeString(str->value.substr(start, test - start)));
1473-
start = test + 1;
1473+
start = test + c->value.size();
14741474
test = start;
14751475
} else {
14761476
++test;

doc/_stdlib_gen/stdlib-content.jsonnet

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -339,36 +339,46 @@ local html = import 'html.libsonnet';
339339
{
340340
name: 'split',
341341
params: ['str', 'c'],
342-
description: |||
343-
Split the string <code>str</code> into an array of strings, divided by the single character
344-
<code>c</code>.
345-
|||,
342+
description: [
343+
html.p({}, |||
344+
Split the string <code>str</code> into an array of strings, divided by the string
345+
<code>c</code>.
346+
|||),
347+
html.p({}, |||
348+
Note: Versions up to and including 0.18.0 require <code>c</code> to be a single character.
349+
|||),
350+
],
346351
examples: [
347352
{
348-
input: @'std.split("foo/bar", "/")',
349-
output: std.split('foo/bar', '/'),
353+
input: @'std.split("foo/_bar", "/_")',
354+
output: std.split('foo/_bar', '/_'),
350355
},
351356
{
352-
input: @'std.split("/foo/", "/")',
353-
output: std.split('/foo/', '/'),
357+
input: @'std.split("/_foo/_bar", "/_")',
358+
output: std.split('/_foo/_bar', '/_'),
354359
},
355360
],
356361
},
357362
{
358363
name: 'splitLimit',
359364
params: ['str', 'c', 'maxsplits'],
360-
description: |||
361-
As std.split(str, c) but will stop after <code>maxsplits</code> splits, thereby the largest
362-
array it will return has length <code>maxsplits + 1</code>. A limit of -1 means unlimited.
363-
|||,
365+
description: [
366+
html.p({}, |||
367+
As <code>std.split(str, c)</code> but will stop after <code>maxsplits</code> splits, thereby the largest
368+
array it will return has length <code>maxsplits + 1</code>. A limit of <code>-1</code> means unlimited.
369+
|||),
370+
html.p({}, |||
371+
Note: Versions up to and including 0.18.0 require <code>c</code> to be a single character.
372+
|||),
373+
],
364374
examples: [
365375
{
366-
input: @'std.splitLimit("foo/bar", "/", 1)',
367-
output: std.splitLimit('foo/bar', '/', 1),
376+
input: @'std.splitLimit("foo/_bar", "/_", 1)',
377+
output: std.splitLimit('foo/_bar', '/_', 1),
368378
},
369379
{
370-
input: @'std.splitLimit("/foo/bar", "/", 1)',
371-
output: std.splitLimit('/foo/bar', '/', 1),
380+
input: @'std.splitLimit("/_foo/_bar", "/_", 1)',
381+
output: std.splitLimit('/_foo/_bar', '/_', 1),
372382
},
373383
],
374384
},

doc/ref/stdlib.html

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -785,14 +785,17 @@ <h4 id="split">
785785
<div class="hgroup-inline">
786786
<div class="panel">
787787
<p>
788-
Split the string <code>str</code> into an array of strings, divided by the single character
788+
Split the string <code>str</code> into an array of strings, divided by the string
789789
<code>c</code>.
790790
</p>
791791
<p>
792-
Example: <code>std.split("foo/bar", "/")</code> yields <code>[ "foo", "bar" ]</code>.
792+
Note: Versions up to and including 0.18.0 require <code>c</code> to be a single character.
793793
</p>
794794
<p>
795-
Example: <code>std.split("/foo/", "/")</code> yields <code>[ "", "foo", "" ]</code>.
795+
Example: <code>std.split("foo/_bar", "/_")</code> yields <code>[ "foo", "bar" ]</code>.
796+
</p>
797+
<p>
798+
Example: <code>std.split("/_foo/_bar", "/_")</code> yields <code>[ "", "foo", "bar" ]</code>.
796799
</p>
797800
</div>
798801
<div style="clear: both"></div>
@@ -813,14 +816,17 @@ <h4 id="splitLimit">
813816
<div class="hgroup-inline">
814817
<div class="panel">
815818
<p>
816-
As std.split(str, c) but will stop after <code>maxsplits</code> splits, thereby the largest
817-
array it will return has length <code>maxsplits + 1</code>. A limit of -1 means unlimited.
819+
As <code>std.split(str, c)</code> but will stop after <code>maxsplits</code> splits, thereby the largest
820+
array it will return has length <code>maxsplits + 1</code>. A limit of <code>-1</code> means unlimited.
821+
</p>
822+
<p>
823+
Note: Versions up to and including 0.18.0 require <code>c</code> to be a single character.
818824
</p>
819825
<p>
820-
Example: <code>std.splitLimit("foo/bar", "/", 1)</code> yields <code>[ "foo", "bar" ]</code>.
826+
Example: <code>std.splitLimit("foo/_bar", "/_", 1)</code> yields <code>[ "foo", "bar" ]</code>.
821827
</p>
822828
<p>
823-
Example: <code>std.splitLimit("/foo/bar", "/", 1)</code> yields <code>[ "", "foo/bar" ]</code>.
829+
Example: <code>std.splitLimit("/_foo/_bar", "/_", 1)</code> yields <code>[ "", "foo/_bar" ]</code>.
824830
</p>
825831
</div>
826832
<div style="clear: both"></div>

stdlib/std.jsonnet

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -110,26 +110,27 @@ limitations under the License.
110110
parse_nat(str, 16),
111111

112112
split(str, c)::
113-
assert std.isString(str) : 'std.split first parameter should be a string, got ' + std.type(str);
114-
assert std.isString(c) : 'std.split second parameter should be a string, got ' + std.type(c);
115-
assert std.length(c) == 1 : 'std.split second parameter should have length 1, got ' + std.length(c);
113+
assert std.isString(str) : 'std.split first parameter must be a String, got ' + std.type(str);
114+
assert std.isString(c) : 'std.split second parameter must be a String, got ' + std.type(c);
115+
assert std.length(c) >= 1 : 'std.split second parameter must have length 1 or greater, got ' + std.length(c);
116116
std.splitLimit(str, c, -1),
117117

118118
splitLimit(str, c, maxsplits)::
119-
assert std.isString(str) : 'std.splitLimit first parameter should be a string, got ' + std.type(str);
120-
assert std.isString(c) : 'std.splitLimit second parameter should be a string, got ' + std.type(c);
121-
assert std.length(c) == 1 : 'std.splitLimit second parameter should have length 1, got ' + std.length(c);
122-
assert std.isNumber(maxsplits) : 'std.splitLimit third parameter should be a number, got ' + std.type(maxsplits);
123-
local aux(str, delim, i, arr, v) =
124-
local c = str[i];
125-
local i2 = i + 1;
126-
if i >= std.length(str) then
127-
arr + [v]
128-
else if c == delim && (maxsplits == -1 || std.length(arr) < maxsplits) then
129-
aux(str, delim, i2, arr + [v], '') tailstrict
119+
assert std.isString(str) : 'str.splitLimit first parameter must be a String, got ' + std.type(str);
120+
assert std.isString(c) : 'str.splitLimit second parameter must be a String, got ' + std.type(c);
121+
assert std.length(c) >= 1 : 'std.splitLimit second parameter must have length 1 or greater, got ' + std.length(c);
122+
assert std.isNumber(maxsplits) : 'str.splitLimit third parameter must be a Number, got ' + std.type(maxsplits);
123+
local strLen = std.length(str);
124+
local cLen = std.length(c);
125+
local aux(idx, ret, val) =
126+
if idx >= strLen then
127+
ret + [val]
128+
else if str[idx : idx + cLen : 1] == c &&
129+
(maxsplits == -1 || std.length(ret) < maxsplits) then
130+
aux(idx + cLen, ret + [val], '')
130131
else
131-
aux(str, delim, i2, arr, v + c) tailstrict;
132-
aux(str, c, 0, [], ''),
132+
aux(idx + 1, ret, val + str[idx]);
133+
aux(0, [], ''),
133134

134135
strReplace(str, from, to)::
135136
assert std.isString(str);

test_suite/stdlib.jsonnet

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,9 +480,13 @@ std.assertEqual(std.extVar('var2') { x+: 2 }.x, 3) &&
480480

481481
std.assertEqual(std.split('foo/bar', '/'), ['foo', 'bar']) &&
482482
std.assertEqual(std.split('/foo/', '/'), ['', 'foo', '']) &&
483+
std.assertEqual(std.split('foo/_bar', '/_'), ['foo', 'bar']) &&
484+
std.assertEqual(std.split('/_foo/_', '/_'), ['', 'foo', '']) &&
483485

484486
std.assertEqual(std.splitLimit('foo/bar', '/', 1), ['foo', 'bar']) &&
485487
std.assertEqual(std.splitLimit('/foo/', '/', 1), ['', 'foo/']) &&
488+
std.assertEqual(std.splitLimit('foo/_bar', '/_', 1), ['foo', 'bar']) &&
489+
std.assertEqual(std.splitLimit('/_foo/_', '/_', 1), ['', 'foo/_']) &&
486490

487491
local some_toml = {
488492
key: 'value',

0 commit comments

Comments
 (0)