Skip to content

Commit 699eda1

Browse files
committed
Fix issues 19042, 19681 - std.range.padRight bugs
1 parent 0482622 commit 699eda1

File tree

1 file changed

+115
-20
lines changed

1 file changed

+115
-20
lines changed

std/range/package.d

Lines changed: 115 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12863,14 +12863,27 @@ if (
1286312863
private:
1286412864
R data;
1286512865
E element;
12866-
size_t counter;
12867-
static if (isBidirectionalRange!R && hasLength!R) size_t backPosition;
12868-
size_t maxSize;
12866+
static if (hasLength!R)
12867+
{
12868+
size_t padLength;
12869+
}
12870+
else
12871+
{
12872+
size_t minLength;
12873+
size_t consumed;
12874+
}
1286912875

1287012876
public:
1287112877
bool empty() @property
1287212878
{
12873-
return data.empty && counter >= maxSize;
12879+
static if (hasLength!R)
12880+
{
12881+
return data.empty && padLength == 0;
12882+
}
12883+
else
12884+
{
12885+
return data.empty && consumed >= minLength;
12886+
}
1287412887
}
1287512888

1287612889
auto front() @property
@@ -12882,20 +12895,33 @@ if (
1288212895
void popFront()
1288312896
{
1288412897
assert(!empty, "Attempting to popFront an empty padRight");
12885-
++counter;
1288612898

12887-
if (!data.empty)
12899+
static if (hasLength!R)
12900+
{
12901+
if (!data.empty)
12902+
{
12903+
data.popFront;
12904+
}
12905+
else
12906+
{
12907+
--padLength;
12908+
}
12909+
}
12910+
else
1288812911
{
12889-
data.popFront;
12912+
++consumed;
12913+
if (!data.empty)
12914+
{
12915+
data.popFront;
12916+
}
1289012917
}
1289112918
}
1289212919

1289312920
static if (hasLength!R)
1289412921
{
1289512922
size_t length() @property
1289612923
{
12897-
import std.algorithm.comparison : max;
12898-
return max(data.length, maxSize);
12924+
return data.length + padLength;
1289912925
}
1290012926
}
1290112927

@@ -12914,16 +12940,15 @@ if (
1291412940
auto back() @property
1291512941
{
1291612942
assert(!empty, "Attempting to fetch the back of an empty padRight");
12917-
return backPosition > data.length ? element : data.back;
12943+
return padLength > 0 ? element : data.back;
1291812944
}
1291912945

1292012946
void popBack()
1292112947
{
1292212948
assert(!empty, "Attempting to popBack an empty padRight");
12923-
if (backPosition > data.length)
12949+
if (padLength > 0)
1292412950
{
12925-
--backPosition;
12926-
--maxSize;
12951+
--padLength;
1292712952
}
1292812953
else
1292912954
{
@@ -12937,8 +12962,7 @@ if (
1293712962
E opIndex(size_t index)
1293812963
{
1293912964
assert(index <= this.length, "Index out of bounds");
12940-
return (index > data.length && index <= maxSize) ? element :
12941-
data[index];
12965+
return index >= data.length ? element : data[index];
1294212966
}
1294312967
}
1294412968

@@ -12954,20 +12978,26 @@ if (
1295412978
b <= length,
1295512979
"Attempting to slice using an out of bounds index on a padRight"
1295612980
);
12957-
return Result((b <= data.length) ? data[a .. b] : data[a .. data.length],
12981+
return Result(
12982+
a >= data.length ? data[0 .. 0] : b <= data.length ? data[a .. b] : data[a .. data.length],
1295812983
element, b - a);
1295912984
}
1296012985

1296112986
alias opDollar = length;
1296212987
}
1296312988

12964-
this(R r, E e, size_t max)
12989+
this(R r, E e, size_t n)
1296512990
{
1296612991
data = r;
1296712992
element = e;
12968-
maxSize = max;
12969-
static if (isBidirectionalRange!R && hasLength!R)
12970-
backPosition = max;
12993+
static if (hasLength!R)
12994+
{
12995+
padLength = n > data.length ? n - data.length : 0;
12996+
}
12997+
else
12998+
{
12999+
minLength = n;
13000+
}
1297113001
}
1297213002

1297313003
@disable this();
@@ -13011,6 +13041,8 @@ pure @safe unittest
1301113041
RangeType r3;
1301213042
assert(r3.padRight(0, 12)[0] == 1);
1301313043
assert(r3.padRight(0, 12)[2] == 3);
13044+
assert(r3.padRight(0, 12)[9] == 10);
13045+
assert(r3.padRight(0, 12)[10] == 0);
1301413046
assert(r3.padRight(0, 12)[11] == 0);
1301513047
}
1301613048

@@ -13022,6 +13054,14 @@ pure @safe unittest
1302213054
.padRight(0, 12)[0 .. 3]
1302313055
.equal([1, 2, 3])
1302413056
);
13057+
assert(r4
13058+
.padRight(0, 12)[0 .. 10]
13059+
.equal([1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 10U])
13060+
);
13061+
assert(r4
13062+
.padRight(0, 12)[0 .. 11]
13063+
.equal([1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 0])
13064+
);
1302513065
assert(r4
1302613066
.padRight(0, 12)[2 .. $]
1302713067
.equal([3U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 0, 0])
@@ -13031,6 +13071,10 @@ pure @safe unittest
1303113071
.equal([1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 0, 0])
1303213072
);
1303313073
}
13074+
13075+
// drop & dropBack test opslice ranges when available, popFront/popBack otherwise
13076+
RangeType r5;
13077+
foreach (i; 1 .. 13) assert(r5.padRight(0, 12).drop(i).walkLength == 12 - i);
1303413078
}
1303513079
}
1303613080

