xref: /trunk/main/sal/systools/win32/uwinapi/sntprintf.c (revision 30b588457612edabf32b6255080af21100f58f0b)
1647f063dSAndrew Rist /**************************************************************
2647f063dSAndrew Rist  *
3647f063dSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4647f063dSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5647f063dSAndrew Rist  * distributed with this work for additional information
6647f063dSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7647f063dSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8647f063dSAndrew Rist  * "License"); you may not use this file except in compliance
9647f063dSAndrew Rist  * with the License.  You may obtain a copy of the License at
10647f063dSAndrew Rist  *
11647f063dSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12647f063dSAndrew Rist  *
13647f063dSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14647f063dSAndrew Rist  * software distributed under the License is distributed on an
15647f063dSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16647f063dSAndrew Rist  * KIND, either express or implied.  See the License for the
17647f063dSAndrew Rist  * specific language governing permissions and limitations
18647f063dSAndrew Rist  * under the License.
19647f063dSAndrew Rist  *
20647f063dSAndrew Rist  *************************************************************/
21647f063dSAndrew Rist 
22cdf0e10cSrcweir #define _SNPRINTF_DLLIMPORT __declspec( dllexport )
23cdf0e10cSrcweir 
24cdf0e10cSrcweir #include <stdarg.h>
25cdf0e10cSrcweir #include <stdio.h>
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <tchar.h>
28cdf0e10cSrcweir #include <systools/win32/snprintf.h>
29cdf0e10cSrcweir 
30cdf0e10cSrcweir #if defined(_MSC_VER) && (_MSC_VER >= 1400)
31cdf0e10cSrcweir #pragma warning(disable:4273)       // inconsistent dll linkage
32cdf0e10cSrcweir #endif
33cdf0e10cSrcweir 
34cdf0e10cSrcweir #if (defined(_MSC_VER) && (_MSC_VER < 1300)) || (defined(__MINGW32_VERSION) && ((__MINGW32_MAJOR_VERSION < 3)||((__MINGW32_MAJOR_VERSION == 3)&&(__MINGW32_MINOR_VERSION < 18))))
35cdf0e10cSrcweir 
36cdf0e10cSrcweir /*  The non-debug versions of _vscprintf/_scprintf are just calls
37cdf0e10cSrcweir     to _vsprintf/_sprintf with string buffer pointer set to NULL,
38cdf0e10cSrcweir     requires MSVCRT version 7.0 */
39cdf0e10cSrcweir #ifdef __MINGW32__
_vsctprintf(const TCHAR * format,va_list ap)40cdf0e10cSrcweir static int __cdecl _vsctprintf( const TCHAR *format, va_list ap )
41cdf0e10cSrcweir #else
42cdf0e10cSrcweir static int __cdecl _vsctprintf( const _TXCHAR *format, va_list ap )
43cdf0e10cSrcweir #endif
44cdf0e10cSrcweir {
45cdf0e10cSrcweir     FILE    *fp = _tfopen( _T("NUL"), _T("wb") );
46cdf0e10cSrcweir 
47cdf0e10cSrcweir     if ( fp )
48cdf0e10cSrcweir     {
49cdf0e10cSrcweir         int retval = _vftprintf( fp, format, ap );
50cdf0e10cSrcweir         fclose( fp );
51cdf0e10cSrcweir 
52cdf0e10cSrcweir         return retval;
53cdf0e10cSrcweir     }
54cdf0e10cSrcweir 
55cdf0e10cSrcweir     return -1;
56cdf0e10cSrcweir }
57cdf0e10cSrcweir #endif
58cdf0e10cSrcweir 
59cdf0e10cSrcweir /*  This function retrieves the pointer to the last character of a buffer.
60cdf0e10cSrcweir     That is the pointer to the last character of the buffer that fits
61*30b58845Smseidel     completely into that buffer or the position of the terminating zero.
62cdf0e10cSrcweir 
63cdf0e10cSrcweir     buffer  Pointer to a _TXCHAR buffer to be examined
64cdf0e10cSrcweir     count   size of the buffer to be examined
65cdf0e10cSrcweir 
66cdf0e10cSrcweir     return  The pointer to the last character that fits into the buffer or
67cdf0e10cSrcweir             NULL if count is zero or count is one and the first byte was a
68cdf0e10cSrcweir             leading DBCS character
69cdf0e10cSrcweir */
70cdf0e10cSrcweir 
GetLastBufferChar(_TCHAR * buffer,size_t count)71cdf0e10cSrcweir static _TCHAR *GetLastBufferChar( _TCHAR *buffer, size_t count )
72cdf0e10cSrcweir {
73cdf0e10cSrcweir     _TCHAR  *last = NULL;
74cdf0e10cSrcweir     _TCHAR  *cur = buffer;
75cdf0e10cSrcweir 
76cdf0e10cSrcweir     while ( (size_t)(cur - buffer) < count )
77cdf0e10cSrcweir     {
78cdf0e10cSrcweir         last = cur;
79cdf0e10cSrcweir 
80cdf0e10cSrcweir         if ( !*last )
81cdf0e10cSrcweir             break;
82cdf0e10cSrcweir 
83cdf0e10cSrcweir         cur = _tcsinc(last);
84cdf0e10cSrcweir     }
85cdf0e10cSrcweir 
86cdf0e10cSrcweir     return last;
87cdf0e10cSrcweir }
88cdf0e10cSrcweir 
89cdf0e10cSrcweir /* Implementation of snprintf following the ISO/IEC 9899:1999 (ISO C99) standard */
90cdf0e10cSrcweir 
vsntprintf(_TCHAR * buffer,size_t count,const _TCHAR * format,va_list list)91cdf0e10cSrcweir _SNPRINTF_DLLIMPORT int __cdecl vsntprintf( _TCHAR *buffer, size_t count, const _TCHAR *format, va_list list )
92cdf0e10cSrcweir {
93cdf0e10cSrcweir     int     retval;
94cdf0e10cSrcweir 
95cdf0e10cSrcweir     /*  First of all call the existing non POSIX standard function assuming
96cdf0e10cSrcweir         the buffer size will be large enough */
97cdf0e10cSrcweir 
98cdf0e10cSrcweir     retval = _vsntprintf( buffer, count, format, list );
99cdf0e10cSrcweir 
100cdf0e10cSrcweir     if ( retval < 0 )
101cdf0e10cSrcweir     {
102cdf0e10cSrcweir         /*  If the buffer wasn't large enough ensure that the buffer will be
103cdf0e10cSrcweir             zero terminated */
104cdf0e10cSrcweir 
105cdf0e10cSrcweir         _TCHAR  *last = GetLastBufferChar( buffer, count );
106cdf0e10cSrcweir         if (last )
107cdf0e10cSrcweir             *last = 0;
108cdf0e10cSrcweir 
109cdf0e10cSrcweir         /*  Retrieve the count of characters that would have been written
110cdf0e10cSrcweir             if the buffer were large enough */
111cdf0e10cSrcweir 
112cdf0e10cSrcweir         retval = _vsctprintf( format, list );
113cdf0e10cSrcweir     }
114cdf0e10cSrcweir     else if ( (size_t)retval == count && count )
115cdf0e10cSrcweir     {
116cdf0e10cSrcweir         /*  If the buffer was large enough but not large enough for the trailing
117cdf0e10cSrcweir             zero make the buffer zero terminated */
118cdf0e10cSrcweir 
119cdf0e10cSrcweir         _TCHAR  *last = GetLastBufferChar( buffer, count );
120cdf0e10cSrcweir         if (last )
121cdf0e10cSrcweir             *last = 0;
122cdf0e10cSrcweir     }
123cdf0e10cSrcweir 
124cdf0e10cSrcweir     return retval;
125cdf0e10cSrcweir }
126cdf0e10cSrcweir 
127cdf0e10cSrcweir /* Implementation of snprintf following the ISO/IEC 9899:1999 (ISO C99) standard */
128cdf0e10cSrcweir 
sntprintf(_TCHAR * buffer,size_t count,const _TCHAR * format,...)129cdf0e10cSrcweir _SNPRINTF_DLLIMPORT int __cdecl sntprintf( _TCHAR *buffer, size_t count, const _TCHAR *format, ... )
130cdf0e10cSrcweir {
131cdf0e10cSrcweir     va_list list;
132cdf0e10cSrcweir     int     retval;
133cdf0e10cSrcweir 
134cdf0e10cSrcweir     va_start( list, format );
135cdf0e10cSrcweir     retval = vsntprintf( buffer, count, format, list );
136cdf0e10cSrcweir     va_end( list );
137cdf0e10cSrcweir 
138cdf0e10cSrcweir     return retval;
139cdf0e10cSrcweir }
140