summaryrefslogtreecommitdiffstats
path: root/vespalib
diff options
context:
space:
mode:
authorArne H Juul <arnej27959@users.noreply.github.com>2020-04-22 09:07:34 +0200
committerGitHub <noreply@github.com>2020-04-22 09:07:34 +0200
commit70bea1994b88a54b59a6e8dcf0a8c1e0854065ff (patch)
tree89af8b4d6bf42f083c36a46cd5538f51ec19f4d7 /vespalib
parentffe381b38b862956e40a2ee5ed6a2cd59d4c8142 (diff)
parent441eb67040d88d99cfbc7043e4ba62533f5ca36a (diff)
Merge pull request #12980 from vespa-engine/fix-foreach-variable-replacement
Fix foreach variable replacement
Diffstat (limited to 'vespalib')
-rw-r--r--vespalib/src/tests/stllike/CMakeLists.txt8
-rw-r--r--vespalib/src/tests/stllike/replace_variable_test.cpp30
-rw-r--r--vespalib/src/vespa/vespalib/stllike/CMakeLists.txt1
-rw-r--r--vespalib/src/vespa/vespalib/stllike/replace_variable.cpp51
-rw-r--r--vespalib/src/vespa/vespalib/stllike/replace_variable.h9
5 files changed, 99 insertions, 0 deletions
diff --git a/vespalib/src/tests/stllike/CMakeLists.txt b/vespalib/src/tests/stllike/CMakeLists.txt
index 04c1a420f5e..ebf7de9c747 100644
--- a/vespalib/src/tests/stllike/CMakeLists.txt
+++ b/vespalib/src/tests/stllike/CMakeLists.txt
@@ -47,3 +47,11 @@ vespa_add_executable(vespalib_lookup_benchmark_app
vespalib
)
vespa_add_test(NAME vespalib_lookup_benchmark_app COMMAND vespalib_lookup_benchmark_app BENCHMARK)
+vespa_add_executable(vespalib_replace_variable_test_app TEST
+ SOURCES
+ replace_variable_test.cpp
+ DEPENDS
+ vespalib
+ gtest
+)
+vespa_add_test(NAME vespalib_replace_variable_test_app COMMAND vespalib_replace_variable_test_app)
diff --git a/vespalib/src/tests/stllike/replace_variable_test.cpp b/vespalib/src/tests/stllike/replace_variable_test.cpp
new file mode 100644
index 00000000000..46aa768013a
--- /dev/null
+++ b/vespalib/src/tests/stllike/replace_variable_test.cpp
@@ -0,0 +1,30 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#include <vespa/vespalib/stllike/replace_variable.h>
+#include <vespa/vespalib/gtest/gtest.h>
+
+using namespace vespalib;
+
+TEST(ReplaceVariableTest, simple_usage)
+{
+ // replace one variable
+ EXPECT_EQ("vv", replace_variable("x", "x", "vv"));
+ EXPECT_EQ("f(vv)", replace_variable("f(x)", "x", "vv"));
+ EXPECT_EQ("f(vv)", replace_variable("f(myvariablename)", "myvariablename", "vv"));
+ EXPECT_EQ("vv(f)", replace_variable("x(f)", "x", "vv"));
+ EXPECT_EQ("3*vv", replace_variable("3*x", "x", "vv"));
+
+ // replace variable multiple times
+ EXPECT_EQ("vv(vv,vv*vv)+vv", replace_variable("x(x,x*x)+x", "x", "vv"));
+
+ // do not replace variable when substring of a word
+ EXPECT_EQ("f(xx)", replace_variable("f(xx)", "x", "vv"));
+ EXPECT_EQ("f(ax)", replace_variable("f(ax)", "x", "vv"));
+ EXPECT_EQ("f(xa)", replace_variable("f(xa)", "x", "vv"));
+ EXPECT_EQ("f(axa)", replace_variable("f(axa)", "x", "vv"));
+
+ // variable names can contain underscore '_'
+ EXPECT_EQ("f(vv)", replace_variable("f(x_y)", "x_y", "vv"));
+}
+
+GTEST_MAIN_RUN_ALL_TESTS()
diff --git a/vespalib/src/vespa/vespalib/stllike/CMakeLists.txt b/vespalib/src/vespa/vespalib/stllike/CMakeLists.txt
index aaada6fdcc4..f8b9e90dc62 100644
--- a/vespalib/src/vespa/vespalib/stllike/CMakeLists.txt
+++ b/vespalib/src/vespa/vespalib/stllike/CMakeLists.txt
@@ -7,6 +7,7 @@ vespa_add_library(vespalib_vespalib_stllike OBJECT
hash_fun.cpp
hash_set.cpp
hash_map.cpp
+ replace_variable.cpp
string.cpp
DEPENDS
)
diff --git a/vespalib/src/vespa/vespalib/stllike/replace_variable.cpp b/vespalib/src/vespa/vespalib/stllike/replace_variable.cpp
new file mode 100644
index 00000000000..fbbcff48963
--- /dev/null
+++ b/vespalib/src/vespa/vespalib/stllike/replace_variable.cpp
@@ -0,0 +1,51 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#include "replace_variable.h"
+#include "asciistream.h"
+#include <ctype.h>
+
+namespace vespalib {
+
+vespalib::string
+replace_variable(const vespalib::string &input,
+ const vespalib::string &variable,
+ const vespalib::string &replacement)
+{
+ vespalib::asciistream result;
+ bool is_in_word = false;
+ size_t last_word_start = 0;
+ size_t last_word_size = 0;
+ for (size_t i = 0; i < input.size(); ++i) {
+ char c = input[i];
+ if (isalnum(c) || (c == '_')) {
+ if (! is_in_word) {
+ last_word_start = i;
+ last_word_size = 0;
+ is_in_word = true;
+ }
+ ++last_word_size;
+ } else {
+ if (is_in_word) {
+ vespalib::string last_word = input.substr(last_word_start, last_word_size);
+ if (last_word == variable) {
+ result << replacement;
+ } else {
+ result << last_word;
+ }
+ is_in_word = false;
+ }
+ result << c;
+ }
+ }
+ if (is_in_word) {
+ vespalib::string last_word = input.substr(last_word_start, last_word_size);
+ if (last_word == variable) {
+ result << replacement;
+ } else {
+ result << last_word;
+ }
+ }
+ return result.str();
+}
+
+} // namespace
diff --git a/vespalib/src/vespa/vespalib/stllike/replace_variable.h b/vespalib/src/vespa/vespalib/stllike/replace_variable.h
new file mode 100644
index 00000000000..8caf1c54bfd
--- /dev/null
+++ b/vespalib/src/vespa/vespalib/stllike/replace_variable.h
@@ -0,0 +1,9 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#include "string.h"
+
+namespace vespalib {
+vespalib::string replace_variable(const vespalib::string &input,
+ const vespalib::string &variable,
+ const vespalib::string &replacement);
+} // namespace vespalib