Skip to content

Commit 082d28c

Browse files
committed
Changed the implementation of PropertyManager::Expand() to process the string in-place which is faster.
1 parent 3d528e5 commit 082d28c

File tree

2 files changed

+28
-14
lines changed

2 files changed

+28
-14
lines changed

src/PropertyManager.cpp

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ namespace shellanything
9292
return EMPTY_VALUE;
9393
}
9494

95-
bool IsPropertyReference(const std::string & token_open, const std::string & token_close, const std::string & value, size_t offset, std::string & name)
95+
inline bool IsPropertyReference(const std::string & token_open, const std::string & token_close, const std::string & value, size_t offset, std::string & name)
9696
{
9797
size_t value_length = value.size();
9898
name.clear();
@@ -130,32 +130,32 @@ namespace shellanything
130130

131131
std::string PropertyManager::Expand(const std::string & value) const
132132
{
133+
//Process expansion in-place
133134
std::string output;
134135
output.reserve(value.size()*2);
136+
output = value;
135137

136138
static const std::string token_open = "${";
137139
static const std::string token_close = "}";
138140

139-
for(size_t i=0; i<value.size(); i++)
141+
for(size_t i=0; i<output.size(); i++)
140142
{
141143
std::string name;
142-
if (strncmp(&value[i], token_open.c_str(), token_open.size()) == 0 && IsPropertyReference(token_open, token_close, value, i, name))
144+
145+
//If we find a property reference token at this location...
146+
if (strncmp(&output[i], token_open.c_str(), token_open.size()) == 0 && IsPropertyReference(token_open, token_close, output, i, name))
143147
{
144-
//Found a property reference at value[i]
148+
//Found a property reference at output[i]
145149
const std::string & property_value = this->GetProperty(name);
146150

147-
//Also expands property_value
148-
std::string expanded = this->Expand(property_value);
149-
150-
//Proceed with the string replacement
151-
output.append(expanded);
151+
//Replace the property reference by the property's value
152+
size_t token_length = token_open.size() + name.size() + token_close.size();
153+
output.replace(output.begin() + i, output.begin() + i + token_length, property_value);
152154

153-
//Update i to skip this property reference
154-
size_t length = token_open.size() + name.size() + token_close.size();
155-
i += length-1; //-1 since the next for loop will increase i by 1.
155+
//Keep i at the same value for the next loop to process the same character position.
156+
//This is required if the property value also contains property references.
157+
i--; //-1 since the next for loop will increase i by 1.
156158
}
157-
else
158-
output.append(1, value[i]);
159159
}
160160

161161
return output;

test/TestPropertyManager.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,20 @@ namespace shellanything { namespace test
199199
ASSERT_EQ("Bond. James Bond.", expanded);
200200
}
201201
//--------------------------------------------------------------------------------------------------
202+
TEST_F(TestPropertyManager, testExpandHalf)
203+
{
204+
PropertyManager & pmgr = PropertyManager::GetInstance();
205+
206+
pmgr.SetProperty("first", "${sec");
207+
pmgr.SetProperty("second", "E.T. phone");
208+
209+
//Property ${first} should be expanded to "${sec" which is followed by "ond}" which makes ${second} which should expand to "E.T. phone"
210+
std::string expanded = pmgr.Expand("${first}ond} home");
211+
212+
//Assert the string was properly expanded.
213+
ASSERT_EQ("E.T. phone home", expanded);
214+
}
215+
//--------------------------------------------------------------------------------------------------
202216
TEST_F(TestPropertyManager, testEnvironmentVariableProperty)
203217
{
204218
PropertyManager & pmgr = PropertyManager::GetInstance();

0 commit comments

Comments
 (0)