summaryrefslogtreecommitdiff
path: root/sal/systools/win32/uwinapi/sntprintf.c
diff options
context:
space:
mode:
Diffstat (limited to 'sal/systools/win32/uwinapi/sntprintf.c')
-rw-r--r--sal/systools/win32/uwinapi/sntprintf.c118
1 files changed, 118 insertions, 0 deletions
diff --git a/sal/systools/win32/uwinapi/sntprintf.c b/sal/systools/win32/uwinapi/sntprintf.c
new file mode 100644
index 000000000000..69d47821311c
--- /dev/null
+++ b/sal/systools/win32/uwinapi/sntprintf.c
@@ -0,0 +1,118 @@
+#define _SNPRINTF_DLLIMPORT __declspec( dllexport )
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include <tchar.h>
+#include <systools/win32/snprintf.h>
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+#pragma warning(disable:4273) // inconsistent dll linkage
+#endif
+
+#if (defined(_MSC_VER) && (_MSC_VER < 1300)) || (defined(__MINGW32_VERSION) && ((__MINGW32_MAJOR_VERSION < 3)||((__MINGW32_MAJOR_VERSION == 3)&&(__MINGW32_MINOR_VERSION < 18))))
+
+/* The non-debug versions of _vscprintf/_scprintf are just calls
+ to _vsprintf/_sprintf with string buffer pointer set to NULL,
+ requires MSVCRT version 7.0 */
+#ifdef __MINGW32__
+static int __cdecl _vsctprintf( const TCHAR *format, va_list ap )
+#else
+static int __cdecl _vsctprintf( const _TXCHAR *format, va_list ap )
+#endif
+{
+ FILE *fp = _tfopen( _T("NUL"), _T("wb") );
+
+ if ( fp )
+ {
+ int retval = _vftprintf( fp, format, ap );
+ fclose( fp );
+
+ return retval;
+ }
+
+ return -1;
+}
+#endif
+
+/* This function retrieves the pointer to the last character of a buffer.
+ That is the pointer to the last character of the buffer that fits
+ completly into that buffer or the position of the terminating zero.
+
+ buffer Pointer to a _TXCHAR buffer to be examined
+ count size of the buffer to be examined
+
+ return The pointer to the last character that fits into the buffer or
+ NULL if count is zero or count is one and the first byte was a
+ leading DBCS character
+*/
+
+static _TCHAR *GetLastBufferChar( _TCHAR *buffer, size_t count )
+{
+ _TCHAR *last = NULL;
+ _TCHAR *cur = buffer;
+
+ while ( (size_t)(cur - buffer) < count )
+ {
+ last = cur;
+
+ if ( !*last )
+ break;
+
+ cur = _tcsinc(last);
+ }
+
+ return last;
+}
+
+/* Implementation of snprintf following the ISO/IEC 9899:1999 (ISO C99) standard */
+
+_SNPRINTF_DLLIMPORT int __cdecl vsntprintf( _TCHAR *buffer, size_t count, const _TCHAR *format, va_list list )
+{
+ int retval;
+
+ /* First of all call the existing non POSIX standard function assuming
+ the buffer size will be large enough */
+
+ retval = _vsntprintf( buffer, count, format, list );
+
+ if ( retval < 0 )
+ {
+ /* If the buffer wasn't large enough ensure that the buffer will be
+ zero terminated */
+
+ _TCHAR *last = GetLastBufferChar( buffer, count );
+ if (last )
+ *last = 0;
+
+ /* Retrieve the count of characters that would have been written
+ if the buffer were large enough */
+
+ retval = _vsctprintf( format, list );
+ }
+ else if ( (size_t)retval == count && count )
+ {
+ /* If the buffer was large enough but not large enough for the trailing
+ zero make the buffer zero terminated */
+
+ _TCHAR *last = GetLastBufferChar( buffer, count );
+ if (last )
+ *last = 0;
+ }
+
+ return retval;
+}
+
+/* Implementation of snprintf following the ISO/IEC 9899:1999 (ISO C99) standard */
+
+_SNPRINTF_DLLIMPORT int __cdecl sntprintf( _TCHAR *buffer, size_t count, const _TCHAR *format, ... )
+{
+ va_list list;
+ int retval;
+
+ va_start( list, format );
+ retval = vsntprintf( buffer, count, format, list );
+ va_end( list );
+
+ return retval;
+}