Web Wispers 1.2.2 C++ Unit Test Coverage
Current view: top level - ssrc/wispers/utility - ToString.h (source / functions) Hit Total Coverage
Test: Web Wispers 1.2.2 C++ Unit Tests Lines: 34 37 91.9 %
Date: 2012-04-09 Functions: 23 27 85.2 %
Branches: 15 30 50.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright 2006-2009 Savarese Software Research Corporation
       3                 :            :  *
       4                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
       5                 :            :  * you may not use this file except in compliance with the License.
       6                 :            :  * You may obtain a copy of the License at
       7                 :            :  *
       8                 :            :  *     https://www.savarese.com/software/ApacheLicense-2.0
       9                 :            :  *
      10                 :            :  * Unless required by applicable law or agreed to in writing, software
      11                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
      12                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      13                 :            :  * See the License for the specific language governing permissions and
      14                 :            :  * limitations under the License.
      15                 :            :  */
      16                 :            : 
      17                 :            : /**
      18                 :            :  * @file
      19                 :            :  * This header defines the ToString class.
      20                 :            :  */
      21                 :            : 
      22                 :            : #ifndef __SSRC_WSPR_UTILITY_TO_STRING_H
      23                 :            : #define __SSRC_WSPR_UTILITY_TO_STRING_H
      24                 :            : 
      25                 :            : #include <ssrc/wispers-packages.h>
      26                 :            : 
      27                 :            : // Pull in std::bad_cast.
      28                 :            : #include <typeinfo>
      29                 :            : #include <sstream>
      30                 :            : 
      31                 :            : // TODO: Determine if it's possible to use a static buffer in
      32                 :            : // configure.ac based on diagnostic test programs instead of
      33                 :            : // hardcoding a specific compiler and version check.
      34                 :            : #if defined(__GNUC__) && (__GNUC__ >= 4)
      35                 :            : #define __WSPR_LEXICAL_CAST_USE_STATIC_BUFFER
      36                 :            : #endif
      37                 :            : 
      38                 :            : #ifdef __WSPR_LEXICAL_CAST_USE_STATIC_BUFFER
      39                 :            : #include <type_traits>
      40                 :            : #endif
      41                 :            : 
      42                 :            : __BEGIN_NS_SSRC_WSPR_UTILITY
      43                 :            : 
      44                 :            : using std::string;
      45                 :            : using std::ostringstream;
      46                 :            : 
      47                 :            : /**
      48                 :            :  * ToString is a convenience class for converting non-string types
      49                 :            :  * to strings.  Even though this functionality (and more) is provided
      50                 :            :  * by boost::lexical_cast, that implementation uses a free-function
      51                 :            :  * and does not allow you to hold on to a casting object.  Therefore,
      52                 :            :  * it reinstantiates a stringstream (and possibly other objects) on
      53                 :            :  * every use.  ToString is meant to be used in situations where
      54                 :            :  * you will be repeatedly converting numbers to strings (such as in a
      55                 :            :  * loop or in a service call) and would like to avoid the overhead of
      56                 :            :  * the reinstantiation performed by boost::lexical_cast.
      57                 :            :  */
      58         [ +  - ]:        114 : class ToString {
      59                 :            :   // This is big enough to hold the string representations of a
      60                 :            :   // 128-bit integer.  If the representation is longer, the buffer
      61                 :            :   // will not be overrun, but the output will be truncated.
      62                 :            : #ifdef __WSPR_LEXICAL_CAST_USE_STATIC_BUFFER
      63                 :            :   char _buffer[64];
      64                 :            : #endif
      65                 :            :   string _str;
      66                 :            :   ostringstream _ostream;
      67                 :            : 
      68                 :            : #ifdef __WSPR_LEXICAL_CAST_USE_STATIC_BUFFER
      69                 :        218 :   void set_static_buffer() {
      70                 :        218 :     _ostream.rdbuf()->pubsetbuf(_buffer, sizeof(_buffer));
      71                 :        218 :   }
      72                 :            : 
      73                 :         20 :   template<typename T> const string & cast_to_string(const T & obj,
      74                 :            :                                                      const std::true_type &)
      75                 :            :     SSRC_DECL_THROW(std::bad_cast)
      76                 :            :   {
      77                 :         20 :     _ostream.seekp(0);
      78                 :            : 
      79   [ -  +  -  + ]:         20 :     if(!(_ostream << obj))
      80                 :          0 :       throw std::bad_cast();
      81                 :            : 
      82                 :         20 :     _str.assign(_buffer,
      83                 :            :                 std::min(static_cast<std::streampos>(sizeof(_buffer)),
      84                 :            :                          _ostream.tellp()));
      85                 :         20 :     return _str;
      86                 :            :   }
      87                 :            : 
      88                 :          1 :   template<typename T> const char * cast_to_c_str(const T & obj,
      89                 :            :                                                   const std::true_type &)
      90                 :            :     SSRC_DECL_THROW(std::bad_cast)
      91                 :            :   {
      92                 :          1 :     _ostream.seekp(0);
      93                 :            : 
      94         [ -  + ]:          1 :     if(!(_ostream << obj))
      95                 :          0 :       throw std::bad_cast();
      96                 :            : 
      97                 :          1 :     _buffer[std::min(static_cast<std::streampos>(sizeof(_buffer) - 1),
      98                 :            :                      _ostream.tellp())] = 0;
      99                 :          1 :     return _buffer;
     100                 :            :   }
     101                 :            : #endif
     102                 :            : 
     103                 :        104 :   template<typename T> const string & cast_to_string(const T & obj
     104                 :            : #ifdef __WSPR_LEXICAL_CAST_USE_STATIC_BUFFER
     105                 :            :                                                      , const std::false_type &
     106                 :            : #endif
     107                 :            :                                                      )
     108                 :            :     SSRC_DECL_THROW(std::bad_cast)
     109                 :            :   {
     110   [ +  -  +  -  :        104 :     _ostream.str("");
                   +  - ]
     111                 :            : 
     112         [ -  + ]:        104 :     if(!(_ostream << obj))
     113                 :          0 :       throw std::bad_cast();
     114                 :            : 
     115         [ +  - ]:        104 :     _str.assign(_ostream.str());
     116                 :            : 
     117                 :            : #ifdef __WSPR_LEXICAL_CAST_USE_STATIC_BUFFER
     118                 :        104 :     set_static_buffer();
     119                 :            : #endif
     120                 :        104 :     return _str;
     121                 :            :   }
     122                 :            : 
     123                 :            :   template<typename T> const char * cast_to_c_str(const T & obj
     124                 :            : #ifdef __WSPR_LEXICAL_CAST_USE_STATIC_BUFFER
     125                 :            :                                                   , const std::false_type &
     126                 :            : #endif
     127                 :            :                                                   )
     128                 :            :     SSRC_DECL_THROW(std::bad_cast)
     129                 :            :   {
     130                 :            :     _ostream.str("");
     131                 :            : 
     132                 :            :     if(!(_ostream << obj))
     133                 :            :       throw std::bad_cast();
     134                 :            : 
     135                 :            :     _str.assign(_ostream.str());
     136                 :            : 
     137                 :            : #ifdef __WSPR_LEXICAL_CAST_USE_STATIC_BUFFER
     138                 :            :     set_static_buffer();
     139                 :            : #endif
     140                 :            :     return _str.c_str();
     141                 :            :   }
     142                 :            : 
     143                 :            : public:
     144                 :            :   typedef ostringstream::fmtflags fmtflags;
     145                 :            :   typedef ostringstream::iostate iostate;
     146                 :            : 
     147                 :            :   ToString(const ToString &) {
     148                 :            : #ifdef __WSPR_LEXICAL_CAST_USE_STATIC_BUFFER
     149                 :            :     set_static_buffer();
     150                 :            : #endif
     151                 :            :   }
     152                 :            : 
     153         [ +  - ]:        114 :   ToString() {
     154                 :            : #ifdef __WSPR_LEXICAL_CAST_USE_STATIC_BUFFER
     155         [ +  - ]:        114 :     set_static_buffer();
     156                 :            : #endif
     157                 :        114 :   }
     158                 :            : 
     159                 :            :   /**
     160                 :            :    * Converts an object to a string.  Be careful of constructs
     161                 :            :    * such as foo.append(_string_cast(bar)).append(_string_cast(baz))
     162                 :            :    * because the cast returns a reference and the compiler may order
     163                 :            :    * calls in such a way that both appends end up with the same value.
     164                 :            :    *
     165                 :            :    * @param T The type of the object to convert.  It must define the
     166                 :            :    * << operator for use with an ostream.
     167                 :            :    * @param obj The object to convert.
     168                 :            :    * @return A string representation of the object.
     169                 :            :    */
     170                 :            : #ifdef __WSPR_LEXICAL_CAST_USE_STATIC_BUFFER
     171                 :        124 :   template<typename T> const string & operator()(const T & obj)
     172                 :            :     SSRC_DECL_THROW(std::bad_cast)
     173                 :            :   {
     174                 :        124 :     return cast_to_string(obj, std::is_fundamental<T>());
     175                 :            :   }
     176                 :            : 
     177                 :          1 :   template<typename T> const char * c_str(const T & obj)
     178                 :            :     SSRC_DECL_THROW(std::bad_cast)
     179                 :            :   {
     180                 :          1 :     return cast_to_c_str(obj, std::is_fundamental<T>());
     181                 :            :   }
     182                 :            : #else
     183                 :            :   template<typename T> const string & operator()(const T & obj)
     184                 :            :     SSRC_DECL_THROW(std::bad_cast)
     185                 :            :   {
     186                 :            :     return cast_to_string(obj);
     187                 :            :   }
     188                 :            : 
     189                 :            :   template<typename T> const char * c_str(const T & obj)
     190                 :            :     SSRC_DECL_THROW(std::bad_cast)
     191                 :            :   {
     192                 :            :     return cast_to_c_str(obj);
     193                 :            :   }
     194                 :            : #endif
     195                 :            : 
     196                 :            :   fmtflags flags() const {
     197                 :            :     return _ostream.flags();
     198                 :            :   }
     199                 :            : 
     200                 :            :   fmtflags flags(const fmtflags flags) {
     201                 :            :     return _ostream.flags(flags);
     202                 :            :   }
     203                 :            : 
     204                 :          1 :   fmtflags setf(const fmtflags flags) {
     205                 :          1 :     return _ostream.setf(flags);
     206                 :            :   }
     207                 :            : 
     208                 :          1 :   fmtflags setf(const fmtflags flags,
     209                 :            :                                const fmtflags mask)
     210                 :            :   {
     211                 :          1 :     return _ostream.setf(flags, mask);
     212                 :            :   }
     213                 :            : 
     214                 :            :   void unsetf(const fmtflags flags) {
     215                 :            :     _ostream.unsetf(flags);
     216                 :            :   }
     217                 :            : 
     218                 :            :   iostate rdstate() const {
     219                 :            :     return _ostream.rdstate();
     220                 :            :   }
     221                 :            : 
     222                 :            :   void clear(iostate state = ostringstream::goodbit) {
     223                 :            :     _ostream.clear(state);
     224                 :            :   }
     225                 :            : 
     226                 :            :   void setstate(iostate state) {
     227                 :            :     _ostream.setstate(state);
     228                 :            :   }
     229                 :            : 
     230                 :            : };
     231                 :            : 
     232                 :            : #ifdef __WSPR_LEXICAL_CAST_USE_STATIC_BUFFER
     233                 :            : #undef __WSPR_LEXICAL_CAST_USE_STATIC_BUFFER
     234                 :            : #endif
     235                 :            : 
     236                 :            : // Only intended for primitive types, otherwise static buffer may
     237                 :            : // be too small.  Should really specialize behavior based on
     238                 :            : // primitive type.
     239                 :            : template<typename T>
     240                 :        105 : inline string to_string(const T & obj)
     241                 :            :   SSRC_DECL_THROW(std::bad_cast)
     242                 :            : {
     243                 :        210 :   ToString string_cast;
     244   [ +  -  +  -  :        210 :   return string_cast(obj);
             +  -  +  - ]
     245                 :            : }
     246                 :            : 
     247                 :            : template<>
     248                 :            : inline string to_string<string>(const string & obj)
     249                 :            :   SSRC_DECL_THROW(std::bad_cast)
     250                 :            : {
     251                 :            :   return obj;
     252                 :            : }
     253                 :            : 
     254                 :            : template<>
     255                 :            : inline string to_string<char *>(char * const & obj)
     256                 :            :   SSRC_DECL_THROW(std::bad_cast)
     257                 :            : {
     258                 :            :   return obj;
     259                 :            : }
     260                 :            : 
     261                 :            : __END_NS_SSRC_WSPR_UTILITY
     262                 :            : 
     263                 :            : #endif