Coverage Report

Created: 2026-05-16 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dcmtk/oflog/libsrc/property.cc
Line
Count
Source
1
// Module:  Log4CPLUS
2
// File:    property.cxx
3
// Created: 2/2002
4
// Author:  Tad E. Smith
5
//
6
//
7
// Copyright 2002-2010 Tad E. Smith
8
//
9
// Licensed under the Apache License, Version 2.0 (the "License");
10
// you may not use this file except in compliance with the License.
11
// You may obtain a copy of the License at
12
//
13
//     http://www.apache.org/licenses/LICENSE-2.0
14
//
15
// Unless required by applicable law or agreed to in writing, software
16
// distributed under the License is distributed on an "AS IS" BASIS,
17
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
// See the License for the specific language governing permissions and
19
// limitations under the License.
20
21
#include "dcmtk/oflog/config.h"
22
23
#include <cstring>
24
#if defined (DCMTK_OFLOG_UNICODE)
25
#  include <cwctype>
26
#else
27
#  include <cctype>
28
#endif
29
#if defined (DCMTK_LOG4CPLUS_HAVE_CODECVT_UTF8_FACET) \
30
    || defined (DCMTK_LOG4CPLUS_HAVE_CODECVT_UTF16_FACET) \
31
    || defined (DCMTK_LOG4CPLUS_HAVE_CODECVT_UTF32_FACET)
