/src/wxwidgets/include/wx/strvararg.h
Line | Count | Source |
1 | | /////////////////////////////////////////////////////////////////////////////// |
2 | | // Name: wx/strvararg.h |
3 | | // Purpose: macros for implementing type-safe vararg passing of strings |
4 | | // Author: Vaclav Slavik |
5 | | // Created: 2007-02-19 |
6 | | // Copyright: (c) 2007 REA Elektronik GmbH |
7 | | // Licence: wxWindows licence |
8 | | /////////////////////////////////////////////////////////////////////////////// |
9 | | |
10 | | /* |
11 | | This header contains helpers for implementing printf-like functions in |
12 | | wxWidgets as well as legacy WX_DEFINE_VARARG_FUNC macros that are not used |
13 | | by wxWidgets itself any more, but are preserved here as they can be used in |
14 | | the application code (even if they had never been part of documented API). |
15 | | |
16 | | The only non-deprecated parts of this header are wxFormatString class and |
17 | | wxFormatStringSpecifier and wxArgNormalizer templates, which are used by |
18 | | wxWidgets itself. |
19 | | */ |
20 | | |
21 | | #ifndef _WX_STRVARARG_H_ |
22 | | #define _WX_STRVARARG_H_ |
23 | | |
24 | | #include "wx/platform.h" |
25 | | |
26 | | #include "wx/cpp.h" |
27 | | #include "wx/chartype.h" |
28 | | #include "wx/strconv.h" |
29 | | #include "wx/buffer.h" |
30 | | #include "wx/unichar.h" |
31 | | |
32 | | #include <string> |
33 | | #include <type_traits> |
34 | | #include <vector> |
35 | | |
36 | | #ifdef __cpp_lib_string_view |
37 | | #include <string_view> |
38 | | #endif // __cpp_lib_string_view |
39 | | |
40 | | class WXDLLIMPEXP_FWD_BASE wxCStrData; |
41 | | class WXDLLIMPEXP_FWD_BASE wxString; |
42 | | |
43 | | // There are a lot of structs with intentionally private ctors in this file, |
44 | | // suppress gcc warnings about this. |
45 | | wxGCC_WARNING_SUPPRESS(ctor-dtor-privacy) |
46 | | |
47 | | // ---------------------------------------------------------------------------- |
48 | | // WX_DEFINE_VARARG_FUNC* macros |
49 | | // ---------------------------------------------------------------------------- |
50 | | |
51 | | // This macro is used to implement type-safe wrappers for variadic functions |
52 | | // that accept strings as arguments. This makes it possible to pass char*, |
53 | | // wchar_t* or even wxString (as opposed to having to use wxString::c_str()) |
54 | | // to e.g. wxPrintf(). |
55 | | // |
56 | | // This is done by defining a set of N template function taking 1..N arguments |
57 | | // (currently, N is set to 30 in this header). These functions are just thin |
58 | | // wrappers around another variadic function ('impl' or 'implUtf8' arguments, |
59 | | // see below) and the only thing the wrapper does is that it normalizes the |
60 | | // arguments passed in so that they are of the type expected by variadic |
61 | | // functions taking string arguments, i.e., char* or wchar_t*, depending on the |
62 | | // build: |
63 | | // * char* with UTF-8 encoding if wxUSE_UNICODE_UTF8 and the app is running |
64 | | // under an UTF-8 locale |
65 | | // * wchar_t* if wxUSE_UNICODE_WCHAR or if wxUSE_UNICODE_UTF8 and the current |
66 | | // locale is not UTF-8 |
67 | | // |
68 | | // Note that wxFormatString *must* be used for the format parameter of these |
69 | | // functions, otherwise the implementation won't work correctly. Furthermore, |
70 | | // it must be passed by value, not reference, because it's modified by the |
71 | | // vararg templates internally. |
72 | | // |
73 | | // Parameters: |
74 | | // [ there are examples in square brackets showing values of the parameters |
75 | | // for the wxFprintf() wrapper for fprintf() function with the following |
76 | | // prototype: |
77 | | // int wxFprintf(FILE *stream, const wxString& format, ...); ] |
78 | | // |
79 | | // rettype Functions' return type [int] |
80 | | // name Name of the function [fprintf] |
81 | | // numfixed The number of leading "fixed" (i.e., not variadic) |
82 | | // arguments of the function (e.g. "stream" and "format" |
83 | | // arguments of fprintf()); their type is _not_ converted |
84 | | // using wxArgNormalizer<T>, unlike the rest of |
85 | | // the function's arguments [2] |
86 | | // fixed List of types of the leading "fixed" arguments, in |
87 | | // parentheses [(FILE*,const wxString&)] |
88 | | // impl Name of the variadic function that implements 'name' for |
89 | | // the native strings representation (wchar_t* if |
90 | | // wxUSE_UNICODE_WCHAR or wxUSE_UNICODE_UTF8 when running under |
91 | | // non-UTF8 locale, char* otherwise) [wxCrt_Fprintf] |
92 | | // implUtf8 Like 'impl', but for the UTF-8 char* version to be used |
93 | | // if wxUSE_UNICODE_UTF8 and running under UTF-8 locale |
94 | | // (ignored otherwise) [fprintf] |
95 | | // |
96 | | #define WX_DEFINE_VARARG_FUNC(rettype, name, numfixed, fixed, impl, implUtf8) \ |
97 | | _WX_VARARG_DEFINE_FUNC_N0(rettype, name, impl, implUtf8, numfixed, fixed) \ |
98 | | WX_DEFINE_VARARG_FUNC_SANS_N0(rettype, name, numfixed, fixed, impl, implUtf8) |
99 | | |
100 | | // ditto, but without the version with 0 template/vararg arguments |
101 | | #define WX_DEFINE_VARARG_FUNC_SANS_N0(rettype, name, \ |
102 | | numfixed, fixed, impl, implUtf8) \ |
103 | | _WX_VARARG_ITER(_WX_VARARG_MAX_ARGS, \ |
104 | | _WX_VARARG_DEFINE_FUNC, \ |
105 | | rettype, name, impl, implUtf8, numfixed, fixed) |
106 | | |
107 | | // Like WX_DEFINE_VARARG_FUNC, but for variadic functions that don't return |
108 | | // a value. |
109 | | #define WX_DEFINE_VARARG_FUNC_VOID(name, numfixed, fixed, impl, implUtf8) \ |
110 | | _WX_VARARG_DEFINE_FUNC_VOID_N0(name, impl, implUtf8, numfixed, fixed) \ |
111 | | _WX_VARARG_ITER(_WX_VARARG_MAX_ARGS, \ |
112 | | _WX_VARARG_DEFINE_FUNC_VOID, \ |
113 | | void, name, impl, implUtf8, numfixed, fixed) |
114 | | |
115 | | // Like WX_DEFINE_VARARG_FUNC_VOID, but instead of wrapping an implementation |
116 | | // function, does nothing in defined functions' bodies. |
117 | | // |
118 | | // Used to implement wxLogXXX functions if wxUSE_LOG=0. |
119 | | #define WX_DEFINE_VARARG_FUNC_NOP(name, numfixed, fixed) \ |
120 | | _WX_VARARG_DEFINE_FUNC_NOP_N0(name, numfixed, fixed) \ |
121 | | _WX_VARARG_ITER(_WX_VARARG_MAX_ARGS, \ |
122 | | _WX_VARARG_DEFINE_FUNC_NOP, \ |
123 | | void, name, dummy, dummy, numfixed, fixed) |
124 | | |
125 | | // Like WX_DEFINE_VARARG_FUNC_CTOR, but for defining template constructors |
126 | | #define WX_DEFINE_VARARG_FUNC_CTOR(name, numfixed, fixed, impl, implUtf8) \ |
127 | | _WX_VARARG_DEFINE_FUNC_CTOR_N0(name, impl, implUtf8, numfixed, fixed) \ |
128 | | _WX_VARARG_ITER(_WX_VARARG_MAX_ARGS, \ |
129 | | _WX_VARARG_DEFINE_FUNC_CTOR, \ |
130 | | void, name, impl, implUtf8, numfixed, fixed) |
131 | | |
132 | | |
133 | | // ---------------------------------------------------------------------------- |
134 | | // wxFormatString |
135 | | // ---------------------------------------------------------------------------- |
136 | | |
137 | | // This class must be used for format string argument of the functions |
138 | | // defined using WX_DEFINE_VARARG_FUNC_* macros. It converts the string to |
139 | | // char* or wchar_t* for passing to implementation function efficiently (i.e. |
140 | | // without keeping the converted string in memory for longer than necessary, |
141 | | // like c_str()). It also converts format string to the correct form that |
142 | | // accounts for string changes done by wxArgNormalizer<> |
143 | | // |
144 | | // Note that this class can _only_ be used for function arguments! |
145 | | class WXDLLIMPEXP_BASE wxFormatString |
146 | | { |
147 | | public: |
148 | | #ifndef wxNO_IMPLICIT_WXSTRING_ENCODING |
149 | | wxFormatString(const char *str) |
150 | 0 | : m_char(wxScopedCharBuffer::CreateNonOwned(str)), m_str(nullptr), m_cstr(nullptr) {} |
151 | | #endif |
152 | | wxFormatString(const wchar_t *str) |
153 | 0 | : m_wchar(wxScopedWCharBuffer::CreateNonOwned(str)), m_str(nullptr), m_cstr(nullptr) {} |
154 | | wxFormatString(const wxString& str) |
155 | 0 | : m_str(&str), m_cstr(nullptr) {} |
156 | | wxFormatString(const wxCStrData& str) |
157 | 0 | : m_str(nullptr), m_cstr(&str) {} |
158 | | #ifndef wxNO_IMPLICIT_WXSTRING_ENCODING |
159 | | wxFormatString(const wxScopedCharBuffer& str) |
160 | 0 | : m_char(str), m_str(nullptr), m_cstr(nullptr) {} |
161 | | #endif |
162 | | wxFormatString(const wxScopedWCharBuffer& str) |
163 | 0 | : m_wchar(str), m_str(nullptr), m_cstr(nullptr) {} |
164 | | |
165 | | // Possible argument types. These are or-combinable for wxASSERT_ARG_TYPE |
166 | | // convenience. Some of the values are or-combined with another value, this |
167 | | // expresses "supertypes" for use with wxASSERT_ARG_TYPE masks. For example, |
168 | | // a char* string is also a pointer and an integer is also a char. |
169 | | enum ArgumentType |
170 | | { |
171 | | Arg_Unused = 0, // not used at all; the value of 0 is chosen to |
172 | | // conveniently pass wxASSERT_ARG_TYPE's check |
173 | | |
174 | | Arg_Char = 0x0001, // character as char %c |
175 | | Arg_Pointer = 0x0002, // %p |
176 | | Arg_String = 0x0004 | Arg_Pointer, // any form of string (%s and %p too) |
177 | | |
178 | | Arg_Int = 0x0008 | Arg_Char, // (ints can be used with %c) |
179 | | #if SIZEOF_INT == SIZEOF_LONG |
180 | | Arg_LongInt = Arg_Int, |
181 | | #else |
182 | | Arg_LongInt = 0x0010, |
183 | | #endif |
184 | | #if defined(SIZEOF_LONG_LONG) && SIZEOF_LONG_LONG == SIZEOF_LONG |
185 | | Arg_LongLongInt = Arg_LongInt, |
186 | | #else |
187 | | Arg_LongLongInt = 0x0020, |
188 | | #endif |
189 | | |
190 | | Arg_Double = 0x0040, |
191 | | Arg_LongDouble = 0x0080, |
192 | | |
193 | | #if defined(wxSIZE_T_IS_UINT) |
194 | | Arg_Size_t = Arg_Int, |
195 | | #elif defined(wxSIZE_T_IS_ULONG) |
196 | | Arg_Size_t = Arg_LongInt, |
197 | | #elif defined(SIZEOF_LONG_LONG) && SIZEOF_SIZE_T == SIZEOF_LONG_LONG |
198 | | Arg_Size_t = Arg_LongLongInt, |
199 | | #else |
200 | | Arg_Size_t = 0x0100, |
201 | | #endif |
202 | | |
203 | | Arg_IntPtr = 0x0200, // %n -- store # of chars written |
204 | | Arg_ShortIntPtr = 0x0400, |
205 | | Arg_LongIntPtr = 0x0800, |
206 | | |
207 | | Arg_Unknown = 0x8000 // unrecognized specifier (likely error) |
208 | | }; |
209 | | |
210 | | // Validate all format string parameters at once: the vector contains the |
211 | | // format specifiers corresponding to the actually given arguments. |
212 | | void Validate(const std::vector<int>& argTypes) const; |
213 | | |
214 | | // returns the type of format specifier for n-th variadic argument (this is |
215 | | // not necessarily n-th format specifier if positional specifiers are used); |
216 | | // called by wxArgNormalizer<> specializations to get information about |
217 | | // n-th variadic argument desired representation |
218 | | ArgumentType GetArgumentType(unsigned n) const; |
219 | | |
220 | | // returns the value passed to ctor, only converted to wxString, similarly |
221 | | // to other InputAsXXX() methods |
222 | | wxString InputAsString() const; |
223 | | |
224 | | #if !wxUSE_UNICODE_WCHAR && !defined wxNO_IMPLICIT_WXSTRING_ENCODING |
225 | | operator const char*() const |
226 | | { return const_cast<wxFormatString*>(this)->AsChar(); } |
227 | | private: |
228 | | // InputAsChar() returns the value passed to ctor, only converted |
229 | | // to char, while AsChar() takes the string returned by InputAsChar() |
230 | | // and does format string conversion on it as well (and similarly for |
231 | | // ..AsWChar() below) |
232 | | const char* InputAsChar(); |
233 | | const char* AsChar(); |
234 | | wxScopedCharBuffer m_convertedChar; |
235 | | #endif // !wxUSE_UNICODE_WCHAR && !defined wx_NO_IMPLICIT_WXSTRING_ENCODING |
236 | | |
237 | | #if !wxUSE_UTF8_LOCALE_ONLY |
238 | | public: |
239 | | operator const wchar_t*() const |
240 | 0 | { return const_cast<wxFormatString*>(this)->AsWChar(); } |
241 | | private: |
242 | | const wchar_t* InputAsWChar(); |
243 | | const wchar_t* AsWChar(); |
244 | | wxScopedWCharBuffer m_convertedWChar; |
245 | | #endif // !wxUSE_UTF8_LOCALE_ONLY |
246 | | |
247 | | private: |
248 | | wxScopedCharBuffer m_char; |
249 | | wxScopedWCharBuffer m_wchar; |
250 | | |
251 | | // NB: we can use a pointer here, because wxFormatString is only used |
252 | | // as function argument, so it has shorter life than the string |
253 | | // passed to the ctor |
254 | | const wxString * const m_str; |
255 | | const wxCStrData * const m_cstr; |
256 | | |
257 | | wxDECLARE_NO_ASSIGN_CLASS(wxFormatString); |
258 | | }; |
259 | | |
260 | | // these two helper classes are used to find wxFormatString argument among fixed |
261 | | // arguments passed to a vararg template |
262 | | struct wxFormatStringArgument |
263 | | { |
264 | 0 | wxFormatStringArgument(const wxFormatString *s = nullptr) : m_str(s) {} |
265 | | const wxFormatString *m_str; |
266 | | |
267 | | // overriding this operator allows us to reuse _WX_VARARG_JOIN macro |
268 | | wxFormatStringArgument operator,(const wxFormatStringArgument& a) const |
269 | 0 | { |
270 | 0 | wxASSERT_MSG( m_str == nullptr || a.m_str == nullptr, |
271 | 0 | "can't have two format strings in vararg function" ); |
272 | 0 | return wxFormatStringArgument(m_str ? m_str : a.m_str); |
273 | 0 | } |
274 | | |
275 | 0 | operator const wxFormatString*() const { return m_str; } |
276 | | }; |
277 | | |
278 | | template<typename T> |
279 | | struct wxFormatStringArgumentFinder |
280 | | { |
281 | | static wxFormatStringArgument find(T) |
282 | | { |
283 | | // by default, arguments are not format strings, so return "not found" |
284 | | return wxFormatStringArgument(); |
285 | | } |
286 | | }; |
287 | | |
288 | | template<> |
289 | | struct wxFormatStringArgumentFinder<const wxFormatString&> |
290 | | { |
291 | | static wxFormatStringArgument find(const wxFormatString& arg) |
292 | 0 | { return wxFormatStringArgument(&arg); } |
293 | | }; |
294 | | |
295 | | template<> |
296 | | struct wxFormatStringArgumentFinder<wxFormatString> |
297 | | : public wxFormatStringArgumentFinder<const wxFormatString&> {}; |
298 | | |
299 | | // avoid passing big objects by value to wxFormatStringArgumentFinder::find() |
300 | | // (and especially wx[W]CharBuffer with its auto_ptr<> style semantics!): |
301 | | template<> |
302 | | struct wxFormatStringArgumentFinder<wxString> |
303 | | : public wxFormatStringArgumentFinder<const wxString&> {}; |
304 | | |
305 | | template<> |
306 | | struct wxFormatStringArgumentFinder<wxScopedCharBuffer> |
307 | | : public wxFormatStringArgumentFinder<const wxScopedCharBuffer&> { |
308 | | #ifdef wxNO_IMPLICIT_WXSTRING_ENCODING |
309 | | private: |
310 | | wxFormatStringArgumentFinder() wxMEMBER_DELETE; |
311 | | #endif // wxNO_IMPLICIT_WXSTRING_ENCODING |
312 | | }; |
313 | | |
314 | | template<> |
315 | | struct wxFormatStringArgumentFinder<wxScopedWCharBuffer> |
316 | | : public wxFormatStringArgumentFinder<const wxScopedWCharBuffer&> {}; |
317 | | |
318 | | template<> |
319 | | struct wxFormatStringArgumentFinder<wxCharBuffer> |
320 | | : public wxFormatStringArgumentFinder<const wxCharBuffer&> { |
321 | | #ifdef wxNO_IMPLICIT_WXSTRING_ENCODING |
322 | | private: |
323 | | wxFormatStringArgumentFinder() wxMEMBER_DELETE; |
324 | | #endif // wxNO_IMPLICIT_WXSTRING_ENCODING |
325 | | }; |
326 | | |
327 | | template<> |
328 | | struct wxFormatStringArgumentFinder<wxWCharBuffer> |
329 | | : public wxFormatStringArgumentFinder<const wxWCharBuffer&> {}; |
330 | | |
331 | | |
332 | | // ---------------------------------------------------------------------------- |
333 | | // wxArgNormalizer*<T> converters |
334 | | // ---------------------------------------------------------------------------- |
335 | | |
336 | | #if wxDEBUG_LEVEL |
337 | | // Check that the format specifier for index-th argument in 'fmt' has |
338 | | // the correct type (one of wxFormatString::Arg_XXX or-combination in |
339 | | // 'expected_mask'). |
340 | | #define wxASSERT_ARG_TYPE(fmt, index, expected_mask) \ |
341 | 0 | wxSTATEMENT_MACRO_BEGIN \ |
342 | 0 | if ( !fmt ) \ |
343 | 0 | break; \ |
344 | 0 | const int argtype = fmt->GetArgumentType(index); \ |
345 | 0 | wxASSERT_MSG( (argtype & (expected_mask)) == argtype, \ |
346 | 0 | "format specifier doesn't match argument type" ); \ |
347 | 0 | wxSTATEMENT_MACRO_END |
348 | | #else |
349 | | // Just define it to suppress "unused parameter" warnings for the |
350 | | // parameters which we don't use otherwise |
351 | | #define wxASSERT_ARG_TYPE(fmt, index, expected_mask) \ |
352 | | wxUnusedVar(fmt); \ |
353 | | wxUnusedVar(index) |
354 | | |
355 | | // Also provide a trivial implementation of Validate() doing nothing in |
356 | | // this case. |
357 | | inline void |
358 | | wxFormatString::Validate(const std::vector<int>& WXUNUSED(argTypes)) const |
359 | | { |
360 | | } |
361 | | #endif // wxDEBUG_LEVEL/!wxDEBUG_LEVEL |
362 | | |
363 | | |
364 | | // Note: this type is misnamed, so that the error message is easier to |
365 | | // understand (no error happens for enums, because the IsEnum=true case is |
366 | | // specialized). |
367 | | template<bool IsEnum> |
368 | | struct wxFormatStringSpecifierNonPodType {}; |
369 | | |
370 | | template<> |
371 | | struct wxFormatStringSpecifierNonPodType<true> |
372 | | { |
373 | | enum { value = wxFormatString::Arg_Int }; |
374 | | }; |
375 | | |
376 | | template<typename T> |
377 | | struct wxFormatStringSpecifier |
378 | | { |
379 | | typedef std::is_enum<T> is_enum; |
380 | | enum { value = wxFormatStringSpecifierNonPodType<is_enum::value>::value }; |
381 | | }; |
382 | | |
383 | | template<typename T> |
384 | | struct wxFormatStringSpecifier<T*> |
385 | | { |
386 | | enum { value = wxFormatString::Arg_Pointer }; |
387 | | }; |
388 | | |
389 | | template<typename T> |
390 | | struct wxFormatStringSpecifier<const T*> |
391 | | { |
392 | | enum { value = wxFormatString::Arg_Pointer }; |
393 | | }; |
394 | | |
395 | | |
396 | | #define wxFORMAT_STRING_SPECIFIER(T, arg) \ |
397 | | template<> struct wxFormatStringSpecifier<T> \ |
398 | | { \ |
399 | | enum { value = arg }; \ |
400 | | }; |
401 | | |
402 | | #define wxDISABLED_FORMAT_STRING_SPECIFIER(T) \ |
403 | | template<> struct wxFormatStringSpecifier<T> \ |
404 | | { \ |
405 | | private: \ |
406 | | wxFormatStringSpecifier() wxMEMBER_DELETE; \ |
407 | | }; |
408 | | |
409 | | wxFORMAT_STRING_SPECIFIER(bool, wxFormatString::Arg_Int) |
410 | | wxFORMAT_STRING_SPECIFIER(char, wxFormatString::Arg_Char | wxFormatString::Arg_Int) |
411 | | wxFORMAT_STRING_SPECIFIER(signed char, wxFormatString::Arg_Char | wxFormatString::Arg_Int) |
412 | | wxFORMAT_STRING_SPECIFIER(unsigned char, wxFormatString::Arg_Char | wxFormatString::Arg_Int) |
413 | | wxFORMAT_STRING_SPECIFIER(int, wxFormatString::Arg_Int) |
414 | | wxFORMAT_STRING_SPECIFIER(unsigned int, wxFormatString::Arg_Int) |
415 | | wxFORMAT_STRING_SPECIFIER(short int, wxFormatString::Arg_Int) |
416 | | wxFORMAT_STRING_SPECIFIER(short unsigned int, wxFormatString::Arg_Int) |
417 | | wxFORMAT_STRING_SPECIFIER(long int, wxFormatString::Arg_LongInt) |
418 | | wxFORMAT_STRING_SPECIFIER(long unsigned int, wxFormatString::Arg_LongInt) |
419 | | wxFORMAT_STRING_SPECIFIER(wxLongLong_t, wxFormatString::Arg_LongLongInt) |
420 | | wxFORMAT_STRING_SPECIFIER(wxULongLong_t, wxFormatString::Arg_LongLongInt) |
421 | | wxFORMAT_STRING_SPECIFIER(float, wxFormatString::Arg_Double) |
422 | | wxFORMAT_STRING_SPECIFIER(double, wxFormatString::Arg_Double) |
423 | | wxFORMAT_STRING_SPECIFIER(long double, wxFormatString::Arg_LongDouble) |
424 | | |
425 | | #if wxWCHAR_T_IS_REAL_TYPE |
426 | | wxFORMAT_STRING_SPECIFIER(wchar_t, wxFormatString::Arg_Char | wxFormatString::Arg_Int) |
427 | | #endif |
428 | | wxFORMAT_STRING_SPECIFIER(wxUniChar, wxFormatString::Arg_Char | wxFormatString::Arg_Int) |
429 | | wxFORMAT_STRING_SPECIFIER(wxUniCharRef, wxFormatString::Arg_Char | wxFormatString::Arg_Int) |
430 | | |
431 | | #ifndef wxNO_IMPLICIT_WXSTRING_ENCODING |
432 | | wxFORMAT_STRING_SPECIFIER(char*, wxFormatString::Arg_String) |
433 | | wxFORMAT_STRING_SPECIFIER(unsigned char*, wxFormatString::Arg_String) |
434 | | wxFORMAT_STRING_SPECIFIER(signed char*, wxFormatString::Arg_String) |
435 | | wxFORMAT_STRING_SPECIFIER(const char*, wxFormatString::Arg_String) |
436 | | wxFORMAT_STRING_SPECIFIER(const unsigned char*, wxFormatString::Arg_String) |
437 | | wxFORMAT_STRING_SPECIFIER(const signed char*, wxFormatString::Arg_String) |
438 | | wxFORMAT_STRING_SPECIFIER(wxCharBuffer, wxFormatString::Arg_String) |
439 | | wxFORMAT_STRING_SPECIFIER(wxScopedCharBuffer, wxFormatString::Arg_String) |
440 | | wxFORMAT_STRING_SPECIFIER(std::string, wxFormatString::Arg_String) |
441 | | #ifdef __cpp_lib_string_view |
442 | | wxFORMAT_STRING_SPECIFIER(std::string_view, wxFormatString::Arg_String) |
443 | | #endif |
444 | | #else // wxNO_IMPLICIT_WXSTRING_ENCODING |
445 | | wxDISABLED_FORMAT_STRING_SPECIFIER(char*) |
446 | | wxDISABLED_FORMAT_STRING_SPECIFIER(unsigned char*) |
447 | | wxDISABLED_FORMAT_STRING_SPECIFIER(signed char*) |
448 | | wxDISABLED_FORMAT_STRING_SPECIFIER(const char*) |
449 | | wxDISABLED_FORMAT_STRING_SPECIFIER(const unsigned char*) |
450 | | wxDISABLED_FORMAT_STRING_SPECIFIER(const signed char*) |
451 | | #endif // wxNO_IMPLICIT_WXSTRING_ENCODING |
452 | | wxFORMAT_STRING_SPECIFIER(wchar_t*, wxFormatString::Arg_String) |
453 | | wxFORMAT_STRING_SPECIFIER(const wchar_t*, wxFormatString::Arg_String) |
454 | | |
455 | | wxFORMAT_STRING_SPECIFIER(wxWCharBuffer, wxFormatString::Arg_String) |
456 | | wxFORMAT_STRING_SPECIFIER(wxScopedWCharBuffer, wxFormatString::Arg_String) |
457 | | wxFORMAT_STRING_SPECIFIER(wxString, wxFormatString::Arg_String) |
458 | | wxFORMAT_STRING_SPECIFIER(wxCStrData, wxFormatString::Arg_String) |
459 | | wxFORMAT_STRING_SPECIFIER(std::wstring, wxFormatString::Arg_String) |
460 | | |
461 | | wxFORMAT_STRING_SPECIFIER(int*, wxFormatString::Arg_IntPtr | wxFormatString::Arg_Pointer) |
462 | | wxFORMAT_STRING_SPECIFIER(short int*, wxFormatString::Arg_ShortIntPtr | wxFormatString::Arg_Pointer) |
463 | | wxFORMAT_STRING_SPECIFIER(long int*, wxFormatString::Arg_LongIntPtr | wxFormatString::Arg_Pointer) |
464 | | |
465 | | #ifdef wxHAS_NULLPTR_T |
466 | | wxFORMAT_STRING_SPECIFIER(std::nullptr_t, wxFormatString::Arg_Pointer) |
467 | | #endif |
468 | | |
469 | | #undef wxFORMAT_STRING_SPECIFIER |
470 | | #undef wxDISABLED_FORMAT_STRING_SPECIFIER |
471 | | |
472 | | |
473 | | // Converts an argument passed to wxPrint etc. into standard form expected, |
474 | | // by wxXXX functions, e.g. all strings (wxString, char*, wchar_t*) are |
475 | | // converted into wchar_t* or char* depending on the build. |
476 | | template<typename T> |
477 | | struct wxArgNormalizer |
478 | | { |
479 | | // Ctor. 'value' is the value passed as variadic argument, 'fmt' is pointer |
480 | | // to printf-like format string or nullptr if the variadic function doesn't |
481 | | // use format string and 'index' is index of 'value' in variadic arguments |
482 | | // list (starting at 1) |
483 | | // |
484 | | // Because the format string and index are used for checking for the format |
485 | | // specifier mismatches and can be nullptr and 0, respectively, if they had |
486 | | // been already checked using wxFormatString::Validate(). |
487 | | wxArgNormalizer(T value, |
488 | | const wxFormatString *fmt, unsigned index) |
489 | 0 | : m_value(value) |
490 | 0 | { |
491 | 0 | wxASSERT_ARG_TYPE( fmt, index, wxFormatStringSpecifier<T>::value ); |
492 | 0 | } Unexecuted instantiation: wxArgNormalizer<unsigned int>::wxArgNormalizer(unsigned int, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizer<void*>::wxArgNormalizer(void*, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizer<unsigned long>::wxArgNormalizer(unsigned long, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizer<int>::wxArgNormalizer(int, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizer<long long>::wxArgNormalizer(long long, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizer<long>::wxArgNormalizer(long, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizer<unsigned short>::wxArgNormalizer(unsigned short, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizer<wxDateTime::WeekDay>::wxArgNormalizer(wxDateTime::WeekDay, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizer<wchar_t>::wxArgNormalizer(wchar_t, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizer<wchar_t const*>::wxArgNormalizer(wchar_t const*, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizer<unsigned long long>::wxArgNormalizer(unsigned long long, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizer<double>::wxArgNormalizer(double, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizer<wxFontEncoding>::wxArgNormalizer(wxFontEncoding, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizer<wxFDIOManager::Direction>::wxArgNormalizer(wxFDIOManager::Direction, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizer<bool>::wxArgNormalizer(bool, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizer<wxFDIOHandler*>::wxArgNormalizer(wxFDIOHandler*, wxFormatString const*, unsigned int) |
493 | | |
494 | | // Returns the value in a form that can be safely passed to real vararg |
495 | | // functions. In case of strings, this is char* in UTF-8-only build and |
496 | | // wchar_t* otherwise. |
497 | 0 | T get() const { return m_value; }Unexecuted instantiation: wxArgNormalizer<double>::get() const Unexecuted instantiation: wxArgNormalizer<long long>::get() const Unexecuted instantiation: wxArgNormalizer<unsigned long long>::get() const Unexecuted instantiation: wxArgNormalizer<unsigned int>::get() const Unexecuted instantiation: wxArgNormalizer<void*>::get() const Unexecuted instantiation: wxArgNormalizer<unsigned long>::get() const Unexecuted instantiation: wxArgNormalizer<int>::get() const Unexecuted instantiation: wxArgNormalizer<long>::get() const Unexecuted instantiation: wxArgNormalizer<unsigned short>::get() const Unexecuted instantiation: wxArgNormalizer<wxDateTime::WeekDay>::get() const Unexecuted instantiation: wxArgNormalizer<wchar_t>::get() const Unexecuted instantiation: wxArgNormalizer<wchar_t const*>::get() const Unexecuted instantiation: wxArgNormalizer<wxFontEncoding>::get() const Unexecuted instantiation: wxArgNormalizer<wxFDIOManager::Direction>::get() const Unexecuted instantiation: wxArgNormalizer<bool>::get() const Unexecuted instantiation: wxArgNormalizer<wxFDIOHandler*>::get() const |
498 | | |
499 | | T m_value; |
500 | | }; |
501 | | |
502 | | // normalizer for passing arguments to functions working with wchar_t* |
503 | | // string representation |
504 | | #if !wxUSE_UTF8_LOCALE_ONLY |
505 | | template<typename T> |
506 | | struct wxArgNormalizerWchar : public wxArgNormalizer<T> |
507 | | { |
508 | | wxArgNormalizerWchar(T value, |
509 | | const wxFormatString *fmt, unsigned index) |
510 | 0 | : wxArgNormalizer<T>(value, fmt, index) {}Unexecuted instantiation: wxArgNormalizerWchar<unsigned int>::wxArgNormalizerWchar(unsigned int, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<void*>::wxArgNormalizerWchar(void*, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<unsigned long>::wxArgNormalizerWchar(unsigned long, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<int>::wxArgNormalizerWchar(int, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<long long>::wxArgNormalizerWchar(long long, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<long>::wxArgNormalizerWchar(long, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<char>::wxArgNormalizerWchar(char, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<unsigned short>::wxArgNormalizerWchar(unsigned short, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<wxDateTime::WeekDay>::wxArgNormalizerWchar(wxDateTime::WeekDay, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<wchar_t>::wxArgNormalizerWchar(wchar_t, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<wchar_t const*>::wxArgNormalizerWchar(wchar_t const*, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<unsigned char>::wxArgNormalizerWchar(unsigned char, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<unsigned long long>::wxArgNormalizerWchar(unsigned long long, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<double>::wxArgNormalizerWchar(double, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<wxFontEncoding>::wxArgNormalizerWchar(wxFontEncoding, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<wxFDIOManager::Direction>::wxArgNormalizerWchar(wxFDIOManager::Direction, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<bool>::wxArgNormalizerWchar(bool, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<wxFDIOHandler*>::wxArgNormalizerWchar(wxFDIOHandler*, wxFormatString const*, unsigned int) |
511 | | }; |
512 | | |
513 | | #endif // !wxUSE_UTF8_LOCALE_ONLY |
514 | | |
515 | | // normalizer for passing arguments to functions working with UTF-8 encoded |
516 | | // char* strings |
517 | | #if wxUSE_UNICODE_UTF8 |
518 | | template<typename T> |
519 | | struct wxArgNormalizerUtf8 : public wxArgNormalizer<T> |
520 | | { |
521 | | wxArgNormalizerUtf8(T value, |
522 | | const wxFormatString *fmt, unsigned index) |
523 | | : wxArgNormalizer<T>(value, fmt, index) {} |
524 | | }; |
525 | | |
526 | | #define wxArgNormalizerNative wxArgNormalizerUtf8 |
527 | | #else // wxUSE_UNICODE_WCHAR |
528 | | #define wxArgNormalizerNative wxArgNormalizerWchar |
529 | | #endif // wxUSE_UNICODE_UTF8/wxUSE_UNICODE_WCHAR |
530 | | |
531 | | |
532 | | |
533 | | // special cases for converting strings: |
534 | | |
535 | | |
536 | | // base class for wxArgNormalizer<T> specializations that need to do conversion; |
537 | | // CharType is either wxStringCharType or wchar_t in UTF-8 build when wrapping |
538 | | // widechar CRT function |
539 | | template<typename CharType> |
540 | | struct wxArgNormalizerWithBuffer |
541 | | { |
542 | | typedef wxScopedCharTypeBuffer<CharType> CharBuffer; |
543 | | |
544 | | wxArgNormalizerWithBuffer() = default; |
545 | | wxArgNormalizerWithBuffer(const CharBuffer& buf, |
546 | | const wxFormatString *fmt, |
547 | | unsigned index) |
548 | 0 | : m_value(buf) |
549 | 0 | { |
550 | 0 | wxASSERT_ARG_TYPE( fmt, index, wxFormatString::Arg_String ); |
551 | 0 | } |
552 | | |
553 | 0 | const CharType *get() const { return m_value; } |
554 | | |
555 | | CharBuffer m_value; |
556 | | }; |
557 | | |
558 | | // string objects: |
559 | | template<> |
560 | | struct WXDLLIMPEXP_BASE wxArgNormalizerNative<const wxString&> |
561 | | { |
562 | | wxArgNormalizerNative(const wxString& s, |
563 | | const wxFormatString *fmt, |
564 | | unsigned index) |
565 | 0 | : m_value(s) |
566 | 0 | { |
567 | 0 | wxASSERT_ARG_TYPE( fmt, index, wxFormatString::Arg_String ); |
568 | 0 | } |
569 | | |
570 | | const wxStringCharType *get() const; |
571 | | |
572 | | const wxString& m_value; |
573 | | }; |
574 | | |
575 | | // c_str() values: |
576 | | template<> |
577 | | struct WXDLLIMPEXP_BASE wxArgNormalizerNative<const wxCStrData&> |
578 | | { |
579 | | wxArgNormalizerNative(const wxCStrData& value, |
580 | | const wxFormatString *fmt, |
581 | | unsigned index) |
582 | 0 | : m_value(value) |
583 | 0 | { |
584 | 0 | wxASSERT_ARG_TYPE( fmt, index, wxFormatString::Arg_String ); |
585 | 0 | } |
586 | | |
587 | | const wxStringCharType *get() const; |
588 | | |
589 | | const wxCStrData& m_value; |
590 | | }; |
591 | | |
592 | | // wxString/wxCStrData conversion to wchar_t* value |
593 | | #if wxUSE_UNICODE_UTF8 && !wxUSE_UTF8_LOCALE_ONLY |
594 | | template<> |
595 | | struct WXDLLIMPEXP_BASE wxArgNormalizerWchar<const wxString&> |
596 | | : public wxArgNormalizerWithBuffer<wchar_t> |
597 | | { |
598 | | wxArgNormalizerWchar(const wxString& s, |
599 | | const wxFormatString *fmt, unsigned index); |
600 | | }; |
601 | | |
602 | | template<> |
603 | | struct WXDLLIMPEXP_BASE wxArgNormalizerWchar<const wxCStrData&> |
604 | | : public wxArgNormalizerWithBuffer<wchar_t> |
605 | | { |
606 | | wxArgNormalizerWchar(const wxCStrData& s, |
607 | | const wxFormatString *fmt, unsigned index); |
608 | | }; |
609 | | #endif // wxUSE_UNICODE_UTF8 && !wxUSE_UTF8_LOCALE_ONLY |
610 | | |
611 | | |
612 | | // C string pointers of the wrong type (wchar_t* for UTF-8-only build, |
613 | | // char* otherwise): |
614 | | #if wxUSE_UNICODE_WCHAR |
615 | | |
616 | | #ifndef wxNO_IMPLICIT_WXSTRING_ENCODING |
617 | | template<> |
618 | | struct wxArgNormalizerWchar<const char*> |
619 | | : public wxArgNormalizerWithBuffer<wchar_t> |
620 | | { |
621 | | wxArgNormalizerWchar(const char* s, |
622 | | const wxFormatString *fmt, unsigned index) |
623 | 0 | : wxArgNormalizerWithBuffer<wchar_t>(wxConvLibc.cMB2WC(s), fmt, index) {} |
624 | | }; |
625 | | #endif // wxNO_IMPLICIT_WXSTRING_ENCODING |
626 | | |
627 | | #else // wxUSE_UNICODE_UTF8 |
628 | | |
629 | | template<> |
630 | | struct wxArgNormalizerUtf8<const wchar_t*> |
631 | | : public wxArgNormalizerWithBuffer<char> |
632 | | { |
633 | | wxArgNormalizerUtf8(const wchar_t* s, |
634 | | const wxFormatString *fmt, unsigned index) |
635 | | : wxArgNormalizerWithBuffer<char>(wxConvUTF8.cWC2MB(s), fmt, index) {} |
636 | | }; |
637 | | |
638 | | #ifndef wxNO_IMPLICIT_WXSTRING_ENCODING |
639 | | template<> |
640 | | struct wxArgNormalizerUtf8<const char*> |
641 | | : public wxArgNormalizerWithBuffer<char> |
642 | | { |
643 | | wxArgNormalizerUtf8(const char* s, |
644 | | const wxFormatString *fmt, |
645 | | unsigned index) |
646 | | { |
647 | | wxASSERT_ARG_TYPE( fmt, index, wxFormatString::Arg_String ); |
648 | | |
649 | | if ( wxLocaleIsUtf8 ) |
650 | | { |
651 | | m_value = wxScopedCharBuffer::CreateNonOwned(s); |
652 | | } |
653 | | else |
654 | | { |
655 | | // convert to widechar string first: |
656 | | wxScopedWCharBuffer buf(wxConvLibc.cMB2WC(s)); |
657 | | |
658 | | // then to UTF-8: |
659 | | if ( buf ) |
660 | | m_value = wxConvUTF8.cWC2MB(buf); |
661 | | } |
662 | | } |
663 | | }; |
664 | | #endif |
665 | | |
666 | | // UTF-8 build needs conversion to wchar_t* too: |
667 | | #if !wxUSE_UTF8_LOCALE_ONLY && !defined wxNO_IMPLICIT_WXSTRING_ENCODING |
668 | | template<> |
669 | | struct wxArgNormalizerWchar<const char*> |
670 | | : public wxArgNormalizerWithBuffer<wchar_t> |
671 | | { |
672 | | wxArgNormalizerWchar(const char* s, |
673 | | const wxFormatString *fmt, unsigned index) |
674 | | : wxArgNormalizerWithBuffer<wchar_t>(wxConvLibc.cMB2WC(s), fmt, index) {} |
675 | | }; |
676 | | #endif // !wxUSE_UTF8_LOCALE_ONLY && !defined wxNO_IMPLICIT_WXSTRING_ENCODING |
677 | | |
678 | | #endif // wxUSE_UNICODE_WCHAR/wxUSE_UNICODE_UTF8 |
679 | | |
680 | | |
681 | | #ifdef wxNO_IMPLICIT_WXSTRING_ENCODING |
682 | | // wxArgNormalizer specializations that cannot be instanced |
683 | | template<> |
684 | | struct wxArgNormalizer<const char*> { |
685 | | private: |
686 | | wxArgNormalizer(const char*, const wxFormatString *, unsigned); |
687 | | const char *get() const; |
688 | | }; |
689 | | template<> |
690 | | struct wxArgNormalizer<char*> { |
691 | | private: |
692 | | wxArgNormalizer(const char*, const wxFormatString *, unsigned); |
693 | | char *get() const; |
694 | | }; |
695 | | template<> |
696 | | struct wxArgNormalizer<const std::string> { |
697 | | private: |
698 | | wxArgNormalizer(const std::string&, const wxFormatString *, unsigned); |
699 | | std::string get() const; |
700 | | }; |
701 | | template<> |
702 | | struct wxArgNormalizer<std::string> { |
703 | | private: |
704 | | wxArgNormalizer(std::string&, const wxFormatString *, unsigned); |
705 | | std::string get() const; |
706 | | }; |
707 | | template<> |
708 | | struct wxArgNormalizer<wxCharBuffer> { |
709 | | private: |
710 | | wxArgNormalizer(wxCharBuffer&, const wxFormatString *, unsigned); |
711 | | std::string get() const; |
712 | | }; |
713 | | template<> |
714 | | struct wxArgNormalizer<wxScopedCharBuffer> { |
715 | | private: |
716 | | wxArgNormalizer(wxScopedCharBuffer&, const wxFormatString *, unsigned); |
717 | | std::string get() const; |
718 | | }; |
719 | | #endif // wxNO_IMPLICIT_WXSTRING_ENCODING |
720 | | |
721 | | // this macro is used to implement specialization that are exactly same as |
722 | | // some other specialization, i.e. to "forward" the implementation (e.g. for |
723 | | // T=wxString and T=const wxString&). Note that the ctor takes BaseT argument, |
724 | | // not T! |
725 | | #if wxUSE_UNICODE_UTF8 |
726 | | #if wxUSE_UTF8_LOCALE_ONLY |
727 | | #define WX_ARG_NORMALIZER_FORWARD(T, BaseT) \ |
728 | | _WX_ARG_NORMALIZER_FORWARD_IMPL(wxArgNormalizerUtf8, T, BaseT) |
729 | | #else // possibly non-UTF8 locales |
730 | | #define WX_ARG_NORMALIZER_FORWARD(T, BaseT) \ |
731 | | _WX_ARG_NORMALIZER_FORWARD_IMPL(wxArgNormalizerWchar, T, BaseT); \ |
732 | | _WX_ARG_NORMALIZER_FORWARD_IMPL(wxArgNormalizerUtf8, T, BaseT) |
733 | | #endif |
734 | | #else // wxUSE_UNICODE_WCHAR |
735 | | #define WX_ARG_NORMALIZER_FORWARD(T, BaseT) \ |
736 | | _WX_ARG_NORMALIZER_FORWARD_IMPL(wxArgNormalizerWchar, T, BaseT) |
737 | | #endif // wxUSE_UNICODE_UTF8/wxUSE_UNICODE_WCHAR |
738 | | |
739 | | #define _WX_ARG_NORMALIZER_FORWARD_IMPL(Normalizer, T, BaseT) \ |
740 | | template<> \ |
741 | | struct Normalizer<T> : public Normalizer<BaseT> \ |
742 | | { \ |
743 | | Normalizer(BaseT value, \ |
744 | | const wxFormatString *fmt, unsigned index) \ |
745 | 0 | : Normalizer<BaseT>(value, fmt, index) {} \Unexecuted instantiation: wxArgNormalizerWchar<wxString>::wxArgNormalizerWchar(wxString const&, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<wxCStrData>::wxArgNormalizerWchar(wxCStrData const&, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<char*>::wxArgNormalizerWchar(char const*, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<wchar_t*>::wxArgNormalizerWchar(wchar_t const*, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<wxScopedCharTypeBuffer<char> >::wxArgNormalizerWchar(char const*, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<wxScopedCharTypeBuffer<char> const&>::wxArgNormalizerWchar(char const*, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<wxScopedCharTypeBuffer<wchar_t> >::wxArgNormalizerWchar(wchar_t const*, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<wxScopedCharTypeBuffer<wchar_t> const&>::wxArgNormalizerWchar(wchar_t const*, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<wxCharBuffer>::wxArgNormalizerWchar(char const*, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<wxCharBuffer const&>::wxArgNormalizerWchar(char const*, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<wxWCharBuffer>::wxArgNormalizerWchar(wchar_t const*, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<wxWCharBuffer const&>::wxArgNormalizerWchar(wchar_t const*, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >::wxArgNormalizerWchar(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<std::__1::basic_string_view<char, std::__1::char_traits<char> > >::wxArgNormalizerWchar(std::__1::basic_string_view<char, std::__1::char_traits<char> > const&, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > >::wxArgNormalizerWchar(std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > const&, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<wxUniChar>::wxArgNormalizerWchar(wxUniChar const&, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<wxUniCharRef const&>::wxArgNormalizerWchar(wxUniChar const&, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<wxUniCharRef>::wxArgNormalizerWchar(wxUniChar const&, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<wchar_t const&>::wxArgNormalizerWchar(wchar_t, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<char const&>::wxArgNormalizerWchar(char, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<unsigned char const&>::wxArgNormalizerWchar(unsigned char, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerWchar<signed char const&>::wxArgNormalizerWchar(signed char, wxFormatString const*, unsigned int) |
746 | | } |
747 | | |
748 | | // non-reference versions of specializations for string objects |
749 | | WX_ARG_NORMALIZER_FORWARD(wxString, const wxString&); |
750 | | WX_ARG_NORMALIZER_FORWARD(wxCStrData, const wxCStrData&); |
751 | | |
752 | | // versions for passing non-const pointers: |
753 | | #ifndef wxNO_IMPLICIT_WXSTRING_ENCODING |
754 | | WX_ARG_NORMALIZER_FORWARD(char*, const char*); |
755 | | #endif |
756 | | WX_ARG_NORMALIZER_FORWARD(wchar_t*, const wchar_t*); |
757 | | |
758 | | // versions for passing wx[W]CharBuffer: |
759 | | #ifndef wxNO_IMPLICIT_WXSTRING_ENCODING |
760 | | WX_ARG_NORMALIZER_FORWARD(wxScopedCharBuffer, const char*); |
761 | | WX_ARG_NORMALIZER_FORWARD(const wxScopedCharBuffer&, const char*); |
762 | | #endif |
763 | | WX_ARG_NORMALIZER_FORWARD(wxScopedWCharBuffer, const wchar_t*); |
764 | | WX_ARG_NORMALIZER_FORWARD(const wxScopedWCharBuffer&, const wchar_t*); |
765 | | #ifndef wxNO_IMPLICIT_WXSTRING_ENCODING |
766 | | WX_ARG_NORMALIZER_FORWARD(wxCharBuffer, const char*); |
767 | | WX_ARG_NORMALIZER_FORWARD(const wxCharBuffer&, const char*); |
768 | | #endif |
769 | | WX_ARG_NORMALIZER_FORWARD(wxWCharBuffer, const wchar_t*); |
770 | | WX_ARG_NORMALIZER_FORWARD(const wxWCharBuffer&, const wchar_t*); |
771 | | |
772 | | // versions for std::[w]string and string_view, if we have it. |
773 | | #if !wxUSE_UTF8_LOCALE_ONLY |
774 | | #ifndef wxNO_IMPLICIT_WXSTRING_ENCODING |
775 | | template<> |
776 | | struct wxArgNormalizerWchar<const std::string&> |
777 | | : public wxArgNormalizerWchar<const char*> |
778 | | { |
779 | | wxArgNormalizerWchar(const std::string& s, |
780 | | const wxFormatString *fmt, unsigned index) |
781 | 0 | : wxArgNormalizerWchar<const char*>(s.c_str(), fmt, index) {} |
782 | | }; |
783 | | |
784 | | #ifdef __cpp_lib_string_view |
785 | | // This is inefficient because we create a temporary string rather than using |
786 | | // the string_view directly, but is required because the rest of the code |
787 | | // assumes NUL-terminated strings and is still better than nothing (i.e. no |
788 | | // support for std::string_view at all). |
789 | | template<> |
790 | | struct wxArgNormalizerWchar<const std::string_view&> |
791 | | : public wxArgNormalizerWchar<const std::string&> |
792 | | { |
793 | | wxArgNormalizerWchar(const std::string_view& v, |
794 | | const wxFormatString *fmt, unsigned index) |
795 | 0 | : wxArgNormalizerWchar<const std::string&>(std::string{v}, fmt, index) {} |
796 | | }; |
797 | | #endif // __cpp_lib_string_view |
798 | | |
799 | | #endif // NO_IMPLICIT_WXSTRING_ENCODING |
800 | | |
801 | | template<> |
802 | | struct wxArgNormalizerWchar<const std::wstring&> |
803 | | : public wxArgNormalizerWchar<const wchar_t*> |
804 | | { |
805 | | wxArgNormalizerWchar(const std::wstring& s, |
806 | | const wxFormatString *fmt, unsigned index) |
807 | 0 | : wxArgNormalizerWchar<const wchar_t*>(s.c_str(), fmt, index) {} |
808 | | }; |
809 | | #endif // !wxUSE_UTF8_LOCALE_ONLY |
810 | | |
811 | | #if wxUSE_UNICODE_UTF8 |
812 | | #ifndef wxNO_IMPLICIT_WXSTRING_ENCODING |
813 | | template<> |
814 | | struct wxArgNormalizerUtf8<const std::string&> |
815 | | : public wxArgNormalizerUtf8<const char*> |
816 | | { |
817 | | wxArgNormalizerUtf8(const std::string& s, |
818 | | const wxFormatString *fmt, unsigned index) |
819 | | : wxArgNormalizerUtf8<const char*>(s.c_str(), fmt, index) {} |
820 | | }; |
821 | | |
822 | | #ifdef __cpp_lib_string_view |
823 | | template<> |
824 | | struct wxArgNormalizerUtf8<const std::string_view&> |
825 | | { |
826 | | wxArgNormalizerUtf8(const std::string_view& v, |
827 | | const wxFormatString *fmt, unsigned index) |
828 | | : m_str{v} |
829 | | { |
830 | | wxASSERT_ARG_TYPE( fmt, index, wxFormatString::Arg_String ); |
831 | | } |
832 | | |
833 | | const char* get() const { return m_str.c_str(); } |
834 | | |
835 | | // We need to store this string to ensure that we use a NUL-terminated |
836 | | // buffer, i.e. we can't use string_view data directly. |
837 | | const std::string m_str; |
838 | | }; |
839 | | #endif // __cpp_lib_string_view |
840 | | |
841 | | #endif // wxNO_IMPLICIT_WXSTRING_ENCODING |
842 | | |
843 | | template<> |
844 | | struct wxArgNormalizerUtf8<const std::wstring&> |
845 | | : public wxArgNormalizerUtf8<const wchar_t*> |
846 | | { |
847 | | wxArgNormalizerUtf8(const std::wstring& s, |
848 | | const wxFormatString *fmt, unsigned index) |
849 | | : wxArgNormalizerUtf8<const wchar_t*>(s.c_str(), fmt, index) {} |
850 | | }; |
851 | | #endif // wxUSE_UNICODE_UTF8 |
852 | | |
853 | | #ifndef wxNO_IMPLICIT_WXSTRING_ENCODING |
854 | | WX_ARG_NORMALIZER_FORWARD(std::string, const std::string&); |
855 | | #ifdef __cpp_lib_string_view |
856 | | WX_ARG_NORMALIZER_FORWARD(std::string_view, const std::string_view&); |
857 | | #endif // __cpp_lib_string_view |
858 | | #endif |
859 | | WX_ARG_NORMALIZER_FORWARD(std::wstring, const std::wstring&); |
860 | | |
861 | | |
862 | | // versions for wxUniChar, wxUniCharRef: |
863 | | // (this is same for UTF-8 and Wchar builds, we just convert to wchar_t) |
864 | | template<> |
865 | | struct wxArgNormalizer<const wxUniChar&> : public wxArgNormalizer<wchar_t> |
866 | | { |
867 | | wxArgNormalizer(const wxUniChar& s, |
868 | | const wxFormatString *fmt, unsigned index) |
869 | 0 | : wxArgNormalizer<wchar_t>(wx_truncate_cast(wchar_t, s.GetValue()), fmt, index) {} |
870 | | }; |
871 | | |
872 | | // for wchar_t, default handler does the right thing |
873 | | |
874 | | // char has to be treated differently: a char argument may |
875 | | // be used either for a character value (which should be converted into |
876 | | // wxUniChar) or as an integer value (which should be left as-is). We take |
877 | | // advantage of the fact that both char and wchar_t are converted into int |
878 | | // in variadic arguments here. |
879 | | template<typename T> |
880 | | struct wxArgNormalizerNarrowChar |
881 | | { |
882 | | wxArgNormalizerNarrowChar(T value, |
883 | | const wxFormatString *fmt, unsigned index) |
884 | 0 | { |
885 | 0 | wxASSERT_ARG_TYPE( fmt, index, |
886 | 0 | wxFormatString::Arg_Char | wxFormatString::Arg_Int ); |
887 | |
|
888 | 0 | if ( fmt && fmt->GetArgumentType(index) == wxFormatString::Arg_Char ) |
889 | 0 | m_value = wx_truncate_cast(T, wxUniChar(value).GetValue()); |
890 | 0 | else |
891 | 0 | m_value = value; |
892 | 0 | } Unexecuted instantiation: wxArgNormalizerNarrowChar<char>::wxArgNormalizerNarrowChar(char, wxFormatString const*, unsigned int) Unexecuted instantiation: wxArgNormalizerNarrowChar<unsigned char>::wxArgNormalizerNarrowChar(unsigned char, wxFormatString const*, unsigned int) |
893 | | |
894 | 0 | int get() const { return m_value; }Unexecuted instantiation: wxArgNormalizerNarrowChar<char>::get() const Unexecuted instantiation: wxArgNormalizerNarrowChar<unsigned char>::get() const |
895 | | |
896 | | T m_value; |
897 | | }; |
898 | | |
899 | | template<> |
900 | | struct wxArgNormalizer<char> : public wxArgNormalizerNarrowChar<char> |
901 | | { |
902 | | wxArgNormalizer(char value, |
903 | | const wxFormatString *fmt, unsigned index) |
904 | 0 | : wxArgNormalizerNarrowChar<char>(value, fmt, index) {} |
905 | | }; |
906 | | |
907 | | template<> |
908 | | struct wxArgNormalizer<unsigned char> |
909 | | : public wxArgNormalizerNarrowChar<unsigned char> |
910 | | { |
911 | | wxArgNormalizer(unsigned char value, |
912 | | const wxFormatString *fmt, unsigned index) |
913 | 0 | : wxArgNormalizerNarrowChar<unsigned char>(value, fmt, index) {} |
914 | | }; |
915 | | |
916 | | template<> |
917 | | struct wxArgNormalizer<signed char> |
918 | | : public wxArgNormalizerNarrowChar<signed char> |
919 | | { |
920 | | wxArgNormalizer(signed char value, |
921 | | const wxFormatString *fmt, unsigned index) |
922 | 0 | : wxArgNormalizerNarrowChar<signed char>(value, fmt, index) {} |
923 | | }; |
924 | | |
925 | | // convert references: |
926 | | WX_ARG_NORMALIZER_FORWARD(wxUniChar, const wxUniChar&); |
927 | | WX_ARG_NORMALIZER_FORWARD(const wxUniCharRef&, const wxUniChar&); |
928 | | WX_ARG_NORMALIZER_FORWARD(wxUniCharRef, const wxUniChar&); |
929 | | WX_ARG_NORMALIZER_FORWARD(const wchar_t&, wchar_t); |
930 | | |
931 | | WX_ARG_NORMALIZER_FORWARD(const char&, char); |
932 | | WX_ARG_NORMALIZER_FORWARD(const unsigned char&, unsigned char); |
933 | | WX_ARG_NORMALIZER_FORWARD(const signed char&, signed char); |
934 | | |
935 | | |
936 | | #undef WX_ARG_NORMALIZER_FORWARD |
937 | | #undef _WX_ARG_NORMALIZER_FORWARD_IMPL |
938 | | |
939 | | // NB: Don't #undef wxASSERT_ARG_TYPE here as it's also used in wx/longlong.h. |
940 | | |
941 | | // ---------------------------------------------------------------------------- |
942 | | // WX_VA_ARG_STRING |
943 | | // ---------------------------------------------------------------------------- |
944 | | |
945 | | // Replacement for va_arg() for use with strings in functions that accept |
946 | | // strings normalized by wxArgNormalizer<T>: |
947 | | |
948 | | struct WXDLLIMPEXP_BASE wxArgNormalizedString |
949 | | { |
950 | 0 | wxArgNormalizedString(const void* ptr) : m_ptr(ptr) {} |
951 | | |
952 | | // returns true if non-null string was passed in |
953 | 0 | bool IsValid() const { return m_ptr != nullptr; } |
954 | 0 | operator bool() const { return IsValid(); } |
955 | | |
956 | | // extracts the string, returns empty string if nullptr was passed in |
957 | | wxString GetString() const; |
958 | | operator wxString() const; |
959 | | |
960 | | private: |
961 | | const void *m_ptr; |
962 | | }; |
963 | | |
964 | | #define WX_VA_ARG_STRING(ap) wxArgNormalizedString(va_arg(ap, const void*)) |
965 | | |
966 | | // ---------------------------------------------------------------------------- |
967 | | // implementation of the WX_DEFINE_VARARG_* macros |
968 | | // ---------------------------------------------------------------------------- |
969 | | |
970 | | // NB: The vararg emulation code is limited to 30 variadic and 4 fixed |
971 | | // arguments at the moment. |
972 | | // If you need more variadic arguments, you need to |
973 | | // 1) increase the value of _WX_VARARG_MAX_ARGS |
974 | | // 2) add _WX_VARARG_JOIN_* and _WX_VARARG_ITER_* up to the new |
975 | | // _WX_VARARG_MAX_ARGS value to the lists below |
976 | | // If you need more fixed arguments, you need to |
977 | | // 1) increase the value of _WX_VARARG_MAX_FIXED_ARGS |
978 | | // 2) add _WX_VARARG_FIXED_EXPAND_* and _WX_VARARG_FIXED_UNUSED_EXPAND_* |
979 | | // macros below |
980 | | #define _WX_VARARG_MAX_ARGS 30 |
981 | | #define _WX_VARARG_MAX_FIXED_ARGS 4 |
982 | | |
983 | 0 | #define _WX_VARARG_JOIN_1(m) m(1) |
984 | 0 | #define _WX_VARARG_JOIN_2(m) _WX_VARARG_JOIN_1(m), m(2) |
985 | 0 | #define _WX_VARARG_JOIN_3(m) _WX_VARARG_JOIN_2(m), m(3) |
986 | | #define _WX_VARARG_JOIN_4(m) _WX_VARARG_JOIN_3(m), m(4) |
987 | | #define _WX_VARARG_JOIN_5(m) _WX_VARARG_JOIN_4(m), m(5) |
988 | | #define _WX_VARARG_JOIN_6(m) _WX_VARARG_JOIN_5(m), m(6) |
989 | | #define _WX_VARARG_JOIN_7(m) _WX_VARARG_JOIN_6(m), m(7) |
990 | | #define _WX_VARARG_JOIN_8(m) _WX_VARARG_JOIN_7(m), m(8) |
991 | | #define _WX_VARARG_JOIN_9(m) _WX_VARARG_JOIN_8(m), m(9) |
992 | | #define _WX_VARARG_JOIN_10(m) _WX_VARARG_JOIN_9(m), m(10) |
993 | | #define _WX_VARARG_JOIN_11(m) _WX_VARARG_JOIN_10(m), m(11) |
994 | | #define _WX_VARARG_JOIN_12(m) _WX_VARARG_JOIN_11(m), m(12) |
995 | | #define _WX_VARARG_JOIN_13(m) _WX_VARARG_JOIN_12(m), m(13) |
996 | | #define _WX_VARARG_JOIN_14(m) _WX_VARARG_JOIN_13(m), m(14) |
997 | | #define _WX_VARARG_JOIN_15(m) _WX_VARARG_JOIN_14(m), m(15) |
998 | | #define _WX_VARARG_JOIN_16(m) _WX_VARARG_JOIN_15(m), m(16) |
999 | | #define _WX_VARARG_JOIN_17(m) _WX_VARARG_JOIN_16(m), m(17) |
1000 | | #define _WX_VARARG_JOIN_18(m) _WX_VARARG_JOIN_17(m), m(18) |
1001 | | #define _WX_VARARG_JOIN_19(m) _WX_VARARG_JOIN_18(m), m(19) |
1002 | | #define _WX_VARARG_JOIN_20(m) _WX_VARARG_JOIN_19(m), m(20) |
1003 | | #define _WX_VARARG_JOIN_21(m) _WX_VARARG_JOIN_20(m), m(21) |
1004 | | #define _WX_VARARG_JOIN_22(m) _WX_VARARG_JOIN_21(m), m(22) |
1005 | | #define _WX_VARARG_JOIN_23(m) _WX_VARARG_JOIN_22(m), m(23) |
1006 | | #define _WX_VARARG_JOIN_24(m) _WX_VARARG_JOIN_23(m), m(24) |
1007 | | #define _WX_VARARG_JOIN_25(m) _WX_VARARG_JOIN_24(m), m(25) |
1008 | | #define _WX_VARARG_JOIN_26(m) _WX_VARARG_JOIN_25(m), m(26) |
1009 | | #define _WX_VARARG_JOIN_27(m) _WX_VARARG_JOIN_26(m), m(27) |
1010 | | #define _WX_VARARG_JOIN_28(m) _WX_VARARG_JOIN_27(m), m(28) |
1011 | | #define _WX_VARARG_JOIN_29(m) _WX_VARARG_JOIN_28(m), m(29) |
1012 | | #define _WX_VARARG_JOIN_30(m) _WX_VARARG_JOIN_29(m), m(30) |
1013 | | |
1014 | | #define _WX_VARARG_ITER_1(m,a,b,c,d,e,f) m(1,a,b,c,d,e,f) |
1015 | | #define _WX_VARARG_ITER_2(m,a,b,c,d,e,f) _WX_VARARG_ITER_1(m,a,b,c,d,e,f) m(2,a,b,c,d,e,f) |
1016 | | #define _WX_VARARG_ITER_3(m,a,b,c,d,e,f) _WX_VARARG_ITER_2(m,a,b,c,d,e,f) m(3,a,b,c,d,e,f) |
1017 | | #define _WX_VARARG_ITER_4(m,a,b,c,d,e,f) _WX_VARARG_ITER_3(m,a,b,c,d,e,f) m(4,a,b,c,d,e,f) |
1018 | | #define _WX_VARARG_ITER_5(m,a,b,c,d,e,f) _WX_VARARG_ITER_4(m,a,b,c,d,e,f) m(5,a,b,c,d,e,f) |
1019 | | #define _WX_VARARG_ITER_6(m,a,b,c,d,e,f) _WX_VARARG_ITER_5(m,a,b,c,d,e,f) m(6,a,b,c,d,e,f) |
1020 | | #define _WX_VARARG_ITER_7(m,a,b,c,d,e,f) _WX_VARARG_ITER_6(m,a,b,c,d,e,f) m(7,a,b,c,d,e,f) |
1021 | | #define _WX_VARARG_ITER_8(m,a,b,c,d,e,f) _WX_VARARG_ITER_7(m,a,b,c,d,e,f) m(8,a,b,c,d,e,f) |
1022 | | #define _WX_VARARG_ITER_9(m,a,b,c,d,e,f) _WX_VARARG_ITER_8(m,a,b,c,d,e,f) m(9,a,b,c,d,e,f) |
1023 | | #define _WX_VARARG_ITER_10(m,a,b,c,d,e,f) _WX_VARARG_ITER_9(m,a,b,c,d,e,f) m(10,a,b,c,d,e,f) |
1024 | | #define _WX_VARARG_ITER_11(m,a,b,c,d,e,f) _WX_VARARG_ITER_10(m,a,b,c,d,e,f) m(11,a,b,c,d,e,f) |
1025 | | #define _WX_VARARG_ITER_12(m,a,b,c,d,e,f) _WX_VARARG_ITER_11(m,a,b,c,d,e,f) m(12,a,b,c,d,e,f) |
1026 | | #define _WX_VARARG_ITER_13(m,a,b,c,d,e,f) _WX_VARARG_ITER_12(m,a,b,c,d,e,f) m(13,a,b,c,d,e,f) |
1027 | | #define _WX_VARARG_ITER_14(m,a,b,c,d,e,f) _WX_VARARG_ITER_13(m,a,b,c,d,e,f) m(14,a,b,c,d,e,f) |
1028 | | #define _WX_VARARG_ITER_15(m,a,b,c,d,e,f) _WX_VARARG_ITER_14(m,a,b,c,d,e,f) m(15,a,b,c,d,e,f) |
1029 | | #define _WX_VARARG_ITER_16(m,a,b,c,d,e,f) _WX_VARARG_ITER_15(m,a,b,c,d,e,f) m(16,a,b,c,d,e,f) |
1030 | | #define _WX_VARARG_ITER_17(m,a,b,c,d,e,f) _WX_VARARG_ITER_16(m,a,b,c,d,e,f) m(17,a,b,c,d,e,f) |
1031 | | #define _WX_VARARG_ITER_18(m,a,b,c,d,e,f) _WX_VARARG_ITER_17(m,a,b,c,d,e,f) m(18,a,b,c,d,e,f) |
1032 | | #define _WX_VARARG_ITER_19(m,a,b,c,d,e,f) _WX_VARARG_ITER_18(m,a,b,c,d,e,f) m(19,a,b,c,d,e,f) |
1033 | | #define _WX_VARARG_ITER_20(m,a,b,c,d,e,f) _WX_VARARG_ITER_19(m,a,b,c,d,e,f) m(20,a,b,c,d,e,f) |
1034 | | #define _WX_VARARG_ITER_21(m,a,b,c,d,e,f) _WX_VARARG_ITER_20(m,a,b,c,d,e,f) m(21,a,b,c,d,e,f) |
1035 | | #define _WX_VARARG_ITER_22(m,a,b,c,d,e,f) _WX_VARARG_ITER_21(m,a,b,c,d,e,f) m(22,a,b,c,d,e,f) |
1036 | | #define _WX_VARARG_ITER_23(m,a,b,c,d,e,f) _WX_VARARG_ITER_22(m,a,b,c,d,e,f) m(23,a,b,c,d,e,f) |
1037 | | #define _WX_VARARG_ITER_24(m,a,b,c,d,e,f) _WX_VARARG_ITER_23(m,a,b,c,d,e,f) m(24,a,b,c,d,e,f) |
1038 | | #define _WX_VARARG_ITER_25(m,a,b,c,d,e,f) _WX_VARARG_ITER_24(m,a,b,c,d,e,f) m(25,a,b,c,d,e,f) |
1039 | | #define _WX_VARARG_ITER_26(m,a,b,c,d,e,f) _WX_VARARG_ITER_25(m,a,b,c,d,e,f) m(26,a,b,c,d,e,f) |
1040 | | #define _WX_VARARG_ITER_27(m,a,b,c,d,e,f) _WX_VARARG_ITER_26(m,a,b,c,d,e,f) m(27,a,b,c,d,e,f) |
1041 | | #define _WX_VARARG_ITER_28(m,a,b,c,d,e,f) _WX_VARARG_ITER_27(m,a,b,c,d,e,f) m(28,a,b,c,d,e,f) |
1042 | | #define _WX_VARARG_ITER_29(m,a,b,c,d,e,f) _WX_VARARG_ITER_28(m,a,b,c,d,e,f) m(29,a,b,c,d,e,f) |
1043 | | #define _WX_VARARG_ITER_30(m,a,b,c,d,e,f) _WX_VARARG_ITER_29(m,a,b,c,d,e,f) m(30,a,b,c,d,e,f) |
1044 | | |
1045 | | |
1046 | | #define _WX_VARARG_FIXED_EXPAND_1(t1) \ |
1047 | | t1 f1 |
1048 | | #define _WX_VARARG_FIXED_EXPAND_2(t1,t2) \ |
1049 | | t1 f1, t2 f2 |
1050 | | #define _WX_VARARG_FIXED_EXPAND_3(t1,t2,t3) \ |
1051 | | t1 f1, t2 f2, t3 f3 |
1052 | | #define _WX_VARARG_FIXED_EXPAND_4(t1,t2,t3,t4) \ |
1053 | | t1 f1, t2 f2, t3 f3, t4 f4 |
1054 | | |
1055 | | #define _WX_VARARG_FIXED_UNUSED_EXPAND_1(t1) \ |
1056 | | t1 WXUNUSED(f1) |
1057 | | #define _WX_VARARG_FIXED_UNUSED_EXPAND_2(t1,t2) \ |
1058 | | t1 WXUNUSED(f1), t2 WXUNUSED(f2) |
1059 | | #define _WX_VARARG_FIXED_UNUSED_EXPAND_3(t1,t2,t3) \ |
1060 | | t1 WXUNUSED(f1), t2 WXUNUSED(f2), t3 WXUNUSED(f3) |
1061 | | #define _WX_VARARG_FIXED_UNUSED_EXPAND_4(t1,t2,t3,t4) \ |
1062 | | t1 WXUNUSED(f1), t2 WXUNUSED(f2), t3 WXUNUSED(f3), t4 WXUNUSED(f4) |
1063 | | |
1064 | | #define _WX_VARARG_FIXED_TYPEDEFS_1(t1) \ |
1065 | | typedef t1 TF1 |
1066 | | #define _WX_VARARG_FIXED_TYPEDEFS_2(t1,t2) \ |
1067 | | _WX_VARARG_FIXED_TYPEDEFS_1(t1); typedef t2 TF2 |
1068 | | #define _WX_VARARG_FIXED_TYPEDEFS_3(t1,t2,t3) \ |
1069 | | _WX_VARARG_FIXED_TYPEDEFS_2(t1,t2); typedef t3 TF3 |
1070 | | #define _WX_VARARG_FIXED_TYPEDEFS_4(t1,t2,t3,t4) \ |
1071 | | _WX_VARARG_FIXED_TYPEDEFS_3(t1,t2,t3); typedef t4 TF4 |
1072 | | |
1073 | | // This macro expands N-items tuple of fixed arguments types into part of |
1074 | | // function's declaration. For example, |
1075 | | // "_WX_VARARG_FIXED_EXPAND(3, (int, char*, int))" expands into |
1076 | | // "int f1, char* f2, int f3". |
1077 | | #define _WX_VARARG_FIXED_EXPAND(N, args) \ |
1078 | | _WX_VARARG_FIXED_EXPAND_IMPL(N, args) |
1079 | | #define _WX_VARARG_FIXED_EXPAND_IMPL(N, args) \ |
1080 | | _WX_VARARG_FIXED_EXPAND_##N args |
1081 | | |
1082 | | // Ditto for unused arguments |
1083 | | #define _WX_VARARG_FIXED_UNUSED_EXPAND(N, args) \ |
1084 | | _WX_VARARG_FIXED_UNUSED_EXPAND_IMPL(N, args) |
1085 | | #define _WX_VARARG_FIXED_UNUSED_EXPAND_IMPL(N, args) \ |
1086 | | _WX_VARARG_FIXED_UNUSED_EXPAND_##N args |
1087 | | |
1088 | | // Declarates typedefs for fixed arguments types; i-th fixed argument types |
1089 | | // will have TFi typedef. |
1090 | | #define _WX_VARARG_FIXED_TYPEDEFS(N, args) \ |
1091 | | _WX_VARARG_FIXED_TYPEDEFS_IMPL(N, args) |
1092 | | #define _WX_VARARG_FIXED_TYPEDEFS_IMPL(N, args) \ |
1093 | | _WX_VARARG_FIXED_TYPEDEFS_##N args |
1094 | | |
1095 | | |
1096 | | // This macro calls another macro 'm' passed as second argument 'N' times, |
1097 | | // with its only argument set to 1..N, and concatenates the results using |
1098 | | // comma as separator. |
1099 | | // |
1100 | | // An example: |
1101 | | // #define foo(i) x##i |
1102 | | // // this expands to "x1,x2,x3,x4" |
1103 | | // _WX_VARARG_JOIN(4, foo) |
1104 | | // |
1105 | | // |
1106 | | // N must not be greater than _WX_VARARG_MAX_ARGS (=30). |
1107 | 0 | #define _WX_VARARG_JOIN(N, m) _WX_VARARG_JOIN_IMPL(N, m) |
1108 | 0 | #define _WX_VARARG_JOIN_IMPL(N, m) _WX_VARARG_JOIN_##N(m) |
1109 | | |
1110 | | |
1111 | | // This macro calls another macro 'm' passed as second argument 'N' times, with |
1112 | | // its first argument set to 1..N and the remaining arguments set to 'a', 'b', |
1113 | | // 'c', 'd', 'e' and 'f'. The results are separated with whitespace in the |
1114 | | // expansion. |
1115 | | // |
1116 | | // An example: |
1117 | | // // this macro expands to: |
1118 | | // // foo(1,a,b,c,d,e,f) |
1119 | | // // foo(2,a,b,c,d,e,f) |
1120 | | // // foo(3,a,b,c,d,e,f) |
1121 | | // _WX_VARARG_ITER(3, foo, a, b, c, d, e, f) |
1122 | | // |
1123 | | // N must not be greater than _WX_VARARG_MAX_ARGS (=30). |
1124 | | #define _WX_VARARG_ITER(N,m,a,b,c,d,e,f) \ |
1125 | | _WX_VARARG_ITER_IMPL(N,m,a,b,c,d,e,f) |
1126 | | #define _WX_VARARG_ITER_IMPL(N,m,a,b,c,d,e,f) \ |
1127 | | _WX_VARARG_ITER_##N(m,a,b,c,d,e,f) |
1128 | | |
1129 | | // Generates code snippet for i-th "variadic" argument in vararg function's |
1130 | | // prototype: |
1131 | | #define _WX_VARARG_ARG(i) T##i a##i |
1132 | | |
1133 | | // Like _WX_VARARG_ARG_UNUSED, but outputs argument's type with WXUNUSED: |
1134 | | #define _WX_VARARG_ARG_UNUSED(i) T##i WXUNUSED(a##i) |
1135 | | |
1136 | | // Generates code snippet for i-th type in vararg function's template<...>: |
1137 | | #define _WX_VARARG_TEMPL(i) typename T##i |
1138 | | |
1139 | | // Generates code snippet for passing i-th argument of vararg function |
1140 | | // wrapper to its implementation, normalizing it in the process: |
1141 | | #define _WX_VARARG_PASS_WCHAR(i) \ |
1142 | | wxArgNormalizerWchar<T##i>(a##i, fmt, i).get() |
1143 | | #define _WX_VARARG_PASS_UTF8(i) \ |
1144 | | wxArgNormalizerUtf8<T##i>(a##i, fmt, i).get() |
1145 | | |
1146 | | |
1147 | | // And the same for fixed arguments, _not_ normalizing it: |
1148 | | #define _WX_VARARG_PASS_FIXED(i) f##i |
1149 | | |
1150 | | #define _WX_VARARG_FIND_FMT(i) \ |
1151 | | (wxFormatStringArgumentFinder<TF##i>::find(f##i)) |
1152 | | |
1153 | | #define _WX_VARARG_FORMAT_STRING(numfixed, fixed) \ |
1154 | | _WX_VARARG_FIXED_TYPEDEFS(numfixed, fixed); \ |
1155 | | const wxFormatString *fmt = \ |
1156 | | (_WX_VARARG_JOIN(numfixed, _WX_VARARG_FIND_FMT)) |
1157 | | |
1158 | | #if wxUSE_UNICODE_UTF8 |
1159 | | #define _WX_VARARG_DO_CALL_UTF8(return_kw, impl, implUtf8, N, numfixed) \ |
1160 | | return_kw implUtf8(_WX_VARARG_JOIN(numfixed, _WX_VARARG_PASS_FIXED), \ |
1161 | | _WX_VARARG_JOIN(N, _WX_VARARG_PASS_UTF8)) |
1162 | | #define _WX_VARARG_DO_CALL0_UTF8(return_kw, impl, implUtf8, numfixed) \ |
1163 | | return_kw implUtf8(_WX_VARARG_JOIN(numfixed, _WX_VARARG_PASS_FIXED)) |
1164 | | #endif // wxUSE_UNICODE_UTF8 |
1165 | | |
1166 | | #define _WX_VARARG_DO_CALL_WCHAR(return_kw, impl, implUtf8, N, numfixed) \ |
1167 | | return_kw impl(_WX_VARARG_JOIN(numfixed, _WX_VARARG_PASS_FIXED), \ |
1168 | | _WX_VARARG_JOIN(N, _WX_VARARG_PASS_WCHAR)) |
1169 | | #define _WX_VARARG_DO_CALL0_WCHAR(return_kw, impl, implUtf8, numfixed) \ |
1170 | | return_kw impl(_WX_VARARG_JOIN(numfixed, _WX_VARARG_PASS_FIXED)) |
1171 | | |
1172 | | #if wxUSE_UNICODE_UTF8 |
1173 | | #if wxUSE_UTF8_LOCALE_ONLY |
1174 | | #define _WX_VARARG_DO_CALL _WX_VARARG_DO_CALL_UTF8 |
1175 | | #define _WX_VARARG_DO_CALL0 _WX_VARARG_DO_CALL0_UTF8 |
1176 | | #else // possibly non-UTF8 locales |
1177 | | #define _WX_VARARG_DO_CALL(return_kw, impl, implUtf8, N, numfixed) \ |
1178 | | if ( wxLocaleIsUtf8 ) \ |
1179 | | _WX_VARARG_DO_CALL_UTF8(return_kw, impl, implUtf8, N, numfixed);\ |
1180 | | else \ |
1181 | | _WX_VARARG_DO_CALL_WCHAR(return_kw, impl, implUtf8, N, numfixed) |
1182 | | |
1183 | | #define _WX_VARARG_DO_CALL0(return_kw, impl, implUtf8, numfixed) \ |
1184 | | if ( wxLocaleIsUtf8 ) \ |
1185 | | _WX_VARARG_DO_CALL0_UTF8(return_kw, impl, implUtf8, numfixed); \ |
1186 | | else \ |
1187 | | _WX_VARARG_DO_CALL0_WCHAR(return_kw, impl, implUtf8, numfixed) |
1188 | | #endif // wxUSE_UTF8_LOCALE_ONLY or not |
1189 | | #else // wxUSE_UNICODE_WCHAR |
1190 | | #define _WX_VARARG_DO_CALL _WX_VARARG_DO_CALL_WCHAR |
1191 | | #define _WX_VARARG_DO_CALL0 _WX_VARARG_DO_CALL0_WCHAR |
1192 | | #endif // wxUSE_UNICODE_UTF8 / wxUSE_UNICODE_WCHAR |
1193 | | |
1194 | | |
1195 | | // Macro to be used with _WX_VARARG_ITER in the implementation of |
1196 | | // WX_DEFINE_VARARG_FUNC (see its documentation for the meaning of arguments) |
1197 | | #define _WX_VARARG_DEFINE_FUNC(N, rettype, name, \ |
1198 | | impl, implUtf8, numfixed, fixed) \ |
1199 | | template<_WX_VARARG_JOIN(N, _WX_VARARG_TEMPL)> \ |
1200 | | rettype name(_WX_VARARG_FIXED_EXPAND(numfixed, fixed), \ |
1201 | | _WX_VARARG_JOIN(N, _WX_VARARG_ARG)) \ |
1202 | | { \ |
1203 | | _WX_VARARG_FORMAT_STRING(numfixed, fixed); \ |
1204 | | _WX_VARARG_DO_CALL(return, impl, implUtf8, N, numfixed); \ |
1205 | | } |
1206 | | |
1207 | | #define _WX_VARARG_DEFINE_FUNC_N0(rettype, name, \ |
1208 | | impl, implUtf8, numfixed, fixed) \ |
1209 | | inline rettype name(_WX_VARARG_FIXED_EXPAND(numfixed, fixed)) \ |
1210 | | { \ |
1211 | | _WX_VARARG_DO_CALL0(return, impl, implUtf8, numfixed); \ |
1212 | | } |
1213 | | |
1214 | | // Macro to be used with _WX_VARARG_ITER in the implementation of |
1215 | | // WX_DEFINE_VARARG_FUNC_VOID (see its documentation for the meaning of |
1216 | | // arguments; rettype is ignored and is used only to satisfy _WX_VARARG_ITER's |
1217 | | // requirements). |
1218 | | #define _WX_VARARG_DEFINE_FUNC_VOID(N, rettype, name, \ |
1219 | | impl, implUtf8, numfixed, fixed) \ |
1220 | | template<_WX_VARARG_JOIN(N, _WX_VARARG_TEMPL)> \ |
1221 | | void name(_WX_VARARG_FIXED_EXPAND(numfixed, fixed), \ |
1222 | | _WX_VARARG_JOIN(N, _WX_VARARG_ARG)) \ |
1223 | | { \ |
1224 | | _WX_VARARG_FORMAT_STRING(numfixed, fixed); \ |
1225 | | _WX_VARARG_DO_CALL(wxEMPTY_PARAMETER_VALUE, \ |
1226 | | impl, implUtf8, N, numfixed); \ |
1227 | | } |
1228 | | |
1229 | | #define _WX_VARARG_DEFINE_FUNC_VOID_N0(name, impl, implUtf8, numfixed, fixed) \ |
1230 | | inline void name(_WX_VARARG_FIXED_EXPAND(numfixed, fixed)) \ |
1231 | | { \ |
1232 | | _WX_VARARG_DO_CALL0(wxEMPTY_PARAMETER_VALUE, \ |
1233 | | impl, implUtf8, numfixed); \ |
1234 | | } |
1235 | | |
1236 | | // Macro to be used with _WX_VARARG_ITER in the implementation of |
1237 | | // WX_DEFINE_VARARG_FUNC_CTOR (see its documentation for the meaning of |
1238 | | // arguments; rettype is ignored and is used only to satisfy _WX_VARARG_ITER's |
1239 | | // requirements). |
1240 | | #define _WX_VARARG_DEFINE_FUNC_CTOR(N, rettype, name, \ |
1241 | | impl, implUtf8, numfixed, fixed) \ |
1242 | | template<_WX_VARARG_JOIN(N, _WX_VARARG_TEMPL)> \ |
1243 | | name(_WX_VARARG_FIXED_EXPAND(numfixed, fixed), \ |
1244 | | _WX_VARARG_JOIN(N, _WX_VARARG_ARG)) \ |
1245 | | { \ |
1246 | | _WX_VARARG_FORMAT_STRING(numfixed, fixed); \ |
1247 | | _WX_VARARG_DO_CALL(wxEMPTY_PARAMETER_VALUE, \ |
1248 | | impl, implUtf8, N, numfixed); \ |
1249 | | } |
1250 | | |
1251 | | #define _WX_VARARG_DEFINE_FUNC_CTOR_N0(name, impl, implUtf8, numfixed, fixed) \ |
1252 | | inline name(_WX_VARARG_FIXED_EXPAND(numfixed, fixed)) \ |
1253 | | { \ |
1254 | | _WX_VARARG_DO_CALL0(wxEMPTY_PARAMETER_VALUE, \ |
1255 | | impl, implUtf8, numfixed); \ |
1256 | | } |
1257 | | |
1258 | | // Macro to be used with _WX_VARARG_ITER in the implementation of |
1259 | | // WX_DEFINE_VARARG_FUNC_NOP, i.e. empty stub for a disabled vararg function. |
1260 | | // The rettype and impl arguments are ignored. |
1261 | | #define _WX_VARARG_DEFINE_FUNC_NOP(N, rettype, name, \ |
1262 | | impl, implUtf8, numfixed, fixed) \ |
1263 | | template<_WX_VARARG_JOIN(N, _WX_VARARG_TEMPL)> \ |
1264 | | void name(_WX_VARARG_FIXED_UNUSED_EXPAND(numfixed, fixed), \ |
1265 | | _WX_VARARG_JOIN(N, _WX_VARARG_ARG_UNUSED)) \ |
1266 | | {} |
1267 | | |
1268 | | #define _WX_VARARG_DEFINE_FUNC_NOP_N0(name, numfixed, fixed) \ |
1269 | | inline void name(_WX_VARARG_FIXED_UNUSED_EXPAND(numfixed, fixed)) \ |
1270 | | {} |
1271 | | |
1272 | | wxGCC_WARNING_RESTORE(ctor-dtor-privacy) |
1273 | | |
1274 | | #endif // _WX_STRVARARG_H_ |