00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "kmacroexpander_p.h"
00024 #include "kdebug.h"
00025
00026 #include <QtCore/QHash>
00027 #include <QtCore/QStringList>
00028
00029 KMacroExpanderBase::KMacroExpanderBase( QChar c ) : d(new KMacroExpanderBasePrivate(c))
00030 {
00031 }
00032
00033 KMacroExpanderBase::~KMacroExpanderBase()
00034 {
00035 delete d;
00036 }
00037
00038 void
00039 KMacroExpanderBase::setEscapeChar( QChar c )
00040 {
00041 d->escapechar = c;
00042 }
00043
00044 QChar
00045 KMacroExpanderBase::escapeChar() const
00046 {
00047 return d->escapechar;
00048 }
00049
00050 void KMacroExpanderBase::expandMacros( QString &str )
00051 {
00052 int pos;
00053 int len;
00054 QChar ec( d->escapechar );
00055 QStringList rst;
00056 QString rsts;
00057
00058 for (pos = 0; pos < str.length(); ) {
00059 if (ec != QLatin1Char(0) ) {
00060 if (str.unicode()[pos] != ec)
00061 goto nohit;
00062 if (!(len = expandEscapedMacro( str, pos, rst )))
00063 goto nohit;
00064 } else {
00065 if (!(len = expandPlainMacro( str, pos, rst )))
00066 goto nohit;
00067 }
00068 if (len < 0) {
00069 pos -= len;
00070 continue;
00071 }
00072 rsts = rst.join( QLatin1String(" ") );
00073 rst.clear();
00074 str.replace( pos, len, rsts );
00075 pos += rsts.length();
00076 continue;
00077 nohit:
00078 pos++;
00079 }
00080 }
00081
00082 bool KMacroExpanderBase::expandMacrosShellQuote( QString &str )
00083 {
00084 int pos = 0;
00085 return expandMacrosShellQuote( str, pos ) && pos == str.length();
00086 }
00087
00088 int KMacroExpanderBase::expandPlainMacro( const QString &, int, QStringList & )
00089 { qFatal( "KMacroExpanderBase::expandPlainMacro called!" ); return 0; }
00090
00091 int KMacroExpanderBase::expandEscapedMacro( const QString &, int, QStringList & )
00092 { qFatal( "KMacroExpanderBase::expandEscapedMacro called!" ); return 0; }
00093
00094
00096
00097 template <typename KT, typename VT>
00098 class KMacroMapExpander : public KMacroExpanderBase {
00099
00100 public:
00101 KMacroMapExpander( const QHash<KT,VT> &map, QChar c = QLatin1Char('%') ) :
00102 KMacroExpanderBase( c ), macromap( map ) {}
00103
00104 protected:
00105 virtual int expandPlainMacro( const QString &str, int pos, QStringList &ret );
00106 virtual int expandEscapedMacro( const QString &str, int pos, QStringList &ret );
00107
00108 private:
00109 QHash<KT,VT> macromap;
00110 };
00111
00112 static QStringList &operator+=( QStringList &s, const QString &n) { s << n; return s; }
00113
00115
00116 static bool
00117 isIdentifier( QChar c )
00118 {
00119 return c == QLatin1Char('_') ||
00120 (c >= QLatin1Char('A') && c <= QLatin1Char('Z')) ||
00121 (c >= QLatin1Char('a') && c <= QLatin1Char('z')) ||
00122 (c >= QLatin1Char('0') && c <= QLatin1Char('9'));
00123 }
00124
00126
00127 template <typename VT>
00128 class KMacroMapExpander<QChar,VT> : public KMacroExpanderBase {
00129
00130 public:
00131 KMacroMapExpander( const QHash<QChar,VT> &map, QChar c = QLatin1Char('%') ) :
00132 KMacroExpanderBase( c ), macromap( map ) {}
00133
00134 protected:
00135 virtual int expandPlainMacro( const QString &str, int pos, QStringList &ret );
00136 virtual int expandEscapedMacro( const QString &str, int pos, QStringList &ret );
00137
00138 private:
00139 QHash<QChar,VT> macromap;
00140 };
00141
00142 template <typename VT>
00143 int
00144 KMacroMapExpander<QChar,VT>::expandPlainMacro( const QString &str, int pos, QStringList &ret )
00145 {
00146 typename QHash<QChar,VT>::const_iterator it = macromap.constFind(str[pos]);
00147 if (it != macromap.constEnd()) {
00148 ret += it.value();
00149 return 1;
00150 }
00151 return 0;
00152 }
00153
00154 template <typename VT>
00155 int
00156 KMacroMapExpander<QChar,VT>::expandEscapedMacro( const QString &str, int pos, QStringList &ret )
00157 {
00158 if (str[pos + 1] == escapeChar()) {
00159 ret += QString( escapeChar() );
00160 return 2;
00161 }
00162 typename QHash<QChar,VT>::const_iterator it = macromap.constFind(str[pos+1]);
00163 if (it != macromap.constEnd()) {
00164 ret += it.value();
00165 return 2;
00166 }
00167
00168 return 0;
00169 }
00170
00171 template <typename VT>
00172 class KMacroMapExpander<QString,VT> : public KMacroExpanderBase {
00173
00174 public:
00175 KMacroMapExpander( const QHash<QString,VT> &map, QChar c = QLatin1Char('%') ) :
00176 KMacroExpanderBase( c ), macromap( map ) {}
00177
00178 protected:
00179 virtual int expandPlainMacro( const QString &str, int pos, QStringList &ret );
00180 virtual int expandEscapedMacro( const QString &str, int pos, QStringList &ret );
00181
00182 private:
00183 QHash<QString,VT> macromap;
00184 };
00185
00186 template <typename VT>
00187 int
00188 KMacroMapExpander<QString,VT>::expandPlainMacro( const QString &str, int pos, QStringList &ret )
00189 {
00190 if (isIdentifier( str[pos - 1] ))
00191 return 0;
00192 int sl;
00193 for (sl = 0; isIdentifier( str[pos + sl] ); sl++)
00194 ;
00195 if (!sl)
00196 return 0;
00197 typename QHash<QString,VT>::const_iterator it =
00198 macromap.constFind( str.mid( pos, sl ) );
00199 if (it != macromap.constEnd()) {
00200 ret += it.value();
00201 return sl;
00202 }
00203 return 0;
00204 }
00205
00206 template <typename VT>
00207 int
00208 KMacroMapExpander<QString,VT>::expandEscapedMacro( const QString &str, int pos, QStringList &ret )
00209 {
00210 if (str.length() <= pos + 1)
00211 return 0;
00212
00213 if (str[pos + 1] == escapeChar()) {
00214 ret += QString( escapeChar() );
00215 return 2;
00216 }
00217 int sl, rsl, rpos;
00218 if (str[pos + 1] == QLatin1Char('{')) {
00219 rpos = pos + 2;
00220 sl = str.indexOf(QLatin1Char('}'), rpos);
00221 if (sl == -1)
00222 return 0;
00223 else
00224 sl -= rpos;
00225 rsl = sl + 3;
00226 } else {
00227 rpos = pos + 1;
00228 for (sl = 0; (rpos + sl < str.length()) && isIdentifier( str[rpos + sl] ); sl++)
00229 ;
00230 rsl = sl + 1;
00231 }
00232 if (!sl)
00233 return 0;
00234 typename QHash<QString,VT>::const_iterator it =
00235 macromap.constFind( str.mid( rpos, sl ) );
00236 if (it != macromap.constEnd()) {
00237 ret += it.value();
00238 return rsl;
00239 }
00240 return 0;
00241 }
00242
00244
00245 int
00246 KCharMacroExpander::expandPlainMacro( const QString &str, int pos, QStringList &ret )
00247 {
00248 if (expandMacro( str[pos], ret ))
00249 return 1;
00250 return 0;
00251 }
00252
00253 int
00254 KCharMacroExpander::expandEscapedMacro( const QString &str, int pos, QStringList &ret )
00255 {
00256 if (str[pos + 1] == escapeChar()) {
00257 ret += QString( escapeChar() );
00258 return 2;
00259 }
00260 if (expandMacro( str[pos+1], ret ))
00261 return 2;
00262 return 0;
00263 }
00264
00265 int
00266 KWordMacroExpander::expandPlainMacro( const QString &str, int pos, QStringList &ret )
00267 {
00268 if (isIdentifier( str[pos - 1] ))
00269 return 0;
00270 int sl;
00271 for (sl = 0; isIdentifier( str[pos + sl] ); sl++)
00272 ;
00273 if (!sl)
00274 return 0;
00275 if (expandMacro( str.mid( pos, sl ), ret ))
00276 return sl;
00277 return 0;
00278 }
00279
00280 int
00281 KWordMacroExpander::expandEscapedMacro( const QString &str, int pos, QStringList &ret )
00282 {
00283 if (str[pos + 1] == escapeChar()) {
00284 ret += QString( escapeChar() );
00285 return 2;
00286 }
00287 int sl, rsl, rpos;
00288 if (str[pos + 1] == QLatin1Char('{')) {
00289 rpos = pos + 2;
00290 for (sl = 0; str[rpos + sl] != QLatin1Char('}'); sl++)
00291 if (rpos + sl >= str.length())
00292 return 0;
00293 rsl = sl + 3;
00294 } else {
00295 rpos = pos + 1;
00296 for (sl = 0; isIdentifier( str[rpos + sl] ); sl++)
00297 ;
00298 rsl = sl + 1;
00299 }
00300 if (!sl)
00301 return 0;
00302 if (expandMacro( str.mid( rpos, sl ), ret ))
00303 return rsl;
00304 return 0;
00305 }
00306
00308
00309 template <typename KT, typename VT>
00310 inline QString
00311 TexpandMacros( const QString &ostr, const QHash<KT,VT> &map, QChar c )
00312 {
00313 QString str( ostr );
00314 KMacroMapExpander<KT,VT> kmx( map, c );
00315 kmx.expandMacros( str );
00316 return str;
00317 }
00318
00319 template <typename KT, typename VT>
00320 inline QString
00321 TexpandMacrosShellQuote( const QString &ostr, const QHash<KT,VT> &map, QChar c )
00322 {
00323 QString str( ostr );
00324 KMacroMapExpander<KT,VT> kmx( map, c );
00325 if (!kmx.expandMacrosShellQuote( str ))
00326 return QString();
00327 return str;
00328 }
00329
00330
00331 namespace KMacroExpander {
00332
00333 QString expandMacros( const QString &ostr, const QHash<QChar,QString> &map, QChar c )
00334 { return TexpandMacros( ostr, map, c ); }
00335 QString expandMacrosShellQuote( const QString &ostr, const QHash<QChar,QString> &map, QChar c )
00336 { return TexpandMacrosShellQuote( ostr, map, c ); }
00337 QString expandMacros( const QString &ostr, const QHash<QString,QString> &map, QChar c )
00338 { return TexpandMacros( ostr, map, c ); }
00339 QString expandMacrosShellQuote( const QString &ostr, const QHash<QString,QString> &map, QChar c )
00340 { return TexpandMacrosShellQuote( ostr, map, c ); }
00341 QString expandMacros( const QString &ostr, const QHash<QChar,QStringList> &map, QChar c )
00342 { return TexpandMacros( ostr, map, c ); }
00343 QString expandMacrosShellQuote( const QString &ostr, const QHash<QChar,QStringList> &map, QChar c )
00344 { return TexpandMacrosShellQuote( ostr, map, c ); }
00345 QString expandMacros( const QString &ostr, const QHash<QString,QStringList> &map, QChar c )
00346 { return TexpandMacros( ostr, map, c ); }
00347 QString expandMacrosShellQuote( const QString &ostr, const QHash<QString,QStringList> &map, QChar c )
00348 { return TexpandMacrosShellQuote( ostr, map, c ); }
00349
00350 }