Lumiera  0.pre.03
»edit your freedom«
format-string.hpp
Go to the documentation of this file.
1 /*
2  FORMAT-STRING.hpp - 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 
14 
98 #ifndef UTIL_FORMAT_STRING_H
99 #define UTIL_FORMAT_STRING_H
100 
101 #include "lib/error.hpp"
102 #include "lib/symbol.hpp"
103 #include "lib/nocopy.hpp"
104 #include "lib/meta/util.hpp"
105 #include "lib/meta/size-trait.hpp"
106 
107 #include <string>
108 
109 
110 
111 namespace std {// forward declaration to avoid including <iostream>
112 
113  template<typename C>
114  struct char_traits;
115 
116  template<typename C, class _TRAITS>
117  class basic_ostream;
118 
119  using ostream = basic_ostream<char, char_traits<char>>;
120 }
121 
122 
123 namespace lib {
124  class Literal;
125  class Symbol;
126 }
127 
128 
129 namespace util {
130 
131  using std::string;
132 
133  typedef unsigned char uchar;
134 
135  LUMIERA_ERROR_DECLARE (FORMAT_SYNTAX);
136 
137 
138 
148  class _Fmt
150  {
152  enum{ FORMATTER_SIZE = lib::meta::SizeTrait::BOOST_FORMAT };
153 
154  typedef std::byte Implementation[FORMATTER_SIZE];
155 
156 
158  alignas(size_t) mutable Implementation formatter_;
159 
160 
162  template<typename VAL>
163  static void format (const VAL, Implementation&);
164 
166  template<typename VAL, class SEL =void>
167  struct Converter;
168 
169 
170 
171  public:
172  ~_Fmt ();
173  _Fmt (string formatString);
174 
175  operator string() const;
176 
177  template<typename VAL>
178  _Fmt&
179  operator% (VAL const&);
180 
181 
182  friend std::ostream&
183  operator<< (std::ostream& os, _Fmt const&);
184 
185  friend bool operator== (_Fmt const&, _Fmt const&);
186  friend bool operator== (_Fmt const&, string const&);
187  friend bool operator== (_Fmt const&, const char * const);
188  friend bool operator== (string const& , _Fmt const&);
189  friend bool operator== (const char * const, _Fmt const&);
190 
191  template<typename X>
192  friend bool operator != (_Fmt const& fmt, X const& x) { return not (fmt == x); }
193  template<typename X>
194  friend bool operator != (X const& x, _Fmt const& fmt) { return not (x == fmt); }
195  };
196 
197 
198 
199 
200 
201  /* ===== forwarding into the implementation ====== */
202 
219  template<typename VAL>
220  inline _Fmt&
221  _Fmt::operator% (VAL const& val)
222  {
223  Converter<VAL>::dump (val, formatter_);
224  return *this;
225  }
226 
227 
228 
229  namespace { // helpers to pick a suitable specialisation....
230 
231  using std::__and_;
232  using std::__not_;
233 
239  template<typename X>
240  struct _allow_call : std::false_type {};
241 
242  /* the following definitions enable some primitive types
243  * to be handed over to the boost::format implementation */
244  template<> struct _allow_call<string> : std::true_type { };
245  template<> struct _allow_call<char> : std::true_type { };
246  template<> struct _allow_call<uchar> : std::true_type { };
247  template<> struct _allow_call<int16_t> : std::true_type { };
248  template<> struct _allow_call<uint16_t>: std::true_type { };
249  template<> struct _allow_call<int32_t> : std::true_type { };
250  template<> struct _allow_call<uint32_t>: std::true_type { };
251  template<> struct _allow_call<int64_t> : std::true_type { };
252  template<> struct _allow_call<uint64_t>: std::true_type { };
253  template<> struct _allow_call<float> : std::true_type { };
254  template<> struct _allow_call<double> : std::true_type { };
255 #ifndef __x86_64__
256  template<> struct _allow_call<long> : std::true_type { };
257  template<> struct _allow_call<ulong> : std::true_type { };
258 #endif
259 
260  template<typename X>
262  : _allow_call<std::remove_cv_t<X>>
263  { };
264 
265  template<typename X>
267  : __and_<__not_<_shall_format_directly<X>>
268  , std::bool_constant<lib::meta::can_convertToString<X>::value>
269  >
270  { };
271 
272 
273  template<typename SP>
275  : std::false_type
276  { };
277  template<typename T>
278  struct _is_smart_wrapper<std::shared_ptr<T>>
279  : std::true_type
280  { };
281  template <typename T, typename D>
282  struct _is_smart_wrapper<std::unique_ptr<T,D>>
283  : std::true_type
284  { };
285 
286 
287 
288  template<typename SP>
290  : __and_<__not_<_shall_convert_toString<SP>>
291  ,_is_smart_wrapper<std::remove_reference_t<std::remove_cv_t<SP>>>
292  >
293  { };
294 
295 
296 
297 
298 
299  inline void
300  _clear_errorflag()
301  {
302  const char* errID = lumiera_error();
303  TRACE_IF (errID, progress, "Lumiera errorstate '%s' cleared.", errID);
304  }
305 
306  inline string
307  _log_and_stringify (std::exception const& ex)
308  {
309  _clear_errorflag();
310  WARN (progress, "Error while invoking custom string conversion: %s", ex.what());
311  try {
312  return string("<string conversion failed: ")+ex.what()+">";
313  }
314  catch(...) { /* secondary errors ignored */ }
315  return "(formatting failure)";
316  }
317 
318  inline string
319  _log_unknown_exception()
320  {
321  const char* errID = lumiera_error();
322  if (errID)
323  ERROR (progress, "Unknown error while invoking custom string conversion. Lumiera error flag = %s", errID);
324  else
325  ERROR (progress, "Unknown error while invoking custom string conversion. No Lumiera error flag set.");
326  return "<Unknown error in string conversion>";
327  }
328 
329  }//(End) guards/helpers
330 
331 
332 
333 
334  /* === explicit specialisations to control the kind of conversion === */
335 
337  template<typename VAL, class SEL>
338  struct _Fmt::Converter
339  {
340  static void
341  dump (VAL const&, Implementation& impl)
342  {
343  format ("«"+typeStr<VAL>()+"»", impl);
344  }
345  };
346 
347  template<typename VAL>
348  struct _Fmt::Converter<VAL*>
349  {
350  static void
351  dump (const VAL *pVal, Implementation& impl)
352  {
353  if (pVal)
354  Converter<VAL>::dump(*pVal, impl);
355  else
356  format (BOTTOM_INDICATOR, impl);
357  }
358  };
359 
360  template<>
361  struct _Fmt::Converter<void *>
362  {
363  static void
364  dump (const void* address, Implementation& impl)
365  {
366  format (address, impl);
367  }
368  };
369 
370  template<>
371  struct _Fmt::Converter<const char *>
372  {
373  static void
374  dump (const char* cString, Implementation& impl)
375  {
376  format (cString? cString : BOTTOM_INDICATOR, impl);
377  }
378  };
379 
380  template<>
381  struct _Fmt::Converter<bool>
382  {
383  static void
384  dump (bool yes, Implementation& impl)
385  {
386  format (yes? "true":"false", impl);
387  }
388  };
389 
390  template<>
391  struct _Fmt::Converter<lib::Literal>
392  {
393  static void
394  dump (lib::Literal const& literal, Implementation& impl)
395  {
396  format (literal.empty()? "" : literal.c(), impl);
397  }
398  };
399 
400  template<>
401  struct _Fmt::Converter<lib::Symbol>
402  {
403  static void
404  dump (lib::Symbol const& symbol, Implementation& impl)
405  {
406  format (symbol.c(), impl);
407  }
408  };
409 
411  template<typename VAL>
412  struct _Fmt::Converter<VAL, lib::meta::enable_if<_shall_convert_toString<VAL>> >
413  {
414  static void
415  dump (VAL const& val, Implementation& impl)
416  try {
417  format (string(val), impl);
418  }
419  catch(std::exception const& ex)
420  {
421  format (_log_and_stringify(ex), impl);
422  }
423  catch(...)
424  {
425  format (_log_unknown_exception(), impl);
426  }
427  };
428 
429  template<typename SP>
430  struct _Fmt::Converter<SP, lib::meta::enable_if<_shall_show_smartWrapper<SP>> >
431  {
432  static void
433  dump (SP const& smP, Implementation& impl)
434  try {
435  format (showSmartPtr (smP, lib::meta::typeSymbol(smP)), impl);
436  }
437  catch(std::exception const& ex)
438  {
439  format (_log_and_stringify(ex), impl);
440  }
441  catch(...)
442  {
443  format (_log_unknown_exception(), impl);
444  }
445  };
446 
449  template<typename VAL>
450  struct _Fmt::Converter<VAL, lib::meta::enable_if<_shall_format_directly<VAL>> >
451  {
452  static void
453  dump (const VAL val, Implementation& impl)
454  {
455  format (val, impl);
456  }
457  };
458 
459 
460 
461  /* === comparison of formatter objects === */
462 
463  inline bool
464  operator== (_Fmt const& left, _Fmt const& right)
465  {
466  return string(left) == string(right);
467  }
468 
469  inline bool
470  operator== (_Fmt const& fmt, string const& str)
471  {
472  return string(fmt) == str;
473  }
474 
475  inline bool
476  operator== (_Fmt const& fmt, const char * const cString)
477  {
478  return string(fmt) == string(cString);
479  }
480 
481  inline bool
482  operator== (string const& str, _Fmt const& fmt)
483  {
484  return fmt == str;
485  }
486 
487  inline bool
488  operator== (const char * const cString, _Fmt const& fmt)
489  {
490  return fmt == cString;
491  }
492 
493 
494 
495 } // namespace util
496 #endif
ostream & operator<<(ostream &os, const Option &ops)
for outputting the help messages.
Definition: option.cpp:151
Simple and lightweight helpers for metaprogramming and type detection.
Any copy and copy construction prohibited.
Definition: nocopy.hpp:37
inline string literal This is a marker type to indicate that
Definition: symbol.hpp:76
STL namespace.
by default we don&#39;t allow to treat any types directly by boost::format.
#define LUMIERA_ERROR_DECLARE(err)
Forward declare an error constant.
Definition: error.h:62
A front-end for using printf-style formatting.
helper to prepare parameters for inclusion
Implementation namespace for support and library code.
Token or Atom with distinct identity.
Definition: symbol.hpp:117
Mix-Ins to allow or prohibit various degrees of copying and cloning.
Metaprogramming definitions to deal with dependency on implementation size and layout.
Marker types to indicate a literal string and a Symbol.
lumiera_err lumiera_error(void)
Get and clear current error state.
Definition: error-state.c:115
Lumiera error handling (C++ interface).
string typeSymbol()
Short readable type identifier, not necessarily unique or complete.
Definition: genfunc.hpp:78