Coverage Report

Created: 2026-05-24 06:59

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
wxFORMAT_STRING_SPECIFIER(wchar_t, wxFormatString::Arg_Char | wxFormatString::Arg_Int)
426
wxFORMAT_STRING_SPECIFIER(wxUniChar, wxFormatString::Arg_Char | wxFormatString::Arg_Int)
427
wxFORMAT_STRING_SPECIFIER(wxUniCharRef, wxFormatString::Arg_Char | wxFormatString::Arg_Int)
428
429
#ifndef wxNO_IMPLICIT_WXSTRING_ENCODING
430
wxFORMAT_STRING_SPECIFIER(char*, wxFormatString::Arg_String)
431
wxFORMAT_STRING_SPECIFIER(unsigned char*, wxFormatString::Arg_String)
432
wxFORMAT_STRING_SPECIFIER(signed char*, wxFormatString::Arg_String)
433
wxFORMAT_STRING_SPECIFIER(const char*, wxFormatString::Arg_String)
434
wxFORMAT_STRING_SPECIFIER(const unsigned char*, wxFormatString::Arg_String)
435
wxFORMAT_STRING_SPECIFIER(const signed char*, wxFormatString::Arg_String)
436
wxFORMAT_STRING_SPECIFIER(wxCharBuffer, wxFormatString::Arg_String)
437
wxFORMAT_STRING_SPECIFIER(wxScopedCharBuffer, wxFormatString::Arg_String)
438
wxFORMAT_STRING_SPECIFIER(std::string, wxFormatString::Arg_String)
439
#ifdef __cpp_lib_string_view
440
wxFORMAT_STRING_SPECIFIER(std::string_view, wxFormatString::Arg_String)
441
#endif
442
#else // wxNO_IMPLICIT_WXSTRING_ENCODING
443
wxDISABLED_FORMAT_STRING_SPECIFIER(char*)
444
wxDISABLED_FORMAT_STRING_SPECIFIER(unsigned char*)
445
wxDISABLED_FORMAT_STRING_SPECIFIER(signed char*)
446
wxDISABLED_FORMAT_STRING_SPECIFIER(const char*)
447
wxDISABLED_FORMAT_STRING_SPECIFIER(const unsigned char*)
448
wxDISABLED_FORMAT_STRING_SPECIFIER(const signed char*)
449
#endif // wxNO_IMPLICIT_WXSTRING_ENCODING
450
wxFORMAT_STRING_SPECIFIER(wchar_t*, wxFormatString::Arg_String)
451
wxFORMAT_STRING_SPECIFIER(const wchar_t*, wxFormatString::Arg_String)
452
453
wxFORMAT_STRING_SPECIFIER(wxWCharBuffer, wxFormatString::Arg_String)
454
wxFORMAT_STRING_SPECIFIER(wxScopedWCharBuffer, wxFormatString::Arg_String)
455
wxFORMAT_STRING_SPECIFIER(wxString, wxFormatString::Arg_String)
456
wxFORMAT_STRING_SPECIFIER(wxCStrData, wxFormatString::Arg_String)
457
wxFORMAT_STRING_SPECIFIER(std::wstring, wxFormatString::Arg_String)
458
459
wxFORMAT_STRING_SPECIFIER(int*, wxFormatString::Arg_IntPtr | wxFormatString::Arg_Pointer)
460
wxFORMAT_STRING_SPECIFIER(short int*, wxFormatString::Arg_ShortIntPtr | wxFormatString::Arg_Pointer)
461
wxFORMAT_STRING_SPECIFIER(long int*, wxFormatString::Arg_LongIntPtr | wxFormatString::Arg_Pointer)
462
463
#ifdef wxHAS_NULLPTR_T
464
wxFORMAT_STRING_SPECIFIER(std::nullptr_t, wxFormatString::Arg_Pointer)
465
#endif
466
467
#undef wxFORMAT_STRING_SPECIFIER
468
#undef wxDISABLED_FORMAT_STRING_SPECIFIER
469
470
471
// Converts an argument passed to wxPrint etc. into standard form expected,
472
// by wxXXX functions, e.g. all strings (wxString, char*, wchar_t*) are
473
// converted into wchar_t* or char* depending on the build.
474
template<typename T>
475
struct wxArgNormalizer
476
{
477
    // Ctor. 'value' is the value passed as variadic argument, 'fmt' is pointer
478
    // to printf-like format string or nullptr if the variadic function doesn't
479
    // use format string and 'index' is index of 'value' in variadic arguments
480
    // list (starting at 1)
481
    //
482
    // Because the format string and index are used for checking for the format
483
    // specifier mismatches and can be nullptr and 0, respectively, if they had
484
    // been already checked using wxFormatString::Validate().
485
    wxArgNormalizer(T value,
486
                    const wxFormatString *fmt, unsigned index)
487
0
        : m_value(value)
488
0
    {
489
0
        wxASSERT_ARG_TYPE( fmt, index, wxFormatStringSpecifier<T>::value );
490
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)
491
492
    // Returns the value in a form that can be safely passed to real vararg
493
    // functions. In case of strings, this is char* in UTF-8-only build and
494
    // wchar_t* otherwise.
495
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
496
497
    T m_value;
498
};
499
500
// normalizer for passing arguments to functions working with wchar_t*
501
// string representation
502
#if !wxUSE_UTF8_LOCALE_ONLY
503
template<typename T>
504
struct wxArgNormalizerWchar : public wxArgNormalizer<T>
505
{
506
    wxArgNormalizerWchar(T value,
507
                         const wxFormatString *fmt, unsigned index)
508
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)
509
};
510
511
#endif // !wxUSE_UTF8_LOCALE_ONLY
512
513
// normalizer for passing arguments to functions working with UTF-8 encoded
514
// char* strings
515
#if wxUSE_UNICODE_UTF8
516
    template<typename T>
517
    struct wxArgNormalizerUtf8 : public wxArgNormalizer<T>
