/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 |