00001
00007 #ifndef __STRINGUTILS_H__
00008 #define __STRINGUTILS_H__
00009
00010 #include "stringparser.h"
00011
00013 namespace String {
00014
00015
00025 template <class String>
00026 bool glob_match(const String& globstr, const String& teststr)
00027 {
00028
00029 if (globstr.empty()) return teststr.empty();
00030
00031 const bool startglob = (globstr[0] =='*');
00032 const bool endglob = (globstr[globstr.length()-1]=='*');
00033
00034 if ((teststr[0]=='.') && startglob) return false;
00035
00036 if (!startglob && !endglob) return globstr==teststr;
00037
00038 const String globtext = String(globstr, (startglob? 1 : 0), globstr.length()-startglob-endglob);
00039
00040 if (!startglob && endglob)
00041 return (teststr.find(globtext)==0);
00042
00043 if (startglob && !endglob)
00044 return (teststr.rfind(globtext)==teststr.length()-globtext.length());
00045
00047 return (globtext=="" || teststr.find(globtext)<teststr.length());
00048 }
00049
00050
00051
00053 template <class String>
00054 bool non_numeric_basename_matches(const String& a, const String& b)
00055 {
00056 return (String(a.data(),a.find_last_not_of("0123456789")) ==
00057 String(b.data(),b.find_last_not_of("0123456789")) );
00058 }
00059
00060
00061
00064 template <class T, class String>
00065 T numeric_extension(const String& a)
00066 {
00067 String b=a;
00068 b.erase(0,b.find_last_not_of("0123456789")+1);
00069 if (b.empty())
00070 return T();
00071
00072 T result;
00073 const StringParser sp;
00074 return sp.parse(b,result);
00075 }
00076
00077
00078
00081 template <class String>
00082 int integer_portion(const String& a)
00083 {
00084 int pivot = int(a.rfind("."));
00085 if (pivot<0 || pivot>=int(a.length())) pivot=a.length();
00086 String b(a,0,pivot);
00087 int result;
00088 const StringParser sp;
00089 return sp.parse(b,result);
00090 }
00091
00092
00093
00098 template <class String>
00099 int fractional_portion(const String& a)
00100 {
00101 int pivot = int(a.rfind("."));
00102 if (pivot<0 || pivot+1>=int(a.length())) return 0;
00103 String b(a,pivot+1,a.length()-pivot-1);
00104 int result;
00105 const StringParser sp;
00106 return sp.parse(b,result);
00107 }
00108
00109
00110
00120 inline unsigned C_identifier_length(const char* s, const char nonalnum='_')
00121 {
00122 if (!s || (!isalpha(*s) && (nonalnum=='_' || *s!=nonalnum)))
00123 return 0;
00124 const char * rem;
00125 for (rem=s; (isalnum(*rem) || *rem == '_' || *rem == nonalnum); rem++);
00126 return rem-s;
00127 }
00128
00129
00130
00131 template <class String>
00132 inline unsigned C_identifier_length(const String& s, const char nonalnum='_')
00133 { return C_identifier_length(s.c_str(),nonalnum); }
00134
00135
00136
00138 template <class String>
00139 String strip_quotes(const String& s)
00140 {
00141 unsigned start = 0;
00142 unsigned end = s.length()-1;
00143
00144 if ( (s[start] == '"' && s[end] == '"' ) ||
00145 (s[start] == '\'' && s[end] == '\'') ) {
00146 start++;
00147 end--;
00148 }
00149 return String(s,start,end-start+1);
00150 }
00151
00152
00153
00156 template <class String>
00157 inline string replace_all(const String& s, const String& fromtext, const String& totext)
00158 {
00159 unsigned pos;
00160 unsigned start=0;
00161 string p=s;
00162 while ((pos=p.find(fromtext,start))<p.length()) {
00163 p.replace(pos,fromtext.length(),totext);
00164 start=pos+totext.length();
00165 }
00166 return p;
00167 }
00168
00169
00170
00177 class StreamFormat {
00178 public:
00179
00180 virtual ~StreamFormat() { }
00181
00188 StreamFormat(const int width_=-1, const char fill_=' ', const int digitsafterdecimal_=-1,
00189 const bool rightadjust_=true)
00190 : width(width_), fill(fill_), digitsafterdecimal(digitsafterdecimal_),
00191 rightadjust(rightadjust_) { }
00192
00203 StreamFormat(const string& flags)
00204 : width(-1), fill(' '), digitsafterdecimal(-1), rightadjust(true) {
00205 if (flags!="") {
00206 const bool hasfill = (!isdigit(flags[0]) || flags[0] == '0');
00207 const string rest = string(flags.begin()+(hasfill? 1 : 0),flags.end());
00208 const bool hasfraction = (rest.find(".")<rest.length());
00209
00210 width = String::integer_portion(rest);
00211 if (hasfill) fill = flags[0];
00212 if (hasfraction) digitsafterdecimal = String::fractional_portion(rest);
00213 }
00214 }
00215
00217 virtual std::ostream& put(std::ostream &s) const {
00218
00219
00220 if (width>=0) s.width(width);
00221 if (digitsafterdecimal>=0) { s.precision(digitsafterdecimal); s.setf(std::ios::fixed,std::ios::floatfield); }
00222 if (fill!=' ') s.fill(fill);
00223 if (!rightadjust) s.setf(std::ios::left,std::ios::adjustfield);
00224 return s;
00225 }
00226
00227 private:
00228 int width;
00229 char fill;
00230 int digitsafterdecimal;
00231 bool rightadjust;
00232 };
00233
00234
00235
00237 inline std::ostream& operator<<(std::ostream &s, const StreamFormat& a) { return a.put(s); }
00238
00239
00240
00247 template<class T>
00248 string stringrep(const T& item, const StreamFormat format=StreamFormat())
00249 {
00250
00251
00252 std::ostrstream os;
00253 os << format << item << std::ends;
00254 return string(os.str());
00255 }
00256
00257
00258 }
00259
00260 #endif