blob: da448a5207bec13acf68e8cf25c70bcea1b499cb
1 | #include <stdio.h> |
2 | #include <stdlib.h> |
3 | #include <assert.h> |
4 | #include <string.h> |
5 | #include <ctype.h> |
6 | |
7 | #include "CIniFile.h" |
8 | |
9 | CIniFile::CIniFile() |
10 | { |
11 | mpFirstSection = NULL; |
12 | mpFileName[0] = '\0'; |
13 | m_pIniFile = NULL; |
14 | mpFirstLine = NULL; |
15 | } |
16 | |
17 | CIniFile::~CIniFile() |
18 | { |
19 | LOGD("CIniFile::~CIniFile()"); |
20 | FreeAllMem(); |
21 | } |
22 | |
23 | int CIniFile::LoadFromFile(const char *filename) |
24 | { |
25 | char lineStr[MAX_INI_FILE_LINE_LEN]; |
26 | char *pStr; |
27 | LINE *pCurLINE = NULL; |
28 | SECTION *pCurSection = NULL; |
29 | |
30 | FreeAllMem(); |
31 | |
32 | int Len; |
33 | if (filename == NULL) { |
34 | return -1; |
35 | } |
36 | |
37 | strcpy(mpFileName, filename); |
38 | LOGD("LoadFromFile 2name = %s", mpFileName); |
39 | if ((m_pIniFile = fopen (mpFileName, "r")) == NULL) { |
40 | return -1; |
41 | } |
42 | |
43 | while (fgets (lineStr, MAX_INI_FILE_LINE_LEN, m_pIniFile) != NULL) { |
44 | //去掉多余字符 |
45 | allTrim(lineStr); |
46 | |
47 | LINE *pLINE = new LINE(); |
48 | pLINE->pKeyStart = pLINE->Text; |
49 | pLINE->pKeyEnd = pLINE->Text; |
50 | pLINE->pValueStart = pLINE->Text; |
51 | pLINE->pValueEnd = pLINE->Text; |
52 | pLINE->pNext = NULL; |
53 | pLINE->type = getLineType(lineStr); |
54 | //LOGD("getline=%s len=%d type=%d", lineStr, strlen(lineStr), pLINE->type); |
55 | strcpy(pLINE->Text, lineStr); |
56 | pLINE->LineLen = strlen(pLINE->Text); |
57 | |
58 | //head |
59 | if (mpFirstLine == NULL) { |
60 | mpFirstLine = pLINE; |
61 | } else { |
62 | pCurLINE->pNext = pLINE; |
63 | } |
64 | |
65 | pCurLINE = pLINE; |
66 | |
67 | switch (pCurLINE->type) { |
68 | case LINE_TYPE_SECTION: { |
69 | SECTION *pSec = new SECTION(); |
70 | pSec->pLine = pLINE; |
71 | pSec->pNext = NULL; |
72 | if (mpFirstSection == NULL) { //first section |
73 | mpFirstSection = pSec; |
74 | } else { |
75 | pCurSection->pNext = pSec; |
76 | } |
77 | pCurSection = pSec; |
78 | break; |
79 | } |
80 | case LINE_TYPE_KEY: { |
81 | char *pM = strchr(pCurLINE->Text, '='); |
82 | pCurLINE->pKeyStart = pCurLINE->Text; |
83 | pCurLINE->pKeyEnd = pM - 1; |
84 | pCurLINE->pValueStart = pM + 1; |
85 | pCurLINE->pValueEnd = pCurLINE->Text + pCurLINE->LineLen - 1; |
86 | break; |
87 | } |
88 | case LINE_TYPE_COMMENT: { |
89 | break; |
90 | } |
91 | default: { |
92 | break; |
93 | } |
94 | } |
95 | } |
96 | |
97 | fclose (m_pIniFile); |
98 | m_pIniFile = NULL; |
99 | |
100 | return 0; |
101 | } |
102 | |
103 | void CIniFile::printAll() |
104 | { |
105 | //line |
106 | for (LINE *pline = mpFirstLine; pline != NULL; pline = pline->pNext) { |
107 | LOGD("line = %s type = %d", pline->Text, pline->type); |
108 | } |
109 | |
110 | //section |
111 | for (SECTION *psec = mpFirstSection; psec != NULL; psec = psec->pNext) { |
112 | LOGD("sec = %s", psec->pLine->Text); |
113 | } |
114 | return; |
115 | } |
116 | |
117 | int CIniFile::LoadFromString(const char *str) |
118 | { |
119 | return 0; |
120 | } |
121 | |
122 | int CIniFile::SaveToFile(const char *filename) |
123 | { |
124 | const char *file = NULL; |
125 | if (m_pIniFile != NULL) { |
126 | fclose (m_pIniFile); |
127 | } |
128 | |
129 | if (filename == NULL) { |
130 | if (strlen(mpFileName) == 0) { |
131 | LOGD("error save file is null"); |
132 | return -1; |
133 | } else { |
134 | file = mpFileName; |
135 | } |
136 | } else { |
137 | file = filename; |
138 | } |
139 | //LOGD("Save to file name = %s", file); |
140 | |
141 | if ((m_pIniFile = fopen (file, "wb")) == NULL) { |
142 | LOGD("Save to file open error = %s", file); |
143 | return -1; |
144 | } |
145 | |
146 | LINE *pCurLine = NULL; |
147 | for (pCurLine = mpFirstLine; pCurLine != NULL; pCurLine = pCurLine->pNext) { |
148 | fprintf (m_pIniFile, "%s\r\n", pCurLine->Text); |
149 | } |
150 | |
151 | fflush(m_pIniFile); |
152 | fsync(fileno(m_pIniFile)); |
153 | |
154 | fclose(m_pIniFile); |
155 | m_pIniFile = NULL; |
156 | return 0; |
157 | } |
158 | |
159 | //暂不插入操作 |
160 | int CIniFile::SetString(const char *section, const char *key, const char *value) |
161 | { |
162 | SECTION *pNewSec = NULL; |
163 | LINE *pNewSecLine = NULL; |
164 | LINE *pNewKeyLine = NULL; |
165 | |
166 | SECTION *pSec = getSection(section); |
167 | if (pSec == NULL) { |
168 | pNewSec = new SECTION(); |
169 | pNewSecLine = new LINE(); |
170 | pNewKeyLine = new LINE(); |
171 | |
172 | pNewKeyLine->type = LINE_TYPE_KEY; |
173 | pNewSecLine->type = LINE_TYPE_SECTION; |
174 | |
175 | |
176 | sprintf(pNewSecLine->Text, "[%s]", section); |
177 | pNewSec->pLine = pNewSecLine; |
178 | |
179 | InsertSection(pNewSec); |
180 | |
181 | int keylen = strlen(key); |
182 | sprintf(pNewKeyLine->Text, "%s=%s", key, value); |
183 | pNewKeyLine->LineLen = strlen(pNewKeyLine->Text); |
184 | pNewKeyLine->pKeyStart = pNewKeyLine->Text; |
185 | pNewKeyLine->pKeyEnd = pNewKeyLine->pKeyStart + keylen - 1; |
186 | pNewKeyLine->pValueStart = pNewKeyLine->pKeyStart + keylen + 1; |
187 | pNewKeyLine->pValueEnd = pNewKeyLine->Text + pNewKeyLine->LineLen - 1; |
188 | |
189 | InsertKeyLine(pNewSec, pNewKeyLine); |
190 | |
191 | } else { //find section |
192 | LINE *pLine = getKeyLineAtSec(pSec, key); |
193 | if (pLine == NULL) { //, not find key |
194 | pNewKeyLine = new LINE(); |
195 | pNewKeyLine->type = LINE_TYPE_KEY; |
196 | |
197 | int keylen = strlen(key); |
198 | sprintf(pNewKeyLine->Text, "%s=%s", key, value); |
199 | pNewKeyLine->LineLen = strlen(pNewKeyLine->Text); |
200 | pNewKeyLine->pKeyStart = pNewKeyLine->Text; |
201 | pNewKeyLine->pKeyEnd = pNewKeyLine->pKeyStart + keylen - 1; |
202 | pNewKeyLine->pValueStart = pNewKeyLine->pKeyStart + keylen + 1; |
203 | pNewKeyLine->pValueEnd = pNewKeyLine->Text + pNewKeyLine->LineLen - 1; |
204 | |
205 | InsertKeyLine(pSec, pNewKeyLine); |
206 | } else { //all find, change it |
207 | sprintf(pLine->Text, "%s=%s", key, value); |
208 | pLine->LineLen = strlen(pLine->Text); |
209 | pLine->pValueEnd = pLine->Text + pLine->LineLen - 1; |
210 | } |
211 | } |
212 | |
213 | //save |
214 | SaveToFile(NULL); |
215 | return 0; |
216 | } |
217 | int CIniFile::SetInt(const char *section, const char *key, int value) |
218 | { |
219 | char tmp[64]; |
220 | sprintf(tmp, "%d", value); |
221 | SetString(section, key, tmp); |
222 | return 0; |
223 | } |
224 | const char *CIniFile::GetString(const char *section, const char *key, const char *def_value) |
225 | { |
226 | SECTION *pSec = getSection(section); |
227 | if (pSec == NULL) return def_value; |
228 | LINE *pLine = getKeyLineAtSec(pSec, key); |
229 | if (pLine == NULL) return def_value; |
230 | |
231 | return pLine->pValueStart; |
232 | } |
233 | int CIniFile::GetInt(const char *section, const char *key, int def_value) |
234 | { |
235 | const char *num = GetString(section, key, NULL); |
236 | if (num != NULL) { |
237 | return atoi(num); |
238 | } |
239 | return def_value; |
240 | } |
241 | |
242 | |
243 | LINE_TYPE CIniFile::getLineType(char *Str) |
244 | { |
245 | LINE_TYPE type = LINE_TYPE_COMMENT; |
246 | //只要有#,就是注释 |
247 | if (strchr(Str, '#') != NULL) { |
248 | type = LINE_TYPE_COMMENT; |
249 | } else if ( (strstr (Str, "[") != NULL) && (strstr (Str, "]") != NULL) ) { /* Is Section */ |
250 | type = LINE_TYPE_SECTION; |
251 | } else { |
252 | if (strstr (Str, "=") != NULL) { |
253 | type = LINE_TYPE_KEY; |
254 | } else { |
255 | type = LINE_TYPE_COMMENT; |
256 | } |
257 | } |
258 | return type; |
259 | } |
260 | |
261 | void CIniFile::FreeAllMem() |
262 | { |
263 | //line |
264 | LINE *pCurLine = NULL; |
265 | LINE *pNextLine = NULL; |
266 | for (pCurLine = mpFirstLine; pCurLine != NULL;) { |
267 | pNextLine = pCurLine->pNext; |
268 | delete pCurLine; |
269 | pCurLine = pNextLine; |
270 | } |
271 | mpFirstLine = NULL; |
272 | //section |
273 | SECTION *pCurSec = NULL; |
274 | SECTION *pNextSec = NULL; |
275 | for (pCurSec = mpFirstSection; pCurSec != NULL;) { |
276 | pNextSec = pCurSec->pNext; |
277 | delete pCurSec; |
278 | pCurSec = pNextSec; |
279 | } |
280 | mpFirstSection = NULL; |
281 | } |
282 | |
283 | int CIniFile::InsertSection(SECTION *pSec) |
284 | { |
285 | //insert it to sections list ,as first section |
286 | pSec->pNext = mpFirstSection; |
287 | mpFirstSection = pSec; |
288 | //insert it to lines list, at first |
289 | pSec->pLine->pNext = mpFirstLine; |
290 | mpFirstLine = pSec->pLine; |
291 | return 0; |
292 | } |
293 | int CIniFile::InsertKeyLine(SECTION *pSec, LINE *line) |
294 | { |
295 | LINE *line1 = pSec->pLine; |
296 | LINE *line2 = line1->pNext; |
297 | line1->pNext = line; |
298 | line->pNext = line2; |
299 | return 0; |
300 | } |
301 | SECTION *CIniFile::getSection(const char *section) |
302 | { |
303 | //section |
304 | for (SECTION *psec = mpFirstSection; psec != NULL; psec = psec->pNext) { |
305 | if (strncmp((psec->pLine->Text) + 1, section, strlen(section)) == 0) |
306 | return psec; |
307 | } |
308 | return NULL; |
309 | } |
310 | LINE *CIniFile::getKeyLineAtSec(SECTION *pSec, const char *key) |
311 | { |
312 | //line |
313 | for (LINE *pline = pSec->pLine->pNext; (pline != NULL && pline->type != LINE_TYPE_SECTION); pline = pline->pNext) { |
314 | if (pline->type == LINE_TYPE_KEY) { |
315 | if (strncmp(pline->Text, key, strlen(key)) == 0) |
316 | return pline; |
317 | } |
318 | } |
319 | return NULL; |
320 | } |
321 | //去掉串里面的,空格,回车,换行,s指向转换处理后的串的开头 |
322 | void CIniFile::allTrim(char *Str) |
323 | { |
324 | //去掉换行 |
325 | char *pStr; |
326 | pStr = strchr (Str, '\n'); |
327 | if (pStr != NULL) { |
328 | *pStr = 0; |
329 | } |
330 | //去掉尾部回车 |
331 | int Len = strlen(Str); |
332 | if ( Len > 0 ) { |
333 | if ( Str[Len - 1] == '\r' ) { |
334 | Str[Len - 1] = '\0'; |
335 | } |
336 | } |
337 | //去掉空格 |
338 | pStr = Str; |
339 | while (*pStr != '\0') { //没到尾部 |
340 | if (*pStr == ' ') { //遇到空格 |
341 | char *pTmp = pStr;//从空格处开始 |
342 | while (*pTmp != '\0') { |
343 | *pTmp = *(pTmp + 1);//前移,包括移最后结束符 |
344 | pTmp++; |
345 | } |
346 | } else { |
347 | pStr++; |
348 | } |
349 | } |
350 | return; |
351 | } |
352 | |
353 | |
354 |