Cupt
format2.hpp
00001 /**************************************************************************
00002 *   Copyright (C) 2011-2012 by Eugene V. Lyubimkin                        *
00003 *                                                                         *
00004 *   This program is free software; you can redistribute it and/or modify  *
00005 *   it under the terms of the GNU General Public License                  *
00006 *   (version 3 or above) as published by the Free Software Foundation.    *
00007 *                                                                         *
00008 *   This program is distributed in the hope that it will be useful,       *
00009 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00010 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00011 *   GNU General Public License for more details.                          *
00012 *                                                                         *
00013 *   You should have received a copy of the GNU GPL                        *
00014 *   along with this program; if not, write to the                         *
00015 *   Free Software Foundation, Inc.,                                       *
00016 *   51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA               *
00017 **************************************************************************/
00018 
00019 // only for internal inclusion
00021 
00022 #include <cstdio>
00023 #include <cstring>
00024 
00025 #include <string>
00026 
00027 namespace cupt {
00028 
00029 using std::string;
00030 
00031 namespace internal {
00032 namespace format2impl {
00033 
00034 template < typename... All >
00035 struct Tuple;
00036 
00037 template < typename Head, typename... Tail >
00038 struct Tuple< Head, Tail... >
00039 {
00040     const Head& head;
00041     Tuple< Tail... > tail;
00042 
00043     Tuple< Head, Tail...>(const Head& head_, const Tail&... tail_)
00044         : head(head_), tail(tail_...)
00045     {}
00046 };
00047 
00048 template <>
00049 struct Tuple<>
00050 {};
00051 
00052 template < typename... Args >
00053 string tupleformat(Tuple<>, Args... args)
00054 {
00055     char formattedBuffer[4096];
00056 
00057     auto bytesWritten = snprintf(formattedBuffer, sizeof(formattedBuffer), args...);
00058 
00059     if ((size_t)bytesWritten < sizeof(formattedBuffer))
00060     {
00061         return string(formattedBuffer);
00062     }
00063     else
00064     {
00065         // we need a bigger buffer, allocate it dynamically
00066         auto size = bytesWritten+1;
00067         char* dynamicBuffer = new char[size];
00068         snprintf(dynamicBuffer, size, args...);
00069         string result(dynamicBuffer);
00070         delete [] dynamicBuffer;
00071         return result;
00072     }
00073 }
00074 
00075 template< typename TupleT, typename... Args >
00076 string tupleformat(TupleT&& tuple, Args... args)
00077 {
00078     return tupleformat(tuple.tail, args..., tuple.head);
00079 }
00080 
00081 template < typename... TupleTailT, typename... Args >
00082 string tupleformat(Tuple< string, TupleTailT... > tuple, Args... args)
00083 {
00084     return tupleformat(tuple.tail, args..., tuple.head.c_str());
00085 }
00086 
00087 }
00088 }
00089 
00090 // now public parts
00091 
00092 template < typename... Args >
00093 string format2(const char* format, const Args&... args)
00094 {
00095     return internal::format2impl::tupleformat(
00096             internal::format2impl::Tuple< const char*, Args... >(format, args...));
00097 }
00098 
00099 template < typename... Args >
00100 string format2(const string& format, const Args&... args)
00101 {
00102     return format2(format.c_str(), args...);
00103 }
00104 
00105 template < typename... Args >
00106 string format2e(const char* format, const Args&... args)
00107 {
00108     char errorBuffer[255] = "?";
00109     // error message may not go to errorBuffer, see man strerror_r (GNU version)
00110     auto errorString = strerror_r(errno, errorBuffer, sizeof(errorBuffer));
00111 
00112     return format2(format, args...) + ": " + errorString;
00113 }
00114 
00115 template < typename... Args >
00116 string format2e(const string& format, const Args&... args)
00117 {
00118     return format2e(format.c_str(), args...);
00119 }
00120 
00121 CUPT_API void __mwrite_line(const char*, const string&);
00122 
00123 template < typename... Args >
00124 void fatal2(const string& format, const Args&... args)
00125 {
00126     auto errorString = format2(format, args...);
00127     __mwrite_line("E: ", errorString);
00128     throw Exception(errorString);
00129 }
00130 
00131 template < typename... Args >
00132 void fatal2i(const char* format, const Args&... args)
00133 {
00134     fatal2((string("internal error: ") + format), args...);
00135 }
00136 
00137 template < typename... Args >
00138 void fatal2e(const string& format, const Args&... args)
00139 {
00140     auto errorString = format2e(format, args...);
00141     __mwrite_line("E: ", errorString);
00142     throw Exception(errorString);
00143 }
00144 
00145 template < typename... Args >
00146 void warn2(const string& format, const Args&... args)
00147 {
00148     __mwrite_line("W: ", format2(format, args...));
00149 }
00150 
00151 template < typename... Args >
00152 void warn2e(const string& format, const Args&... args)
00153 {
00154     __mwrite_line("W: ", format2e(format, args...));
00155 }
00156 
00157 template < typename... Args >
00158 void debug2(const char* format, const Args&... args)
00159 {
00160     __mwrite_line("D: ", format2(format, args...));
00161 }
00162 
00163 template < typename... Args >
00164 void simulate2(const char* format, const Args&... args)
00165 {
00166     __mwrite_line("S: ", format2(format, args...));
00167 }
00168 
00169 }
00170 
00172