32
#  include <codecvt>
33
#endif
34
#include <locale>
35
#include <fstream>
36
#include <sstream>
37
#include "dcmtk/ofstd/ofstd.h"
38
#include "dcmtk/oflog/streams.h"
39
#include "dcmtk/oflog/fstreams.h"
40
#include "dcmtk/oflog/helpers/strhelp.h"
41
#include "dcmtk/oflog/helpers/property.h"
42
#include "dcmtk/oflog/internal/internal.h"
43
#include "dcmtk/oflog/internal/env.h"
44
#include "dcmtk/oflog/helpers/loglog.h"
45
46
47
namespace dcmtk {
48
namespace log4cplus { namespace helpers {
49
50
51
const tchar Properties::PROPERTIES_COMMENT_CHAR = DCMTK_LOG4CPLUS_TEXT('#');
52
53
54
namespace
55
{
56
57
58
static
59
int
60
is_space (tchar ch)
61
0
{
62
#if defined (DCMTK_OFLOG_UNICODE)
63
    return STD_NAMESPACE iswspace (ch);
64
#else
65
0
    return OFStandard::isspace (ch);
66
0
#endif
67
0
}
68
69
70
static
71
void
72
trim_leading_ws (tstring & str)
73
0
{
74
0
    tstring::iterator it = str.begin ();
75
0
    for (; it != str.end (); ++it)
76
0
    {
77
0
        if (! is_space (*it))
78
0
            break;
79
0
    }
80
0
    str.erase (0, it - str.begin ());
81
0
}
82
83
84
static
85
void
86
trim_trailing_ws (tstring & str)
87
0
{
88
0
    size_t i;
89
0
    for (i = str.length(); i > 0; i--)
90
0
    {
91
0
        if (! is_space (str[i-1]))
92
0
            break;
93
0
    }
94
0
    str.erase (i, str.length() - i);
95
0
}
96
97
98
static
99
void
100
trim_ws (tstring & str)
101
0
{
102
0
    trim_trailing_ws (str);
103
0
    trim_leading_ws (str);
104
0
}
105
106
107
} // namespace
108
109
110
111
///////////////////////////////////////////////////////////////////////////////
112
// Properties ctors and dtor
113
///////////////////////////////////////////////////////////////////////////////
114
115
0
Properties::Properties() : data()
116
0
{
117
0
}
118
119
120
121
0
Properties::Properties(tistream& input) : data()
122
0
{
123
0
    init(input);
124
0
}
125
126
127
128
0
Properties::Properties(const tstring& inputFile, unsigned flags) : data()
129
0
{
130
0
    if (inputFile.empty ())
131
0
        return;
132
133
0
    tifstream file;
134
135
0
    switch (flags & fEncodingMask)
136
0
    {
137
#if defined (DCMTK_LOG4CPLUS_HAVE_CODECVT_UTF8_FACET) && defined (DCMTK_OFLOG_UNICODE)
138
    case fUTF8:
139
        file.imbue (
140
            STD_NAMESPACE locale (file.getloc (),
141
                new STD_NAMESPACE codecvt_utf8<tchar, 0x10FFFF,
142
                    OFstatic_cast(STD_NAMESPACE codecvt_mode, STD_NAMESPACE consume_header | STD_NAMESPACE little_endian)>));
143
        break;
144
#endif
145
146
#if defined (DCMTK_LOG4CPLUS_HAVE_CODECVT_UTF16_FACET) && defined (DCMTK_OFLOG_UNICODE)
147
    case fUTF16:
148
        file.imbue (
149
            STD_NAMESPACE locale (file.getloc (),
150
                new STD_NAMESPACE codecvt_utf16<tchar, 0x10FFFF,
151
                    OFstatic_cast(STD_NAMESPACE codecvt_mode, STD_NAMESPACE consume_header | STD_NAMESPACE little_endian)>));
152
        break;
153
154
#elif defined (DCMTK_OFLOG_UNICODE) && defined (WIN32)
155
    case fUTF16:
156
        file.imbue (
157
            STD_NAMESPACE locale (file.getloc (),
158
                new STD_NAMESPACE codecvt<wchar_t, wchar_t, STD_NAMESPACE mbstate_t>));
159
    break;
160
161
#endif
162
163
#if defined (DCMTK_LOG4CPLUS_HAVE_CODECVT_UTF32_FACET) && defined (DCMTK_OFLOG_UNICODE)
164
    case fUTF32:
165
        file.imbue (
166
            STD_NAMESPACE locale (file.getloc (),
167
                new STD_NAMESPACE codecvt_utf32<tchar, 0x10FFFF,
168
                    OFstatic_cast(STD_NAMESPACE codecvt_mode, STD_NAMESPACE consume_header | STD_NAMESPACE little_endian)>));
169
        break;
170
#endif
171
172
0
    case fUnspecEncoding:;
173
0
    default:
174
        // Do nothing.
175
0
        ;
176
0
    }
177
178
0
    file.open(DCMTK_LOG4CPLUS_FSTREAM_PREFERED_FILE_NAME(inputFile).c_str(),
179
0
        STD_NAMESPACE ios::binary);
180
0
    if (! file.good ())
181
0
        helpers::getLogLog ().error (DCMTK_LOG4CPLUS_TEXT ("could not open file ")
182
0
            + inputFile);
183
184
0
    init(file);
185
0
}
186
187
188
189
void
190
Properties::init(tistream& input)
191
0
{
192
0
    if (! input)
193
0
        return;
194
195
0
    STD_NAMESPACE string buffer_;
196
0
    while (STD_NAMESPACE getline (input, buffer_))
197
0
    {
198
0
        tstring buffer(buffer_.c_str(), buffer_.length());
199
0
        trim_leading_ws (buffer);
200
201
0
        tstring::size_type const buffLen = buffer.size ();
202
0
        if (buffLen == 0 || buffer[0] == PROPERTIES_COMMENT_CHAR)
203
0
            continue;
204
205
        // Check if we have a trailing \r because we are
206
        // reading a properties file produced on Windows.
207
0
        if (buffer[buffLen-1] == DCMTK_LOG4CPLUS_TEXT('\r'))
208
            // Remove trailing 'Windows' \r.
209
0
            buffer.resize (buffLen - 1);
210
211
0
        tstring::size_type const idx = buffer.find('=');
212
0
        if (idx != OFString_npos)
213
0
        {
214
0
            tstring key = buffer.substr(0, idx);
215
0
            tstring value = buffer.substr(idx + 1);
216
0
            trim_trailing_ws (key);
217
0
            trim_ws (value);
218
0
            setProperty(key, value);
219
0
        }
220
0
    }
221
0
}
222
223
224
225
Properties::~Properties()
226
0
{
227
0
}
228
229
230
231
///////////////////////////////////////////////////////////////////////////////
232
// helpers::Properties public methods
233
///////////////////////////////////////////////////////////////////////////////
234
235
236
bool
237
Properties::exists(const log4cplus::tstring& key) const
238
0
{
239
0
    return data.find(key) != data.end();
240
0
}
241
242
243
bool
244
Properties::exists(tchar const * key) const
245
0
{
246
0
    return data.find(key) != data.end();
247
0
}
248
249
250
tstring const &
251
Properties::getProperty(const tstring& key) const
252
0
{
253
0
    return get_property_worker (key);
254
0
}
255
256
257
log4cplus::tstring const &
258
Properties::getProperty(tchar const * key) const
259
0
{
260
0
    return get_property_worker (key);
261
0
}
262
263
264
tstring
265
Properties::getProperty(const tstring& key, const tstring& defaultVal) const
266
0
{
267
0
    StringMap::const_iterator it (data.find (key));
268
0
    if (it == data.end ())
269
0
        return defaultVal;
270
0
    else
271
0
        return it->second;
272
0
}
273
274
275
OFVector<tstring>
276
Properties::propertyNames() const
277
0
{
278
0
    OFVector<tstring> tmp;
279
0
    for (StringMap::const_iterator it=data.begin(); it!=data.end(); ++it)
280
0
        tmp.push_back(it->first);
281
282
0
    return tmp;
283
0
}
284
285
286
287
void
288
Properties::setProperty(const log4cplus::tstring& key,
289
    const log4cplus::tstring& value)
290
0
{
291
0
    data[key] = value;
292
0
}
293
294
295
bool
296
Properties::removeProperty(const log4cplus::tstring& key)
297
0
{
298
0
    return data.erase(key) > 0;
299
0
}
300
301
302
Properties
303
Properties::getPropertySubset(const log4cplus::tstring& prefix) const
304
0
{
305
0
    Properties ret;
306
0
    size_t const prefix_len = prefix.size ();
307
0
    OFVector<tstring> keys = propertyNames();
308
0
    for (OFVector<tstring>::iterator it=keys.begin(); it!=keys.end(); ++it)
309
0
    {
310
0
        int result = it->compare (0, prefix_len, prefix);
311
0
        if (result == 0)
312
0
            ret.setProperty (it->substr (prefix_len), getProperty(*it));
313
0
    }
314
315
0
    return ret;
316
0
}
317
318
319
bool
320
Properties::getInt (int & val, log4cplus::tstring const & key) const
321
0
{
322
0
    return get_type_val_worker (val, key);
323
0
}
324
325
326
bool
327
Properties::getUInt (unsigned & val, log4cplus::tstring const & key) const
328
0
{
329
0
    return get_type_val_worker (val, key);
330
0
}
331
332
333
bool
334
Properties::getLong (long & val, log4cplus::tstring const & key) const
335
0
{
336
0
    return get_type_val_worker (val, key);
337
0
}
338
339
340
bool
341
Properties::getULong (unsigned long & val, log4cplus::tstring const & key) const
342
0
{
343
0
    return get_type_val_worker (val, key);
344
0
}
345
346
347
bool
348
Properties::getBool (bool & val, log4cplus::tstring const & key) const
349
0
{
350
0
    if (! exists (key))
351
0
        return false;
352
353
0
    log4cplus::tstring const & prop_val = getProperty (key);
354
0
    return internal::parse_bool (val, prop_val);
355
0
}
356
357
358
template <typename StringType>
359
log4cplus::tstring const &
360
Properties::get_property_worker (StringType const & key) const
361
0
{
362
0
    StringMap::const_iterator it (data.find (key));
363
0
    if (it == data.end ())
364
0
        return log4cplus::internal::empty_str;
365
0
    else
366
0
        return it->second;
367
0
}
Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const& dcmtk::log4cplus::helpers::Properties::get_property_worker<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) const
Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const& dcmtk::log4cplus::helpers::Properties::get_property_worker<char const*>(char const* const&) const
368
369
370
template <typename ValType>
371
bool
372
Properties::get_type_val_worker (ValType & val, log4cplus::tstring const & key)
373
    const
374
0
{
375
0
    if (! exists (key))
376
0
        return false;
377
378
0
    log4cplus::tstring const & prop_val = getProperty (key);
379
0
    log4cplus::tistringstream iss (STD_NAMESPACE string(prop_val.c_str(), prop_val.length()));
380
0
    ValType tmp_val;
381
0
    tchar ch;
382
383
0
    iss >> tmp_val;
384
0
    if (! iss)
385
0
        return false;
386
0
    iss >> ch;
387
0
    if (iss)
388
0
        return false;
389
390
0
    val = tmp_val;
391
0
    return true;
392
0
}
Unexecuted instantiation: bool dcmtk::log4cplus::helpers::Properties::get_type_val_worker<int>(int&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) const
Unexecuted instantiation: bool dcmtk::log4cplus::helpers::Properties::get_type_val_worker<unsigned int>(unsigned int&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) const
Unexecuted instantiation: bool dcmtk::log4cplus::helpers::Properties::get_type_val_worker<long>(long&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) const
Unexecuted instantiation: bool dcmtk::log4cplus::helpers::Properties::get_type_val_worker<unsigned long>(unsigned long&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) const
393
394
395
} } // namespace log4cplus { namespace helpers {
396
} // end namespace dcmtk