reader.inc 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060
  1. {%MainUnit classes.pp}
  2. {
  3. This file is part of the Free Component Library (FCL)
  4. Copyright (c) 1999-2000 by the Free Pascal development team
  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. {****************************************************************************}
  12. {* TBinaryObjectReader *}
  13. {****************************************************************************}
  14. {$ifndef FPUNONE}
  15. {$IFNDEF FPC_HAS_TYPE_EXTENDED}
  16. function ExtendedToDouble(e : pointer) : double;
  17. var mant : qword;
  18. exp : smallint;
  19. sign : boolean;
  20. d : qword;
  21. begin
  22. move(pbyte(e)[0],mant,8); //mantissa : bytes 0..7
  23. move(pbyte(e)[8],exp,2); //exponent and sign: bytes 8..9
  24. mant:=LEtoN(mant);
  25. exp:=LEtoN(word(exp));
  26. sign:=(exp and $8000)<>0;
  27. if sign then exp:=exp and $7FFF;
  28. case exp of
  29. 0 : mant:=0; //if denormalized, value is too small for double,
  30. //so it's always zero
  31. $7FFF : exp:=2047 //either infinity or NaN
  32. else
  33. begin
  34. dec(exp,16383-1023);
  35. if (exp>=-51) and (exp<=0) then //can be denormalized
  36. begin
  37. mant:=mant shr (-exp);
  38. exp:=0;
  39. end
  40. else
  41. if (exp<-51) or (exp>2046) then //exponent too large.
  42. begin
  43. Result:=0;
  44. exit;
  45. end
  46. else //normalized value
  47. mant:=mant shl 1; //hide most significant bit
  48. end;
  49. end;
  50. d:=word(exp);
  51. d:=d shl 52;
  52. mant:=mant shr 12;
  53. d:=d or mant;
  54. if sign then d:=d or $8000000000000000;
  55. Result:=pdouble(@d)^;
  56. end;
  57. {$ENDIF}
  58. {$endif}
  59. procedure TAbstractObjectReader.BeginComponent(var Flags: TFilerFlags; var AChildPos: Integer;
  60. var CompUnitName, CompClassName, CompName: String);
  61. begin
  62. CompUnitName:='';
  63. BeginComponent(Flags,AChildPos,CompClassName, CompName);
  64. end;
  65. procedure TAbstractObjectReader.ReadPrefix(var Flags: TFilerFlags; var AChildPos: Integer);
  66. begin
  67. // Do nothing
  68. Flags:=[];
  69. aChildPos:=0;
  70. end;
  71. function TBinaryObjectReader.ReadWord : word; {$ifdef CLASSESINLINE}inline;{$endif CLASSESINLINE}
  72. begin
  73. Read(Result,2);
  74. Result:=LEtoN(Result);
  75. end;
  76. function TBinaryObjectReader.ReadDWord : longword; {$ifdef CLASSESINLINE}inline;{$endif CLASSESINLINE}
  77. begin
  78. Read(Result,4);
  79. Result:=LEtoN(Result);
  80. end;
  81. function TBinaryObjectReader.ReadQWord : qword; {$ifdef CLASSESINLINE}inline;{$endif CLASSESINLINE}
  82. begin
  83. Read(Result,8);
  84. Result:=LEtoN(Result);
  85. end;
  86. {$IFDEF FPC_DOUBLE_HILO_SWAPPED}
  87. procedure SwapDoubleHiLo(var avalue: double); {$ifdef CLASSESINLINE}inline{$endif CLASSESINLINE}
  88. var dwo1 : dword;
  89. type tdoublerec = array[0..1] of dword;
  90. begin
  91. dwo1:= tdoublerec(avalue)[0];
  92. tdoublerec(avalue)[0]:=tdoublerec(avalue)[1];
  93. tdoublerec(avalue)[1]:=dwo1;
  94. end;
  95. {$ENDIF FPC_DOUBLE_HILO_SWAPPED}
  96. {$ifndef FPUNONE}
  97. function TBinaryObjectReader.ReadExtended : extended; {$ifdef CLASSESINLINE}inline;{$endif CLASSESINLINE}
  98. {$IFNDEF FPC_HAS_TYPE_EXTENDED}
  99. var ext : array[0..9] of byte;
  100. {$ENDIF}
  101. begin
  102. {$IFNDEF FPC_HAS_TYPE_EXTENDED}
  103. Read(ext[0],10);
  104. Result:=ExtendedToDouble(@(ext[0]));
  105. {$IFDEF FPC_DOUBLE_HILO_SWAPPED}
  106. SwapDoubleHiLo(result);
  107. {$ENDIF}
  108. {$ELSE}
  109. Read(Result,sizeof(Result));
  110. {$ENDIF}
  111. end;
  112. {$endif}
  113. constructor TBinaryObjectReader.Create(Stream: TStream; BufSize: Integer);
  114. begin
  115. inherited Create;
  116. If (Stream=Nil) then
  117. Raise EReadError.Create(SEmptyStreamIllegalReader);
  118. FStream := Stream;
  119. FBufSize := BufSize;
  120. GetMem(FBuffer, BufSize);
  121. end;
  122. destructor TBinaryObjectReader.Destroy;
  123. begin
  124. { Seek back the amount of bytes that we didn't process until now: }
  125. FStream.Seek(Integer(FBufPos) - Integer(FBufEnd), soFromCurrent);
  126. if Assigned(FBuffer) then
  127. FreeMem(FBuffer, FBufSize);
  128. inherited Destroy;
  129. end;
  130. function TBinaryObjectReader.ReadValue: TValueType;
  131. var
  132. b: byte;
  133. begin
  134. Read(b, 1);
  135. FCurrentValue:=TValueType(b);
  136. Result := FCurrentValue;
  137. end;
  138. function TBinaryObjectReader.CurrentValue: TValueType;
  139. begin
  140. Result:=FCurrentValue;
  141. end;
  142. function TBinaryObjectReader.NextValue: TValueType;
  143. var
  144. b: byte;
  145. begin
  146. Read(b,1);
  147. Result:=TValueType(b);
  148. { We only 'peek' at the next value, so seek back to unget the read value: }
  149. Dec(FBufPos);
  150. end;
  151. procedure TBinaryObjectReader.BeginRootComponent;
  152. begin
  153. { Read filer signature }
  154. ReadSignature;
  155. end;
  156. procedure TBinaryObjectReader.BeginComponent(var Flags: TFilerFlags;
  157. var AChildPos: Integer; var CompClassName, CompName: String);
  158. var
  159. CompUnitName: String;
  160. begin
  161. CompUnitName:='';
  162. BeginComponent(Flags, AChildPos, CompUnitName, CompClassName, CompName);
  163. end;
  164. procedure TBinaryObjectReader.ReadPrefix(var Flags: TFilerFlags; var AChildPos: Integer);
  165. var
  166. Prefix: Byte;
  167. ValueType: TValueType;
  168. begin
  169. Flags := [];
  170. if (Byte(NextValue) and $f0) = $f0 then
  171. begin
  172. Prefix := Byte(ReadValue);
  173. Flags := TFilerFlags(TFilerFlagsInt(Prefix and $0f));
  174. if ffChildPos in Flags then
  175. begin
  176. ValueType := ReadValue;
  177. case ValueType of
  178. vaInt8:
  179. AChildPos := ReadInt8;
  180. vaInt16:
  181. AChildPos := ReadInt16;
  182. vaInt32:
  183. AChildPos := ReadInt32;
  184. else
  185. raise EReadError.Create(SInvalidPropertyValue);
  186. end;
  187. end;
  188. end;
  189. end;
  190. procedure TBinaryObjectReader.BeginComponent(var Flags: TFilerFlags;
  191. var AChildPos: Integer; var CompUnitName, CompClassName, CompName: String);
  192. var
  193. ValueType: TValueType;
  194. p: SizeInt;
  195. begin
  196. { Every component can start with a special prefix: }
  197. ReadPrefix(Flags,aChildPos);
  198. CompUnitName:='';
  199. if Version = TBOVersion.boVersion1 then
  200. begin
  201. ValueType := ReadValue;
  202. CompClassName := ReadString(ValueType);
  203. p:=Pos(UnitnameSeparator,CompClassName);
  204. if p>0 then
  205. begin
  206. CompUnitName:=copy(CompClassName,1,p-1);
  207. System.Delete(CompClassName,1,p);
  208. end;
  209. end
  210. else
  211. CompClassName := ReadStr;
  212. CompName := ReadStr;
  213. end;
  214. function TBinaryObjectReader.BeginProperty: String;
  215. begin
  216. Result := ReadStr;
  217. end;
  218. procedure TBinaryObjectReader.ReadBinary(const DestData: TMemoryStream);
  219. var
  220. BinSize: LongInt;
  221. begin
  222. BinSize:=LongInt(ReadDWord);
  223. DestData.Size := BinSize;
  224. Read(DestData.Memory^, BinSize);
  225. end;
  226. {$ifndef FPUNONE}
  227. function TBinaryObjectReader.ReadFloat: Extended;
  228. begin
  229. Result:=ReadExtended;
  230. end;
  231. function TBinaryObjectReader.ReadSingle: Single;
  232. var
  233. r: record
  234. case byte of
  235. 1: (d: dword);
  236. 2: (s: single);
  237. end;
  238. begin
  239. r.d:=ReadDWord;
  240. Result:=r.s;
  241. end;
  242. function TBinaryObjectReader.ReadDouble: Double;
  243. var
  244. r: record
  245. case byte of
  246. 1: (q: qword);
  247. 2: (d: double);
  248. end;
  249. begin
  250. r.q:=ReadQWord;
  251. Result:=R.d;
  252. end;
  253. {$endif}
  254. function TBinaryObjectReader.ReadCurrency: Currency;
  255. var
  256. r: record
  257. case byte of
  258. 1: (q: qword);
  259. 2: (c: currency);
  260. end;
  261. begin
  262. r.c:=ReadQWord;
  263. Result:=r.c;
  264. end;
  265. {$ifndef FPUNONE}
  266. function TBinaryObjectReader.ReadDate: TDateTime;
  267. var
  268. r: record
  269. case byte of
  270. 1: (q: qword);
  271. 2: (d: TDateTime);
  272. end;
  273. begin
  274. r.q:=ReadQWord;
  275. Result:=r.d;
  276. end;
  277. {$endif}
  278. function TBinaryObjectReader.ReadIdent(ValueType: TValueType): RawByteString;
  279. var
  280. i: Byte;
  281. begin
  282. case ValueType of
  283. vaIdent:
  284. begin
  285. Read(i, 1);
  286. SetLength(Result, i);
  287. Read(Pointer(@Result[1])^, i);
  288. end;
  289. vaNil:
  290. Result := 'nil';
  291. vaFalse:
  292. Result := 'False';
  293. vaTrue:
  294. Result := 'True';
  295. vaNull:
  296. Result := 'Null';
  297. end;
  298. end;
  299. function TBinaryObjectReader.ReadInt8: ShortInt;
  300. begin
  301. Read(Result, 1);
  302. end;
  303. function TBinaryObjectReader.ReadInt16: SmallInt;
  304. begin
  305. Result:=SmallInt(ReadWord);
  306. end;
  307. function TBinaryObjectReader.ReadInt32: LongInt;
  308. begin
  309. Result:=LongInt(ReadDWord);
  310. end;
  311. function TBinaryObjectReader.ReadInt64: Int64;
  312. begin
  313. Result:=Int64(ReadQWord);
  314. end;
  315. function TBinaryObjectReader.ReadSet(EnumType: Pointer): Integer;
  316. type
  317. {$packset 1}
  318. tset = set of 0..(SizeOf(Integer)*8-1);
  319. {$packset default}
  320. var
  321. Name: String;
  322. Value: Integer;
  323. begin
  324. try
  325. Result := 0;
  326. while True do
  327. begin
  328. Name := ReadStr;
  329. if Length(Name) = 0 then
  330. break;
  331. Value := GetEnumValue(PTypeInfo(EnumType), Name);
  332. if Value = -1 then
  333. raise EReadError.Create(SInvalidPropertyValue);
  334. include(tset(result),Value);
  335. end;
  336. except
  337. SkipSetBody;
  338. raise;
  339. end;
  340. end;
  341. procedure TBinaryObjectReader.ReadSignature;
  342. var
  343. Signature: LongInt;
  344. begin
  345. Read(Signature, 4);
  346. if Signature = LongInt(unaligned(FilerSignature1)) then
  347. FVersion:=TBOVersion.boVersion1
  348. else if Signature = LongInt(unaligned(FilerSignature)) then
  349. FVersion:=TBOVersion.boVersion0
  350. else
  351. raise EReadError.Create(SInvalidImage);
  352. end;
  353. function TBinaryObjectReader.ReadStr: RawByteString;
  354. var
  355. i: Byte;
  356. begin
  357. Read(i, 1);
  358. SetLength(Result, i);
  359. if i > 0 then
  360. Read(Pointer(@Result[1])^, i);
  361. end;
  362. function TBinaryObjectReader.ReadString(StringType: TValueType): RawByteString;
  363. var
  364. b: Byte;
  365. i: Integer;
  366. begin
  367. case StringType of
  368. vaLString, vaUTF8String:
  369. i:=ReadDWord;
  370. else
  371. //vaString:
  372. begin
  373. Read(b, 1);
  374. i := b;
  375. end;
  376. end;
  377. SetLength(Result, i);
  378. if i > 0 then
  379. Read(Pointer(@Result[1])^, i);
  380. end;
  381. function TBinaryObjectReader.ReadWideString: WideString;
  382. var
  383. len: DWord;
  384. {$IFDEF ENDIAN_BIG}
  385. i : integer;
  386. {$ENDIF}
  387. begin
  388. len := ReadDWord;
  389. SetLength(Result, len);
  390. if (len > 0) then
  391. begin
  392. Read(Pointer(@Result[1])^, len*2);
  393. {$IFDEF ENDIAN_BIG}
  394. for i:=1 to len do
  395. Result[i]:=widechar(SwapEndian(word(Result[i])));
  396. {$ENDIF}
  397. end;
  398. end;
  399. function TBinaryObjectReader.ReadUnicodeString: UnicodeString;
  400. var
  401. len: DWord;
  402. {$IFDEF ENDIAN_BIG}
  403. i : integer;
  404. {$ENDIF}
  405. begin
  406. len := ReadDWord;
  407. SetLength(Result, len);
  408. if (len > 0) then
  409. begin
  410. Read(Pointer(@Result[1])^, len*2);
  411. {$IFDEF ENDIAN_BIG}
  412. for i:=1 to len do
  413. Result[i]:=UnicodeChar(SwapEndian(word(Result[i])));
  414. {$ENDIF}
  415. end;
  416. end;
  417. procedure TBinaryObjectReader.SkipComponent(SkipComponentInfos: Boolean);
  418. var
  419. Flags: TFilerFlags;
  420. Dummy: Integer;
  421. CompUnitName, CompClassName, CompName: String;
  422. begin
  423. if SkipComponentInfos then
  424. begin
  425. { Skip prefix, component class name and component object name }
  426. BeginComponent(Flags, Dummy, CompUnitName, CompClassName, CompName);
  427. if (CompUnitName='') or (CompClassName='') or (CompName='') then ;
  428. end;
  429. { Skip properties }
  430. while NextValue <> vaNull do
  431. SkipProperty;
  432. ReadValue;
  433. { Skip children }
  434. while NextValue <> vaNull do
  435. SkipComponent(True);
  436. ReadValue;
  437. end;
  438. procedure TBinaryObjectReader.SkipValue;
  439. procedure SkipBytes(Count: LongInt);
  440. var
  441. Dummy: array[0..1023] of Byte;
  442. SkipNow: Integer;
  443. begin
  444. while Count > 0 do
  445. begin
  446. if Count > 1024 then
  447. SkipNow := 1024
  448. else
  449. SkipNow := Count;
  450. Read(Dummy, SkipNow);
  451. Dec(Count, SkipNow);
  452. end;
  453. end;
  454. var
  455. Count: LongInt;
  456. begin
  457. case ReadValue of
  458. vaNull, vaFalse, vaTrue, vaNil: ;
  459. vaList:
  460. begin
  461. while NextValue <> vaNull do
  462. SkipValue;
  463. ReadValue;
  464. end;
  465. vaInt8:
  466. SkipBytes(1);
  467. vaInt16:
  468. SkipBytes(2);
  469. vaInt32:
  470. SkipBytes(4);
  471. vaExtended:
  472. SkipBytes(10);
  473. vaString, vaIdent:
  474. ReadStr;
  475. vaBinary, vaLString:
  476. begin
  477. Count:=LongInt(ReadDWord);
  478. SkipBytes(Count);
  479. end;
  480. vaWString:
  481. begin
  482. Count:=LongInt(ReadDWord);
  483. SkipBytes(Count*sizeof(widechar));
  484. end;
  485. vaUString:
  486. begin
  487. Count:=LongInt(ReadDWord);
  488. SkipBytes(Count*sizeof(widechar));
  489. end;
  490. vaSet:
  491. SkipSetBody;
  492. vaCollection:
  493. begin
  494. while NextValue <> vaNull do
  495. begin
  496. { Skip the order value if present }
  497. if NextValue in [vaInt8, vaInt16, vaInt32] then
  498. SkipValue;
  499. SkipBytes(1);
  500. while NextValue <> vaNull do
  501. SkipProperty;
  502. ReadValue;
  503. end;
  504. ReadValue;
  505. end;
  506. vaSingle:
  507. {$ifndef FPUNONE}
  508. SkipBytes(Sizeof(Single));
  509. {$else}
  510. SkipBytes(4);
  511. {$endif}
  512. {!!!: vaCurrency:
  513. SkipBytes(SizeOf(Currency));}
  514. vaDate, vaInt64:
  515. SkipBytes(8);
  516. end;
  517. end;
  518. { private methods }
  519. procedure TBinaryObjectReader.Read(var Buf; Count: LongInt);
  520. var
  521. CopyNow: LongInt;
  522. Dest: Pointer;
  523. begin
  524. Dest := @Buf;
  525. while Count > 0 do
  526. begin
  527. if FBufPos >= FBufEnd then
  528. begin
  529. FBufEnd := FStream.Read(FBuffer^, FBufSize);
  530. if FBufEnd = 0 then
  531. raise EReadError.Create(SReadError);
  532. FBufPos := 0;
  533. end;
  534. CopyNow := FBufEnd - FBufPos;
  535. if CopyNow > Count then
  536. CopyNow := Count;
  537. Move(PAnsiChar(FBuffer)[FBufPos], Dest^, CopyNow);
  538. Inc(FBufPos, CopyNow);
  539. Inc(Dest, CopyNow);
  540. Dec(Count, CopyNow);
  541. end;
  542. end;
  543. procedure TBinaryObjectReader.SkipProperty;
  544. begin
  545. { Skip property name, then the property value }
  546. ReadStr;
  547. SkipValue;
  548. end;
  549. procedure TBinaryObjectReader.SkipSetBody;
  550. begin
  551. while Length(ReadStr) > 0 do;
  552. end;
  553. {****************************************************************************}
  554. {* TREADER *}
  555. {****************************************************************************}
  556. type
  557. TFieldInfo =
  558. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  559. packed
  560. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  561. record
  562. FieldOffset: SizeUInt;
  563. ClassTypeIndex: Word; // start at 1
  564. Name: ShortString;
  565. end;
  566. PFieldInfo = ^TFieldInfo;
  567. PPersistentClass = ^TPersistentClass;
  568. PersistentClassRef = PPersistentClass;
  569. TFieldClassTable =
  570. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  571. packed
  572. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  573. record
  574. Count: Word;
  575. Entries: array[{$ifdef cpu16}0..16384 div sizeof(PersistentClassRef){$else}Word{$endif}] of PersistentClassRef;
  576. end;
  577. PFieldClassTable = ^TFieldClassTable;
  578. TFieldTable =
  579. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  580. packed
  581. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  582. record
  583. FieldCount: Word;
  584. ClassTable: PFieldClassTable;
  585. Fields: array[0..0] of TFieldInfo;
  586. end;
  587. PFieldTable = ^TFieldTable;
  588. function GetFieldClass(Instance: TObject; const ClassName: string): TPersistentClass;
  589. var
  590. ShortClassName: shortstring;
  591. ClassType: TClass;
  592. ClassTable: PFieldClassTable;
  593. i: Integer;
  594. FieldTable: PFieldTable;
  595. begin
  596. // At first, try to locate the class in the class tables
  597. ShortClassName := ClassName;
  598. ClassType := Instance.ClassType;
  599. while ClassType <> TPersistent do
  600. begin
  601. FieldTable := PFieldTable(PVmt(ClassType)^.vFieldTable);
  602. if Assigned(FieldTable) then
  603. begin
  604. ClassTable := FieldTable^.ClassTable;
  605. for i := 0 to ClassTable^.Count - 1 do
  606. begin
  607. Result := ClassTable^.Entries[i]^;
  608. if Result.ClassNameIs(ShortClassName) then
  609. exit;
  610. end;
  611. end;
  612. // Try again with the parent class type
  613. ClassType := ClassType.ClassParent;
  614. end;
  615. Result := {$IFDEF FPC_DOTTEDUNITS}System.{$ENDIF}Classes.GetClass(ClassName);
  616. end;
  617. constructor TReader.Create(Stream: TStream; BufSize: Integer);
  618. begin
  619. inherited Create;
  620. If (Stream=Nil) then
  621. Raise EReadError.Create(SEmptyStreamIllegalReader);
  622. FDriver := CreateDriver(Stream, BufSize);
  623. {$ifdef FPC_HAS_FEATURE_THREADING}
  624. InitCriticalSection(FLock);
  625. {$ENDIF}
  626. end;
  627. destructor TReader.Destroy;
  628. begin
  629. {$ifdef FPC_HAS_FEATURE_THREADING}
  630. DoneCriticalSection(FLock);
  631. {$ENDIF}
  632. FDriver.Free;
  633. inherited Destroy;
  634. end;
  635. procedure TReader.Lock;
  636. begin
  637. {$ifdef FPC_HAS_FEATURE_THREADING}
  638. EnterCriticalSection(FLock);
  639. {$ENDIF}
  640. end;
  641. procedure TReader.Unlock;
  642. begin
  643. {$ifdef FPC_HAS_FEATURE_THREADING}
  644. LeaveCriticalSection(FLock);
  645. {$ENDIF}
  646. end;
  647. procedure TReader.FlushBuffer;
  648. begin
  649. Driver.FlushBuffer;
  650. end;
  651. function TReader.CreateDriver(Stream: TStream; BufSize: Integer): TAbstractObjectReader;
  652. begin
  653. Result := TBinaryObjectReader.Create(Stream, BufSize);
  654. end;
  655. procedure TReader.BeginReferences;
  656. begin
  657. FLoaded := TFpList.Create;
  658. end;
  659. procedure TReader.CheckValue(Value: TValueType);
  660. begin
  661. if FDriver.NextValue <> Value then
  662. raise EReadError.Create(SInvalidPropertyValue)
  663. else
  664. FDriver.ReadValue;
  665. end;
  666. procedure TReader.DefineProperty(const Name: string; AReadData: TReaderProc;
  667. WriteData: TWriterProc; HasData: Boolean);
  668. begin
  669. if Assigned(AReadData) and (UpperCase(Name) = UpperCase(FPropName)) then
  670. begin
  671. AReadData(Self);
  672. SetLength(FPropName, 0);
  673. end;
  674. end;
  675. procedure TReader.DefineBinaryProperty(const Name: string; AReadData,
  676. WriteData: TStreamProc; HasData: Boolean);
  677. var
  678. MemBuffer: TMemoryStream;
  679. begin
  680. if Assigned(AReadData) and (UpperCase(Name) = UpperCase(FPropName)) then
  681. begin
  682. { Check if the next property really is a binary property}
  683. if FDriver.NextValue <> vaBinary then
  684. begin
  685. FDriver.SkipValue;
  686. FCanHandleExcepts := True;
  687. raise EReadError.Create(SInvalidPropertyValue);
  688. end else
  689. FDriver.ReadValue;
  690. MemBuffer := TMemoryStream.Create;
  691. try
  692. FDriver.ReadBinary(MemBuffer);
  693. FCanHandleExcepts := True;
  694. AReadData(MemBuffer);
  695. finally
  696. MemBuffer.Free;
  697. end;
  698. SetLength(FPropName, 0);
  699. end;
  700. end;
  701. function TReader.EndOfList: Boolean;
  702. begin
  703. Result := FDriver.NextValue = vaNull;
  704. end;
  705. procedure TReader.EndReferences;
  706. begin
  707. FLoaded.Free;
  708. FLoaded := nil;
  709. end;
  710. function TReader.Error(const Message: string): Boolean;
  711. begin
  712. Result := False;
  713. if Assigned(FOnError) then
  714. FOnError(Self, Message, Result);
  715. end;
  716. function TReader.FindMethod(ARoot: TComponent; const AMethodName: rawbytestring): CodePointer;
  717. var
  718. ErrorResult: Boolean;
  719. begin
  720. Result := ARoot.MethodAddress(AMethodName);
  721. ErrorResult := Result = nil;
  722. { always give the OnFindMethod callback a chance to locate the method }
  723. if Assigned(FOnFindMethod) then
  724. FOnFindMethod(Self, AMethodName, Result, ErrorResult);
  725. if ErrorResult then
  726. raise EReadError.Create(SInvalidPropertyValue);
  727. end;
  728. procedure TReader.DoFixupReferences;
  729. Var
  730. R,RN : TLocalUnresolvedReference;
  731. G : TUnresolvedInstance;
  732. Ref : String;
  733. C : TComponent;
  734. P : integer;
  735. L : TLinkedList;
  736. RI: Pointer; // raw interface
  737. IIDStr: ShortString;
  738. begin
  739. If Assigned(FFixups) then
  740. begin
  741. L:=TLinkedList(FFixups);
  742. R:=TLocalUnresolvedReference(L.Root);
  743. While (R<>Nil) do
  744. begin
  745. RN:=TLocalUnresolvedReference(R.Next);
  746. Ref:=R.FRelative;
  747. If Assigned(FOnReferenceName) then
  748. FOnReferenceName(Self,Ref);
  749. C:=FindNestedComponent(R.FRoot,Ref);
  750. If Assigned(C) then
  751. if R.FPropInfo^.PropType^.Kind = tkInterface then
  752. SetInterfaceProp(R.FInstance,R.FPropInfo,C)
  753. else if R.FPropInfo^.PropType^.Kind = tkInterfaceRaw then
  754. begin
  755. IIDStr := GetTypeData(R.FPropInfo^.PropType)^.IIDStr;
  756. if IIDStr = '' then
  757. raise EReadError.CreateFmt(SInterfaceNoIIDStr, [R.FPropInfo^.PropType^.Name]);
  758. if C.GetInterface(IIDStr, RI) then
  759. SetRawInterfaceProp(R.FInstance,R.FPropInfo,RI)
  760. else
  761. raise EReadError.CreateFmt(SComponentDoesntImplement, [C.ClassName, IIDStr]);
  762. end
  763. else
  764. SetObjectProp(R.FInstance,R.FPropInfo,C)
  765. else
  766. begin
  767. P:=Pos('.',R.FRelative);
  768. If (P<>0) then
  769. begin
  770. G:=AddToResolveList(R.FInstance);
  771. G.Addreference(R.FRoot,R.FPropInfo,Copy(R.FRelative,1,P-1),Copy(R.FRelative,P+1,Length(R.FRelative)-P));
  772. end;
  773. end;
  774. L.RemoveItem(R,True);
  775. R:=RN;
  776. end;
  777. FreeAndNil(FFixups);
  778. end;
  779. end;
  780. procedure TReader.FixupReferences;
  781. var
  782. i: Integer;
  783. begin
  784. DoFixupReferences;
  785. GlobalFixupReferences;
  786. for i := 0 to FLoaded.Count - 1 do
  787. TComponent(FLoaded[I]).Loaded;
  788. end;
  789. function TReader.NextValue: TValueType;
  790. begin
  791. Result := FDriver.NextValue;
  792. end;
  793. procedure TReader.Read(var Buf; Count: LongInt);
  794. begin
  795. //This should give an exception if read is not implemented (i.e. TTextObjectReader)
  796. //but should work with TBinaryObjectReader.
  797. Driver.Read(Buf, Count);
  798. end;
  799. procedure TReader.PropertyError;
  800. begin
  801. FDriver.SkipValue;
  802. raise EReadError.CreateFmt(SUnknownProperty,[FPropName]);
  803. end;
  804. function TReader.ReadBoolean: Boolean;
  805. var
  806. ValueType: TValueType;
  807. begin
  808. ValueType := FDriver.ReadValue;
  809. if ValueType = vaTrue then
  810. Result := True
  811. else if ValueType = vaFalse then
  812. Result := False
  813. else
  814. raise EReadError.Create(SInvalidPropertyValue);
  815. end;
  816. function TReader.ReadChar: AnsiChar;
  817. var
  818. s: String;
  819. begin
  820. s := ReadString;
  821. if Length(s) = 1 then
  822. Result := s[1]
  823. else
  824. raise EReadError.Create(SInvalidPropertyValue);
  825. end;
  826. function TReader.ReadWideChar: WideChar;
  827. var
  828. W: WideString;
  829. begin
  830. W := ReadWideString;
  831. if Length(W) = 1 then
  832. Result := W[1]
  833. else
  834. raise EReadError.Create(SInvalidPropertyValue);
  835. end;
  836. function TReader.ReadUnicodeChar: UnicodeChar;
  837. var
  838. U: UnicodeString;
  839. begin
  840. U := ReadUnicodeString;
  841. if Length(U) = 1 then
  842. Result := U[1]
  843. else
  844. raise EReadError.Create(SInvalidPropertyValue);
  845. end;
  846. procedure TReader.ReadCollection(Collection: TCollection);
  847. var
  848. Item: TCollectionItem;
  849. begin
  850. Collection.BeginUpdate;
  851. if not EndOfList then
  852. Collection.Clear;
  853. while not EndOfList do begin
  854. ReadListBegin;
  855. Item := Collection.Add;
  856. while NextValue<>vaNull do
  857. ReadProperty(Item);
  858. ReadListEnd;
  859. end;
  860. Collection.EndUpdate;
  861. ReadListEnd;
  862. end;
  863. procedure TReader.SetName(aComponent: TComponent; var aName : string);
  864. begin
  865. if Assigned(FOnSetName) then
  866. FOnSetName(Self,aComponent,aName);
  867. aComponent.Name:=aName;
  868. end;
  869. function TReader.ReadComponent(Component: TComponent): TComponent;
  870. var
  871. Flags: TFilerFlags;
  872. function Recover(var aComponent: TComponent): Boolean;
  873. begin
  874. Result := False;
  875. if ExceptObject.InheritsFrom(Exception) then
  876. begin
  877. if not ((ffInherited in Flags) or Assigned(Component)) then
  878. aComponent.Free;
  879. aComponent := nil;
  880. FDriver.SkipComponent(False);
  881. Result := Error(Exception(ExceptObject).Message);
  882. end;
  883. end;
  884. var
  885. CompUnitName, CompClassName, Name: String;
  886. n, ChildPos: Integer;
  887. SavedParent, SavedLookupRoot: TComponent;
  888. ComponentClass: TComponentClass;
  889. C, NewComponent: TComponent;
  890. SubComponents: TList;
  891. begin
  892. FDriver.BeginComponent(Flags, ChildPos, CompUnitName, CompClassName, Name);
  893. SavedParent := Parent;
  894. SavedLookupRoot := FLookupRoot;
  895. SubComponents := nil;
  896. try
  897. Result := Component;
  898. if not Assigned(Result) then
  899. try
  900. if ffInherited in Flags then
  901. begin
  902. { Try to locate the existing ancestor component }
  903. if Assigned(FLookupRoot) then
  904. Result := FLookupRoot.FindComponent(Name)
  905. else
  906. Result := nil;
  907. if not Assigned(Result) then
  908. begin
  909. if Assigned(FOnAncestorNotFound) then
  910. FOnAncestorNotFound(Self, Name,
  911. FindComponentClass(Name,CompUnitName,CompClassName), Result);
  912. if not Assigned(Result) then
  913. raise EReadError.CreateFmt(SAncestorNotFound, [Name]);
  914. end;
  915. Parent := Result.GetParentComponent;
  916. if not Assigned(Parent) then
  917. Parent := Root;
  918. end else
  919. begin
  920. Result := nil;
  921. ComponentClass := FindComponentClass(Name,CompUnitName,CompClassName);
  922. if Assigned(FOnCreateComponent) then
  923. FOnCreateComponent(Self, ComponentClass, Result);
  924. if not Assigned(Result) then
  925. begin
  926. NewComponent := TComponent(ComponentClass.NewInstance);
  927. if ffInline in Flags then
  928. NewComponent.FComponentState :=
  929. NewComponent.FComponentState + [csLoading, csInline];
  930. NewComponent.Create(Owner);
  931. { Don't set Result earlier because else we would come in trouble
  932. with the exception recover mechanism! (Result should be NIL if
  933. an error occurred) }
  934. Result := NewComponent;
  935. end;
  936. Include(Result.FComponentState, csLoading);
  937. end;
  938. except
  939. if not Recover(Result) then
  940. raise;
  941. end;
  942. if Assigned(Result) then
  943. try
  944. Include(Result.FComponentState, csLoading);
  945. { create list of subcomponents and set loading}
  946. SubComponents := TList.Create;
  947. for n := 0 to Result.ComponentCount - 1 do
  948. begin
  949. C := Result.Components[n];
  950. if csSubcomponent in C.ComponentStyle
  951. then begin
  952. SubComponents.Add(C);
  953. Include(C.FComponentState, csLoading);
  954. end;
  955. end;
  956. if not (ffInherited in Flags) then
  957. try
  958. Result.SetParentComponent(Parent);
  959. SetName(Result,Name);
  960. if FindGlobalComponent(Name) = Result then
  961. Include(Result.FComponentState, csInline);
  962. except
  963. if not Recover(Result) then
  964. raise;
  965. end;
  966. if not Assigned(Result) then
  967. exit;
  968. if csInline in Result.ComponentState then
  969. FLookupRoot := Result;
  970. { Read the component state }
  971. Include(Result.FComponentState, csReading);
  972. for n := 0 to Subcomponents.Count - 1 do
  973. Include(TComponent(Subcomponents[n]).FComponentState, csReading);
  974. Result.ReadState(Self);
  975. Exclude(Result.FComponentState, csReading);
  976. for n := 0 to Subcomponents.Count - 1 do
  977. Exclude(TComponent(Subcomponents[n]).FComponentState, csReading);
  978. if ffChildPos in Flags then
  979. Parent.SetChildOrder(Result, ChildPos);
  980. { Add component to list of loaded components, if necessary }
  981. if (not ((ffInherited in Flags) or (csInline in Result.ComponentState))) or
  982. (FLoaded.IndexOf(Result) < 0)
  983. then begin
  984. for n := 0 to Subcomponents.Count - 1 do
  985. FLoaded.Add(Subcomponents[n]);
  986. FLoaded.Add(Result);
  987. end;
  988. except
  989. if ((ffInherited in Flags) or Assigned(Component)) then
  990. Result.Free;
  991. raise;
  992. end;
  993. finally
  994. Parent := SavedParent;
  995. FLookupRoot := SavedLookupRoot;
  996. Subcomponents.Free;
  997. end;
  998. end;
  999. procedure TReader.SkipValue;
  1000. begin
  1001. FDriver.SkipValue;
  1002. end;
  1003. procedure TReader.ReadData(Instance: TComponent);
  1004. var
  1005. SavedOwner, SavedParent: TComponent;
  1006. begin
  1007. { Read properties }
  1008. while not EndOfList do
  1009. ReadProperty(Instance);
  1010. ReadListEnd;
  1011. { Read children }
  1012. SavedOwner := Owner;
  1013. SavedParent := Parent;
  1014. try
  1015. Owner := Instance.GetChildOwner;
  1016. if not Assigned(Owner) then
  1017. Owner := Root;
  1018. Parent := Instance.GetChildParent;
  1019. while not EndOfList do
  1020. ReadComponent(nil);
  1021. ReadListEnd;
  1022. finally
  1023. Owner := SavedOwner;
  1024. Parent := SavedParent;
  1025. end;
  1026. { Fixup references if necessary (normally only if this is the root) }
  1027. If (Instance=FRoot) then
  1028. DoFixupReferences;
  1029. end;
  1030. {$ifndef FPUNONE}
  1031. function TReader.ReadFloat: Extended;
  1032. begin
  1033. if FDriver.NextValue = vaExtended then
  1034. begin
  1035. ReadValue;
  1036. Result := FDriver.ReadFloat
  1037. end else
  1038. Result := ReadInt64;
  1039. end;
  1040. function TReader.ReadDouble: Double;
  1041. begin
  1042. // We have no vaDouble
  1043. Case FDriver.NextValue of
  1044. vaExtended:
  1045. begin
  1046. ReadValue;
  1047. Result := FDriver.ReadFloat
  1048. end;
  1049. vaSingle:
  1050. begin
  1051. ReadValue;
  1052. Result := FDriver.ReadSingle
  1053. end;
  1054. vaDouble:
  1055. begin
  1056. ReadValue;
  1057. Result := FDriver.ReadDouble
  1058. end;
  1059. else
  1060. Result := ReadInt64;
  1061. end
  1062. end;
  1063. procedure TReader.ReadSignature;
  1064. begin
  1065. FDriver.ReadSignature;
  1066. end;
  1067. function TReader.ReadSingle: Single;
  1068. var
  1069. vt : TValueType;
  1070. begin
  1071. vt:=FDriver.NextValue;
  1072. Case vt of
  1073. vaSingle :
  1074. begin
  1075. FDriver.ReadValue;
  1076. Result := FDriver.ReadSingle;
  1077. end;
  1078. vaDouble :
  1079. begin
  1080. FDriver.ReadValue;
  1081. Result := FDriver.ReadDouble;
  1082. end;
  1083. vaExtended :
  1084. begin
  1085. FDriver.ReadValue;
  1086. Result := FDriver.ReadFloat;
  1087. end;
  1088. else
  1089. Result := ReadInteger;
  1090. end;
  1091. end;
  1092. {$endif}
  1093. function TReader.ReadCurrency: Currency;
  1094. begin
  1095. if FDriver.NextValue = vaCurrency then
  1096. begin
  1097. FDriver.ReadValue;
  1098. Result := FDriver.ReadCurrency;
  1099. end else
  1100. Result := ReadInteger;
  1101. end;
  1102. {$ifndef FPUNONE}
  1103. function TReader.ReadDate: TDateTime;
  1104. begin
  1105. if FDriver.NextValue = vaDate then
  1106. begin
  1107. FDriver.ReadValue;
  1108. Result := FDriver.ReadDate;
  1109. end else
  1110. Result := ReadInteger;
  1111. end;
  1112. {$endif}
  1113. function TReader.ReadIdent: rawbytestring;
  1114. var
  1115. ValueType: TValueType;
  1116. begin
  1117. ValueType := FDriver.ReadValue;
  1118. if ValueType in [vaIdent, vaNil, vaFalse, vaTrue, vaNull] then
  1119. Result := FDriver.ReadIdent(ValueType)
  1120. else
  1121. raise EReadError.Create(SInvalidPropertyValue);
  1122. end;
  1123. function TReader.ReadInteger: Longint;
  1124. begin
  1125. case FDriver.ReadValue of
  1126. vaInt8:
  1127. Result := FDriver.ReadInt8;
  1128. vaInt16:
  1129. Result := FDriver.ReadInt16;
  1130. vaInt32:
  1131. Result := FDriver.ReadInt32;
  1132. else
  1133. raise EReadError.Create(SInvalidPropertyValue);
  1134. end;
  1135. end;
  1136. function TReader.ReadInt64: Int64;
  1137. begin
  1138. if FDriver.NextValue = vaInt64 then
  1139. begin
  1140. FDriver.ReadValue;
  1141. Result := FDriver.ReadInt64;
  1142. end else
  1143. Result := ReadInteger;
  1144. end;
  1145. function TReader.ReadSet(EnumType: Pointer): Integer;
  1146. begin
  1147. if FDriver.NextValue = vaSet then
  1148. begin
  1149. FDriver.ReadValue;
  1150. Result := FDriver.ReadSet(enumtype);
  1151. end
  1152. else
  1153. Result := ReadInteger;
  1154. end;
  1155. procedure TReader.ReadListBegin;
  1156. begin
  1157. CheckValue(vaList);
  1158. end;
  1159. procedure TReader.ReadListEnd;
  1160. begin
  1161. CheckValue(vaNull);
  1162. end;
  1163. function TReader.ReadVariant: Variant;
  1164. var
  1165. nv: TValueType;
  1166. begin
  1167. { Ensure that a Variant manager is installed }
  1168. if not Assigned(VarClearProc) then
  1169. raise EReadError.Create(SErrNoVariantSupport);
  1170. Result:=default(variant);
  1171. nv:=NextValue;
  1172. case nv of
  1173. vaNil:
  1174. begin
  1175. Result:=system.unassigned;
  1176. readvalue;
  1177. end;
  1178. vaNull:
  1179. begin
  1180. Result:=system.null;
  1181. readvalue;
  1182. end;
  1183. { all integer sizes must be split for big endian systems }
  1184. vaInt8,vaInt16,vaInt32:
  1185. begin
  1186. Result:=ReadInteger;
  1187. end;
  1188. vaInt64:
  1189. begin
  1190. Result:=ReadInt64;
  1191. end;
  1192. vaQWord:
  1193. begin
  1194. Result:=QWord(ReadInt64);
  1195. end;
  1196. vaFalse,vaTrue:
  1197. begin
  1198. Result:=(nv<>vaFalse);
  1199. readValue;
  1200. end;
  1201. vaCurrency:
  1202. begin
  1203. Result:=ReadCurrency;
  1204. end;
  1205. {$ifndef fpunone}
  1206. vaSingle:
  1207. begin
  1208. Result:=ReadSingle;
  1209. end;
  1210. vaExtended:
  1211. begin
  1212. Result:=ReadFloat;
  1213. end;
  1214. vaDate:
  1215. begin
  1216. Result:=ReadDate;
  1217. end;
  1218. {$endif fpunone}
  1219. vaWString,vaUTF8String:
  1220. begin
  1221. Result:=ReadWideString;
  1222. end;
  1223. vaString:
  1224. begin
  1225. Result:=ReadString;
  1226. end;
  1227. vaUString:
  1228. begin
  1229. Result:=ReadUnicodeString;
  1230. end;
  1231. else
  1232. raise EReadError.CreateFmt(SUnsupportedPropertyVariantType, [Ord(nv)]);
  1233. end;
  1234. end;
  1235. procedure TReader.ReadProperty(AInstance: TPersistent);
  1236. var
  1237. Path: RawByteString;
  1238. Instance: TPersistent;
  1239. DotPos, NextPos: PAnsiChar;
  1240. PropInfo: PPropInfo;
  1241. Obj: TObject;
  1242. Name: String;
  1243. Skip: Boolean;
  1244. Handled: Boolean;
  1245. OldPropName: String;
  1246. function HandleMissingProperty(IsPath: Boolean): boolean;
  1247. Var
  1248. lPropName : String;
  1249. begin
  1250. Result:=true;
  1251. if Assigned(OnPropertyNotFound) then begin
  1252. // user defined property error handling
  1253. OldPropName:=FPropName;
  1254. lPropName:=FPropName;
  1255. Handled:=false;
  1256. Skip:=false;
  1257. OnPropertyNotFound(Self,Instance,lPropName,IsPath,Handled,Skip);
  1258. if Handled and (not Skip) and (OldPropName<>lPropName) then
  1259. // try alias property
  1260. begin
  1261. FPropName:=lPropName;
  1262. PropInfo := GetPropInfo(Instance.ClassInfo, FPropName);
  1263. end;
  1264. if Skip then begin
  1265. FDriver.SkipValue;
  1266. Result:=false;
  1267. exit;
  1268. end;
  1269. end;
  1270. end;
  1271. begin
  1272. try
  1273. Path := FDriver.BeginProperty;
  1274. try
  1275. Instance := AInstance;
  1276. FCanHandleExcepts := True;
  1277. DotPos := PAnsiChar(Path);
  1278. while True do
  1279. begin
  1280. NextPos := StrScan(DotPos, '.');
  1281. if Assigned(NextPos) then
  1282. FPropName := Copy(String(DotPos), 1, Integer(NextPos - DotPos))
  1283. else
  1284. begin
  1285. FPropName := DotPos;
  1286. break;
  1287. end;
  1288. DotPos := NextPos + 1;
  1289. PropInfo := GetPropInfo(Instance.ClassInfo, FPropName);
  1290. if not Assigned(PropInfo) then begin
  1291. if not HandleMissingProperty(true) then Exit;
  1292. if not Assigned(PropInfo) then
  1293. Break; // Defineproperties deserves a shot.
  1294. end;
  1295. if PropInfo^.PropType^.Kind = tkClass then
  1296. Obj := TObject(GetObjectProp(Instance, PropInfo))
  1297. //else if PropInfo^.PropType^.Kind = tkInterface then
  1298. // Obj := TObject(GetInterfaceProp(Instance, PropInfo))
  1299. else
  1300. Obj := nil;
  1301. if not (Obj is TPersistent) then
  1302. begin
  1303. { All path elements must be persistent objects! }
  1304. FDriver.SkipValue;
  1305. raise EReadError.Create(SInvalidPropertyPath);
  1306. end;
  1307. Instance := TPersistent(Obj);
  1308. end;
  1309. PropInfo := GetPropInfo(Instance.ClassInfo, FPropName);
  1310. if Assigned(PropInfo) then
  1311. ReadPropValue(Instance, PropInfo)
  1312. else
  1313. begin
  1314. FCanHandleExcepts := False;
  1315. if Instance=aInstance then
  1316. begin
  1317. // Use case:
  1318. // DefineProperty('Size.X',proc1,proc2,True)
  1319. FPropName:=Path;
  1320. end;
  1321. Instance.DefineProperties(Self);
  1322. FCanHandleExcepts := True;
  1323. if Length(FPropName) > 0 then begin
  1324. if not HandleMissingProperty(false) then exit;
  1325. if not Assigned(PropInfo) then
  1326. PropertyError;
  1327. end;
  1328. end;
  1329. except
  1330. on e: Exception do
  1331. begin
  1332. SetLength(Name, 0);
  1333. if AInstance.InheritsFrom(TComponent) then
  1334. Name := TComponent(AInstance).Name;
  1335. if Length(Name) = 0 then
  1336. Name := AInstance.ClassName;
  1337. raise EReadError.CreateFmt(SPropertyException,
  1338. [Name, DotSep, Path, e.Message]);
  1339. end;
  1340. end;
  1341. except
  1342. on e: Exception do
  1343. if not FCanHandleExcepts or not Error(E.Message) then
  1344. raise;
  1345. end;
  1346. end;
  1347. procedure TReader.ReadPropValue(Instance: TPersistent; PropInfo: Pointer);
  1348. const
  1349. NullMethod: TMethod = (Code: nil; Data: nil);
  1350. var
  1351. PropType: PTypeInfo;
  1352. Value: LongInt;
  1353. { IdentToIntFn: TIdentToInt; }
  1354. Ident: RawByteString;
  1355. Method: TMethod;
  1356. Handled: Boolean;
  1357. TmpStr: String;
  1358. uTmpStr : UnicodeString;
  1359. begin
  1360. if not Assigned(PPropInfo(PropInfo)^.SetProc) then
  1361. raise EReadError.Create(SReadOnlyProperty);
  1362. PropType := PPropInfo(PropInfo)^.PropType;
  1363. case PropType^.Kind of
  1364. tkInteger:
  1365. if FDriver.NextValue = vaIdent then
  1366. begin
  1367. Ident := ReadIdent;
  1368. if GlobalIdentToInt(Ident,Value) then
  1369. SetOrdProp(Instance, PropInfo, Value)
  1370. else
  1371. raise EReadError.Create(SInvalidPropertyValue);
  1372. end else
  1373. SetOrdProp(Instance, PropInfo, ReadInteger);
  1374. tkBool:
  1375. SetOrdProp(Instance, PropInfo, Ord(ReadBoolean));
  1376. tkChar:
  1377. SetOrdProp(Instance, PropInfo, Ord(ReadChar));
  1378. tkWChar,tkUChar:
  1379. SetOrdProp(Instance, PropInfo, Ord(ReadWideChar));
  1380. tkEnumeration:
  1381. begin
  1382. Value := GetEnumValue(PropType, ReadIdent);
  1383. if Value = -1 then
  1384. raise EReadError.Create(SInvalidPropertyValue);
  1385. SetOrdProp(Instance, PropInfo, Value);
  1386. end;
  1387. {$ifndef FPUNONE}
  1388. tkFloat:
  1389. SetFloatProp(Instance, PropInfo, ReadFloat);
  1390. {$endif}
  1391. tkSet:
  1392. begin
  1393. CheckValue(vaSet);
  1394. SetOrdProp(Instance, PropInfo,
  1395. FDriver.ReadSet(GetTypeData(PropType)^.CompType));
  1396. end;
  1397. tkMethod:
  1398. if FDriver.NextValue = vaNil then
  1399. begin
  1400. FDriver.ReadValue;
  1401. SetMethodProp(Instance, PropInfo, NullMethod);
  1402. end else
  1403. begin
  1404. Handled:=false;
  1405. Ident:=ReadIdent;
  1406. if Assigned(OnSetMethodProperty) then
  1407. OnSetMethodProperty(Self,Instance,PPropInfo(PropInfo),Ident,
  1408. Handled);
  1409. if not Handled then begin
  1410. Method.Code := FindMethod(Root, Ident);
  1411. Method.Data := Root;
  1412. if Assigned(Method.Code) then
  1413. SetMethodProp(Instance, PropInfo, Method);
  1414. end;
  1415. end;
  1416. tkSString, tkLString, tkAString:
  1417. begin
  1418. TmpStr:=ReadString;
  1419. if Assigned(FOnReadStringProperty) then
  1420. FOnReadStringProperty(Self,Instance,PropInfo,TmpStr);
  1421. SetStrProp(Instance, PropInfo, TmpStr);
  1422. end;
  1423. tkUstring:
  1424. begin
  1425. uTmpStr:=ReadUnicodeString;
  1426. {$IFDEF UNICODERTL}
  1427. if Assigned(FOnReadStringProperty) then
  1428. FOnReadStringProperty(Self,Instance,PropInfo,uTmpStr);
  1429. {$ENDIF}
  1430. SetUnicodeStrProp(Instance,PropInfo,uTmpStr);
  1431. end;
  1432. tkWString:
  1433. SetWideStrProp(Instance,PropInfo,ReadWideString);
  1434. tkVariant:
  1435. begin
  1436. SetVariantProp(Instance,PropInfo,ReadVariant);
  1437. end;
  1438. tkClass, tkInterface, tkInterfaceRaw:
  1439. case FDriver.NextValue of
  1440. vaNil:
  1441. begin
  1442. FDriver.ReadValue;
  1443. SetOrdProp(Instance, PropInfo, 0)
  1444. end;
  1445. vaCollection:
  1446. begin
  1447. FDriver.ReadValue;
  1448. ReadCollection(TCollection(GetObjectProp(Instance, PropInfo)));
  1449. end
  1450. else
  1451. begin
  1452. If Not Assigned(FFixups) then
  1453. FFixups:=TLinkedList.Create(TLocalUnresolvedReference);
  1454. With TLocalUnresolvedReference(TLinkedList(FFixups).Add) do
  1455. begin
  1456. FInstance:=Instance;
  1457. FRoot:=Root;
  1458. FPropInfo:=PropInfo;
  1459. FRelative:=ReadIdent;
  1460. end;
  1461. end;
  1462. end;
  1463. tkInt64, tkQWord: SetInt64Prop(Instance, PropInfo, ReadInt64);
  1464. else
  1465. raise EReadError.CreateFmt(SUnknownPropertyType, [Ord(PropType^.Kind)]);
  1466. end;
  1467. end;
  1468. procedure TReader.ReadPrefix(var aFlags: TFilerFlags; var aChildPos: Integer);
  1469. var
  1470. CompUnitName, CompClassName, CompName : String;
  1471. begin
  1472. if RawMode then
  1473. Driver.ReadPrefix(aFlags,aChildPos)
  1474. else
  1475. Driver.BeginComponent(aFlags,aChildPos, CompUnitName, CompClassName, CompName);
  1476. end;
  1477. function TReader.ReadRootComponent(ARoot: TComponent): TComponent;
  1478. var
  1479. Dummy, i: Integer;
  1480. Flags: TFilerFlags;
  1481. CompUnitName, CompClassName, CompName, ResultName: String;
  1482. begin
  1483. FDriver.BeginRootComponent;
  1484. Result := nil;
  1485. {!!!: GlobalNameSpace.BeginWrite; // Loading from stream adds to name space
  1486. try}
  1487. try
  1488. FDriver.BeginComponent(Flags, Dummy, CompUnitName, CompClassName, CompName);
  1489. if not Assigned(ARoot) then
  1490. begin
  1491. { Read the class name and the object name and create a new object: }
  1492. Result := TComponentClass(FindClass(CompUnitName,CompClassName)).Create(nil);
  1493. Result.Name := CompName;
  1494. end else
  1495. begin
  1496. Result := ARoot;
  1497. if not (csDesigning in Result.ComponentState) then
  1498. begin
  1499. Result.FComponentState :=
  1500. Result.FComponentState + [csLoading, csReading];
  1501. { We need an unique name }
  1502. i := 0;
  1503. { Don't use Result.Name directly, as this would influence
  1504. FindGlobalComponent in successive loop runs }
  1505. ResultName := CompName;
  1506. Lock;
  1507. try
  1508. if ResultName<>'' then
  1509. while Assigned(FindGlobalComponent(ResultName)) do
  1510. begin
  1511. Inc(i);
  1512. ResultName := CompName + '_' + IntToStr(i);
  1513. end;
  1514. Result.Name := ResultName;
  1515. finally
  1516. Unlock;
  1517. end;
  1518. end;
  1519. end;
  1520. FRoot := Result;
  1521. FLookupRoot := Result;
  1522. if Assigned(GlobalLoaded) then
  1523. FLoaded := GlobalLoaded
  1524. else
  1525. FLoaded := TFpList.Create;
  1526. try
  1527. if FLoaded.IndexOf(FRoot) < 0 then
  1528. FLoaded.Add(FRoot);
  1529. FOwner := FRoot;
  1530. FRoot.FComponentState := FRoot.FComponentState + [csLoading, csReading];
  1531. FRoot.ReadState(Self);
  1532. Exclude(FRoot.FComponentState, csReading);
  1533. if not Assigned(GlobalLoaded) then
  1534. for i := 0 to FLoaded.Count - 1 do
  1535. TComponent(FLoaded[i]).Loaded;
  1536. finally
  1537. if not Assigned(GlobalLoaded) then
  1538. FLoaded.Free;
  1539. FLoaded := nil;
  1540. end;
  1541. GlobalFixupReferences;
  1542. except
  1543. RemoveFixupReferences(ARoot, '');
  1544. if not Assigned(ARoot) then
  1545. Result.Free;
  1546. raise;
  1547. end;
  1548. {finally
  1549. GlobalNameSpace.EndWrite;
  1550. end;}
  1551. end;
  1552. procedure TReader.ReadComponents(AOwner, AParent: TComponent;
  1553. Proc: TReadComponentsProc);
  1554. var
  1555. Component: TComponent;
  1556. begin
  1557. Root := AOwner;
  1558. Owner := AOwner;
  1559. Parent := AParent;
  1560. BeginReferences;
  1561. try
  1562. while not EndOfList do
  1563. begin
  1564. FDriver.BeginRootComponent;
  1565. Component := ReadComponent(nil);
  1566. if Assigned(Proc) then
  1567. Proc(Component);
  1568. end;
  1569. ReadListEnd;
  1570. FixupReferences;
  1571. finally
  1572. EndReferences;
  1573. end;
  1574. end;
  1575. function TReader.ReadStr: RawByteString;
  1576. Var
  1577. Curr : TValueType;
  1578. begin
  1579. Curr:=Driver.CurrentValue;
  1580. if RawMode then
  1581. Curr:=vaString;
  1582. Result:=DoReadString(Curr);
  1583. end;
  1584. function TReader.DoReadString(aType : TValueType): rawbytestring;
  1585. begin
  1586. Case aType of
  1587. vaString, vaLString,vaUTF8String:
  1588. begin
  1589. Result := FDriver.ReadString(aType);
  1590. if (aType=vaUTF8String) then
  1591. Result:=rawbytestring(utf8Decode(Result));
  1592. end;
  1593. vaWString:
  1594. Result:= rawbytestring(FDriver.ReadWidestring);
  1595. vaUString:
  1596. Result:= rawbytestring(FDriver.ReadUnicodeString);
  1597. else
  1598. raise EReadError.Create(SInvalidPropertyValue);
  1599. end;
  1600. end;
  1601. function TReader.ReadString: RawBytestring;
  1602. begin
  1603. Result:=DoReadString(FDriver.ReadValue);
  1604. end;
  1605. function TReader.ReadWideString: WideString;
  1606. var
  1607. s: RawByteString;
  1608. i: Integer;
  1609. vt:TValueType;
  1610. begin
  1611. if NextValue in [vaWString,vaUString,vaUTF8String] then
  1612. //vaUTF8String needs conversion? 2008-09-06 mse, YES!! AntonK
  1613. begin
  1614. vt:=ReadValue;
  1615. if vt=vaUTF8String then
  1616. Result := utf8decode(fDriver.ReadString(vaLString))
  1617. else
  1618. Result := FDriver.ReadWideString
  1619. end
  1620. else
  1621. begin
  1622. //data probable from ObjectTextToBinary
  1623. s := ReadString;
  1624. setlength(result,length(s));
  1625. for i:= 1 to length(s) do begin
  1626. result[i]:= widechar(ord(s[i])); //no code conversion
  1627. end;
  1628. end;
  1629. end;
  1630. function TReader.ReadUnicodeString: UnicodeString;
  1631. var
  1632. s: RawByteString;
  1633. i: Integer;
  1634. vt:TValueType;
  1635. begin
  1636. if NextValue in [vaWString,vaUString,vaUTF8String] then
  1637. //vaUTF8String needs conversion? 2008-09-06 mse, YES!! AntonK
  1638. begin
  1639. vt:=ReadValue;
  1640. if vt=vaUTF8String then
  1641. Result := utf8decode(fDriver.ReadString(vaLString))
  1642. else
  1643. Result := FDriver.ReadWideString
  1644. end
  1645. else
  1646. begin
  1647. //data probable from ObjectTextToBinary
  1648. s := ReadString;
  1649. setlength(result,length(s));
  1650. for i:= 1 to length(s) do begin
  1651. result[i]:= UnicodeChar(ord(s[i])); //no code conversion
  1652. end;
  1653. end;
  1654. end;
  1655. function TReader.ReadValue: TValueType;
  1656. begin
  1657. Result := FDriver.ReadValue;
  1658. end;
  1659. procedure TReader.CopyValue(Writer: TWriter);
  1660. procedure CopyBytes(Count: Integer);
  1661. { var
  1662. Buffer: array[0..1023] of Byte; }
  1663. begin
  1664. {!!!: while Count > 1024 do
  1665. begin
  1666. FDriver.Read(Buffer, 1024);
  1667. Writer.Driver.Write(Buffer, 1024);
  1668. Dec(Count, 1024);
  1669. end;
  1670. if Count > 0 then
  1671. begin
  1672. FDriver.Read(Buffer, Count);
  1673. Writer.Driver.Write(Buffer, Count);
  1674. end;}
  1675. end;
  1676. {var
  1677. s: String;
  1678. Count: LongInt; }
  1679. begin
  1680. case FDriver.NextValue of
  1681. vaNull:
  1682. Writer.WriteIdent('NULL');
  1683. vaFalse:
  1684. Writer.WriteIdent('FALSE');
  1685. vaTrue:
  1686. Writer.WriteIdent('TRUE');
  1687. vaNil:
  1688. Writer.WriteIdent('NIL');
  1689. {!!!: vaList, vaCollection:
  1690. begin
  1691. Writer.WriteValue(FDriver.ReadValue);
  1692. while not EndOfList do
  1693. CopyValue(Writer);
  1694. ReadListEnd;
  1695. Writer.WriteListEnd;
  1696. end;}
  1697. vaInt8, vaInt16, vaInt32:
  1698. Writer.WriteInteger(ReadInteger);
  1699. {$ifndef FPUNONE}
  1700. vaExtended:
  1701. Writer.WriteFloat(ReadFloat);
  1702. {$endif}
  1703. {!!!: vaString:
  1704. Writer.WriteStr(ReadStr);}
  1705. vaIdent:
  1706. Writer.WriteIdent(ReadIdent);
  1707. {!!!: vaBinary, vaLString, vaWString:
  1708. begin
  1709. Writer.WriteValue(FDriver.ReadValue);
  1710. FDriver.Read(Count, SizeOf(Count));
  1711. Writer.Driver.Write(Count, SizeOf(Count));
  1712. CopyBytes(Count);
  1713. end;}
  1714. {!!!: vaSet:
  1715. Writer.WriteSet(ReadSet);}
  1716. {$ifndef FPUNONE}
  1717. vaSingle:
  1718. Writer.WriteSingle(ReadSingle);
  1719. {$endif}
  1720. {!!!: vaCurrency:
  1721. Writer.WriteCurrency(ReadCurrency);}
  1722. {$ifndef FPUNONE}
  1723. vaDate:
  1724. Writer.WriteDate(ReadDate);
  1725. {$endif}
  1726. vaInt64:
  1727. Writer.WriteInteger(ReadInt64);
  1728. end;
  1729. end;
  1730. function TReader.FindComponentClass(const AName, anUnitName, AClassName: rawbytestring
  1731. ): TComponentClass;
  1732. var
  1733. PersistentClass: TPersistentClass;
  1734. ShortName, ShortClassName: shortstring;
  1735. function FindInFieldTable(Instance: TComponent): TComponentClass;
  1736. var
  1737. aClassType: TClass;
  1738. FieldTable: PFieldTable;
  1739. ClassTable: PFieldClassTable;
  1740. i: Integer;
  1741. FieldInfo: PFieldInfo;
  1742. PersistenClass: TPersistentClass;
  1743. begin
  1744. //writeln('FindInFieldTable Instance=',Instance.Name,':',Instance.UnitName,'>',Instance.ClassName,' ShortName="',ShortName,'" ShortClassName="',ShortClassName,'"');
  1745. Result:=nil;
  1746. // search field by name
  1747. aClassType := Instance.ClassType;
  1748. while aClassType <> TPersistent do
  1749. begin
  1750. FieldTable := PFieldTable(PVmt(aClassType)^.vFieldTable);
  1751. if Assigned(FieldTable) then
  1752. begin
  1753. ClassTable := FieldTable^.ClassTable;
  1754. FieldInfo := @FieldTable^.Fields[0];
  1755. for i := 0 to FieldTable^.FieldCount - 1 do
  1756. begin
  1757. //writeln('FindInFieldTable Instance=',Instance.ClassName,' FieldInfo ',i,'/',FieldTable^.FieldCount,' ',FieldInfo^.Name);
  1758. if ShortCompareText(FieldInfo^.Name,ShortName)=0 then
  1759. begin
  1760. PersistenClass := ClassTable^.Entries[FieldInfo^.ClassTypeIndex-1]^;
  1761. //writeln('FindInFieldTable Found Field "',FieldInfo^.Name,'" Class="',PersistenClass.UnitName,'>',PersistenClass.ClassName,'"');
  1762. if PersistenClass.ClassNameIs(ShortClassName)
  1763. and PersistenClass.InheritsFrom(TComponent) then
  1764. exit(TComponentClass(PersistenClass));
  1765. end;
  1766. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  1767. FieldInfo := PFieldInfo(PByte(@FieldInfo^.Name) + 1 + Length(FieldInfo^.Name));
  1768. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  1769. FieldInfo := PFieldInfo(align(PByte(@FieldInfo^.Name) + 1 + Length(FieldInfo^.Name), sizeof(SizeUInt)));
  1770. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  1771. end;
  1772. end;
  1773. // Try again with the parent class type
  1774. aClassType := aClassType.ClassParent;
  1775. end;
  1776. // search class
  1777. aClassType := Instance.ClassType;
  1778. while aClassType <> TPersistent do
  1779. begin
  1780. FieldTable := PFieldTable(PVmt(aClassType)^.vFieldTable);
  1781. if Assigned(FieldTable) then
  1782. begin
  1783. ClassTable := FieldTable^.ClassTable;
  1784. for i := 0 to ClassTable^.Count - 1 do
  1785. begin
  1786. PersistenClass := ClassTable^.Entries[i]^;
  1787. if PersistenClass.ClassNameIs(ShortClassName)
  1788. and PersistenClass.InheritsFrom(TComponent) then
  1789. begin
  1790. if (anUnitName='') or SameText(PersistenClass.UnitName,anUnitName) then
  1791. exit(TComponentClass(PersistenClass));
  1792. end;
  1793. end;
  1794. end;
  1795. // Try again with the parent class type
  1796. aClassType := aClassType.ClassParent;
  1797. end;
  1798. Result:=nil;
  1799. end;
  1800. begin
  1801. ShortName:=AName;
  1802. ShortClassName:=AClassName;
  1803. Result:=FindInFieldTable(Root);
  1804. if (Result=nil) and assigned(LookupRoot) and (LookupRoot<>Root) then
  1805. FindInFieldTable(LookupRoot);
  1806. if (Result=nil) and assigned(OnFindComponentClassEx) then
  1807. OnFindComponentClassEx(Self, AName, anUnitName, AClassName, Result);
  1808. if (Result=nil) then begin
  1809. if anUnitName<>'' then
  1810. PersistentClass := GetClass(anUnitName,AClassName)
  1811. else
  1812. PersistentClass := GetClass(AClassName);
  1813. if PersistentClass.InheritsFrom(TComponent) then
  1814. Result := TComponentClass(PersistentClass);
  1815. end;
  1816. if (Result=nil) and assigned(OnFindComponentClass) then
  1817. OnFindComponentClass(Self, AClassName, Result);
  1818. if (Result=nil) or (not Result.InheritsFrom(TComponent)) then
  1819. if anUnitName<>'' then
  1820. raise EClassNotFound.CreateFmt(SNoFieldOfClassIn, [anUnitName+'/'+AClassName, Root.ClassName])
  1821. else
  1822. raise EClassNotFound.CreateFmt(SNoFieldOfClassIn, [AClassName, Root.ClassName]);
  1823. end;
  1824. function TReader.ReadComponentDeltaRes(Instance: TComponent; const DeltaCandidates: array of Ansistring; const Proc: TGetStreamProc): TComponent;
  1825. var
  1826. ResHandle: THandle;
  1827. RootName, Delta, DeltaName: AnsiString;
  1828. S: TStream;
  1829. begin
  1830. if (Instance=nil) or not Assigned(Proc) then
  1831. Raise EArgumentNilException.Create(SArgumentNil);
  1832. Result:=Instance;
  1833. RootName:=Instance.ClassName;
  1834. for Delta in DeltaCandidates do
  1835. begin
  1836. DeltaName:=RootName+'_'+Delta;
  1837. // No module support yet
  1838. ResHandle:=System.FindResource(Nilhandle,DeltaName, PAnsiChar(RT_RCDATA));
  1839. if ResHandle<>NilHandle then
  1840. Break;
  1841. end;
  1842. if ResHandle=NilHandle then
  1843. exit;
  1844. {$ifdef FPC_OS_UNICODE}
  1845. // Wince
  1846. S:=TResourceStream.Create(NilHandle,DeltaName, PWideChar(RT_RCDATA));
  1847. {$ELSE}
  1848. S:=TResourceStream.Create(NilHandle,DeltaName, PAnsiChar(RT_RCDATA));
  1849. {$ENDIF}
  1850. try
  1851. Proc(S);
  1852. finally
  1853. S.Free;
  1854. end;
  1855. end;
  1856. { TAbstractObjectReader }
  1857. procedure TAbstractObjectReader.FlushBuffer;
  1858. begin
  1859. // Do nothing
  1860. end;