makeini.pp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. {
  2. $Id$
  3. This file is part of the Free Component Library (FCL)
  4. Copyright (c) 1999-2000 by Michael A. Hess
  5. Old inifiles unit adapted for fpcmake
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. **********************************************************************}
  10. unit MakeIni;
  11. {$mode objfpc}
  12. {$H+}
  13. interface
  14. uses Classes;
  15. type
  16. { TIniFile class }
  17. TIniFile = class(TObject)
  18. private
  19. FEscapeLineFeeds : Boolean;
  20. FFileName : string;
  21. FStream : TStream;
  22. FFileBuffer : TStringList;
  23. function GetName(const line : string) : string;
  24. function GetValue(const line, name : string) : string;
  25. function IsComment(const line : string) : boolean;
  26. function IsSection(const line : string) : boolean;
  27. function GetSectionIndex(const section : string) : integer;
  28. protected
  29. procedure SetFileName(const fn:string);
  30. procedure SetStream(s:TStream);
  31. procedure LoadFromFile;
  32. procedure SaveToFile;
  33. procedure LoadFromStream;
  34. procedure SaveToStream;
  35. public
  36. constructor Create(const theFileName : string);
  37. constructor Create(s:TStream);
  38. destructor Destroy; override;
  39. procedure DeleteKey(const section, ident : string);
  40. procedure EraseSection(const section : string);
  41. function ReadBool(const section, ident : string; defaultValue : boolean) : boolean;
  42. function ReadInteger(const section, ident : string; defaultValue : longint) : longint;
  43. procedure ReadSection(const section : string; strings : TStrings);
  44. procedure ReadSections(strings : TStrings);
  45. procedure ReadSectionValues(const section : string; strings : TStrings);
  46. procedure ReadSectionRaw(const section : string; strings : TStrings);
  47. function ReadString(const section, ident, defaultValue : string) : string;
  48. procedure WriteBool(const section, ident : string; value : boolean);
  49. procedure WriteInteger(const section, ident : string; value : longint);
  50. procedure WriteString(const section, ident, value : string);
  51. property FileName : String read FFileName;
  52. property EscapeLineFeeds : Boolean Read FEscapeLineFeeds Write FEscapeLineFeeds default false;
  53. end;
  54. implementation
  55. uses SysUtils;
  56. const
  57. brackets : array[0..1] of Char = ('[', ']');
  58. separator : Char = '=';
  59. comment : Char = ';';
  60. { TIniFile }
  61. constructor TIniFile.Create(const theFileName : string);
  62. begin
  63. FFileName := theFileName;
  64. FStream:=nil;
  65. FEscapeLineFeeds:=False;
  66. FFileBuffer := TStringList.Create;
  67. if FileExists(fileName) then
  68. LoadFromFile;
  69. end;
  70. constructor TIniFile.Create(s:TStream);
  71. begin
  72. FFileName := '';
  73. FStream:=s;
  74. FEscapeLineFeeds:=False;
  75. FFileBuffer := TStringList.Create;
  76. LoadFromStream;
  77. end;
  78. destructor TIniFile.Destroy;
  79. begin
  80. FFileBuffer.Free;
  81. end;
  82. function TIniFile.GetName(const line : string) : string;
  83. var
  84. index,index2 : integer;
  85. begin
  86. Result := '';
  87. index := Pos(separator, line);
  88. if index <> 0 then
  89. begin
  90. index2:=Pos(comment, line);
  91. if (index2=0) or (index2>index) then
  92. result := Trim(Copy(line, 1, index - 1));
  93. end;
  94. end;
  95. function TIniFile.GetValue(const line, name : string) : string;
  96. var
  97. index1,index2,index3 : integer;
  98. begin
  99. result := '';
  100. if (line <> '') and (name <> '') then
  101. begin
  102. index1 := Pos(name, line);
  103. index2 := Pos(separator, line);
  104. index3 := Pos(comment, line);
  105. if index3=0 then
  106. index3:=MaxInt;
  107. if (index1 <> 0) and (index2 <> 0) and (index2 > index1) then
  108. result := Trim(Copy(line, index2 + 1, index3));
  109. end;
  110. end;
  111. function TIniFile.IsSection(const line : string) : boolean;
  112. var
  113. str : string;
  114. begin
  115. result := False;
  116. if line <> '' then
  117. begin
  118. str := Trim(line);
  119. if (str[1] = brackets[0]) and (str[Length(str)] = brackets[1]) then
  120. result := True;
  121. end;
  122. end;
  123. function TIniFile.IsComment(const line : string) : boolean;
  124. var
  125. str : string;
  126. begin
  127. result := False;
  128. if line <> '' then
  129. begin
  130. str := Trim(line);
  131. result := (str[1]=comment);
  132. end;
  133. end;
  134. function TIniFile.GetSectionIndex(const section : string) : integer;
  135. begin
  136. result := FFileBuffer.IndexOf(brackets[0] + section + brackets[1]);
  137. end;
  138. { Load/Save }
  139. procedure TIniFile.SetFileName(const fn:string);
  140. begin
  141. FFileName:=fn;
  142. end;
  143. procedure TIniFile.SetStream(s:TStream);
  144. begin
  145. FStream:=s;
  146. end;
  147. procedure TIniFile.LoadFromFile;
  148. begin
  149. if FFileName<>'' then
  150. FFileBuffer.LoadFromFile(FFileName);
  151. end;
  152. procedure TIniFile.SaveToFile;
  153. begin
  154. if FFileName<>'' then
  155. FFileBuffer.SaveToFile(FFileName);
  156. end;
  157. procedure TIniFile.LoadFromStream;
  158. begin
  159. if assigned(FStream) then
  160. FFileBuffer.LoadFromStream(FStream);
  161. end;
  162. procedure TIniFile.SaveToStream;
  163. begin
  164. if assigned(FStream) then
  165. FFileBuffer.SaveToStream(FStream);
  166. end;
  167. { Read all Names of one Section }
  168. procedure TIniFile.ReadSection(const section : string; strings : TStrings);
  169. var
  170. index : integer;
  171. name : string;
  172. begin
  173. strings.BeginUpdate;
  174. try
  175. strings.Clear;
  176. if FFileBuffer.Count > 0 then
  177. begin
  178. index := GetSectionIndex(section);
  179. if index <> -1 then
  180. begin
  181. Inc(index);
  182. while (index < FFileBuffer.Count) and not IsSection(FFileBuffer[index]) do
  183. begin
  184. name := GetName(FFileBuffer[index]);
  185. if name <> '' then
  186. strings.Add(name);
  187. Inc(index);
  188. end;
  189. end;
  190. end;
  191. finally
  192. strings.EndUpdate;
  193. end;
  194. end;
  195. { Read all Sections of the Ini-File }
  196. procedure TIniFile.ReadSections(strings : TStrings);
  197. var
  198. index : integer;
  199. section : string;
  200. begin
  201. strings.BeginUpdate;
  202. try
  203. strings.Clear;
  204. if FFileBuffer.Count > 0 then
  205. begin
  206. index := 0;
  207. while (index < FFileBuffer.Count) do
  208. begin
  209. if IsSection(FFileBuffer[index]) then
  210. begin
  211. section := Trim(FFileBuffer[index]);
  212. Delete(section, 1, 1);
  213. Delete(section, Length(section), 1);
  214. strings.Add(Trim(section));
  215. end;
  216. Inc(index);
  217. end;
  218. end;
  219. finally
  220. strings.EndUpdate;
  221. end;
  222. end;
  223. { Reads a String-Value of "ident" in one "section".
  224. The result is "defaultValue" if
  225. o section doesn't exists
  226. o ident doesn't exists
  227. o ident doesn't have any assigned value }
  228. function TIniFile.ReadString(const section, ident, defaultValue : string) : string;
  229. var
  230. index : integer;
  231. value : string;
  232. begin
  233. result := defaultValue;
  234. if FFileBuffer.Count > 0 then
  235. begin
  236. index := GetSectionIndex(section);
  237. if index <> -1 then
  238. begin
  239. Inc(index);
  240. while (index < FFileBuffer.Count) and not IsSection(FFileBuffer[index]) do
  241. begin
  242. if CompareText(GetName(FFileBuffer[index]),ident)=0 then
  243. begin
  244. value := GetValue(FFileBuffer[index], ident);
  245. if value <> '' then
  246. begin
  247. result := value;
  248. if EscapeLineFeeds and (result[length(result)]='\') then
  249. begin
  250. inc(index);
  251. while (index < FFileBuffer.Count) and (result[length(result)]='\') do
  252. begin
  253. result:=Copy(result,1,length(result)-1)+Trim(FFileBuffer[index]);
  254. inc(index);
  255. end;
  256. end;
  257. end;
  258. break;
  259. end;
  260. Inc(index);
  261. end;
  262. end;
  263. end;
  264. end;
  265. { Reads an Integer-Value of Ident in one Section }
  266. function TIniFile.ReadInteger(const section, ident : string; defaultValue : longint) : longint;
  267. var
  268. intStr : string;
  269. begin
  270. intStr := ReadString(section, ident, '');
  271. { convert a Hex-Value }
  272. if (Length(intStr) > 2) and (intStr[1] = '0') and ((intStr[2] = 'X') or (intStr[2] = 'x')) then
  273. intStr := '$' + Copy(intStr, 3, Maxint);
  274. result := StrToIntDef(intStr, defaultValue);
  275. end;
  276. { Reads a Bool-Value of Ident in one Section }
  277. function TIniFile.ReadBool(const section, ident : string; defaultValue : boolean) : boolean;
  278. begin
  279. result := ReadInteger(section, ident, Ord(defaultValue)) <> 0;
  280. end;
  281. { Reads all Names + Values of one Section }
  282. procedure TIniFile.ReadSectionValues(const section : string; strings : TStrings);
  283. var
  284. name : string;
  285. value : string;
  286. index : integer;
  287. begin
  288. strings.BeginUpdate;
  289. try
  290. strings.Clear;
  291. if FFileBuffer.Count > 0 then
  292. begin
  293. index := GetSectionIndex(section);
  294. if index <> -1 then
  295. begin
  296. Inc(index);
  297. while (index < FFileBuffer.Count) and not IsSection(FFileBuffer[index]) do
  298. begin
  299. name := GetName(FFileBuffer[index]);
  300. if name <> '' then
  301. begin
  302. value := GetValue(FFileBuffer[index], name);
  303. strings.Add(name + separator + value);
  304. end;
  305. Inc(index);
  306. end;
  307. end;
  308. end;
  309. finally
  310. strings.EndUpdate;
  311. end;
  312. end;
  313. procedure TIniFile.ReadSectionRaw(const section : string; strings : TStrings);
  314. var
  315. eols,index : integer;
  316. begin
  317. strings.BeginUpdate;
  318. try
  319. eols:=0;
  320. strings.Clear;
  321. if FFileBuffer.Count > 0 then
  322. begin
  323. index := GetSectionIndex(section);
  324. if index <> -1 then
  325. begin
  326. Inc(index);
  327. while (index < FFileBuffer.Count) and not IsSection(FFileBuffer[index]) do
  328. begin
  329. { Skip empty lines at the end of the section }
  330. if FFileBuffer[index]='' then
  331. inc(eols)
  332. else
  333. begin
  334. while eols>0 do
  335. begin
  336. Strings.Add('');
  337. dec(eols);
  338. end;
  339. if not IsComment(FFileBuffer[index]) then
  340. strings.Add(FFileBuffer[index]);
  341. end;
  342. Inc(index);
  343. end;
  344. end;
  345. end;
  346. finally
  347. strings.EndUpdate;
  348. end;
  349. end;
  350. { Writes a String-Value for Ident in one Section.
  351. Note: If Section and/or Ident don't exist, they will be placed in the Ini-File }
  352. procedure TIniFile.WriteString(const section, ident, value : string);
  353. var
  354. index : integer;
  355. begin
  356. index := GetSectionIndex(section);
  357. { Section exists }
  358. if index <> -1 then
  359. begin
  360. Inc(index);
  361. while (index < FFileBuffer.Count) and not IsSection(FFileBuffer[index]) and
  362. (GetName(FFileBuffer[index]) <> ident) do
  363. Inc(index);
  364. if (index >= FFileBuffer.Count) or IsSection(FFileBuffer[index]) then
  365. begin { End of File or ident doesn't exists in the section }
  366. if ident <> '' then
  367. FFileBuffer.Insert(index, ident + separator + value);
  368. end
  369. else if ident <> '' then { Ident does exists in the section }
  370. FFileBuffer[index] := ident + separator + value;
  371. end
  372. else { section doesn't exists, so add new [section] with ident=value }
  373. begin
  374. FFileBuffer.Add('');
  375. FFileBuffer.Add(brackets[0] + section + brackets[1]);
  376. if ident <> '' then
  377. FFileBuffer.Add(ident + separator + value);
  378. end;
  379. SaveToFile;
  380. end;
  381. { Writes an Integer-Value for Ident in one Section }
  382. procedure TIniFile.WriteInteger(const section, ident : string; value : longint);
  383. begin
  384. WriteString(section, ident, IntToStr(value));
  385. end;
  386. { Writes a Bool-Value for Ident in one Section }
  387. procedure TIniFile.WriteBool(const section, ident : string; value : boolean);
  388. const
  389. values: array[boolean] of string = ('0', '1');
  390. begin
  391. WriteString(section, ident, values[Value]);
  392. end;
  393. { Deletes the value of ident in one section.
  394. Note: Only if section and ident exist, the value of ident will be set to NULL }
  395. procedure TIniFile.DeleteKey(const section, ident : string);
  396. var
  397. index : integer;
  398. begin
  399. index := GetSectionIndex(section);
  400. if index <> -1 then
  401. begin
  402. Inc(index);
  403. while (index < FFileBuffer.Count) and not IsSection(FFileBuffer[index]) and
  404. (GetName(FFileBuffer[index]) <> ident) do
  405. Inc(index);
  406. if not (index >= FFileBuffer.Count) and not IsSection(FFileBuffer[index]) then
  407. begin { Ident does exists }
  408. FFileBuffer.Delete(index);
  409. SaveToFile;
  410. end;
  411. end;
  412. end;
  413. { Erases the whole Section from an Ini-File }
  414. procedure TIniFile.EraseSection(const section : string);
  415. var
  416. index : integer;
  417. begin
  418. index := GetSectionIndex(section);
  419. if index <> -1 then
  420. begin
  421. FFileBuffer.Delete(index); { Delete Section-Header }
  422. while (index < FFileBuffer.Count) and not IsSection(FFileBuffer[index]) do
  423. FFileBuffer.Delete(index); { Delete Section-Items }
  424. if index > 0 then FFileBuffer.Insert(index, '');
  425. SaveToFile;
  426. end;
  427. end;
  428. end.
  429. {
  430. $Log$
  431. Revision 1.1 2000-05-11 17:59:12 peter
  432. * makeini unit added as replacement for old inifiles unit
  433. }