Simbody 3.9
Loading...
Searching...
No Matches
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-15 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
29#include "SimTKcommon/Scalar.h"
30
31#include <iomanip>
32#include <cstdio>
33#include <string>
34#include <limits>
35#include <complex>
36#include <sstream>
37
38// Keeps MS VC++ quiet about sprintf, strcpy, etc.
39#ifdef _MSC_VER
40#pragma warning(push)
41#pragma warning(disable:4996)
42#endif
43
44namespace SimTK {
45
46template <class N> class negator;
47template <class R> class conjugate;
48
64class String : public std::string {
65public:
66
68String() { }
69
70// uses default copy constructor, copy assignment, and destructor
71
73String(const char* s) : std::string(s) { }
74
76explicit String(char c) {push_back(c);}
77
79String(const std::string& s) : std::string(s) { }
80
83String(const String& s, int start, int len) : std::string(s,start,len) { }
84
87operator const char*() const { return c_str(); }
88
90char& operator[](int i) {
91 assert(i >= 0);
92 return std::string::operator[]((std::string::size_type)i);
93}
94
96char operator[](int i) const {
97 assert(i >= 0);
98 return std::string::operator[]((std::string::size_type)i);
99}
100
102char& operator[](std::string::size_type i) {return std::string::operator[](i);}
104char operator[](std::string::size_type i) const {return std::string::operator[](i);}
105
108int size() const {return (int)std::string::size();}
109
112int length() const {return (int)std::string::length();}
113
122explicit String(int i, const char* fmt="%d")
123{ const int n=32; char buf[n]; snprintf(buf,n,fmt,i); (*this)=buf; }
125explicit String(long i, const char* fmt="%ld")
126{ const int n=64; char buf[n]; snprintf(buf,n,fmt,i); (*this)=buf; }
128explicit String(long long i, const char* fmt="%lld")
129{ const int n=64; char buf[n]; snprintf(buf,n,fmt,i); (*this)=buf; }
131explicit String(unsigned int s, const char* fmt="%u")
132{ const int n=32; char buf[n]; snprintf(buf,n,fmt,s); (*this)=buf; }
134explicit String(unsigned long s, const char* fmt="%lu")
135{ const int n=64; char buf[n]; snprintf(buf,n,fmt,s); (*this)=buf; }
137explicit String(unsigned long long s, const char* fmt="%llu")
138{ const int n=64; char buf[n]; snprintf(buf,n,fmt,s); (*this)=buf; }
139
144SimTK_SimTKCOMMON_EXPORT explicit String(float r, const char* fmt="%.9g");
145
150SimTK_SimTKCOMMON_EXPORT explicit String(double r, const char* fmt="%.17g");
151
155explicit String(std::complex<float> r, const char* fmt="%.9g")
156{ (*this)="(" + String(r.real(),fmt) + "," + String(r.imag(),fmt) + ")"; }
160explicit String(std::complex<double> r, const char* fmt="%.17g")
161{ (*this)="(" + String(r.real(),fmt) + "," + String(r.imag(),fmt) + ")"; }
162
165explicit String(bool b) : std::string(b?"true":"false") { }
166
173template <class T> inline explicit
174String(const T& t);
175
185template <class T> inline explicit
186String(const T& t, int precision);
187
190template <class T> explicit
191String(const negator<T>& nt) {
192 new (this) String(T(nt));
193}
195template <class T>
196String(const negator<T>& nt, const char* fmt) {
197 new (this) String(T(nt), fmt);
198}
199
202template <class T> explicit
204 new (this) String(std::complex<T>(ct));
205}
207template <class T>
208String(const conjugate<T>& ct, const char* fmt) {
209 new (this) String(std::complex<T>(ct), fmt);
210}
211
212
245template <class T> inline bool tryConvertTo(T& out) const; // see below
246
253template <class T> inline void convertTo(T& out) const; // see below
254
261template <class T> T convertTo() const
262{ T temp; convertTo<T>(temp); return temp; }
263
269
275
303SimTK_SimTKCOMMON_EXPORT String& replaceAllChar(char oldChar, char newChar);
313static String toUpper(const std::string& in)
314{ return String(in).toUpper(); }
317static String toLower(const std::string& in)
318{ return String(in).toLower(); }
323static SimTK_SimTKCOMMON_EXPORT String trimWhiteSpace(const std::string& in);
326String& replaceAllChar(const std::string& in, char oldChar, char newChar)
327{ return String(in).replaceAllChar(oldChar, newChar); }
330};
331
332// All std::stream activity should be dealt with inline so that we don't have
333// to worry about binary compatibility issues that can arise when passing
334// streams through the API.
335
// Hide from Doxygen
337template <class T> inline
338auto stringStreamInsertHelper(std::ostringstream& os, const T& t, bool)
339 -> decltype(static_cast<std::ostringstream&>(os << t)) {
340 os << t;
341 return os;
342}
343
344
345template <class T> inline
346auto stringStreamInsertHelper(std::ostringstream& os, const T& t, int)
347 -> std::ostringstream& {
348 SimTK_ERRCHK1_ALWAYS(!"no stream insertion operator", "String::String(T)",
349 "Type T=%s has no stream insertion operator<<(T) and there "
350 "is no specialized String(T) constructor.",
351 NiceTypeName<T>::namestr().c_str());
352 return os;
353}
354
355template <class T> inline
356auto stringStreamExtractHelper(std::istringstream& is, T& t, bool)
357 -> decltype(static_cast<std::istringstream&>(is >> t)) {
358 is >> t;
359 return is;
360}
361
362template <class T> inline
363auto stringStreamExtractHelper(std::istringstream& is, T& t, int)
364 -> std::istringstream& {
365 SimTK_ERRCHK1_ALWAYS(!"no stream extraction operator",
366 "String::tryConvertTo<T>()",
367 "Type T=%s has no stream extraction operator>>(T) and there "
368 "is no specialized tryConvertTo<T>() constructor.",
369 NiceTypeName<T>::namestr().c_str());
370 return is;
371}
372
375// Implementation of the generic templatized String constructor.
376template <class T> inline
377String::String(const T& t) {
378 std::ostringstream os;
379 *this = stringStreamInsertHelper(os, t, true).str();
380}
381
382// Implementation of the generic templatized String constructor
383// with precision.
384// To ensure consistent behavior of ostream::setprecision() across operating
385// systems and whether a build is debug or release, precision is bounded:
386// 1 <= precision <= SimTK::LosslessNumDigitsReal
387template <class T> inline
388String::String(const T& t, int precision) {
389 std::ostringstream os;
390 if(precision < 1)
391 precision = 1;
392 else if(precision > SimTK::LosslessNumDigitsReal)
394 os << std::setprecision(precision);
395 *this = stringStreamInsertHelper(os, t, true).str();
396}
397
398
399// This namespace-level static method should not be necessary but gcc 4.1
400// still has trouble with template specialization for template member
401// functions. So rather than specializing the tryConvertTo() member, I'm
402// specializing this helper function instead.
403template <class T> inline static
404bool tryConvertStringTo(const String& value, T& out) {
405 std::istringstream sstream(value);
406 stringStreamExtractHelper(sstream, out, true);
407 if (sstream.fail()) return false;
408 if (sstream.eof()) return true;
409 // Successful conversion but didn't use all the characters. Maybe the
410 // rest is just whitespace?
411 std::ws(sstream); // Skip trailing whitespace if any.
412 return sstream.eof(); // We must have used up the whole string now.
413}
414
415// This specialization ensures that "true" and "false" are recognized as
416// values for bools (with any case).
417template <> inline
418bool tryConvertStringTo(const String& value, bool& out)
419{ return value.tryConvertToBool(out); }
420
421// Specialization to ensure recognition of non-finite values NaN, Inf, etc.
422template <> inline
423bool tryConvertStringTo(const String& value, float& out)
424{ return value.tryConvertToFloat(out); }
425
426// Specialization to ensure recognition of non-finite values NaN, Inf, etc.
427template <> inline
428bool tryConvertStringTo(const String& value, double& out)
429{ return value.tryConvertToDouble(out); }
430
431// This specialization ensures that we get the whole String including
432// leading and trailing white space. Of course this is not useful for
433// anything but may occur as a result of some higher-level templatized
434// method that doesn't know what type it is converting here.
435template<> inline
436bool tryConvertStringTo(const String& value, String& out)
437{ out = value; return true; }
438
439// Same as above but for std::string output rather than String.
440template<> inline
441bool tryConvertStringTo(const String& value, std::string& out)
442{ out = value; return true; }
443
445template <class T> inline
446bool tryConvertStringTo(const String& value, negator<T>& out) {
447 T nonnegated;
448 if (!tryConvertStringTo(value, nonnegated)) return false;
449 out = nonnegated;
450 return true;
451}
452
454template <class T> inline
455bool tryConvertStringTo(const String& value, conjugate<T>& out) {
456 std::complex<T> cmplx;
457 if (!tryConvertStringTo(value, cmplx)) return false;
458 out = cmplx;
459 return true;
460}
461
462
463// This partial specialization ensures that you can't interpret
464// a String as a pointer.
465template<class T> inline static
466bool tryConvertStringTo(const String& value, T*& out) {
467 SimTK_ERRCHK1_ALWAYS(false, "SimTK::convertStringTo(value,T*)",
468 "Can't interpret a string as a pointer (%s*).",
469 NiceTypeName<T>::namestr().c_str());
470 return false;
471}
472
473template <class T> inline bool
475{ return tryConvertStringTo(*this, out); }
476
477template <class T> inline void
478String::convertTo(T& out) const {
479 const int MaxStr = 50;
480 const bool convertOK = tryConvertTo<T>(out);
481 if (convertOK) return;
482
483 // Make sure we don't try to output more than MaxStr characters of
484 // the bad string in the error message.
485 String shorter = this->substr(0, MaxStr);
486 if (shorter.size() < this->size()) shorter += " ...";
487 SimTK_ERRCHK2_ALWAYS(convertOK, "String::convertTo()",
488 "Couldn't interpret string '%s' as type T=%s.",
489 shorter.c_str(), NiceTypeName<T>::namestr().c_str());
490}
491
503template <class T> inline static
504void convertStringTo(const String& in, T& out)
505{ in.convertTo<T>(out); }
506
517template <class T> inline static
519{ return in.convertTo<T>(); }
520
521} // namespace SimTK
522
523#ifdef _MSC_VER
524#pragma warning(pop)
525#endif
526
527#endif // SimTK_SimTKCOMMON_STRING_H_
This file contains macros which are convenient to use for sprinkling error checking around liberally ...
#define SimTK_ERRCHK2_ALWAYS(cond, whereChecked, fmt, a1, a2)
Definition ExceptionMacros.h:289
#define SimTK_ERRCHK1_ALWAYS(cond, whereChecked, fmt, a1)
Definition ExceptionMacros.h:285
This is a user-includable header which includes everything needed to make use of SimMatrix Scalar cod...
Mandatory first inclusion for any Simbody source or header file.
#define SimTK_SimTKCOMMON_EXPORT
Definition SimTKcommon/include/SimTKcommon/internal/common.h:224
SimTK::String is a plug-compatible std::string replacement (plus some additional functionality) inten...
Definition String.h:64
char operator[](std::string::size_type i) const
Pass through to string::operator[].
Definition String.h:104
int size() const
Override std::string size() method to return an int instead of the inconvenient unsigned type size_ty...
Definition String.h:108
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:317
String(const char *s)
This is an implicit conversion from const char* to String.
Definition String.h:73
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:203
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:504
String(const negator< T > &nt, const char *fmt)
Same, but allows for format specification.
Definition String.h:196
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:191
String(unsigned long s, const char *fmt="%lu")
Format an unsigned long as a printable String.
Definition String.h:134
String(char c)
We allow creating a String from a char but you have to do it explicitly.
Definition String.h:76
String(const conjugate< T > &ct, const char *fmt)
Same, but allows for format specification.
Definition String.h:208
String & toLower()
Downshift the given String in place, so that uppercase letters are replaced with their lowercase equi...
String(long long i, const char *fmt="%lld")
Format a long long as a printable String.
Definition String.h:128
String(std::complex< float > r, const char *fmt="%.9g")
Format a complex<float> as a printable String (real,imag) with parentheses and a comma as shown.
Definition String.h:155
String()
Default constructor produces an empty string.
Definition String.h:68
String & toUpper()
Upshift the given String in place, so that lowercase letters are replaced with their uppercase equiva...
bool tryConvertToDouble(double &out) const
Special-purpose method for interpreting this String as a double.
String(unsigned int s, const char *fmt="%u")
Format an unsigned int as a printable String.
Definition String.h:131
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:518
int length() const
Override std::string length() method to return an int instead of the inconvenient unsigned type size_...
Definition String.h:112
String(float r, const char *fmt="%.9g")
Format a float as a printable String.
String(const String &s, int start, int len)
Construct a String as a copy of a substring beginning at position start with length len.
Definition String.h:83
String(double r, const char *fmt="%.17g")
Format a double as a printable String.
String(std::complex< double > r, const char *fmt="%.17g")
Format a complex<double> as a printable String (real,imag) with parentheses and a comma as shown.
Definition String.h:160
char & operator[](int i)
Add operator[] that takes int index instead of size_type.
Definition String.h:90
String(const std::string &s)
This is an implicit conversion from std::string to String.
Definition String.h:79
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:326
bool tryConvertToBool(bool &out) const
Special-purpose method for interpreting this String as a bool.
String & trimWhiteSpace()
Trim this String in place, removing all the initial leading and trailing white space,...
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:474
static String trimWhiteSpace(const std::string &in)
Copy the input std::string to a new SimTK::String leaving off all the initial leading and trailing wh...
String(int i, const char *fmt="%d")
Format an int as a printable String.
Definition String.h:122
String & replaceAllChar(char oldChar, char newChar)
Substitute in place newChar for oldChar wherever oldChar appears in this String.
char & operator[](std::string::size_type i)
Pass through to string::operator[].
Definition String.h:102
String(long i, const char *fmt="%ld")
Format a long as a printable String.
Definition String.h:125
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:313
T convertTo() const
A more convenient form of convertTo<T>() that returns the result as its function argument,...
Definition String.h:261
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:478
String(unsigned long long s, const char *fmt="%llu")
Format an unsigned long long as a printable String.
Definition String.h:137
bool tryConvertToFloat(float &out) const
Special-purpose method for interpreting this String as a float.
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:165
char operator[](int i) const
Add operator[] that takes int index instead of size_type.
Definition String.h:96
SimTK::conjugate<R> should be instantiated only for float, double.
Definition conjugate.h:178
negator<N>, where N is a number type (real, complex, conjugate), is represented in memory identically...
Definition negator.h:75
constexpr int LosslessNumDigitsReal
This is the smallest number of decimal digits you should store in a text file if you want to be able ...
Definition Scalar.h:136
This is the top-level SimTK namespace into which all SimTK names are placed to avoid collision with o...
Definition Assembler.h:37
static bool tryConvertStringTo(const String &value, T &out)
Definition String.h:404
Obtain human-readable and XML-usable names for arbitrarily-complicated C++ types.
Definition SimTKcommon/include/SimTKcommon/internal/common.h:881
static const std::string & namestr()
The default implementation of namestr() attempts to return a nicely demangled and canonicalized type ...
Definition SimTKcommon/include/SimTKcommon/internal/common.h:890