dfmreader.pp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2008 by Giulio Bernardi
  4. Resource reader for DFM files
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. unit dfmreader;
  12. {$MODE OBJFPC} {$H+}
  13. interface
  14. uses
  15. Classes, SysUtils, resource;
  16. type
  17. { TDfmResourceReader }
  18. TDfmResourceReader = class (TAbstractResourceReader)
  19. private
  20. fExtensions : string;
  21. fDescription : string;
  22. fLine : string;
  23. fLinePos : integer;
  24. fObjectName : string;
  25. dummyType : TResourceDesc;
  26. dummyName : TResourceDesc;
  27. fIsBinary : boolean;
  28. function IsAlpha : boolean;
  29. function IsNum : boolean;
  30. function IsAlphaNum : boolean;
  31. function IsSpace : boolean;
  32. procedure SkipSpaces;
  33. function GetIdent : string;
  34. procedure ReadLine(aStream : TStream);
  35. function CheckTextDfm(aStream : TStream) : boolean;
  36. function CheckBinDfm(aStream : TStream) : boolean;
  37. protected
  38. function GetExtensions : string; override;
  39. function GetDescription : string; override;
  40. procedure Load(aResources : TResources; aStream : TStream); override;
  41. function CheckMagic(aStream : TStream) : boolean; override;
  42. public
  43. constructor Create; override;
  44. destructor Destroy; override;
  45. end;
  46. implementation
  47. uses
  48. resdatastream, resfactory;
  49. type
  50. TSignature = array[0..3] of char;
  51. const
  52. FilerSignature = 'TPF0';
  53. { TDfmResourceReader }
  54. function TDfmResourceReader.IsAlpha: boolean;
  55. begin
  56. Result:=pchar(fLine)[fLinePos] in ['_','A'..'Z','a'..'z'];
  57. end;
  58. function TDfmResourceReader.IsNum: boolean;
  59. begin
  60. Result:=pchar(fLine)[fLinePos] in ['0'..'9'];
  61. end;
  62. function TDfmResourceReader.IsAlphaNum: boolean;
  63. begin
  64. Result:=IsAlpha or IsNum;
  65. end;
  66. function TDfmResourceReader.IsSpace: boolean;
  67. const TAB = #9;
  68. begin
  69. Result:=pchar(fLine)[fLinePos] in [' ',TAB];
  70. end;
  71. procedure TDfmResourceReader.SkipSpaces;
  72. begin
  73. while IsSpace do inc(fLinePos);
  74. end;
  75. function TDfmResourceReader.GetIdent: string;
  76. begin
  77. Result:='';
  78. SkipSpaces;
  79. if not IsAlpha then exit;
  80. while IsAlphaNum do
  81. begin
  82. Result:=Result+pchar(fLine)[fLinePos];
  83. inc(fLinePos);
  84. end;
  85. end;
  86. procedure TDfmResourceReader.ReadLine(aStream : TStream);
  87. const CR = #13;
  88. LF = #10;
  89. var c : char;
  90. begin
  91. fLine:='';
  92. repeat
  93. aStream.ReadBuffer(c,1);
  94. if not (c in [CR,LF,#0]) then
  95. fLine:=fLine+c;
  96. until c in [CR,LF,#0];
  97. fLinePos:=0;
  98. end;
  99. (*should be: object Name: Type or inherited Name: Type*)
  100. function TDfmResourceReader.CheckTextDfm(aStream: TStream): boolean;
  101. var tmp : string;
  102. begin
  103. Result:=false;
  104. fLine:='';
  105. while fLine='' do
  106. ReadLine(aStream);
  107. //skip UTF-8 BOM, if needed
  108. if (copy(fLine,1,3)=(#$EF+#$BB+#$BF)) then
  109. inc(fLinePos,3);
  110. tmp:=lowercase(GetIdent);
  111. if (tmp <> 'object') and (tmp<>'inherited') then exit;
  112. if GetIdent='' then exit;
  113. SkipSpaces;
  114. if pchar(fLine)[fLinePos]<>':' then exit;
  115. inc(fLinePos);
  116. SkipSpaces;
  117. fObjectName:=UpperCase(GetIdent);
  118. if fObjectName='' then exit;
  119. Result:=true;
  120. fIsBinary:=false;
  121. end;
  122. function TDfmResourceReader.CheckBinDfm(aStream: TStream): boolean;
  123. var s : shortstring;
  124. b : byte;
  125. begin
  126. aStream.ReadBuffer(b,1);
  127. s[0]:=Chr(b);
  128. aStream.ReadBuffer(s[1],b);
  129. fObjectName:=UpperCase(s);
  130. Result:=fObjectName<>'';
  131. fIsBinary:=true;
  132. end;
  133. function TDfmResourceReader.GetExtensions: string;
  134. begin
  135. Result:=fExtensions;
  136. end;
  137. function TDfmResourceReader.GetDescription: string;
  138. begin
  139. Result:=fDescription;
  140. end;
  141. procedure TDfmResourceReader.Load(aResources: TResources; aStream: TStream);
  142. var aRes : TAbstractResource;
  143. RawData : TResourceDataStream;
  144. begin
  145. if not CheckMagic(aStream) then
  146. raise EResourceReaderWrongFormatException.Create('');
  147. dummyName.Name:=fObjectName;
  148. aRes:=TResourceFactory.CreateResource(dummyType,dummyName);
  149. if fIsBinary then
  150. begin
  151. SetDataSize(aRes,aStream.Size-aStream.Position);
  152. SetDataOffset(aRes,aStream.Position);
  153. RawData:=TResourceDataStream.Create(aStream,aRes,aRes.DataSize,TCachedResourceDataStream);
  154. SetRawData(aRes,RawData);
  155. end
  156. else
  157. ObjectTextToBinary(aStream,aRes.RawData);
  158. try
  159. aResources.Add(aRes);
  160. except
  161. on e : EResourceDuplicateException do
  162. begin
  163. aRes.Free;
  164. raise;
  165. end;
  166. end;
  167. end;
  168. function TDfmResourceReader.CheckMagic(aStream: TStream): boolean;
  169. var sig : TSignature;
  170. orig : int64;
  171. begin
  172. orig:=aStream.Position;
  173. aStream.ReadBuffer(sig,4);
  174. if sig=FilerSignature then Result:=CheckBinDfm(aStream)
  175. else
  176. begin
  177. aStream.Seek(-4,soFromCurrent);
  178. Result:=CheckTextDfm(aStream);
  179. end;
  180. aStream.Position:=orig;
  181. end;
  182. constructor TDfmResourceReader.Create;
  183. begin
  184. fExtensions:='.dfm .xfm .lfm';
  185. fDescription:='DFM resource reader';
  186. fLine:='';
  187. fLinePos:=0;
  188. fObjectName:='';
  189. fIsBinary:=false;
  190. dummyType:=TResourceDesc.Create;
  191. dummyType.ID:=RT_RCDATA;
  192. dummyName:=TResourceDesc.Create;
  193. end;
  194. destructor TDfmResourceReader.Destroy;
  195. begin
  196. dummyType.Free;
  197. dummyName.Free;
  198. end;
  199. initialization
  200. TResources.RegisterReader('.dfm',TDfmResourceReader);
  201. TResources.RegisterReader('.xfm',TDfmResourceReader);
  202. TResources.RegisterReader('.lfm',TDfmResourceReader);
  203. end.