Cupt
format2.hpp
1/**************************************************************************
2* Copyright (C) 2011-2012 by Eugene V. Lyubimkin *
3* *
4* This program is free software; you can redistribute it and/or modify *
5* it under the terms of the GNU General Public License *
6* (version 3 or above) as published by the Free Software Foundation. *
7* *
8* This program is distributed in the hope that it will be useful, *
9* but WITHOUT ANY WARRANTY; without even the implied warranty of *
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
11* GNU General Public License for more details. *
12* *
13* You should have received a copy of the GNU GPL *
14* along with this program; if not, write to the *
15* Free Software Foundation, Inc., *
16* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA *
17**************************************************************************/
18
19// only for internal inclusion
21
22#include <cstdio>
23#include <cstring>
24#include <cerrno>
25
26#include <string>
27
28namespace cupt {
29
30using std::string;
31
32namespace internal {
33namespace format2impl {
34
35template < typename... All >
36struct Tuple;
37
38template < typename Head, typename... Tail >
39struct Tuple< Head, Tail... >
40{
41 const Head& head;
42 Tuple< Tail... > tail;
43
44 Tuple< Head, Tail...>(const Head& head_, const Tail&... tail_)
45 : head(head_), tail(tail_...)
46 {}
47};
48
49template <>
50struct Tuple<>
51{};
52
53template < typename... Args >
54string tupleformat(Tuple<>, Args... args)
55{
56 char formattedBuffer[4096];
57
58 auto bytesWritten = snprintf(formattedBuffer, sizeof(formattedBuffer), args...);
59
60 if ((size_t)bytesWritten < sizeof(formattedBuffer))
61 {
62 return string(formattedBuffer);
63 }
64 else
65 {
66 // we need a bigger buffer, allocate it dynamically
67 auto size = bytesWritten+1;
68 char* dynamicBuffer = new char[size];
69 snprintf(dynamicBuffer, size, args...);
70 string result(dynamicBuffer);
71 delete [] dynamicBuffer;
72 return result;
73 }
74}
75
76template< typename TupleT, typename... Args >
77string tupleformat(TupleT&& tuple, Args... args)
78{
79 return tupleformat(tuple.tail, args..., tuple.head);
80}
81
82template < typename... TupleTailT, typename... Args >
83string tupleformat(Tuple< string, TupleTailT... > tuple, Args... args)
84{
85 return tupleformat(tuple.tail, args..., tuple.head.c_str());
86}
87
88}
89}
90
91// now public parts
92
93template < typename... Args >
94string format2(const char* format, const Args&... args)
95{
96 return internal::format2impl::tupleformat(
97 internal::format2impl::Tuple< const char*, Args... >(format, args...));
98}
99
100template < typename... Args >
101string format2(const string& format, const Args&... args)
102{
103 return format2(format.c_str(), args...);
104}
105
106template < typename... Args >
107string format2e(const char* format, const Args&... args)
108{
109 char errorBuffer[255] = "?";
110 // error message may not go to errorBuffer, see man strerror_r (GNU version)
111 auto errorString = strerror_r(errno, errorBuffer, sizeof(errorBuffer));
112
113 return format2(format, args...) + ": " + errorString;
114}
115
116template < typename... Args >
117string format2e(const string& format, const Args&... args)
118{
119 return format2e(format.c_str(), args...);
120}
121
122CUPT_API void __mwrite_line(const char*, const string&);
123
124template < typename... Args >
125[[noreturn]] void fatal2(const string& format, const Args&... args)
126{
127 auto errorString = format2(format, args...);
128 __mwrite_line("E: ", errorString);
129 throw Exception(errorString);
130}
131
132template < typename... Args >
133[[noreturn]] void fatal2i(const char* format, const Args&... args)
134{
135 fatal2((string("internal error: ") + format), args...);
136}
137
138template < typename... Args >
139[[noreturn]] void fatal2e(const string& format, const Args&... args)
140{
141 auto errorString = format2e(format, args...);
142 __mwrite_line("E: ", errorString);
143 throw Exception(errorString);
144}
145
146template < typename... Args >
147void warn2(const string& format, const Args&... args)
148{
149 __mwrite_line("W: ", format2(format, args...));
150}
151
152template < typename... Args >
153void warn2e(const string& format, const Args&... args)
154{
155 __mwrite_line("W: ", format2e(format, args...));
156}
157
158template < typename... Args >
159void debug2(const char* format, const Args&... args)
160{
161 __mwrite_line("D: ", format2(format, args...));
162}
163
164template < typename... Args >
165void simulate2(const char* format, const Args&... args)
166{
167 __mwrite_line("S: ", format2(format, args...));
168}
169
170}
171
173