TPropertiesUnit.pas 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. {
  2. Copyright 2005-2006 Log4Delphi Project
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. }
  13. {*----------------------------------------------------------------------------
  14. Contains the TProperties class.
  15. @version 0.5
  16. @author <a href="mailto:tcmiller@users.sourceforge.net">Trevor Miller</a>
  17. ----------------------------------------------------------------------------}
  18. unit TPropertiesUnit;
  19. {$ifdef fpc}
  20. {$mode objfpc}
  21. {$h+}
  22. {$endif}
  23. interface
  24. uses
  25. Classes, SysUtils,
  26. TStringUnit, TPrintWriterUnit;
  27. type
  28. {*----------------------------------------------------------------------------
  29. TProperties represents a persistent set of properties that can be saved to
  30. a TStream or loaded from a TStream. A property is simply a key=value
  31. mapping between two strings, one the key and the other the value.
  32. <p>
  33. Properties are saved to stream as key=value, one such pair per line, and
  34. when loaded from a stream, the same format is expected. Keys can be of the
  35. form "base.name" thus allowing a subset of all properties with the same
  36. base to be found.
  37. ----------------------------------------------------------------------------}
  38. TProperties = class (TObject)
  39. private
  40. FValues : TStrings;
  41. public
  42. constructor Create;
  43. destructor Destroy; Override;
  44. procedure SetProperty(const AKey, AValue : String);
  45. procedure RemoveProperty(const AKey : String);
  46. procedure Save(AStream : TStream);
  47. procedure Load(AStream : TStream);
  48. procedure Clear();
  49. function GetProperty(const AKey : String) : String; Overload;
  50. function GetProperty(const AKey, ADefaultValue : String)
  51. : String; Overload;
  52. function GetPropertyNames() : TStrings;
  53. function Subset(const APrefix : String) : TProperties;
  54. end;
  55. implementation
  56. {*----------------------------------------------------------------------------
  57. Instantiate a Properties instance with an empty properties set.
  58. ----------------------------------------------------------------------------}
  59. constructor TProperties.Create;
  60. begin
  61. inherited Create;
  62. FValues := TStringList.Create;
  63. end;
  64. {*----------------------------------------------------------------------------
  65. Destruct the instance by freeing the internal properties set.
  66. ----------------------------------------------------------------------------}
  67. destructor TProperties.Destroy;
  68. begin
  69. clear();
  70. FValues.Free;
  71. inherited Destroy;
  72. end;
  73. {*----------------------------------------------------------------------------
  74. Set a property in the set.
  75. @param AKey The key to set
  76. @param AValue The value that maps to that key
  77. ----------------------------------------------------------------------------}
  78. procedure TProperties.SetProperty(const AKey, AValue : String);
  79. var
  80. index : Integer;
  81. begin
  82. index := FValues.IndexOf(AKey);
  83. if (index < 0) then begin
  84. FValues.AddObject(AKey, TString.Create(AValue));
  85. end else begin
  86. TString(FValues.Objects[index]).setString(AValue);
  87. end;
  88. end;
  89. {*----------------------------------------------------------------------------
  90. Remove the value that maps to the given key. Does nothing if the key is
  91. non-existent, no such key in the set.
  92. @param AKey The key whose value to delete
  93. ----------------------------------------------------------------------------}
  94. procedure TProperties.RemoveProperty(const AKey : String);
  95. var
  96. index : Integer;
  97. begin
  98. index := FValues.IndexOf(AKey);
  99. if (index >= 0) then begin
  100. FValues.Objects[index].Free;
  101. FValues.Delete(index);
  102. end;
  103. end;
  104. {*----------------------------------------------------------------------------
  105. Save the set of properties to a stream. This can be any class that
  106. subclasses TStream.
  107. @param AStream The TStream to save to
  108. ----------------------------------------------------------------------------}
  109. procedure TProperties.Save(AStream : TStream);
  110. var
  111. writer : TPrintWriter;
  112. index : Integer;
  113. begin
  114. writer := TPrintWRiter.Create(AStream);
  115. for index := 0 to FValues.Count-1 do begin
  116. writer.print(FValues[index]);
  117. writer.print('=');
  118. writer.println(TString(FValues.Objects[index]).ToString);
  119. end;
  120. writer.Free;
  121. end;
  122. {*----------------------------------------------------------------------------
  123. Load a properties set from a stream. This can be any class that subclasses
  124. TStream.
  125. @param AStream The stream to load from
  126. ----------------------------------------------------------------------------}
  127. procedure TProperties.Load(AStream : TStream);
  128. var
  129. strings : TStrings;
  130. count : Integer;
  131. index : Integer;
  132. begin
  133. clear();
  134. strings := TStringList.Create;
  135. strings.LoadFromStream(AStream);
  136. for count := 0 to strings.Count-1 do begin
  137. if (Length(strings[count]) > 0) then
  138. if (strings[count][1] <> '#') then begin
  139. index := Pos('=', strings[count]);
  140. if (index >= 0) then begin
  141. FValues.AddObject(trim(copy(strings[count],0,index-1)),
  142. TString.Create(trim(copy(strings[count],index+1,
  143. Length(strings[count])-index))));
  144. end;
  145. end;
  146. end;
  147. strings.Free;
  148. end;
  149. {*----------------------------------------------------------------------------
  150. Clear the properties set.
  151. ----------------------------------------------------------------------------}
  152. procedure TProperties.Clear();
  153. var
  154. count : Integer;
  155. begin
  156. for count := 0 to FValues.Count-1 do
  157. FValues.Objects[count].Free;
  158. FValues.Clear;
  159. end;
  160. {*----------------------------------------------------------------------------
  161. Return a property matching the given key. If no such key exists in the
  162. properties set then the empty string '' is returned.
  163. @param AKey The key whose value to return
  164. @return The value matching the given key or an emprty string if no such
  165. key exists
  166. ----------------------------------------------------------------------------}
  167. function TProperties.GetProperty(const AKey : String) : String;
  168. begin
  169. result := getProperty(Akey, '');
  170. end;
  171. {*----------------------------------------------------------------------------
  172. Return a property matching the given key. If no such key exists in the
  173. properties set then the default value is returned.
  174. @param AKey The key whose value to return
  175. @param ADefaultValue The default value to use
  176. @return The value matching the given key or default value if no such
  177. key exists
  178. ----------------------------------------------------------------------------}
  179. function TProperties.GetProperty(const AKey, ADefaultValue : String) : String;
  180. var
  181. index : Integer;
  182. begin
  183. index := FValues.IndexOf(AKey);
  184. if (index >= 0) then
  185. result := TString(FValues.Objects[index]).toString
  186. else
  187. result := ADefaultValue;
  188. end;
  189. {*----------------------------------------------------------------------------
  190. Return a list of all the property keys in the set. This can be used for
  191. iterating through all the properties in the set.
  192. @return TStringList with all the keys
  193. ----------------------------------------------------------------------------}
  194. function TProperties.GetPropertyNames() : TStrings;
  195. var
  196. tmp : TStrings;
  197. begin
  198. tmp := TStringList.Create;
  199. tmp.Text := FValues.Text;
  200. result := tmp;
  201. end;
  202. {*----------------------------------------------------------------------------
  203. Return a subset of properties whose keys match a given base prefix. It is
  204. possible that none of the keys match the base prefix, in such a case, an
  205. empty properties set will be returned. It is the caller's responsibility to
  206. free the memory of the returned TProperties instance.
  207. @param APrefix The base prefix of the subset
  208. @return A new TProperteis instance containing the subset of properties
  209. ----------------------------------------------------------------------------}
  210. function TProperties.Subset(const APrefix : String) : TProperties;
  211. var
  212. tmp : TProperties;
  213. i : Integer;
  214. begin
  215. tmp := TProperties.Create;
  216. for i := 0 to FValues.Count-1 do
  217. if (TStringUnit.StartsWith(FValues[i], APrefix, 0)) then
  218. tmp.FValues.AddObject(FValues[i],
  219. TString.Create(TString(FValues.Objects[i])));
  220. result := tmp;
  221. end;
  222. end.