Skip to content

Commit

Permalink
Changed the implementation of PropertyManager::Expand() to process th…
Browse files Browse the repository at this point in the history
…e string in-place which is faster. #72
  • Loading branch information
end2endzone committed Dec 28, 2020
1 parent 3d528e5 commit 71a5b08
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 14 deletions.
28 changes: 14 additions & 14 deletions src/PropertyManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ namespace shellanything
return EMPTY_VALUE;
}

bool IsPropertyReference(const std::string & token_open, const std::string & token_close, const std::string & value, size_t offset, std::string & name)
inline bool IsPropertyReference(const std::string & token_open, const std::string & token_close, const std::string & value, size_t offset, std::string & name)
{
size_t value_length = value.size();
name.clear();
Expand Down Expand Up @@ -130,32 +130,32 @@ namespace shellanything

std::string PropertyManager::Expand(const std::string & value) const
{
//Process expansion in-place
std::string output;
output.reserve(value.size()*2);
output = value;

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

for(size_t i=0; i<value.size(); i++)
for(size_t i=0; i<output.size(); i++)
{
std::string name;
if (strncmp(&value[i], token_open.c_str(), token_open.size()) == 0 && IsPropertyReference(token_open, token_close, value, i, name))

//If we find a property reference token at this location...
if (strncmp(&output[i], token_open.c_str(), token_open.size()) == 0 && IsPropertyReference(token_open, token_close, output, i, name))
{
//Found a property reference at value[i]
//Found a property reference at output[i]
const std::string & property_value = this->GetProperty(name);

//Also expands property_value
std::string expanded = this->Expand(property_value);

//Proceed with the string replacement
output.append(expanded);
//Replace the property reference by the property's value
size_t token_length = token_open.size() + name.size() + token_close.size();
output.replace(output.begin() + i, output.begin() + i + token_length, property_value);

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

return output;
Expand Down
14 changes: 14 additions & 0 deletions test/TestPropertyManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,20 @@ namespace shellanything { namespace test
ASSERT_EQ("Bond. James Bond.", expanded);
}
//--------------------------------------------------------------------------------------------------
TEST_F(TestPropertyManager, testExpandHalf)
{
PropertyManager & pmgr = PropertyManager::GetInstance();

pmgr.SetProperty("first", "${sec");
pmgr.SetProperty("second", "E.T. phone");

//Property ${first} should be expanded to "${sec" which is followed by "ond}" which makes ${second} which should expand to "E.T. phone"
std::string expanded = pmgr.Expand("${first}ond} home");

//Assert the string was properly expanded.
ASSERT_EQ("E.T. phone home", expanded);
}
//--------------------------------------------------------------------------------------------------
TEST_F(TestPropertyManager, testEnvironmentVariableProperty)
{
PropertyManager & pmgr = PropertyManager::GetInstance();
Expand Down

0 comments on commit 71a5b08

Please sign in to comment.