format_wrap.hpp

Go to the documentation of this file.
00001 // Copyright (C) 2010 NICTA and the authors listed below
00002 // http://nicta.com.au
00003 // 
00004 // Authors:
00005 // - Conrad Sanderson (conradsand at ieee dot org)
00006 // 
00007 // This file is part of the Armadillo C++ library.
00008 // It is provided without any warranty of fitness
00009 // for any purpose. You can redistribute this file
00010 // and/or modify it under the terms of the GNU
00011 // Lesser General Public License (LGPL) as published
00012 // by the Free Software Foundation, either version 3
00013 // of the License or (at your option) any later version.
00014 // (see http://www.opensource.org/licenses for more info)
00015 
00016 
00017 //! \addtogroup format_wrap
00018 //! @{
00019 
00020 
00021 //! \namespace arma_boost namespace for functions and classes which partially emulate Boost functionality 
00022 namespace arma_boost
00023   {
00024   
00025   #if defined(ARMA_USE_BOOST_FORMAT)
00026 
00027     using boost::format;
00028     using boost::basic_format;
00029     using boost::str;
00030 
00031   #else
00032   
00033     #if defined(ARMA_HAVE_STD_SNPRINTF)
00034 
00035       #define arma_snprintf std::snprintf
00036 
00037     #else
00038 
00039       // better-than-nothing emulation of C99 snprintf(),
00040       // with correct return value and null-terminated output string.
00041       // note that _snprintf() provided by MS is not a good substitute for snprintf()
00042 
00043       inline
00044       int
00045       arma_snprintf(char* out, size_t size, const char* fmt, ...)
00046         {
00047         size_t i;
00048         
00049         for(i=0; i<size; ++i)
00050           {
00051           out[i] = fmt[i];
00052           if(fmt[i] == char(0))
00053             break;
00054           }
00055         
00056         if(size > 0)
00057           out[size-1] = char(0);
00058         
00059         return int(i);
00060         }
00061 
00062     #endif
00063     
00064     class format
00065       {
00066       public:
00067     
00068       format(const char* in_fmt)
00069         : A(in_fmt)
00070         {
00071         }
00072     
00073       format(const std::string& in_fmt)
00074         : A(in_fmt)
00075         {
00076         }
00077     
00078     
00079       const std::string A;
00080     
00081       private:
00082       format();
00083       };
00084     
00085     
00086     
00087     template<typename T1, typename T2>
00088     class basic_format
00089       {
00090       public:
00091     
00092       basic_format(const T1& in_A, const T2& in_B)
00093         : A(in_A)
00094         , B(in_B)
00095         {
00096         }
00097     
00098       const T1& A;
00099       const T2& B;
00100     
00101       private:
00102       basic_format();
00103       };
00104     
00105     
00106     
00107     template<typename T2>
00108     inline
00109     basic_format< format, T2 >
00110     operator% (const format& X, const T2& arg)
00111       {
00112       return basic_format< format, T2 >(X, arg);
00113       }
00114     
00115     
00116     
00117     template<typename T1, typename T2, typename T3>
00118     inline
00119     basic_format< basic_format<T1,T2>, T3 >
00120     operator% (const basic_format<T1,T2>& X, const T3& arg)
00121       {
00122       return basic_format< basic_format<T1,T2>, T3 >(X, arg);
00123       }
00124     
00125     
00126     
00127     template<typename T2>
00128     inline
00129     std::string
00130     str(const basic_format< format, T2>& X)
00131       {
00132       char  local_buffer[1024];
00133       char* buffer = local_buffer;
00134       
00135       int buffer_size   = 1024;
00136       int required_size = buffer_size;
00137    
00138       bool using_local_buffer = true;
00139       
00140       std::string out;
00141       
00142       do
00143         {
00144         if(using_local_buffer == false)
00145           {
00146           buffer = new char[buffer_size];
00147           }
00148         
00149         required_size = arma_snprintf(buffer, buffer_size, X.A.A.c_str(), X.B);
00150         
00151         if(required_size < buffer_size)
00152           {
00153           if(required_size > 0)
00154             {
00155             out = buffer;
00156             }
00157           }
00158         else
00159           {
00160           buffer_size *= 2;
00161           }
00162         
00163         if(using_local_buffer == true)
00164           {
00165           using_local_buffer = false;
00166           }
00167         else
00168           {
00169           delete[] buffer;
00170           }
00171         
00172         } while( (required_size >= buffer_size) );
00173 
00174       return out;
00175       }
00176     
00177     
00178     
00179     template<typename T2, typename T3>
00180     inline
00181     std::string
00182     str(const basic_format< basic_format< format, T2>, T3>& X)
00183       {
00184       char  local_buffer[1024];
00185       char* buffer = local_buffer;
00186       
00187       int buffer_size   = 1024;
00188       int required_size = buffer_size;
00189    
00190       bool using_local_buffer = true;
00191       
00192       std::string out;
00193       
00194       do
00195         {
00196         if(using_local_buffer == false)
00197           {
00198           buffer = new char[buffer_size];
00199           }
00200         
00201         required_size = arma_snprintf(buffer, buffer_size, X.A.A.A.c_str(), X.A.B, X.B);
00202         
00203         if(required_size < buffer_size)
00204           {
00205           if(required_size > 0)
00206             {
00207             out = buffer;
00208             }
00209           }
00210         else
00211           {
00212           buffer_size *= 2;
00213           }
00214         
00215         if(using_local_buffer == true)
00216           {
00217           using_local_buffer = false;
00218           }
00219         else
00220           {
00221           delete[] buffer;
00222           }
00223         
00224         } while( (required_size >= buffer_size) );
00225 
00226       return out;
00227       }
00228     
00229     
00230     
00231     template<typename T2, typename T3, typename T4>
00232     inline
00233     std::string
00234     str(const basic_format< basic_format< basic_format< format, T2>, T3>, T4>& X)
00235       {
00236       char  local_buffer[1024];
00237       char* buffer = local_buffer;
00238       
00239       int buffer_size   = 1024;
00240       int required_size = buffer_size;
00241    
00242       bool using_local_buffer = true;
00243       
00244       std::string out;
00245       
00246       do
00247         {
00248         if(using_local_buffer == false)
00249           {
00250           buffer = new char[buffer_size];
00251           }
00252         
00253         required_size = arma_snprintf(buffer, buffer_size, X.A.A.A.A.c_str(), X.A.A.B, X.A.B, X.B);
00254         
00255         if(required_size < buffer_size)
00256           {
00257           if(required_size > 0)
00258             {
00259             out = buffer;
00260             }
00261           }
00262         else
00263           {
00264           buffer_size *= 2;
00265           }
00266         
00267         if(using_local_buffer == true)
00268           {
00269           using_local_buffer = false;
00270           }
00271         else
00272           {
00273           delete[] buffer;
00274           }
00275         
00276         } while( (required_size >= buffer_size) );
00277 
00278       return out;
00279       }
00280     
00281     
00282     
00283     template<typename T2, typename T3, typename T4, typename T5>
00284     inline
00285     std::string
00286     str(const basic_format< basic_format< basic_format< basic_format< format, T2>, T3>, T4>, T5>& X)
00287       {
00288       char  local_buffer[1024];
00289       char* buffer = local_buffer;
00290       
00291       int buffer_size   = 1024;
00292       int required_size = buffer_size;
00293    
00294       bool using_local_buffer = true;
00295       
00296       std::string out;
00297       
00298       do
00299         {
00300         if(using_local_buffer == false)
00301           {
00302           buffer = new char[buffer_size];
00303           }
00304         
00305         required_size = arma_snprintf(buffer, buffer_size, X.A.A.A.A.A.c_str(), X.A.A.A.B, X.A.A.B, X.A.B, X.B);
00306         
00307         if(required_size < buffer_size)
00308           {
00309           if(required_size > 0)
00310             {
00311             out = buffer;
00312             }
00313           }
00314         else
00315           {
00316           buffer_size *= 2;
00317           }
00318         
00319         if(using_local_buffer == true)
00320           {
00321           using_local_buffer = false;
00322           }
00323         else
00324           {
00325           delete[] buffer;
00326           }
00327         
00328         } while( (required_size >= buffer_size) );
00329 
00330       return out;
00331       }
00332     
00333     
00334     
00335     template<typename T2, typename T3, typename T4, typename T5, typename T6>
00336     inline
00337     std::string
00338     str(const basic_format< basic_format< basic_format< basic_format< basic_format< format, T2>, T3>, T4>, T5>, T6>& X)
00339       {
00340       char  local_buffer[1024];
00341       char* buffer = local_buffer;
00342       
00343       int buffer_size   = 1024;
00344       int required_size = buffer_size;
00345    
00346       bool using_local_buffer = true;
00347       
00348       std::string out;
00349       
00350       do
00351         {
00352         if(using_local_buffer == false)
00353           {
00354           buffer = new char[buffer_size];
00355           }
00356         
00357         required_size = arma_snprintf(buffer, buffer_size, X.A.A.A.A.A.A.c_str(), X.A.A.A.A.B, X.A.A.A.B, X.A.A.B, X.A.B, X.B);
00358         
00359         if(required_size < buffer_size)
00360           {
00361           if(required_size > 0)
00362             {
00363             out = buffer;
00364             }
00365           }
00366         else
00367           {
00368           buffer_size *= 2;
00369           }
00370         
00371         if(using_local_buffer == true)
00372           {
00373           using_local_buffer = false;
00374           }
00375         else
00376           {
00377           delete[] buffer;
00378           }
00379         
00380         } while( (required_size >= buffer_size) );
00381 
00382       return out;
00383       }
00384     
00385     
00386     
00387     template<typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
00388     inline
00389     std::string
00390     str(const basic_format< basic_format< basic_format< basic_format< basic_format< basic_format< format, T2>, T3>, T4>, T5>, T6>, T7>& X)
00391       {
00392       char  local_buffer[1024];
00393       char* buffer = local_buffer;
00394       
00395       int buffer_size   = 1024;
00396       int required_size = buffer_size;
00397    
00398       bool using_local_buffer = true;
00399       
00400       std::string out;
00401       
00402       do
00403         {
00404         if(using_local_buffer == false)
00405           {
00406           buffer = new char[buffer_size];
00407           }
00408         
00409         required_size = arma_snprintf(buffer, buffer_size, X.A.A.A.A.A.A.A.c_str(), X.A.A.A.A.A.B, X.A.A.A.A.B, X.A.A.A.B, X.A.A.B, X.A.B, X.B);
00410         
00411         if(required_size < buffer_size)
00412           {
00413           if(required_size > 0)
00414             {
00415             out = buffer;
00416             }
00417           }
00418         else
00419           {
00420           buffer_size *= 2;
00421           }
00422         
00423         if(using_local_buffer == true)
00424           {
00425           using_local_buffer = false;
00426           }
00427         else
00428           {
00429           delete[] buffer;
00430           }
00431         
00432         } while( (required_size >= buffer_size) );
00433 
00434       return out;
00435       }
00436     
00437     
00438     
00439     template<typename T1>
00440     struct format_metaprog
00441       {
00442       static const u32 depth = 0;
00443     
00444       inline
00445       static  
00446       const std::string&
00447       get_fmt(const T1& X)
00448         {
00449         return X.A;
00450         }
00451       };
00452     
00453     
00454     
00455     //template<>
00456     template<typename T1, typename T2>
00457     struct format_metaprog< basic_format<T1,T2> >
00458       {
00459       static const u32 depth = 1 + format_metaprog<T1>::depth;
00460     
00461       inline
00462       static
00463       const std::string&
00464       get_fmt(const T1& X)
00465         {
00466         return format_metaprog<T1>::get_fmt(X.A);
00467         }
00468     
00469       };
00470     
00471     
00472     
00473     template<typename T1, typename T2>
00474     inline
00475     std::string
00476     str(const basic_format<T1,T2>& X)
00477       {
00478       return format_metaprog< basic_format<T1,T2> >::get_fmt(X.A);
00479       }
00480     
00481     
00482     
00483     template<typename T1, typename T2>
00484     inline
00485     std::ostream&
00486     operator<< (std::ostream& o, const basic_format<T1,T2>& X)
00487       {
00488       o << str(X);
00489       return o;
00490       }
00491         
00492         
00493   #endif
00494   
00495   
00496   template<typename T> struct string_only              { };
00497   template<>           struct string_only<std::string> { typedef std::string result; };
00498   
00499   template<typename T> struct char_only                { };
00500   template<>           struct char_only<char         > { typedef char        result; };
00501 
00502   template<typename T>
00503   struct basic_format_only { };
00504   
00505   #if defined(ARMA_USE_BOOST_FORMAT)
00506     template<typename T>
00507     struct basic_format_only< basic_format<T>      > { typedef basic_format<T>     result; };
00508   #else
00509     template<typename T1, typename T2>
00510     struct basic_format_only< basic_format<T1, T2> > { typedef basic_format<T1,T2> result; };
00511   #endif
00512 
00513 
00514 
00515   template<typename T1>
00516   inline
00517   static
00518   const T1&
00519   str_wrapper(const T1& x, const typename string_only<T1>::result* junk = 0)
00520     {
00521     return x;
00522     }
00523   
00524   
00525   
00526   template<typename T1>
00527   inline
00528   static
00529   const T1*
00530   str_wrapper(const T1* x, const typename char_only<T1>::result* junk = 0)
00531     {
00532     return x;
00533     }
00534   
00535   
00536     
00537   template<typename T1>
00538   inline
00539   static
00540   std::string
00541   str_wrapper(const T1& x, const typename basic_format_only<T1>::result* junk = 0)
00542     {
00543     return str(x);
00544     }
00545   
00546   }
00547 
00548 //! @}