DCL 4.0
Loading...
Searching...
No Matches
IniFile.cpp
Go to the documentation of this file.
1#include <dcl/Config.h>
2
3#if __DCL_WINDOWS
4#include <windows.h> // for dcl/Thread.h
5#endif
6
7#include <stdlib.h> // for ListT.h malloc, free, realloc
8#include <string.h> // for ListT.h memset, memmove
9
10#include <dcl/Object.h>
11
12#if __DCL_HAVE_ALLOC_DEBUG
13#undef __DCL_ALLOC_LEVEL
14#define __DCL_ALLOC_LEVEL __DCL_ALLOC_INTERNAL
15#endif
16
17#include <dcl/Numeric.h>
18#include <dcl/File.h>
19#include <dcl/FileInputStream.h>
22#include <dcl/BufferedReader.h>
24#include <dcl/ListT.h>
25#include <dcl/IniFile.h>
26
27#if __DCL_HAVE_THIS_FILE__
28#undef __THIS_FILE__
29static const char_t __THIS_FILE__[] = __T("dcl/IniFile.cpp");
30#endif
31
32__DCL_BEGIN_NAMESPACE
33
34
41
42struct IniLine
43{
45 String m_strName;
46 String m_strValue;
47
49 {
50 }
51
52 IniLine(IniLineType type, const String& str)
53 {
54 m_type = type;
55 m_strName = str;
56 }
57 IniLine(const String& strKey, const String& strValue)
58 {
60 m_strName = strKey;
61 m_strValue = strValue;
62 }
63 String toString() const
64 {
65 String str;
66 switch (m_type)
67 {
68 case ltSectionName :
69 str = L"[" + m_strName + L"]";
70 break;
71 case ltEntry :
72 str = m_strName + L"=" + m_strValue;
73 break;
74 default :
75 str = m_strName;
76 }
77 return str;
78 }
79};
80
82
84
85String IniFile::toString() const
86{
87 return m_strName;
88}
89
90#if __DCL_DEBUG
91void IniFile::dump(Writer& out) const
92{
93 Object::dump(out);
94 out << L"fileName: " << m_strName << L"\n";
95 if (m_handle)
96 {
97 const IniLineList* pLines = (const IniLineList*)m_handle;
98 for(IniLineList::ConstIterator it = pLines->begin();
99 it != pLines->end(); it++)
100 {
101 out << (*it).toString() << L"\n";
102 }
103 }
104}
105
106#endif
107
109{
110 m_handle = NULL;
111 m_bModified = false;
112}
113
114IniFile::IniFile(const String& strFileName)
116{
117 m_handle = NULL;
118 m_bModified = false;
119
120 __DCL_ASSERT(!strFileName.isEmpty());
121
122 IniLineList* pLines = new IniLineList;
123 m_handle = pLines;
124
127 new FileInputStream(strFileName)
128 )
129 );
130 String s;
131 while(in.readLine(s))
132 {
133 s = s.trim();
134
135 if (s.isEmpty())
136 pLines->addTail(IniLine(ltComment, String()));
137 else if (s[(size_t)0] == L';' || s[(size_t)0] == L'#')
138 {
139 pLines->addTail(IniLine(ltComment, s));
140 }
141 else if (s[(size_t)0] == L'[')
142 {
143 // section name
144 s = s.trim(L"[]\t ");
145 pLines->addTail(IniLine(ltSectionName, s));
146 }
147 else
148 {
149 // key=value
150 size_t pos = s.indexOf(L'=');
151 if (pos != (size_t)-1)
152 {
153 String name = s.left(pos).trim();
154 String value = s.right(s.length() - pos - 1).trim();
155 pLines->addTail(IniLine(name, value));
156 }
157 else
158 {
159 // invalid line value. ignore
160 }
161 }
162 }
163}
164
165IniFile::~IniFile()
166{
167 if (m_handle)
168 {
169 try
170 {
171 close();
172 }
173 catch (IOException* e)
174 {
175 __DCL_TRACE1(L"%ls\n", e->toString().data());
176 e->destroy();
177 }
178 }
179}
180
181
182void IniFile::close()
184{
186
187 if (m_handle != NULL) {
188 IniLineList* pLines = (IniLineList*)m_handle;
189 m_handle = NULL;
190 Exception* e = NULL;
191 if (m_bModified) {
192 m_bModified = false;
193 try {
194 OutputStreamWriter out(
195 new FileOutputStream(m_strName, true)
196 );
197 for (IniLineList::Iterator it = pLines->begin();
198 it != pLines->end(); it++) {
199 out << (*it).toString() << endl;
200 }
201 }
202 catch (Exception* _e) {
203 e = _e;
204 }
205 }
206 delete pLines;
207 if (e) {
208 throw e;
209 }
210 }
211}
212
213/*
214#if __DCL_DEBUG
215void IniFile::dump(FILE* fp)
216{
217 if (m_handle)
218 {
219 IniLineList* pLines = (IniLineList*)m_handle;
220 for(IniLineList::Iterator it = pLines->begin(); it != pLines->end(); it++)
221 {
222 fprintf(fp, "%s\n", (*it).line().cstr());
223 }
224 }
225}
226#endif
227*/
228
229String IniFile::getString(
230 const String& strSection,
231 const String& strEntry,
232 const wchar_t* pszDefault // = NULL
234{
235 __DCL_ASSERT(!strSection.isEmpty());
236 __DCL_ASSERT(!strEntry.isEmpty());
237
238 String strResult = __getValue(strSection, strEntry);
239
240 if (strResult.isEmpty() && pszDefault != NULL)
241 strResult = pszDefault;
242
243 return strResult;
244}
245
246int IniFile::getInteger(
247 const String& strSection,
248 const String& strEntry,
249 int nDefault
251{
252 __DCL_ASSERT(!strSection.isEmpty());
253 __DCL_ASSERT(!strEntry.isEmpty());
254
255 String strResult = __getValue(strSection, strEntry);
256 if (!strResult.isEmpty())
257 {
258 try
259 {
260 nDefault = Integer::parse(strResult, 10);
261 }
262 catch (NumericConvertException* e)
263 {
264 throw (new IOException(m_strName, e));
265 }
266 }
267 return nDefault;
268}
269
270void IniFile::setValue(
271 const String& strSection,
272 const String& strEntry,
273 const String& strValue
275{
276 __DCL_ASSERT(!strSection.isEmpty());
277 __DCL_ASSERT(!strEntry.isEmpty());
278
279 __setValue(strSection, strEntry, strValue);
280}
281
282void IniFile::setValue(
283 const String& strSection,
284 const String& strEntry,
285 int nValue
287{
288 __DCL_ASSERT(!strSection.isEmpty());
289 __DCL_ASSERT(!strEntry.isEmpty());
290
291 __setValue(strSection, strEntry, Integer::toString(nValue, 10));
292}
293
294String IniFile::__getValue(
295 const String& strSection,
296 const String& strEntry
297 )
298{
300
301 String strResult;
302 if (m_handle)
303 {
304 IniLineList* pLines = (IniLineList*)m_handle;
305 IniLineList::Iterator it = pLines->begin();
306 for(; it != pLines->end(); it++)
307 {
308 if (((*it).m_type == ltSectionName)
309 && ((*it).m_strName.compareNoCase(strSection) == 0))
310 {
311 // found section
312 it++;
313 for( ; (it != pLines->end()) && ((*it).m_type != ltSectionName); it++)
314 {
315 if (((*it).m_type == ltEntry)
316 && ((*it).m_strName.compareNoCase(strEntry) == 0))
317 {
318 strResult = (*it).m_strValue;
319 break;
320 }
321 }
322 break;
323 }
324 }
325 }
326
327 return strResult;
328}
329
330void IniFile::__setValue(
331 const String& strSection,
332 const String& strEntry,
333 const String& strValue
334 )
335{
337 m_bModified = true;
338
339 IniLineList* pLines = (IniLineList*)m_handle;
340 for(IniLineList::Iterator it = pLines->begin(); it != pLines->end(); it++)
341 {
342 if (((*it).m_type == ltSectionName)
343 && ((*it).m_strName.compareNoCase(strSection) == 0))
344 {
345 // found!
346 it++;
347 for( ; (it != pLines->end()) && ((*it).m_type != ltSectionName); it++)
348 {
349 if (((*it).m_type == ltEntry)
350 && ((*it).m_strName.compareNoCase(strEntry) == 0))
351 {
352 // strEntry 가 있다. 값을 교체한다.
353 (*it).m_strValue = strValue;
354 return;
355 }
356 }
357 pLines->insert(it, IniLine(strEntry, strValue));
358 }
359 else
360 {
361 // 해당하는 섹션이 없다.
362 // 섹션을 추가하고 엔트리를 추가한다.
363 pLines->addTail(IniLine(ltSectionName, strSection));
364 pLines->addTail(IniLine(strEntry, strValue));
365 }
366 }
367}
368
369#if __DCL_WINDOWS
370
371IMPLEMENT_CLASSINFO(RegIniFile, IniFile)
372
373RegIniFile::RegIniFile(HKEY hParentKey, const String& strKey)
375 : m_reg(hParentKey)
376{
377 __DCL_ASSERT(!strKey.isEmpty());
378
379 m_reg.create(strKey, KEY_ALL_ACCESS);
380 m_handle = &m_reg;
381 IniFile::m_strName = strKey;
382}
383
384void RegIniFile::close()
386{
387 m_handle = NULL;
388 m_reg.close();
389}
390
391String RegIniFile::getString(
392 const String& strSection,
393 const String& strEntry,
394 const wchar_t* pszDefault // = NULL
396{
397 __DCL_ASSERT(!strSection.isEmpty());
398 __DCL_ASSERT(!strEntry.isEmpty());
399
400 String strResult;
401
402 try
403 {
404 Registry section(m_reg.key(), strSection, KEY_READ);
405 strResult = section.getString(strEntry);
406 }
407 catch (IOException* e)
408 {
409 __DCL_TRACE1(L"%ls\n", e->toString().data());
410 e->destroy();
411
412 if (pszDefault)
413 strResult = pszDefault;
414 }
415
416 return strResult;
417}
418
419int RegIniFile::getInteger(
420 const String& strSection,
421 const String& strEntry,
422 int nDefault
424{
425 __DCL_ASSERT(!strSection.isEmpty());
426 __DCL_ASSERT(!strEntry.isEmpty());
427
428 int nResult;
429
430 try
431 {
432 Registry section(m_reg.key(), strSection, KEY_READ);
433 nResult = section.getInteger(strEntry);
434 }
435 catch (IOException* e)
436 {
437 __DCL_TRACE1(L"%ls\n", e->toString().data());
438 e->destroy();
439
440 nResult = nDefault;
441 }
442
443 return nResult;
444}
445
446void RegIniFile::setValue(
447 const String& strSection,
448 const String& strEntry,
449 const String& strValue
451{
452 __DCL_ASSERT(!strSection.isEmpty());
453 __DCL_ASSERT(!strEntry.isEmpty());
454
455 Registry section(m_reg.key());
456 section.create(strSection);
457 section.setValue(strEntry, strValue);
458}
459
460void RegIniFile::setValue(
461 const String& strSection,
462 const String& strEntry,
463 int nValue
465{
466 __DCL_ASSERT(!strSection.isEmpty());
467 __DCL_ASSERT(!strEntry.isEmpty());
468
469 Registry section(m_reg.key());
470 section.create(strSection);
471 section.setValue(strEntry, nValue);
472}
473
474#endif // __DCL_WINDOWS
475
476__DCL_END_NAMESPACE
#define __THIS_FILE__
Definition _trace.h:14
#define NULL
Definition Config.h:340
wchar_t char_t
Definition Config.h:275
#define __DCL_THROWS1(e)
Definition Config.h:167
IniLineType
Definition IniFile.cpp:36
@ ltComment
Definition IniFile.cpp:38
@ ltEntry
Definition IniFile.cpp:39
@ ltSectionName
Definition IniFile.cpp:37
List< IniLine > IniLineList
Definition IniFile.cpp:81
#define __DCL_TRACE1(fmt, arg1)
Definition Object.h:376
#define __DCL_ASSERT(expr)
Definition Object.h:371
#define IMPLEMENT_CLASSINFO(class_name, base_class_name)
Definition Object.h:228
#define __T(str)
Definition Object.h:44
#define endl
virtual void destroy()
Definition Exception.cpp:74
virtual String toString() const
Object * m_handle
Definition IniFile.h:73
bool m_bModified
Definition IniFile.h:75
String m_strName
Definition IniFile.h:74
String toString(unsigned _base=10) const
Definition Numeric.inl:21
static int parse(const wchar_t *_number, unsigned _base=10) __DCL_THROWS1(NumericConvertException *)
Definition Numeric.inl:36
ConstIterator end() const
Iterator insert(Iterator _pos, const ELEMENT &_element)
ConstIterator begin() const
List< ELEMENT > & addTail(const ELEMENT &_element)
virtual String toString() const
Definition Object.cpp:187
String m_strValue
Definition IniFile.cpp:46
IniLine(const String &strKey, const String &strValue)
Definition IniFile.cpp:57
IniLineType m_type
Definition IniFile.cpp:44
IniLine()
Definition IniFile.cpp:48
IniLine(IniLineType type, const String &str)
Definition IniFile.cpp:52
String m_strName
Definition IniFile.cpp:45
String toString() const
Definition IniFile.cpp:63