Simbody  3.4 (development)
String.h
Go to the documentation of this file.
00001 #ifndef SimTK_SimTKCOMMON_STRING_H_
00002 #define SimTK_SimTKCOMMON_STRING_H_
00003 
00004 /* -------------------------------------------------------------------------- *
00005  *                       Simbody(tm): SimTKcommon                             *
00006  * -------------------------------------------------------------------------- *
00007  * This is part of the SimTK 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/home/simbody.  *
00011  *                                                                            *
00012  * Portions copyright (c) 2005-12 Stanford University and the Authors.        *
00013  * Authors: Michael Sherman                                                   *
00014  * Contributors:                                                              *
00015  *                                                                            *
00016  * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
00017  * not use this file except in compliance with the License. You may obtain a  *
00018  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
00019  *                                                                            *
00020  * Unless required by applicable law or agreed to in writing, software        *
00021  * distributed under the License is distributed on an "AS IS" BASIS,          *
00022  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
00023  * See the License for the specific language governing permissions and        *
00024  * limitations under the License.                                             *
00025  * -------------------------------------------------------------------------- */
00026 
00027 // Keeps MS VC++ 8 quiet about sprintf, strcpy, etc.
00028 #ifdef _MSC_VER
00029 #pragma warning(disable:4996)
00030 #endif
00031 
00032 
00033 #include "SimTKcommon/internal/common.h"
00034 #include "SimTKcommon/internal/ExceptionMacros.h"
00035 
00036 #include <cstdio>
00037 #include <string>
00038 #include <limits>
00039 #include <complex>
00040 #include <sstream>
00041 
00042 namespace SimTK {
00043 
00044 template <class N> class negator;
00045 template <class R> class conjugate;
00046     
00062 class String : public std::string {
00063 public:
00064 
00066 String() { }
00067 
00068 // uses default copy constructor, copy assignment, and destructor
00069 
00071 String(const char* s) : std::string(s) { }
00072 
00074 explicit String(char c) {push_back(c);}
00075 
00077 String(const std::string& s) : std::string(s) { }
00078 
00081 String(const String& s, int start, int len) : std::string(s,start,len) { }
00082 
00085 operator const char*() const { return c_str(); }
00086 
00088 char& operator[](int i) {
00089     assert(i >= 0);
00090     return std::string::operator[]((std::string::size_type)i);
00091 }
00092 
00094 char operator[](int i) const {
00095     assert(i >= 0);
00096     return std::string::operator[]((std::string::size_type)i);
00097 }
00098 
00100 char& operator[](std::string::size_type i) {return std::string::operator[](i);}
00102 char operator[](std::string::size_type i) const {return std::string::operator[](i);}
00103 
00106 int size() const {return (int)std::string::size();}
00107 
00110 int length() const {return (int)std::string::length();}
00111 
00120 explicit String(int i, const char* fmt="%d") 
00121 {   char buf[32]; sprintf(buf,fmt,i); (*this)=buf; }
00123 explicit String(long i, const char* fmt="%ld") 
00124 {   char buf[64]; sprintf(buf,fmt,i); (*this)=buf; }
00126 explicit String(long long i, const char* fmt="%lld") 
00127 {   char buf[64]; sprintf(buf,fmt,i); (*this)=buf; }
00129 explicit String(unsigned int s, const char* fmt="%u")  
00130 {   char buf[32]; sprintf(buf,fmt,s); (*this)=buf; }
00132 explicit String(unsigned long s, const char* fmt="%lu") 
00133 {   char buf[64]; sprintf(buf,fmt,s); (*this)=buf; }
00135 explicit String(unsigned long long s, const char* fmt="%llu") 
00136 {   char buf[64]; sprintf(buf,fmt,s); (*this)=buf; }
00137 
00140 SimTK_SimTKCOMMON_EXPORT explicit String(float r, const char* fmt="%.7g");
00141 
00144 SimTK_SimTKCOMMON_EXPORT explicit String(double r, const char* fmt="%.15g");
00145 
00148 SimTK_SimTKCOMMON_EXPORT explicit String(long double r, 
00149                                          const char* fmt="%.20Lg");
00150 
00154 explicit String(std::complex<float> r, const char* fmt="%.7g")
00155 {   (*this)="(" + String(r.real(),fmt) + "," + String(r.imag(),fmt) + ")"; }
00159 explicit String(std::complex<double> r, const char* fmt="%.15g")    
00160 {   (*this)="(" + String(r.real(),fmt) + "," + String(r.imag(),fmt) + ")"; }
00165 explicit String(std::complex<long double> r, const char* fmt="%.20Lg")  
00166 {   (*this)="(" + String(r.real(),fmt) + "," + String(r.imag(),fmt) + ")"; }
00167 
00170 explicit String(bool b) : std::string(b?"true":"false") { }
00171 
00176 template <class T> inline explicit String(const T& t); // see below
00177 
00180 template <class T> explicit
00181 String(const negator<T>& nt) {
00182     new (this) String(T(nt));
00183 }
00185 template <class T>
00186 String(const negator<T>& nt, const char* fmt) {
00187     new (this) String(T(nt), fmt);
00188 }
00189 
00192 template <class T> explicit
00193 String(const conjugate<T>& ct) {
00194     new (this) String(std::complex<T>(ct));
00195 }
00197 template <class T>
00198 String(const conjugate<T>& ct, const char* fmt) {
00199     new (this) String(std::complex<T>(ct), fmt);
00200 }
00201 
00202 
00235 template <class T> inline bool tryConvertTo(T& out) const; // see below
00236 
00243 template <class T> inline void convertTo(T& out) const; // see below
00244 
00251 template <class T> T convertTo() const 
00252 {   T temp; convertTo<T>(temp); return temp; }
00253 
00258 SimTK_SimTKCOMMON_EXPORT bool tryConvertToBool(bool& out) const;
00259 
00264 SimTK_SimTKCOMMON_EXPORT bool tryConvertToFloat(float& out) const;
00265 
00270 SimTK_SimTKCOMMON_EXPORT bool tryConvertToDouble(double& out) const;
00271 
00276 SimTK_SimTKCOMMON_EXPORT bool tryConvertToLongDouble(long double& out) const;
00289 SimTK_SimTKCOMMON_EXPORT String& toUpper();
00292 SimTK_SimTKCOMMON_EXPORT String& toLower();
00296 SimTK_SimTKCOMMON_EXPORT String& trimWhiteSpace();
00299 SimTK_SimTKCOMMON_EXPORT String& replaceAllChar(char oldChar, char newChar);
00309 static String toUpper(const std::string& in)
00310 {   return String(in).toUpper(); }
00313 static String toLower(const std::string& in)
00314 {   return String(in).toLower(); }
00319 static SimTK_SimTKCOMMON_EXPORT String trimWhiteSpace(const std::string& in);
00322 String& replaceAllChar(const std::string& in, char oldChar, char newChar)
00323 {   return String(in).replaceAllChar(oldChar, newChar); }
00326 };  
00327 
00328 // All std::stream activity should be dealt with inline so that we don't have
00329 // to worry about binary compatibility issues that can arise when passing 
00330 // streams through the API.
00331 
00334 template <class T> inline
00335 String::String(const T& t) {
00336     std::ostringstream stream;
00337     stream << t;
00338     *this = stream.str();
00339 }
00340 
00341 
00342 // This namespace-level static method should not be necessary but gcc 4.1
00343 // still has trouble with template specialization for template member
00344 // functions. So rather than specializing the tryConvertTo() member, I'm 
00345 // specializing this helper function instead.
00346 template <class T> inline static
00347 bool tryConvertStringTo(const String& value, T& out) {
00348     std::istringstream sstream(value);
00349     sstream >> out; if (sstream.fail()) return false;
00350     if (sstream.eof()) return true;
00351     // Successful conversion but didn't use all the characters. Maybe the
00352     // rest is just whitespace?
00353     std::ws(sstream);       // Skip trailing whitespace if any.
00354     return sstream.eof();   // We must have used up the whole string now.
00355 }
00356 
00357 // This specialization ensures that "true" and "false" are recognized as 
00358 // values for bools (with any case).
00359 template <> inline 
00360 bool tryConvertStringTo(const String& value, bool& out)
00361 {   return value.tryConvertToBool(out); }
00362 
00363 // Specialization to ensure recognition of non-finite values NaN, Inf, etc.
00364 template <> inline 
00365 bool tryConvertStringTo(const String& value, float& out)
00366 {   return value.tryConvertToFloat(out); }
00367 
00368 // Specialization to ensure recognition of non-finite values NaN, Inf, etc.
00369 template <> inline 
00370 bool tryConvertStringTo(const String& value, double& out)
00371 {   return value.tryConvertToDouble(out); }
00372 
00373 // Specialization to ensure recognition of non-finite values NaN, Inf, etc.
00374 template <> inline 
00375 bool tryConvertStringTo(const String& value, long double& out)
00376 {   return value.tryConvertToLongDouble(out); }
00377 
00378 // This specialization ensures that we get the whole String including
00379 // leading and trailing white space. Of course this is not useful for 
00380 // anything but may occur as a result of some higher-level templatized 
00381 // method that doesn't know what type it is converting here.
00382 template<> inline
00383 bool tryConvertStringTo(const String& value, String& out)
00384 {   out = value; return true; }
00385 
00386 // Same as above but for std::string output rather than String.
00387 template<> inline
00388 bool tryConvertStringTo(const String& value, std::string& out)
00389 {   out = value; return true; }
00390 
00392 template <class T> inline
00393 bool tryConvertStringTo(const String& value, negator<T>& out) {
00394     T nonnegated; 
00395     if (!tryConvertStringTo(value, nonnegated)) return false;
00396     out = nonnegated;
00397     return true;
00398 }
00399 
00401 template <class T> inline
00402 bool tryConvertStringTo(const String& value, conjugate<T>& out) {
00403     std::complex<T> cmplx; 
00404     if (!tryConvertStringTo(value, cmplx)) return false;
00405     out = cmplx;
00406     return true;
00407 }
00408 
00409 
00410 // This partial specialization ensures that you can't interpret
00411 // a String as a pointer.
00412 template<class T> inline static
00413 bool tryConvertStringTo(const String& value, T*& out) {
00414     SimTK_ERRCHK1_ALWAYS(false, "SimTK::convertStringTo(value,T*)",
00415         "Can't interpret a string as a pointer (%s*).",
00416         NiceTypeName<T>::name());
00417     return false; 
00418 }
00419 
00420 template <class T> inline bool 
00421 String::tryConvertTo(T& out) const 
00422 {   return tryConvertStringTo(*this, out); }
00423 
00424 template <class T> inline void 
00425 String::convertTo(T& out) const {
00426     const int MaxStr = 50;
00427     const bool convertOK = tryConvertTo<T>(out);
00428     if (convertOK) return;
00429 
00430     // Make sure we don't try to output more than MaxStr characters of
00431     // the bad string in the error message.
00432     String shorter = this->substr(0, MaxStr);
00433     if (shorter.size() < this->size()) shorter += " ...";
00434     SimTK_ERRCHK2_ALWAYS(convertOK, "String::convertTo()",
00435         "Couldn't interpret string '%s' as type T=%s.",
00436         shorter.c_str(), NiceTypeName<T>::name());
00437 }
00438 
00450 template <class T> inline static
00451 void convertStringTo(const String& in, T& out)
00452 {   in.convertTo<T>(out); }
00453 
00464 template <class T> inline static
00465 T convertStringTo(const String& in)
00466 {   return in.convertTo<T>(); }
00467 
00468 }
00469 #endif // SimTK_SimTKCOMMON_STRING_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines