Simbody  3.5
String.h
Go to the documentation of this file.
1 #ifndef SimTK_SimTKCOMMON_STRING_H_
2 #define SimTK_SimTKCOMMON_STRING_H_
3 
4 /* -------------------------------------------------------------------------- *
5  * Simbody(tm): SimTKcommon *
6  * -------------------------------------------------------------------------- *
7  * This is part of the SimTK biosimulation toolkit originating from *
8  * Simbios, the NIH National Center for Physics-Based Simulation of *
9  * Biological Structures at Stanford, funded under the NIH Roadmap for *
10  * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody. *
11  * *
12  * Portions copyright (c) 2005-12 Stanford University and the Authors. *
13  * Authors: Michael Sherman *
14  * Contributors: *
15  * *
16  * Licensed under the Apache License, Version 2.0 (the "License"); you may *
17  * not use this file except in compliance with the License. You may obtain a *
18  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. *
19  * *
20  * Unless required by applicable law or agreed to in writing, software *
21  * distributed under the License is distributed on an "AS IS" BASIS, *
22  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
23  * See the License for the specific language governing permissions and *
24  * limitations under the License. *
25  * -------------------------------------------------------------------------- */
26 
27 // Keeps MS VC++ 8 quiet about sprintf, strcpy, etc.
28 #ifdef _MSC_VER
29 #pragma warning(disable:4996)
30 #endif
31 
32 
35 
36 #include <cstdio>
37 #include <string>
38 #include <limits>
39 #include <complex>
40 #include <sstream>
41 
42 namespace SimTK {
43 
44 template <class N> class negator;
45 template <class R> class conjugate;
46 
62 class String : public std::string {
63 public:
64 
66 String() { }
67 
68 // uses default copy constructor, copy assignment, and destructor
69 
71 String(const char* s) : std::string(s) { }
72 
74 explicit String(char c) {push_back(c);}
75 
77 String(const std::string& s) : std::string(s) { }
78 
81 String(const String& s, int start, int len) : std::string(s,start,len) { }
82 
85 operator const char*() const { return c_str(); }
86 
88 char& operator[](int i) {
89  assert(i >= 0);
90  return std::string::operator[]((std::string::size_type)i);
91 }
92 
94 char operator[](int i) const {
95  assert(i >= 0);
96  return std::string::operator[]((std::string::size_type)i);
97 }
98 
100 char& operator[](std::string::size_type i) {return std::string::operator[](i);}
102 char operator[](std::string::size_type i) const {return std::string::operator[](i);}
103 
106 int size() const {return (int)std::string::size();}
107 
110 int length() const {return (int)std::string::length();}
111 
120 explicit String(int i, const char* fmt="%d")
121 { char buf[32]; sprintf(buf,fmt,i); (*this)=buf; }
123 explicit String(long i, const char* fmt="%ld")
124 { char buf[64]; sprintf(buf,fmt,i); (*this)=buf; }
126 explicit String(long long i, const char* fmt="%lld")
127 { char buf[64]; sprintf(buf,fmt,i); (*this)=buf; }
129 explicit String(unsigned int s, const char* fmt="%u")
130 { char buf[32]; sprintf(buf,fmt,s); (*this)=buf; }
132 explicit String(unsigned long s, const char* fmt="%lu")
133 { char buf[64]; sprintf(buf,fmt,s); (*this)=buf; }
135 explicit String(unsigned long long s, const char* fmt="%llu")
136 { char buf[64]; sprintf(buf,fmt,s); (*this)=buf; }
137 
140 SimTK_SimTKCOMMON_EXPORT explicit String(float r, const char* fmt="%.7g");
141 
144 SimTK_SimTKCOMMON_EXPORT explicit String(double r, const char* fmt="%.15g");
145 
148 SimTK_SimTKCOMMON_EXPORT explicit String(long double r,
149  const char* fmt="%.20Lg");
150 
154 explicit String(std::complex<float> r, const char* fmt="%.7g")
155 { (*this)="(" + String(r.real(),fmt) + "," + String(r.imag(),fmt) + ")"; }
159 explicit String(std::complex<double> r, const char* fmt="%.15g")
160 { (*this)="(" + String(r.real(),fmt) + "," + String(r.imag(),fmt) + ")"; }
165 explicit String(std::complex<long double> r, const char* fmt="%.20Lg")
166 { (*this)="(" + String(r.real(),fmt) + "," + String(r.imag(),fmt) + ")"; }
167 
170 explicit String(bool b) : std::string(b?"true":"false") { }
171 
176 template <class T> inline explicit String(const T& t); // see below
177 
180 template <class T> explicit
181 String(const negator<T>& nt) {
182  new (this) String(T(nt));
183 }
185 template <class T>
186 String(const negator<T>& nt, const char* fmt) {
187  new (this) String(T(nt), fmt);
188 }
189 
192 template <class T> explicit
193 String(const conjugate<T>& ct) {
194  new (this) String(std::complex<T>(ct));
195 }
197 template <class T>
198 String(const conjugate<T>& ct, const char* fmt) {
199  new (this) String(std::complex<T>(ct), fmt);
200 }
201 
202 
235 template <class T> inline bool tryConvertTo(T& out) const; // see below
236 
243 template <class T> inline void convertTo(T& out) const; // see below
244 
251 template <class T> T convertTo() const
252 { T temp; convertTo<T>(temp); return temp; }
253 
258 SimTK_SimTKCOMMON_EXPORT bool tryConvertToBool(bool& out) const;
259 
264 SimTK_SimTKCOMMON_EXPORT bool tryConvertToFloat(float& out) const;
265 
270 SimTK_SimTKCOMMON_EXPORT bool tryConvertToDouble(double& out) const;
271 
276 SimTK_SimTKCOMMON_EXPORT bool tryConvertToLongDouble(long double& out) const;
299 SimTK_SimTKCOMMON_EXPORT String& replaceAllChar(char oldChar, char newChar);
309 static String toUpper(const std::string& in)
310 { return String(in).toUpper(); }
313 static String toLower(const std::string& in)
314 { return String(in).toLower(); }
319 static SimTK_SimTKCOMMON_EXPORT String trimWhiteSpace(const std::string& in);
322 String& replaceAllChar(const std::string& in, char oldChar, char newChar)
323 { return String(in).replaceAllChar(oldChar, newChar); }
326 };
327 
328 // All std::stream activity should be dealt with inline so that we don't have
329 // to worry about binary compatibility issues that can arise when passing
330 // streams through the API.
331 
334 template <class T> inline
335 String::String(const T& t) {
336  std::ostringstream stream;
337  stream << t;
338  *this = stream.str();
339 }
340 
341 
342 // This namespace-level static method should not be necessary but gcc 4.1
343 // still has trouble with template specialization for template member
344 // functions. So rather than specializing the tryConvertTo() member, I'm
345 // specializing this helper function instead.
346 template <class T> inline static
347 bool tryConvertStringTo(const String& value, T& out) {
348  std::istringstream sstream(value);
349  sstream >> out; if (sstream.fail()) return false;
350  if (sstream.eof()) return true;
351  // Successful conversion but didn't use all the characters. Maybe the
352  // rest is just whitespace?
353  std::ws(sstream); // Skip trailing whitespace if any.
354  return sstream.eof(); // We must have used up the whole string now.
355 }
356 
357 // This specialization ensures that "true" and "false" are recognized as
358 // values for bools (with any case).
359 template <> inline
360 bool tryConvertStringTo(const String& value, bool& out)
361 { return value.tryConvertToBool(out); }
362 
363 // Specialization to ensure recognition of non-finite values NaN, Inf, etc.
364 template <> inline
365 bool tryConvertStringTo(const String& value, float& out)
366 { return value.tryConvertToFloat(out); }
367 
368 // Specialization to ensure recognition of non-finite values NaN, Inf, etc.
369 template <> inline
370 bool tryConvertStringTo(const String& value, double& out)
371 { return value.tryConvertToDouble(out); }
372 
373 // Specialization to ensure recognition of non-finite values NaN, Inf, etc.
374 template <> inline
375 bool tryConvertStringTo(const String& value, long double& out)
376 { return value.tryConvertToLongDouble(out); }
377 
378 // This specialization ensures that we get the whole String including
379 // leading and trailing white space. Of course this is not useful for
380 // anything but may occur as a result of some higher-level templatized
381 // method that doesn't know what type it is converting here.
382 template<> inline
383 bool tryConvertStringTo(const String& value, String& out)
384 { out = value; return true; }
385 
386 // Same as above but for std::string output rather than String.
387 template<> inline
388 bool tryConvertStringTo(const String& value, std::string& out)
389 { out = value; return true; }
390 
392 template <class T> inline
393 bool tryConvertStringTo(const String& value, negator<T>& out) {
394  T nonnegated;
395  if (!tryConvertStringTo(value, nonnegated)) return false;
396  out = nonnegated;
397  return true;
398 }
399 
401 template <class T> inline
402 bool tryConvertStringTo(const String& value, conjugate<T>& out) {
403  std::complex<T> cmplx;
404  if (!tryConvertStringTo(value, cmplx)) return false;
405  out = cmplx;
406  return true;
407 }
408 
409 
410 // This partial specialization ensures that you can't interpret
411 // a String as a pointer.
412 template<class T> inline static
413 bool tryConvertStringTo(const String& value, T*& out) {
414  SimTK_ERRCHK1_ALWAYS(false, "SimTK::convertStringTo(value,T*)",
415  "Can't interpret a string as a pointer (%s*).",
416  NiceTypeName<T>::namestr().c_str());
417  return false;
418 }
419 
420 template <class T> inline bool
421 String::tryConvertTo(T& out) const
422 { return tryConvertStringTo(*this, out); }
423 
424 template <class T> inline void
425 String::convertTo(T& out) const {
426  const int MaxStr = 50;
427  const bool convertOK = tryConvertTo<T>(out);
428  if (convertOK) return;
429 
430  // Make sure we don't try to output more than MaxStr characters of
431  // the bad string in the error message.
432  String shorter = this->substr(0, MaxStr);
433  if (shorter.size() < this->size()) shorter += " ...";
434  SimTK_ERRCHK2_ALWAYS(convertOK, "String::convertTo()",
435  "Couldn't interpret string '%s' as type T=%s.",
436  shorter.c_str(), NiceTypeName<T>::namestr().c_str());
437 }
438 
450 template <class T> inline static
451 void convertStringTo(const String& in, T& out)
452 { in.convertTo<T>(out); }
453 
464 template <class T> inline static
466 { return in.convertTo<T>(); }
467 
468 }
469 #endif // SimTK_SimTKCOMMON_STRING_H_
char operator[](std::string::size_type i) const
Pass through to string::operator[].
Definition: String.h:102
String & replaceAllChar(const std::string &in, char oldChar, char newChar)
Copy the input std::string to a new SimTK::String while substituting newChar for oldChar wherever old...
Definition: String.h:322
String(unsigned long long s, const char *fmt="%llu")
Format an unsigned long long as a printable String.
Definition: String.h:135
bool tryConvertToBool(bool &out) const
Special-purpose method for interpreting this String as a bool.
String(long i, const char *fmt="%ld")
Format a long as a printable String.
Definition: String.h:123
#define SimTK_SimTKCOMMON_EXPORT
Definition: SimTKcommon/include/SimTKcommon/internal/common.h:218
String(unsigned long s, const char *fmt="%lu")
Format an unsigned long as a printable String.
Definition: String.h:132
String(std::complex< double > r, const char *fmt="%.15g")
Format a complex<double> as a printable String (real,imag) with parentheses and a comma as shown...
Definition: String.h:159
This is the top-level SimTK namespace into which all SimTK names are placed to avoid collision with o...
Definition: Assembler.h:37
SimTK::conjugate<R> should be instantiated only for float, double, long double.
Definition: String.h:45
bool tryConvertTo(T &out) const
Attempt to convert this String to an object of type T, returning a status value to indicate success o...
Definition: String.h:421
void convertTo(T &out) const
Convert this String to an object of type T using the tryConvertTo<T>() method but throwing an error o...
Definition: String.h:425
bool tryConvertToLongDouble(long double &out) const
Special-purpose method for interpreting this String as a long double.
static void convertStringTo(const String &in, T &out)
This method converts its String argument to type T and returns it into the variable supplied as its s...
Definition: String.h:451
bool tryConvertToFloat(float &out) const
Special-purpose method for interpreting this String as a float.
static std::string namestr()
The default implementation of namestr() attempts to return a nicely demangled type name on all platfo...
Definition: SimTKcommon/include/SimTKcommon/internal/common.h:769
char & operator[](int i)
Add operator[] that takes int index instead of size_type.
Definition: String.h:88
String(const conjugate< T > &ct, const char *fmt)
Same, but allows for format specification.
Definition: String.h:198
STL namespace.
String(long long i, const char *fmt="%lld")
Format a long long as a printable String.
Definition: String.h:126
#define SimTK_ERRCHK2_ALWAYS(cond, whereChecked, fmt, a1, a2)
Definition: ExceptionMacros.h:289
int length() const
Override std::string length() method to return an int instead of the inconvenient unsigned type size_...
Definition: String.h:110
negator<N>, where N is a number type (real, complex, conjugate), is represented in memory identically...
Definition: String.h:44
String(char c)
We allow creating a String from a char but you have to do it explicitly.
Definition: String.h:74
String(std::complex< float > r, const char *fmt="%.7g")
Format a complex<float> as a printable String (real,imag) with parentheses and a comma as shown...
Definition: String.h:154
This file contains macros which are convenient to use for sprinkling error checking around liberally ...
String(unsigned int s, const char *fmt="%u")
Format an unsigned int as a printable String.
Definition: String.h:129
int size() const
Override std::string size() method to return an int instead of the inconvenient unsigned type size_ty...
Definition: String.h:106
String(const negator< T > &nt)
Constructing a String from a negated value converts to the underlying native type and then uses one o...
Definition: String.h:181
#define SimTK_ERRCHK1_ALWAYS(cond, whereChecked, fmt, a1)
Definition: ExceptionMacros.h:285
char operator[](int i) const
Add operator[] that takes int index instead of size_type.
Definition: String.h:94
String & toLower()
Downshift the given String in place, so that uppercase letters are replaced with their lowercase equi...
String(const String &s, int start, int len)
Construct a String as a copy of a substring begining at position start with length len...
Definition: String.h:81
String & replaceAllChar(char oldChar, char newChar)
Substitute in place newChar for oldChar wherever oldChar appears in this String.
String(int i, const char *fmt="%d")
Format an int as a printable String.
Definition: String.h:120
bool tryConvertToDouble(double &out) const
Special-purpose method for interpreting this String as a double.
SimTK::String is a plug-compatible std::string replacement (plus some additional functionality) inten...
Definition: String.h:62
char & operator[](std::string::size_type i)
Pass through to string::operator[].
Definition: String.h:100
Mandatory first inclusion for any Simbody source or header file.
static T convertStringTo(const String &in)
This method converts its String argument to type T and returns it as its function value; this is part...
Definition: String.h:465
In case you don&#39;t like the name you get from typeid(), you can specialize this class to provide a nic...
Definition: SimTKcommon/include/SimTKcommon/internal/common.h:761
static String toLower(const std::string &in)
Downshift the given std::string returning a new SimTK::String in which all the letters have be made l...
Definition: String.h:313
String(const negator< T > &nt, const char *fmt)
Same, but allows for format specification.
Definition: String.h:186
String & trimWhiteSpace()
Trim this String in place, removing all the initial leading and trailing white space, as defined by std::isspace() which typically includes space, tab (\t), newline (\n), return (\r), and form feed (\f).
T convertTo() const
A more convenient form of convertTo<T>() that returns the result as its function argument, although this may involve an extra copy operation.
Definition: String.h:251
String & toUpper()
Upshift the given String in place, so that lowercase letters are replaced with their uppercase equiva...
String(bool b)
Format a bool as a printable String "true" or "false"; if you want "1" or "0" cast the bool to an int...
Definition: String.h:170
String(std::complex< long double > r, const char *fmt="%.20Lg")
Format a complex<long double> as a printable String (real,imag) with parentheses and a comma as shown...
Definition: String.h:165
String(const char *s)
This is an implicit conversion from const char* to String.
Definition: String.h:71
String()
Default constructor produces an empty string.
Definition: String.h:66
static String toUpper(const std::string &in)
Upshift the given std::string returning a new SimTK::String in which all the letters have been made u...
Definition: String.h:309
String(const std::string &s)
This is an implicit conversion from std::string to String.
Definition: String.h:77
String(const conjugate< T > &ct)
Constructing a String from a conjugate value converts to the underlying complex type and then uses on...
Definition: String.h:193
static bool tryConvertStringTo(const String &value, T &out)
Definition: String.h:347