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 
28 namespace cupt {
29 
30 using std::string;
31 
32 namespace internal {
33 namespace format2impl {
34 
35 template < typename... All >
36 struct Tuple;
37 
38 template < typename Head, typename... Tail >
39 struct 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 
49 template <>
50 struct Tuple<>
51 {};
52 
53 template < typename... Args >
54 string 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 
76 template< typename TupleT, typename... Args >
77 string tupleformat(TupleT&& tuple, Args... args)
78 {
79  return tupleformat(tuple.tail, args..., tuple.head);
80 }
81 
82 template < typename... TupleTailT, typename... Args >
83 string 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 
93 template < typename... Args >
94 string format2(const char* format, const Args&... args)
95 {
96  return internal::format2impl::tupleformat(
97  internal::format2impl::Tuple< const char*, Args... >(format, args...));
98 }
99 
100 template < typename... Args >
101 string format2(const string& format, const Args&... args)
102 {
103  return format2(format.c_str(), args...);
104 }
105 
106 template < typename... Args >
107 string 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 
116 template < typename... Args >
117 string format2e(const string& format, const Args&... args)
118 {
119  return format2e(format.c_str(), args...);
120 }
121 
122 CUPT_API void __mwrite_line(const char*, const string&);
123 
124 template < 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 
132 template < typename... Args >
133 [[noreturn]] void fatal2i(const char* format, const Args&... args)
134 {
135  fatal2((string("internal error: ") + format), args...);
136 }
137 
138 template < 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 
146 template < typename... Args >
147 void warn2(const string& format, const Args&... args)
148 {
149  __mwrite_line("W: ", format2(format, args...));
150 }
151 
152 template < typename... Args >
153 void warn2e(const string& format, const Args&... args)
154 {
155  __mwrite_line("W: ", format2e(format, args...));
156 }
157 
158 template < typename... Args >
159 void debug2(const char* format, const Args&... args)
160 {
161  __mwrite_line("D: ", format2(format, args...));
162 }
163 
164 template < typename... Args >
165 void simulate2(const char* format, const Args&... args)
166 {
167  __mwrite_line("S: ", format2(format, args...));
168 }
169 
170 }
171 
173