KDECore
kmacroexpander.cpp
Go to the documentation of this file.
00001 /* 00002 This file is part of the KDE libraries 00003 00004 Copyright (c) 2002-2003 Oswald Buddenhagen <ossi@kde.org> 00005 Copyright (c) 2003 Waldo Bastian <bastian@kde.org> 00006 00007 This library is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU Library General Public 00009 License as published by the Free Software Foundation; either 00010 version 2 of the License, or (at your option) any later version. 00011 00012 This library is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 Library General Public License for more details. 00016 00017 You should have received a copy of the GNU Library General Public License 00018 along with this library; see the file COPYING.LIB. If not, write to 00019 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00020 Boston, MA 02110-1301, USA. 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 ushort ec = d->escapechar.unicode(); 00055 QStringList rst; 00056 QString rsts; 00057 00058 for (pos = 0; pos < str.length(); ) { 00059 if (ec != 0) { 00060 if (str.unicode()[pos].unicode() != 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( ushort c ) 00118 { 00119 return c == '_' || 00120 (c >= 'A' && c <= 'Z') || 00121 (c >= 'a' && c <= 'z') || 00122 (c >= '0' && c <= '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.unicode()[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.length() <= pos + 1) 00159 return 0; 00160 00161 if (str.unicode()[pos + 1] == escapeChar()) { 00162 ret += QString( escapeChar() ); 00163 return 2; 00164 } 00165 typename QHash<QChar,VT>::const_iterator it = macromap.constFind(str.unicode()[pos + 1]); 00166 if (it != macromap.constEnd()) { 00167 ret += it.value(); 00168 return 2; 00169 } 00170 00171 return 0; 00172 } 00173 00174 template <typename VT> 00175 class KMacroMapExpander<QString,VT> : public KMacroExpanderBase { 00176 00177 public: 00178 KMacroMapExpander( const QHash<QString,VT> &map, QChar c = QLatin1Char('%') ) : 00179 KMacroExpanderBase( c ), macromap( map ) {} 00180 00181 protected: 00182 virtual int expandPlainMacro( const QString &str, int pos, QStringList &ret ); 00183 virtual int expandEscapedMacro( const QString &str, int pos, QStringList &ret ); 00184 00185 private: 00186 QHash<QString,VT> macromap; 00187 }; 00188 00189 template <typename VT> 00190 int 00191 KMacroMapExpander<QString,VT>::expandPlainMacro( const QString &str, int pos, QStringList &ret ) 00192 { 00193 if (pos && isIdentifier( str.unicode()[pos - 1].unicode() )) 00194 return 0; 00195 int sl; 00196 for (sl = 0; isIdentifier( str.unicode()[pos + sl].unicode() ); sl++) 00197 ; 00198 if (!sl) 00199 return 0; 00200 typename QHash<QString,VT>::const_iterator it = 00201 macromap.constFind( str.mid( pos, sl ) ); 00202 if (it != macromap.constEnd()) { 00203 ret += it.value(); 00204 return sl; 00205 } 00206 return 0; 00207 } 00208 00209 template <typename VT> 00210 int 00211 KMacroMapExpander<QString,VT>::expandEscapedMacro( const QString &str, int pos, QStringList &ret ) 00212 { 00213 if (str.length() <= pos + 1) 00214 return 0; 00215 00216 if (str.unicode()[pos + 1] == escapeChar()) { 00217 ret += QString( escapeChar() ); 00218 return 2; 00219 } 00220 int sl, rsl, rpos; 00221 if (str.unicode()[pos + 1].unicode() == '{') { 00222 rpos = pos + 2; 00223 if ((sl = str.indexOf(QLatin1Char('}'), rpos)) < 0) 00224 return 0; 00225 sl -= rpos; 00226 rsl = sl + 3; 00227 } else { 00228 rpos = pos + 1; 00229 for (sl = 0; isIdentifier( str.unicode()[rpos + sl].unicode() ); sl++) 00230 ; 00231 rsl = sl + 1; 00232 } 00233 if (!sl) 00234 return 0; 00235 typename QHash<QString,VT>::const_iterator it = 00236 macromap.constFind( str.mid( rpos, sl ) ); 00237 if (it != macromap.constEnd()) { 00238 ret += it.value(); 00239 return rsl; 00240 } 00241 return 0; 00242 } 00243 00245 00246 int 00247 KCharMacroExpander::expandPlainMacro( const QString &str, int pos, QStringList &ret ) 00248 { 00249 if (expandMacro( str.unicode()[pos], ret )) 00250 return 1; 00251 return 0; 00252 } 00253 00254 int 00255 KCharMacroExpander::expandEscapedMacro( const QString &str, int pos, QStringList &ret ) 00256 { 00257 if (str.length() <= pos + 1) 00258 return 0; 00259 00260 if (str.unicode()[pos + 1] == escapeChar()) { 00261 ret += QString( escapeChar() ); 00262 return 2; 00263 } 00264 if (expandMacro( str.unicode()[pos + 1], ret )) 00265 return 2; 00266 return 0; 00267 } 00268 00269 int 00270 KWordMacroExpander::expandPlainMacro( const QString &str, int pos, QStringList &ret ) 00271 { 00272 if (pos && isIdentifier( str.unicode()[pos - 1].unicode() )) 00273 return 0; 00274 int sl; 00275 for (sl = 0; isIdentifier( str.unicode()[pos + sl].unicode() ); sl++) 00276 ; 00277 if (!sl) 00278 return 0; 00279 if (expandMacro( str.mid( pos, sl ), ret )) 00280 return sl; 00281 return 0; 00282 } 00283 00284 int 00285 KWordMacroExpander::expandEscapedMacro( const QString &str, int pos, QStringList &ret ) 00286 { 00287 if (str.length() <= pos + 1) 00288 return 0; 00289 00290 if (str.unicode()[pos + 1] == escapeChar()) { 00291 ret += QString( escapeChar() ); 00292 return 2; 00293 } 00294 int sl, rsl, rpos; 00295 if (str.unicode()[pos + 1].unicode() == '{') { 00296 rpos = pos + 2; 00297 if ((sl = str.indexOf(QLatin1Char('}'), rpos)) < 0) 00298 return 0; 00299 sl -= rpos; 00300 rsl = sl + 3; 00301 } else { 00302 rpos = pos + 1; 00303 for (sl = 0; isIdentifier( str.unicode()[rpos + sl].unicode() ); sl++) 00304 ; 00305 rsl = sl + 1; 00306 } 00307 if (!sl) 00308 return 0; 00309 if (expandMacro( str.mid( rpos, sl ), ret )) 00310 return rsl; 00311 return 0; 00312 } 00313 00315 00316 template <typename KT, typename VT> 00317 inline QString 00318 TexpandMacros( const QString &ostr, const QHash<KT,VT> &map, QChar c ) 00319 { 00320 QString str( ostr ); 00321 KMacroMapExpander<KT,VT> kmx( map, c ); 00322 kmx.expandMacros( str ); 00323 return str; 00324 } 00325 00326 template <typename KT, typename VT> 00327 inline QString 00328 TexpandMacrosShellQuote( const QString &ostr, const QHash<KT,VT> &map, QChar c ) 00329 { 00330 QString str( ostr ); 00331 KMacroMapExpander<KT,VT> kmx( map, c ); 00332 if (!kmx.expandMacrosShellQuote( str )) 00333 return QString(); 00334 return str; 00335 } 00336 00337 // public API 00338 namespace KMacroExpander { 00339 00340 QString expandMacros( const QString &ostr, const QHash<QChar,QString> &map, QChar c ) 00341 { return TexpandMacros( ostr, map, c ); } 00342 QString expandMacrosShellQuote( const QString &ostr, const QHash<QChar,QString> &map, QChar c ) 00343 { return TexpandMacrosShellQuote( ostr, map, c ); } 00344 QString expandMacros( const QString &ostr, const QHash<QString,QString> &map, QChar c ) 00345 { return TexpandMacros( ostr, map, c ); } 00346 QString expandMacrosShellQuote( const QString &ostr, const QHash<QString,QString> &map, QChar c ) 00347 { return TexpandMacrosShellQuote( ostr, map, c ); } 00348 QString expandMacros( const QString &ostr, const QHash<QChar,QStringList> &map, QChar c ) 00349 { return TexpandMacros( ostr, map, c ); } 00350 QString expandMacrosShellQuote( const QString &ostr, const QHash<QChar,QStringList> &map, QChar c ) 00351 { return TexpandMacrosShellQuote( ostr, map, c ); } 00352 QString expandMacros( const QString &ostr, const QHash<QString,QStringList> &map, QChar c ) 00353 { return TexpandMacros( ostr, map, c ); } 00354 QString expandMacrosShellQuote( const QString &ostr, const QHash<QString,QStringList> &map, QChar c ) 00355 { return TexpandMacrosShellQuote( ostr, map, c ); } 00356 00357 } // namespace
KDE 4.6 API Reference