518
    {
519
        wxArgNormalizerUtf8(T value,
520
                            const wxFormatString *fmt, unsigned index)
521
            : wxArgNormalizer<T>(value, fmt, index) {}
522
    };
523
524
    #define wxArgNormalizerNative wxArgNormalizerUtf8
525
#else // wxUSE_UNICODE_WCHAR
526
    #define wxArgNormalizerNative wxArgNormalizerWchar
527
#endif // wxUSE_UNICODE_UTF8/wxUSE_UNICODE_WCHAR
528
529
530
531
// special cases for converting strings:
532
533
534
// base class for wxArgNormalizer<T> specializations that need to do conversion;
535
// CharType is either wxStringCharType or wchar_t in UTF-8 build when wrapping
536
// widechar CRT function
537
template<typename CharType>
538
struct wxArgNormalizerWithBuffer
539
{
540
    typedef wxScopedCharTypeBuffer<CharType> CharBuffer;
541
542
    wxArgNormalizerWithBuffer() = default;
543
    wxArgNormalizerWithBuffer(const CharBuffer& buf,
544
                              const wxFormatString *fmt,
545
                              unsigned index)
546
0
        : m_value(buf)
547
0
    {
548
0
        wxASSERT_ARG_TYPE( fmt, index, wxFormatString::Arg_String );
549
0
    }
550
551
0
    const CharType *get() const { return m_value; }
552
553
    CharBuffer m_value;
554
};
555
556
// string objects:
557
template<>
558
struct WXDLLIMPEXP_BASE wxArgNormalizerNative<const wxString&>
559
{
560
    wxArgNormalizerNative(const wxString& s,
561
                          const wxFormatString *fmt,
562
                          unsigned index)
563
0
        : m_value(s)
564
0
    {
565
0
        wxASSERT_ARG_TYPE( fmt, index, wxFormatString::Arg_String );
566
0
    }
567
568
    const wxStringCharType *get() const;
569
570
    const wxString& m_value;
571
};
572
573
// c_str() values:
574
template<>
575
struct WXDLLIMPEXP_BASE wxArgNormalizerNative<const wxCStrData&>
576
{
577
    wxArgNormalizerNative(const wxCStrData& value,
578
                          const wxFormatString *fmt,
579
                          unsigned index)
580
0
        : m_value(value)
581
0
    {
582
0
        wxASSERT_ARG_TYPE( fmt, index, wxFormatString::Arg_String );
583
0
    }
584
585
    const wxStringCharType *get() const;
586
587
    const wxCStrData& m_value;
588
};
589
590
// wxString/wxCStrData conversion to wchar_t* value
591
#if wxUSE_UNICODE_UTF8 && !wxUSE_UTF8_LOCALE_ONLY
592
template<>
593
struct WXDLLIMPEXP_BASE wxArgNormalizerWchar<const wxString&>
594
    : public wxArgNormalizerWithBuffer<wchar_t>
595
{
596
    wxArgNormalizerWchar(const wxString& s,
597
                         const wxFormatString *fmt, unsigned index);
598
};
599
600
template<>
601
struct WXDLLIMPEXP_BASE wxArgNormalizerWchar<const wxCStrData&>
602
    : public wxArgNormalizerWithBuffer<wchar_t>
603
{
604
    wxArgNormalizerWchar(const wxCStrData& s,
605
                         const wxFormatString *fmt, unsigned index);
606
};
607
#endif // wxUSE_UNICODE_UTF8 && !wxUSE_UTF8_LOCALE_ONLY
608
609
610
// C string pointers of the wrong type (wchar_t* for UTF-8-only build,
611
// char* otherwise):
612
#if wxUSE_UNICODE_WCHAR
613
614
#ifndef wxNO_IMPLICIT_WXSTRING_ENCODING
615
template<>
616
struct wxArgNormalizerWchar<const char*>
617
    : public wxArgNormalizerWithBuffer<wchar_t>
618
{
619
    wxArgNormalizerWchar(const char* s,
620
                         const wxFormatString *fmt, unsigned index)
621
0
        : wxArgNormalizerWithBuffer<wchar_t>(wxConvLibc.cMB2WC(s), fmt, index) {}
622
};
623
#endif // wxNO_IMPLICIT_WXSTRING_ENCODING
624
625
#else // wxUSE_UNICODE_UTF8
626
627
template<>
628
struct wxArgNormalizerUtf8<const wchar_t*>
629
    : public wxArgNormalizerWithBuffer<char>
630
{
631
    wxArgNormalizerUtf8(const wchar_t* s,
632
                        const wxFormatString *fmt, unsigned index)
633
        : wxArgNormalizerWithBuffer<char>(wxConvUTF8.cWC2MB(s), fmt, index) {}
634
};
635
636
#ifndef wxNO_IMPLICIT_WXSTRING_ENCODING
637
template<>
638
struct wxArgNormalizerUtf8<const char*>
639
    : public wxArgNormalizerWithBuffer<char>
640
{
641
    wxArgNormalizerUtf8(const char* s,
642
                        const wxFormatString *fmt,
643
                        unsigned index)
644
    {
645
        wxASSERT_ARG_TYPE( fmt, index, wxFormatString::Arg_String );
646
647
        if ( wxLocaleIsUtf8 )
648
        {
649
            m_value = wxScopedCharBuffer::CreateNonOwned(s);
650
        }
651
        else
652
        {
653
            // convert to widechar string first:
654
            wxScopedWCharBuffer buf(wxConvLibc.cMB2WC(s));
655
656
            // then to UTF-8:
657
            if ( buf )
658
                m_value = wxConvUTF8.cWC2MB(buf);
659
        }
660
    }
661
};
662
#endif
663
664
// UTF-8 build needs conversion to wchar_t* too:
665
#if !wxUSE_UTF8_LOCALE_ONLY && !defined wxNO_IMPLICIT_WXSTRING_ENCODING
666
template<>
667
struct wxArgNormalizerWchar<const char*>
668
    : public wxArgNormalizerWithBuffer<wchar_t>
