inicol.pp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. {$mode objfpc}
  2. {$h+}
  3. unit inicol;
  4. interface
  5. Uses SysUtils,Classes,Inifiles;
  6. Type
  7. { TIniCollectionItem }
  8. TIniCollectionItem = Class(TCollectionItem)
  9. protected
  10. function GetSectionName: String; virtual; abstract;
  11. procedure SetSectionName(const Value: String); virtual; abstract;
  12. Public
  13. Procedure SaveToIni(Ini: TCustomInifile; Section : String); Virtual; Abstract;
  14. Procedure LoadFromIni(Ini: TCustomInifile; Section : String); Virtual; Abstract;
  15. Procedure SaveToFile(FileName : String; Section : String);
  16. Procedure LoadFromFile(FileName : String; Section : String);
  17. Property SectionName : String Read GetSectionName Write SetSectionName;
  18. end;
  19. TIniCollection = Class(TCollection)
  20. private
  21. FFileName: String;
  22. FGlobalSection: String;
  23. protected
  24. FPrefix: String; // Descendent must set this.
  25. FSectionPrefix : String; // Descendent must set this too.
  26. Public
  27. Procedure Load;
  28. Procedure Save;
  29. Procedure SaveToIni(Ini: TCustomInifile; Section : String); virtual;
  30. Procedure SaveToFile(AFileName : String; Section : String);
  31. Procedure LoadFromIni(Ini: TCustomInifile; Section : String); virtual;
  32. Procedure LoadFromFile(AFileName : String; Section : String);
  33. Property Prefix : String Read FPrefix;
  34. Property SectionPrefix : String Read FSectionPrefix;
  35. Property FileName : String Read FFileName Write FFileName;
  36. Property GlobalSection : String Read FGlobalSection Write FGlobalSection;
  37. end;
  38. { TNamedIniCollectionItem }
  39. TNamedIniCollectionItem = Class(TIniCollectionItem)
  40. private
  41. procedure SetName(const AValue: String);
  42. Protected
  43. FName : String;
  44. FUserData : TObject;
  45. Protected
  46. Procedure SetCollection(Value : TCollection); override;
  47. function GetSectionName: String; override;
  48. procedure SetSectionName(const Value: String); override;
  49. Public
  50. Property UserData : TObject Read FUserData Write FUserData;
  51. Published
  52. Property Name : String Read FName Write SetName;
  53. end;
  54. { TNamedIniCollection }
  55. TNamedIniCollection = Class(TIniCollection)
  56. private
  57. function GetNamedItem(Index: Integer): TNamedIniCollectionItem;
  58. procedure SetNamedItem(Index: Integer; const AValue: TNamedIniCollectionItem);
  59. Public
  60. Function IndexOfUserData(UserData : TObject) : Integer;
  61. Function IndexOfName(Const AName : String) : Integer;
  62. Function FindByName(Const AName : string) : TNamedIniCollectionItem;
  63. Function FindByUserData(UserData : TObject) : TNamedIniCollectionItem;
  64. Property NamedItems [Index: Integer] : TNamedIniCollectionItem Read GetNamedItem Write SetNamedItem; default;
  65. end;
  66. EIniCol = Class(Exception);
  67. Const
  68. KeyCount = 'Count';
  69. SGlobal = 'Global';
  70. implementation
  71. { TIniCollectionItem }
  72. resourcestring
  73. SErrNoFileName = '%s: No filename specified.';
  74. SErrNoSection = '%s: No [global] section specified.';
  75. SErrDuplicateName = 'Duplicate names "%s" not allowed in collection';
  76. procedure TIniCollectionItem.LoadFromFile(FileName, Section: String);
  77. Var
  78. Ini : TMemInifile;
  79. begin
  80. Ini:=TMemInifile.Create(FileName);
  81. Try
  82. LoadFromIni(Ini,Section);
  83. Finally
  84. Ini.Free;
  85. end;
  86. end;
  87. procedure TIniCollectionItem.SaveToFile(FileName, Section: String);
  88. Var
  89. Ini : TMemInifile;
  90. begin
  91. Ini:=TMemInifile.Create(FileName);
  92. Try
  93. SaveToIni(Ini,Section);
  94. Ini.UpdateFile;
  95. Finally
  96. Ini.Free;
  97. end;
  98. end;
  99. { TIniCollection }
  100. procedure TIniCollection.Load;
  101. begin
  102. If (FFileName='') then
  103. Raise EIniCol.CreateFmt(SErrNoFileName,[ClassName]);
  104. If (GlobalSection='') then
  105. Raise EIniCol.CreateFmt(SErrNoSection,[ClassName]);
  106. LoadFromFile(FFileName,GlobalSection)
  107. end;
  108. procedure TIniCollection.LoadFromFile(AFileName, Section: String);
  109. Var
  110. Ini : TMemIniFile;
  111. begin
  112. Ini:=TMemInifile.Create(AFileName);
  113. Try
  114. LoadFromIni(Ini,Section);
  115. FFileName:=AFileName;
  116. FGlobalSection:=Section;
  117. Finally
  118. ini.Free;
  119. end;
  120. end;
  121. procedure TIniCollection.LoadFromIni(Ini: TCustomInifile; Section: String);
  122. Var
  123. ACount,I : Integer;
  124. N,SP : String;
  125. begin
  126. Clear;
  127. SP:=FSectionPrefix;
  128. If (SP<>'') then
  129. SP:=SP+'_';
  130. ACount:=Ini.ReadInteger(Section,KeyCount,0);
  131. For I:=1 to ACount do
  132. begin
  133. N:=Ini.ReadString(Section,Prefix+IntToStr(I),'');
  134. If (N<>'') then
  135. With Add as TIniCollectionItem do
  136. begin
  137. SectionName:=N;
  138. LoadFromIni(Ini,SP+N);
  139. end;
  140. end;
  141. end;
  142. procedure TIniCollection.Save;
  143. begin
  144. If (FFileName='') then
  145. Raise EIniCol.CreateFmt(SErrNoFileName,[ClassName]);
  146. If (GlobalSection='') then
  147. Raise EIniCol.CreateFmt(SErrNoSection,[ClassName]);
  148. SaveToFile(FFileName,GlobalSection)
  149. end;
  150. procedure TIniCollection.SaveToFile(AFileName, Section: String);
  151. Var
  152. Ini : TMemIniFile;
  153. begin
  154. Ini:=TMemInifile.Create(AFileName);
  155. Try
  156. Ini.CacheUpdates:=True;
  157. SaveToIni(Ini,Section);
  158. Ini.UpdateFile;
  159. finally
  160. Ini.Free;
  161. end;
  162. end;
  163. procedure TIniCollection.SaveToIni(Ini: TCustomInifile; Section: String);
  164. Var
  165. S,V,SP : String;
  166. I : Integer;
  167. CI : TIniCollectionItem;
  168. begin
  169. SP:=FSectionPrefix;
  170. if (SP<>'') then
  171. SP:=SP+'_';
  172. Ini.WriteInteger(Section,KeyCount,Count);
  173. For I:=0 to Count-1 do
  174. begin
  175. CI:=(Items[i]) as TIniCollectionItem;
  176. With CI do
  177. begin
  178. V:=SectionName;
  179. S:=Prefix+IntToStr(I+1);
  180. Ini.WriteString(Section,S,V);
  181. CI.SaveToIni(Ini,SP+V);
  182. end;
  183. end;
  184. end;
  185. { ---------------------------------------------------------------------
  186. TNamedIniCollectionItem
  187. ---------------------------------------------------------------------}
  188. procedure TNamedIniCollectionItem.SetName(const AValue: String);
  189. begin
  190. If (CompareText(AValue,FName)<>0) then
  191. begin
  192. If (AValue<>'') and (Collection<>Nil) and (Collection is TNamedIniCollection) then
  193. If TNamedIniCollection(Collection).IndexOfName(AValue)<>-1 then
  194. Raise EIniCol.CreateFmt(SErrDuplicateName,[AValue]);
  195. end;
  196. FName:=AValue;
  197. end;
  198. procedure TNamedIniCollectionItem.SetCollection(Value: TCollection);
  199. begin
  200. If (Value<>Collection) then
  201. begin
  202. If (Value<>Nil) and (Value is TNamedIniCollection) Then
  203. If TNamedIniCollection(Value).IndexOfName(Self.Name)<>-1 then
  204. Raise EIniCol.CreateFmt(SErrDuplicateName,[Self.Name]);
  205. end;
  206. inherited SetCollection(Value);
  207. end;
  208. function TNamedIniCollectionItem.GetSectionName: String;
  209. begin
  210. Result:=FName;
  211. end;
  212. procedure TNamedIniCollectionItem.SetSectionName(const Value: String);
  213. begin
  214. FName:=Value; // Skip check. Ini files have only 1 named section
  215. end;
  216. { ---------------------------------------------------------------------
  217. TNamedIniCollection
  218. ---------------------------------------------------------------------}
  219. function TNamedIniCollection.GetNamedItem(Index: Integer): TNamedIniCollectionItem;
  220. begin
  221. Result:=Items[Index] as TNamedIniCollectionItem;
  222. end;
  223. procedure TNamedIniCollection.SetNamedItem(Index: Integer; const AValue: TNamedIniCollectionItem);
  224. begin
  225. Items[Index]:=AValue;
  226. end;
  227. function TNamedIniCollection.IndexOfUserData(UserData: TObject): Integer;
  228. begin
  229. If (UserData=Nil) then
  230. Result:=-1
  231. else
  232. begin
  233. Result:=Count-1;
  234. While (Result>=0) and (GetNamedItem(Result).UserData<>UserData) do
  235. Dec(Result);
  236. end;
  237. end;
  238. function TNamedIniCollection.IndexOfName(const AName: String): Integer;
  239. begin
  240. Result:=Count-1;
  241. While (Result>=0) and (CompareText(GetNamedItem(Result).Name,AName)<>0) do
  242. Dec(Result);
  243. end;
  244. function TNamedIniCollection.FindByName(const AName : string): TNamedIniCollectionItem;
  245. Var
  246. I : Integer;
  247. begin
  248. I:=IndexOfName(AName);
  249. If (I=-1) then
  250. Result:=Nil
  251. else
  252. Result:=GetNamedItem(I);
  253. end;
  254. function TNamedIniCollection.FindByUserData(UserData: TObject): TNamedIniCollectionItem;
  255. Var
  256. I : Integer;
  257. begin
  258. I:=IndexOfUserData(UserData);
  259. If (I=-1) then
  260. Result:=Nil
  261. else
  262. Result:=GetNamedItem(I);
  263. end;
  264. end.