Lumiera  0.pre.03
»edityourfreedom«
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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) 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 
23 
105 #ifndef UTIL_FORMAT_STRING_H
106 #define UTIL_FORMAT_STRING_H
107 
108 #include "lib/error.hpp"
109 #include "lib/nocopy.hpp"
110 #include "lib/meta/util.hpp"
111 #include "lib/meta/size-trait.hpp"
112 
113 #include <string>
114 
115 
116 
117 namespace std { // forward declaration to avoid including <iostream>
118 
119  template<typename C>
120  struct char_traits;
121 
122  template<typename C, class _TRAITS>
123  class basic_ostream;
124 
125  using ostream = basic_ostream<char, char_traits<char>>;
126 }
127 
128 
129 namespace lib {
130  class Literal;
131  class Symbol;
132 }
133 
134 
135 namespace util {
136 
137  using std::string;
138 
139  typedef unsigned char uchar;
140 
141  LUMIERA_ERROR_DECLARE (FORMAT_SYNTAX);
142 
143 
144 
154  class _Fmt
156  {
159 
161 
162 
164  mutable Implementation formatter_;
165 
166 
168  template<typename VAL>
169  static void format (const VAL, Implementation&);
170 
172  template<typename VAL, class SEL =void>
173  struct Converter;
174 
175 
176 
177  public:
178  ~_Fmt ();
179  _Fmt (string formatString);
180 
181  operator string() const;
182 
183  template<typename VAL>
184  _Fmt&
185  operator% (VAL const&);
186 
187 
188  friend std::ostream&
189  operator<< (std::ostream& os, _Fmt const&);
190 
191  friend bool operator== (_Fmt const&, _Fmt const&);
192  friend bool operator== (_Fmt const&, string const&);
193  friend bool operator== (_Fmt const&, const char * const);
194  friend bool operator== (string const& , _Fmt const&);
195  friend bool operator== (const char * const, _Fmt const&);
196 
197  template<typename X>
198  friend bool operator != (_Fmt const& fmt, X const& x) { return not (fmt == x); }
199  template<typename X>
200  friend bool operator != (X const& x, _Fmt const& fmt) { return not (x == fmt); }
201  };
202 
203 
204 
205 
206 
207  /* ===== forwarding into the implementation ====== */
208 
225  template<typename VAL>
226  inline _Fmt&
227  _Fmt::operator% (VAL const& val)
228  {
230  return *this;
231  }
232 
233 
234 
235  namespace { // helpers to pick a suitable specialisation....
236 
242  template<typename X>
243  struct _allow_call { enum{ value = false };};
244 
245  /* the following definitions enable some primitive types
246  * to be handed over to the boost::format implementation */
247  template<> struct _allow_call<string> { enum{ value = true }; };
248  template<> struct _allow_call<char> { enum{ value = true }; };
249  template<> struct _allow_call<uchar> { enum{ value = true }; };
250  template<> struct _allow_call<int16_t> { enum{ value = true }; };
251  template<> struct _allow_call<uint16_t>{ enum{ value = true }; };
252  template<> struct _allow_call<int32_t> { enum{ value = true }; };
253  template<> struct _allow_call<uint32_t>{ enum{ value = true }; };
254  template<> struct _allow_call<int64_t> { enum{ value = true }; };
255  template<> struct _allow_call<uint64_t>{ enum{ value = true }; };
256  template<> struct _allow_call<float> { enum{ value = true }; };
257  template<> struct _allow_call<double> { enum{ value = true }; };
258 #ifndef __x86_64__
259  template<> struct _allow_call<long> { enum{ value = true }; };
260  template<> struct _allow_call<ulong> { enum{ value = true }; };
261 #endif
262 
263  template<typename X>
264  struct _shall_format_directly
265  {
266  typedef typename lib::meta::UnConst<X>::Type BaseType;
267 
268  enum{ value = _allow_call<BaseType>::value };
269  };
270 
271 
272 
273  template<typename X>
274  struct _shall_convert_toString
275  {
276  enum{ value = not _shall_format_directly<X>::value
278  };
279  };
280 
281  template<typename SP>
282  struct _is_smart_wrapper
283  : std::false_type
284  { };
285  template<typename T>
286  struct _is_smart_wrapper<std::shared_ptr<T>>
287  : std::true_type
288  { };
289  template <typename T, typename D>
290  struct _is_smart_wrapper<std::unique_ptr<T,D>>
291  : std::true_type
292  { };
293 
294 
295 
296  template<typename SP>
297  struct _shall_show_smartWrapper
298  {
299  enum{ value = not _shall_convert_toString<SP>::value
300  and _is_smart_wrapper<typename std::remove_reference<
301  typename std::remove_cv<SP>::type>::type>::value
302  };
303  };
304 
305 
306 
307 
308 
309  inline void
310  _clear_errorflag()
311  {
312  const char* errID = lumiera_error();
313  TRACE_IF (errID, progress, "Lumiera errorstate '%s' cleared.", errID);
314  }
315 
316  inline string
317  _log_and_stringify (std::exception const& ex)
318  {
319  _clear_errorflag();
320  WARN (progress, "Error while invoking custom string conversion: %s", ex.what());
321  try {
322  return string("<string conversion failed: ")+ex.what()+">";
323  }
324  catch(...) { /* secondary errors ignored */ }
325  return "(formatting failure)";
326  }
327 
328  inline string
329  _log_unknown_exception()
330  {
331  const char* errID = lumiera_error();
332  if (errID)
333  ERROR (progress, "Unknown error while invoking custom string conversion. Lumiera error flag = %s", errID);
334  else
335  ERROR (progress, "Unknown error while invoking custom string conversion. No Lumiera error flag set.");
336  return "<Unknown error in string conversion>";
337  }
338 
339  }//(End) guards/helpers
340 
341 
342 
343 
344  /* === explicit specialisations to control the kind of conversion === */
345 
347  template<typename VAL, class SEL>
348  struct _Fmt::Converter
349  {
350  static void
351  dump (VAL const&, Implementation& impl)
352  {
353  format ("«"+typeStr<VAL>()+"»", impl);
354  }
355  };
356 
357  template<typename VAL>
358  struct _Fmt::Converter<VAL*>
359  {
360  static void
361  dump (const VAL *pVal, Implementation& impl)
362  {
363  if (pVal)
364  Converter<VAL>::dump(*pVal, impl);
365  else
366  format (BOTTOM_INDICATOR, impl);
367  }
368  };
369 
370  template<>
371  struct _Fmt::Converter<void *>
372  {
373  static void
374  dump (const void* address, Implementation& impl)
375  {
376  format (address, impl);
377  }
378  };
379 
380  template<>
381  struct _Fmt::Converter<const char *>
382  {
383  static void
384  dump (const char* cString, Implementation& impl)
385  {
386  format (cString? cString : BOTTOM_INDICATOR, impl);
387  }
388  };
389 
390  template<>
391  struct _Fmt::Converter<bool>
392  {
393  static void
394  dump (bool yes, Implementation& impl)
395  {
396  format (yes? "true":"false", impl);
397  }
398  };
399 
400  template<>
401  struct _Fmt::Converter<lib::Literal>
402  {
403  static void
404  dump (lib::Literal const& literal, Implementation& impl)
405  {
406  format (literal.empty()? "" : literal.c(), impl);
407  }
408  };
409 
410  template<>
411  struct _Fmt::Converter<lib::Symbol>
412  {
413  static void
414  dump (lib::Symbol const& symbol, Implementation& impl)
415  {
416  format (symbol.c(), impl);
417  }
418  };
419 
421  template<typename VAL>
422  struct _Fmt::Converter<VAL, lib::meta::enable_if<_shall_convert_toString<VAL>> >
423  {
424  static void
425  dump (VAL const& val, Implementation& impl)
426  try {
427  format (string(val), impl);
428  }
429  catch(std::exception const& ex)
430  {
431  format (_log_and_stringify(ex), impl);
432  }
433  catch(...)
434  {
435  format (_log_unknown_exception(), impl);
436  }
437  };
438 
439  template<typename SP>
440  struct _Fmt::Converter<SP, lib::meta::enable_if<_shall_show_smartWrapper<SP>> >
441  {
442  static void
443  dump (SP const& smP, Implementation& impl)
444  try {
445  format (showSmartPtr (smP, lib::meta::typeSymbol(smP)), impl);
446  }
447  catch(std::exception const& ex)
448  {
449  format (_log_and_stringify(ex), impl);
450  }
451  catch(...)
452  {
453  format (_log_unknown_exception(), impl);
454  }
455  };
456 
459  template<typename VAL>
460  struct _Fmt::Converter<VAL, lib::meta::enable_if<_shall_format_directly<VAL>> >
461  {
462  static void
463  dump (const VAL val, Implementation& impl)
464  {
465  format (val, impl);
466  }
467  };
468 
469 
470 
471  /* === comparison of formatter objects === */
472 
473  inline bool
474  operator== (_Fmt const& left, _Fmt const& right)
475  {
476  return string(left) == string(right);
477  }
478 
479  inline bool
480  operator== (_Fmt const& fmt, string const& str)
481  {
482  return string(fmt) == str;
483  }
484 
485  inline bool
486  operator== (_Fmt const& fmt, const char * const cString)
487  {
488  return string(fmt) == string(cString);
489  }
490 
491  inline bool
492  operator== (string const& str, _Fmt const& fmt)
493  {
494  return fmt == str;
495  }
496 
497  inline bool
498  operator== (const char * const cString, _Fmt const& fmt)
499  {
500  return fmt == cString;
501  }
502 
503 
504 
505 } // namespace util
506 #endif
std::string typeSymbol(TY const *obj=nullptr)
simple expressive symbol to designate a type
Definition: meta/util.hpp:304
friend std::ostream & operator<<(std::ostream &os, _Fmt const &)
send the formatted buffer directly to the output stream.
_Fmt & operator%(VAL const &)
The percent operator ('' ) is used do feed parameter values to be included into the formatted result...
static void dump(bool yes, Implementation &impl)
static void dump(const VAL *pVal, Implementation &impl)
static void format(const VAL, Implementation &)
call into the opaque implementation
Implementation formatter_
LUMIERA_ERROR_DECLARE(FORMAT_SYNTAX)
"Syntax error in format string for boost::format"
_Fmt(string formatString)
Build a formatter object based on the given format string.
char Implementation[FORMATTER_SIZE]
typename enable_if_c< Cond::value, T >::type enable_if
SFINAE helper to control the visibility of specialisations and overloads.
Definition: meta/util.hpp:91
unsigned char uchar
Simple and lightweight helpers for metaprogramming and type detection.
Any copy and copy construction prohibited.
Definition: nocopy.hpp:46
std::string dump(std::tuple< TYPES...> const &tuple)
convenience function to dump a given tuple's contents.
inline string literal This is a marker type to indicate that
Definition: symbol.hpp:75
STL namespace.
A front-end for using printf-style formatting.
helper to prepare parameters for inclusion
Implementation namespace for support and library code.
static void dump(const void *address, Implementation &impl)
Token or Atom with distinct identity.
Definition: symbol.hpp:116
Mix-Ins to allow or prohibit various degrees of copying and cloning.
static void dump(lib::Symbol const &symbol, Implementation &impl)
Metaprogramming definitions to deal with dependency on implementation size and layout.
std::string showSmartPtr(SP const &smPtr, std::string label="smP")
Definition: meta/util.hpp:392
static void dump(lib::Literal const &literal, Implementation &impl)
lumiera_err lumiera_error(void)
Get and clear current error state.
Definition: error-state.c:124
Lumiera error handling (C++ interface).
detect possibility of a conversion to string.
Definition: meta/util.hpp:116
static void dump(VAL const &, Implementation &impl)
friend bool operator==(_Fmt const &, _Fmt const &)
const string BOTTOM_INDICATOR
Definition: meta/util.hpp:244
friend bool operator!=(_Fmt const &fmt, X const &x)
bool operator==(_Fmt const &left, _Fmt const &right)
const char * c() const
Definition: symbol.hpp:92
static void dump(const char *cString, Implementation &impl)
bool empty() const
Definition: symbol.hpp:95