669
{
670
    wxArgNormalizerWchar(const char* s,
671
                         const wxFormatString *fmt, unsigned index)
672
        : wxArgNormalizerWithBuffer<wchar_t>(wxConvLibc.cMB2WC(s), fmt, index) {}
673
};
674
#endif // !wxUSE_UTF8_LOCALE_ONLY && !defined wxNO_IMPLICIT_WXSTRING_ENCODING
675
676
#endif // wxUSE_UNICODE_WCHAR/wxUSE_UNICODE_UTF8
677
678
679
#ifdef wxNO_IMPLICIT_WXSTRING_ENCODING
680
// wxArgNormalizer specializations that cannot be instanced
681
template<>
682
struct wxArgNormalizer<const char*> {
683
private:
684
    wxArgNormalizer(const char*, const wxFormatString *, unsigned);
685
    const char *get() const;
686
};
687
template<>
688
struct wxArgNormalizer<char*> {
689
private:
690
    wxArgNormalizer(const char*, const wxFormatString *, unsigned);
691
    char *get() const;
692
};
693
template<>
694
struct wxArgNormalizer<const std::string> {
695
private:
696
    wxArgNormalizer(const std::string&, const wxFormatString *, unsigned);
697
    std::string get() const;
698
};
699
template<>
700
struct wxArgNormalizer<std::string> {
701
private:
702
    wxArgNormalizer(std::string&, const wxFormatString *, unsigned);
703
    std::string get() const;
704
};
705
template<>
706
struct wxArgNormalizer<wxCharBuffer> {
707
private:
708
    wxArgNormalizer(wxCharBuffer&, const wxFormatString *, unsigned);
709
    std::string get() const;
710
};
711
template<>
712
struct wxArgNormalizer<wxScopedCharBuffer> {
713
private:
714
    wxArgNormalizer(wxScopedCharBuffer&, const wxFormatString *, unsigned);
715
    std::string get() const;
716
};
717
#endif // wxNO_IMPLICIT_WXSTRING_ENCODING
718
719
// this macro is used to implement specialization that are exactly same as
720
// some other specialization, i.e. to "forward" the implementation (e.g. for
721
// T=wxString and T=const wxString&). Note that the ctor takes BaseT argument,
722
// not T!
723
#if wxUSE_UNICODE_UTF8
724
    #if wxUSE_UTF8_LOCALE_ONLY
725
        #define WX_ARG_NORMALIZER_FORWARD(T, BaseT)                         \
726
          _WX_ARG_NORMALIZER_FORWARD_IMPL(wxArgNormalizerUtf8, T, BaseT)
727
    #else // possibly non-UTF8 locales
728
        #define WX_ARG_NORMALIZER_FORWARD(T, BaseT)                         \
729
          _WX_ARG_NORMALIZER_FORWARD_IMPL(wxArgNormalizerWchar, T, BaseT);  \
730
          _WX_ARG_NORMALIZER_FORWARD_IMPL(wxArgNormalizerUtf8, T, BaseT)
731
    #endif
732
#else // wxUSE_UNICODE_WCHAR
733
    #define WX_ARG_NORMALIZER_FORWARD(T, BaseT)                             \
734
        _WX_ARG_NORMALIZER_FORWARD_IMPL(wxArgNormalizerWchar, T, BaseT)
735
#endif // wxUSE_UNICODE_UTF8/wxUSE_UNICODE_WCHAR
736
737
#define _WX_ARG_NORMALIZER_FORWARD_IMPL(Normalizer, T, BaseT)               \
738
    template<>                                                              \
739
    struct Normalizer<T> : public Normalizer<BaseT>                         \
740
    {                                                                       \
741
        Normalizer(BaseT value,                                             \
742
                   const wxFormatString *fmt, unsigned index)               \
743
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)
744
    }
745
746
// non-reference versions of specializations for string objects
747
WX_ARG_NORMALIZER_FORWARD(wxString, const wxString&);
748
WX_ARG_NORMALIZER_FORWARD(wxCStrData, const wxCStrData&);
749
750
// versions for passing non-const pointers:
751
#ifndef wxNO_IMPLICIT_WXSTRING_ENCODING
752
WX_ARG_NORMALIZER_FORWARD(char*, const char*);
753
#endif
754
WX_ARG_NORMALIZER_FORWARD(wchar_t*, const wchar_t*);
755
756
// versions for passing wx[W]CharBuffer:
757
#ifndef wxNO_IMPLICIT_WXSTRING_ENCODING
758
WX_ARG_NORMALIZER_FORWARD(wxScopedCharBuffer, const char*);
759
WX_ARG_NORMALIZER_FORWARD(const wxScopedCharBuffer&, const char*);
760
#endif
761
WX_ARG_NORMALIZER_FORWARD(wxScopedWCharBuffer, const wchar_t*);
762
WX_ARG_NORMALIZER_FORWARD(const wxScopedWCharBuffer&, const wchar_t*);
763
#ifndef wxNO_IMPLICIT_WXSTRING_ENCODING
764
WX_ARG_NORMALIZER_FORWARD(wxCharBuffer, const char*);
765
WX_ARG_NORMALIZER_FORWARD(const wxCharBuffer&, const char*);
766
#endif
767
WX_ARG_NORMALIZER_FORWARD(wxWCharBuffer, const wchar_t*);
768
WX_ARG_NORMALIZER_FORWARD(const wxWCharBuffer&, const wchar_t*);
769
770
// versions for std::[w]string and string_view, if we have it.
771
#if !wxUSE_UTF8_LOCALE_ONLY
772
#ifndef wxNO_IMPLICIT_WXSTRING_ENCODING
773
template<>
774
struct wxArgNormalizerWchar<const std::string&>
775
    : public wxArgNormalizerWchar<const char*>
