Lumiera 0.pre.04~rc.1
»edit your freedom«
Loading...
Searching...
No Matches
format-string.cpp
Go to the documentation of this file.
1/*
2 FormatString - string template formatting based on boost::format
3
4 Copyright (C)
5 2011, Hermann Vosseler <Ichthyostega@web.de>
6
7  **Lumiera** is free software; you can redistribute it and/or modify it
8  under the terms of the GNU General Public License as published by the
9  Free Software Foundation; either version 2 of the License, or (at your
10  option) any later version. See the file COPYING for further details.
11
12* *****************************************************************/
13
41#include "lib/error.hpp"
42#include "lib/format-util.hpp"
43#include "lib/format-string.hpp"
44
45#include <boost/static_assert.hpp>
46#include <boost/format.hpp>
47#include <iostream>
48#include <cstddef>
49#include <new>
50
51
52
53
54
55namespace util {
56
57 using boost::format;
58
59
60 namespace { // implementation details...
61
62 inline boost::format&
63 accessImpl (std::byte* buffer)
64 {
65 return * std::launder (reinterpret_cast<boost::format*> (buffer));
66 }
67
68
69 inline void
70 destroyImpl (std::byte* buffer)
71 {
72 accessImpl(buffer).~format();
73 }
74
75
78 void
79 pushFailsafeReplacement (std::byte* formatter, CStr errorMsg =nullptr)
80 try {
81 string placeholder("<Error");
82 if (errorMsg){
83 placeholder += ": ";
84 placeholder += errorMsg;
85 }
86 placeholder += ">";
87
88 accessImpl(formatter) % placeholder;
89 }
90 ERROR_LOG_AND_IGNORE (progress, "Supplying placeholder for problematic format parameter")
91
92
93 inline void
94 suppressInsufficientArgumentErrors (std::byte* formatter)
95 {
96 using namespace boost::io;
97 accessImpl(formatter).exceptions (all_error_bits ^ too_few_args_bit);
98 }
99
100
101 }//(End) implementation details
102
103
104
105
106
114 _Fmt::_Fmt (string formatString)
115 try {
116 static_assert (sizeof(boost::format) <= FORMATTER_SIZE,
117 "opaque working buffer insufficient "
118 "to hold a boost::format instance. "
119 "Maybe boost implementation change. "
120 "Please verify lib/meta/size-trait.hpp");
121
122 new(formatter_) boost::format(formatString);
123 suppressInsufficientArgumentErrors (formatter_);
124 }
125 catch (boost::io::bad_format_string& syntaxError)
126 {
127 throw lumiera::error::Fatal (syntaxError
128 , _Fmt("Format string '%s' is broken") % formatString
129 , LUMIERA_ERROR_FORMAT_SYNTAX);
130 }
131
132
134 {
135 destroyImpl (formatter_);
136 }
137
138
152 template<typename VAL>
153 void
154 _Fmt::format (const VAL val, Implementation& formatter)
155 try {
156 accessImpl(formatter) % val;
157 }
158
159 catch (boost::io::too_many_args& argErr)
160 {
161 WARN (progress, "Format: excess argument '%s' of type «%s» ignored."
162 , cStr(toString(val))
163 , cStr(typeStr(val)));
164 }
165 catch (std::exception& failure)
166 {
167 _clear_errorflag();
168 WARN (progress, "Format: Parameter '%s' causes problems: %s"
169 , cStr(toString(val))
170 , failure.what());
171 pushFailsafeReplacement (formatter, failure.what());
172 }
173 catch (...)
174 {
176 WARN (progress, "Format: Unexpected problems accepting format parameter '%s'", cStr(toString(val)));
177 pushFailsafeReplacement (formatter);
178 }
179
180
181
182
183 /* ===== explicitly supported =================== */
184
185 template void _Fmt::format (const char, Implementation&);
186 template void _Fmt::format (const uchar, Implementation&);
187 template void _Fmt::format (const int16_t, Implementation&);
188 template void _Fmt::format (const uint16_t,Implementation&);
189 template void _Fmt::format (const int32_t, Implementation&);
190 template void _Fmt::format (const uint32_t,Implementation&);
191 template void _Fmt::format (const int64_t, Implementation&);
192 template void _Fmt::format (const uint64_t,Implementation&);
193 template void _Fmt::format (const float, Implementation&);
194 template void _Fmt::format (const double, Implementation&);
195 template void _Fmt::format (const string, Implementation&);
196 template void _Fmt::format (const void *, Implementation&);
197 template void _Fmt::format (const char *, Implementation&);
198#ifndef __x86_64__
199 template void _Fmt::format (const long, Implementation&);
200 template void _Fmt::format (const ulong, Implementation&);
201#endif
202
203
204
205
213 _Fmt::operator string() const
214 try {
215 return accessImpl(formatter_).str();
216 }
217
218 catch (std::exception& failure)
219 {
220 _clear_errorflag();
221 WARN (progress, "Format: Failure to receive formatted result: %s", failure.what());
222 return "<formatting failure>";
223 }
224 catch (...)
225 {
226 _clear_errorflag();
227 WARN (progress, "Format: Unexpected problems while formatting output.");
228 return "<unexpected problems>";
229 }
230
231
232
238 std::ostream&
239 operator<< (std::ostream& os, _Fmt const& fmt)
240 try {
241 return os << accessImpl(fmt.formatter_);
242 }
243
244 catch(std::exception& failure)
245 {
246 _clear_errorflag();
247 WARN (progress, "Format: Failure when outputting formatted result: %s", failure.what());
248 return os << "<formatting failure>";
249 }
250 catch(...)
251 {
252 _clear_errorflag();
253 WARN (progress, "Format: Unexpected problems while producing formatted output.");
254 return os << "<unexpected problems>";
255 }
256
257
258 LUMIERA_ERROR_DEFINE (FORMAT_SYNTAX, "Syntax error in format string for boost::format");
259
260
261
262} // namespace util
A front-end for using printf-style formatting.
Implementation formatter_
static void format(const VAL, Implementation &)
call into the opaque implementation
_Fmt(string formatString)
Build a formatter object based on the given format string.
#define LUMIERA_ERROR_DEFINE(err, msg)
Definition and initialisation of an error constant.
Definition error.h:71
Lumiera error handling (C++ interface).
#define ERROR_LOG_AND_IGNORE(_FLAG_, _OP_DESCR_)
convenience shortcut for a sequence of catch blocks just logging and consuming an error.
Definition error.hpp:267
const char * CStr
Definition error.hpp:42
Front-end for printf-style string template interpolation.
Collection of small helpers and convenience shortcuts for diagnostics & formatting.
unsigned long int ulong
Definition integral.hpp:31
unsigned char uchar
Definition integral.hpp:30
LumieraError< LERR_(FATAL), Logic > Fatal
Definition error.hpp:208
STL namespace.
boost::format & accessImpl(std::byte *buffer)
void pushFailsafeReplacement(std::byte *formatter, CStr errorMsg=nullptr)
in case the formatting of a (primitive) value fails, we try to supply an error indicator instead
std::ostream & operator<<(std::ostream &os, _Fmt const &fmt)
send the formatted buffer directly to the output stream.
std::string toString(TY const &val) noexcept
get some string representation of any object, reliably.
CStr cStr(std::string const &rendered)
convenience shortcut: forced conversion to c-String via string.
Definition symbol.hpp:60