Simbody
|
00001 #ifndef SimTK_SimTKCOMMON_STRING_H_ 00002 #define SimTK_SimTKCOMMON_STRING_H_ 00003 00004 /* -------------------------------------------------------------------------- * 00005 * SimTK Core: SimTKcommon * 00006 * -------------------------------------------------------------------------- * 00007 * This is part of the SimTK Core biosimulation toolkit originating from * 00008 * Simbios, the NIH National Center for Physics-Based Simulation of * 00009 * Biological Structures at Stanford, funded under the NIH Roadmap for * 00010 * Medical Research, grant U54 GM072970. See https://simtk.org. * 00011 * * 00012 * Portions copyright (c) 2005-10 Stanford University and the Authors. * 00013 * Authors: Michael Sherman * 00014 * Contributors: * 00015 * * 00016 * Permission is hereby granted, free of charge, to any person obtaining a * 00017 * copy of this software and associated documentation files (the "Software"), * 00018 * to deal in the Software without restriction, including without limitation * 00019 * the rights to use, copy, modify, merge, publish, distribute, sublicense, * 00020 * and/or sell copies of the Software, and to permit persons to whom the * 00021 * Software is furnished to do so, subject to the following conditions: * 00022 * * 00023 * The above copyright notice and this permission notice shall be included in * 00024 * all copies or substantial portions of the Software. * 00025 * * 00026 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * 00027 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * 00028 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * 00029 * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 00030 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 00031 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * 00032 * USE OR OTHER DEALINGS IN THE SOFTWARE. * 00033 * -------------------------------------------------------------------------- */ 00034 00035 // Keeps MS VC++ 8 quiet about sprintf, strcpy, etc. 00036 #ifdef _MSC_VER 00037 #pragma warning(disable:4996) 00038 #endif 00039 00040 00041 #include "SimTKcommon/internal/common.h" 00042 00043 #include <cstdio> 00044 #include <string> 00045 #include <limits> 00046 #include <complex> 00047 #include <sstream> 00048 00049 namespace SimTK { 00050 00066 class String : public std::string { 00067 public: 00068 00070 String() { } 00071 00072 // uses default copy constructor, copy assignment, and destructor 00073 00075 String(const char* s) : std::string(s) { } 00076 00078 explicit String(char c) {push_back(c);} 00079 00081 String(const std::string& s) : std::string(s) { } 00082 00085 String(const String& s, int start, int len) : std::string(s,start,len) { } 00086 00089 operator const char*() const { return c_str(); } 00090 00092 char& operator[](int i) { 00093 assert(i >= 0); 00094 return std::string::operator[]((std::string::size_type)i); 00095 } 00096 00098 char operator[](int i) const { 00099 assert(i >= 0); 00100 return std::string::operator[]((std::string::size_type)i); 00101 } 00102 00104 char& operator[](std::string::size_type i) {return std::string::operator[](i);} 00106 char operator[](std::string::size_type i) const {return std::string::operator[](i);} 00107 00110 int size() const {return (int)std::string::size();} 00111 00114 int length() const {return (int)std::string::length();} 00115 00120 explicit String(int i) { char buf[32]; sprintf(buf,"%d",i); (*this)=buf; } 00122 explicit String(long i) { char buf[32]; sprintf(buf,"%ld",i); (*this)=buf; } 00124 explicit String(long long i) { char buf[64]; sprintf(buf,"%lld",i); (*this)=buf; } 00126 explicit String(unsigned int s) { char buf[32]; sprintf(buf,"%u",s); (*this)=buf; } 00128 explicit String(unsigned long s) { char buf[32]; sprintf(buf,"%lu",s); (*this)=buf; } 00130 explicit String(unsigned long long s) { char buf[64]; sprintf(buf,"%llu",s); (*this)=buf; } 00132 explicit String(float r) { char buf[64]; sprintf(buf,"%.8g",r); (*this)=buf; } 00134 explicit String(double r) { char buf[64]; sprintf(buf,"%.16g",r); (*this)=buf; } 00136 explicit String(long double r) { char buf[64]; sprintf(buf,"%.20Lg",r); (*this)=buf; } 00138 explicit String(std::complex<float> r) 00139 { char buf[128]; sprintf(buf,"(%.8g,%.8g)",r.real(),r.imag()); (*this)=buf; } 00141 explicit String(std::complex<double> r) 00142 { char buf[128]; sprintf(buf,"(%.16g,%.16g)",r.real(),r.imag()); (*this)=buf; } 00144 explicit String(std::complex<long double> r) 00145 { char buf[128]; sprintf(buf,"(%.20Lg,%.20Lg)",r.real(),r.imag()); (*this)=buf; } 00148 explicit String(bool b) : std::string(b?"true":"false") { } 00152 template <class T> inline explicit String(const T& t); // see below 00185 template <class T> inline bool tryConvertTo(T& out) const; // see below 00186 00193 template <class T> inline void convertTo(T& out) const; // see below 00194 00201 template <class T> T convertTo() const 00202 { T temp; convertTo<T>(temp); return temp; } 00203 00216 SimTK_SimTKCOMMON_EXPORT String& toUpper(); 00219 SimTK_SimTKCOMMON_EXPORT String& toLower(); 00223 SimTK_SimTKCOMMON_EXPORT String& trimWhiteSpace(); 00226 SimTK_SimTKCOMMON_EXPORT String& replaceAllChar(char oldChar, char newChar); 00237 static const String& getAs(const std::string& s) 00238 { return reinterpret_cast<const String&>(s); } 00242 static String& updAs(std::string& s) 00243 { return reinterpret_cast<String&>(s); } 00246 static String toUpper(const std::string& in) 00247 { return String(in).toUpper(); } 00250 static String toLower(const std::string& in) 00251 { return String(in).toLower(); } 00256 static SimTK_SimTKCOMMON_EXPORT String trimWhiteSpace(const std::string& in); 00259 String& replaceAllChar(const std::string& in, char oldChar, char newChar) 00260 { return String(in).replaceAllChar(oldChar, newChar); } 00263 }; 00264 00265 // All std::stream activity should be dealt with inline so that we don't have 00266 // to worry about binary compatibiliy issues that can arise when passing 00267 // streams through the API. 00268 00269 // Templatized String constructor definition. 00270 template <class T> inline 00271 String::String(const T& t) { 00272 std::ostringstream stream; 00273 stream << t; 00274 *this = stream.str(); 00275 } 00276 00277 // This namespace-level static method should not be necessary but gcc 4.1 00278 // still has trouble with template specialization for template member 00279 // functions. So rather than specializing the tryConvertTo() member, I'm 00280 // specializing this helper function instead. 00281 template <class T> inline static 00282 bool tryConvertStringTo(const String& value, T& out) { 00283 std::istringstream sstream(value); 00284 sstream >> out; if (sstream.fail()) return false; 00285 if (sstream.eof()) return true; 00286 // Successful conversion but didn't use all the characters. Maybe the 00287 // rest is just whitespace? 00288 std::ws(sstream); // Skip trailing whitespace if any. 00289 return sstream.eof(); // We must have used up the whole string now. 00290 } 00291 00292 // This specialization ensures that we get the whole String including 00293 // leading and trailing white space. Of course this is not useful for 00294 // anything but may occur as a result of some higher-level templatized 00295 // method that doesn't know what type it is converting here. 00296 template<> inline 00297 bool tryConvertStringTo(const String& value, String& out) 00298 { out = value; return true; } 00299 00300 // Same as above but for std::string output rather than String. 00301 template<> inline 00302 bool tryConvertStringTo(const String& value, std::string& out) 00303 { out = value; return true; } 00304 00305 // This partial specialization ensures that you can't interpret 00306 // a String as a pointer. 00307 template<class T> inline static 00308 bool tryConvertStringTo(const String& value, T*& out) { 00309 SimTK_ERRCHK1_ALWAYS(false, "SimTK::convertStringTo(value,T*)", 00310 "Can't interpret a string as a pointer (%s*).", 00311 NiceTypeName<T>::name()); 00312 return false; 00313 } 00314 00315 template <class T> inline bool 00316 String::tryConvertTo(T& out) const 00317 { return tryConvertStringTo(*this, out); } 00318 00319 template <class T> inline void 00320 String::convertTo(T& out) const { 00321 const int MaxStr = 50; 00322 const bool convertOK = tryConvertTo<T>(out); 00323 if (convertOK) return; 00324 00325 // Make sure we don't try to output more than MaxStr characters of 00326 // the bad string in the error message. 00327 String shorter = this->substr(0, MaxStr); 00328 if (shorter.size() < this->size()) shorter += " ..."; 00329 SimTK_ERRCHK2_ALWAYS(convertOK, "Xml::getAs()", 00330 "Couldn't interpret string '%s' as type T=%s.", 00331 shorter.c_str(), NiceTypeName<T>::name()); 00332 } 00333 00345 template <class T> inline static 00346 void convertStringTo(const String& in, T& out) 00347 { in.convertTo<T>(out); } 00348 00359 template <class T> inline static 00360 T convertStringTo(const String& in) 00361 { return in.convertTo<T>(); } 00362 00363 } 00364 #endif // SimTK_SimTKCOMMON_STRING_H_