Lumiera  0.pre.03
»edit your freedom«
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 
55 namespace 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, const char* errorMsg =NULL)
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 
133  _Fmt::~_Fmt ()
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  {
175  _clear_errorflag();
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
static void format(const VAL, Implementation &)
call into the opaque implementation
Implementation formatter_
_Fmt(string formatString)
Build a formatter object based on the given format string.
CStr cStr(std::string const &rendered)
convenience shortcut: forced conversion to c-String via string.
Definition: symbol.hpp:59
void pushFailsafeReplacement(std::byte *formatter, const char *errorMsg=NULL)
in case the formatting of a (primitive) value fails, we try to supply an error indicator instead ...
#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:266
Front-end for printf-style string template interpolation.
A front-end for using printf-style formatting.
Derived specific exceptions within Lumiera&#39;s exception hierarchy.
Definition: error.hpp:190
std::string toString(TY const &val) noexcept
get some string representation of any object, reliably.
Definition: format-obj.hpp:191
Lumiera error handling (C++ interface).
Collection of small helpers and convenience shortcuts for diagnostics & formatting.
#define LUMIERA_ERROR_DEFINE(err, msg)
Definition and initialisation of an error constant.
Definition: error.h:71