776
{
777
    wxArgNormalizerWchar(const std::string& s,
778
                         const wxFormatString *fmt, unsigned index)
779
0
        : wxArgNormalizerWchar<const char*>(s.c_str(), fmt, index) {}
780
};
781
782
#ifdef __cpp_lib_string_view
783
// This is inefficient because we create a temporary string rather than using
784
// the string_view directly, but is required because the rest of the code
785
// assumes NUL-terminated strings and is still better than nothing (i.e. no
786
// support for std::string_view at all).
787
template<>
788
struct wxArgNormalizerWchar<const std::string_view&>
789
    : public wxArgNormalizerWchar<const std::string&>
790
{
791
    wxArgNormalizerWchar(const std::string_view& v,
792
                         const wxFormatString *fmt, unsigned index)
793
0
        : wxArgNormalizerWchar<const std::string&>(std::string{v}, fmt, index) {}
794
};
795
#endif // __cpp_lib_string_view
796
797
#endif // NO_IMPLICIT_WXSTRING_ENCODING
798
799
template<>
800
struct wxArgNormalizerWchar<const std::wstring&>
801
    : public wxArgNormalizerWchar<const wchar_t*>
802
{
803
    wxArgNormalizerWchar(const std::wstring& s,
804
                         const wxFormatString *fmt, unsigned index)
805
0
        : wxArgNormalizerWchar<const wchar_t*>(s.c_str(), fmt, index) {}
806
};
807
#endif // !wxUSE_UTF8_LOCALE_ONLY
808
809
#if wxUSE_UNICODE_UTF8
810
#ifndef wxNO_IMPLICIT_WXSTRING_ENCODING
811
template<>
812
struct wxArgNormalizerUtf8<const std::string&>
813
    : public wxArgNormalizerUtf8<const char*>
814
{
815
    wxArgNormalizerUtf8(const std::string& s,
816
                        const wxFormatString *fmt, unsigned index)
817
        : wxArgNormalizerUtf8<const char*>(s.c_str(), fmt, index) {}
818
};
819
820
#ifdef __cpp_lib_string_view
821
template<>
822
struct wxArgNormalizerUtf8<const std::string_view&>
823
{
824
    wxArgNormalizerUtf8(const std::string_view& v,
825
                        const wxFormatString *fmt, unsigned index)
826
        : m_str{v}
827
    {
828
        wxASSERT_ARG_TYPE( fmt, index, wxFormatString::Arg_String );
829
    }
830
831
    const char* get() const { return m_str.c_str(); }
832
833
    // We need to store this string to ensure that we use a NUL-terminated
834
    // buffer, i.e. we can't use string_view data directly.
835
    const std::string m_str;
836
};
837
#endif // __cpp_lib_string_view
838
839
#endif // wxNO_IMPLICIT_WXSTRING_ENCODING
840
841
template<>
842
struct wxArgNormalizerUtf8<const std::wstring&>
843
    : public wxArgNormalizerUtf8<const wchar_t*>
844
{
845
    wxArgNormalizerUtf8(const std::wstring& s,
846
                        const wxFormatString *fmt, unsigned index)
847
        : wxArgNormalizerUtf8<const wchar_t*>(s.c_str(), fmt, index) {}
848
};
849
#endif // wxUSE_UNICODE_UTF8
850
851
#ifndef wxNO_IMPLICIT_WXSTRING_ENCODING
852
WX_ARG_NORMALIZER_FORWARD(std::string, const std::string&);
853
#ifdef __cpp_lib_string_view
854
WX_ARG_NORMALIZER_FORWARD(std::string_view, const std::string_view&);
855
#endif // __cpp_lib_string_view
856
#endif
857
WX_ARG_NORMALIZER_FORWARD(std::wstring, const std::wstring&);
858
859
860
// versions for wxUniChar, wxUniCharRef:
861
// (this is same for UTF-8 and Wchar builds, we just convert to wchar_t)
862
template<>
863
struct wxArgNormalizer<const wxUniChar&> : public wxArgNormalizer<wchar_t>
864
{
865
    wxArgNormalizer(const wxUniChar& s,
866
                    const wxFormatString *fmt, unsigned index)
867
0
        : wxArgNormalizer<wchar_t>(wx_truncate_cast(wchar_t, s.GetValue()), fmt, index) {}
868
};
869
870
// for wchar_t, default handler does the right thing
871
872
// char has to be treated differently: a char argument may
873
// be used either for a character value (which should be converted into
874
// wxUniChar) or as an integer value (which should be left as-is). We take
875
// advantage of the fact that both char and wchar_t are converted into int
876
// in variadic arguments here.
877
template<typename T>
878
struct wxArgNormalizerNarrowChar
879
{
880
    wxArgNormalizerNarrowChar(T value,
881
                              const wxFormatString *fmt, unsigned index)
882
0
    {
883
0
        wxASSERT_ARG_TYPE( fmt, index,
884
0
                           wxFormatString::Arg_Char | wxFormatString::Arg_Int );
885
886
0
        if ( fmt && fmt->GetArgumentType(index) == wxFormatString::Arg_Char )
887
0
            m_value = wx_truncate_cast(T, wxUniChar(value).GetValue());
888
0
        else
889
0
            m_value = value;
890
0
    }
Unexecuted instantiation: wxArgNormalizerNarrowChar<char>::wxArgNormalizerNarrowChar(char, wxFormatString const*, unsigned int)
Unexecuted instantiation: wxArgNormalizerNarrowChar<unsigned char>::wxArgNormalizerNarrowChar(unsigned char, wxFormatString const*, unsigned int)
891
892
0
    int get() const { return m_value; }
Unexecuted instantiation: wxArgNormalizerNarrowChar<char>::get() const
Unexecuted instantiation: wxArgNormalizerNarrowChar<unsigned char>::get() const
893
894
    T m_value;
895
};
896
897
template<>
898
struct wxArgNormalizer<char> : public wxArgNormalizerNarrowChar<char>
899
{
900
    wxArgNormalizer(char value,
901
                    const wxFormatString *fmt, unsigned index)
902
0
        : wxArgNormalizerNarrowChar<char>(value, fmt, index) {}
903
};
904
905
template<>
906
struct wxArgNormalizer<unsigned char>
907
    : public wxArgNormalizerNarrowChar<unsigned char>
