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