forked from qt-creator/qt-creator
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.
This commit is contained in:
@@ -119,4 +119,42 @@ QTCREATOR_UTILS_EXPORT QString withTildeHomePath(const QString &path)
|
|||||||
return outPath;
|
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
|
} // 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
|
// If path is not sub of home path, or when running on Windows, returns the input
|
||||||
QTCREATOR_UTILS_EXPORT QString withTildeHomePath(const QString &path);
|
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
|
} // namespace Utils
|
||||||
|
|
||||||
#endif // SETTINGSTUTILS_H
|
#endif // SETTINGSTUTILS_H
|
||||||
|
|||||||
@@ -33,13 +33,30 @@
|
|||||||
|
|
||||||
//TESTED_COMPONENT=src/libs/utils
|
//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
|
class tst_StringUtils : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void testWithTildeHomePath();
|
void testWithTildeHomePath();
|
||||||
|
void testMacroExpander_data();
|
||||||
|
void testMacroExpander();
|
||||||
|
|
||||||
|
private:
|
||||||
|
TestMacroExpander mx;
|
||||||
};
|
};
|
||||||
|
|
||||||
void tst_StringUtils::testWithTildeHomePath()
|
void tst_StringUtils::testWithTildeHomePath()
|
||||||
@@ -73,6 +90,39 @@ void tst_StringUtils::testWithTildeHomePath()
|
|||||||
#endif
|
#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)
|
QTEST_MAIN(tst_StringUtils)
|
||||||
|
|
||||||
#include "tst_stringutils.moc"
|
#include "tst_stringutils.moc"
|
||||||
|
|||||||
Reference in New Issue
Block a user