908
{
909
    wxArgNormalizer(unsigned char value,
910
                    const wxFormatString *fmt, unsigned index)
911
0
        : wxArgNormalizerNarrowChar<unsigned char>(value, fmt, index) {}
912
};
913
914
template<>
915
struct wxArgNormalizer<signed char>
916
    : public wxArgNormalizerNarrowChar<signed char>
917
{
918
    wxArgNormalizer(signed char value,
919
                    const wxFormatString *fmt, unsigned index)
920
0
        : wxArgNormalizerNarrowChar<signed char>(value, fmt, index) {}
921
};
922
923
// convert references:
924
WX_ARG_NORMALIZER_FORWARD(wxUniChar, const wxUniChar&);
925
WX_ARG_NORMALIZER_FORWARD(const wxUniCharRef&, const wxUniChar&);
926
WX_ARG_NORMALIZER_FORWARD(wxUniCharRef, const wxUniChar&);
927
WX_ARG_NORMALIZER_FORWARD(const wchar_t&, wchar_t);
928
929
WX_ARG_NORMALIZER_FORWARD(const char&, char);
930
WX_ARG_NORMALIZER_FORWARD(const unsigned char&, unsigned char);
931
WX_ARG_NORMALIZER_FORWARD(const signed char&, signed char);
932
933
934
#undef WX_ARG_NORMALIZER_FORWARD
935
#undef _WX_ARG_NORMALIZER_FORWARD_IMPL
936
937
// NB: Don't #undef wxASSERT_ARG_TYPE here as it's also used in wx/longlong.h.
938
939
// ----------------------------------------------------------------------------
940
// WX_VA_ARG_STRING
941
// ----------------------------------------------------------------------------
942
943
// Replacement for va_arg() for use with strings in functions that accept
944
// strings normalized by wxArgNormalizer<T>:
945
946
struct WXDLLIMPEXP_BASE wxArgNormalizedString
947
{
948
0
    wxArgNormalizedString(const void* ptr) : m_ptr(ptr) {}
949
950
    // returns true if non-null string was passed in
951
0
    bool IsValid() const { return m_ptr != nullptr; }
952
0
    operator bool() const { return IsValid(); }
953
954
    // extracts the string, returns empty string if nullptr was passed in
955
    wxString GetString() const;
956
    operator wxString() const;
957
958
private:
959
    const void *m_ptr;
960
};
961
962
#define WX_VA_ARG_STRING(ap) wxArgNormalizedString(va_arg(ap, const void*))
963
964
// ----------------------------------------------------------------------------
965
// implementation of the WX_DEFINE_VARARG_* macros
966
// ----------------------------------------------------------------------------
967
968
// NB: The vararg emulation code is limited to 30 variadic and 4 fixed
969
//     arguments at the moment.
970
//     If you need more variadic arguments, you need to
971
//        1) increase the value of _WX_VARARG_MAX_ARGS
972
//        2) add _WX_VARARG_JOIN_* and _WX_VARARG_ITER_* up to the new
973
//           _WX_VARARG_MAX_ARGS value to the lists below
974
//     If you need more fixed arguments, you need to
975
//        1) increase the value of _WX_VARARG_MAX_FIXED_ARGS
976
//        2) add _WX_VARARG_FIXED_EXPAND_* and _WX_VARARG_FIXED_UNUSED_EXPAND_*
977
//           macros below
978
#define _WX_VARARG_MAX_ARGS        30
979
#define _WX_VARARG_MAX_FIXED_ARGS   4
980
981
0
#define _WX_VARARG_JOIN_1(m)                                 m(1)
982
0
#define _WX_VARARG_JOIN_2(m)       _WX_VARARG_JOIN_1(m),     m(2)
983
0
#define _WX_VARARG_JOIN_3(m)       _WX_VARARG_JOIN_2(m),     m(3)
984
#define _WX_VARARG_JOIN_4(m)       _WX_VARARG_JOIN_3(m),     m(4)
985
#define _WX_VARARG_JOIN_5(m)       _WX_VARARG_JOIN_4(m),     m(5)
986
#define _WX_VARARG_JOIN_6(m)       _WX_VARARG_JOIN_5(m),     m(6)
987
#define _WX_VARARG_JOIN_7(m)       _WX_VARARG_JOIN_6(m),     m(7)
988
#define _WX_VARARG_JOIN_8(m)       _WX_VARARG_JOIN_7(m),     m(8)
989
#define _WX_VARARG_JOIN_9(m)       _WX_VARARG_JOIN_8(m),     m(9)
990
#define _WX_VARARG_JOIN_10(m)      _WX_VARARG_JOIN_9(m),     m(10)
991
#define _WX_VARARG_JOIN_11(m)      _WX_VARARG_JOIN_10(m),    m(11)
992
#define _WX_VARARG_JOIN_12(m)      _WX_VARARG_JOIN_11(m),    m(12)
993
#define _WX_VARARG_JOIN_13(m)      _WX_VARARG_JOIN_12(m),    m(13)
994
#define _WX_VARARG_JOIN_14(m)      _WX_VARARG_JOIN_13(m),    m(14)
995
#define _WX_VARARG_JOIN_15(m)      _WX_VARARG_JOIN_14(m),    m(15)
996
#define _WX_VARARG_JOIN_16(m)      _WX_VARARG_JOIN_15(m),    m(16)
997
#define _WX_VARARG_JOIN_17(m)      _WX_VARARG_JOIN_16(m),    m(17)
998
#define _WX_VARARG_JOIN_18(m)      _WX_VARARG_JOIN_17(m),    m(18)
999
#define _WX_VARARG_JOIN_19(m)      _WX_VARARG_JOIN_18(m),    m(19)
1000
#define _WX_VARARG_JOIN_20(m)      _WX_VARARG_JOIN_19(m),    m(20)
1001
#define _WX_VARARG_JOIN_21(m)      _WX_VARARG_JOIN_20(m),    m(21)
1002
#define _WX_VARARG_JOIN_22(m)      _WX_VARARG_JOIN_21(m),    m(22)
1003
#define _WX_VARARG_JOIN_23(m)      _WX_VARARG_JOIN_22(m),    m(23)
1004
#define _WX_VARARG_JOIN_24(m)      _WX_VARARG_JOIN_23(m),    m(24)
1005
#define _WX_VARARG_JOIN_25(m)      _WX_VARARG_JOIN_24(m),    m(25)
1006
#define _WX_VARARG_JOIN_26(m)      _WX_VARARG_JOIN_25(m),    m(26)
1007
#define _WX_VARARG_JOIN_27(m)      _WX_VARARG_JOIN_26(m),    m(27)
1008
#define _WX_VARARG_JOIN_28(m)      _WX_VARARG_JOIN_27(m),    m(28)
1009
#define _WX_VARARG_JOIN_29(m)      _WX_VARARG_JOIN_28(m),    m(29)
1010
#define _WX_VARARG_JOIN_30(m)      _WX_VARARG_JOIN_29(m),    m(30)
1011
1012
#define _WX_VARARG_ITER_1(m,a,b,c,d,e,f)                                    m(1,a,b,c,d,e,f)
1013
#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)
1014
#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)
1015
#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)
1016
#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)
1017
#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)
1018
#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)
1019
#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)
1020
#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)
1021
#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)
1022
#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)
1023
#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)
1024
#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)
1025
#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)
1026
#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)
1027
#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)
1028
#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)
1029
#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)
1030
#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)
1031
#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)
1032
#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)
1033
#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)
1034
#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)
1035
#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)
1036
#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)
1037
#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)
1038
#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)
1039
#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)
1040
#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)
1041
#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)
1042
1043
1044
#define _WX_VARARG_FIXED_EXPAND_1(t1) \
1045
         t1 f1
