Skip to content

Commit 1fd2d0d

Browse files
committed
Add new string utils with initial support for uniquePostfixPath for a range of names
1 parent f0ed107 commit 1fd2d0d

File tree

1 file changed

+96
-0
lines changed

1 file changed

+96
-0
lines changed

libdeadcode/src/util/string.d

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
module util.string;
2+
3+
import std.typecons;
4+
5+
version (unittest) import test;
6+
7+
// TODO: This could be optimized
8+
auto uniquePostfixPath(R)(R names)
9+
{
10+
import std.algorithm;
11+
import std.array;
12+
import std.path;
13+
14+
struct SortHelper
15+
{
16+
int index;
17+
string name;
18+
const(char)[][] reversePathElements;
19+
int pathElementsUsed;
20+
}
21+
int idx = 0;
22+
23+
auto r = names
24+
.map!((a) => SortHelper(idx++, a, a.pathSplitter.array.reverse)).array
25+
.sort!"a.reversePathElements < b.reversePathElements"().array;
26+
27+
28+
foreach (index, ref item; r)
29+
{
30+
import std.stdio;
31+
item.pathElementsUsed = 1;
32+
if (index != 0)
33+
{
34+
int lastPathElementsUsed = r[index-1].pathElementsUsed;
35+
36+
auto prefix = commonPrefix(r[index-1].reversePathElements, item.reversePathElements);
37+
if (prefix.length != 0)
38+
{
39+
int newElementsUsed = prefix.length + 1; // +1 to add the disambiguating elements
40+
item.pathElementsUsed = min(newElementsUsed, item.reversePathElements.length);
41+
r[index - 1].pathElementsUsed = min(newElementsUsed, r[index - 1].reversePathElements.length);
42+
}
43+
}
44+
}
45+
46+
return r.sort!((a,b) => a.index < b.index).map!((a) => tuple(a.reversePathElements[0..a.pathElementsUsed].reverse.buildPath, a.name));
47+
}
48+
49+
version (unittest)
50+
private string[] toarr(R)(R e)
51+
{
52+
import std.algorithm;
53+
import std.array;
54+
return e.map!"a[0]".array;
55+
}
56+
57+
unittest
58+
{
59+
auto a = [ "a1", "a2", "b" ];
60+
61+
62+
a = [ "b", "a", "b"];
63+
Assert(uniquePostfixPath(a).toarr, a, "One level uniquePostfixPath");
64+
65+
a = [ "b", "a", "foo\\a" ];
66+
Assert(uniquePostfixPath(a).toarr, a, "One conflict uniquePostfixPath");
67+
68+
a = [ "b", "foo\\a", "bar\\a"];
69+
Assert(uniquePostfixPath(a).toarr, a, "One two conflicts uniquePostfixPath");
70+
71+
a = [ "b", "a", "foo\\a", "bar\\a"];
72+
Assert(uniquePostfixPath(a).toarr, a, "One two conflicts uniquePostfixPath");
73+
74+
a = [ "b", "foo\\a", "bar\\a", "a"];
75+
Assert(uniquePostfixPath(a).toarr, a, "One two conflicts reverse uniquePostfixPath");
76+
77+
a = [ "b", "foo\\a", "bar\\goo\\a", "a"];
78+
Assert(uniquePostfixPath(a).toarr, [ "b", "foo\\a", "goo\\a", "a"], "One three conflicts reverse uniquePostfixPath");
79+
80+
// With prefix
81+
a = [ "prefix\\b", "prefix\\a", "prefix\\b"];
82+
Assert(uniquePostfixPath(a).toarr, [ "prefix\\b", "a", "prefix\\b"], "One level uniquePostfixPath");
83+
84+
a = [ "prefix\\b", "prefix\\a", "prefix\\foo\\a" ];
85+
Assert(uniquePostfixPath(a).toarr, [ "b", "prefix\\a", "foo\\a" ], "One conflict uniquePostfixPath");
86+
87+
a = [ "prefix\\b", "prefix\\a", "prefix\\foo\\a", "prefix\\bar\\a"];
88+
Assert(uniquePostfixPath(a).toarr, [ "b", "prefix\\a", "foo\\a", "bar\\a"], "One two conflicts uniquePostfixPath");
89+
90+
a = [ "prefix\\b", "prefix\\foo\\a", "prefix\\bar\\a", "prefix\\a"];
91+
Assert(uniquePostfixPath(a).toarr, [ "b", "foo\\a", "bar\\a", "prefix\\a"], "One two conflicts reverse uniquePostfixPath");
92+
93+
a = [ "prefix\\b", "prefix\\foo\\a", "prefix\\bar\\goo\\a", "prefix\\a"];
94+
Assert(uniquePostfixPath(a).toarr, [ "b", "foo\\a", "goo\\a", "prefix\\a"], "One three conflicts reverse uniquePostfixPath");
95+
//printStats(true);
96+
}

0 commit comments

Comments
 (0)