xref: /trunk/main/sal/systools/win32/uwinapi/sntprintf.c (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir #define _SNPRINTF_DLLIMPORT __declspec( dllexport )
2*cdf0e10cSrcweir 
3*cdf0e10cSrcweir #include <stdarg.h>
4*cdf0e10cSrcweir #include <stdio.h>
5*cdf0e10cSrcweir 
6*cdf0e10cSrcweir #include <tchar.h>
7*cdf0e10cSrcweir #include <systools/win32/snprintf.h>
8*cdf0e10cSrcweir 
9*cdf0e10cSrcweir #if defined(_MSC_VER) && (_MSC_VER >= 1400)
10*cdf0e10cSrcweir #pragma warning(disable:4273)       // inconsistent dll linkage
11*cdf0e10cSrcweir #endif
12*cdf0e10cSrcweir 
13*cdf0e10cSrcweir #if (defined(_MSC_VER) && (_MSC_VER < 1300)) || (defined(__MINGW32_VERSION) && ((__MINGW32_MAJOR_VERSION < 3)||((__MINGW32_MAJOR_VERSION == 3)&&(__MINGW32_MINOR_VERSION < 18))))
14*cdf0e10cSrcweir 
15*cdf0e10cSrcweir /*  The non-debug versions of _vscprintf/_scprintf are just calls
16*cdf0e10cSrcweir     to _vsprintf/_sprintf with string buffer pointer set to NULL,
17*cdf0e10cSrcweir     requires MSVCRT version 7.0 */
18*cdf0e10cSrcweir #ifdef __MINGW32__
19*cdf0e10cSrcweir static int __cdecl _vsctprintf( const TCHAR *format, va_list ap )
20*cdf0e10cSrcweir #else
21*cdf0e10cSrcweir static int __cdecl _vsctprintf( const _TXCHAR *format, va_list ap )
22*cdf0e10cSrcweir #endif
23*cdf0e10cSrcweir {
24*cdf0e10cSrcweir     FILE    *fp = _tfopen( _T("NUL"), _T("wb") );
25*cdf0e10cSrcweir 
26*cdf0e10cSrcweir     if ( fp )
27*cdf0e10cSrcweir     {
28*cdf0e10cSrcweir         int retval = _vftprintf( fp, format, ap );
29*cdf0e10cSrcweir         fclose( fp );
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir         return retval;
32*cdf0e10cSrcweir     }
33*cdf0e10cSrcweir 
34*cdf0e10cSrcweir     return -1;
35*cdf0e10cSrcweir }
36*cdf0e10cSrcweir #endif
37*cdf0e10cSrcweir 
38*cdf0e10cSrcweir /*  This function retrieves the pointer to the last character of a buffer.
39*cdf0e10cSrcweir     That is the pointer to the last character of the buffer that fits
40*cdf0e10cSrcweir     completly into that buffer or the position of the terminating zero.
41*cdf0e10cSrcweir 
42*cdf0e10cSrcweir     buffer  Pointer to a _TXCHAR buffer to be examined
43*cdf0e10cSrcweir     count   size of the buffer to be examined
44*cdf0e10cSrcweir 
45*cdf0e10cSrcweir     return  The pointer to the last character that fits into the buffer or
46*cdf0e10cSrcweir             NULL if count is zero or count is one and the first byte was a
47*cdf0e10cSrcweir             leading DBCS character
48*cdf0e10cSrcweir */
49*cdf0e10cSrcweir 
50*cdf0e10cSrcweir static _TCHAR *GetLastBufferChar( _TCHAR *buffer, size_t count )
51*cdf0e10cSrcweir {
52*cdf0e10cSrcweir     _TCHAR  *last = NULL;
53*cdf0e10cSrcweir     _TCHAR  *cur = buffer;
54*cdf0e10cSrcweir 
55*cdf0e10cSrcweir     while ( (size_t)(cur - buffer) < count )
56*cdf0e10cSrcweir     {
57*cdf0e10cSrcweir         last = cur;
58*cdf0e10cSrcweir 
59*cdf0e10cSrcweir         if ( !*last )
60*cdf0e10cSrcweir             break;
61*cdf0e10cSrcweir 
62*cdf0e10cSrcweir         cur = _tcsinc(last);
63*cdf0e10cSrcweir     }
64*cdf0e10cSrcweir 
65*cdf0e10cSrcweir     return last;
66*cdf0e10cSrcweir }
67*cdf0e10cSrcweir 
68*cdf0e10cSrcweir /* Implementation of snprintf following the ISO/IEC 9899:1999 (ISO C99) standard */
69*cdf0e10cSrcweir 
70*cdf0e10cSrcweir _SNPRINTF_DLLIMPORT int __cdecl vsntprintf( _TCHAR *buffer, size_t count, const _TCHAR *format, va_list list )
71*cdf0e10cSrcweir {
72*cdf0e10cSrcweir     int     retval;
73*cdf0e10cSrcweir 
74*cdf0e10cSrcweir     /*  First of all call the existing non POSIX standard function assuming
75*cdf0e10cSrcweir         the buffer size will be large enough */
76*cdf0e10cSrcweir 
77*cdf0e10cSrcweir     retval = _vsntprintf( buffer, count, format, list );
78*cdf0e10cSrcweir 
79*cdf0e10cSrcweir     if ( retval < 0 )
80*cdf0e10cSrcweir     {
81*cdf0e10cSrcweir         /*  If the buffer wasn't large enough ensure that the buffer will be
82*cdf0e10cSrcweir             zero terminated */
83*cdf0e10cSrcweir 
84*cdf0e10cSrcweir         _TCHAR  *last = GetLastBufferChar( buffer, count );
85*cdf0e10cSrcweir         if (last )
86*cdf0e10cSrcweir             *last = 0;
87*cdf0e10cSrcweir 
88*cdf0e10cSrcweir         /*  Retrieve the count of characters that would have been written
89*cdf0e10cSrcweir             if the buffer were large enough */
90*cdf0e10cSrcweir 
91*cdf0e10cSrcweir         retval = _vsctprintf( format, list );
92*cdf0e10cSrcweir     }
93*cdf0e10cSrcweir     else if ( (size_t)retval == count && count )
94*cdf0e10cSrcweir     {
95*cdf0e10cSrcweir         /*  If the buffer was large enough but not large enough for the trailing
96*cdf0e10cSrcweir             zero make the buffer zero terminated */
97*cdf0e10cSrcweir 
98*cdf0e10cSrcweir         _TCHAR  *last = GetLastBufferChar( buffer, count );
99*cdf0e10cSrcweir         if (last )
100*cdf0e10cSrcweir             *last = 0;
101*cdf0e10cSrcweir     }
102*cdf0e10cSrcweir 
103*cdf0e10cSrcweir     return retval;
104*cdf0e10cSrcweir }
105*cdf0e10cSrcweir 
106*cdf0e10cSrcweir /* Implementation of snprintf following the ISO/IEC 9899:1999 (ISO C99) standard */
107*cdf0e10cSrcweir 
108*cdf0e10cSrcweir _SNPRINTF_DLLIMPORT int __cdecl sntprintf( _TCHAR *buffer, size_t count, const _TCHAR *format, ... )
109*cdf0e10cSrcweir {
110*cdf0e10cSrcweir     va_list list;
111*cdf0e10cSrcweir     int     retval;
112*cdf0e10cSrcweir 
113*cdf0e10cSrcweir     va_start( list, format );
114*cdf0e10cSrcweir     retval = vsntprintf( buffer, count, format, list );
115*cdf0e10cSrcweir     va_end( list );
116*cdf0e10cSrcweir 
117*cdf0e10cSrcweir     return retval;
118*cdf0e10cSrcweir }
119