PLearn 0.1
stringutils.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // PLearn (A C++ Machine Learning Library)
00004 // Copyright (C) 1998 Pascal Vincent
00005 // Copyright (C) 1999-2002 Pascal Vincent, Yoshua Bengio and University of Montreal
00006 //
00007 
00008 // Redistribution and use in source and binary forms, with or without
00009 // modification, are permitted provided that the following conditions are met:
00010 // 
00011 //  1. Redistributions of source code must retain the above copyright
00012 //     notice, this list of conditions and the following disclaimer.
00013 // 
00014 //  2. Redistributions in binary form must reproduce the above copyright
00015 //     notice, this list of conditions and the following disclaimer in the
00016 //     documentation and/or other materials provided with the distribution.
00017 // 
00018 //  3. The name of the authors may not be used to endorse or promote
00019 //     products derived from this software without specific prior written
00020 //     permission.
00021 // 
00022 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
00023 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00024 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
00025 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00026 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00027 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00028 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00029 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00030 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00031 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00032 // 
00033 // This file is part of the PLearn library. For more information on the PLearn
00034 // library, go to the PLearn Web site at www.plearn.org
00035 
00036 
00037  
00038 
00039 /* *******************************************************      
00040  * $Id: stringutils.cc 10044 2009-03-20 18:39:33Z nouiz $
00041  * AUTHORS: Pascal Vincent
00042  * This file is part of the PLearn library.
00043  ******************************************************* */
00044 
00045 #include "stringutils.h"
00046 #include "general.h"
00047 
00048 namespace PLearn {
00049 using namespace std;
00050 
00051 
00052 string left(const string& s, size_t width, char padding)
00053 { 
00054     if(s.length()>width)
00055         return s;
00056     else
00057         return s+string(width-s.length(),padding);
00058 }
00059 
00060 string right(const string& s, size_t width, char padding)
00061 {
00062     if(s.length()>width)
00063         return s;
00064     else
00065         return string(width-s.length(),padding)+s;
00066 }
00067 
00068 string center(const string& s, size_t width, char padding)
00069 {
00070     if(s.length()>width)
00071         return s;
00072     else
00073         return string((width-s.length())/2,padding) + s +
00074             string((width-s.length()+1)/2,padding);
00075 }
00076 
00077 
00078 string extract_filename(const string& filepath)
00079 {
00080     size_t p = filepath.rfind(slash);
00081     if (p != string::npos)
00082         return filepath.substr(p+1,filepath.length()-(p+1));
00083     else
00084         return filepath;
00085 }
00086 
00087 string extract_directory(const string& filepath)
00088 {
00089     size_t p = filepath.rfind(slash);
00090     if (p != string::npos)
00091         return filepath.substr(0,p+1);
00092     else
00093     {
00094         string dot = ".";
00095         return dot+slash;
00096     }
00097 }
00098   
00099 string extract_extension(const string& filepath)
00100 {
00101     string filename = extract_filename(filepath);
00102     size_t p = filename.rfind(".");
00103     if (p != string::npos)
00104         return filename.substr(p,filename.length()-p);
00105     else
00106         return "";
00107 }
00108 
00109 string extract_filename_without_extension(const string& filepath)
00110 {
00111     string filename = extract_filename(filepath);
00112     size_t p = filename.rfind(".");
00113     if (p != string::npos)
00114         return filename.substr(0,p);
00115     else
00116         return filename;
00117 }
00118 
00119 string remove_extension(const string& filename)
00120 {
00121     size_t p = filename.rfind(".");
00122     if (p != string::npos)
00123         return filename.substr(0,p);
00124     else
00125         return filename;
00126 }
00127 
00128 string* data_filename_2_filenames(const string& filename, int& nb_files)
00129 {
00130     ifstream in(filename.c_str());
00131     if (!in)
00132         PLERROR("In data_filename_2_filenames: couldn't open file %s",
00133                 filename.c_str());
00134  
00135     const int buffersize = 100;
00136     string* filenames = new string[buffersize];
00137     nb_files = 0;
00138     string fname;
00139     while (getline(in, fname, '\n'))
00140         filenames[nb_files++] = fname;
00141  
00142     return filenames;
00143 }
00144 
00145 string removeblanks(const string& s)
00146 {
00147     size_t start=0;
00148     size_t end=0;
00149     size_t i;
00150     string::size_type j;
00151     for(i=0; i<s.length(); i++)
00152         if(s[i]!=' ' && s[i]!='\t' && s[i]!='\n' && s[i]!='\r')
00153             break;
00154   
00155     if(i==s.length())
00156         return string("");
00157     else
00158         start = i;
00159 
00160     for(j=s.length(); j>=1; j--)
00161         if(s[j-1]!=' ' && s[j-1]!='\t' && s[j-1]!='\n' && s[j-1]!='\r')
00162             break;
00163     end = size_t(j - 1);
00164     return s.substr(start,end-start+1);
00165 }
00166 
00167 string removeallblanks(const string& s)
00168 {
00169     string res;
00170     size_t l = s.length();
00171     for(size_t i=0; i<l; i++)
00172     {
00173         char c = s[i];
00174         if(c!=' ' && c!='\t' && c!='\n' && c!='\r')
00175             res += c;
00176     }
00177     return res;
00178 }
00179 
00180 string removenewline(const string& s)
00181 {
00182     string::size_type pos = s.length();
00183     while(pos>=1 && (s[pos - 1]=='\r' || s[pos - 1]=='\n'))
00184         pos--;
00185     return s.substr(0,pos);
00186 }
00187 
00188 string removequotes(const string& s)
00189 {
00190     const int n = int(s.size());
00191     if (n >= 2) {
00192         if ((s[0] == '"'  && s[n-1] == '"') ||
00193             (s[0] == '\'' && s[n-1] == '\''))
00194             return s.substr(1,n-2);
00195     }
00196     return s;
00197 }
00198 
00199 string quote_string(const string& s)
00200 {
00201     string quoted(s);
00202         
00203     // Escape the existing quotes
00204     string::size_type pos = quoted.find("\"");
00205     while ( pos != quoted.npos )
00206     {
00207         quoted.insert(pos, "\\");
00208         pos = quoted.find("\"", pos+2); // +2 since the inserted char...
00209     }
00210 
00211     // Quote the string
00212     quoted.insert(0, "\"");
00213     quoted.insert(quoted.size(), "\"");
00214     return quoted;
00215 }
00216 
00217 string remove_trailing_slash(const string& s)
00218 {
00219     string::size_type pos = s.length();
00220     while(pos >= 1 && s[pos - 1]==slash_char)
00221         pos--;
00222     return s.substr(0,pos);
00223 }
00224 
00225 string append_slash(const string& path)
00226 {
00227     size_t l = path.length();
00228     if(l>0 && path[l-1]!=slash_char)
00229         return path+slash;
00230     else
00231         return path;
00232 }
00233 
00234 string lowerstring(const string& ss)
00235 {
00236     string s(ss);
00237     string::iterator it = s.begin(), end = s.end();
00238 
00239     // for some reason toupper and tolower from ctype.h seem to create
00240     // problems when compiling in optimized mode, so we do this
00241     for (; it != end; ++it)
00242     {
00243         if(*it>='A' && *it<='Z')
00244             *it += 'a'-'A';
00245     }
00246     return s;
00247 }
00248 
00249 string upperstring(const string& ss)
00250 {
00251     string s(ss);
00252     string::iterator it = s.begin(), end = s.end();
00253 
00254     // for some reason toupper and tolower from ctype.h seem to create
00255     // problems when compiling in optimized mode, so we do this
00256     for (; it != end; ++it)
00257     {
00258         if(*it>='a' && *it<='z')
00259             *it -= 'a'-'A';
00260     }
00261     return s;
00262 }
00263 
00264 string pgetline(istream& in)
00265 {
00266     string line;
00267     getline(in,line);
00268     return removenewline(line);
00269 }
00270 
00271 bool isBlank(const string& s)
00272 {
00273     string::size_type l = s.length();
00274     for(unsigned int i=0; i<l; i++)
00275     {
00276         char c = s[i];
00277         if(c=='#' || c=='\n' || c=='\r')
00278             return true;
00279         else if(c!=' ' && c!='\t')
00280             return false;
00281     }
00282     return true; // empty line
00283 }
00284 
00285 
00286 bool isParagraphBlank(const string& s)
00287 {
00288     string::size_type l = s.length();
00289     bool in_comment=false;
00290     for(unsigned int i=0; i<l; i++)
00291     {
00292         char c = s[i];
00293         if(c=='#')
00294             in_comment=true;
00295         else if(c=='\n' || c=='\r')
00296             in_comment=false;
00297         else if(c!=' ' && c!='\t' && !in_comment)
00298             return false;
00299     }
00300     return true; // empty line
00301 }
00302 
00303 string space_to_underscore(string str)
00304 {
00305     for(size_t i=0; i<str.size(); i++)
00306     {
00307         if(str[i]<=' ')
00308             str[i] = '_';
00309     }
00310     return str;
00311 }
00312 
00313 string underscore_to_space(string str)
00314 {
00315     for(size_t i=0; i<str.size(); i++)
00316     {
00317         if(str[i]=='_')
00318             str[i] = ' ';
00319     }
00320     return str;
00321 }
00322 
00323 string backslash_to_slash(string str)
00324 {
00325     for(size_t i=0; i<str.size(); i++)
00326     {
00327         if(str[i]=='\\')
00328             str[i] = '/';
00329     }
00330     return str;
00331 }
00332 
00333 
00334 int search_replace(string& text, const string& searchstr, const string& replacestr)
00335 {
00336     int n = 0;
00337     size_t startpos = text.find(searchstr, 0);
00338     while(startpos!=string::npos)
00339     {
00340         text.replace(startpos, searchstr.length(), replacestr);
00341         ++n;
00342         startpos = text.find(searchstr, startpos+replacestr.length());
00343     }
00344     return n;
00345 }
00346 
00347 
00348 vector<string> split(const string& s, char delimiter)
00349 {
00350     vector<string> res;
00351     string::size_type l = s.length();
00352     unsigned int beg = 0;
00353     unsigned int end = 0;
00354   
00355     while(end<=l)
00356     {
00357         while(end<l && s[end]!=delimiter)
00358             ++end;
00359         res.push_back(s.substr(beg,end-beg));
00360         ++end;
00361         beg = end;
00362     }
00363 
00364     return res;
00365 }
00366 
00367 vector<string> split_quoted_delimiter(const string& s, char delimiter,
00368                                       const string& double_quote){
00369     int quote_size=double_quote.size();
00370     if(quote_size==1)
00371         return split_quoted_delimiter(s,delimiter,double_quote[0]);
00372     else if(quote_size==0)
00373         return split(s,delimiter);
00374     PLASSERT(double_quote.size()>0);
00375 
00376     vector<string> ret = split(s, delimiter);
00377     vector<string> ret2;
00378     for(uint i=0; i<ret.size();i++){
00379         bool bw=string_begins_with(ret[i],double_quote);
00380         bool ew=string_ends_with(ret[i],double_quote);
00381         if(bw && ew){
00382             ret2.push_back(ret[i].substr(quote_size,
00383                                          ret[i].size()-quote_size)); 
00384         }else if(bw){
00385             string tmp=ret[i].substr(quote_size);
00386             tmp+=delimiter;
00387             for(uint j=i+1;j<ret.size();j++){
00388                 if(string_ends_with(ret[j],double_quote)){
00389                     tmp+=ret[j].substr(0,ret[j].size()-quote_size);
00390                     ret2.push_back(tmp);
00391                     i=j;
00392                     break;
00393                 }
00394                 tmp+=ret[j];
00395                 tmp+=delimiter;
00396             }
00397         }else
00398             ret2.push_back(ret[i]);
00399     }
00400     return ret2;
00401     
00402 }
00403 vector<string> split_quoted_delimiter(const string& s, char delimiter,
00404                                       char double_quote){
00405     PLASSERT(delimiter!=double_quote);
00406     vector<string> ret = split(s, delimiter);
00407     vector<string> ret2;
00408     for(uint i=0; i<ret.size();i++){
00409         string f = ret[i];
00410         bool bw=f[0]==double_quote;
00411         bool ew=f[f.size()-1]==double_quote;
00412         if(bw && ew){
00413             ret2.push_back(f.substr(1,f.size()-2)); 
00414         }else if(bw){
00415             string tmp=f.substr(1);
00416             tmp+=delimiter;
00417             for(uint j=i+1;j<ret.size();j++){
00418                 if(ret[j][ret[j].size()-1]==double_quote){
00419                     tmp+=ret[j].substr(0,ret[j].size()-1);
00420                     ret2.push_back(tmp);
00421                     i=j;
00422                     break;
00423                 }
00424                 tmp+=ret[j];
00425                 tmp+=delimiter;
00426             }
00427         }else
00428             ret2.push_back(f);
00429     }
00430     return ret2;
00431 }
00432 
00433 vector<string> split_quoted_delimiter(const string& s, const string& delimiters,
00434                                       const string& double_quote)
00435 {
00436     int quote_size=double_quote.size();
00437     if(quote_size==1 && delimiters.size()==1)
00438         return split_quoted_delimiter(s,delimiters[0],double_quote[0]);
00439     else if(delimiters.size()==1 && quote_size==0)
00440         return split(s,delimiters[0]);
00441     PLASSERT(delimiters.size()>0);
00442     vector<string> ret;
00443 
00444     size_t startpos = 0;
00445     size_t endpos = 0;
00446 
00447     for(;;)
00448     {
00449         startpos = endpos;
00450         bool quoted = string_begins_with(s.substr(startpos),double_quote);
00451         if(quoted){
00452             startpos+=quote_size;
00453             endpos = s.find(double_quote,startpos);
00454         }else
00455             endpos = s.find_first_of(delimiters,startpos);
00456         if(endpos==string::npos)
00457         {
00458             ret.push_back(s.substr(startpos));
00459             break;
00460         }
00461         ret.push_back(s.substr(startpos,endpos-startpos));
00462         if(quoted){
00463             endpos+=quote_size+1;
00464         }else
00465             endpos++;
00466         if(endpos>s.size())
00467             break;
00468     }
00469     return ret;
00470 }
00471 
00472 vector<string> split_all(const string& s, const string& delimiters)
00473 {
00474     vector<string> result;
00475 
00476     size_t startpos = 0;
00477     size_t endpos = 0;
00478 
00479     for(;;)
00480     {
00481         startpos = endpos;
00482         endpos = s.find_first_of(delimiters,startpos);
00483         if(endpos==string::npos)
00484         {
00485             result.push_back(s.substr(startpos));
00486             break;
00487         }
00488         result.push_back(s.substr(startpos,endpos-startpos));
00489         endpos++;
00490     }
00491 
00492     return result;
00493 }
00494 
00495 vector<string> split(const string& s, const string& delimiters, bool keep_delimiters)
00496 {
00497     vector<string> result;
00498 
00499     size_t startpos = 0;
00500     size_t endpos = 0;
00501 
00502     for(;;)
00503     {
00504         startpos = endpos;
00505         endpos = s.find_first_not_of(delimiters,startpos);
00506         if(endpos==string::npos)
00507         {
00508             if(keep_delimiters)
00509                 result.push_back(s.substr(startpos));
00510             break;
00511         }
00512         if(keep_delimiters && endpos>startpos)
00513             result.push_back(s.substr(startpos,endpos-startpos));
00514 
00515         startpos = endpos;
00516         endpos = s.find_first_of(delimiters,startpos);
00517         if(endpos==string::npos)
00518         {
00519             result.push_back(s.substr(startpos));
00520             break;
00521         }
00522         result.push_back(s.substr(startpos,endpos-startpos));
00523     }
00524 
00525     return result;
00526 }
00527 
00528 
00529 void split_on_first(const string& s,
00530                     const string& delimiters, string& left, string& right)
00531 {
00532     size_t pos = s.find_first_of(delimiters);
00533     if (pos != string::npos)
00534     {
00535         left = s.substr(0,pos);
00536         right = s.substr(pos+1);
00537     }
00538     else
00539     {
00540         left = s;
00541         right = "";
00542     }
00543 }
00544 
00545 pair<string,string> split_on_first(const string& s,
00546                                    const string& delimiters)
00547 {
00548     string left, right;
00549     split_on_first(s, delimiters, left, right);
00550     return make_pair(left,right);
00551 }
00552 
00553 
00554 void remove_comments(string& text, const string& commentstart)
00555 {
00556     size_t startpos=0;
00557     size_t endpos=0;
00558     while(endpos!=string::npos)
00559     {
00560         startpos = text.find(commentstart,startpos);
00561         if(startpos==string::npos)
00562             break;
00563         endpos = text.find_first_of("\n\r",startpos);
00564         text.erase(startpos, endpos-startpos);
00565     }
00566 }
00567 
00568 
00569 string join(const vector<string>& s, const string& separator)
00570 {
00571     string result;
00572     vector<string>::const_iterator it = s.begin();
00573     if(it!=s.end())
00574     {
00575         for(;;)
00576         {
00577             result += *it;
00578             ++it;
00579             if(it==s.end())
00580                 break;
00581             result += separator;
00582         }
00583     }
00584     return result;
00585 }
00586 
00587 vector<string> remove(const vector<string> &v, string element)
00588 {
00589     vector<string> res;
00590     for (size_t i=0;i<v.size();i++)
00591         if (v[i]!=element) res.push_back(v[i]);
00592     return res;
00593 }
00594 
00595 
00596 int findpos(const vector<string> &v, string element)
00597 {
00598     for (size_t i=0;i<v.size();i++)
00599         if (v[i]==element) return int(i);
00600     return -1;
00601 }
00602 
00603 
00604 int universal_compare(const string& x, const string& y)
00605 {
00606     // Try numerical comparison
00607     double x_double = todouble(x);
00608     double y_double = todouble(y);
00609     if (! (is_missing(x_double) || is_missing(y_double))) {
00610         if (is_equal(x_double, y_double))
00611             return 0;
00612         else
00613             return int(x_double - y_double);
00614     }
00615 
00616     // Fall back to string comparison
00617     return x.compare(y);
00618 }
00619 
00620 
00621 vector<string> addprepostfix(const string& prefix, const vector<string>& names, const string& postfix)
00622 {
00623     vector<string> newnames(names.size());
00624     vector<string>::const_iterator it = names.begin();
00625     vector<string>::iterator newit = newnames.begin();
00626     while(it!=names.end())
00627     {
00628         *newit = prefix + *it + postfix;
00629         ++it;
00630         ++newit;
00631     }
00632     return newnames;
00633 }
00634 
00635 string addprepostfix(const string& prefix, const string& text, const string& postfix)
00636 {
00637     size_t startpos = 0;
00638     size_t endpos = 0;
00639     string res;
00640     while(endpos!=string::npos)
00641     {
00642         endpos = text.find_first_of("\n",startpos);
00643         if(endpos!=string::npos)
00644             res += prefix + text.substr(startpos, endpos-startpos) + postfix
00645                                                                   + "\n";
00646         else
00647             res += prefix + text.substr(startpos) + postfix;
00648         startpos = endpos + 1;
00649     }
00650     return res;
00651 }
00652 
00653 vector<string> stringvector(int argc, char** argv)
00654 {
00655     if(argc>0)
00656     {
00657         vector<string> result(argc);
00658         for(int i=0; i<argc; i++)
00659             result[i] = string(argv[i]);
00660         return result;
00661     }
00662     else
00663         return vector<string>();
00664 }
00665 
00666 string get_option(const vector<string> &command_line, 
00667                   const string& option, const string& default_value)
00668 {
00669     vector<string>::size_type n = command_line.size();
00670     for (unsigned int i=0;i<n;i++)
00671         if (command_line[i]==option && i+1<n) return command_line[i+1];
00672     return default_value;
00673 }
00674 
00675 bool find(const vector<string> &command_line, const string& option)
00676 {
00677     vector<string>::size_type n = command_line.size();
00678     for (unsigned int i=0;i<n;i++)
00679         if (command_line[i]==option) return true;
00680     return false;
00681 }
00682 
00683 vector<string> getNonBlankLines(const string & in)
00684 {
00685     vector<string> lines;
00686     vector<string> nblines;
00687 
00688     char sep[3]={10,13,0};
00689     lines= split(in,sep);
00690     for(size_t i=0;i<lines.size();i++)
00691         if(!isBlank(lines[i]))
00692             nblines.push_back(lines[i]);
00693     return nblines;
00694 }
00695 
00696 
00697 ostream& operator<<(ostream& out, const vector<string>& vs)
00698 {
00699     vector<string>::const_iterator it = vs.begin();
00700     if(it!=vs.end())
00701     {
00702         out << *it;
00703         ++it;
00704     }
00705     while(it!=vs.end())
00706     {
00707         out << ", " << *it;
00708         ++it;
00709     }
00710     return out;
00711 }
00712 
00714 // split_from_string //
00716 vector<string> split_from_string(const string& s, const string& delimiter)
00717 {
00718     vector<string> res;
00719     string::size_type pos_of_delim;
00720     string::size_type pos_of_start = 0;
00721     string::size_type size_of_delim = delimiter.size();
00722     do {
00723         pos_of_delim = s.find(delimiter, pos_of_start);
00724         if (pos_of_delim == string::npos)
00725             res.push_back(s.substr(pos_of_start));
00726         else {
00727             res.push_back(s.substr(pos_of_start, pos_of_delim - pos_of_start));
00728             pos_of_start = pos_of_delim + size_of_delim;
00729         }
00730     } while (pos_of_delim != string::npos);
00731     return res;
00732 }
00733 
00735 // parseBaseAndParameters //
00737 void parseBaseAndParameters(const string& s, string& base,
00738                             map<string, string>& params,
00739                             map<string, string>* added,
00740                             map<string, string>* backup,
00741                             const string& delimiter)
00742 {
00743     vector<string> splits = split_from_string(s, delimiter);
00744     base = splits[0];
00745     string name, value;
00746     map<string, string>::const_iterator it;
00747     if (backup)
00748         backup->clear();
00749     if (added)
00750         added->clear();
00751     for (vector<string>::size_type i = 1; i < splits.size(); i++) {
00752         const string& str = splits[i];
00753         if (str.find('=') == string::npos)
00754             PLERROR("In parseBaseAndParameters - Could not find the '=' character when parsing "
00755                     "parameter '%s'", str.c_str());
00756         split_on_first(str, "=", name, value);
00757         if (name.empty())
00758             PLERROR("In parseBaseAndParameters - Read an empty parameter name in string '%s'"
00759                     , s.c_str());
00760         if (backup && (it = params.find(name)) != params.end())
00761             (*backup)[name] = it->second;
00762         params[name] = value;
00763         if (added)
00764             (*added)[name] = value;
00765     }
00766 }
00767 
00768 } // end of namespace PLearn
00769 
00770 
00771 /*
00772   Local Variables:
00773   mode:c++
00774   c-basic-offset:4
00775   c-file-style:"stroustrup"
00776   c-file-offsets:((innamespace . 0)(inline-open . 0))
00777   indent-tabs-mode:nil
00778   fill-column:79
00779   End:
00780 */
00781 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines