inifile.cpp 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283
  1. /* Copyright (c) 2014-2019 WinnerHust
  2. * All rights reserved.
  3. * Redistribution and use in source and binary forms, with or without
  4. * modification, are permitted provided that the following conditions are met:
  5. *
  6. * Redistributions of source code must retain the above copyright notice,
  7. * this list of conditions and the following disclaimer.
  8. *
  9. * Redistributions in binary form must reproduce the above copyright notice,
  10. * this list of conditions and the following disclaimer in the documentation
  11. * and/or other materials provided with the distribution.
  12. *
  13. * The names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  17. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  18. * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  19. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
  20. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
  21. * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  22. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  23. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  24. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  25. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  26. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. #include <stdlib.h>
  29. #include <stdio.h>
  30. #include <ctype.h>
  31. #include <iostream>
  32. #include <fstream>
  33. #include "inifile.hpp"
  34. #include "inifile_api.h"
  35. #include "sample_log.h"
  36. namespace inifile
  37. {
  38. // 构造函数,会初始化注释字符集合flags_(容器),目前只使用#和;作为注释前缀
  39. IniFile::IniFile()
  40. :commentDelimiter("#")
  41. {
  42. }
  43. //解析一行数据,得到键值
  44. /* --------------------------------------------------------------------------*/
  45. /**
  46. * @brief parse
  47. *
  48. * @param content 数据源指针
  49. * @param key 键名
  50. * @param value 键值
  51. * @param c 分隔符
  52. *
  53. * @return bool
  54. */
  55. /* ----------------------------------------------------------------------------*/
  56. bool IniFile::parse(const string &content, string *key, string *value)
  57. {
  58. return split(content, "=", key, value);
  59. }
  60. int IniFile::UpdateSection(const string &cleanLine, const string &comment,
  61. const string &rightComment, IniSection **section)
  62. {
  63. IniSection *newSection;
  64. // 查找右中括号
  65. size_t index = cleanLine.find_first_of(']');
  66. if (index == string::npos) {
  67. errMsg = string("no matched ] found");
  68. return ERR_UNMATCHED_BRACKETS;
  69. }
  70. int len = index - 1;
  71. // 若段名为空,继续下一行
  72. if (len <= 0) {
  73. errMsg = string("section name is empty");
  74. return ERR_SECTION_EMPTY;
  75. }
  76. // 取段名
  77. string s(cleanLine, 1, len);
  78. trim(s);
  79. //检查段是否已存在
  80. if (getSection(s) != NULL) {
  81. errMsg = string("section ") + s + string("already exist");
  82. return ERR_SECTION_ALREADY_EXISTS;
  83. }
  84. // 申请一个新段,由于map容器会自动排序,打乱原有顺序,因此改用vector存储(sections_vt)
  85. newSection = new IniSection();
  86. // 填充段名
  87. newSection->name = s;
  88. // 填充段开头的注释
  89. newSection->comment = comment;
  90. newSection->rightComment = rightComment;
  91. sections_vt.push_back(newSection);
  92. *section = newSection;
  93. return 0;
  94. }
  95. int IniFile::AddKeyValuePair(const string &cleanLine, const string &comment,
  96. const string &rightComment, IniSection *section)
  97. {
  98. string key, value;
  99. if (!parse(cleanLine, &key, &value)) {
  100. errMsg = string("parse line failed:") + cleanLine;
  101. return ERR_PARSE_KEY_VALUE_FAILED;
  102. }
  103. IniItem item;
  104. item.key = key;
  105. item.value = value;
  106. item.comment = comment;
  107. item.rightComment = rightComment;
  108. section->items.push_back(item);
  109. return 0;
  110. }
  111. int IniFile::Load(const string &filePath)
  112. {
  113. int err;
  114. string line; // 带注释的行
  115. string cleanLine; // 去掉注释后的行
  116. string comment;
  117. string rightComment;
  118. IniSection *currSection = NULL; // 初始化一个字段指针
  119. release();
  120. iniFilePath = filePath;
  121. std::ifstream ifs(iniFilePath);
  122. if (!ifs.is_open()) {
  123. errMsg = string("open") +iniFilePath+ string(" file failed");
  124. return ERR_OPEN_FILE_FAILED;
  125. }
  126. //增加默认段,即 无名段""
  127. currSection = new IniSection();
  128. currSection->name = "";
  129. sections_vt.push_back(currSection);
  130. // 每次读取一行内容到line
  131. while (std::getline(ifs, line)) {
  132. trim(line);
  133. // step 0,空行处理,如果长度为0,说明是空行,添加到comment,当作是注释的一部分
  134. if (line.length() <= 0) {
  135. comment += delim;
  136. continue;
  137. }
  138. // step 1
  139. // 如果行首不是注释,查找行尾是否存在注释
  140. // 如果该行以注释开头,添加到comment,跳过当前循环,continue
  141. if (IsCommentLine(line)) {
  142. comment += line + delim;
  143. continue;
  144. }
  145. // 如果行首不是注释,查找行尾是否存在注释,若存在,切割该行,将注释内容添加到rightComment
  146. split(line, commentDelimiter, &cleanLine, &rightComment);
  147. // step 2,判断line内容是否为段或键
  148. //段开头查找 [
  149. if (cleanLine[0] == '[') {
  150. err = UpdateSection(cleanLine, comment, rightComment, &currSection);
  151. } else {
  152. // 如果该行是键值,添加到section段的items容器
  153. err = AddKeyValuePair(cleanLine, comment, rightComment, currSection);
  154. }
  155. if (err != 0) {
  156. ifs.close();
  157. return err;
  158. }
  159. // comment清零
  160. comment = "";
  161. rightComment = "";
  162. }
  163. ifs.close();
  164. return 0;
  165. }
  166. int IniFile::Save()
  167. {
  168. return SaveAs(iniFilePath);
  169. }
  170. int IniFile::SaveAs(const string &filePath)
  171. {
  172. string data = "";
  173. /* 载入section数据 */
  174. for (IniSection_it sect = sections_vt.begin(); sect != sections_vt.end(); ++sect) {
  175. if ((*sect)->comment != "") {
  176. data += (*sect)->comment;
  177. }
  178. if ((*sect)->name != "") {
  179. data += string("[") + (*sect)->name + string("]");
  180. data += delim;
  181. }
  182. if ((*sect)->rightComment != "") {
  183. data += " " + commentDelimiter +(*sect)->rightComment;
  184. }
  185. /* 载入item数据 */
  186. for (IniSection::IniItem_it item = (*sect)->items.begin(); item != (*sect)->items.end(); ++item) {
  187. if (item->comment != "") {
  188. data += item->comment;
  189. if (data[data.length()-1] != '\n') {
  190. data += delim;
  191. }
  192. }
  193. data += item->key + "=" + item->value;
  194. if (item->rightComment != "") {
  195. data += " " + commentDelimiter + item->rightComment;
  196. }
  197. if (data[data.length()-1] != '\n') {
  198. data += delim;
  199. }
  200. }
  201. }
  202. std::ofstream ofs(filePath);
  203. ofs << data;
  204. ofs.close();
  205. return 0;
  206. }
  207. IniSection *IniFile::getSection(const string &section /*=""*/)
  208. {
  209. for (IniSection_it it = sections_vt.begin(); it != sections_vt.end(); ++it) {
  210. if ((*it)->name == section) {
  211. return *it;
  212. }
  213. }
  214. return NULL;
  215. }
  216. int IniFile::GetSections(vector<string> *sections)
  217. {
  218. for (IniSection_it it = sections_vt.begin(); it != sections_vt.end(); ++it) {
  219. sections->push_back((*it)->name);
  220. }
  221. return sections->size();
  222. }
  223. int IniFile::GetSectionNum()
  224. {
  225. return sections_vt.size();
  226. }
  227. int IniFile::GetStringValue(const string &section, const string &key, string *value)
  228. {
  229. return getValue(section, key, value);
  230. }
  231. int IniFile::GetIntValue(const string &section, const string &key, int *intValue)
  232. {
  233. int err;
  234. string strValue;
  235. err = getValue(section, key, &strValue);
  236. *intValue = atoi(strValue.c_str());
  237. return err;
  238. }
  239. int IniFile::GetDoubleValue(const string &section, const string &key, double *value)
  240. {
  241. int err;
  242. string strValue;
  243. err = getValue(section, key, &strValue);
  244. *value = atof(strValue.c_str());
  245. return err;
  246. }
  247. int IniFile::GetBoolValue(const string &section, const string &key, bool *value)
  248. {
  249. int err;
  250. string strValue;
  251. err = getValue(section, key, &strValue);
  252. if (StringCmpIgnoreCase(strValue, "true") || StringCmpIgnoreCase(strValue, "1")) {
  253. *value = true;
  254. } else if (StringCmpIgnoreCase(strValue, "false") || StringCmpIgnoreCase(strValue, "0")) {
  255. *value = false;
  256. }
  257. return err;
  258. }
  259. /* 获取section段第一个键为key的string值,成功返回获取的值,否则返回默认值 */
  260. void IniFile::GetStringValueOrDefault(const string &section, const string &key,
  261. string *value, const string &defaultValue)
  262. {
  263. if (GetStringValue(section, key, value) != 0) {
  264. *value = defaultValue;
  265. }
  266. return;
  267. }
  268. /* 获取section段第一个键为key的int值,成功返回获取的值,否则返回默认值 */
  269. void IniFile::GetIntValueOrDefault(const string &section, const string &key, int *value, int defaultValue)
  270. {
  271. if (GetIntValue(section, key, value) != 0) {
  272. *value = defaultValue;
  273. }
  274. return;
  275. }
  276. /* 获取section段第一个键为key的double值,成功返回获取的值,否则返回默认值 */
  277. void IniFile::GetDoubleValueOrDefault(const string &section, const string &key, double *value, double defaultValue)
  278. {
  279. if (GetDoubleValue(section, key, value) != 0) {
  280. *value = defaultValue;
  281. }
  282. return;
  283. }
  284. /* 获取section段第一个键为key的bool值,成功返回获取的值,否则返回默认值 */
  285. void IniFile::GetBoolValueOrDefault(const string &section, const string &key, bool *value, bool defaultValue)
  286. {
  287. if (GetBoolValue(section, key, value) != 0) {
  288. *value = defaultValue;
  289. }
  290. return;
  291. }
  292. /* 获取注释,如果key=""则获取段注释 */
  293. int IniFile::GetComment(const string &section, const string &key, string *comment)
  294. {
  295. IniSection *sect = getSection(section);
  296. if (sect == NULL) {
  297. errMsg = string("not find the section ")+section;
  298. return ERR_NOT_FOUND_SECTION;
  299. }
  300. if (key == "") {
  301. *comment = sect->comment;
  302. return RET_OK;
  303. }
  304. for (IniSection::IniItem_it it = sect->begin(); it != sect->end(); ++it) {
  305. if (it->key == key) {
  306. *comment = it->comment;
  307. return RET_OK;
  308. }
  309. }
  310. errMsg = string("not find the key ")+section;
  311. return ERR_NOT_FOUND_KEY;
  312. }
  313. /* 获取行尾注释,如果key=""则获取段的行尾注释 */
  314. int IniFile::GetRightComment(const string &section, const string &key, string *rightComment)
  315. {
  316. IniSection *sect = getSection(section);
  317. if (sect == NULL) {
  318. errMsg = string("not find the section ")+section;
  319. return ERR_NOT_FOUND_SECTION;
  320. }
  321. if (key == "") {
  322. *rightComment = sect->rightComment;
  323. return RET_OK;
  324. }
  325. for (IniSection::IniItem_it it = sect->begin(); it != sect->end(); ++it) {
  326. if (it->key == key) {
  327. *rightComment = it->rightComment;
  328. return RET_OK;
  329. }
  330. }
  331. errMsg = string("not find the key ")+key;
  332. return ERR_NOT_FOUND_KEY;
  333. }
  334. int IniFile::getValue(const string &section, const string &key, string *value)
  335. {
  336. string comment;
  337. return getValue(section, key, value, &comment);
  338. }
  339. int IniFile::getValue(const string &section, const string &key, string *value, string *comment)
  340. {
  341. IniSection *sect = getSection(section);
  342. if (sect == NULL) {
  343. errMsg = string("not find the section ")+section;
  344. return ERR_NOT_FOUND_SECTION;
  345. }
  346. for (IniSection::IniItem_it it = sect->begin(); it != sect->end(); ++it) {
  347. if (it->key == key) {
  348. *value = it->value;
  349. *comment = it->comment;
  350. return RET_OK;
  351. }
  352. }
  353. errMsg = string("not find the key ")+key;
  354. return ERR_NOT_FOUND_KEY;
  355. }
  356. int IniFile::GetValues(const string &section, const string &key, vector<string> *values)
  357. {
  358. vector<string> comments;
  359. return GetValues(section, key, values, &comments);
  360. }
  361. int IniFile::GetValues(const string &section, const string &key, vector<string> *values, vector<string> *comments)
  362. {
  363. string value, comment;
  364. values->clear();
  365. comments->clear();
  366. IniSection *sect = getSection(section);
  367. if (sect == NULL) {
  368. errMsg = string("not find the section ")+section;
  369. return ERR_NOT_FOUND_SECTION;
  370. }
  371. for (IniSection::IniItem_it it = sect->begin(); it != sect->end(); ++it) {
  372. if (it->key == key) {
  373. value = it->value;
  374. comment = it->comment;
  375. values->push_back(value);
  376. comments->push_back(comment);
  377. }
  378. }
  379. if (values->size() == 0) {
  380. errMsg = string("not find the key ")+key;
  381. return ERR_NOT_FOUND_KEY;
  382. }
  383. return RET_OK;
  384. }
  385. bool IniFile::HasSection(const string &section)
  386. {
  387. return (getSection(section) != NULL);
  388. }
  389. bool IniFile::HasKey(const string &section, const string &key)
  390. {
  391. IniSection *sect = getSection(section);
  392. if (sect != NULL) {
  393. for (IniSection::IniItem_it it = sect->begin(); it != sect->end(); ++it) {
  394. if (it->key == key) {
  395. return true;
  396. }
  397. }
  398. }
  399. return false;
  400. }
  401. int IniFile::setValue(const string &section, const string &key, const string &value, const string &comment /*=""*/)
  402. {
  403. IniSection *sect = getSection(section);
  404. string comt = comment;
  405. if (comt != "") {
  406. comt = commentDelimiter + comt;
  407. }
  408. if (sect == NULL) {
  409. //如果段不存在,新建一个
  410. sect = new IniSection();
  411. if (sect == NULL) {
  412. errMsg = string("no enough memory!");
  413. return ERR_NO_ENOUGH_MEMORY;
  414. }
  415. sect->name = section;
  416. if (sect->name == "") {
  417. // 确保空section在第一个
  418. sections_vt.insert(sections_vt.begin(), sect);
  419. } else {
  420. sections_vt.push_back(sect);
  421. }
  422. }
  423. for (IniSection::IniItem_it it = sect->begin(); it != sect->end(); ++it) {
  424. if (it->key == key) {
  425. it->value = value;
  426. it->comment = comt;
  427. return RET_OK;
  428. }
  429. }
  430. // not found key
  431. IniItem item;
  432. item.key = key;
  433. item.value = value;
  434. item.comment = comt;
  435. sect->items.push_back(item);
  436. return RET_OK;
  437. }
  438. int IniFile::SetStringValue(const string &section, const string &key, const string &value)
  439. {
  440. return setValue(section, key, value);
  441. }
  442. int IniFile::SetIntValue(const string &section, const string &key, int value)
  443. {
  444. char buf[64] = {0};
  445. snprintf(buf, sizeof(buf), "%d", value);
  446. return setValue(section, key, buf);
  447. }
  448. int IniFile::SetDoubleValue(const string &section, const string &key, double value)
  449. {
  450. char buf[64] = {0};
  451. snprintf(buf, sizeof(buf), "%f", value);
  452. return setValue(section, key, buf);
  453. }
  454. int IniFile::SetBoolValue(const string &section, const string &key, bool value)
  455. {
  456. if (value) {
  457. return setValue(section, key, "true");
  458. } else {
  459. return setValue(section, key, "false");
  460. }
  461. }
  462. int IniFile::SetComment(const string &section, const string &key, const string &comment)
  463. {
  464. IniSection *sect = getSection(section);
  465. if (sect == NULL) {
  466. errMsg = string("Not find the section ")+section;
  467. return ERR_NOT_FOUND_SECTION;
  468. }
  469. if (key == "") {
  470. sect->comment = comment;
  471. return RET_OK;
  472. }
  473. for (IniSection::IniItem_it it = sect->begin(); it != sect->end(); ++it) {
  474. if (it->key == key) {
  475. it->comment = comment;
  476. return RET_OK;
  477. }
  478. }
  479. errMsg = string("not find the key ")+key;
  480. return ERR_NOT_FOUND_KEY;
  481. }
  482. int IniFile::SetRightComment(const string &section, const string &key, const string &rightComment)
  483. {
  484. IniSection *sect = getSection(section);
  485. if (sect == NULL) {
  486. errMsg = string("Not find the section ")+section;
  487. return ERR_NOT_FOUND_SECTION;
  488. }
  489. if (key == "") {
  490. sect->rightComment = rightComment;
  491. return RET_OK;
  492. }
  493. for (IniSection::IniItem_it it = sect->begin(); it != sect->end(); ++it) {
  494. if (it->key == key) {
  495. it->rightComment = rightComment;
  496. return RET_OK;
  497. }
  498. }
  499. errMsg = string("not find the key ")+key;
  500. return ERR_NOT_FOUND_KEY;
  501. }
  502. void IniFile::SetCommentDelimiter(const string &delimiter)
  503. {
  504. commentDelimiter = delimiter;
  505. }
  506. void IniFile::DeleteSection(const string &section)
  507. {
  508. for (IniSection_it it = sections_vt.begin(); it != sections_vt.end(); ) {
  509. if ((*it)->name == section) {
  510. delete *it;
  511. it = sections_vt.erase(it);
  512. break;
  513. } else {
  514. it++;
  515. }
  516. }
  517. }
  518. void IniFile::DeleteKey(const string &section, const string &key)
  519. {
  520. IniSection *sect = getSection(section);
  521. if (sect != NULL) {
  522. for (IniSection::IniItem_it it = sect->begin(); it != sect->end();) {
  523. if (it->key == key) {
  524. it = sect->items.erase(it);
  525. break;
  526. } else {
  527. it++;
  528. }
  529. }
  530. }
  531. }
  532. /*-------------------------------------------------------------------------*/
  533. /**
  534. @brief release: 释放全部资源,清空容器
  535. @param none
  536. @return none
  537. */
  538. /*--------------------------------------------------------------------------*/
  539. void IniFile::release()
  540. {
  541. iniFilePath = "";
  542. for (IniSection_it it = sections_vt.begin(); it != sections_vt.end(); ++it) {
  543. delete (*it); // 清除section
  544. }
  545. sections_vt.clear();
  546. }
  547. /*-------------------------------------------------------------------------*/
  548. /**
  549. @brief 判断是否是注释
  550. @param str 一个string变量
  551. @return 如果是注释则为真
  552. */
  553. /*--------------------------------------------------------------------------*/
  554. bool IniFile::IsCommentLine(const string &str)
  555. {
  556. return StartWith(str, commentDelimiter);
  557. }
  558. /*-------------------------------------------------------------------------*/
  559. /**
  560. @brief print for debug
  561. @param none
  562. @return none
  563. */
  564. /*--------------------------------------------------------------------------*/
  565. void IniFile::print()
  566. {
  567. printf("############ print start ############\n");
  568. printf("filePath:[%s]\n", iniFilePath.c_str());
  569. printf("commentDelimiter:[%s]\n", commentDelimiter.c_str());
  570. for (IniSection_it it = sections_vt.begin(); it != sections_vt.end(); ++it) {
  571. printf("comment :[\n%s]\n", (*it)->comment.c_str());
  572. printf("section :\n[%s]\n", (*it)->name.c_str());
  573. if ((*it)->rightComment != "") {
  574. printf("rightComment:\n%s", (*it)->rightComment.c_str());
  575. }
  576. for (IniSection::IniItem_it i = (*it)->items.begin(); i != (*it)->items.end(); ++i) {
  577. printf(" comment :[\n%s]\n", i->comment.c_str());
  578. printf(" parm :%s=%s\n", i->key.c_str(), i->value.c_str());
  579. if (i->rightComment != "") {
  580. printf(" rcomment:[\n%s]\n", i->rightComment.c_str());
  581. }
  582. }
  583. }
  584. printf("############ print end ############\n");
  585. return;
  586. }
  587. const string & IniFile::GetErrMsg()
  588. {
  589. return errMsg;
  590. }
  591. bool IniFile::StartWith(const string &str, const string &prefix)
  592. {
  593. if (strncmp(str.c_str(), prefix.c_str(), prefix.size()) == 0) {
  594. return true;
  595. }
  596. return false;
  597. }
  598. void IniFile::trimleft(string &str, char c /*=' '*/)
  599. {
  600. int len = str.length();
  601. int i = 0;
  602. while (str[i] == c && str[i] != '\0') {
  603. i++;
  604. }
  605. if (i != 0) {
  606. str = string(str, i, len - i);
  607. }
  608. }
  609. void IniFile::trimright(string &str, char c /*=' '*/)
  610. {
  611. int i = 0;
  612. int len = str.length();
  613. for (i = len - 1; i >= 0; --i) {
  614. if (str[i] != c) {
  615. break;
  616. }
  617. }
  618. str = string(str, 0, i + 1);
  619. }
  620. /*-------------------------------------------------------------------------*/
  621. /**
  622. @brief trim,整理一行字符串,去掉首尾空格
  623. @param str string变量
  624. */
  625. /*--------------------------------------------------------------------------*/
  626. void IniFile::trim(string &str)
  627. {
  628. int len = str.length();
  629. int i = 0;
  630. while ((i < len) && isspace(str[i]) && (str[i] != '\0')) {
  631. i++;
  632. }
  633. if (i != 0) {
  634. str = string(str, i, len - i);
  635. }
  636. len = str.length();
  637. for (i = len - 1; i >= 0; --i) {
  638. if (!isspace(str[i])) {
  639. break;
  640. }
  641. }
  642. str = string(str, 0, i + 1);
  643. }
  644. /*-------------------------------------------------------------------------*/
  645. /**
  646. @brief split,用分隔符切割字符串
  647. @param str 输入字符串
  648. @param left_str 分隔后得到的左字符串
  649. @param right_str 分隔后得到的右字符串(不包含seperator)
  650. @param seperator 分隔符
  651. @return pos
  652. */
  653. /*--------------------------------------------------------------------------*/
  654. bool IniFile::split(const string &str, const string &sep, string *pleft, string *pright)
  655. {
  656. size_t pos = str.find(sep);
  657. string left, right;
  658. if (pos != string::npos) {
  659. left = string(str, 0, pos);
  660. right = string(str, pos+1);
  661. trim(left);
  662. trim(right);
  663. *pleft = left;
  664. *pright = right;
  665. return true;
  666. } else {
  667. left = str;
  668. right = "";
  669. trim(left);
  670. *pleft = left;
  671. *pright = right;
  672. return false;
  673. }
  674. }
  675. bool IniFile::StringCmpIgnoreCase(const string &str1, const string &str2)
  676. {
  677. string a = str1;
  678. string b = str2;
  679. transform(a.begin(), a.end(), a.begin(), towupper);
  680. transform(b.begin(), b.end(), b.begin(), towupper);
  681. return (a == b);
  682. }
  683. static AX_S32 str2array(const AX_CHAR *pszInput, AX_F64 *pszOut, AX_S32 maxSize)
  684. {
  685. AX_CHAR *pszData = strdup(pszInput);
  686. AX_CHAR *pszToken = NULL;
  687. AX_S32 szCnt = 0;
  688. AX_CHAR *p = pszData;
  689. while (p && *p != '\0') {
  690. if (*p == '[' || *p == ']') {
  691. *p = ' ';
  692. }
  693. p++;
  694. }
  695. const AX_CHAR *pszDelimiters = ",";
  696. pszToken = strtok(pszData, pszDelimiters);
  697. while(pszToken) {
  698. if (szCnt >= maxSize) {
  699. break;
  700. }
  701. pszOut[szCnt++] = (AX_F64)strtod(pszToken, NULL);
  702. pszToken = strtok(NULL, pszDelimiters);
  703. }
  704. free(pszData);
  705. return szCnt;
  706. }
  707. } /* namespace inifile */
  708. /* 打开并解析一个名为fname的INI文件 */
  709. AX_S32 AX_INI_Load(const AX_CHAR *fname, AX_INI_HANDLE *handle)
  710. {
  711. if (!fname || !handle) {
  712. return -1;
  713. }
  714. IniFile *f = new IniFile;
  715. if (!f) {
  716. return -1;
  717. }
  718. std::string strIniFile = fname;
  719. AX_S32 ret = f->Load(strIniFile);
  720. if (0 != ret) {
  721. ALOGE("load %s fail", strIniFile.c_str());
  722. return ret;
  723. }
  724. *handle = (AX_INI_HANDLE)f;
  725. return 0;
  726. }
  727. /* 关闭文件 */
  728. AX_S32 AX_INI_Close(AX_INI_HANDLE handle)
  729. {
  730. if (!handle) {
  731. return -1;
  732. }
  733. IniFile *f = (IniFile *)handle;
  734. delete f;
  735. return 0;
  736. }
  737. /* 将内容保存到当前文件 */
  738. AX_S32 AX_INI_Save(AX_INI_HANDLE handle)
  739. {
  740. if (!handle) {
  741. return -1;
  742. }
  743. IniFile *f = (IniFile *)handle;
  744. AX_S32 ret = f->Save();
  745. return ret;
  746. }
  747. /* 将内容另存到一个名为fname的文件 */
  748. AX_S32 AX_INI_SaveAs(AX_INI_HANDLE handle, const AX_CHAR *fname)
  749. {
  750. if (!handle) {
  751. return -1;
  752. }
  753. IniFile *f = (IniFile *)handle;
  754. AX_S32 ret = f->SaveAs(fname);
  755. return ret;
  756. }
  757. /* 获取section段第一个键为key的string值,成功返回0,否则返回错误码 */
  758. AX_S32 AX_INI_GetStringValue(AX_INI_HANDLE handle, const AX_CHAR *section, const AX_CHAR *key, const AX_CHAR **value)
  759. {
  760. if (!handle) {
  761. return -1;
  762. }
  763. IniFile *f = (IniFile *)handle;
  764. static string strValue;
  765. AX_S32 ret = f->GetStringValue(section, key, &strValue);
  766. *value = (const AX_CHAR *)strValue.c_str();
  767. return ret;
  768. }
  769. /* 获取section段第一个键为key的数组,成功返回0,否则返回错误码 */
  770. AX_S32 AX_INI_GetArrayValue(AX_INI_HANDLE handle, const AX_CHAR *section, const AX_CHAR *key, AX_F64 *value, AX_S32 *valueSize, AX_S32 maxSize)
  771. {
  772. if (!handle) {
  773. return -1;
  774. }
  775. IniFile *f = (IniFile *)handle;
  776. string strValue;
  777. AX_S32 ret = f->GetStringValue(section, key, &strValue);
  778. *valueSize = str2array(strValue.c_str(), value, maxSize);
  779. return ret;
  780. }
  781. /* 获取section段第一个键为key的AX_S32值,成功返回0,否则返回错误码 */
  782. AX_S32 AX_INI_GetIntValue(AX_INI_HANDLE handle, const AX_CHAR *section, const AX_CHAR *key, AX_S32 *value)
  783. {
  784. if (!handle) {
  785. return -1;
  786. }
  787. IniFile *f = (IniFile *)handle;
  788. AX_S32 ret = f->GetIntValue(section, key, value);
  789. return ret;
  790. }
  791. /* 获取section段第一个键为key的double值,成功返回0,否则返回错误码 */
  792. AX_S32 AX_INI_GetDoubleValue(AX_INI_HANDLE handle, const AX_CHAR *section, const AX_CHAR *key, AX_F64 *value)
  793. {
  794. if (!handle) {
  795. return -1;
  796. }
  797. IniFile *f = (IniFile *)handle;
  798. AX_S32 ret = f->GetDoubleValue(section, key, value);
  799. return ret;
  800. }
  801. /* 获取section段第一个键为key的AX_BOOL值,成功返回0,否则返回错误码 */
  802. AX_S32 AX_INI_GetBoolValue(AX_INI_HANDLE handle, const AX_CHAR *section, const AX_CHAR *key, AX_BOOL *value)
  803. {
  804. if (!handle) {
  805. return -1;
  806. }
  807. IniFile *f = (IniFile *)handle;
  808. bool t = false;
  809. AX_S32 ret = f->GetBoolValue(section, key, &t);
  810. *value = (AX_BOOL)t;
  811. return ret;
  812. }
  813. /* 获取注释,如果key=""则获取段注释 */
  814. AX_S32 AX_INI_GetComment(AX_INI_HANDLE handle, const AX_CHAR *section, const AX_CHAR *key, const AX_CHAR **comment)
  815. {
  816. if (!handle) {
  817. return -1;
  818. }
  819. IniFile *f = (IniFile *)handle;
  820. static string strValue;
  821. AX_S32 ret = f->GetComment(section, key, &strValue);
  822. *comment = (const AX_CHAR *)strValue.c_str();
  823. return ret;
  824. }
  825. /* 获取行尾注释,如果key=""则获取段的行尾注释 */
  826. AX_S32 AX_INI_GetRightComment(AX_INI_HANDLE handle, const AX_CHAR *section, const AX_CHAR *key, const AX_CHAR **rightComment)
  827. {
  828. if (!handle) {
  829. return -1;
  830. }
  831. IniFile *f = (IniFile *)handle;
  832. static string strValue;
  833. AX_S32 ret = f->GetRightComment(section, key, &strValue);
  834. *rightComment = (const AX_CHAR *)strValue.c_str();
  835. return ret;
  836. }
  837. /* 获取section段第一个键为key的string值,成功返回获取的值,否则返回默认值 */
  838. AX_S32 AX_INI_GetStringValueOrDefault(AX_INI_HANDLE handle, const AX_CHAR *section, const AX_CHAR *key, const AX_CHAR **value, const AX_CHAR *defaultValue)
  839. {
  840. if (!handle) {
  841. return -1;
  842. }
  843. IniFile *f = (IniFile *)handle;
  844. static string strValue;
  845. f->GetStringValueOrDefault(section, key, &strValue, defaultValue);
  846. *value = (const AX_CHAR *)strValue.c_str();
  847. return 0;
  848. }
  849. /* 获取section段第一个键为key的AX_S32值,成功返回获取的值,否则返回默认值 */
  850. AX_S32 AX_INI_GetIntValueOrDefault(AX_INI_HANDLE handle, const AX_CHAR *section, const AX_CHAR *key, AX_S32 *value, AX_S32 defaultValue)
  851. {
  852. if (!handle) {
  853. return -1;
  854. }
  855. IniFile *f = (IniFile *)handle;
  856. f->GetIntValueOrDefault(section, key, value, defaultValue);
  857. return 0;
  858. }
  859. /* 获取section段第一个键为key的double值,成功返回获取的值,否则返回默认值 */
  860. AX_S32 AX_INI_GetDoubleValueOrDefault(AX_INI_HANDLE handle, const AX_CHAR *section, const AX_CHAR *key, AX_F64 *value, AX_F64 defaultValue)
  861. {
  862. if (!handle) {
  863. return -1;
  864. }
  865. IniFile *f = (IniFile *)handle;
  866. f->GetDoubleValueOrDefault(section, key, value, defaultValue);
  867. return 0;
  868. }
  869. /* 获取section段第一个键为key的AX_BOOL值,成功返回获取的值,否则返回默认值 */
  870. AX_S32 AX_INI_GetBoolValueOrDefault(AX_INI_HANDLE handle, const AX_CHAR *section, const AX_CHAR *key, AX_BOOL *value, AX_BOOL defaultValue)
  871. {
  872. if (!handle) {
  873. return -1;
  874. }
  875. IniFile *f = (IniFile *)handle;
  876. bool t = false;
  877. f->GetBoolValueOrDefault(section, key, &t, (bool)defaultValue);
  878. *value = (AX_BOOL)t;
  879. return 0;
  880. }
  881. /* 获取section个数,至少存在一个空section */
  882. AX_S32 AX_INI_GetSectionNum(AX_INI_HANDLE handle)
  883. {
  884. if (!handle) {
  885. return -1;
  886. }
  887. IniFile *f = (IniFile *)handle;
  888. return (AX_BOOL)f->GetSectionNum();
  889. }
  890. /* 是否存在某个section */
  891. AX_BOOL AX_INI_HasSection(AX_INI_HANDLE handle, const AX_CHAR *section)
  892. {
  893. if (!handle) {
  894. return AX_FALSE;
  895. }
  896. IniFile *f = (IniFile *)handle;
  897. return (AX_BOOL)f->HasSection(section);
  898. }
  899. /* 是否存在某个key */
  900. AX_BOOL AX_INI_HasKey(AX_INI_HANDLE handle, const AX_CHAR *section, const AX_CHAR *key)
  901. {
  902. if (!handle) {
  903. return AX_FALSE;
  904. }
  905. IniFile *f = (IniFile *)handle;
  906. return (AX_BOOL)f->HasKey(section, key);
  907. }
  908. /* 设置字符串值 */
  909. AX_S32 AX_INI_SetStringValue(AX_INI_HANDLE handle, const AX_CHAR *section, const AX_CHAR *key, const AX_CHAR *value)
  910. {
  911. if (!handle) {
  912. return -1;
  913. }
  914. IniFile *f = (IniFile *)handle;
  915. AX_S32 ret = f->SetStringValue(section, key, value);
  916. return ret;
  917. }
  918. /* 设置整形值 */
  919. AX_S32 AX_INI_SetIntValue(AX_INI_HANDLE handle, const AX_CHAR *section, const AX_CHAR *key, AX_S32 value)
  920. {
  921. if (!handle) {
  922. return -1;
  923. }
  924. IniFile *f = (IniFile *)handle;
  925. AX_S32 ret = f->SetIntValue(section, key, value);
  926. return ret;
  927. }
  928. /* 设置浮点数值 */
  929. AX_S32 AX_INI_SetDoubleValue(AX_INI_HANDLE handle, const AX_CHAR *section, const AX_CHAR *key, AX_F64 value)
  930. {
  931. if (!handle) {
  932. return -1;
  933. }
  934. IniFile *f = (IniFile *)handle;
  935. AX_S32 ret = f->SetDoubleValue(section, key, value);
  936. return ret;
  937. }
  938. /* 设置布尔值 */
  939. AX_S32 AX_INI_SetBoolValue(AX_INI_HANDLE handle, const AX_CHAR *section, const AX_CHAR *key, AX_BOOL value)
  940. {
  941. if (!handle) {
  942. return -1;
  943. }
  944. IniFile *f = (IniFile *)handle;
  945. AX_S32 ret = f->SetBoolValue(section, key, value);
  946. return ret;
  947. }
  948. /* 设置注释,如果key=""则设置段注释 */
  949. AX_S32 AX_INI_SetComment(AX_INI_HANDLE handle, const AX_CHAR *section, const AX_CHAR *key, const AX_CHAR *comment)
  950. {
  951. if (!handle) {
  952. return -1;
  953. }
  954. IniFile *f = (IniFile *)handle;
  955. AX_S32 ret = f->SetComment(section, key, comment);
  956. return ret;
  957. }
  958. /* 设置行尾注释,如果key=""则设置段的行尾注释 */
  959. AX_S32 AX_INI_SetRightComment(AX_INI_HANDLE handle, const AX_CHAR *section, const AX_CHAR *key, const AX_CHAR *rightComment)
  960. {
  961. if (!handle) {
  962. return -1;
  963. }
  964. IniFile *f = (IniFile *)handle;
  965. AX_S32 ret = f->SetRightComment(section, key, rightComment);
  966. return ret;
  967. }
  968. /* 删除段 */
  969. AX_S32 AX_INI_DeleteSection(AX_INI_HANDLE handle, const AX_CHAR *section)
  970. {
  971. if (!handle) {
  972. return -1;
  973. }
  974. IniFile *f = (IniFile *)handle;
  975. f->DeleteSection(section);
  976. return 0;
  977. }
  978. /* 删除特定段的特定参数 */
  979. AX_S32 AX_INI_DeleteKey(AX_INI_HANDLE handle, const AX_CHAR *section, const AX_CHAR *key)
  980. {
  981. if (!handle) {
  982. return -1;
  983. }
  984. IniFile *f = (IniFile *)handle;
  985. f->DeleteKey(section, key);
  986. return 0;
  987. }
  988. /*设置注释分隔符,默认为"#" */
  989. AX_S32 AX_INI_SetCommentDelimiter(AX_INI_HANDLE handle, const AX_CHAR *delimiter)
  990. {
  991. if (!handle) {
  992. return -1;
  993. }
  994. IniFile *f = (IniFile *)handle;
  995. f->SetCommentDelimiter(delimiter);
  996. return 0;
  997. }