wxSscanf() and friends are now Unicode+ANSI friendly wrappers instead of defines...
[wxWidgets.git] / include / wx / wxcrtvararg.h
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
7 // Created: 2007-02-19
8 // RCS-ID: $Id$
9 // Copyright: (c) 2007 REA Elektronik GmbH
10 // Licence: wxWindows licence
11 ///////////////////////////////////////////////////////////////////////////////
12
13 #ifndef _WX_WXCRTVARARG_H_
14 #define _WX_WXCRTVARARG_H_
15
16 #include "wx/wxcrt.h"
17 #include "wx/strvararg.h"
18
19 #include "wx/string.h"
20
21 // ----------------------------------------------------------------------------
22 // CRT functions aliases
23 // ----------------------------------------------------------------------------
24
25 /* Required for wxPrintf() etc */
26 #include <stdarg.h>
27
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 */
38
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
49 #endif /* ASCII */
50 #endif /* TCHAR-aware compilers/the others */
51
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
59
60 /* printf() family saga */
61
62 /*
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.
65 */
66 #if defined(HAVE_VSNPRINTF) && !defined(HAVE_VSNPRINTF_DECL)
67 #ifdef __cplusplus
68 extern "C"
69 #else
70 extern
71 #endif
72 int vsnprintf(char *str, size_t size, const char *format, va_list ap);
73 #endif /* !HAVE_VSNPRINTF_DECL */
74
75 #if defined(HAVE_SNPRINTF) && !defined(HAVE_SNPRINTF_DECL)
76 #ifdef __cplusplus
77 extern "C"
78 #else
79 extern
80 #endif
81 WXDLLIMPEXP_BASE int snprintf(char *str, size_t size, const char *format, ...);
82 #endif /* !HAVE_SNPRINTF_DECL */
83
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)
89 {
90 return vsnprintf(str, size, (char*)format, ap);
91 }
92 #endif
93
94 /*
95 MinGW MSVCRT has non-standard vswprintf() (for MSVC compatibility
96 presumably) and normally _vsnwprintf() is used instead
97 */
98 #if defined(HAVE_VSWPRINTF) && defined(__MINGW32__)
99 #undef HAVE_VSWPRINTF
100 #endif
101
102 #if wxUSE_PRINTF_POS_PARAMS
103 /*
104 The systems where vsnprintf() supports positional parameters should
105 define the HAVE_UNIX98_PRINTF symbol.
106
107 On systems which don't (e.g. Windows) we are forced to use
108 our wxVsnprintf() implementation.
109 */
110 #if defined(HAVE_UNIX98_PRINTF)
111 #if wxUSE_UNICODE
112 #ifdef HAVE_VSWPRINTF
113 #define wxVsnprintf_ vswprintf
114 #endif
115 #else /* ASCII */
116 #ifdef HAVE_BROKEN_VSNPRINTF_DECL
117 #define wxVsnprintf_ wx_fixed_vsnprintf
118 #else
119 #define wxVsnprintf_ vsnprintf
120 #endif
121 #endif
122 #else /* !HAVE_UNIX98_PRINTF */
123 /*
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.
128 */
129 #if defined _MSC_FULL_VER && _MSC_FULL_VER >= 140050727 && !defined __WXWINCE__
130 #if wxUSE_UNICODE
131 #define wxVsnprintf_ _vswprintf_p
132 #else
133 #define wxVsnprintf_ _vsprintf_p
134 #endif
135 #endif
136 #endif /* HAVE_UNIX98_PRINTF/!HAVE_UNIX98_PRINTF */
137 #else /* !wxUSE_PRINTF_POS_PARAMS */
138 /*
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()
142 code.
143
144 We define function with a trailing underscore here because the real one
145 is a wrapper around it as explained below
146 */
147
148 /* first deal with TCHAR-aware compilers which have _vsntprintf */
149 #ifndef wxVsnprintf_
150 #if defined(__VISUALC__) || \
151 (defined(__BORLANDC__) && __BORLANDC__ >= 0x540)
152 #define wxVsnprintf_ _vsntprintf
153 #endif
154 #endif
155
156 /* if this didn't work, define it separately for Unicode and ANSI builds */
157 #ifndef wxVsnprintf_
158 #if wxUSE_UNICODE
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
165 #endif
166 #else /* ASCII */
167 /*
168 All versions of CodeWarrior supported by wxWidgets apparently
169 have both snprintf() and vsnprintf()
170 */
171 #if defined(HAVE_VSNPRINTF) \
172 || defined(__MWERKS__) || defined(__WATCOMC__)
173 #ifdef HAVE_BROKEN_VSNPRINTF_DECL
174 #define wxVsnprintf_ wx_fixed_vsnprintf
175 #else
176 #define wxVsnprintf_ vsnprintf
177 #endif
178 #endif
179 #endif /* Unicode/ASCII */
180 #endif /* wxVsnprintf_ */
181 #endif /* wxUSE_PRINTF_POS_PARAMS/!wxUSE_PRINTF_POS_PARAMS */
182
183 #ifndef wxVsnprintf_
184 /* no (suitable) vsnprintf(), cook our own */
185 WXDLLIMPEXP_BASE int
186 wxVsnprintf_(wxChar *buf, size_t len, const wxChar *format, va_list argptr);
187
188 #define wxUSE_WXVSNPRINTF 1
189 #else
190 #define wxUSE_WXVSNPRINTF 0
191 #endif
192
193 /*
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
196 case.
197 */
198 #if wxUSE_UNICODE && !defined(wxHAVE_TCHAR_SUPPORT) && !defined(HAVE_WPRINTF)
199 #define wxNEED_WPRINTF
200 #endif
201
202 /*
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.
209
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().
212
213 */
214
215 #if defined(wxNEED_PRINTF_CONVERSION) || defined(wxNEED_WPRINTF)
216 /*
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
219 need
220 */
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 */
227
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 */
230 /*
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.
233 */
234 #if defined(wxNEED_PRINTF_CONVERSION) && defined(wxVsnprintf_)
235 int wxCRT_Vsnprintf( wxChar *str, size_t size, const wxChar *format, va_list ap );
236 #else
237 #define wxCRT_Vsnprintf wxVsnprintf_
238 #endif
239
240
241 // ----------------------------------------------------------------------------
242 // user-friendly wrappers to CRT functions
243 // ----------------------------------------------------------------------------
244
245 #ifdef __WATCOMC__
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
251 #endif
252
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)
256
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
263
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)
268
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) \
275 return implUtf8 args
276 #else
277 #define WX_VARARG_VFOO_IMPL(args, implWchar, implUtf8) \
278 if ( wxLocaleIsUtf8 ) return implUtf8 args; \
279 else return implWchar args
280 #endif
281 #else // wxUSE_UNICODE_WCHAR / ANSI
282 #define WX_VARARG_VFOO_IMPL(args, implWchar, implUtf8) \
283 return implWchar args
284 #endif
285
286 inline int
287 wxVprintf(const wxString& format, va_list ap)
288 {
289 WX_VARARG_VFOO_IMPL((wxFormatString(format), ap),
290 wxCRT_Vprintf, vprintf);
291 }
292
293 inline int
294 wxVfprintf(FILE *f, const wxString& format, va_list ap)
295 {
296 WX_VARARG_VFOO_IMPL((f, wxFormatString(format), ap),
297 wxCRT_Vfprintf, vfprintf);
298 }
299
300 #undef WX_VARARG_VFOO_IMPL
301
302
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*:
305
306 #if !wxUSE_UTF8_LOCALE_ONLY
307 int WXDLLIMPEXP_BASE wxDoSprintfWchar(char *str, const wxChar *format, ...);
308 #endif
309 #if wxUSE_UNICODE_UTF8
310 int WXDLLIMPEXP_BASE wxDoSprintfUtf8(char *str, const char *format, ...);
311 #endif
312 WX_DEFINE_VARARG_FUNC(int, wxSprintf, 2, (char*, const wxFormatString&),
313 wxDoSprintfWchar, wxDoSprintfUtf8)
314
315 int WXDLLIMPEXP_BASE
316 wxVsprintf(char *str, const wxString& format, va_list argptr);
317
318 #if !wxUSE_UTF8_LOCALE_ONLY
319 int WXDLLIMPEXP_BASE wxDoSnprintfWchar(char *str, size_t size, const wxChar *format, ...);
320 #endif
321 #if wxUSE_UNICODE_UTF8
322 int WXDLLIMPEXP_BASE wxDoSnprintfUtf8(char *str, size_t size, const char *format, ...);
323 #endif
324 WX_DEFINE_VARARG_FUNC(int, wxSnprintf, 3, (char*, size_t, const wxFormatString&),
325 wxDoSnprintfWchar, wxDoSnprintfUtf8)
326
327 int WXDLLIMPEXP_BASE
328 wxVsnprintf(char *str, size_t size, const wxString& format, va_list argptr);
329
330 #if wxUSE_UNICODE
331
332 #if !wxUSE_UTF8_LOCALE_ONLY
333 int WXDLLIMPEXP_BASE wxDoSprintfWchar(wchar_t *str, const wxChar *format, ...);
334 #endif
335 #if wxUSE_UNICODE_UTF8
336 int WXDLLIMPEXP_BASE wxDoSprintfUtf8(wchar_t *str, const char *format, ...);
337 #endif
338 WX_DEFINE_VARARG_FUNC(int, wxSprintf, 2, (wchar_t*, const wxFormatString&),
339 wxDoSprintfWchar, wxDoSprintfUtf8)
340
341 int WXDLLIMPEXP_BASE
342 wxVsprintf(wchar_t *str, const wxString& format, va_list argptr);
343
344 #if !wxUSE_UTF8_LOCALE_ONLY
345 int WXDLLIMPEXP_BASE wxDoSnprintfWchar(wchar_t *str, size_t size, const wxChar *format, ...);
346 #endif
347 #if wxUSE_UNICODE_UTF8
348 int WXDLLIMPEXP_BASE wxDoSnprintfUtf8(wchar_t *str, size_t size, const char *format, ...);
349 #endif
350 WX_DEFINE_VARARG_FUNC(int, wxSnprintf, 3, (wchar_t*, size_t, const wxFormatString&),
351 wxDoSnprintfWchar, wxDoSnprintfUtf8)
352
353 int WXDLLIMPEXP_BASE
354 wxVsnprintf(wchar_t *str, size_t size, const wxString& format, va_list argptr);
355
356 #endif // wxUSE_UNICODE
357
358 #ifdef __WATCOMC__
359 // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351
360 //
361 // fortunately, OpenWatcom implements __VA_ARGS__, so we can provide macros
362 // that cast the format argument to wxString:
363 #undef wxPrintf
364 #undef wxFprintf
365 #undef wxSprintf
366 #undef wxSnprintf
367
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__
377
378
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.
384 //
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
388 // only.
389
390 int WXDLLIMPEXP_BASE wxScanf(const char *format, ...);
391 int WXDLLIMPEXP_BASE wxScanf(const wchar_t *format, ...);
392
393 int WXDLLIMPEXP_BASE wxFscanf(FILE *stream, const char *format, ...);
394 int WXDLLIMPEXP_BASE wxFscanf(FILE *stream, const wchar_t *format, ...);
395
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, ...);
404
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);
413
414 #endif /* _WX_WXCRTVARARG_H_ */