inifiles.pp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816
  1. {
  2. $Id$
  3. This file is part of the Free Component Library (FCL)
  4. Copyright (c) 1999-2000 Erik WachtMeester.
  5. File which provides TIniFile and friends.
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {* Original disclaimer:
  13. * FCL inifiles.pp rewrite by Erik Wachtmeester ([email protected])
  14. *
  15. * Proposed replacement for inifiles.pp v 1.8
  16. *
  17. * This version is Borland Delphi 5 compatible, implementing the classes
  18. * TCustomIniFile, TIniFile and TMemIniFile, with all the public
  19. * properties and methods that Delphi 5 implements.
  20. *
  21. * (inifiles.pp v 1.8 only implements TIniFile with some properties and
  22. * methods missing, and some functionality added)
  23. *
  24. * In order to stay compatible with v 1.8, I added:
  25. * - TIniFile can be created and loaded from, and saved to a stream.
  26. * - ReadSectionRaw method (although it doesn't add empty lines to the
  27. * TStrings recipient like v 1.8, since empty lines aren't stored in
  28. * the SectionList object structure)
  29. * - ReadInteger supports '0x' type hex formats
  30. * - Comment support (this isn't standard in ini files)
  31. * - EscapeLineFeeds property
  32. *
  33. * Since the SectionList object structure is very different from the
  34. * way Delphi 5 accesses ini files (Delphi mostly uses Windows calls
  35. * like GetPrivateProfileString, etc.) it's completely platform
  36. * independant, and probably faster.
  37. * The only drawback is memory consumption: all sections, keys and
  38. * values are kept in memory. But same goes for inifiles.pp v 1.8
  39. * (the FFileBuffer member) and for Delphi's TMemIniFile.
  40. * Anyway, Windows restricts ini files to 64K max, so this shouldn't be
  41. * too much of a problem.
  42. *
  43. *}
  44. unit IniFiles;
  45. {$mode objfpc}
  46. {$H+}
  47. interface
  48. uses classes, sysutils;
  49. type
  50. TIniFileKey = class
  51. FIdent: string;
  52. FValue: string;
  53. public
  54. constructor Create(AIdent, AValue: string);
  55. property Ident: string read FIdent write FIdent;
  56. property Value: string read FValue write FValue;
  57. end;
  58. TIniFileKeyList = class(TList)
  59. private
  60. function GetItem(Index: integer): TIniFileKey;
  61. function KeyByName(AName: string): TIniFileKey;
  62. public
  63. procedure Clear;
  64. property Items[Index: integer]: TIniFileKey read GetItem; default;
  65. end;
  66. TIniFileSection = class
  67. FName: string;
  68. FKeyList: TIniFileKeyList;
  69. public
  70. constructor Create(AName: string);
  71. destructor Destroy; override;
  72. property Name: string read FName;
  73. property KeyList: TIniFileKeyList read FKeyList;
  74. end;
  75. TIniFileSectionList = class(TList)
  76. private
  77. function GetItem(Index: integer): TIniFileSection;
  78. function SectionByName(AName: string): TIniFileSection;
  79. public
  80. procedure Clear;
  81. property Items[Index: integer]: TIniFileSection read GetItem; default;
  82. end;
  83. TCustomIniFile = class
  84. FFileName: string;
  85. FSectionList: TIniFileSectionList;
  86. FEscapeLineFeeds: boolean;
  87. public
  88. constructor Create(const AFileName: string);
  89. destructor Destroy; override;
  90. function SectionExists(const Section: string): Boolean; virtual;
  91. function ReadString(const Section, Ident, Default: string): string; virtual; abstract;
  92. procedure WriteString(const Section, Ident, Value: String); virtual; abstract;
  93. function ReadInteger(const Section, Ident: string; Default: Longint): Longint; virtual;
  94. procedure WriteInteger(const Section, Ident: string; Value: Longint); virtual;
  95. function ReadBool(const Section, Ident: string; Default: Boolean): Boolean; virtual;
  96. procedure WriteBool(const Section, Ident: string; Value: Boolean); virtual;
  97. function ReadDate(const Section, Ident: string; Default: TDateTime): TDateTime; virtual;
  98. function ReadDateTime(const Section, Ident: string; Default: TDateTime): TDateTime; virtual;
  99. function ReadFloat(const Section, Ident: string; Default: Double): Double; virtual;
  100. function ReadTime(const Section, Ident: string; Default: TDateTime): TDateTime; virtual;
  101. procedure WriteDate(const Section, Ident: string; Value: TDateTime); virtual;
  102. procedure WriteDateTime(const Section, Ident: string; Value: TDateTime); virtual;
  103. procedure WriteFloat(const Section, Ident: string; Value: Double); virtual;
  104. procedure WriteTime(const Section, Ident: string; Value: TDateTime); virtual;
  105. procedure ReadSection(const Section: string; Strings: TStrings); virtual; abstract;
  106. procedure ReadSections(Strings: TStrings); virtual; abstract;
  107. procedure ReadSectionValues(const Section: string; Strings: TStrings); virtual; abstract;
  108. procedure EraseSection(const Section: string); virtual; abstract;
  109. procedure DeleteKey(const Section, Ident: String); virtual; abstract;
  110. procedure UpdateFile; virtual; abstract;
  111. function ValueExists(const Section, Ident: string): Boolean; virtual;
  112. property FileName: string read FFileName;
  113. property EscapeLineFeeds: boolean read FEscapeLineFeeds write FEscapeLineFeeds;
  114. end;
  115. TIniFile = class(TCustomIniFile)
  116. FStream: TStream;
  117. private
  118. procedure FillSectionList(AStrings: TStrings);
  119. public
  120. constructor Create(const AFileName: string);
  121. constructor Create(AStream: TStream);
  122. function ReadString(const Section, Ident, Default: string): string; override;
  123. procedure WriteString(const Section, Ident, Value: String); override;
  124. procedure ReadSection(const Section: string; Strings: TStrings); override;
  125. procedure ReadSectionRaw(const Section: string; Strings: TStrings);
  126. procedure ReadSections(Strings: TStrings); override;
  127. procedure ReadSectionValues(const Section: string; Strings: TStrings); override;
  128. procedure EraseSection(const Section: string); override;
  129. procedure DeleteKey(const Section, Ident: String); override;
  130. procedure UpdateFile; override;
  131. property Stream: TStream read FStream;
  132. end;
  133. TMemIniFile = class(TIniFile)
  134. public
  135. procedure Clear;
  136. procedure GetStrings(List: TStrings);
  137. procedure Rename(const AFileName: string; Reload: Boolean);
  138. procedure SetStrings(List: TStrings);
  139. end;
  140. implementation
  141. const
  142. Brackets : array[0..1] of Char = ('[', ']');
  143. Separator : Char = '=';
  144. Comment : Char = ';';
  145. LF_Escape : Char = '\';
  146. function CharToBool(AChar: char): boolean;
  147. begin
  148. Result := (Achar = '1');
  149. end;
  150. function BoolToChar(ABool: boolean): char;
  151. begin
  152. if ABool then
  153. Result := '1'
  154. else
  155. Result := '0';
  156. end;
  157. function IsComment(AString: string): boolean;
  158. begin
  159. Result := False;
  160. if AString > '' then
  161. Result := (Copy(AString, 1, 1) = Comment);
  162. end;
  163. { TIniFileKey }
  164. constructor TIniFileKey.Create(AIdent, AValue: string);
  165. begin
  166. FIdent := AIdent;
  167. FValue := AValue;
  168. end;
  169. { TIniFileKeyList }
  170. function TIniFileKeyList.GetItem(Index: integer): TIniFileKey;
  171. begin
  172. Result := nil;
  173. if (Index >= 0) and (Index < Count) then
  174. Result := TIniFileKey(inherited Items[Index]);
  175. end;
  176. function TIniFileKeyList.KeyByName(AName: string): TIniFileKey;
  177. var
  178. i: integer;
  179. begin
  180. Result := nil;
  181. if (AName > '') and not IsComment(AName) then
  182. for i := 0 to Count-1 do
  183. if CompareText(Items[i].Ident, AName) = 0 then begin
  184. Result := Items[i];
  185. Break;
  186. end;
  187. end;
  188. procedure TIniFileKeyList.Clear;
  189. var
  190. i: integer;
  191. begin
  192. for i := Count-1 downto 0 do
  193. Items[i].Free;
  194. inherited Clear;
  195. end;
  196. { TIniFileSection }
  197. constructor TIniFileSection.Create(AName: string);
  198. begin
  199. FName := AName;
  200. FKeyList := TIniFileKeyList.Create;
  201. end;
  202. destructor TIniFileSection.Destroy;
  203. begin
  204. FKeyList.Free;
  205. end;
  206. { TIniFileSectionList }
  207. function TIniFileSectionList.GetItem(Index: integer): TIniFileSection;
  208. begin
  209. Result := nil;
  210. if (Index >= 0) and (Index < Count) then
  211. Result := TIniFileSection(inherited Items[Index]);
  212. end;
  213. function TIniFileSectionList.SectionByName(AName: string): TIniFileSection;
  214. var
  215. i: integer;
  216. begin
  217. Result := nil;
  218. if (AName > '') and not IsComment(AName) then
  219. for i := 0 to Count-1 do
  220. if CompareText(Items[i].Name, AName) = 0 then begin
  221. Result := Items[i];
  222. Break;
  223. end;
  224. end;
  225. procedure TIniFileSectionList.Clear;
  226. var
  227. i: integer;
  228. begin
  229. for i := Count-1 downto 0 do
  230. Items[i].Free;
  231. inherited Clear;
  232. end;
  233. { TCustomIniFile }
  234. constructor TCustomIniFile.Create(const AFileName: string);
  235. begin
  236. FFileName := AFileName;
  237. FSectionList := TIniFileSectionList.Create;
  238. FEscapeLineFeeds := False;
  239. end;
  240. destructor TCustomIniFile.Destroy;
  241. begin
  242. FSectionList.Free;
  243. inherited Destroy;
  244. end;
  245. function TCustomIniFile.SectionExists(const Section: string): Boolean;
  246. begin
  247. Result := (FSectionList.SectionByName(Section) <> nil);
  248. end;
  249. function TCustomIniFile.ReadInteger(const Section, Ident: string; Default: Longint): Longint;
  250. var
  251. s: string;
  252. begin
  253. Result := Default;
  254. s := ReadString(Section, Ident, '');
  255. if s > '' then try
  256. // convert hex string
  257. if Pos('0X', UpperCase(s)) = 1 then
  258. s := '$' + Copy(s, 3, Length(s) - 2);
  259. Result := StrToInt(s);
  260. except
  261. on EConvertError do
  262. else raise;
  263. end;
  264. end;
  265. procedure TCustomIniFile.WriteInteger(const Section, Ident: string; Value: Longint);
  266. begin
  267. WriteString(Section, Ident, IntToStr(Value));
  268. end;
  269. function TCustomIniFile.ReadBool(const Section, Ident: string; Default: Boolean): Boolean;
  270. var
  271. s: string;
  272. begin
  273. Result := Default;
  274. s := ReadString(Section, Ident, '');
  275. if s > '' then
  276. Result := CharToBool(s[1]);
  277. end;
  278. procedure TCustomIniFile.WriteBool(const Section, Ident: string; Value: Boolean);
  279. begin
  280. WriteString(Section, Ident, BoolToChar(Value));
  281. end;
  282. function TCustomIniFile.ReadDate(const Section, Ident: string; Default: TDateTime): TDateTime;
  283. var
  284. s: string;
  285. begin
  286. Result := Default;
  287. s := ReadString(Section, Ident, '');
  288. if s > '' then try
  289. Result := StrToDate(s);
  290. except
  291. on EConvertError do
  292. else raise;
  293. end;
  294. end;
  295. function TCustomIniFile.ReadDateTime(const Section, Ident: string; Default: TDateTime): TDateTime;
  296. var
  297. s: string;
  298. begin
  299. Result := Default;
  300. s := ReadString(Section, Ident, '');
  301. if s > '' then try
  302. Result := StrToDateTime(s);
  303. except
  304. on EConvertError do
  305. else raise;
  306. end;
  307. end;
  308. function TCustomIniFile.ReadFloat(const Section, Ident: string; Default: Double): Double;
  309. var
  310. s: string;
  311. begin
  312. Result := Default;
  313. s := ReadString(Section, Ident, '');
  314. if s > '' then try
  315. Result := StrToFloat(s);
  316. except
  317. on EConvertError do
  318. else raise;
  319. end;
  320. end;
  321. function TCustomIniFile.ReadTime(const Section, Ident: string; Default: TDateTime): TDateTime;
  322. var
  323. s: string;
  324. begin
  325. Result := Default;
  326. s := ReadString(Section, Ident, '');
  327. if s > '' then try
  328. Result := StrToTime(s);
  329. except
  330. on EConvertError do
  331. else raise;
  332. end;
  333. end;
  334. procedure TCustomIniFile.WriteDate(const Section, Ident: string; Value: TDateTime);
  335. begin
  336. WriteString(Section, Ident, DateToStr(Value));
  337. end;
  338. procedure TCustomIniFile.WriteDateTime(const Section, Ident: string; Value: TDateTime);
  339. begin
  340. WriteString(Section, Ident, DateTimeToStr(Value));
  341. end;
  342. procedure TCustomIniFile.WriteFloat(const Section, Ident: string; Value: Double);
  343. begin
  344. WriteString(Section, Ident, FloatToStr(Value));
  345. end;
  346. procedure TCustomIniFile.WriteTime(const Section, Ident: string; Value: TDateTime);
  347. begin
  348. WriteString(Section, Ident, TimeToStr(Value));
  349. end;
  350. function TCustomIniFile.ValueExists(const Section, Ident: string): Boolean;
  351. var
  352. oSection: TIniFileSection;
  353. begin
  354. Result := False;
  355. oSection := FSectionList.SectionByName(Section);
  356. if oSection <> nil then
  357. Result := (oSection.KeyList.KeyByName(Ident) <> nil);
  358. end;
  359. { TIniFile }
  360. constructor TIniFile.Create(const AFileName: string);
  361. var
  362. slLines: TStringList;
  363. begin
  364. inherited Create(AFileName);
  365. FStream := nil;
  366. slLines := TStringList.Create;
  367. try
  368. if FileExists(FFileName) then begin
  369. // read the ini file values
  370. slLines.LoadFromFile(FFileName);
  371. FillSectionList(slLines);
  372. end else
  373. // create a new ini file
  374. slLines.SaveToFile(FFileName);
  375. finally
  376. slLines.Free;
  377. end;
  378. end;
  379. constructor TIniFile.Create(AStream: TStream);
  380. var
  381. slLines: TStringList;
  382. begin
  383. inherited Create('');
  384. FStream := AStream;
  385. slLines := TStringList.Create;
  386. try
  387. // read the ini file values
  388. slLines.LoadFromStream(FStream);
  389. FillSectionList(slLines);
  390. finally
  391. slLines.Free;
  392. end;
  393. end;
  394. procedure TIniFile.FillSectionList(AStrings: TStrings);
  395. var
  396. i,j: integer;
  397. sLine, sIdent, sValue: string;
  398. oSection: TIniFileSection;
  399. procedure RemoveBackslashes;
  400. var
  401. i: integer;
  402. s: string;
  403. bAppendNextLine, bAppended: boolean;
  404. begin
  405. AStrings.BeginUpdate;
  406. try
  407. i := 0;
  408. bAppendNextLine := False;
  409. while i < AStrings.Count do begin
  410. s := AStrings[i];
  411. bAppended := False;
  412. if bAppendNextLine then begin
  413. // add line to previous line
  414. AStrings[i-1] := AStrings[i-1] + Trim(s);
  415. AStrings.Delete(i);
  416. s := AStrings[i-1];
  417. bAppended := True;
  418. end;
  419. bAppendNextLine := (Copy(s, Length(s), 1) = LF_Escape);
  420. if bAppendNextLine then
  421. // remove backslash
  422. AStrings[i] := Copy(s, 1, Length(s) - 1);
  423. if not bAppended then
  424. Inc(i);
  425. end;
  426. finally
  427. AStrings.EndUpdate;
  428. end;
  429. end;
  430. begin
  431. oSection := nil;
  432. FSectionList.Clear;
  433. if FEscapeLineFeeds then
  434. RemoveBackslashes;
  435. for i := 0 to AStrings.Count-1 do begin
  436. sLine := Trim(AStrings[i]);
  437. if sLine > '' then
  438. if IsComment(sLine) and (oSection = nil) then begin
  439. // comment at the beginning of the ini file
  440. oSection := TIniFileSection.Create(sLine);
  441. FSectionList.Add(oSection);
  442. end;
  443. if (Copy(sLine, 1, 1) = Brackets[0]) and (Copy(sLine, length(sLine), 1) = Brackets[1]) then begin
  444. // regular section
  445. oSection := TIniFileSection.Create(Copy(sLine, 2, Length(sLine) - 2));
  446. FSectionList.Add(oSection);
  447. end else if oSection <> nil then begin
  448. if IsComment(sLine) then begin
  449. // comment within a section
  450. sIdent := sLine;
  451. sValue := '';
  452. end else begin
  453. // regular key
  454. j:=Pos(Separator, sLine);
  455. if j=0 then
  456. begin
  457. sIdent:='';
  458. sValue:=sLine
  459. end
  460. else
  461. begin
  462. sIdent:=Trim(Copy(sLine, 1, j - 1));
  463. sValue:=Trim(Copy(sLine, j + 1, Length(sLine) - j));
  464. end;
  465. end;
  466. oSection.KeyList.Add(TIniFileKey.Create(sIdent, sValue));
  467. end;
  468. end;
  469. end;
  470. function TIniFile.ReadString(const Section, Ident, Default: string): string;
  471. var
  472. oSection: TIniFileSection;
  473. oKey: TIniFileKey;
  474. begin
  475. Result := Default;
  476. oSection := FSectionList.SectionByName(Section);
  477. if oSection <> nil then begin
  478. oKey := oSection.KeyList.KeyByName(Ident);
  479. if oKey <> nil then
  480. Result := oKey.Value;
  481. end;
  482. end;
  483. procedure TIniFile.WriteString(const Section, Ident, Value: String);
  484. var
  485. oSection: TIniFileSection;
  486. oKey: TIniFileKey;
  487. begin
  488. if (Section > '') and (Ident > '') then begin
  489. // update or add key
  490. oSection := FSectionList.SectionByName(Section);
  491. if (Value > '') then begin
  492. if oSection = nil then begin
  493. oSection := TIniFileSection.Create(Section);
  494. FSectionList.Add(oSection);
  495. end;
  496. with oSection.KeyList do begin
  497. oKey := KeyByName(Ident);
  498. if oKey <> nil then
  499. oKey.Value := Value
  500. else
  501. oSection.KeyList.Add(TIniFileKey.Create(Ident, Value));
  502. end;
  503. end else if oSection <> nil then begin
  504. // remove key
  505. oKey := oSection.KeyList.KeyByName(Ident);
  506. if oKey <> nil then begin
  507. oSection.KeyList.Remove(oKey);
  508. end;
  509. end;
  510. UpdateFile;
  511. end;
  512. end;
  513. procedure TIniFile.ReadSection(const Section: string; Strings: TStrings);
  514. var
  515. oSection: TIniFileSection;
  516. i: integer;
  517. begin
  518. Strings.BeginUpdate;
  519. try
  520. Strings.Clear;
  521. oSection := FSectionList.SectionByName(Section);
  522. if oSection <> nil then with oSection.KeyList do
  523. for i := 0 to Count-1 do
  524. if not IsComment(Items[i].Ident) then
  525. Strings.Add(Items[i].Ident);
  526. finally
  527. Strings.EndUpdate;
  528. end;
  529. end;
  530. procedure TIniFile.ReadSectionRaw(const Section: string; Strings: TStrings);
  531. var
  532. oSection: TIniFileSection;
  533. i: integer;
  534. begin
  535. Strings.BeginUpdate;
  536. try
  537. Strings.Clear;
  538. oSection := FSectionList.SectionByName(Section);
  539. if oSection <> nil then with oSection.KeyList do
  540. for i := 0 to Count-1 do
  541. if not IsComment(Items[i].Ident) then
  542. begin
  543. if Items[i].Ident<>'' then
  544. Strings.Add(Items[i].Ident + Separator +Items[i].Value)
  545. else
  546. Strings.Add(Items[i].Value);
  547. end;
  548. finally
  549. Strings.EndUpdate;
  550. end;
  551. end;
  552. procedure TIniFile.ReadSections(Strings: TStrings);
  553. var
  554. i: integer;
  555. begin
  556. Strings.BeginUpdate;
  557. try
  558. Strings.Clear;
  559. for i := 0 to FSectionList.Count-1 do
  560. if not IsComment(FSectionList[i].Name) then
  561. Strings.Add(FSectionList[i].Name);
  562. finally
  563. Strings.EndUpdate;
  564. end;
  565. end;
  566. procedure TIniFile.ReadSectionValues(const Section: string; Strings: TStrings);
  567. var
  568. oSection: TIniFileSection;
  569. s: string;
  570. i: integer;
  571. begin
  572. Strings.BeginUpdate;
  573. try
  574. Strings.Clear;
  575. oSection := FSectionList.SectionByName(Section);
  576. if oSection <> nil then with oSection.KeyList do
  577. for i := 0 to Count-1 do begin
  578. s := Items[i].Value;
  579. if s > '' then
  580. Strings.Add(s);
  581. end;
  582. finally
  583. Strings.EndUpdate;
  584. end;
  585. end;
  586. procedure TIniFile.EraseSection(const Section: string);
  587. var
  588. oSection: TIniFileSection;
  589. begin
  590. oSection := FSectionList.SectionByName(Section);
  591. if oSection <> nil then begin
  592. oSection.Free;
  593. UpdateFile;
  594. end;
  595. end;
  596. procedure TIniFile.DeleteKey(const Section, Ident: String);
  597. var
  598. oSection: TIniFileSection;
  599. oKey: TIniFileKey;
  600. begin
  601. oSection := FSectionList.SectionByName(Section);
  602. if oSection <> nil then begin
  603. oKey := oSection.KeyList.KeyByName(Ident);
  604. if oKey <> nil then begin
  605. oKey.Free;
  606. UpdateFile;
  607. end;
  608. end;
  609. end;
  610. procedure TIniFile.UpdateFile;
  611. var
  612. slLines: TStringList;
  613. i, j: integer;
  614. begin
  615. slLines := TStringList.Create;
  616. try
  617. for i := 0 to FSectionList.Count-1 do
  618. with FSectionList[i] do begin
  619. if IsComment(Name) then
  620. // comment
  621. slLines.Add(Name)
  622. else
  623. // regular section
  624. slLines.Add(Brackets[0] + Name + Brackets[1]);
  625. for j := 0 to KeyList.Count-1 do
  626. if IsComment(KeyList[j].Ident) then
  627. // comment
  628. slLines.Add(KeyList[j].Ident)
  629. else
  630. // regular key
  631. slLines.Add(KeyList[j].Ident + Separator + KeyList[j].Value);
  632. if (i < FSectionList.Count-1) and not IsComment(Name) then
  633. slLines.Add('');
  634. end;
  635. if FFileName > '' then
  636. slLines.SaveToFile(FFileName)
  637. else if FStream <> nil then
  638. slLines.SaveToStream(FStream);
  639. FillSectionList(slLines);
  640. finally
  641. slLines.Free;
  642. end;
  643. end;
  644. { TMemIniFile }
  645. procedure TMemIniFile.Clear;
  646. begin
  647. FSectionList.Clear;
  648. end;
  649. procedure TMemIniFile.GetStrings(List: TStrings);
  650. var
  651. i, j: integer;
  652. oSection: TIniFileSection;
  653. begin
  654. List.BeginUpdate;
  655. try
  656. for i := 0 to FSectionList.Count-1 do begin
  657. oSection := FSectionList[i];
  658. with oSection do begin
  659. if IsComment(Name) then
  660. List.Add(Name)
  661. else
  662. List.Add(Brackets[0] + Name + Brackets[1]);
  663. for j := 0 to KeyList.Count-1 do begin
  664. if IsComment(KeyList[j].Ident) then
  665. List.Add(KeyList[j].Ident)
  666. else
  667. List.Add(KeyList[j].Ident + Separator + KeyList[j].Value);
  668. end;
  669. end;
  670. if i < FSectionList.Count-1 then
  671. List.Add('');
  672. end;
  673. finally
  674. List.EndUpdate;
  675. end;
  676. end;
  677. procedure TMemIniFile.Rename(const AFileName: string; Reload: Boolean);
  678. var
  679. slLines: TStringList;
  680. begin
  681. FFileName := AFileName;
  682. FStream := nil;
  683. if Reload then begin
  684. slLines := TStringList.Create;
  685. try
  686. slLines.LoadFromFile(FFileName);
  687. FillSectionList(slLines);
  688. finally
  689. slLines.Free;
  690. end;
  691. end;
  692. end;
  693. procedure TMemIniFile.SetStrings(List: TStrings);
  694. begin
  695. FillSectionList(List);
  696. end;
  697. end.
  698. {
  699. $Log$
  700. Revision 1.1 2000-07-13 06:31:30 michael
  701. + Initial import
  702. Revision 1.13 2000/06/30 22:11:25 peter
  703. * fixed truncating of last char
  704. Revision 1.12 2000/05/11 14:50:01 peter
  705. * fixed getting of value when there was no separator. But it still
  706. doesn't work for fpcmake
  707. Revision 1.11 2000/05/10 16:43:43 michael
  708. + New implementation by Erik WachtMeester
  709. Revision ?.? 2000/04/29 13:51:00 erik
  710. * fully rewritten for D5 compatibility and SectionList object structure
  711. Revision 1.8 2000/01/07 01:24:33 peter
  712. * updated copyright to 2000
  713. Revision 1.7 2000/01/06 01:20:33 peter
  714. * moved out of packages/ back to topdir
  715. Revision 1.1 2000/01/03 19:33:07 peter
  716. * moved to packages dir
  717. Revision 1.5 1999/11/23 09:50:51 peter
  718. * load/save stream support
  719. Revision 1.4 1999/11/08 15:01:38 peter
  720. * fpcmake support
  721. Revision 1.3 1999/11/02 23:58:37 peter
  722. * comment support
  723. * readsectionraw method
  724. Revision 1.2 1999/04/29 16:21:54 michael
  725. + Default mode Hugestrings
  726. Revision 1.1 1999/04/08 15:44:10 michael
  727. + Donated by Michael A. Hess
  728. Initial Release 1999/04/07 MAH
  729. }