Lumiera  0.pre.03
»edityourfreedom«
format-string.cpp
Go to the documentation of this file.
1 /*
2  FormatString - string template formatting based on boost::format
3 
4  Copyright (C) Lumiera.org
5  2011, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 * *****************************************************/
22 
50 #include "lib/error.hpp"
51 #include "lib/format-util.hpp"
52 #include "lib/format-string.hpp"
53 
54 #include <boost/static_assert.hpp>
55 #include <boost/format.hpp>
56 #include <iostream>
57 
58 
59 
60 
61 
62 namespace util {
63 
64  using boost::format;
65 
66 
67  namespace { // implementation details...
68 
69  inline boost::format&
70  accessImpl (char* buffer)
71  {
72  return reinterpret_cast<boost::format&> (*buffer);
73  }
74 
75 
76  inline void
77  destroyImpl (char* buffer)
78  {
79  accessImpl(buffer).~format();
80  }
81 
82 
85  void
86  pushFailsafeReplacement (char* formatter, const char* errorMsg =NULL)
87  try {
88  string placeholder("<Error");
89  if (errorMsg){
90  placeholder += ": ";
91  placeholder += errorMsg;
92  }
93  placeholder += ">";
94 
95  accessImpl(formatter) % placeholder;
96  }
97  ERROR_LOG_AND_IGNORE (progress, "Supplying placeholder for problematic format parameter")
98 
99 
100  inline void
101  suppressInsufficientArgumentErrors (char* formatter)
102  {
103  using namespace boost::io;
104  accessImpl(formatter).exceptions (all_error_bits ^ too_few_args_bit);
105  }
106 
107 
108  }//(End) implementation details
109 
110 
111 
112 
113 
121  _Fmt::_Fmt (string formatString)
122  try {
123  static_assert (sizeof(boost::format) <= FORMATTER_SIZE,
124  "opaque working buffer insufficient "
125  "to hold a boost::format instance. "
126  "Maybe boost implementation change. "
127  "Please verify lib/meta/size-trait.hpp");
128 
129  new(formatter_) boost::format(formatString);
130  suppressInsufficientArgumentErrors (formatter_);
131  }
132  catch (boost::io::bad_format_string& syntaxError)
133  {
134  throw lumiera::error::Fatal (syntaxError
135  , _Fmt("Format string '%s' is broken") % formatString
136  , LUMIERA_ERROR_FORMAT_SYNTAX);
137  }
138 
139 
141  {
142  destroyImpl (formatter_);
143  }
144 
145 
159  template<typename VAL>
160  void
161  _Fmt::format (const VAL val, Implementation& formatter)
162  try {
163  accessImpl(formatter) % val;
164  }
165 
166  catch (boost::io::too_many_args& argErr)
167  {
168  WARN (progress, "Format: excess argument '%s' of type «%s» ignored."
169  , cStr(toString(val))
170  , cStr(typeStr(val)));
171  }
172  catch (std::exception& failure)
173  {
174  _clear_errorflag();
175  WARN (progress, "Format: Parameter '%s' causes problems: %s"
176  , cStr(toString(val))
177  , failure.what());
178  pushFailsafeReplacement (formatter, failure.what());
179  }
180  catch (...)
181  {
182  _clear_errorflag();
183  WARN (progress, "Format: Unexpected problems accepting format parameter '%s'", cStr(toString(val)));
184  pushFailsafeReplacement (formatter);
185  }
186 
187 
188 
189 
190  /* ===== explicitly supported =================== */
191 
192  template void _Fmt::format (const char, Implementation&);
193  template void _Fmt::format (const uchar, Implementation&);
194  template void _Fmt::format (const int16_t, Implementation&);
195  template void _Fmt::format (const uint16_t,Implementation&);
196  template void _Fmt::format (const int32_t, Implementation&);
197  template void _Fmt::format (const uint32_t,Implementation&);
198  template void _Fmt::format (const int64_t, Implementation&);
199  template void _Fmt::format (const uint64_t,Implementation&);
200  template void _Fmt::format (const float, Implementation&);
201  template void _Fmt::format (const double, Implementation&);
202  template void _Fmt::format (const string, Implementation&);
203  template void _Fmt::format (const void *, Implementation&);
204  template void _Fmt::format (const char *, Implementation&);
205 #ifndef __x86_64__
206  template void _Fmt::format (const long, Implementation&);
207  template void _Fmt::format (const ulong, Implementation&);
208 #endif
209 
210 
211 
212 
220  _Fmt::operator string() const
221  try {
222  return accessImpl(formatter_).str();
223  }
224 
225  catch (std::exception& failure)
226  {
227  _clear_errorflag();
228  WARN (progress, "Format: Failure to receive formatted result: %s", failure.what());
229  return "<formatting failure>";
230  }
231  catch (...)
232  {
233  _clear_errorflag();
234  WARN (progress, "Format: Unexpected problems while formatting output.");
235  return "<unexpected problems>";
236  }
237 
238 
239 
245  std::ostream&
246  operator<< (std::ostream& os, _Fmt const& fmt)
247  try {
248  return os << accessImpl(fmt.formatter_);
249  }
250 
251  catch(std::exception& failure)
252  {
253  _clear_errorflag();
254  WARN (progress, "Format: Failure when outputting formatted result: %s", failure.what());
255  return os << "<formatting failure>";
256  }
257  catch(...)
258  {
259  _clear_errorflag();
260  WARN (progress, "Format: Unexpected problems while producing formatted output.");
261  return os << "<unexpected problems>";
262  }
263 
264 
265  LUMIERA_ERROR_DEFINE (FORMAT_SYNTAX, "Syntax error in format string for boost::format");
266 
267 
268 
269 } // 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.
unsigned char uchar
#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:272
std::string toString(TY const &val) noexcept
get some string representation of any object, reliably.
Definition: format-obj.hpp:174
Front-end for printf-style string template interpolation.
A front-end for using printf-style formatting.
std::string typeStr(TY const *obj=nullptr) noexcept
failsafe human readable type display
Definition: meta/util.hpp:272
const char * cStr(string const &org)
convenience shortcut: conversion to c-String via string.
Definition: util.hpp:380
return NULL
Definition: llist.h:596
Lumiera error handling (C++ interface).
LUMIERA_ERROR_DEFINE(FORMAT_SYNTAX, "Syntax error in format string for boost::format")
Collection of small helpers and convenience shortcuts for diagnostics & formatting.
std::ostream & operator<<(std::ostream &os, _Fmt const &fmt)
send the formatted buffer directly to the output stream.
LumieraError< LERR_(FATAL), Logic > Fatal
Definition: error.hpp:213