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