Main Page   Namespace List   Compound List   File List   Compound Members   File Members  

replace.cc

Go to the documentation of this file.
00001 /*
00002  *
00003  *  This file  is part of the PCRE++ Class Library.
00004  *
00005  *  By  accessing  this software,  PCRE++, you  are  duly informed
00006  *  of and agree to be  bound  by the  conditions  described below
00007  *  in this notice:
00008  *
00009  *  This software product,  PCRE++,  is developed by Thomas Linden
00010  *  and copyrighted (C) 2002-2003 by Thomas Linden,with all rights 
00011  *  reserved.
00012  *
00013  *  There  is no charge for PCRE++ software.  You can redistribute
00014  *  it and/or modify it under the terms of the GNU  Lesser General
00015  *  Public License, which is incorporated by reference herein.
00016  *
00017  *  PCRE++ is distributed WITHOUT ANY WARRANTY, IMPLIED OR EXPRESS,
00018  *  OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE or that
00019  *  the use of it will not infringe on any third party's intellec-
00020  *  tual property rights.
00021  *
00022  *  You should have received a copy of the GNU Lesser General Public
00023  *  License along with PCRE++.  Copies can also be obtained from:
00024  *
00025  *    http://www.gnu.org/licenses/lgpl.txt
00026  *
00027  *  or by writing to:
00028  *
00029  *  Free Software Foundation, Inc.
00030  *  59 Temple Place, Suite 330
00031  *  Boston, MA 02111-1307
00032  *  USA
00033  *
00034  *  Or contact:
00035  *
00036  *   "Thomas Linden" <tom@daemon.de>
00037  *
00038  *
00039  */
00040 
00041 
00042 #include "pcre++.h"
00043 
00044 using namespace std;
00045 using namespace pcrepp;
00046 
00047 /*
00048  * replace method
00049  */
00050 
00051 string Pcre::replace(const string& piece, const string& with) {
00052   /*
00053    * Pcre::replace version by "Marcus Kramer" <marcus.kramer@scherrer.de>
00054    */
00055   string Replaced(piece);
00056 
00057   bool bReplaced = false;
00058   int  iReplaced = -1;
00059 
00060   __pcredebug << "replace: " << piece << " with: " << with << endl;
00061 
00062   /*
00063    * certainly we need an anchor, we want to check if the whole arg is in brackets
00064    * //Pcre braces("^[^\\\\]\\(.*[^\\\\]\\)$"); // perlish: [^\\]\(.*[^\\]\)
00065    *
00066    * There's no reason, not to add brackets in general.
00067    * It's more comfortable, cause we wants to start with $1 at all, 
00068    * also if we set the whole arg in brackets!
00069    */
00070   
00071   /* recreate the p_pcre* objects to avoid memory leaks */
00072   pcre_free(p_pcre);
00073   pcre_free(p_pcre_extra);
00074   
00075   pcre       *_p = NULL;
00076   pcre_extra *_e = NULL;;
00077         
00078   p_pcre = _p;
00079   p_pcre_extra = _e;
00080   
00081   if (! _have_paren ) {
00082     string::size_type p_open, p_close;
00083     p_open  = _expression.find_first_of("(");
00084     p_close = _expression.find_first_of(")");
00085     if ( p_open == string::npos && p_close == string::npos ) {
00086       /*
00087        * Well, _expression completely lacks of parens, which are
00088        * required for search/replace operation. So add parens automatically.
00089        * Note, that we add 2 pairs of parens so that we finally have $0 matchin
00090        * the whole expression and $1 matching the inner side (which is in this
00091        * case the very same string.
00092        * We do this for perl compatibility. If the expression already contains
00093        * parens, the whole match will produce $0 for us, so in this case we
00094        * have no problem
00095        */
00096       _expression = "((" + _expression + "))";
00097     }
00098     else {
00099       /*
00100        * Add parens to the very beginning and end of the expression
00101        * so that we have $0. I don't care if the user already supplied
00102        * double-parentesed experssion (e.g. "((1))"), because PCRE seems
00103        * to eat redundant parenteses, e.g. "((((1))))" returns the same
00104        * result as "((1))".
00105        */
00106       _expression = "(" + _expression;
00107       _expression=_expression + ")"; 
00108     }
00109 
00110     _have_paren = true;
00111   }
00112 
00113   __pcredebug << "_expression: " << _expression << endl;
00114 
00115   Compile(_flags);
00116         
00117   if(search(piece)) {
00118     /* we found at least one match */
00119     
00120     // sure we must resolve $1 for ever piece we found especially for "g"
00121     // so let's just create that var, we resolve it when we needed!
00122     string use_with;
00123 
00124 
00125     if(!global_t) {
00126       // here we can resolve vars if option g is not set
00127       use_with = _replace_vars(with);
00128 
00129       if(matched() && matches() >= 1) {
00130         __pcredebug << "matches: " << matches() << endl;
00131         int len = get_match_end() - get_match_start() + 1;
00132         Replaced.replace(get_match_start(0), len, use_with);
00133         bReplaced  = true;
00134         iReplaced = 0;
00135       }
00136     }
00137     else {
00138       /* global replace */
00139 
00140       // in global replace we just need to remember our position
00141       // so let's initialize it first
00142       int match_pos = 0;
00143       while( search( Replaced, match_pos ) ) {
00144         int len = 0;
00145                                 
00146         // here we need to resolve the vars certainly for every hit.
00147         // could be different content sometimes!
00148         use_with = _replace_vars(with);
00149                                 
00150         len = get_match_end() - get_match_start() + 1;
00151         Replaced.replace(get_match_start(0), len, use_with);
00152                                 
00153         //# Next run should begin after the last char of the stuff we put in the text
00154         match_pos = ( use_with.length() - len ) + get_match_end() + 1;
00155 
00156         bReplaced  = true;
00157         ++iReplaced;
00158       }
00159     }
00160   }
00161   
00162   did_match   = bReplaced;
00163   num_matches = iReplaced;
00164 
00165   return Replaced;
00166 }
00167 
00168 
00169 
00170 
00171 
00172 string Pcre::_replace_vars(const string& piece) {
00173   /*
00174    * Pcre::_replace_vars version by "Marcus Kramer" <marcus.kramer@scherrer.de>
00175    */
00176   string with  = piece;
00177   Pcre dollar("\\$([0-9]+)");
00178 
00179   while ( dollar.search( with ) ) {
00180     // let's do some conversion first
00181     __pcredebug << "Pcre::dollar matched: " << piece << ". Match(0): " << dollar.get_match(0) << endl;
00182     int iBracketIndex = atoi( dollar.get_match(0).data() );
00183     string sBracketContent = get_match(iBracketIndex);
00184     
00185     // now we can splitt the stuff
00186     string sSubSplit = "\\$" + dollar.get_match(0);
00187     Pcre subsplit(sSubSplit);
00188                 
00189     // normally 2 (or more) parts, the one in front of and the other one after "$1"
00190     vector<string> splitted = subsplit.split(with); 
00191     string Replaced;
00192                 
00193     for(size_t pos=0; pos < splitted.size(); pos++) {
00194       if( pos == ( splitted.size() - 1 ) ) 
00195         Replaced += splitted[pos];
00196       else 
00197         Replaced += splitted[pos] + sBracketContent;
00198     }
00199     with = Replaced; // well, one part is done
00200   }
00201   return with;
00202 }

Generated on Wed Aug 25 01:38:04 2004 for PCRE++ by doxygen1.3-rc3