1046
#define _WX_VARARG_FIXED_EXPAND_2(t1,t2) \
1047
         t1 f1, t2 f2
1048
#define _WX_VARARG_FIXED_EXPAND_3(t1,t2,t3) \
1049
         t1 f1, t2 f2, t3 f3
1050
#define _WX_VARARG_FIXED_EXPAND_4(t1,t2,t3,t4) \
1051
         t1 f1, t2 f2, t3 f3, t4 f4
1052
1053
#define _WX_VARARG_FIXED_UNUSED_EXPAND_1(t1) \
1054
         t1 WXUNUSED(f1)
1055
#define _WX_VARARG_FIXED_UNUSED_EXPAND_2(t1,t2) \
1056
         t1 WXUNUSED(f1), t2 WXUNUSED(f2)
1057
#define _WX_VARARG_FIXED_UNUSED_EXPAND_3(t1,t2,t3) \
1058
         t1 WXUNUSED(f1), t2 WXUNUSED(f2), t3 WXUNUSED(f3)
1059
#define _WX_VARARG_FIXED_UNUSED_EXPAND_4(t1,t2,t3,t4) \
1060
         t1 WXUNUSED(f1), t2 WXUNUSED(f2), t3 WXUNUSED(f3), t4 WXUNUSED(f4)
1061
1062
#define _WX_VARARG_FIXED_TYPEDEFS_1(t1) \
1063
             typedef t1 TF1
1064
#define _WX_VARARG_FIXED_TYPEDEFS_2(t1,t2) \
1065
             _WX_VARARG_FIXED_TYPEDEFS_1(t1); typedef t2 TF2
1066
#define _WX_VARARG_FIXED_TYPEDEFS_3(t1,t2,t3) \
1067
             _WX_VARARG_FIXED_TYPEDEFS_2(t1,t2); typedef t3 TF3
1068
#define _WX_VARARG_FIXED_TYPEDEFS_4(t1,t2,t3,t4) \
1069
             _WX_VARARG_FIXED_TYPEDEFS_3(t1,t2,t3); typedef t4 TF4
1070
1071
// This macro expands N-items tuple of fixed arguments types into part of
1072
// function's declaration. For example,
1073
// "_WX_VARARG_FIXED_EXPAND(3, (int, char*, int))" expands into
1074
// "int f1, char* f2, int f3".
1075
#define _WX_VARARG_FIXED_EXPAND(N, args) \
1076
                _WX_VARARG_FIXED_EXPAND_IMPL(N, args)
1077
#define _WX_VARARG_FIXED_EXPAND_IMPL(N, args) \
1078
                _WX_VARARG_FIXED_EXPAND_##N args
1079
1080
// Ditto for unused arguments
1081
#define _WX_VARARG_FIXED_UNUSED_EXPAND(N, args) \
1082
                _WX_VARARG_FIXED_UNUSED_EXPAND_IMPL(N, args)
1083
#define _WX_VARARG_FIXED_UNUSED_EXPAND_IMPL(N, args) \
1084
                _WX_VARARG_FIXED_UNUSED_EXPAND_##N args
1085
1086
// Declarates typedefs for fixed arguments types; i-th fixed argument types
1087
// will have TFi typedef.
1088
#define _WX_VARARG_FIXED_TYPEDEFS(N, args) \
1089
                _WX_VARARG_FIXED_TYPEDEFS_IMPL(N, args)
1090
#define _WX_VARARG_FIXED_TYPEDEFS_IMPL(N, args) \
1091
                _WX_VARARG_FIXED_TYPEDEFS_##N args
