Anklang 0.3.0-460-gc4ef46ba
ASE — Anklang Sound Engine (C++)

« « « Anklang Documentation
Loading...
Searching...
No Matches
formatter.hh
Go to the documentation of this file.
1 // This Source Code Form is licensed MPL-2.0: http://mozilla.org/MPL/2.0
2#ifndef __ASE_FORMATTER_HH__
3#define __ASE_FORMATTER_HH__
4
5#include <type_traits>
6#include <clocale>
7#include <cstdint>
8#include <sstream>
9#include <variant>
10#include <string>
11#include <list>
12
13namespace Ase {
14
16template<class ...Args> std::string string_format (const char *format, const Args &...args) __attribute__ ((__format__ (__printf__, 1, 0)));
17
19class ScopedPosixLocale final {
20 locale_t saved_locale_ = {};
21 void operator= (const ScopedPosixLocale&) = delete;
22 ScopedPosixLocale (const ScopedPosixLocale&) = delete;
23public:
24 explicit ScopedPosixLocale ();
25 virtual ~ScopedPosixLocale ();
26 static locale_t posix_locale();
27};
28
29// == Implementation Details ==
30namespace Impl {
31using StringFormatVariant = std::variant<uint64_t,double,const char*>;
33 using SL = std::list<std::string>; // use list to keep c_str() references stable
34 using StringFormatVariant::operator=;
35 void assign (const char *s, SL &h) { *this = s; }
36 void assign (const std::string &s, SL &h) { *this = s.c_str(); }
37 void assign (std::nullptr_t, SL &h) { *this = uint64_t (0); }
38 void assign (const void *p, SL &h) { *this = uint64_t (ptrdiff_t (p)); }
39 template<class T> typename std::enable_if<std::is_integral_v<T> || std::is_enum_v<T>, void>
40 ::type assign (const T &v, SL &h) { *this = uint64_t (v); }
41 template<class T> typename std::enable_if<std::is_floating_point_v<T>, void>
42 ::type assign (const T &v, SL &h) { *this = double (v); }
43 template<class T> typename std::enable_if<std::is_class<T>::value, void>
44 ::type assign (const T &o, SL &h) { std::ostringstream s; s << o; h.push_back (s.str()); *this = h.back().c_str(); }
45 static std::string string_format_args (const char *format, size_t N, const StringFormatArg *args);
46};
47} // Impl
48
63template<class ...Args> __attribute__ ((noinline)) std::string
64string_format (const char *format, const Args &...args)
65{
66 constexpr size_t N = sizeof... (Args);
67 Impl::StringFormatArg sfa[N ? N : 1];
68 size_t i = 0;
69 Impl::StringFormatArg::SL templist; // keep temporary strings across string_format_args()
70 (sfa[i++].assign (args, templist), ...); // C++17 fold expression
71 return sfa[0].string_format_args (format, N, sfa);
72}
73
74} // Ase
75
76#endif // __ASE_FORMATTER_HH__
Class to push the POSIX/C locale_t (UTF-8) for the scope of its lifetime.
Definition formatter.hh:19
typedef double
The Anklang C++ API namespace.
Definition api.hh:9
std::string string_format(const char *format, const Args &...args) __attribute__((__format__(__printf__
Format a string similar to sprintf(3) with support for std::string and std::ostringstream convertible...
typedef uint64_t
T str(T... args)