Lumiera 0.pre.04
»edit your freedom«
Loading...
Searching...
No Matches
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"
106
107#include <string>
108
109
110
111namespace 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
123namespace lib {
124 class Literal;
125 class Symbol;
126}
127
128
129namespace 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 {
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&, CStr const );
188 friend bool operator== (string const&, _Fmt const&);
189 friend bool operator== (CStr 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 {
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
301 {
302 CStr 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 {
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
320 {
321 CStr 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>
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<>
372 {
373 static void
374 dump (CStr 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, CStr 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== (CStr const cString, _Fmt const& fmt)
489 {
490 return fmt == cString;
491 }
492
493
494
495} // namespace util
496#endif
Inline string literal.
Definition symbol.hpp:78
constexpr const char * c() const
Definition symbol.hpp:93
constexpr bool empty() const
Definition symbol.hpp:96
Token or Atom with distinct identity.
Definition symbol.hpp:120
Any copy and copy construction prohibited.
Definition nocopy.hpp:38
A front-end for using printf-style formatting.
std::byte Implementation[FORMATTER_SIZE]
friend bool operator!=(_Fmt const &fmt, X const &x)
friend std::ostream & operator<<(std::ostream &os, _Fmt const &)
send the formatted buffer directly to the output stream.
Implementation formatter_
static void format(const VAL, Implementation &)
call into the opaque implementation
friend bool operator==(_Fmt const &, _Fmt const &)
_Fmt & operator%(VAL const &)
The percent operator ('' ) is used do feed parameter values to be included into the formatted result,...
lumiera_err lumiera_error(void)
Get and clear current error state.
#define LUMIERA_ERROR_DECLARE(err)
Forward declare an error constant.
Definition error.h:62
Lumiera error handling (C++ interface).
const char * CStr
Definition error.hpp:42
unsigned long int ulong
Definition integral.hpp:31
Simple and lightweight helpers for metaprogramming and type detection.
std::string typeSymbol(TY const *obj=nullptr)
simple expressive symbol to designate a type
Implementation namespace for support and library code.
STL namespace.
basic_ostream< char, char_traits< char > > ostream
string _log_and_stringify(std::exception const &ex)
unsigned char uchar
std::string showSmartPtr(SP const &smPtr, std::string label="smP")
bool operator==(_Fmt const &left, _Fmt const &right)
Mix-Ins to allow or prohibit various degrees of copying and cloning.
Metaprogramming definitions to deal with dependency on implementation size and layout.
static void dump(CStr cString, Implementation &impl)
static void dump(const VAL *pVal, Implementation &impl)
static void dump(bool yes, Implementation &impl)
static void dump(lib::Literal const &literal, Implementation &impl)
static void dump(lib::Symbol const &symbol, Implementation &impl)
static void dump(const void *address, Implementation &impl)
helper to prepare parameters for inclusion
static void dump(VAL const &, Implementation &impl)
by default we don't allow to treat any types directly by boost::format.
Marker types to indicate a literal string and a Symbol.