+
+// ----------------------------------------------------------------------------
+// wxFormatString
+// ----------------------------------------------------------------------------
+
+// This class must be used for format string argument of the functions
+// defined using WX_DEFINE_VARARG_FUNC_* macros. It converts the string to
+// char* or wchar_t* for passing to implementation function efficiently (i.e.
+// without keeping the converted string in memory for longer than necessary,
+// like c_str()). It also converts format string to the correct form that
+// accounts for string changes done by wxArgNormalizer<>
+//
+// Note that this class can _only_ be used for function arguments!
+class WXDLLIMPEXP_BASE wxFormatString
+{
+public:
+ wxFormatString(const char *str)
+ : m_char(wxScopedCharBuffer::CreateNonOwned(str)), m_str(NULL), m_cstr(NULL) {}
+ wxFormatString(const wchar_t *str)
+ : m_wchar(wxScopedWCharBuffer::CreateNonOwned(str)), m_str(NULL), m_cstr(NULL) {}
+ wxFormatString(const wxString& str)
+ : m_str(&str), m_cstr(NULL) {}
+ wxFormatString(const wxCStrData& str)
+ : m_str(NULL), m_cstr(&str) {}
+ wxFormatString(const wxScopedCharBuffer& str)
+ : m_char(str), m_str(NULL), m_cstr(NULL) {}
+ wxFormatString(const wxScopedWCharBuffer& str)
+ : m_wchar(str), m_str(NULL), m_cstr(NULL) {}
+
+ // Possible argument types. These are or-combinable for wxASSERT_ARG_TYPE
+ // convenience. Some of the values are or-combined with another value, this
+ // expresses "supertypes" for use with wxASSERT_ARG_TYPE masks. For example,
+ // a char* string is also a pointer and an integer is also a char.
+ enum ArgumentType
+ {
+ Arg_Char = 0x0001, // character as char %c
+ Arg_Pointer = 0x0002, // %p
+ Arg_String = 0x0004 | Arg_Pointer, // any form of string (%s and %p too)
+
+ Arg_Int = 0x0008 | Arg_Char, // (ints can be used with %c)
+#if SIZEOF_INT == SIZEOF_LONG
+ Arg_LongInt = Arg_Int,
+#else
+ Arg_LongInt = 0x0010,
+#endif
+#if defined(SIZEOF_LONG_LONG) && SIZEOF_LONG_LONG == SIZEOF_LONG
+ Arg_LongLongInt = Arg_LongInt,
+#elif defined(wxLongLong_t)
+ Arg_LongLongInt = 0x0020,
+#endif
+
+ Arg_Double = 0x0040,
+ Arg_LongDouble = 0x0080,
+
+#if defined(wxSIZE_T_IS_UINT)
+ Arg_Size_t = Arg_Int,
+#elif defined(wxSIZE_T_IS_ULONG)
+ Arg_Size_t = Arg_LongInt,
+#elif defined(SIZEOF_LONG_LONG) && SIZEOF_SIZE_T == SIZEOF_LONG_LONG
+ Arg_Size_t = Arg_LongLongInt,
+#else
+ Arg_Size_t = 0x0100,
+#endif
+
+ Arg_IntPtr = 0x0200, // %n -- store # of chars written
+ Arg_ShortIntPtr = 0x0400,
+ Arg_LongIntPtr = 0x0800,
+
+ Arg_Unknown = 0x8000 // unrecognized specifier (likely error)
+ };
+
+ // returns the type of format specifier for n-th variadic argument (this is
+ // not necessarily n-th format specifier if positional specifiers are used);
+ // called by wxArgNormalizer<> specializations to get information about
+ // n-th variadic argument desired representation
+ ArgumentType GetArgumentType(unsigned n) const;
+
+ // returns the value passed to ctor, only converted to wxString, similarly
+ // to other InputAsXXX() methods
+ wxString InputAsString() const;
+
+#if !wxUSE_UNICODE_WCHAR
+ operator const char*() const
+ { return const_cast<wxFormatString*>(this)->AsChar(); }
+private:
+ // InputAsChar() returns the value passed to ctor, only converted
+ // to char, while AsChar() takes the string returned by InputAsChar()
+ // and does format string conversion on it as well (and similarly for
+ // ..AsWChar() below)
+ const char* InputAsChar();
+ const char* AsChar();
+ wxScopedCharBuffer m_convertedChar;
+#endif // !wxUSE_UNICODE_WCHAR
+
+#if wxUSE_UNICODE && !wxUSE_UTF8_LOCALE_ONLY
+public:
+ operator const wchar_t*() const
+ { return const_cast<wxFormatString*>(this)->AsWChar(); }
+private:
+ const wchar_t* InputAsWChar();
+ const wchar_t* AsWChar();
+ wxScopedWCharBuffer m_convertedWChar;
+#endif // wxUSE_UNICODE && !wxUSE_UTF8_LOCALE_ONLY
+
+private:
+ wxScopedCharBuffer m_char;
+ wxScopedWCharBuffer m_wchar;
+
+ // NB: we can use a pointer here, because wxFormatString is only used
+ // as function argument, so it has shorter life than the string
+ // passed to the ctor
+ const wxString * const m_str;
+ const wxCStrData * const m_cstr;
+
+ wxDECLARE_NO_ASSIGN_CLASS(wxFormatString);
+};
+
+// these two helper classes are used to find wxFormatString argument among fixed
+// arguments passed to a vararg template
+struct wxFormatStringArgument
+{
+ wxFormatStringArgument(const wxFormatString *s = NULL) : m_str(s) {}
+ const wxFormatString *m_str;
+
+ // overriding this operator allows us to reuse _WX_VARARG_JOIN macro
+ wxFormatStringArgument operator,(const wxFormatStringArgument& a) const
+ {
+ wxASSERT_MSG( m_str == NULL || a.m_str == NULL,
+ "can't have two format strings in vararg function" );
+ return wxFormatStringArgument(m_str ? m_str : a.m_str);
+ }
+
+ operator const wxFormatString*() const { return m_str; }
+};
+
+template<typename T>
+struct wxFormatStringArgumentFinder
+{
+ static wxFormatStringArgument find(T)
+ {
+ // by default, arguments are not format strings, so return "not found"
+ return wxFormatStringArgument();
+ }
+};
+
+template<>
+struct wxFormatStringArgumentFinder<const wxFormatString&>
+{
+ static wxFormatStringArgument find(const wxFormatString& arg)
+ { return wxFormatStringArgument(&arg); }
+};
+
+template<>
+struct wxFormatStringArgumentFinder<wxFormatString>
+ : public wxFormatStringArgumentFinder<const wxFormatString&> {};
+
+// avoid passing big objects by value to wxFormatStringArgumentFinder::find()
+// (and especially wx[W]CharBuffer with its auto_ptr<> style semantics!):
+template<>
+struct wxFormatStringArgumentFinder<wxString>
+ : public wxFormatStringArgumentFinder<const wxString&> {};
+
+template<>
+struct wxFormatStringArgumentFinder<wxScopedCharBuffer>
+ : public wxFormatStringArgumentFinder<const wxScopedCharBuffer&> {};
+
+template<>
+struct wxFormatStringArgumentFinder<wxScopedWCharBuffer>
+ : public wxFormatStringArgumentFinder<const wxScopedWCharBuffer&> {};
+
+template<>
+struct wxFormatStringArgumentFinder<wxCharBuffer>
+ : public wxFormatStringArgumentFinder<const wxCharBuffer&> {};
+
+template<>
+struct wxFormatStringArgumentFinder<wxWCharBuffer>
+ : public wxFormatStringArgumentFinder<const wxWCharBuffer&> {};
+
+