@@ -13043,3 +13087,54 @@ pure @safe unittest
1304313087
static immutable r2 = [1, 2, 3, 4, 0, 0];
1304413088
assert(r1.padRight(0, 6).equal(r2));
1304513089
}
13090+
13091+
// Test back, popBack, and save
13092+
@safe pure unittest
13093+
{
13094+
import std.algorithm.comparison : equal;
13095+
13096+
auto r1 = [1, 2, 3, 4].padRight(0, 6);
13097+
assert(r1.back == 0);
13098+
13099+
r1.popBack;
13100+
auto r2 = r1.save;
13101+
assert(r1.equal([1, 2, 3, 4, 0]));
13102+
assert(r2.equal([1, 2, 3, 4, 0]));
13103+
13104+
r1.popBackN(2);
13105+
assert(r1.back == 3);
13106+
assert(r1.length == 3);
13107+
assert(r2.length == 5);
13108+
assert(r2.equal([1, 2, 3, 4, 0]));
13109+
13110+
r2.popFront;
13111+
assert(r2.length == 4);
13112+
assert(r2[0] == 2);
13113+
assert(r2[1] == 3);
13114+
assert(r2[2] == 4);
13115+
assert(r2[3] == 0);
13116+
assert(r2.equal([2, 3, 4, 0]));
13117+
13118+
r2.popBack;
13119+
assert(r2.equal([2, 3, 4]));
13120+
13121+
auto r3 = [1, 2, 3, 4].padRight(0, 6);
13122+
size_t len = 0;
13123+
while (!r3.empty)
13124+
{
13125+
++len;
13126+
r3.popBack;
13127+
}
13128+
assert(len == 6);
13129+
}
13130+
13131+
// Issue 19042
13132+
@safe pure unittest
13133+
{
13134+
import std.algorithm.comparison : equal;
13135+
13136+
assert([2, 5, 13].padRight(42, 10).chunks(5)
13137+
.equal!equal([[2, 5, 13, 42, 42], [42, 42, 42, 42, 42]]));
13138+
13139+
assert([1, 2, 3, 4].padRight(0, 10)[7 .. 9].equal([0, 0]));
13140+
}

0 commit comments

Comments
 (0)