Rapicorn - Experimental UI Toolkit - Source Code
13.07.0
|
00001 // Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html 00002 #ifndef __RAPICORN_FORMATTER_HH__ 00003 #define __RAPICORN_FORMATTER_HH__ 00004 00005 #include <rcore/cxxaux.hh> 00006 #include <rcore/aida.hh> 00007 #include <sstream> 00008 00009 namespace Rapicorn { 00010 namespace Lib { // Namespace for implementation internals 00011 00012 // == StringFormatter == 00014 00021 class StringFormatter { 00022 typedef long long signed int LLong; 00023 typedef long long unsigned int ULLong; 00024 typedef long double LDouble; 00025 struct FormatArg { 00026 union { LDouble d; double f; signed char i1; short i2; int i4; long i6; LLong i8; void *p; const char *s; }; 00027 char kind; // f d i u p s 00028 }; 00029 inline void assign (FormatArg &farg, bool arg) { farg.kind = '1'; farg.i1 = arg; } 00030 inline void assign (FormatArg &farg, char arg) { farg.kind = '1'; farg.i1 = arg; } 00031 inline void assign (FormatArg &farg, signed char arg) { farg.kind = '1'; farg.i1 = arg; } 00032 inline void assign (FormatArg &farg, unsigned char arg) { farg.kind = '1'; farg.i1 = arg; } 00033 #if __SIZEOF_WCHAR_T__ == 1 00034 inline void assign (FormatArg &farg, wchar_t arg) { farg.kind = '1'; farg.i1 = arg; } 00035 #endif 00036 inline void assign (FormatArg &farg, short arg) { farg.kind = '2'; farg.i2 = arg; } 00037 inline void assign (FormatArg &farg, unsigned short arg) { farg.kind = '2'; farg.i2 = arg; } 00038 #if __SIZEOF_WCHAR_T__ == 2 00039 inline void assign (FormatArg &farg, wchar_t arg) { farg.kind = '2'; farg.i2 = arg; } 00040 #endif 00041 inline void assign (FormatArg &farg, int arg) { farg.kind = '4'; farg.i4 = arg; } 00042 inline void assign (FormatArg &farg, unsigned int arg) { farg.kind = '4'; farg.i4 = arg; } 00043 #if __SIZEOF_WCHAR_T__ == 4 00044 inline void assign (FormatArg &farg, wchar_t arg) { farg.kind = '4'; farg.i4 = arg; } 00045 #endif 00046 inline void assign (FormatArg &farg, long arg) { farg.kind = '6'; farg.i6 = arg; } 00047 inline void assign (FormatArg &farg, unsigned long arg) { farg.kind = '6'; farg.i6 = arg; } 00048 inline void assign (FormatArg &farg, long long arg) { farg.kind = '8'; farg.i8 = arg; } 00049 inline void assign (FormatArg &farg, unsigned long long arg) { farg.kind = '8'; farg.i8 = arg; } 00050 inline void assign (FormatArg &farg, float arg) { farg.kind = 'f'; farg.f = arg; } 00051 inline void assign (FormatArg &farg, double arg) { farg.kind = 'f'; farg.f = arg; } 00052 inline void assign (FormatArg &farg, long double arg) { farg.kind = 'd'; farg.d = arg; } 00053 inline void assign (FormatArg &farg, char *arg) { farg.kind = 's'; farg.s = arg; } 00054 inline void assign (FormatArg &farg, const char *arg) { farg.kind = 's'; farg.s = arg; } 00055 inline void assign (FormatArg &farg, const std::string &arg) { assign (farg, arg.c_str()); } 00056 inline void assign (FormatArg &farg, void *arg) { farg.kind = 'p'; farg.p = arg; } 00057 template<class T> inline void assign (FormatArg &farg, T *const &arg) { assign (farg, (void*) arg); } 00058 template<class T> typename std::enable_if<std::is_enum<T>::value, void> // eliminated via SFINAE 00059 ::type assign (FormatArg &farg, const T &arg) { farg.kind = '8'; farg.i8 = arg; } 00060 template<class T> typename std::enable_if<std::is_class<T>::value, void> // eliminated via SFINAE 00061 ::type assign (FormatArg &farg, const T &arg) 00062 { 00063 std::ostringstream os; 00064 os << arg; 00065 temporaries_.push_back (os.str()); 00066 assign (farg, temporaries_[temporaries_.size()-1]); 00067 } 00068 const FormatArg& format_arg (size_t nth); 00069 uint32_t arg_as_width (size_t nth); 00070 uint32_t arg_as_precision (size_t nth); 00071 LLong arg_as_longlong (size_t nth); 00072 LDouble arg_as_ldouble (size_t nth); 00073 const char* arg_as_chars (size_t nth); 00074 void* arg_as_ptr (size_t nth); 00075 struct Directive { 00076 char conversion; 00077 uint32_t adjust_left : 1, add_sign : 1, use_width : 1, use_precision : 1; 00078 uint32_t alternate_form : 1, zero_padding : 1, add_space : 1, locale_grouping : 1; 00079 uint32_t field_width, precision, start, end, value_index, width_index, precision_index; 00080 Directive() : 00081 conversion (0), adjust_left (0), add_sign (0), use_width (0), use_precision (0), 00082 alternate_form (0), zero_padding (0), add_space (0), locale_grouping (0), 00083 field_width (0), precision (0), start (0), end (0), value_index (0), width_index (0), precision_index (0) 00084 {} 00085 }; 00086 typedef std::function<String (const String&)> ArgTransform; 00087 FormatArg *const fargs_; 00088 const size_t nargs_; 00089 const int locale_context_; 00090 const ArgTransform &arg_transform_; 00091 vector<std::string> temporaries_; 00092 static std::string format_error (const char *err, const char *format, size_t directive); 00093 static const char* parse_directive (const char **stringp, size_t *indexp, Directive *dirp); 00094 std::string locale_format (size_t last, const char *format); 00095 std::string render_format (size_t last, const char *format); 00096 std::string render_directive (const Directive &dir); 00097 template<class A> std::string render_arg (const Directive &dir, const char *modifier, A arg); 00098 template<size_t N> inline std::string 00099 intern_format (const char *format) 00100 { 00101 return locale_format (N, format); 00102 } 00103 template<size_t N, class A, class ...Args> inline std::string 00104 intern_format (const char *format, const A &arg, const Args &...args) 00105 { 00106 assign (fargs_[N], arg); 00107 return intern_format<N+1> (format, args...); 00108 } 00109 template<size_t N> inline constexpr 00110 StringFormatter (const ArgTransform &arg_transform, size_t nargs, FormatArg (&mem)[N], int lc) : 00111 fargs_ (mem), nargs_ (nargs), locale_context_ (lc), arg_transform_ (arg_transform) {} 00112 public: 00113 enum LocaleContext { 00114 POSIX_LOCALE, 00115 CURRENT_LOCALE, 00116 }; 00117 template<LocaleContext LC = POSIX_LOCALE, class ...Args> 00118 static __attribute__ ((__format__ (printf, 2, 0), noinline)) std::string 00119 format (const ArgTransform &arg_transform, const char *format, const Args &...args) 00120 { 00121 constexpr size_t N = sizeof... (Args); 00122 FormatArg mem[N ? N : 1]; 00123 StringFormatter formatter (arg_transform, N, mem, LC); 00124 return formatter.intern_format<0> (format, args...); 00125 } 00126 }; 00127 00129 00130 } // Lib 00131 } // Rapicorn 00132 00133 #endif /* __RAPICORN_FORMATTER_HH__ */