Coverage Report

Created: 2026-11-12 07:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dcmtk/oflog/libsrc/snprintf.cc
Line
Count
Source
1
//  Copyright (C) 2010, Vaclav Haisman. All rights reserved.
2
//  
3
//  Redistribution and use in source and binary forms, with or without modifica-
4
//  tion, are permitted provided that the following conditions are met:
5
//  
6
//  1. Redistributions of  source code must  retain the above copyright  notice,
7
//     this list of conditions and the following disclaimer.
8
//  
9
//  2. Redistributions in binary form must reproduce the above copyright notice,
10
//     this list of conditions and the following disclaimer in the documentation
11
//     and/or other materials provided with the distribution.
12
//  
13
//  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
14
//  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
15
//  FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
16
//  APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
17
//  INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
18
//  DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
19
//  OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
20
//  ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
21
//  (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
22
//  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
24
#include "dcmtk/oflog/helpers/snprintf.h"
25
#include "dcmtk/oflog/helpers/loglog.h"
26
#include "dcmtk/oflog/internal/internal.h"
27
#include <cstdarg>
28
#include <cstdio>
29
#if defined (DCMTK_OFLOG_UNICODE)
30
#include <cwchar>
31
#endif
32
#if defined (DCMTK_LOG4CPLUS_HAVE_STDARG_H)
33
#  include <stdarg.h>
34
#endif
35
#if defined (DCMTK_LOG4CPLUS_HAVE_WCHAR_H)
36
#  include <wchar.h>
37
#endif
38
#if defined (DCMTK_LOG4CPLUS_HAVE_STDIO_H)
39
#  include <stdio.h>
40
#endif
41
42
43
namespace dcmtk {
44
namespace log4cplus { namespace helpers {
45
46
47
size_t const START_BUF_SIZE = 512;
48
49
#if defined (DCMTK_LOG4CPLUS_USE_POOR_MANS_SNPRINTF)
50
51
#if defined (_WIN32)
52
char const NULL_FILE[] = "NUL";
53
#else
54
char const NULL_FILE[] = "/dev/null";
55
#endif
56
57
#endif
58
59
namespace
60
{
61
62
63
#if defined (DCMTK_LOG4CPLUS_USE_POOR_MANS_SNPRINTF)
64
65
static inline int vftprintf (STD_NAMESPACE FILE * file, tchar const * fmt,
66
    va_list args) DCMTK_LOG4CPLUS_FORMAT_ATTRIBUTE (__printf__, 2, 0);
67
68
static inline
69
int
70
vftprintf (STD_NAMESPACE FILE * file, tchar const * fmt, va_list args)
71
{
72
#if defined (DCMTK_OFLOG_UNICODE)
73
#  if defined (DCMTK_LOG4CPLUS_HAVE_VFWPRINTF_S)
74
    return vfwprintf_s (file, fmt, args);
75
#  else
76
    return STD_NAMESPACE vfwprintf (file, fmt, args);
77
#  endif
78
#else
79
#  if defined (DCMTK_LOG4CPLUS_HAVE_VFPRINTF_S)
80
    return vfprintf_s (file, fmt, args);
81
#  else
82
    return STD_NAMESPACE vfprintf (file, fmt, args);
83
#  endif
84
#endif
85
}
86
87
88
static inline int vstprintf (tchar * dest, size_t dest_size,
89
    tchar const * fmt, va_list args)
90
    DCMTK_LOG4CPLUS_FORMAT_ATTRIBUTE (__printf__, 3, 0);
91
92
static inline
93
int
94
vstprintf (tchar * dest, size_t dest_size, tchar const * fmt,
95
    va_list args)
96
{
97
    int ret;
98
#if defined (DCMTK_OFLOG_UNICODE)
99
#  if defined (DCMTK_LOG4CPLUS_HAVE_VSWPRINTF_S)
100
    ret = vswprintf_s (dest, dest_size, fmt, args);
101
#  else
102
    ret = STD_NAMESPACE vswprintf (dest, dest_size, fmt, args);
103
#  endif
104
#else
105
#  if defined (DCMTK_LOG4CPLUS_HAVE_VSPRINTF_S)
106
    ret = vsprintf_s (dest, dest_size, fmt, args);
107
#  else
108
    ret = STD_NAMESPACE vsprintf (dest, fmt, args);
109
#  endif
110
#endif
111
112
    if (ret >= 0)
113
        assert (OFstatic_cast(size_t, ret) <= dest_size);
114
    
115
    return ret;
116
}
117
118
#else /* ?defined (DCMTK_LOG4CPLUS_USE_POOR_MANS_SNPRINTF) */
119
120
static inline int vsntprintf (tchar * dest, size_t dest_size,
121
    tchar const * fmt, va_list args)
122
    DCMTK_LOG4CPLUS_FORMAT_ATTRIBUTE (__printf__, 3, 0);
123
124
static inline
125
int
126
vsntprintf (tchar * dest, size_t dest_size, tchar const * fmt,
127
    va_list args)
128
0
{
129
0
    int ret;
130
131
#if defined (DCMTK_OFLOG_UNICODE)
132
#  if defined (DCMTK_LOG4CPLUS_HAVE__VSNWPRINTF_S) && defined (_TRUNCATE)
133
    ret = _vsnwprintf_s (dest, dest_size, _TRUNCATE, fmt, args);
134
#  else
135
    ret = STD_NAMESPACE vswprintf (dest, dest_size, fmt, args);
136
#  endif
137
#else
138
#  if defined (DCMTK_LOG4CPLUS_HAVE_VSNPRINTF_S) && defined (_TRUNCATE)
139
    ret = vsnprintf_s (dest, dest_size, _TRUNCATE, fmt, args);
140
#  elif defined (DCMTK_LOG4CPLUS_HAVE__VSNPRINTF_S) && defined (_TRUNCATE)
141
    ret = _vsnprintf_s (dest, dest_size, _TRUNCATE, fmt, args);
142
#  elif defined (DCMTK_LOG4CPLUS_HAVE_VSNPRINTF)
143
    ret = vsnprintf (dest, dest_size, fmt, args);
144
#  elif defined (DCMTK_LOG4CPLUS_HAVE__VSNPRINTF)
145
    ret = _vsnprintf (dest, dest_size, fmt, args);
146
#  else
147
#    error "None of vsnprintf_s, _vsnprintf_s, vsnprintf or _vsnprintf is available."
148
#  endif
149
0
#endif
150
    
151
0
    return ret;
152
0
}
153
#endif
154
155
156
}
157
158
159
snprintf_buf::snprintf_buf ()
160
6
    : buf (START_BUF_SIZE)
161
6
{ }
162
163
164
tchar const *
165
snprintf_buf::print (tchar const * fmt, ...)
166
0
{
167
0
    assert (fmt);
168
169
0
    va_list args;
170
0
    va_start (args, fmt);
171
0
    tchar const * ret = print_va_list (fmt, args);
172
0
    va_end (args);
173
0
    return ret;
174
0
}
175
176
177
tchar const *
178
snprintf_buf::print_va_list(tchar const * fmt, va_list args)
179
0
{
180
0
    int printed;
181
0
    size_t const fmt_len = STD_NAMESPACE char_traits<tchar>::length (fmt);
182
0
    size_t buf_size = buf.size ();
183
0
    size_t const output_estimate = fmt_len + fmt_len / 2 + 1;
184
0
    if (output_estimate > buf_size)
185
0
        buf.resize (output_estimate);
186
187
#if defined (DCMTK_LOG4CPLUS_USE_POOR_MANS_SNPRINTF)
188
    STD_NAMESPACE FILE * & fnull = internal::get_ptd ()->fnull;
189
    if (! fnull)
190
    {
191
        fnull = STD_NAMESPACE fopen (NULL_FILE, "wb");
192
        if (! fnull)
193
        {
194
            LogLog::getLogLog ()->error (
195
                DCMTK_LOG4CPLUS_TEXT ("Could not open NULL_FILE."));
196
            buf.clear ();
197
            buf.push_back (0);
198
            return &buf[0];
199
        }
200
    }
201
   
202
    printed = vftprintf (fnull, fmt, args);
203
    if (printed == -1)
204
    {
205
        LogLog::getLogLog ()->error (
206
            DCMTK_LOG4CPLUS_TEXT ("Error printing into NULL_FILE."));
207
        buf.clear ();
208
        buf.push_back (0);
209
        return &buf[0];
210
    }
211
212
    buf.resize (printed + 1);
213
    int sprinted = vstprintf (&buf[0], buf.size (), fmt, args);
214
    if (sprinted == -1)
215
    {
216
        LogLog::getLogLog ()->error (
217
            DCMTK_LOG4CPLUS_TEXT ("Error printing into string."));
218
        buf.clear ();
219
        buf.push_back (0);
220
        return &buf[0];
221
    }
222
    assert (printed == sprinted);
223
    
224
    buf[sprinted] = 0;
225
226
#else
227
0
    do
228
0
    {
229
0
        printed = vsntprintf (&buf[0], buf_size - 1, fmt, args);
230
0
        if (printed == -1)
231
0
        {
232
0
            buf_size *= 2;
233
0
            buf.resize (buf_size);
234
0
        }
235
0
        else
236
0
            buf[printed] = 0;
237
0
    }
238
0
    while (printed == -1);
239
240
0
#endif
241
242
0
    return &buf[0];
243
0
}
244
245
246
} } // namespace log4cplus { namespace helpers
247
} // end namespace dcmtk