Coverage Report

Created: 2025-12-10 06:08

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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_