1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: wx/wxcrtvararg.h
3 // Purpose: Type-safe ANSI and Unicode builds compatible wrappers for
4 // printf(), scanf() and related CRT functions
5 // Author: Joel Farley, Ove Kåven
6 // Modified by: Vadim Zeitlin, Robert Roebling, Ron Lee
9 // Copyright: (c) 2007 REA Elektronik GmbH
10 // Licence: wxWindows licence
11 ///////////////////////////////////////////////////////////////////////////////
13 #ifndef _WX_WXCRTVARARG_H_
14 #define _WX_WXCRTVARARG_H_
17 #include "wx/strvararg.h"
19 #include "wx/string.h"
21 // ----------------------------------------------------------------------------
22 // CRT functions aliases
23 // ----------------------------------------------------------------------------
25 /* Required for wxPrintf() etc */
28 #ifdef wxHAVE_TCHAR_SUPPORT
29 #define wxCRT_Fprintf _ftprintf
30 #define wxCRT_Printf _tprintf
31 #define wxCRT_Vfprintf _vftprintf
32 #define wxCRT_Vprintf _vtprintf
33 #define wxCRT_Vsprintf _vstprintf
34 #define wxCRT_Vscanf _vtscanf
35 #define wxCRT_Vfscanf _vftscanf
36 #define wxCRT_Vsscanf _vstscanf
37 #else /* !TCHAR-aware compilers */
39 #if !wxUSE_UNICODE /* ASCII */
40 #define wxCRT_Fprintf fprintf
41 #define wxCRT_Fscanf fscanf
42 #define wxCRT_Printf printf
43 #define wxCRT_Vfprintf vfprintf
44 #define wxCRT_Vprintf vprintf
45 #define wxCRT_Vsprintf vsprintf
46 #define wxCRT_Scanf scanf
47 #define wxCRT_Sscanf sscanf
48 #define wxCRT_Vsscanf vsscanf
50 #endif /* TCHAR-aware compilers/the others */
52 /* Required for wxScanf() etc. */
53 #define wxCRT_VscanfA vscanf
54 #define wxCRT_VsscanfA vsscanf
55 #define wxCRT_VfscanfA vfscanf
56 #define wxCRT_VscanfW vwscanf
57 #define wxCRT_VsscanfW vswscanf
58 #define wxCRT_VfscanfW vfwscanf
60 /* printf() family saga */
63 For some systems [v]snprintf() exists in the system libraries but not in the
64 headers, so we need to declare it ourselves to be able to use it.
66 #if defined(HAVE_VSNPRINTF) && !defined(HAVE_VSNPRINTF_DECL)
72 int vsnprintf(char *str
, size_t size
, const char *format
, va_list ap
);
73 #endif /* !HAVE_VSNPRINTF_DECL */
75 #if defined(HAVE_SNPRINTF) && !defined(HAVE_SNPRINTF_DECL)
81 WXDLLIMPEXP_BASE
int snprintf(char *str
, size_t size
, const char *format
, ...);
82 #endif /* !HAVE_SNPRINTF_DECL */
84 /* Wrapper for vsnprintf if it's 3rd parameter is non-const. Note: the
85 * same isn't done for snprintf below, the builtin wxSnprintf_ is used
86 * instead since it's already a simple wrapper */
87 #if defined __cplusplus && defined HAVE_BROKEN_VSNPRINTF_DECL
88 inline int wx_fixed_vsnprintf(char *str
, size_t size
, const char *format
, va_list ap
)
90 return vsnprintf(str
, size
, (char*)format
, ap
);
95 MinGW MSVCRT has non-standard vswprintf() (for MSVC compatibility
96 presumably) and normally _vsnwprintf() is used instead
98 #if defined(HAVE_VSWPRINTF) && defined(__MINGW32__)
102 #if wxUSE_PRINTF_POS_PARAMS
104 The systems where vsnprintf() supports positional parameters should
105 define the HAVE_UNIX98_PRINTF symbol.
107 On systems which don't (e.g. Windows) we are forced to use
108 our wxVsnprintf() implementation.
110 #if defined(HAVE_UNIX98_PRINTF)
112 #ifdef HAVE_VSWPRINTF
113 #define wxVsnprintf_ vswprintf
116 #ifdef HAVE_BROKEN_VSNPRINTF_DECL
117 #define wxVsnprintf_ wx_fixed_vsnprintf
119 #define wxVsnprintf_ vsnprintf
122 #else /* !HAVE_UNIX98_PRINTF */
124 The only compiler with positional parameters support under Windows
125 is VC++ 8.0 which provides a new xxprintf_p() functions family.
126 The 2003 PSDK includes a slightly earlier version of VC8 than the
127 main release and does not have the printf_p functions.
129 #if defined _MSC_FULL_VER && _MSC_FULL_VER >= 140050727 && !defined __WXWINCE__
131 #define wxVsnprintf_ _vswprintf_p
133 #define wxVsnprintf_ _vsprintf_p
136 #endif /* HAVE_UNIX98_PRINTF/!HAVE_UNIX98_PRINTF */
137 #else /* !wxUSE_PRINTF_POS_PARAMS */
139 We always want to define safe snprintf() function to be used instead of
140 sprintf(). Some compilers already have it (or rather vsnprintf() which
141 we really need...), otherwise we implement it using our own printf()
144 We define function with a trailing underscore here because the real one
145 is a wrapper around it as explained below
148 /* first deal with TCHAR-aware compilers which have _vsntprintf */
150 #if defined(__VISUALC__) || \
151 (defined(__BORLANDC__) && __BORLANDC__ >= 0x540)
152 #define wxVsnprintf_ _vsntprintf
156 /* if this didn't work, define it separately for Unicode and ANSI builds */
159 #if defined(HAVE__VSNWPRINTF)
160 #define wxVsnprintf_ _vsnwprintf
161 #elif defined(HAVE_VSWPRINTF)
162 #define wxVsnprintf_ vswprintf
163 #elif defined(__WATCOMC__)
164 #define wxVsnprintf_ _vsnwprintf
168 All versions of CodeWarrior supported by wxWidgets apparently
169 have both snprintf() and vsnprintf()
171 #if defined(HAVE_VSNPRINTF) \
172 || defined(__MWERKS__) || defined(__WATCOMC__)
173 #ifdef HAVE_BROKEN_VSNPRINTF_DECL
174 #define wxVsnprintf_ wx_fixed_vsnprintf
176 #define wxVsnprintf_ vsnprintf
179 #endif /* Unicode/ASCII */
180 #endif /* wxVsnprintf_ */
181 #endif /* wxUSE_PRINTF_POS_PARAMS/!wxUSE_PRINTF_POS_PARAMS */
184 /* no (suitable) vsnprintf(), cook our own */
186 wxVsnprintf_(wxChar
*buf
, size_t len
, const wxChar
*format
, va_list argptr
);
188 #define wxUSE_WXVSNPRINTF 1
190 #define wxUSE_WXVSNPRINTF 0
194 In Unicode mode we need to have all standard functions such as wprintf() and
195 so on but not all systems have them so use our own implementations in this
198 #if wxUSE_UNICODE && !defined(wxHAVE_TCHAR_SUPPORT) && !defined(HAVE_WPRINTF)
199 #define wxNEED_WPRINTF
203 More Unicode complications: although both ANSI C and C++ define a number of
204 wide character functions such as wprintf(), not all environments have them.
205 Worse, those which do have different behaviours: under Windows, %s format
206 specifier changes its meaning in Unicode build and expects a Unicode string
207 while under Unix/POSIX it still means an ASCII string even for wprintf() and
208 %ls has to be used for wide strings.
210 We choose to always emulate Windows behaviour as more useful for us so even
211 if we have wprintf() we still must wrap it in a non trivial wxPrintf().
215 #if defined(wxNEED_PRINTF_CONVERSION) || defined(wxNEED_WPRINTF)
217 we need to implement all wide character printf functions either because
218 we don't have them at all or because they don't have the semantics we
221 int wxCRT_Printf( const wxChar
*format
, ... ) ATTRIBUTE_PRINTF_1
;
222 int wxCRT_Fprintf( FILE *stream
, const wxChar
*format
, ... ) ATTRIBUTE_PRINTF_2
;
223 int wxCRT_Vfprintf( FILE *stream
, const wxChar
*format
, va_list ap
);
224 int wxCRT_Vprintf( const wxChar
*format
, va_list ap
);
225 int wxCRT_Vsprintf( wxChar
*str
, const wxChar
*format
, va_list ap
);
226 #endif /* wxNEED_PRINTF_CONVERSION */
228 /* these 2 can be simply mapped to the versions with underscore at the end */
229 /* if we don't have to do the conversion */
231 However, if we don't have any vswprintf() at all we don't need to redefine
232 anything as our own wxVsnprintf_() already behaves as needed.
234 #if defined(wxNEED_PRINTF_CONVERSION) && defined(wxVsnprintf_)
235 int wxCRT_Vsnprintf( wxChar
*str
, size_t size
, const wxChar
*format
, va_list ap
);
237 #define wxCRT_Vsnprintf wxVsnprintf_
241 // ----------------------------------------------------------------------------
242 // user-friendly wrappers to CRT functions
243 // ----------------------------------------------------------------------------
246 // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351
247 #define wxPrintf wxPrintf_Impl
248 #define wxFprintf wxFprintf_Impl
249 #define wxSprintf wxSprintf_Impl
250 #define wxSnprintf wxSnprintf_Impl
253 // FIXME-UTF8: explicit wide-string and short-string format specifiers
254 // (%hs, %ls and variants) are currently broken, only %s works
255 // as expected (regardless of the build)
257 // FIXME-UTF8: %c (and %hc, %lc) don't work as expected either: in UTF-8 build,
258 // we should replace them with %s (as some Unicode chars may be
259 // encoded with >1 bytes) and in all builds, we should use wchar_t
260 // for all characters and convert char to it;
261 // we'll also need wxArgNormalizer<T> specializations for char,
262 // wchar_t, wxUniChar and wxUniCharRef to handle this correctly
264 WX_DEFINE_VARARG_FUNC(int, wxPrintf
, 1, (const wxFormatString
&),
265 wxCRT_Printf
, printf
)
266 WX_DEFINE_VARARG_FUNC(int, wxFprintf
, 2, (FILE*, const wxFormatString
&),
267 wxCRT_Fprintf
, fprintf
)
269 // va_list versions of printf functions simply forward to the respective
270 // CRT function; note that they assume that va_list was created using
271 // wxArgNormalizer<T>!
272 #if wxUSE_UNICODE_UTF8
273 #if wxUSE_UTF8_LOCALE_ONLY
274 #define WX_VARARG_VFOO_IMPL(args, implWchar, implUtf8) \
277 #define WX_VARARG_VFOO_IMPL(args, implWchar, implUtf8) \
278 if ( wxLocaleIsUtf8 ) return implUtf8 args; \
279 else return implWchar args
281 #else // wxUSE_UNICODE_WCHAR / ANSI
282 #define WX_VARARG_VFOO_IMPL(args, implWchar, implUtf8) \
283 return implWchar args
287 wxVprintf(const wxString
& format
, va_list ap
)
289 WX_VARARG_VFOO_IMPL((wxFormatString(format
), ap
),
290 wxCRT_Vprintf
, vprintf
);
294 wxVfprintf(FILE *f
, const wxString
& format
, va_list ap
)
296 WX_VARARG_VFOO_IMPL((f
, wxFormatString(format
), ap
),
297 wxCRT_Vfprintf
, vfprintf
);
300 #undef WX_VARARG_VFOO_IMPL
303 // wxSprintf() and friends have to be implemented in two forms, one for
304 // writing to char* buffer and one for writing to wchar_t*:
306 #if !wxUSE_UTF8_LOCALE_ONLY
307 int WXDLLIMPEXP_BASE
wxDoSprintfWchar(char *str
, const wxChar
*format
, ...);
309 #if wxUSE_UNICODE_UTF8
310 int WXDLLIMPEXP_BASE
wxDoSprintfUtf8(char *str
, const char *format
, ...);
312 WX_DEFINE_VARARG_FUNC(int, wxSprintf
, 2, (char*, const wxFormatString
&),
313 wxDoSprintfWchar
, wxDoSprintfUtf8
)
316 wxVsprintf(char *str
, const wxString
& format
, va_list argptr
);
318 #if !wxUSE_UTF8_LOCALE_ONLY
319 int WXDLLIMPEXP_BASE
wxDoSnprintfWchar(char *str
, size_t size
, const wxChar
*format
, ...);
321 #if wxUSE_UNICODE_UTF8
322 int WXDLLIMPEXP_BASE
wxDoSnprintfUtf8(char *str
, size_t size
, const char *format
, ...);
324 WX_DEFINE_VARARG_FUNC(int, wxSnprintf
, 3, (char*, size_t, const wxFormatString
&),
325 wxDoSnprintfWchar
, wxDoSnprintfUtf8
)
328 wxVsnprintf(char *str
, size_t size
, const wxString
& format
, va_list argptr
);
332 #if !wxUSE_UTF8_LOCALE_ONLY
333 int WXDLLIMPEXP_BASE
wxDoSprintfWchar(wchar_t *str
, const wxChar
*format
, ...);
335 #if wxUSE_UNICODE_UTF8
336 int WXDLLIMPEXP_BASE
wxDoSprintfUtf8(wchar_t *str
, const char *format
, ...);
338 WX_DEFINE_VARARG_FUNC(int, wxSprintf
, 2, (wchar_t*, const wxFormatString
&),
339 wxDoSprintfWchar
, wxDoSprintfUtf8
)
342 wxVsprintf(wchar_t *str
, const wxString
& format
, va_list argptr
);
344 #if !wxUSE_UTF8_LOCALE_ONLY
345 int WXDLLIMPEXP_BASE
wxDoSnprintfWchar(wchar_t *str
, size_t size
, const wxChar
*format
, ...);
347 #if wxUSE_UNICODE_UTF8
348 int WXDLLIMPEXP_BASE
wxDoSnprintfUtf8(wchar_t *str
, size_t size
, const char *format
, ...);
350 WX_DEFINE_VARARG_FUNC(int, wxSnprintf
, 3, (wchar_t*, size_t, const wxFormatString
&),
351 wxDoSnprintfWchar
, wxDoSnprintfUtf8
)
354 wxVsnprintf(wchar_t *str
, size_t size
, const wxString
& format
, va_list argptr
);
356 #endif // wxUSE_UNICODE
359 // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351
361 // fortunately, OpenWatcom implements __VA_ARGS__, so we can provide macros
362 // that cast the format argument to wxString:
368 #define wxPrintf(fmt, ...) \
369 wxPrintf_Impl(wxFormatString(fmt), __VA_ARGS__)
370 #define wxFprintf(f, fmt, ...) \
371 wxFprintf_Impl(f, wxFormatString(fmt), __VA_ARGS__)
372 #define wxSprintf(s, fmt, ...) \
373 wxSprintf_Impl(s, wxFormatString(fmt), __VA_ARGS__)
374 #define wxSnprintf(s, n, fmt, ...) \
375 wxSnprintf_Impl(s, n, wxFormatString(fmt), __VA_ARGS__)
376 #endif // __WATCOMC__
379 // We can't use wxArgNormalizer<T> for variadic arguments to wxScanf() etc.
380 // because they are writable, so instead of providing friendly template
381 // vararg-like functions, we just provide both char* and wchar_t* variants
382 // of these functions. The type of output variadic arguments for %s must match
383 // the type of 'str' and 'format' arguments.
385 // For compatibility with earlier wx versions, we also provide wxSscanf()
386 // version with the first argument (input string) wxString; for this version,
387 // the type of output string values is determined by the type of format string
390 int WXDLLIMPEXP_BASE
wxScanf(const char *format
, ...);
391 int WXDLLIMPEXP_BASE
wxScanf(const wchar_t *format
, ...);
393 int WXDLLIMPEXP_BASE
wxFscanf(FILE *stream
, const char *format
, ...);
394 int WXDLLIMPEXP_BASE
wxFscanf(FILE *stream
, const wchar_t *format
, ...);
396 int WXDLLIMPEXP_BASE
wxSscanf(const char *str
, const char *format
, ...);
397 int WXDLLIMPEXP_BASE
wxSscanf(const wchar_t *str
, const wchar_t *format
, ...);
398 int WXDLLIMPEXP_BASE
wxSscanf(const wxCharBuffer
& str
, const char *format
, ...);
399 int WXDLLIMPEXP_BASE
wxSscanf(const wxWCharBuffer
& str
, const wchar_t *format
, ...);
400 int WXDLLIMPEXP_BASE
wxSscanf(const wxString
& str
, const char *format
, ...);
401 int WXDLLIMPEXP_BASE
wxSscanf(const wxString
& str
, const wchar_t *format
, ...);
402 int WXDLLIMPEXP_BASE
wxSscanf(const wxCStrData
& str
, const char *format
, ...);
403 int WXDLLIMPEXP_BASE
wxSscanf(const wxCStrData
& str
, const wchar_t *format
, ...);
405 int WXDLLIMPEXP_BASE
wxVsscanf(const char *str
, const char *format
, va_list ap
);
406 int WXDLLIMPEXP_BASE
wxVsscanf(const wchar_t *str
, const wchar_t *format
, va_list ap
);
407 int WXDLLIMPEXP_BASE
wxVsscanf(const wxCharBuffer
& str
, const char *format
, va_list ap
);
408 int WXDLLIMPEXP_BASE
wxVsscanf(const wxWCharBuffer
& str
, const wchar_t *format
, va_list ap
);
409 int WXDLLIMPEXP_BASE
wxVsscanf(const wxString
& str
, const char *format
, va_list ap
);
410 int WXDLLIMPEXP_BASE
wxVsscanf(const wxString
& str
, const wchar_t *format
, va_list ap
);
411 int WXDLLIMPEXP_BASE
wxVsscanf(const wxCStrData
& str
, const char *format
, va_list ap
);
412 int WXDLLIMPEXP_BASE
wxVsscanf(const wxCStrData
& str
, const wchar_t *format
, va_list ap
);
414 #endif /* _WX_WXCRTVARARG_H_ */