1092
1093
1094
// This macro calls another macro 'm' passed as second argument 'N' times,
1095
// with its only argument set to 1..N, and concatenates the results using
1096
// comma as separator.
1097
//
1098
// An example:
1099
//     #define foo(i)  x##i
1100
//     // this expands to "x1,x2,x3,x4"
1101
//     _WX_VARARG_JOIN(4, foo)
1102
//
1103
//
1104
// N must not be greater than _WX_VARARG_MAX_ARGS (=30).
1105
0
#define _WX_VARARG_JOIN(N, m)             _WX_VARARG_JOIN_IMPL(N, m)
1106
0
#define _WX_VARARG_JOIN_IMPL(N, m)        _WX_VARARG_JOIN_##N(m)
1107
1108
1109
// This macro calls another macro 'm' passed as second argument 'N' times, with
1110
// its first argument set to 1..N and the remaining arguments set to 'a', 'b',
1111
// 'c', 'd', 'e' and 'f'. The results are separated with whitespace in the
1112
// expansion.
1113
//
1114
// An example:
1115
//     // this macro expands to:
1116
//     //     foo(1,a,b,c,d,e,f)
1117
//     //     foo(2,a,b,c,d,e,f)
1118
//     //     foo(3,a,b,c,d,e,f)
1119
//     _WX_VARARG_ITER(3, foo, a, b, c, d, e, f)
1120
//
1121
// N must not be greater than _WX_VARARG_MAX_ARGS (=30).
1122
#define _WX_VARARG_ITER(N,m,a,b,c,d,e,f) \
1123
        _WX_VARARG_ITER_IMPL(N,m,a,b,c,d,e,f)
1124
#define _WX_VARARG_ITER_IMPL(N,m,a,b,c,d,e,f) \
1125
        _WX_VARARG_ITER_##N(m,a,b,c,d,e,f)
1126
1127
// Generates code snippet for i-th "variadic" argument in vararg function's
1128
// prototype:
1129
#define _WX_VARARG_ARG(i)               T##i a##i
1130
1131
// Like _WX_VARARG_ARG_UNUSED, but outputs argument's type with WXUNUSED:
1132
#define _WX_VARARG_ARG_UNUSED(i)        T##i WXUNUSED(a##i)
1133
1134
// Generates code snippet for i-th type in vararg function's template<...>:
1135
#define _WX_VARARG_TEMPL(i)             typename T##i
1136
1137
// Generates code snippet for passing i-th argument of vararg function
1138
// wrapper to its implementation, normalizing it in the process:
1139
#define _WX_VARARG_PASS_WCHAR(i) \
1140
    wxArgNormalizerWchar<T##i>(a##i, fmt, i).get()
1141
#define _WX_VARARG_PASS_UTF8(i) \
1142
    wxArgNormalizerUtf8<T##i>(a##i, fmt, i).get()
1143
1144
1145
// And the same for fixed arguments, _not_ normalizing it:
1146
#define _WX_VARARG_PASS_FIXED(i)        f##i
1147
1148
#define _WX_VARARG_FIND_FMT(i) \
1149
            (wxFormatStringArgumentFinder<TF##i>::find(f##i))
1150
1151
#define _WX_VARARG_FORMAT_STRING(numfixed, fixed)                             \
1152
    _WX_VARARG_FIXED_TYPEDEFS(numfixed, fixed);                               \
1153
    const wxFormatString *fmt =                                               \
1154
            (_WX_VARARG_JOIN(numfixed, _WX_VARARG_FIND_FMT))
1155
1156
#if wxUSE_UNICODE_UTF8
1157
    #define _WX_VARARG_DO_CALL_UTF8(return_kw, impl, implUtf8, N, numfixed)   \
1158
        return_kw implUtf8(_WX_VARARG_JOIN(numfixed, _WX_VARARG_PASS_FIXED),  \
1159
                        _WX_VARARG_JOIN(N, _WX_VARARG_PASS_UTF8))
1160
    #define _WX_VARARG_DO_CALL0_UTF8(return_kw, impl, implUtf8, numfixed)     \
1161
        return_kw implUtf8(_WX_VARARG_JOIN(numfixed, _WX_VARARG_PASS_FIXED))
1162
#endif // wxUSE_UNICODE_UTF8
1163
1164
#define _WX_VARARG_DO_CALL_WCHAR(return_kw, impl, implUtf8, N, numfixed)      \
1165
    return_kw impl(_WX_VARARG_JOIN(numfixed, _WX_VARARG_PASS_FIXED),          \
1166
                    _WX_VARARG_JOIN(N, _WX_VARARG_PASS_WCHAR))
1167
#define _WX_VARARG_DO_CALL0_WCHAR(return_kw, impl, implUtf8, numfixed)        \
1168
    return_kw impl(_WX_VARARG_JOIN(numfixed, _WX_VARARG_PASS_FIXED))
1169
1170
#if wxUSE_UNICODE_UTF8
1171
    #if wxUSE_UTF8_LOCALE_ONLY
1172
        #define _WX_VARARG_DO_CALL _WX_VARARG_DO_CALL_UTF8
1173
        #define _WX_VARARG_DO_CALL0 _WX_VARARG_DO_CALL0_UTF8
1174
    #else // possibly non-UTF8 locales
1175
        #define _WX_VARARG_DO_CALL(return_kw, impl, implUtf8, N, numfixed)    \
1176
            if ( wxLocaleIsUtf8 )                                             \
1177
              _WX_VARARG_DO_CALL_UTF8(return_kw, impl, implUtf8, N, numfixed);\
1178
            else                                                              \
1179
              _WX_VARARG_DO_CALL_WCHAR(return_kw, impl, implUtf8, N, numfixed)
1180
1181
        #define _WX_VARARG_DO_CALL0(return_kw, impl, implUtf8, numfixed)      \
1182
            if ( wxLocaleIsUtf8 )                                             \
1183
              _WX_VARARG_DO_CALL0_UTF8(return_kw, impl, implUtf8, numfixed);  \
1184
            else                                                              \
1185
              _WX_VARARG_DO_CALL0_WCHAR(return_kw, impl, implUtf8, numfixed)
1186
    #endif // wxUSE_UTF8_LOCALE_ONLY or not
1187
#else // wxUSE_UNICODE_WCHAR
1188
    #define _WX_VARARG_DO_CALL _WX_VARARG_DO_CALL_WCHAR
1189
    #define _WX_VARARG_DO_CALL0 _WX_VARARG_DO_CALL0_WCHAR
1190
#endif // wxUSE_UNICODE_UTF8 / wxUSE_UNICODE_WCHAR
1191
1192
1193
// Macro to be used with _WX_VARARG_ITER in the implementation of
1194
// WX_DEFINE_VARARG_FUNC (see its documentation for the meaning of arguments)
1195
#define _WX_VARARG_DEFINE_FUNC(N, rettype, name,                              \
1196
                               impl, implUtf8, numfixed, fixed)               \
1197
    template<_WX_VARARG_JOIN(N, _WX_VARARG_TEMPL)>                            \
1198
    rettype name(_WX_VARARG_FIXED_EXPAND(numfixed, fixed),                    \
1199
                 _WX_VARARG_JOIN(N, _WX_VARARG_ARG))                          \
1200
    {                                                                         \
1201
        _WX_VARARG_FORMAT_STRING(numfixed, fixed);                            \
1202
        _WX_VARARG_DO_CALL(return, impl, implUtf8, N, numfixed);              \
1203
    }
1204
1205
#define _WX_VARARG_DEFINE_FUNC_N0(rettype, name,                              \
1206
                                  impl, implUtf8, numfixed, fixed)            \
1207
    inline rettype name(_WX_VARARG_FIXED_EXPAND(numfixed, fixed))             \
1208
    {                                                                         \
1209
        _WX_VARARG_DO_CALL0(return, impl, implUtf8, numfixed);                \
1210
    }
1211
1212
// Macro to be used with _WX_VARARG_ITER in the implementation of
1213
// WX_DEFINE_VARARG_FUNC_VOID (see its documentation for the meaning of
1214
// arguments; rettype is ignored and is used only to satisfy _WX_VARARG_ITER's
1215
// requirements).
1216
#define _WX_VARARG_DEFINE_FUNC_VOID(N, rettype, name,                         \
1217
                                    impl, implUtf8, numfixed, fixed)          \
1218
    template<_WX_VARARG_JOIN(N, _WX_VARARG_TEMPL)>                            \
1219
    void name(_WX_VARARG_FIXED_EXPAND(numfixed, fixed),                       \
1220
                 _WX_VARARG_JOIN(N, _WX_VARARG_ARG))                          \
1221
    {                                                                         \
1222
        _WX_VARARG_FORMAT_STRING(numfixed, fixed);                            \
1223
        _WX_VARARG_DO_CALL(wxEMPTY_PARAMETER_VALUE,                           \
1224
                           impl, implUtf8, N, numfixed);                      \
1225
    }
1226
1227
#define _WX_VARARG_DEFINE_FUNC_VOID_N0(name, impl, implUtf8, numfixed, fixed) \
1228
    inline void name(_WX_VARARG_FIXED_EXPAND(numfixed, fixed))                \
1229
    {                                                                         \
1230
        _WX_VARARG_DO_CALL0(wxEMPTY_PARAMETER_VALUE,                          \
1231
                            impl, implUtf8, numfixed);                        \
1232
    }
1233
1234
// Macro to be used with _WX_VARARG_ITER in the implementation of
1235
// WX_DEFINE_VARARG_FUNC_CTOR (see its documentation for the meaning of
1236
// arguments; rettype is ignored and is used only to satisfy _WX_VARARG_ITER's
1237
// requirements).
1238
#define _WX_VARARG_DEFINE_FUNC_CTOR(N, rettype, name,                         \
1239
                                    impl, implUtf8, numfixed, fixed)          \
1240
    template<_WX_VARARG_JOIN(N, _WX_VARARG_TEMPL)>                            \
1241
    name(_WX_VARARG_FIXED_EXPAND(numfixed, fixed),                            \
1242
                _WX_VARARG_JOIN(N, _WX_VARARG_ARG))                           \
1243
    {                                                                         \
1244
        _WX_VARARG_FORMAT_STRING(numfixed, fixed);                            \
1245
        _WX_VARARG_DO_CALL(wxEMPTY_PARAMETER_VALUE,                           \
1246
                           impl, implUtf8, N, numfixed);                      \
1247
    }
1248
1249
#define _WX_VARARG_DEFINE_FUNC_CTOR_N0(name, impl, implUtf8, numfixed, fixed) \
1250
    inline name(_WX_VARARG_FIXED_EXPAND(numfixed, fixed))                     \
1251
    {                                                                         \
1252
        _WX_VARARG_DO_CALL0(wxEMPTY_PARAMETER_VALUE,                          \
1253
                            impl, implUtf8, numfixed);                        \
1254
    }
1255
1256
// Macro to be used with _WX_VARARG_ITER in the implementation of
1257
// WX_DEFINE_VARARG_FUNC_NOP, i.e. empty stub for a disabled vararg function.
1258
// The rettype and impl arguments are ignored.
1259
#define _WX_VARARG_DEFINE_FUNC_NOP(N, rettype, name,                          \
1260
                                   impl, implUtf8, numfixed, fixed)           \
1261
    template<_WX_VARARG_JOIN(N, _WX_VARARG_TEMPL)>                            \
1262
    void name(_WX_VARARG_FIXED_UNUSED_EXPAND(numfixed, fixed),                \
1263
                 _WX_VARARG_JOIN(N, _WX_VARARG_ARG_UNUSED))                   \
1264
    {}
1265
1266
#define _WX_VARARG_DEFINE_FUNC_NOP_N0(name, numfixed, fixed)                  \
1267
    inline void name(_WX_VARARG_FIXED_UNUSED_EXPAND(numfixed, fixed))         \
1268
    {}
1269
1270
wxGCC_WARNING_RESTORE(ctor-dtor-privacy)
1271
1272
#endif // _WX_STRVARARG_H_