1 // File: testsi.cpp
2 // Library: SimpleIni
3 // Author: Brodie Thiesfield <code@jellycan.com>
4 // Source: http://code.jellycan.com/simpleini/
5 //
6 // Demo of usage
7
8 #ifdef _WIN32
9 # pragma warning(disable: 4786)
10 #endif
11
12 #include <locale.h>
13 #include <stdio.h>
14 #include <cassert>
15
16 #define SI_SUPPORT_IOSTREAMS
17 #if defined(SI_SUPPORT_IOSTREAMS) && !defined(_UNICODE)
18 # include <fstream>
19 #endif
20
21 //#define SI_CONVERT_GENERIC
22 //#define SI_CONVERT_ICU
23 //#define SI_CONVERT_WIN32
24 #include "SimpleIni.h"
25
26 #ifdef SI_CONVERT_ICU
27 // if converting using ICU then we need the ICU library
28 # pragma comment(lib, "icuuc.lib")
29 #endif
30
31 #ifdef _WIN32
32 # include <tchar.h>
33 #else // !_WIN32
34 # define TCHAR char
35 # define _T(x) x
36 # define _tprintf printf
37 # define _tmain main
38 #endif // _WIN32
39
40 static void
Test(CSimpleIni & ini)41 Test(
42 CSimpleIni & ini
43 )
44 {
45 const TCHAR *pszSection = 0;
46 const TCHAR *pItem = 0;
47 const TCHAR *pszVal = 0;
48
49 // get the value of the key "foo" in section "standard"
50 bool bHasMulti;
51 pszVal = ini.GetValue(_T("standard"), _T("foo"), 0, &bHasMulti);
52 _tprintf(_T("\n-- Value of standard::foo is '%s' (hasMulti = %d)\n"),
53 pszVal ? pszVal : _T("(null)"), bHasMulti);
54
55 // set the value of the key "foo" in section "standard"
56 ini.SetValue(_T("standard"), _T("foo"), _T("wibble"));
57 pszVal = ini.GetValue(_T("standard"), _T("foo"), 0, &bHasMulti);
58 _tprintf(_T("\n-- Value of standard::foo is '%s' (hasMulti = %d)\n"),
59 pszVal ? pszVal : _T("(null)"), bHasMulti);
60
61 // get all values of the key "foo" in section "standard"
62 CSimpleIni::TNamesDepend values;
63 if (ini.GetAllValues(_T("standard"), _T("foo"), values)) {
64 _tprintf(_T("\n-- Values of standard::foo are:\n"));
65 CSimpleIni::TNamesDepend::const_iterator i = values.begin();
66 for (; i != values.end(); ++i) {
67 pszVal = i->pItem;
68 _tprintf(_T(" -> '%s'\n"), pszVal);
69 }
70 }
71
72 // get the size of the section [standard]
73 _tprintf(_T("\n-- Number of keys in section [standard] = %d\n"),
74 ini.GetSectionSize(_T("standard")));
75
76 // delete the key "foo" in section "standard", if it has value "bar"
77 ini.DeleteValue(_T("standard"), _T("foo"), _T("bar"));
78 pszVal = ini.GetValue(_T("standard"), _T("foo"), 0);
79 _tprintf(_T("\n-- Value of standard::foo is now '%s'\n"),
80 pszVal ? pszVal : _T("(null)"));
81
82 // delete the key "foo" in section "standard"
83 ini.Delete(_T("standard"), _T("foo"));
84 pszVal = ini.GetValue(_T("standard"), _T("foo"), 0);
85 _tprintf(_T("\n-- Value of standard::foo is now '%s'\n"),
86 pszVal ? pszVal : _T("(null)"));
87
88 // get the size of the section [standard]
89 _tprintf(_T("\n-- Number of keys in section [standard] = %d\n"),
90 ini.GetSectionSize(_T("standard")));
91
92 // get the list of all key names for the section "standard"
93 _tprintf(_T("\n-- Dumping keys of section: [standard]\n"));
94 CSimpleIni::TNamesDepend keys;
95 ini.GetAllKeys(_T("standard"), keys);
96
97 // dump all of the key names
98 CSimpleIni::TNamesDepend::const_iterator iKey = keys.begin();
99 for ( ; iKey != keys.end(); ++iKey ) {
100 pItem = iKey->pItem;
101 _tprintf(_T("Key: %s\n"), pItem);
102 }
103
104 // add a decimal value
105 ini.SetLongValue(_T("integer"), _T("dec"), 42, NULL, false);
106 ini.SetLongValue(_T("integer"), _T("hex"), 42, NULL, true);
107
108 // add some bool values
109 ini.SetBoolValue(_T("bool"), _T("t"), true);
110 ini.SetBoolValue(_T("bool"), _T("f"), false);
111
112 // get the values back
113 assert(42 == ini.GetLongValue(_T("integer"), _T("dec")));
114 assert(42 == ini.GetLongValue(_T("integer"), _T("hex")));
115 assert(true == ini.GetBoolValue(_T("bool"), _T("t")));
116 assert(false == ini.GetBoolValue(_T("bool"), _T("f")));
117
118 // delete the section "standard"
119 ini.Delete(_T("standard"), NULL);
120 _tprintf(_T("\n-- Number of keys in section [standard] = %d\n"),
121 ini.GetSectionSize(_T("standard")));
122
123 // iterate through every section in the file
124 _tprintf(_T("\n-- Dumping all sections\n"));
125 CSimpleIni::TNamesDepend sections;
126 ini.GetAllSections(sections);
127 CSimpleIni::TNamesDepend::const_iterator iSection = sections.begin();
128 for ( ; iSection != sections.end(); ++iSection ) {
129 pszSection = iSection->pItem;
130
131 // print the section name
132 printf("\n");
133 if (*pszSection) {
134 _tprintf(_T("[%s]\n"), pszSection);
135 }
136
137 // if there are keys and values...
138 const CSimpleIni::TKeyVal * pSectionData = ini.GetSection(pszSection);
139 if (pSectionData) {
140 // iterate over all keys and dump the key name and value
141 CSimpleIni::TKeyVal::const_iterator iKeyVal = pSectionData->begin();
142 for ( ;iKeyVal != pSectionData->end(); ++iKeyVal) {
143 pItem = iKeyVal->first.pItem;
144 pszVal = iKeyVal->second;
145 _tprintf(_T("%s=%s\n"), pItem, pszVal);
146 }
147 }
148 }
149 }
150
151 #if defined(SI_SUPPORT_IOSTREAMS) && !defined(_UNICODE)
152 static bool
TestStreams(const TCHAR * a_pszFile,bool a_bIsUtf8,bool a_bUseMultiKey,bool a_bUseMultiLine)153 TestStreams(
154 const TCHAR * a_pszFile,
155 bool a_bIsUtf8,
156 bool a_bUseMultiKey,
157 bool a_bUseMultiLine
158 )
159 {
160 // load the file
161 CSimpleIni ini(a_bIsUtf8, a_bUseMultiKey, a_bUseMultiLine);
162 _tprintf(_T("Loading file: %s\n"), a_pszFile);
163 std::ifstream instream;
164 instream.open(a_pszFile, std::ifstream::in | std::ifstream::binary);
165 SI_Error rc = ini.LoadData(instream);
166 instream.close();
167 if (rc < 0) {
168 printf("Failed to open file.\n");
169 return false;
170 }
171
172 Test(ini);
173
174 // save the file (simple)
175 _tprintf(_T("\n-- Saving file to: testsi-out-streams.ini\n"));
176 std::ofstream outstream;
177 outstream.open("testsi-out-streams.ini", std::ofstream::out | std::ofstream::binary);
178 ini.Save(outstream);
179 outstream.close();
180
181 return true;
182 }
183 #endif // SI_SUPPORT_IOSTREAMS
184
185 static bool
TestFile(const TCHAR * a_pszFile,bool a_bIsUtf8,bool a_bUseMultiKey,bool a_bUseMultiLine)186 TestFile(
187 const TCHAR * a_pszFile,
188 bool a_bIsUtf8,
189 bool a_bUseMultiKey,
190 bool a_bUseMultiLine
191 )
192 {
193 // load the file
194 CSimpleIni ini(a_bIsUtf8, a_bUseMultiKey, a_bUseMultiLine);
195 _tprintf(_T("Loading file: %s\n"), a_pszFile);
196 SI_Error rc = ini.LoadFile(a_pszFile);
197 if (rc < 0) {
198 printf("Failed to open file.\n");
199 return false;
200 }
201
202 // run the tests
203 Test(ini);
204
205 // save the file (simple)
206 _tprintf(_T("\n-- Saving file to: testsi-out.ini\n"));
207 ini.SaveFile("testsi-out.ini");
208
209 // save the file (with comments)
210 // Note: to save the file and add a comment to the beginning, use
211 // code such as the following.
212 _tprintf(_T("\n-- Saving file to: testsi-out-comment.ini\n"));
213 FILE * fp = NULL;
214 #if __STDC_WANT_SECURE_LIB__
215 fopen_s(&fp, "testsi-out-comment.ini", "wb");
216 #else
217 fp = fopen("testsi-out-comment.ini", "wb");
218 #endif
219 if (fp) {
220 CSimpleIni::FileWriter writer(fp);
221 if (a_bIsUtf8) {
222 writer.Write(SI_UTF8_SIGNATURE);
223 }
224
225 // add a string to the file in the correct text format
226 CSimpleIni::Converter convert = ini.GetConverter();
227 convert.ConvertToStore(_T("; output from testsi.cpp test program")
228 SI_NEWLINE SI_NEWLINE);
229 writer.Write(convert.Data());
230
231 ini.Save(writer, false);
232 fclose(fp);
233 }
234
235 return true;
236 }
237
238 static bool
ParseCommandLine(int argc,TCHAR * argv[],const TCHAR * & a_pszFile,bool & a_bIsUtf8,bool & a_bUseMultiKey,bool & a_bUseMultiLine)239 ParseCommandLine(
240 int argc,
241 TCHAR * argv[],
242 const TCHAR * & a_pszFile,
243 bool & a_bIsUtf8,
244 bool & a_bUseMultiKey,
245 bool & a_bUseMultiLine
246 )
247 {
248 a_pszFile = 0;
249 a_bIsUtf8 = false;
250 a_bUseMultiKey = false;
251 a_bUseMultiLine = false;
252 for (--argc; argc > 0; --argc) {
253 if (argv[argc][0] == '-') {
254 switch (argv[argc][1]) {
255 case TCHAR('u'):
256 a_bIsUtf8 = true;
257 break;
258 case TCHAR('m'):
259 a_bUseMultiKey = true;
260 break;
261 case TCHAR('l'):
262 a_bUseMultiLine = true;
263 break;
264 }
265 }
266 else {
267 a_pszFile = argv[argc];
268 }
269 }
270 if (!a_pszFile) {
271 _tprintf(
272 _T("Usage: testsi [-u] [-m] [-l] iniFile\n")
273 _T(" -u Load file as UTF-8 (Default is to use system locale)\n")
274 _T(" -m Enable multiple keys\n")
275 _T(" -l Enable multiple line values\n")
276 );
277 return false;
278 }
279
280 return true;
281 }
282
283 extern bool TestStreams();
284
285 int
_tmain(int argc,TCHAR * argv[])286 _tmain(
287 int argc,
288 TCHAR * argv[]
289 )
290 {
291 setlocale(LC_ALL, "");
292
293 // start of automated testing...
294 TestStreams();
295
296 // parse the command line
297 const TCHAR * pszFile;
298 bool bIsUtf8, bUseMultiKey, bUseMultiLine;
299 if (!ParseCommandLine(argc, argv, pszFile, bIsUtf8, bUseMultiKey, bUseMultiLine)) {
300 return 1;
301 }
302
303 // run the test
304 if (!TestFile(pszFile, bIsUtf8, bUseMultiKey, bUseMultiLine)) {
305 return 1;
306 }
307 #if defined(SI_SUPPORT_IOSTREAMS) && !defined(_UNICODE)
308 if (!TestStreams(pszFile, bIsUtf8, bUseMultiKey, bUseMultiLine)) {
309 return 1;
310 }
311 #endif
312
313 return 0;
314 }
315
316