Teuchos Package Browser (Single Doxygen Collection) Version of the Day
Teuchos_StrUtils.cpp
Go to the documentation of this file.
00001 // @HEADER
00002 // ***********************************************************************
00003 //
00004 //                    Teuchos: Common Tools Package
00005 //                 Copyright (2004) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00025 //
00026 // ***********************************************************************
00027 // @HEADER
00028 
00029 #include "Teuchos_StrUtils.hpp"
00030 #include "Teuchos_TestForException.hpp"
00031 
00032 
00033 using namespace Teuchos;
00034 
00035 
00036 Array<std::string> StrUtils::readFile(std::istream& is, char comment)
00037 {
00038   std::string line;
00039   Array<std::string> rtn(0);
00040 
00041   while (readLine(is, line))
00042     {
00043       if (line.length() > 0) rtn.append(before(line, comment));
00044       line="";
00045     }
00046   
00047   return rtn;
00048 }
00049 
00050 Array<std::string> StrUtils::splitIntoLines(const std::string& input)
00051 {
00052   int begin = 0;
00053   Array<std::string> rtn;
00054   const unsigned int len = input.length();
00055   for (unsigned int p=0; p<len; ++p) {
00056     const bool isEnd = p==len-1;
00057     if( input[p]=='\n' || input[p]=='\0' || input[p]=='\r' || isEnd )
00058     {
00059       if (p-begin > 1)
00060         rtn.append(
00061           subString( input, begin, p+(isEnd?(input[len-1]=='\n'?0:1):0) )
00062           );
00063       begin = p+1;
00064     }
00065   }
00066   return rtn;
00067 }
00068 
00069 Array<Array<std::string> > StrUtils::tokenizeFile(std::istream& is, char comment)
00070 {
00071   std::string line;
00072   Array<Array<std::string> > rtn(0);
00073   Array<std::string> lines = readFile(is, comment);
00074   rtn.reserve(lines.length());
00075   
00076   int count = 0;
00077   for (int i=0; i<lines.length(); i++)
00078     {
00079       if (lines[i].length() == 0) continue;
00080       Array<std::string> tokens = stringTokenizer(lines[i]);
00081       if (tokens.length() == 0) continue;
00082       rtn.append(tokens);
00083       count++;
00084     }
00085   
00086   return rtn;
00087 }
00088 
00089 bool StrUtils::readLine(std::istream& is, std::string& line)
00090 {
00091   char c[500];
00092   if (line.length() > 0) line[0] = '\0';
00093   
00094   if (is.eof()) return false;
00095   if (is.getline(c, 499))
00096     {
00097       line = std::string(c);
00098     }
00099   
00100   return true;
00101 }
00102 
00103   
00104 
00105 Array<std::string> StrUtils::getTokensPlusWhitespace(const std::string& str){
00106   Array<std::string> rtn(0);
00107   unsigned int start = 0;
00108   
00109   while(start < str.length())
00110     {
00111       unsigned int wordStart =  findNextNonWhitespace(str, start);
00112       /* add any preceding whitespace */
00113       if (wordStart > start)
00114         {
00115           rtn.append(subString(str, start, wordStart));
00116         }
00117       start = wordStart;
00118       /* add the next word */
00119       int stop = findNextWhitespace(str, start);
00120       if (start-stop == 0) return rtn;
00121       std::string sub = subString(str, start, stop);
00122       rtn.append(sub);
00123       start = stop;// findNextNonWhitespace(str, stop);
00124     }
00125   return rtn;
00126 }
00127 
00128 Array<std::string> StrUtils::stringTokenizer(const std::string& str){
00129   Array<std::string> rtn(0);
00130   unsigned int start = 0;
00131   
00132   while(start < str.length())
00133     {
00134       start =  findNextNonWhitespace(str, start);
00135       int stop = findNextWhitespace(str, start);
00136       if (start-stop == 0) return rtn;
00137       std::string sub = subString(str, start, stop);
00138       rtn.append(sub);
00139       start =  findNextNonWhitespace(str, stop);
00140     }
00141   return rtn;
00142 }
00143 
00144 std::string StrUtils::reassembleFromTokens(const Array<std::string>& tokens, int iStart)
00145 {
00146   std::string rtn;
00147 
00148   for (int i=iStart; i<tokens.length(); i++) 
00149     {
00150       rtn += tokens[i];
00151       if (i < (tokens.length()-1)) rtn += " ";
00152     }
00153   return rtn;
00154 }
00155 
00156 void StrUtils::splitList(const std::string& big, Array<std::string>& list) 
00157 {
00158   if (subString(big, 0,1)!="[") 
00159     {
00160       list.resize(1);
00161       list[0] = big;
00162       return;
00163     }
00164   
00165   int parenDepth = 0;
00166   int localCount = 0;
00167   std::string tmp(big);
00168   list.resize(0);
00169 
00170   // start at 1 to ignore '[';
00171   
00172   for (unsigned int i=1; i<big.length(); i++)
00173     {
00174       if (big[i]=='(') parenDepth++;
00175       if (big[i]==')') parenDepth--;
00176       if (big[i]==']') 
00177   {
00178     tmp[localCount]='\0'; 
00179     list.append(tmp);
00180     break;
00181   }
00182       if (big[i]==',' && parenDepth==0)
00183   {
00184     tmp[localCount]='\0';
00185     list.append(tmp);
00186     tmp = big;
00187     localCount = 0;
00188     continue;
00189   }
00190       tmp[localCount] = big[i];
00191       localCount++;
00192     }
00193 }
00194               
00195 
00196 // return the position of the next whitespace in a std::string. 
00197 // If no whitespace, return -1;
00198 
00199 int StrUtils::findNextWhitespace(const std::string& str, int offset)
00200 {
00201   for (unsigned int i=0; i<(str.length()-offset); i++)
00202     {
00203       if (str[i+offset]==' ' || str[i+offset]=='\t' || str[i+offset]=='\n')
00204   {
00205     return i+offset;
00206   }
00207     }
00208   return str.length();
00209 }
00210 
00211 int StrUtils::findNextNonWhitespace(const std::string& str, int offset)
00212 {
00213   for (unsigned int i=0; i<(str.length()-offset); i++)
00214     {
00215       if (!(str[i+offset]==' ' || str[i+offset]=='\t' || str[i+offset]=='\n'))
00216   {
00217     return i+offset;
00218   }
00219     }
00220   return str.length();
00221 }
00222 
00223 
00224 std::string StrUtils::varTableSubstitute(const std::string& rawLine,
00225             const Array<std::string>& varNames,
00226             const Array<std::string>& varValues)
00227 {
00228   TEST_FOR_EXCEPTION(varNames.length() != varValues.length(),
00229                      std::runtime_error,
00230                      "mismatched variable tables in varTableSubstitute");
00231                      
00232   std::string line = rawLine;
00233   for (int i=0; i<varNames.length(); i++)
00234     {
00235       line = varSubstitute(line, varNames[i], varValues[i]);
00236     }
00237   return line;
00238 }
00239 
00240 
00241 
00242 
00243 std::string StrUtils::varSubstitute(const std::string& rawLine, 
00244              const std::string& varName, 
00245              const std::string& varValue)
00246 {
00247   std::string line = rawLine;
00248   
00249   // iterate because there might be more than one occurance on this line
00250   while (find(line, varName) >= 0)
00251     {
00252       std::string b = before(line, varName);
00253       std::string a = after(line, varName);
00254       line = b + varValue + a;
00255     }
00256   return line;
00257 }
00258 
00259 
00260 std::string StrUtils::before(const std::string& str, char sub)
00261 {
00262   char c[2];
00263   c[0] = sub;
00264   c[1] = 0;
00265   return before(str, c);
00266 }
00267 
00268 std::string StrUtils::before(const std::string& str, const std::string& sub)
00269 {
00270   TEST_FOR_EXCEPTION(sub.c_str()==0,
00271                      std::runtime_error, "String::before: arg is null pointer");
00272 
00273   char* p = std::strstr((char*) str.c_str(), (char*) sub.c_str());
00274   if (p==0) return str;
00275   int subLen = p-str.c_str();
00276   std::string rtn(str.c_str(), subLen);
00277   return rtn;
00278 }
00279 
00280 std::string StrUtils::after(const std::string& str, const std::string& sub)
00281 {
00282   TEST_FOR_EXCEPTION(sub.c_str()==0,
00283                      std::runtime_error, "String::after: arg is null pointer");
00284 
00285   // find beginning of substring
00286   char* p = std::strstr((char*) str.c_str(), (char*) sub.c_str()) ;
00287   // if substring not found, return empty std::string
00288   if (p==0) return std::string();
00289   // offset to end of substring
00290   p+= std::strlen(sub.c_str());
00291   return std::string(p);
00292 }
00293 
00294 int StrUtils::find(const std::string& str, const std::string& sub)
00295 {
00296   char* p = std::strstr((char*) str.c_str(), (char*) sub.c_str());
00297   if (p==0) return -1;
00298   return p-str.c_str();
00299 }
00300 
00301 bool StrUtils::isWhite(const std::string& str)
00302 {
00303   for (unsigned int i=0; i<str.length(); i++)
00304     {
00305       unsigned char c = str[i];
00306       if (c >= 33 && c <= 126)
00307         {
00308           return false;
00309         }
00310     }
00311   return true;
00312 }
00313 
00314 std::string StrUtils::fixUnprintableCharacters(const std::string& str)
00315 {
00316   std::string rtn = str;
00317   for (unsigned int i=0; i<rtn.length(); i++)
00318     {
00319       unsigned char c = rtn[i];
00320       if (c < 33 || c > 126) 
00321         {
00322           if (c != '\t' && c != '\n'&& c != '\r' && c != '\f' && c != ' ')
00323             {
00324               rtn[i] = ' ';
00325             }
00326         }
00327     }
00328   return rtn;
00329 }
00330 
00331 std::string StrUtils::between(const std::string& str, const std::string& begin,
00332        const std::string& end, std::string& front,
00333        std::string& back)
00334 {
00335   front = before(str, begin);
00336   std::string middle = before(after(str, begin), end);
00337   back = after(str, end);
00338   return middle;
00339 }
00340 
00341 
00342 std::string StrUtils::subString(const std::string& str, int begin, int end)
00343 {
00344 return std::string(str.c_str()+begin, end-begin);
00345 }
00346 
00347 std::string StrUtils::readFromStream(std::istream& is)
00348 {
00349   TEST_FOR_EXCEPTION(true, std::logic_error, 
00350                      "StrUtils::readFromStream isn't implemented yet");
00351 
00352   return "";
00353 }
00354 
00355 std::string StrUtils::allCaps(const std::string& s)
00356 {
00357   std::string rtn = s;
00358   for (unsigned int i=0; i<rtn.length(); i++)
00359     {
00360       rtn[i] = toupper(rtn[i]);
00361     }
00362   return rtn;
00363 }
00364 
00365 double StrUtils::atof(const std::string& s)
00366 {
00367   return std::atof(s.c_str());
00368 }
00369 
00370 int StrUtils::atoi(const std::string& s)
00371 {
00372   return std::atoi(s.c_str());
00373 }
00374 
00375 std::ostream& StrUtils::printLines(
00376   std::ostream             &os
00377   ,const std::string       &linePrefix
00378   ,const std::string       &lines
00379   )
00380 {
00381   typedef Teuchos::Array<std::string> array_t;
00382   array_t linesArray = splitIntoLines(lines);
00383   for( int i = 0; i < static_cast<int>(linesArray.size()); ++i )
00384   {
00385     os << linePrefix << linesArray[i] << "\n";
00386   }
00387   return os;
00388 }
00389   
00390 
00391   
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines