| 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 | // RCS-ID: $Id$ |
| 7 | // Copyright: (c) 2007 REA Elektronik GmbH |
| 8 | // Licence: wxWindows licence |
| 9 | /////////////////////////////////////////////////////////////////////////////// |
| 10 | |
| 11 | #ifndef _WX_STRVARARG_H_ |
| 12 | #define _WX_STRVARARG_H_ |
| 13 | |
| 14 | #include "wx/platform.h" |
| 15 | #if wxONLY_WATCOM_EARLIER_THAN(1,4) |
| 16 | #error "OpenWatcom version >= 1.4 is required to compile this code" |
| 17 | #endif |
| 18 | |
| 19 | #include "wx/cpp.h" |
| 20 | #include "wx/chartype.h" |
| 21 | #include "wx/strconv.h" |
| 22 | #include "wx/buffer.h" |
| 23 | #include "wx/unichar.h" |
| 24 | |
| 25 | class WXDLLIMPEXP_FWD_BASE wxCStrData; |
| 26 | class WXDLLIMPEXP_FWD_BASE wxString; |
| 27 | |
| 28 | // ---------------------------------------------------------------------------- |
| 29 | // WX_DEFINE_VARARG_FUNC* macros |
| 30 | // ---------------------------------------------------------------------------- |
| 31 | |
| 32 | // This macro is used to implement type-safe wrappers for variadic functions |
| 33 | // that accept strings as arguments. This makes it possible to pass char*, |
| 34 | // wchar_t* or even wxString (as opposed to having to use wxString::c_str()) |
| 35 | // to e.g. wxPrintf(). |
| 36 | // |
| 37 | // This is done by defining a set of N template function taking 1..N arguments |
| 38 | // (currently, N is set to 30 in this header). These functions are just thin |
| 39 | // wrappers around another variadic function ('impl' or 'implUtf8' arguments, |
| 40 | // see below) and the only thing the wrapper does is that it normalizes the |
| 41 | // arguments passed in so that they are of the type expected by variadic |
| 42 | // functions taking string arguments, i.e., char* or wchar_t*, depending on the |
| 43 | // build: |
| 44 | // * char* in the current locale's charset in ANSI build |
| 45 | // * char* with UTF-8 encoding if wxUSE_UNICODE_UTF8 and the app is running |
| 46 | // under an UTF-8 locale |
| 47 | // * wchar_t* if wxUSE_UNICODE_WCHAR or if wxUSE_UNICODE_UTF8 and the current |
| 48 | // locale is not UTF-8 |
| 49 | // |
| 50 | // Note that wxFormatString *must* be used for the format parameter of these |
| 51 | // functions, otherwise the implementation won't work correctly. Furthermore, |
| 52 | // it must be passed by value, not reference, because it's modified by the |
| 53 | // vararg templates internally. |
| 54 | // |
| 55 | // Parameters: |
| 56 | // [ there are examples in square brackets showing values of the parameters |
| 57 | // for the wxFprintf() wrapper for fprintf() function with the following |
| 58 | // prototype: |
| 59 | // int wxFprintf(FILE *stream, const wxString& format, ...); ] |
| 60 | // |
| 61 | // rettype Functions' return type [int] |
| 62 | // name Name of the function [fprintf] |
| 63 | // numfixed The number of leading "fixed" (i.e., not variadic) |
| 64 | // arguments of the function (e.g. "stream" and "format" |
| 65 | // arguments of fprintf()); their type is _not_ converted |
| 66 | // using wxArgNormalizer<T>, unlike the rest of |
| 67 | // the function's arguments [2] |
| 68 | // fixed List of types of the leading "fixed" arguments, in |
| 69 | // parenthesis [(FILE*,const wxString&)] |
| 70 | // impl Name of the variadic function that implements 'name' for |
| 71 | // the native strings representation (wchar_t* if |
| 72 | // wxUSE_UNICODE_WCHAR or wxUSE_UNICODE_UTF8 when running under |
| 73 | // non-UTF8 locale, char* in ANSI build) [wxCrt_Fprintf] |
| 74 | // implUtf8 Like 'impl', but for the UTF-8 char* version to be used |
| 75 | // if wxUSE_UNICODE_UTF8 and running under UTF-8 locale |
| 76 | // (ignored otherwise) [fprintf] |
| 77 | // |
| 78 | #define WX_DEFINE_VARARG_FUNC(rettype, name, numfixed, fixed, impl, implUtf8) \ |
| 79 | _WX_VARARG_DEFINE_FUNC_N0(rettype, name, impl, implUtf8, numfixed, fixed) \ |
| 80 | WX_DEFINE_VARARG_FUNC_SANS_N0(rettype, name, numfixed, fixed, impl, implUtf8) |
| 81 | |
| 82 | // ditto, but without the version with 0 template/vararg arguments |
| 83 | #define WX_DEFINE_VARARG_FUNC_SANS_N0(rettype, name, \ |
| 84 | numfixed, fixed, impl, implUtf8) \ |
| 85 | _WX_VARARG_ITER(_WX_VARARG_MAX_ARGS, \ |
| 86 | _WX_VARARG_DEFINE_FUNC, \ |
| 87 | rettype, name, impl, implUtf8, numfixed, fixed) |
| 88 | |
| 89 | // Like WX_DEFINE_VARARG_FUNC, but for variadic functions that don't return |
| 90 | // a value. |
| 91 | #define WX_DEFINE_VARARG_FUNC_VOID(name, numfixed, fixed, impl, implUtf8) \ |
| 92 | _WX_VARARG_DEFINE_FUNC_VOID_N0(name, impl, implUtf8, numfixed, fixed) \ |
| 93 | _WX_VARARG_ITER(_WX_VARARG_MAX_ARGS, \ |
| 94 | _WX_VARARG_DEFINE_FUNC_VOID, \ |
| 95 | void, name, impl, implUtf8, numfixed, fixed) |
| 96 | |
| 97 | // Like WX_DEFINE_VARARG_FUNC_VOID, but instead of wrapping an implementation |
| 98 | // function, does nothing in defined functions' bodies. |
| 99 | // |
| 100 | // Used to implement wxLogXXX functions if wxUSE_LOG=0. |
| 101 | #define WX_DEFINE_VARARG_FUNC_NOP(name, numfixed, fixed) \ |
| 102 | _WX_VARARG_DEFINE_FUNC_NOP_N0(name, numfixed, fixed) \ |
| 103 | _WX_VARARG_ITER(_WX_VARARG_MAX_ARGS, \ |
| 104 | _WX_VARARG_DEFINE_FUNC_NOP, \ |
| 105 | void, name, dummy, dummy, numfixed, fixed) |
| 106 | |
| 107 | // Like WX_DEFINE_VARARG_FUNC_CTOR, but for defining template constructors |
| 108 | #define WX_DEFINE_VARARG_FUNC_CTOR(name, numfixed, fixed, impl, implUtf8) \ |
| 109 | _WX_VARARG_DEFINE_FUNC_CTOR_N0(name, impl, implUtf8, numfixed, fixed) \ |
| 110 | _WX_VARARG_ITER(_WX_VARARG_MAX_ARGS, \ |
| 111 | _WX_VARARG_DEFINE_FUNC_CTOR, \ |
| 112 | void, name, impl, implUtf8, numfixed, fixed) |
| 113 | |
| 114 | |
| 115 | // ---------------------------------------------------------------------------- |
| 116 | // wxFormatString |
| 117 | // ---------------------------------------------------------------------------- |
| 118 | |
| 119 | // This class must be used for format string argument of the functions |
| 120 | // defined using WX_DEFINE_VARARG_FUNC_* macros. It converts the string to |
| 121 | // char* or wchar_t* for passing to implementation function efficiently (i.e. |
| 122 | // without keeping the converted string in memory for longer than necessary, |
| 123 | // like c_str()). It also converts format string to the correct form that |
| 124 | // accounts for string changes done by wxArgNormalizer<> |
| 125 | // |
| 126 | // Note that this class can _only_ be used for function arguments! |
| 127 | #ifdef __VISUALC__ |
| 128 | // "struct 'wx[W]CharBuffer<T>' needs to have dll-interface to be used by |
| 129 | // clients of class 'wxString'" - this is private, we don't care |
| 130 | #pragma warning (disable:4251) |
| 131 | #endif |
| 132 | class WXDLLIMPEXP_BASE wxFormatString |
| 133 | { |
| 134 | public: |
| 135 | wxFormatString(const char *str) |
| 136 | : m_char(wxCharBuffer::CreateNonOwned(str)), m_str(NULL), m_cstr(NULL) {} |
| 137 | wxFormatString(const wchar_t *str) |
| 138 | : m_wchar(wxWCharBuffer::CreateNonOwned(str)), m_str(NULL), m_cstr(NULL) {} |
| 139 | wxFormatString(const wxString& str) |
| 140 | : m_str(&str), m_cstr(NULL) {} |
| 141 | wxFormatString(const wxCStrData& str) |
| 142 | : m_str(NULL), m_cstr(&str) {} |
| 143 | wxFormatString(const wxCharBuffer& str) |
| 144 | : m_char(str), m_str(NULL), m_cstr(NULL) {} |
| 145 | wxFormatString(const wxWCharBuffer& str) |
| 146 | : m_wchar(str), m_str(NULL), m_cstr(NULL) {} |
| 147 | |
| 148 | |
| 149 | enum ArgumentType |
| 150 | { |
| 151 | Arg_Char, // character as char |
| 152 | |
| 153 | Arg_Other // something else, for example int for %d |
| 154 | }; |
| 155 | |
| 156 | // returns the type of format specifier for n-th variadic argument (this is |
| 157 | // not necessarily n-th format specifier if positional specifiers are used); |
| 158 | // called by wxArgNormalizer<> specializations to get information about |
| 159 | // n-th variadic argument desired representation |
| 160 | ArgumentType GetArgumentType(unsigned n) const; |
| 161 | |
| 162 | #if !wxUSE_UNICODE_WCHAR |
| 163 | operator const char*() const |
| 164 | { return wx_const_cast(wxFormatString*, this)->AsChar(); } |
| 165 | private: |
| 166 | // InputAsChar() returns the value converted passed to ctor, only converted |
| 167 | // to char, while AsChar() takes the the string returned by InputAsChar() |
| 168 | // and does format string conversion on it as well (and similarly for |
| 169 | // ..AsWChar() below) |
| 170 | const char* InputAsChar(); |
| 171 | const char* AsChar(); |
| 172 | wxCharBuffer m_convertedChar; |
| 173 | #endif // !wxUSE_UNICODE_WCHAR |
| 174 | |
| 175 | #if wxUSE_UNICODE && !wxUSE_UTF8_LOCALE_ONLY |
| 176 | public: |
| 177 | operator const wchar_t*() const |
| 178 | { return wx_const_cast(wxFormatString*, this)->AsWChar(); } |
| 179 | private: |
| 180 | const wchar_t* InputAsWChar(); |
| 181 | const wchar_t* AsWChar(); |
| 182 | wxWCharBuffer m_convertedWChar; |
| 183 | #endif // wxUSE_UNICODE && !wxUSE_UTF8_LOCALE_ONLY |
| 184 | |
| 185 | private: |
| 186 | wxCharBuffer m_char; |
| 187 | wxWCharBuffer m_wchar; |
| 188 | #ifdef __VISUALC__ |
| 189 | #pragma warning (default:4251) |
| 190 | #endif |
| 191 | |
| 192 | // NB: we can use a pointer here, because wxFormatString is only used |
| 193 | // as function argument, so it has shorter life than the string |
| 194 | // passed to the ctor |
| 195 | const wxString * const m_str; |
| 196 | const wxCStrData * const m_cstr; |
| 197 | |
| 198 | DECLARE_NO_ASSIGN_CLASS(wxFormatString) |
| 199 | }; |
| 200 | |
| 201 | // these two helper classes are used to find wxFormatString argument among fixed |
| 202 | // arguments passed to a vararg template |
| 203 | struct wxFormatStringArgument |
| 204 | { |
| 205 | wxFormatStringArgument(const wxFormatString *s = NULL) : m_str(s) {} |
| 206 | const wxFormatString *m_str; |
| 207 | |
| 208 | // overriding this operator allows us to reuse _WX_VARARG_JOIN macro |
| 209 | wxFormatStringArgument operator,(const wxFormatStringArgument& a) const |
| 210 | { |
| 211 | wxASSERT_MSG( m_str == NULL || a.m_str == NULL, |
| 212 | "can't have two format strings in vararg function" ); |
| 213 | return wxFormatStringArgument(m_str ? m_str : a.m_str); |
| 214 | } |
| 215 | |
| 216 | operator const wxFormatString*() const { return m_str; } |
| 217 | }; |
| 218 | |
| 219 | template<typename T> |
| 220 | struct wxFormatStringArgumentFinder |
| 221 | { |
| 222 | static wxFormatStringArgument find(T) |
| 223 | { |
| 224 | // by default, arguments are not format strings, so return "not found" |
| 225 | return wxFormatStringArgument(); |
| 226 | } |
| 227 | }; |
| 228 | |
| 229 | template<> |
| 230 | struct wxFormatStringArgumentFinder<const wxFormatString&> |
| 231 | { |
| 232 | static wxFormatStringArgument find(const wxFormatString& arg) |
| 233 | { return wxFormatStringArgument(&arg); } |
| 234 | }; |
| 235 | |
| 236 | template<> |
| 237 | struct wxFormatStringArgumentFinder<wxFormatString> |
| 238 | { |
| 239 | static wxFormatStringArgument find(const wxFormatString& arg) |
| 240 | { return wxFormatStringArgument(&arg); } |
| 241 | }; |
| 242 | |
| 243 | |
| 244 | // ---------------------------------------------------------------------------- |
| 245 | // wxArgNormalizer*<T> converters |
| 246 | // ---------------------------------------------------------------------------- |
| 247 | |
| 248 | // Converts an argument passed to wxPrint etc. into standard form expected, |
| 249 | // by wxXXX functions, e.g. all strings (wxString, char*, wchar_t*) are |
| 250 | // converted into wchar_t* or char* depending on the build. |
| 251 | template<typename T> |
| 252 | struct wxArgNormalizer |
| 253 | { |
| 254 | // Ctor. 'value' is the value passed as variadic argument, 'fmt' is pointer |
| 255 | // to printf-like format string or NULL if the variadic function doesn't |
| 256 | // use format string and 'index' is index of 'value' in variadic arguments |
| 257 | // list (starting at 1) |
| 258 | wxArgNormalizer(T value, |
| 259 | const wxFormatString *WXUNUSED(fmt), unsigned WXUNUSED(index)) |
| 260 | : m_value(value) {} |
| 261 | |
| 262 | // Returns the value in a form that can be safely passed to real vararg |
| 263 | // functions. In case of strings, this is char* in ANSI build and wchar_t* |
| 264 | // in Unicode build. |
| 265 | T get() const { return m_value; } |
| 266 | |
| 267 | T m_value; |
| 268 | }; |
| 269 | |
| 270 | // normalizer for passing arguments to functions working with wchar_t* (and |
| 271 | // until ANSI build is removed, char* in ANSI build as well - FIXME-UTF8) |
| 272 | // string representation |
| 273 | #if !wxUSE_UTF8_LOCALE_ONLY |
| 274 | template<typename T> |
| 275 | struct wxArgNormalizerWchar : public wxArgNormalizer<T> |
| 276 | { |
| 277 | wxArgNormalizerWchar(T value, |
| 278 | const wxFormatString *fmt, unsigned index) |
| 279 | : wxArgNormalizer<T>(value, fmt, index) {} |
| 280 | }; |
| 281 | #endif // !wxUSE_UTF8_LOCALE_ONLY |
| 282 | |
| 283 | // normalizer for passing arguments to functions working with UTF-8 encoded |
| 284 | // char* strings |
| 285 | #if wxUSE_UNICODE_UTF8 |
| 286 | template<typename T> |
| 287 | struct wxArgNormalizerUtf8 : public wxArgNormalizer<T> |
| 288 | { |
| 289 | wxArgNormalizerUtf8(T value, |
| 290 | const wxFormatString *fmt, unsigned index) |
| 291 | : wxArgNormalizer<T>(value, fmt, index) {} |
| 292 | }; |
| 293 | |
| 294 | #define wxArgNormalizerNative wxArgNormalizerUtf8 |
| 295 | #else // wxUSE_UNICODE_WCHAR |
| 296 | #define wxArgNormalizerNative wxArgNormalizerWchar |
| 297 | #endif // wxUSE_UNICODE_UTF8 // wxUSE_UNICODE_UTF8 |
| 298 | |
| 299 | |
| 300 | |
| 301 | // special cases for converting strings: |
| 302 | |
| 303 | |
| 304 | // base class for wxArgNormalizer<T> specializations that need to do conversion; |
| 305 | // CharType is either wxStringCharType or wchar_t in UTF-8 build when wrapping |
| 306 | // widechar CRT function |
| 307 | template<typename CharType> |
| 308 | struct wxArgNormalizerWithBuffer |
| 309 | { |
| 310 | typedef wxCharTypeBuffer<CharType> CharBuffer; |
| 311 | |
| 312 | wxArgNormalizerWithBuffer() {} |
| 313 | wxArgNormalizerWithBuffer(const CharBuffer& buf, |
| 314 | const wxFormatString *WXUNUSED(fmt), |
| 315 | unsigned WXUNUSED(index)) |
| 316 | : m_value(buf) {} |
| 317 | |
| 318 | const CharType *get() const { return m_value; } |
| 319 | |
| 320 | CharBuffer m_value; |
| 321 | }; |
| 322 | |
| 323 | // string objects: |
| 324 | template<> |
| 325 | struct WXDLLIMPEXP_BASE wxArgNormalizerNative<const wxString&> |
| 326 | { |
| 327 | wxArgNormalizerNative(const wxString& s, |
| 328 | const wxFormatString *WXUNUSED(fmt), |
| 329 | unsigned WXUNUSED(index)) |
| 330 | : m_value(s) {} |
| 331 | |
| 332 | const wxStringCharType *get() const; |
| 333 | |
| 334 | const wxString& m_value; |
| 335 | }; |
| 336 | |
| 337 | // c_str() values: |
| 338 | template<> |
| 339 | struct WXDLLIMPEXP_BASE wxArgNormalizerNative<const wxCStrData&> |
| 340 | { |
| 341 | wxArgNormalizerNative(const wxCStrData& value, |
| 342 | const wxFormatString *WXUNUSED(fmt), |
| 343 | unsigned WXUNUSED(index)) |
| 344 | : m_value(value) {} |
| 345 | |
| 346 | const wxStringCharType *get() const; |
| 347 | |
| 348 | const wxCStrData& m_value; |
| 349 | }; |
| 350 | |
| 351 | // wxString/wxCStrData conversion to wchar_t* value |
| 352 | #if wxUSE_UNICODE_UTF8 && !wxUSE_UTF8_LOCALE_ONLY |
| 353 | template<> |
| 354 | struct WXDLLIMPEXP_BASE wxArgNormalizerWchar<const wxString&> |
| 355 | : public wxArgNormalizerWithBuffer<wchar_t> |
| 356 | { |
| 357 | wxArgNormalizerWchar(const wxString& s, |
| 358 | const wxFormatString *fmt, unsigned index); |
| 359 | }; |
| 360 | |
| 361 | template<> |
| 362 | struct WXDLLIMPEXP_BASE wxArgNormalizerWchar<const wxCStrData&> |
| 363 | : public wxArgNormalizerWithBuffer<wchar_t> |
| 364 | { |
| 365 | wxArgNormalizerWchar(const wxCStrData& s, |
| 366 | const wxFormatString *fmt, unsigned index); |
| 367 | }; |
| 368 | #endif // wxUSE_UNICODE_UTF8 && !wxUSE_UTF8_LOCALE_ONLY |
| 369 | |
| 370 | |
| 371 | // C string pointers of the wrong type (wchar_t* for ANSI or UTF8 build, |
| 372 | // char* for wchar_t Unicode build or UTF8): |
| 373 | #if wxUSE_UNICODE_WCHAR |
| 374 | |
| 375 | template<> |
| 376 | struct wxArgNormalizerWchar<const char*> |
| 377 | : public wxArgNormalizerWithBuffer<wchar_t> |
| 378 | { |
| 379 | wxArgNormalizerWchar(const char* s, |
| 380 | const wxFormatString *fmt, unsigned index) |
| 381 | : wxArgNormalizerWithBuffer<wchar_t>(wxConvLibc.cMB2WC(s), fmt, index) {} |
| 382 | }; |
| 383 | |
| 384 | #elif wxUSE_UNICODE_UTF8 |
| 385 | |
| 386 | template<> |
| 387 | struct wxArgNormalizerUtf8<const wchar_t*> |
| 388 | : public wxArgNormalizerWithBuffer<char> |
| 389 | { |
| 390 | wxArgNormalizerUtf8(const wchar_t* s, |
| 391 | const wxFormatString *fmt, unsigned index) |
| 392 | : wxArgNormalizerWithBuffer<char>(wxConvUTF8.cWC2MB(s), fmt, index) {} |
| 393 | }; |
| 394 | |
| 395 | template<> |
| 396 | struct wxArgNormalizerUtf8<const char*> |
| 397 | : public wxArgNormalizerWithBuffer<char> |
| 398 | { |
| 399 | wxArgNormalizerUtf8(const char* s, |
| 400 | const wxFormatString *WXUNUSED(fmt), |
| 401 | unsigned WXUNUSED(index)) |
| 402 | { |
| 403 | if ( wxLocaleIsUtf8 ) |
| 404 | { |
| 405 | m_value = wxCharBuffer::CreateNonOwned(s); |
| 406 | } |
| 407 | else |
| 408 | { |
| 409 | // convert to widechar string first: |
| 410 | wxWCharBuffer buf(wxConvLibc.cMB2WC(s)); |
| 411 | |
| 412 | // then to UTF-8: |
| 413 | if ( buf ) |
| 414 | m_value = wxConvUTF8.cWC2MB(buf); |
| 415 | } |
| 416 | } |
| 417 | }; |
| 418 | |
| 419 | // UTF-8 build needs conversion to wchar_t* too: |
| 420 | #if !wxUSE_UTF8_LOCALE_ONLY |
| 421 | template<> |
| 422 | struct wxArgNormalizerWchar<const char*> |
| 423 | : public wxArgNormalizerWithBuffer<wchar_t> |
| 424 | { |
| 425 | wxArgNormalizerWchar(const char* s, |
| 426 | const wxFormatString *fmt, unsigned index) |
| 427 | : wxArgNormalizerWithBuffer<wchar_t>(wxConvLibc.cMB2WC(s), fmt, index) {} |
| 428 | }; |
| 429 | #endif // !wxUSE_UTF8_LOCALE_ONLY |
| 430 | |
| 431 | #else // ANSI - FIXME-UTF8 |
| 432 | |
| 433 | template<> |
| 434 | struct wxArgNormalizerWchar<const wchar_t*> |
| 435 | : public wxArgNormalizerWithBuffer<char> |
| 436 | { |
| 437 | wxArgNormalizerWchar(const wchar_t* s, |
| 438 | const wxFormatString *fmt, unsigned index) |
| 439 | : wxArgNormalizerWithBuffer<char>(wxConvLibc.cWC2MB(s), fmt, index) {} |
| 440 | }; |
| 441 | |
| 442 | #endif // wxUSE_UNICODE_WCHAR/wxUSE_UNICODE_UTF8/ANSI |
| 443 | |
| 444 | |
| 445 | // this macro is used to implement specialization that are exactly same as |
| 446 | // some other specialization, i.e. to "forward" the implementation (e.g. for |
| 447 | // T=wxString and T=const wxString&). Note that the ctor takes BaseT argument, |
| 448 | // not T! |
| 449 | #if wxUSE_UNICODE_UTF8 |
| 450 | #if wxUSE_UTF8_LOCALE_ONLY |
| 451 | #define WX_ARG_NORMALIZER_FORWARD(T, BaseT) \ |
| 452 | _WX_ARG_NORMALIZER_FORWARD_IMPL(wxArgNormalizerUtf8, T, BaseT) |
| 453 | #else // possibly non-UTF8 locales |
| 454 | #define WX_ARG_NORMALIZER_FORWARD(T, BaseT) \ |
| 455 | _WX_ARG_NORMALIZER_FORWARD_IMPL(wxArgNormalizerWchar, T, BaseT); \ |
| 456 | _WX_ARG_NORMALIZER_FORWARD_IMPL(wxArgNormalizerUtf8, T, BaseT) |
| 457 | #endif |
| 458 | #else // wxUSE_UNICODE_WCHAR |
| 459 | #define WX_ARG_NORMALIZER_FORWARD(T, BaseT) \ |
| 460 | _WX_ARG_NORMALIZER_FORWARD_IMPL(wxArgNormalizerWchar, T, BaseT) |
| 461 | #endif // wxUSE_UNICODE_UTF8/wxUSE_UNICODE_WCHAR |
| 462 | |
| 463 | #define _WX_ARG_NORMALIZER_FORWARD_IMPL(Normalizer, T, BaseT) \ |
| 464 | template<> \ |
| 465 | struct Normalizer<T> : public Normalizer<BaseT> \ |
| 466 | { \ |
| 467 | Normalizer(BaseT value, \ |
| 468 | const wxFormatString *fmt, unsigned index) \ |
| 469 | : Normalizer<BaseT>(value, fmt, index) {} \ |
| 470 | } |
| 471 | |
| 472 | // non-reference versions of specializations for string objects |
| 473 | WX_ARG_NORMALIZER_FORWARD(wxString, const wxString&); |
| 474 | WX_ARG_NORMALIZER_FORWARD(wxCStrData, const wxCStrData&); |
| 475 | |
| 476 | // versions for passing non-const pointers: |
| 477 | WX_ARG_NORMALIZER_FORWARD(char*, const char*); |
| 478 | WX_ARG_NORMALIZER_FORWARD(wchar_t*, const wchar_t*); |
| 479 | |
| 480 | // versions for passing wx[W]CharBuffer: |
| 481 | WX_ARG_NORMALIZER_FORWARD(wxCharBuffer, const char*); |
| 482 | WX_ARG_NORMALIZER_FORWARD(const wxCharBuffer&, const char*); |
| 483 | WX_ARG_NORMALIZER_FORWARD(wxWCharBuffer, const wchar_t*); |
| 484 | WX_ARG_NORMALIZER_FORWARD(const wxWCharBuffer&, const wchar_t*); |
| 485 | |
| 486 | // versions for std::[w]string: |
| 487 | #if wxUSE_STD_STRING |
| 488 | |
| 489 | #include "wx/stringimpl.h" |
| 490 | |
| 491 | #if !wxUSE_UTF8_LOCALE_ONLY |
| 492 | template<> |
| 493 | struct wxArgNormalizerWchar<const std::string&> |
| 494 | : public wxArgNormalizerWchar<const char*> |
| 495 | { |
| 496 | wxArgNormalizerWchar(const std::string& s, |
| 497 | const wxFormatString *fmt, unsigned index) |
| 498 | : wxArgNormalizerWchar<const char*>(s.c_str(), fmt, index) {} |
| 499 | }; |
| 500 | |
| 501 | template<> |
| 502 | struct wxArgNormalizerWchar<const wxStdWideString&> |
| 503 | : public wxArgNormalizerWchar<const wchar_t*> |
| 504 | { |
| 505 | wxArgNormalizerWchar(const wxStdWideString& s, |
| 506 | const wxFormatString *fmt, unsigned index) |
| 507 | : wxArgNormalizerWchar<const wchar_t*>(s.c_str(), fmt, index) {} |
| 508 | }; |
| 509 | #endif // !wxUSE_UTF8_LOCALE_ONLY |
| 510 | |
| 511 | #if wxUSE_UNICODE_UTF8 |
| 512 | template<> |
| 513 | struct wxArgNormalizerUtf8<const std::string&> |
| 514 | : public wxArgNormalizerUtf8<const char*> |
| 515 | { |
| 516 | wxArgNormalizerUtf8(const std::string& s, |
| 517 | const wxFormatString *fmt, unsigned index) |
| 518 | : wxArgNormalizerUtf8<const char*>(s.c_str(), fmt, index) {} |
| 519 | }; |
| 520 | |
| 521 | template<> |
| 522 | struct wxArgNormalizerUtf8<const wxStdWideString&> |
| 523 | : public wxArgNormalizerUtf8<const wchar_t*> |
| 524 | { |
| 525 | wxArgNormalizerUtf8(const wxStdWideString& s, |
| 526 | const wxFormatString *fmt, unsigned index) |
| 527 | : wxArgNormalizerUtf8<const wchar_t*>(s.c_str(), fmt, index) {} |
| 528 | }; |
| 529 | #endif // wxUSE_UNICODE_UTF8 |
| 530 | |
| 531 | WX_ARG_NORMALIZER_FORWARD(std::string, const std::string&); |
| 532 | WX_ARG_NORMALIZER_FORWARD(wxStdWideString, const wxStdWideString&); |
| 533 | |
| 534 | #endif // wxUSE_STD_STRING |
| 535 | |
| 536 | |
| 537 | // versions for wxUniChar, wxUniCharRef: |
| 538 | // (this is same for UTF-8 and Wchar builds, we just convert to wchar_t) |
| 539 | template<> |
| 540 | struct wxArgNormalizer<const wxUniChar&> : public wxArgNormalizer<wchar_t> |
| 541 | { |
| 542 | wxArgNormalizer(const wxUniChar& s, |
| 543 | const wxFormatString *fmt, unsigned index) |
| 544 | : wxArgNormalizer<wchar_t>(s.GetValue(), fmt, index) {} |
| 545 | }; |
| 546 | |
| 547 | // for wchar_t, default handler does the right thing |
| 548 | |
| 549 | // char has to be treated differently in Unicode builds: a char argument may |
| 550 | // be used either for a character value (which should be converted into |
| 551 | // wxUniChar) or as an integer value (which should be left as-is). We take |
| 552 | // advantage of the fact that both char and wchar_t are converted into int |
| 553 | // in variadic arguments here. |
| 554 | #if wxUSE_UNICODE |
| 555 | template<typename T> |
| 556 | struct wxArgNormalizerNarrowChar |
| 557 | { |
| 558 | wxArgNormalizerNarrowChar(T value, |
| 559 | const wxFormatString *fmt, unsigned index) |
| 560 | { |
| 561 | // FIXME-UTF8: which one is better default in absence of fmt string |
| 562 | // (i.e. when used like e.g. Foo("foo", "bar", 'c', NULL)? |
| 563 | if ( !fmt || fmt->GetArgumentType(index) == wxFormatString::Arg_Char ) |
| 564 | m_value = wxUniChar(value).GetValue(); |
| 565 | else |
| 566 | m_value = value; |
| 567 | } |
| 568 | |
| 569 | int get() const { return m_value; } |
| 570 | |
| 571 | T m_value; |
| 572 | }; |
| 573 | |
| 574 | template<> |
| 575 | struct wxArgNormalizer<char> : public wxArgNormalizerNarrowChar<char> |
| 576 | { |
| 577 | wxArgNormalizer(char value, |
| 578 | const wxFormatString *fmt, unsigned index) |
| 579 | : wxArgNormalizerNarrowChar<char>(value, fmt, index) {} |
| 580 | }; |
| 581 | |
| 582 | template<> |
| 583 | struct wxArgNormalizer<unsigned char> |
| 584 | : public wxArgNormalizerNarrowChar<unsigned char> |
| 585 | { |
| 586 | wxArgNormalizer(unsigned char value, |
| 587 | const wxFormatString *fmt, unsigned index) |
| 588 | : wxArgNormalizerNarrowChar<unsigned char>(value, fmt, index) {} |
| 589 | }; |
| 590 | |
| 591 | #endif // wxUSE_UNICODE |
| 592 | |
| 593 | // convert references: |
| 594 | WX_ARG_NORMALIZER_FORWARD(wxUniChar, const wxUniChar&); |
| 595 | WX_ARG_NORMALIZER_FORWARD(const wxUniCharRef&, const wxUniChar&); |
| 596 | WX_ARG_NORMALIZER_FORWARD(wxUniCharRef, const wxUniChar&); |
| 597 | WX_ARG_NORMALIZER_FORWARD(const wchar_t&, wchar_t); |
| 598 | |
| 599 | WX_ARG_NORMALIZER_FORWARD(const char&, char); |
| 600 | WX_ARG_NORMALIZER_FORWARD(const unsigned char&, unsigned char); |
| 601 | |
| 602 | |
| 603 | #undef WX_ARG_NORMALIZER_FORWARD |
| 604 | #undef _WX_ARG_NORMALIZER_FORWARD_IMPL |
| 605 | |
| 606 | // ---------------------------------------------------------------------------- |
| 607 | // WX_VA_ARG_STRING |
| 608 | // ---------------------------------------------------------------------------- |
| 609 | |
| 610 | // Replacement for va_arg() for use with strings in functions that accept |
| 611 | // strings normalized by wxArgNormalizer<T>: |
| 612 | |
| 613 | struct WXDLLIMPEXP_BASE wxArgNormalizedString |
| 614 | { |
| 615 | wxArgNormalizedString(const void* ptr) : m_ptr(ptr) {} |
| 616 | |
| 617 | // returns true if non-NULL string was passed in |
| 618 | bool IsValid() const { return m_ptr != NULL; } |
| 619 | operator bool() const { return IsValid(); } |
| 620 | |
| 621 | // extracts the string, returns empty string if NULL was passed in |
| 622 | wxString GetString() const; |
| 623 | operator wxString() const; |
| 624 | |
| 625 | private: |
| 626 | const void *m_ptr; |
| 627 | }; |
| 628 | |
| 629 | #define WX_VA_ARG_STRING(ap) wxArgNormalizedString(va_arg(ap, const void*)) |
| 630 | |
| 631 | // ---------------------------------------------------------------------------- |
| 632 | // implementation of the WX_DEFINE_VARARG_* macros |
| 633 | // ---------------------------------------------------------------------------- |
| 634 | |
| 635 | // NB: The vararg emulation code is limited to 30 variadic and 4 fixed |
| 636 | // arguments at the moment. |
| 637 | // If you need more variadic arguments, you need to |
| 638 | // 1) increase the value of _WX_VARARG_MAX_ARGS |
| 639 | // 2) add _WX_VARARG_JOIN_* and _WX_VARARG_ITER_* up to the new |
| 640 | // _WX_VARARG_MAX_ARGS value to the lists below |
| 641 | // If you need more fixed arguments, you need to |
| 642 | // 1) increase the value of _WX_VARARG_MAX_FIXED_ARGS |
| 643 | // 2) add _WX_VARARG_FIXED_EXPAND_* and _WX_VARARG_FIXED_UNUSED_EXPAND_* |
| 644 | // macros below |
| 645 | #define _WX_VARARG_MAX_ARGS 30 |
| 646 | #define _WX_VARARG_MAX_FIXED_ARGS 4 |
| 647 | |
| 648 | #define _WX_VARARG_JOIN_1(m) m(1) |
| 649 | #define _WX_VARARG_JOIN_2(m) _WX_VARARG_JOIN_1(m), m(2) |
| 650 | #define _WX_VARARG_JOIN_3(m) _WX_VARARG_JOIN_2(m), m(3) |
| 651 | #define _WX_VARARG_JOIN_4(m) _WX_VARARG_JOIN_3(m), m(4) |
| 652 | #define _WX_VARARG_JOIN_5(m) _WX_VARARG_JOIN_4(m), m(5) |
| 653 | #define _WX_VARARG_JOIN_6(m) _WX_VARARG_JOIN_5(m), m(6) |
| 654 | #define _WX_VARARG_JOIN_7(m) _WX_VARARG_JOIN_6(m), m(7) |
| 655 | #define _WX_VARARG_JOIN_8(m) _WX_VARARG_JOIN_7(m), m(8) |
| 656 | #define _WX_VARARG_JOIN_9(m) _WX_VARARG_JOIN_8(m), m(9) |
| 657 | #define _WX_VARARG_JOIN_10(m) _WX_VARARG_JOIN_9(m), m(10) |
| 658 | #define _WX_VARARG_JOIN_11(m) _WX_VARARG_JOIN_10(m), m(11) |
| 659 | #define _WX_VARARG_JOIN_12(m) _WX_VARARG_JOIN_11(m), m(12) |
| 660 | #define _WX_VARARG_JOIN_13(m) _WX_VARARG_JOIN_12(m), m(13) |
| 661 | #define _WX_VARARG_JOIN_14(m) _WX_VARARG_JOIN_13(m), m(14) |
| 662 | #define _WX_VARARG_JOIN_15(m) _WX_VARARG_JOIN_14(m), m(15) |
| 663 | #define _WX_VARARG_JOIN_16(m) _WX_VARARG_JOIN_15(m), m(16) |
| 664 | #define _WX_VARARG_JOIN_17(m) _WX_VARARG_JOIN_16(m), m(17) |
| 665 | #define _WX_VARARG_JOIN_18(m) _WX_VARARG_JOIN_17(m), m(18) |
| 666 | #define _WX_VARARG_JOIN_19(m) _WX_VARARG_JOIN_18(m), m(19) |
| 667 | #define _WX_VARARG_JOIN_20(m) _WX_VARARG_JOIN_19(m), m(20) |
| 668 | #define _WX_VARARG_JOIN_21(m) _WX_VARARG_JOIN_20(m), m(21) |
| 669 | #define _WX_VARARG_JOIN_22(m) _WX_VARARG_JOIN_21(m), m(22) |
| 670 | #define _WX_VARARG_JOIN_23(m) _WX_VARARG_JOIN_22(m), m(23) |
| 671 | #define _WX_VARARG_JOIN_24(m) _WX_VARARG_JOIN_23(m), m(24) |
| 672 | #define _WX_VARARG_JOIN_25(m) _WX_VARARG_JOIN_24(m), m(25) |
| 673 | #define _WX_VARARG_JOIN_26(m) _WX_VARARG_JOIN_25(m), m(26) |
| 674 | #define _WX_VARARG_JOIN_27(m) _WX_VARARG_JOIN_26(m), m(27) |
| 675 | #define _WX_VARARG_JOIN_28(m) _WX_VARARG_JOIN_27(m), m(28) |
| 676 | #define _WX_VARARG_JOIN_29(m) _WX_VARARG_JOIN_28(m), m(29) |
| 677 | #define _WX_VARARG_JOIN_30(m) _WX_VARARG_JOIN_29(m), m(30) |
| 678 | |
| 679 | #define _WX_VARARG_ITER_1(m,a,b,c,d,e,f) m(1,a,b,c,d,e,f) |
| 680 | #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) |
| 681 | #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) |
| 682 | #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) |
| 683 | #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) |
| 684 | #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) |
| 685 | #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) |
| 686 | #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) |
| 687 | #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) |
| 688 | #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) |
| 689 | #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) |
| 690 | #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) |
| 691 | #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) |
| 692 | #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) |
| 693 | #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) |
| 694 | #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) |
| 695 | #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) |
| 696 | #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) |
| 697 | #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) |
| 698 | #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) |
| 699 | #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) |
| 700 | #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) |
| 701 | #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) |
| 702 | #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) |
| 703 | #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) |
| 704 | #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) |
| 705 | #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) |
| 706 | #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) |
| 707 | #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) |
| 708 | #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) |
| 709 | |
| 710 | |
| 711 | #define _WX_VARARG_FIXED_EXPAND_1(t1) \ |
| 712 | t1 f1 |
| 713 | #define _WX_VARARG_FIXED_EXPAND_2(t1,t2) \ |
| 714 | t1 f1, t2 f2 |
| 715 | #define _WX_VARARG_FIXED_EXPAND_3(t1,t2,t3) \ |
| 716 | t1 f1, t2 f2, t3 f3 |
| 717 | #define _WX_VARARG_FIXED_EXPAND_4(t1,t2,t3,t4) \ |
| 718 | t1 f1, t2 f2, t3 f3, t4 f4 |
| 719 | |
| 720 | #define _WX_VARARG_FIXED_UNUSED_EXPAND_1(t1) \ |
| 721 | t1 WXUNUSED(f1) |
| 722 | #define _WX_VARARG_FIXED_UNUSED_EXPAND_2(t1,t2) \ |
| 723 | t1 WXUNUSED(f1), t2 WXUNUSED(f2) |
| 724 | #define _WX_VARARG_FIXED_UNUSED_EXPAND_3(t1,t2,t3) \ |
| 725 | t1 WXUNUSED(f1), t2 WXUNUSED(f2), t3 WXUNUSED(f3) |
| 726 | #define _WX_VARARG_FIXED_UNUSED_EXPAND_4(t1,t2,t3,t4) \ |
| 727 | t1 WXUNUSED(f1), t2 WXUNUSED(f2), t3 WXUNUSED(f3), t4 WXUNUSED(f4) |
| 728 | |
| 729 | #define _WX_VARARG_FIXED_TYPEDEFS_1(t1) \ |
| 730 | typedef t1 TF1 |
| 731 | #define _WX_VARARG_FIXED_TYPEDEFS_2(t1,t2) \ |
| 732 | _WX_VARARG_FIXED_TYPEDEFS_1(t1); typedef t2 TF2 |
| 733 | #define _WX_VARARG_FIXED_TYPEDEFS_3(t1,t2,t3) \ |
| 734 | _WX_VARARG_FIXED_TYPEDEFS_2(t1,t2); typedef t3 TF3 |
| 735 | #define _WX_VARARG_FIXED_TYPEDEFS_4(t1,t2,t3,t4) \ |
| 736 | _WX_VARARG_FIXED_TYPEDEFS_3(t1,t2,t3); typedef t4 TF4 |
| 737 | |
| 738 | // This macro expands N-items tuple of fixed arguments types into part of |
| 739 | // function's declaration. For example, |
| 740 | // "_WX_VARARG_FIXED_EXPAND(3, (int, char*, int))" expands into |
| 741 | // "int f1, char* f2, int f3". |
| 742 | #define _WX_VARARG_FIXED_EXPAND(N, args) \ |
| 743 | _WX_VARARG_FIXED_EXPAND_IMPL(N, args) |
| 744 | #define _WX_VARARG_FIXED_EXPAND_IMPL(N, args) \ |
| 745 | _WX_VARARG_FIXED_EXPAND_##N args |
| 746 | |
| 747 | // Ditto for unused arguments |
| 748 | #define _WX_VARARG_FIXED_UNUSED_EXPAND(N, args) \ |
| 749 | _WX_VARARG_FIXED_UNUSED_EXPAND_IMPL(N, args) |
| 750 | #define _WX_VARARG_FIXED_UNUSED_EXPAND_IMPL(N, args) \ |
| 751 | _WX_VARARG_FIXED_UNUSED_EXPAND_##N args |
| 752 | |
| 753 | // Declarates typedefs for fixed arguments types; i-th fixed argument types |
| 754 | // will have TFi typedef. |
| 755 | #define _WX_VARARG_FIXED_TYPEDEFS(N, args) \ |
| 756 | _WX_VARARG_FIXED_TYPEDEFS_IMPL(N, args) |
| 757 | #define _WX_VARARG_FIXED_TYPEDEFS_IMPL(N, args) \ |
| 758 | _WX_VARARG_FIXED_TYPEDEFS_##N args |
| 759 | |
| 760 | |
| 761 | // This macro calls another macro 'm' passed as second argument 'N' times, |
| 762 | // with its only argument set to 1..N, and concatenates the results using |
| 763 | // comma as separator. |
| 764 | // |
| 765 | // An example: |
| 766 | // #define foo(i) x##i |
| 767 | // // this expands to "x1,x2,x3,x4" |
| 768 | // _WX_VARARG_JOIN(4, foo) |
| 769 | // |
| 770 | // |
| 771 | // N must not be greater than _WX_VARARG_MAX_ARGS (=30). |
| 772 | #define _WX_VARARG_JOIN(N, m) _WX_VARARG_JOIN_IMPL(N, m) |
| 773 | #define _WX_VARARG_JOIN_IMPL(N, m) _WX_VARARG_JOIN_##N(m) |
| 774 | |
| 775 | |
| 776 | // This macro calls another macro 'm' passed as second argument 'N' times, with |
| 777 | // its first argument set to 1..N and the remaining arguments set to 'a', 'b', |
| 778 | // 'c', 'd', 'e' and 'f'. The results are separated with whitespace in the |
| 779 | // expansion. |
| 780 | // |
| 781 | // An example: |
| 782 | // // this macro expands to: |
| 783 | // // foo(1,a,b,c,d,e,f) |
| 784 | // // foo(2,a,b,c,d,e,f) |
| 785 | // // foo(3,a,b,c,d,e,f) |
| 786 | // _WX_VARARG_ITER(3, foo, a, b, c, d, e, f) |
| 787 | // |
| 788 | // N must not be greater than _WX_VARARG_MAX_ARGS (=30). |
| 789 | #define _WX_VARARG_ITER(N,m,a,b,c,d,e,f) \ |
| 790 | _WX_VARARG_ITER_IMPL(N,m,a,b,c,d,e,f) |
| 791 | #define _WX_VARARG_ITER_IMPL(N,m,a,b,c,d,e,f) \ |
| 792 | _WX_VARARG_ITER_##N(m,a,b,c,d,e,f) |
| 793 | |
| 794 | // Generates code snippet for i-th "variadic" argument in vararg function's |
| 795 | // prototype: |
| 796 | #define _WX_VARARG_ARG(i) T##i a##i |
| 797 | |
| 798 | // Like _WX_VARARG_ARG_UNUSED, but outputs argument's type with WXUNUSED: |
| 799 | #define _WX_VARARG_ARG_UNUSED(i) T##i WXUNUSED(a##i) |
| 800 | |
| 801 | // Generates code snippet for i-th type in vararg function's template<...>: |
| 802 | #define _WX_VARARG_TEMPL(i) typename T##i |
| 803 | |
| 804 | // Generates code snippet for passing i-th argument of vararg function |
| 805 | // wrapper to its implementation, normalizing it in the process: |
| 806 | #define _WX_VARARG_PASS_WCHAR(i) \ |
| 807 | wxArgNormalizerWchar<T##i>(a##i, fmt, i).get() |
| 808 | #define _WX_VARARG_PASS_UTF8(i) \ |
| 809 | wxArgNormalizerUtf8<T##i>(a##i, fmt, i).get() |
| 810 | |
| 811 | |
| 812 | // And the same for fixed arguments, _not_ normalizing it: |
| 813 | #define _WX_VARARG_PASS_FIXED(i) f##i |
| 814 | |
| 815 | #define _WX_VARARG_FIND_FMT(i) \ |
| 816 | (wxFormatStringArgumentFinder<TF##i>::find(f##i)) |
| 817 | |
| 818 | #define _WX_VARARG_FORMAT_STRING(numfixed, fixed) \ |
| 819 | _WX_VARARG_FIXED_TYPEDEFS(numfixed, fixed); \ |
| 820 | const wxFormatString *fmt = \ |
| 821 | (_WX_VARARG_JOIN(numfixed, _WX_VARARG_FIND_FMT)) |
| 822 | |
| 823 | #if wxUSE_UNICODE_UTF8 |
| 824 | #define _WX_VARARG_DO_CALL_UTF8(return_kw, impl, implUtf8, N, numfixed) \ |
| 825 | return_kw implUtf8(_WX_VARARG_JOIN(numfixed, _WX_VARARG_PASS_FIXED), \ |
| 826 | _WX_VARARG_JOIN(N, _WX_VARARG_PASS_UTF8)) |
| 827 | #define _WX_VARARG_DO_CALL0_UTF8(return_kw, impl, implUtf8, numfixed) \ |
| 828 | return_kw implUtf8(_WX_VARARG_JOIN(numfixed, _WX_VARARG_PASS_FIXED)) |
| 829 | #endif // wxUSE_UNICODE_UTF8 |
| 830 | |
| 831 | #define _WX_VARARG_DO_CALL_WCHAR(return_kw, impl, implUtf8, N, numfixed) \ |
| 832 | return_kw impl(_WX_VARARG_JOIN(numfixed, _WX_VARARG_PASS_FIXED), \ |
| 833 | _WX_VARARG_JOIN(N, _WX_VARARG_PASS_WCHAR)) |
| 834 | #define _WX_VARARG_DO_CALL0_WCHAR(return_kw, impl, implUtf8, numfixed) \ |
| 835 | return_kw impl(_WX_VARARG_JOIN(numfixed, _WX_VARARG_PASS_FIXED)) |
| 836 | |
| 837 | #if wxUSE_UNICODE_UTF8 |
| 838 | #if wxUSE_UTF8_LOCALE_ONLY |
| 839 | #define _WX_VARARG_DO_CALL _WX_VARARG_DO_CALL_UTF8 |
| 840 | #define _WX_VARARG_DO_CALL0 _WX_VARARG_DO_CALL0_UTF8 |
| 841 | #else // possibly non-UTF8 locales |
| 842 | #define _WX_VARARG_DO_CALL(return_kw, impl, implUtf8, N, numfixed) \ |
| 843 | if ( wxLocaleIsUtf8 ) \ |
| 844 | _WX_VARARG_DO_CALL_UTF8(return_kw, impl, implUtf8, N, numfixed);\ |
| 845 | else \ |
| 846 | _WX_VARARG_DO_CALL_WCHAR(return_kw, impl, implUtf8, N, numfixed) |
| 847 | |
| 848 | #define _WX_VARARG_DO_CALL0(return_kw, impl, implUtf8, numfixed) \ |
| 849 | if ( wxLocaleIsUtf8 ) \ |
| 850 | _WX_VARARG_DO_CALL0_UTF8(return_kw, impl, implUtf8, numfixed); \ |
| 851 | else \ |
| 852 | _WX_VARARG_DO_CALL0_WCHAR(return_kw, impl, implUtf8, numfixed) |
| 853 | #endif // wxUSE_UTF8_LOCALE_ONLY or not |
| 854 | #else // wxUSE_UNICODE_WCHAR or ANSI |
| 855 | #define _WX_VARARG_DO_CALL _WX_VARARG_DO_CALL_WCHAR |
| 856 | #define _WX_VARARG_DO_CALL0 _WX_VARARG_DO_CALL0_WCHAR |
| 857 | #endif // wxUSE_UNICODE_UTF8 / wxUSE_UNICODE_WCHAR |
| 858 | |
| 859 | |
| 860 | // Macro to be used with _WX_VARARG_ITER in the implementation of |
| 861 | // WX_DEFINE_VARARG_FUNC (see its documentation for the meaning of arguments) |
| 862 | #define _WX_VARARG_DEFINE_FUNC(N, rettype, name, \ |
| 863 | impl, implUtf8, numfixed, fixed) \ |
| 864 | template<_WX_VARARG_JOIN(N, _WX_VARARG_TEMPL)> \ |
| 865 | rettype name(_WX_VARARG_FIXED_EXPAND(numfixed, fixed), \ |
| 866 | _WX_VARARG_JOIN(N, _WX_VARARG_ARG)) \ |
| 867 | { \ |
| 868 | _WX_VARARG_FORMAT_STRING(numfixed, fixed); \ |
| 869 | _WX_VARARG_DO_CALL(return, impl, implUtf8, N, numfixed); \ |
| 870 | } |
| 871 | |
| 872 | #define _WX_VARARG_DEFINE_FUNC_N0(rettype, name, \ |
| 873 | impl, implUtf8, numfixed, fixed) \ |
| 874 | inline rettype name(_WX_VARARG_FIXED_EXPAND(numfixed, fixed)) \ |
| 875 | { \ |
| 876 | _WX_VARARG_DO_CALL0(return, impl, implUtf8, numfixed); \ |
| 877 | } |
| 878 | |
| 879 | // Macro to be used with _WX_VARARG_ITER in the implementation of |
| 880 | // WX_DEFINE_VARARG_FUNC_VOID (see its documentation for the meaning of |
| 881 | // arguments; rettype is ignored and is used only to satisfy _WX_VARARG_ITER's |
| 882 | // requirements). |
| 883 | #define _WX_VARARG_DEFINE_FUNC_VOID(N, rettype, name, \ |
| 884 | impl, implUtf8, numfixed, fixed) \ |
| 885 | template<_WX_VARARG_JOIN(N, _WX_VARARG_TEMPL)> \ |
| 886 | void name(_WX_VARARG_FIXED_EXPAND(numfixed, fixed), \ |
| 887 | _WX_VARARG_JOIN(N, _WX_VARARG_ARG)) \ |
| 888 | { \ |
| 889 | _WX_VARARG_FORMAT_STRING(numfixed, fixed); \ |
| 890 | _WX_VARARG_DO_CALL(wxEMPTY_PARAMETER_VALUE, \ |
| 891 | impl, implUtf8, N, numfixed); \ |
| 892 | } |
| 893 | |
| 894 | #define _WX_VARARG_DEFINE_FUNC_VOID_N0(name, impl, implUtf8, numfixed, fixed) \ |
| 895 | inline void name(_WX_VARARG_FIXED_EXPAND(numfixed, fixed)) \ |
| 896 | { \ |
| 897 | _WX_VARARG_DO_CALL0(wxEMPTY_PARAMETER_VALUE, \ |
| 898 | impl, implUtf8, numfixed); \ |
| 899 | } |
| 900 | |
| 901 | // Macro to be used with _WX_VARARG_ITER in the implementation of |
| 902 | // WX_DEFINE_VARARG_FUNC_CTOR (see its documentation for the meaning of |
| 903 | // arguments; rettype is ignored and is used only to satisfy _WX_VARARG_ITER's |
| 904 | // requirements). |
| 905 | #define _WX_VARARG_DEFINE_FUNC_CTOR(N, rettype, name, \ |
| 906 | impl, implUtf8, numfixed, fixed) \ |
| 907 | template<_WX_VARARG_JOIN(N, _WX_VARARG_TEMPL)> \ |
| 908 | name(_WX_VARARG_FIXED_EXPAND(numfixed, fixed), \ |
| 909 | _WX_VARARG_JOIN(N, _WX_VARARG_ARG)) \ |
| 910 | { \ |
| 911 | _WX_VARARG_FORMAT_STRING(numfixed, fixed); \ |
| 912 | _WX_VARARG_DO_CALL(wxEMPTY_PARAMETER_VALUE, \ |
| 913 | impl, implUtf8, N, numfixed); \ |
| 914 | } |
| 915 | |
| 916 | #define _WX_VARARG_DEFINE_FUNC_CTOR_N0(name, impl, implUtf8, numfixed, fixed) \ |
| 917 | inline name(_WX_VARARG_FIXED_EXPAND(numfixed, fixed)) \ |
| 918 | { \ |
| 919 | _WX_VARARG_DO_CALL0(wxEMPTY_PARAMETER_VALUE, \ |
| 920 | impl, implUtf8, numfixed); \ |
| 921 | } |
| 922 | |
| 923 | // Macro to be used with _WX_VARARG_ITER in the implementation of |
| 924 | // WX_DEFINE_VARARG_FUNC_NOP, i.e. empty stub for a disabled vararg function. |
| 925 | // The rettype and impl arguments are ignored. |
| 926 | #define _WX_VARARG_DEFINE_FUNC_NOP(N, rettype, name, \ |
| 927 | impl, implUtf8, numfixed, fixed) \ |
| 928 | template<_WX_VARARG_JOIN(N, _WX_VARARG_TEMPL)> \ |
| 929 | void name(_WX_VARARG_FIXED_UNUSED_EXPAND(numfixed, fixed), \ |
| 930 | _WX_VARARG_JOIN(N, _WX_VARARG_ARG_UNUSED)) \ |
| 931 | {} |
| 932 | |
| 933 | #define _WX_VARARG_DEFINE_FUNC_NOP_N0(name, numfixed, fixed) \ |
| 934 | inline void name(_WX_VARARG_FIXED_UNUSED_EXPAND(numfixed, fixed)) \ |
| 935 | {} |
| 936 | |
| 937 | |
| 938 | // ---------------------------------------------------------------------------- |
| 939 | // workaround for OpenWatcom bug #351 |
| 940 | // ---------------------------------------------------------------------------- |
| 941 | |
| 942 | #ifdef __WATCOMC__ |
| 943 | // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351 |
| 944 | |
| 945 | // This macro can be used to forward a 'vararg' template to another one with |
| 946 | // different fixed arguments types. Parameters are same as for |
| 947 | // WX_DEFINE_VARARG_FUNC (rettype=void can be used here), 'convfixed' is how |
| 948 | // to convert fixed arguments. For example, this is typical code for dealing |
| 949 | // with different forms of format string: |
| 950 | // |
| 951 | // WX_DEFINE_VARARG_FUNC_VOID(Printf, 1, (const wxFormatString&), |
| 952 | // DoPrintfWchar, DoPrintfUtf8) |
| 953 | // #ifdef __WATCOMC__ |
| 954 | // WX_VARARG_WATCOM_WORKAROUND(void, Printf, 1, (const wxString&), |
| 955 | // (wxFormatString(f1))) |
| 956 | // WX_VARARG_WATCOM_WORKAROUND(void, Printf, 1, (const char*), |
| 957 | // (wxFormatString(f1))) |
| 958 | // ... |
| 959 | #define WX_VARARG_WATCOM_WORKAROUND(rettype, name, numfixed, fixed, convfixed)\ |
| 960 | _WX_VARARG_ITER(_WX_VARARG_MAX_ARGS, \ |
| 961 | _WX_VARARG_WATCOM_WORKAROUND, \ |
| 962 | rettype, name, convfixed, dummy, numfixed, fixed) |
| 963 | |
| 964 | #define WX_VARARG_WATCOM_WORKAROUND_CTOR(name, numfixed, fixed, convfixed) \ |
| 965 | _WX_VARARG_ITER(_WX_VARARG_MAX_ARGS, \ |
| 966 | _WX_VARARG_WATCOM_WORKAROUND_CTOR, \ |
| 967 | dummy, name, convfixed, dummy, numfixed, fixed) |
| 968 | |
| 969 | #define _WX_VARARG_WATCOM_UNPACK_1(a1) a1 |
| 970 | #define _WX_VARARG_WATCOM_UNPACK_2(a1, a2) a1, a2 |
| 971 | #define _WX_VARARG_WATCOM_UNPACK_3(a1, a2, a3) a1, a2, a3 |
| 972 | #define _WX_VARARG_WATCOM_UNPACK_4(a1, a2, a3, a4) a1, a2, a3, a4 |
| 973 | #define _WX_VARARG_WATCOM_UNPACK(N, convfixed) \ |
| 974 | _WX_VARARG_WATCOM_UNPACK_##N convfixed |
| 975 | |
| 976 | #define _WX_VARARG_PASS_WATCOM(i) a##i |
| 977 | |
| 978 | #define _WX_VARARG_WATCOM_WORKAROUND(N, rettype, name, \ |
| 979 | convfixed, dummy, numfixed, fixed) \ |
| 980 | template<_WX_VARARG_JOIN(N, _WX_VARARG_TEMPL)> \ |
| 981 | rettype name(_WX_VARARG_FIXED_EXPAND(numfixed, fixed), \ |
| 982 | _WX_VARARG_JOIN(N, _WX_VARARG_ARG)) \ |
| 983 | { \ |
| 984 | return name(_WX_VARARG_WATCOM_UNPACK(numfixed, convfixed), \ |
| 985 | _WX_VARARG_JOIN(N, _WX_VARARG_PASS_WATCOM)); \ |
| 986 | } |
| 987 | |
| 988 | #define _WX_VARARG_WATCOM_WORKAROUND_CTOR(N, dummy1, name, \ |
| 989 | convfixed, dummy2, numfixed, fixed) \ |
| 990 | template<_WX_VARARG_JOIN(N, _WX_VARARG_TEMPL)> \ |
| 991 | name(_WX_VARARG_FIXED_EXPAND(numfixed, fixed), \ |
| 992 | _WX_VARARG_JOIN(N, _WX_VARARG_ARG)) \ |
| 993 | { \ |
| 994 | name(_WX_VARARG_WATCOM_UNPACK(numfixed, convfixed), \ |
| 995 | _WX_VARARG_JOIN(N, _WX_VARARG_PASS_WATCOM)); \ |
| 996 | } |
| 997 | |
| 998 | #endif // __WATCOMC__ |
| 999 | |
| 1000 | #endif // _WX_STRVARARG_H_ |