PLearn 0.1
|
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 :