fix SubstVar to be usable as a replace_all method
authorDavid Kalnischkies <david@kalnischkies.de>
Tue, 17 Jun 2014 14:55:19 +0000 (16:55 +0200)
committerDavid Kalnischkies <david@kalnischkies.de>
Wed, 18 Jun 2014 09:17:18 +0000 (11:17 +0200)
The name suggests that it is supposed to substitute a variable with a
value, but we tend to use it in a more liberal replace_all() fashion,
but this breaks if either of the parameters is empty or more importantly
if two "variable" occurrences follow each other directly.

apt-pkg/contrib/strutl.cc
test/libapt/strutil_test.cc

index 2100ee4..ce69c7a 100644 (file)
@@ -434,23 +434,30 @@ string TimeToStr(unsigned long Sec)
 /* This replaces all occurrences of Subst with Contents in Str. */
 string SubstVar(const string &Str,const string &Subst,const string &Contents)
 {
+   if (Subst.empty() == true)
+      return Str;
+
    string::size_type Pos = 0;
    string::size_type OldPos = 0;
    string Temp;
-   
-   while (OldPos < Str.length() && 
+
+   while (OldPos < Str.length() &&
          (Pos = Str.find(Subst,OldPos)) != string::npos)
    {
-      Temp += string(Str,OldPos,Pos) + Contents;
-      OldPos = Pos + Subst.length();      
+      if (OldPos != Pos)
+        Temp.append(Str, OldPos, Pos - OldPos);
+      if (Contents.empty() == false)
+        Temp.append(Contents);
+      OldPos = Pos + Subst.length();
    }
-   
+
    if (OldPos == 0)
       return Str;
-   
+
+   if (OldPos >= Str.length())
+      return Temp;
    return Temp + string(Str,OldPos);
 }
-
 string SubstVar(string Str,const struct SubstVar *Vars)
 {
    for (; Vars->Subst != 0; Vars++)
index bc004fd..e9b778c 100644 (file)
@@ -70,3 +70,38 @@ TEST(StrUtilTest,EndsWith)
    EXPECT_FALSE(Endswith("abcd", "x"));
    EXPECT_FALSE(Endswith("abcd", "abcndefg"));
 }
+TEST(StrUtilTest,SubstVar)
+{
+   EXPECT_EQ("", SubstVar("", "fails", "passes"));
+   EXPECT_EQ("test ", SubstVar("test fails", "fails", ""));
+   EXPECT_EQ("test passes", SubstVar("test passes", "", "fails"));
+
+   EXPECT_EQ("test passes", SubstVar("test passes", "fails", "passes"));
+   EXPECT_EQ("test passes", SubstVar("test fails", "fails", "passes"));
+
+   EXPECT_EQ("starts with", SubstVar("beginnt with", "beginnt", "starts"));
+   EXPECT_EQ("beginnt with", SubstVar("starts with", "starts", "beginnt"));
+   EXPECT_EQ("is in middle", SubstVar("is in der middle", "in der", "in"));
+   EXPECT_EQ("is in der middle", SubstVar("is in middle", "in", "in der"));
+   EXPECT_EQ("does end", SubstVar("does enden", "enden", "end"));
+   EXPECT_EQ("does enden", SubstVar("does end", "end", "enden"));
+
+   EXPECT_EQ("abc", SubstVar("abc", "d", "a"));
+   EXPECT_EQ("abc", SubstVar("abd", "d", "c"));
+   EXPECT_EQ("abc", SubstVar("adc", "d", "b"));
+   EXPECT_EQ("abc", SubstVar("dbc", "d", "a"));
+
+   EXPECT_EQ("b", SubstVar("b", "aa", "a"));
+   EXPECT_EQ("bb", SubstVar("bb", "aa", "a"));
+   EXPECT_EQ("bbb", SubstVar("bbb", "aa", "a"));
+
+   EXPECT_EQ("aa", SubstVar("aaaa", "aa", "a"));
+   EXPECT_EQ("aaaa", SubstVar("aa", "a", "aa"));
+   EXPECT_EQ("aaaa", SubstVar("aaaa", "a", "a"));
+   EXPECT_EQ("a a a a ", SubstVar("aaaa", "a", "a "));
+
+   EXPECT_EQ(" bb bb bb bb ", SubstVar(" a a a a ", "a", "bb"));
+   EXPECT_EQ(" bb bb bb bb ", SubstVar(" aaa aaa aaa aaa ", "aaa", "bb"));
+   EXPECT_EQ(" bb a bb a bb a bb ", SubstVar(" aaa a aaa a aaa a aaa ", "aaa", "bb"));
+
+}