Teuchos - Trilinos Tools Package  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Teuchos_StrUtils.cpp
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 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00038 //
00039 // ***********************************************************************
00040 // @HEADER
00041 
00042 #include "Teuchos_StrUtils.hpp"
00043 #include "Teuchos_Assert.hpp"
00044 
00045 
00046 namespace Teuchos {
00047 
00048 
00049 Array<std::string> StrUtils::readFile(std::istream& is, char comment)
00050 {
00051   std::string line;
00052   Array<std::string> rtn(0);
00053 
00054   while (readLine(is, line))
00055   {
00056     if (line.length() > 0) rtn.append(before(line, comment));
00057     line="";
00058   }
00059 
00060   return rtn;
00061 }
00062 
00063 
00064 Array<std::string> StrUtils::splitIntoLines(const std::string& input)
00065 {
00066   int begin = 0;
00067   Array<std::string> rtn;
00068   const unsigned int len = input.length();
00069   for (unsigned int p=0; p<len; ++p) {
00070     const bool isEnd = p==len-1;
00071     if( input[p]=='\n' || input[p]=='\0' || input[p]=='\r' || isEnd )
00072     {
00073       if (p-begin > 1)
00074         rtn.append(
00075           subString( input, begin, p+(isEnd?(input[len-1]=='\n'?0:1):0) )
00076           );
00077       begin = p+1;
00078     }
00079   }
00080   return rtn;
00081 }
00082 
00083 
00084 Array<Array<std::string> > StrUtils::tokenizeFile(std::istream& is, char comment)
00085 {
00086   std::string line;
00087   Array<Array<std::string> > rtn(0);
00088   Array<std::string> lines = readFile(is, comment);
00089   rtn.reserve(lines.length());
00090 
00091   int count = 0;
00092   for (int i=0; i<lines.length(); i++)
00093   {
00094     if (lines[i].length() == 0) continue;
00095     Array<std::string> tokens = stringTokenizer(lines[i]);
00096     if (tokens.length() == 0) continue;
00097     rtn.append(tokens);
00098     count++;
00099   }
00100 
00101   return rtn;
00102 }
00103 
00104 
00105 bool StrUtils::readLine(std::istream& is, std::string& line)
00106 {
00107   char c[500];
00108   if (line.length() > 0) line[0] = '\0';
00109 
00110   if (is.eof()) return false;
00111   if (is.getline(c, 499))
00112   {
00113     line = std::string(c);
00114   }
00115 
00116   return true;
00117 }
00118 
00119 
00120 Array<std::string> StrUtils::getTokensPlusWhitespace(const std::string& str){
00121   Array<std::string> rtn(0);
00122   unsigned int start = 0;
00123 
00124   while(start < str.length())
00125   {
00126     unsigned int wordStart =  findNextNonWhitespace(str, start);
00127     /* add any preceding whitespace */
00128     if (wordStart > start)
00129     {
00130       rtn.append(subString(str, start, wordStart));
00131     }
00132     start = wordStart;
00133     /* add the next word */
00134     int stop = findNextWhitespace(str, start);
00135     if (start-stop == 0) return rtn;
00136     std::string sub = subString(str, start, stop);
00137     rtn.append(sub);
00138     start = stop;// findNextNonWhitespace(str, stop);
00139   }
00140   return rtn;
00141 }
00142 
00143 
00144 Array<std::string> StrUtils::stringTokenizer(const std::string& str){
00145   Array<std::string> rtn(0);
00146   unsigned int start = 0;
00147 
00148   while(start < str.length())
00149   {
00150     start =  findNextNonWhitespace(str, start);
00151     int stop = findNextWhitespace(str, start);
00152     if (start-stop == 0) return rtn;
00153     std::string sub = subString(str, start, stop);
00154     rtn.append(sub);
00155     start =  findNextNonWhitespace(str, stop);
00156   }
00157   return rtn;
00158 }
00159 
00160 
00161 std::string StrUtils::reassembleFromTokens(const Array<std::string>& tokens,
00162   int iStart)
00163 {
00164   std::string rtn;
00165 
00166   for (int i=iStart; i<tokens.length(); i++)
00167   {
00168     rtn += tokens[i];
00169     if (i < (tokens.length()-1)) rtn += " ";
00170   }
00171   return rtn;
00172 }
00173 
00174 
00175 void StrUtils::splitList(const std::string& big, Array<std::string>& list)
00176 {
00177   if (subString(big, 0,1)!="[")
00178   {
00179     list.resize(1);
00180     list[0] = big;
00181     return;
00182   }
00183 
00184   int parenDepth = 0;
00185   int localCount = 0;
00186   std::string tmp(big);
00187   list.resize(0);
00188 
00189   // start at 1 to ignore '[';
00190 
00191   for (unsigned int i=1; i<big.length(); i++)
00192   {
00193     if (big[i]=='(') parenDepth++;
00194     if (big[i]==')') parenDepth--;
00195     if (big[i]==']')
00196     {
00197       tmp[localCount]='\0';
00198       list.append(tmp);
00199       break;
00200     }
00201     if (big[i]==',' && parenDepth==0)
00202     {
00203       tmp[localCount]='\0';
00204       list.append(tmp);
00205       tmp = big;
00206       localCount = 0;
00207       continue;
00208     }
00209     tmp[localCount] = big[i];
00210     localCount++;
00211   }
00212 }
00213 
00214 
00215 // return the position of the next whitespace in a std::string.
00216 // If no whitespace, return -1;
00217 
00218 int StrUtils::findNextWhitespace(const std::string& str, int offset)
00219 {
00220   for (unsigned int i=0; i<(str.length()-offset); i++)
00221   {
00222     if (str[i+offset]==' ' || str[i+offset]=='\t' || str[i+offset]=='\n')
00223     {
00224       return i+offset;
00225     }
00226   }
00227   return str.length();
00228 }
00229 
00230 
00231 int StrUtils::findNextNonWhitespace(const std::string& str, int offset)
00232 {
00233   for (unsigned int i=0; i<(str.length()-offset); i++)
00234   {
00235     if (!(str[i+offset]==' ' || str[i+offset]=='\t' || str[i+offset]=='\n'))
00236     {
00237       return i+offset;
00238     }
00239   }
00240   return str.length();
00241 }
00242 
00243 
00244 std::string StrUtils::varTableSubstitute(const std::string& rawLine,
00245   const Array<std::string>& varNames,
00246   const Array<std::string>& varValues)
00247 {
00248   TEUCHOS_TEST_FOR_EXCEPTION(varNames.length() != varValues.length(),
00249     std::runtime_error,
00250     "mismatched variable tables in varTableSubstitute");
00251 
00252   std::string line = rawLine;
00253   for (int i=0; i<varNames.length(); i++)
00254   {
00255     line = varSubstitute(line, varNames[i], varValues[i]);
00256   }
00257   return line;
00258 }
00259 
00260 
00261 std::string StrUtils::varSubstitute(const std::string& rawLine,
00262   const std::string& varName,
00263   const std::string& varValue)
00264 {
00265   std::string line = rawLine;
00266 
00267   // iterate because there might be more than one occurance on this line
00268   while (find(line, varName) >= 0)
00269   {
00270     std::string b = before(line, varName);
00271     std::string a = after(line, varName);
00272     line = b + varValue + a;
00273   }
00274   return line;
00275 }
00276 
00277 
00278 std::string StrUtils::before(const std::string& str, char sub)
00279 {
00280   char c[2];
00281   c[0] = sub;
00282   c[1] = 0;
00283   return before(str, c);
00284 }
00285 
00286 
00287 std::string StrUtils::before(const std::string& str, const std::string& sub)
00288 {
00289   TEUCHOS_TEST_FOR_EXCEPTION(sub.c_str()==0,
00290     std::runtime_error, "String::before: arg is null pointer");
00291 
00292   char* p = std::strstr((char*) str.c_str(), (char*) sub.c_str());
00293   if (p==0) return str;
00294   int subLen = p-str.c_str();
00295   std::string rtn(str.c_str(), subLen);
00296   return rtn;
00297 }
00298 
00299 
00300 std::string StrUtils::after(const std::string& str, const std::string& sub)
00301 {
00302   TEUCHOS_TEST_FOR_EXCEPTION(sub.c_str()==0,
00303     std::runtime_error, "String::after: arg is null pointer");
00304 
00305   // find beginning of substring
00306   char* p = std::strstr((char*) str.c_str(), (char*) sub.c_str()) ;
00307   // if substring not found, return empty std::string
00308   if (p==0) return std::string();
00309   // offset to end of substring
00310   p+= std::strlen(sub.c_str());
00311   return std::string(p);
00312 }
00313 
00314 
00315 int StrUtils::find(const std::string& str, const std::string& sub)
00316 {
00317   char* p = std::strstr((char*) str.c_str(), (char*) sub.c_str());
00318   if (p==0) return -1;
00319   return p-str.c_str();
00320 }
00321 
00322 
00323 bool StrUtils::isWhite(const std::string& str)
00324 {
00325   for (unsigned int i=0; i<str.length(); i++)
00326   {
00327     unsigned char c = str[i];
00328     if (c >= 33 && c <= 126)
00329     {
00330       return false;
00331     }
00332   }
00333   return true;
00334 }
00335 
00336 
00337 std::string StrUtils::fixUnprintableCharacters(const std::string& str)
00338 {
00339   std::string rtn = str;
00340   for (unsigned int i=0; i<rtn.length(); i++)
00341   {
00342     unsigned char c = rtn[i];
00343     if (c < 33 || c > 126)
00344     {
00345       if (c != '\t' && c != '\n'&& c != '\r' && c != '\f' && c != ' ')
00346       {
00347         rtn[i] = ' ';
00348       }
00349     }
00350   }
00351   return rtn;
00352 }
00353 
00354 
00355 std::string StrUtils::between(const std::string& str, const std::string& begin,
00356   const std::string& end, std::string& front,
00357   std::string& back)
00358 {
00359   front = before(str, begin);
00360   std::string middle = before(after(str, begin), end);
00361   back = after(str, end);
00362   return middle;
00363 }
00364 
00365 
00366 std::string StrUtils::subString(const std::string& str, int begin, int end)
00367 {
00368   return std::string(str.c_str()+begin, end-begin);
00369 }
00370 
00371 
00372 std::string StrUtils::readFromStream(std::istream& is)
00373 {
00374   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
00375     "StrUtils::readFromStream isn't implemented yet");
00376 
00377   // NOTE (mfh 15 Sep 2014): Most compilers have figured out that the
00378   // return statement below is unreachable.  Some older compilers
00379   // might not realize this.  That's why the return statement was put
00380   // there, so that those compilers don't warn that this function
00381   // doesn't return a value.  If it's a choice between one warning and
00382   // another, I would prefer the choice that produces less code and
00383   // doesn't have unreachable code (which never gets tested).
00384 
00385   //return "";
00386 }
00387 
00388 
00389 std::string StrUtils::allCaps(const std::string& s)
00390 {
00391   std::string rtn = s;
00392   for (unsigned int i=0; i<rtn.length(); i++)
00393   {
00394     rtn[i] = toupper(rtn[i]);
00395   }
00396   return rtn;
00397 }
00398 
00399 
00400 double StrUtils::atof(const std::string& s)
00401 {
00402         return std::atof(s.c_str());
00403 }
00404 
00405 
00406 int StrUtils::atoi(const std::string& s)
00407 {
00408         return std::atoi(s.c_str());
00409 }
00410 
00411 
00412 std::ostream& StrUtils::printLines(
00413   std::ostream             &os
00414   ,const std::string       &linePrefix
00415   ,const std::string       &lines
00416   )
00417 {
00418   typedef Teuchos::Array<std::string> array_t;
00419   array_t linesArray = splitIntoLines(lines);
00420   for( int i = 0; i < static_cast<int>(linesArray.size()); ++i )
00421   {
00422     os << linePrefix << linesArray[i] << "\n";
00423   }
00424   return os;
00425 }
00426 
00427 
00428 std::string StrUtils::removeAllSpaces(std::string stringToClean)
00429 {
00430   std::string::size_type pos=0;
00431   bool spacesLeft = true;
00432 
00433   while(spacesLeft){
00434     pos = stringToClean.find(" ");
00435     if(pos != string::npos){
00436       stringToClean.erase(pos,1);
00437     }
00438     else{
00439       spacesLeft = false;
00440     }
00441   }
00442   return stringToClean;
00443 }
00444 
00445 
00446 } // namespace Teuchos
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines