osgEarth 2.1.1
|
00001 /* -*-c++-*- */ 00002 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph 00003 * Copyright 2008-2010 Pelican Mapping 00004 * http://osgearth.org 00005 * 00006 * osgEarth is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU Lesser General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public License 00017 * along with this program. If not, see <http://www.gnu.org/licenses/> 00018 */ 00019 #ifndef OSGEARTH_STRING_UTILS_H 00020 #define OSGEARTH_STRING_UTILS_H 1 00021 00022 #include <osgEarth/Common> 00023 #include <osg/Vec4> 00024 #include <osg/Vec4ub> 00025 #include <string> 00026 #include <algorithm> 00027 #include <vector> 00028 #include <sstream> 00029 #include <iomanip> 00030 #include <map> 00031 00032 namespace osgEarth 00033 { 00034 typedef std::vector<std::string> StringVector; 00035 00037 static std::string& 00038 replaceIn( std::string& s, const std::string& sub, const std::string& other) 00039 { 00040 if ( sub.empty() ) return s; 00041 size_t b=0; 00042 for( ; ; ) 00043 { 00044 b = s.find( sub, b ); 00045 if ( b == s.npos ) break; 00046 s.replace( b, sub.size(), other ); 00047 b += other.size(); 00048 } 00049 return s; 00050 } 00051 00057 static 00058 std::string trim( const std::string& in ) 00059 { 00060 std::string whitespace (" \t\f\v\n\r"); 00061 std::string str = in; 00062 std::string::size_type pos = str.find_last_not_of( whitespace ); 00063 if(pos != std::string::npos) { 00064 str.erase(pos + 1); 00065 pos = str.find_first_not_of( whitespace ); 00066 if(pos != std::string::npos) str.erase(0, pos); 00067 } 00068 else str.erase(str.begin(), str.end()); 00069 return str; 00070 } 00071 00075 static 00076 bool startsWith( const std::string& ref, const std::string& pattern ) 00077 { 00078 return ref.find( pattern ) == 0; 00079 } 00080 00084 static 00085 bool endsWith( const std::string& ref, const std::string& pattern ) 00086 { 00087 return ref.find( pattern ) == ref.length()-pattern.length(); 00088 } 00089 00094 class OSGEARTH_EXPORT StringTokenizer 00095 { 00096 public: 00097 StringTokenizer( const std::string& delims =" \t\r\n", const std::string& quotes ="'\"" ); 00098 00099 StringTokenizer( 00100 const std::string& input, StringVector& output, 00101 const std::string& delims =" \t\r\n", const std::string& quotes ="'\"", 00102 bool keepEmpties =true, bool trimTokens =true); 00103 00104 void tokenize( const std::string& input, StringVector& output ) const; 00105 00106 bool& keepEmpties() { return _allowEmpties; } 00107 00108 bool& trimTokens() { return _trimTokens; } 00109 00110 void addDelim( char delim, bool keepAsToken =false ); 00111 00112 void addDelims( const std::string& delims, bool keepAsTokens =false ); 00113 00114 void addQuote( char delim, bool keepInToken =false ); 00115 00116 void addQuotes( const std::string& delims, bool keepInTokens =false ); 00117 00118 private: 00119 typedef std::map<char,bool> TokenMap; 00120 TokenMap _delims; 00121 TokenMap _quotes; 00122 bool _allowEmpties; 00123 bool _trimTokens; 00124 }; 00125 00126 static std::string 00127 joinStrings( const StringVector& input, char delim ) 00128 { 00129 std::stringstream buf; 00130 for( StringVector::const_iterator i = input.begin(); i != input.end(); ++i ) 00131 { 00132 buf << *i; 00133 if ( (i+1) != input.end() ) buf << delim; 00134 } 00135 std::string result = buf.str(); 00136 return result; 00137 } 00138 00140 static std::string 00141 toLower( const std::string& input ) 00142 { 00143 std::string output = input; 00144 std::transform( output.begin(), output.end(), output.begin(), ::tolower ); 00145 return output; 00146 } 00147 00149 static osg::Vec4ub 00150 stringToColor(const std::string& str, osg::Vec4ub default_value) 00151 { 00152 osg::Vec4ub color = default_value; 00153 std::istringstream strin(str); 00154 int r, g, b, a; 00155 if (strin >> r && strin >> g && strin >> b && strin >> a) 00156 { 00157 color.r() = (unsigned char)r; 00158 color.g() = (unsigned char)g; 00159 color.b() = (unsigned char)b; 00160 color.a() = (unsigned char)a; 00161 } 00162 return color; 00163 } 00164 00166 static std::string 00167 colorToString( const osg::Vec4ub& c ) 00168 { 00169 std::stringstream ss; 00170 ss << (int)c.r() << " " << (int)c.g() << " " << (int)c.b() << " " << (int)c.a(); 00171 std::string ssStr; 00172 ssStr = ss.str(); 00173 return ssStr; 00174 } 00175 00177 static osg::Vec3f 00178 stringToVec3f( const std::string& str, const osg::Vec3f& default_value ) 00179 { 00180 std::stringstream buf(str); 00181 osg::Vec3f out = default_value; 00182 buf >> out.x(); 00183 if ( !buf.eof() ) { 00184 buf >> out.y() >> out.z(); 00185 } 00186 else { 00187 out.y() = out.x(); 00188 out.z() = out.x(); 00189 } 00190 return out; 00191 } 00192 00194 static std::string 00195 vec3fToString( const osg::Vec3f& v ) 00196 { 00197 std::stringstream buf; 00198 buf << std::setprecision(6) 00199 << v.x() << " " << v.y() << " " << v.z() 00200 << std::endl; 00201 std::string result; 00202 result = buf.str(); 00203 return result; 00204 } 00205 00207 static osg::Vec4f 00208 htmlColorToVec4f( const std::string& html ) 00209 { 00210 std::string t = html; 00211 std::transform( t.begin(), t.end(), t.begin(), ::tolower ); 00212 osg::Vec4ub c(0,0,0,255); 00213 if ( t.length() >= 7 ) { 00214 c.r() |= t[1]<='9' ? (t[1]-'0')<<4 : (10+(t[1]-'a'))<<4; 00215 c.r() |= t[2]<='9' ? (t[2]-'0') : (10+(t[2]-'a')); 00216 c.g() |= t[3]<='9' ? (t[3]-'0')<<4 : (10+(t[3]-'a'))<<4; 00217 c.g() |= t[4]<='9' ? (t[4]-'0') : (10+(t[4]-'a')); 00218 c.b() |= t[5]<='9' ? (t[5]-'0')<<4 : (10+(t[5]-'a'))<<4; 00219 c.b() |= t[6]<='9' ? (t[6]-'0') : (10+(t[6]-'a')); 00220 if ( t.length() == 9 ) { 00221 c.a() = 0; 00222 c.a() |= t[7]<='9' ? (t[7]-'0')<<4 : (10+(t[7]-'a'))<<4; 00223 c.a() |= t[8]<='9' ? (t[8]-'0') : (10+(t[8]-'a')); 00224 } 00225 } 00226 return osg::Vec4f( ((float)c.r())/255.0f, ((float)c.g())/255.0f, ((float)c.b())/255.0f, ((float)c.a())/255.0f ); 00227 } 00228 00230 static std::string 00231 vec4fToHtmlColor( const osg::Vec4f& c ) 00232 { 00233 std::stringstream buf; 00234 buf << "#"; 00235 buf << std::hex << std::setw(2) << std::setfill('0') << (int)(c.r()*255.0f); 00236 buf << std::hex << std::setw(2) << std::setfill('0') << (int)(c.g()*255.0f); 00237 buf << std::hex << std::setw(2) << std::setfill('0') << (int)(c.b()*255.0f); 00238 if ( c.a() < 1.0f ) 00239 buf << std::hex << std::setw(2) << std::setfill('0') << (int)(c.a()*255.0f); 00240 std::string ssStr = buf.str(); 00241 return ssStr; 00242 } 00243 00245 static unsigned int 00246 hashString( const std::string& input ) 00247 { 00248 const unsigned int m = 0x5bd1e995; 00249 const int r = 24; 00250 unsigned int len = input.length(); 00251 const char* data = input.c_str(); 00252 unsigned int h = m ^ len; // using "m" as the seed. 00253 00254 while(len >= 4) 00255 { 00256 unsigned int k = *(unsigned int *)data; 00257 k *= m; 00258 k ^= k >> r; 00259 k *= m; 00260 h *= m; 00261 h ^= k; 00262 data += 4; 00263 len -= 4; 00264 } 00265 00266 switch(len) 00267 { 00268 case 3: h ^= data[2] << 16; 00269 case 2: h ^= data[1] << 8; 00270 case 1: h ^= data[0]; 00271 h *= m; 00272 }; 00273 00274 h ^= h >> 13; 00275 h *= m; 00276 h ^= h >> 15; 00277 00278 return h; 00279 } 00280 00281 //------------------------------------------------------------------------ 00282 // conversion templates 00283 00284 // converts a string to primitive using serialization 00285 template<typename T> inline T 00286 as( const std::string& str, const T& default_value ) 00287 { 00288 T temp = default_value; 00289 std::istringstream strin( str ); 00290 if ( !strin.eof() ) strin >> temp; 00291 return temp; 00292 } 00293 00294 // template specialization for a bool 00295 template<> inline bool 00296 as<bool>( const std::string& str, const bool& default_value ) 00297 { 00298 std::string temp = str; 00299 std::transform( temp.begin(), temp.end(), temp.begin(), ::tolower ); 00300 return 00301 temp == "true" || temp == "yes" || temp == "on" ? true : 00302 temp == "false" || temp == "no" || temp == "off" ? false : 00303 default_value; 00304 } 00305 00306 template<> inline osg::Vec3f 00307 as<osg::Vec3f>( const std::string& str, const osg::Vec3f& default_value ) 00308 { 00309 return stringToVec3f(str, default_value); 00310 } 00311 00312 // template specialization for string 00313 template<> inline std::string 00314 as<std::string>( const std::string& str, const std::string& default_value ) 00315 { 00316 return str; 00317 } 00318 00319 // converts a primitive to a string 00320 // TODO: precision?? 00321 template<typename T> inline std::string 00322 toString(const T& value) 00323 { 00324 std::stringstream out; 00325 out << std::setprecision(20) << std::fixed << value; 00326 std::string outStr; 00327 outStr = out.str(); 00328 return outStr; 00329 } 00330 00331 // template speciallization for a bool to print out "true" or "false" 00332 template<> inline std::string 00333 toString<bool>(const bool& value) 00334 { 00335 return value ? "true" : "false"; 00336 } 00337 00338 template<> inline std::string 00339 toString<osg::Vec3f>(const osg::Vec3f& value) 00340 { 00341 return vec3fToString(value); 00342 } 00343 00344 struct Stringify 00345 { 00346 operator std::string () const 00347 { 00348 std::string result; 00349 result = buf.str(); 00350 return result; 00351 } 00352 00353 Stringify& operator << (bool val) { buf << val; return (*this); } 00354 Stringify& operator << (short val) { buf << val; return (*this); } 00355 Stringify& operator << (unsigned short val) { buf << val; return (*this); } 00356 Stringify& operator << (int val) { buf << val; return (*this); } 00357 Stringify& operator << (unsigned int val) { buf << val; return (*this); } 00358 Stringify& operator << (long val) { buf << val; return (*this); } 00359 Stringify& operator << (unsigned long val) { buf << val; return (*this); } 00360 Stringify& operator << (float val) { buf << val; return (*this); } 00361 Stringify& operator << (double val) { buf << val; return (*this); } 00362 Stringify& operator << (long double val) { buf << val; return (*this); } 00363 Stringify& operator << (const void* val) { buf << val; return (*this); } 00364 Stringify& operator << (char val) { buf << val; return (*this); } 00365 Stringify& operator << (signed char val) { buf << val; return (*this); } 00366 Stringify& operator << (unsigned char val) { buf << val; return (*this); } 00367 Stringify& operator << (const char* val) { buf << val; return (*this); } 00368 Stringify& operator << (const signed char* val) { buf << val; return (*this); } 00369 Stringify& operator << (const unsigned char* val) { buf << val; return (*this); } 00370 Stringify& operator << (const std::string& val) { buf << val; return (*this); } 00371 Stringify& operator << (std::streambuf* val) { buf << val; return (*this); } 00372 Stringify& operator << (std::ostream& (*val)(std::ostream&)) { buf << val; return (*this); } 00373 Stringify& operator << (std::ios& (*val)(std::ostream&)) { buf << val; return (*this); } 00374 Stringify& operator << (std::ios_base& (*val)(std::ios_base&)) { buf << val; return (*this); } 00375 00376 protected: 00377 std::stringstream buf; 00378 }; 00379 } 00380 00381 #endif // OSGEARTH_STRING_UTILS_H 00382