Commit 9bd95ade authored by Oswald Buddenhagen's avatar Oswald Buddenhagen
Browse files

add generic macro expansion classes & functions to Utils

AbstractMacroExpander (any macros), AbstractQtcMacroExpander (%{var}
style macros, which is a hybrid of printf format specifiers and unix
environment expansions) and expandMacros() for the actual string
manipulation.
parent a2b6391b
......@@ -119,4 +119,42 @@ QTCREATOR_UTILS_EXPORT QString withTildeHomePath(const QString &path)
return outPath;
}
int AbstractQtcMacroExpander::findMacro(const QString &str, int *pos, QString *ret)
{
forever {
int openPos = str.indexOf(QLatin1String("%{"), *pos);
if (openPos < 0)
return 0;
int varPos = openPos + 2;
int closePos = str.indexOf(QLatin1Char('}'), varPos);
if (closePos < 0)
return 0;
int varLen = closePos - varPos;
if (resolveMacro(str.mid(varPos, varLen), ret)) {
*pos = openPos;
return varLen + 3;
}
// An actual expansion may be nested into a "false" one,
// so we continue right after the last %{.
*pos = varPos;
}
}
QTCREATOR_UTILS_EXPORT void expandMacros(QString *str, AbstractMacroExpander *mx)
{
QString rsts;
for (int pos = 0; int len = mx->findMacro(*str, &pos, &rsts); ) {
str->replace(pos, len, rsts);
pos += rsts.length();
}
}
QTCREATOR_UTILS_EXPORT QString expandMacros(const QString &str, AbstractMacroExpander *mx)
{
QString ret = str;
expandMacros(&ret, mx);
return ret;
}
} // namespace Utils
......@@ -55,6 +55,30 @@ QTCREATOR_UTILS_EXPORT QString commonPath(const QStringList &files);
// If path is not sub of home path, or when running on Windows, returns the input
QTCREATOR_UTILS_EXPORT QString withTildeHomePath(const QString &path);
class QTCREATOR_UTILS_EXPORT AbstractMacroExpander {
public:
// Not const, as it may change the state of the expander.
//! Find an expando to replace and provide a replacement string.
//! \param str The string to scan
//! \param pos Position to start scan on input, found position on output
//! \param ret Replacement string on output
//! \return Length of string part to replace, zero if no (further) matches found
virtual int findMacro(const QString &str, int *pos, QString *ret) = 0;
};
class QTCREATOR_UTILS_EXPORT AbstractQtcMacroExpander : public AbstractMacroExpander {
public:
virtual int findMacro(const QString &str, int *pos, QString *ret);
//! Provide a replacement string for an expando
//! \param name The name of the expando
//! \param ret Replacement string on output
//! \return True if the expando was found
virtual bool resolveMacro(const QString &name, QString *ret) = 0;
};
QTCREATOR_UTILS_EXPORT void expandMacros(QString *str, AbstractMacroExpander *mx);
QTCREATOR_UTILS_EXPORT QString expandMacros(const QString &str, AbstractMacroExpander *mx);
} // namespace Utils
#endif // SETTINGSTUTILS_H
......@@ -33,13 +33,30 @@
//TESTED_COMPONENT=src/libs/utils
class TestMacroExpander : public Utils::AbstractQtcMacroExpander
{
public:
virtual bool resolveMacro(const QString &name, QString *ret)
{
if (name == QLatin1String("a")) {
*ret = QLatin1String("hi");
return true;
}
return false;
}
};
class tst_StringUtils : public QObject
{
Q_OBJECT
private slots:
void testWithTildeHomePath();
void testMacroExpander_data();
void testMacroExpander();
private:
TestMacroExpander mx;
};
void tst_StringUtils::testWithTildeHomePath()
......@@ -73,6 +90,39 @@ void tst_StringUtils::testWithTildeHomePath()
#endif
}
void tst_StringUtils::testMacroExpander_data()
{
QTest::addColumn<QString>("in");
QTest::addColumn<QString>("out");
static const struct {
const char * const in;
const char * const out;
} vals[] = {
{ "text", "text" },
{ "%{a}", "hi" },
{ "pre%{a}", "prehi" },
{ "%{a}post", "hipost" },
{ "pre%{a}post", "prehipost" },
{ "%{a}%{a}", "hihi" },
{ "%{a}text%{a}", "hitexthi" },
};
for (unsigned i = 0; i < sizeof(vals)/sizeof(vals[0]); i++)
QTest::newRow(vals[i].in) << QString::fromLatin1(vals[i].in)
<< QString::fromLatin1(vals[i].out);
}
void tst_StringUtils::testMacroExpander()
{
QFETCH(QString, in);
QFETCH(QString, out);
Utils::expandMacros(&in, &mx);
QCOMPARE(in, out);
}
QTEST_MAIN(tst_StringUtils)
#include "tst_stringutils.moc"
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment