reader.inc 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289
  1. {
  2. $Id$
  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. constructor TBinaryObjectReader.Create(Stream: TStream; BufSize: Integer);
  15. begin
  16. inherited Create;
  17. FStream := Stream;
  18. FBufSize := BufSize;
  19. GetMem(FBuffer, BufSize);
  20. end;
  21. destructor TBinaryObjectReader.Destroy;
  22. begin
  23. { Seek back the amount of bytes that we didn't process until now: }
  24. FStream.Seek(Integer(FBufPos) - Integer(FBufEnd), soFromCurrent);
  25. if Assigned(FBuffer) then
  26. FreeMem(FBuffer, FBufSize);
  27. inherited Destroy;
  28. end;
  29. function TBinaryObjectReader.ReadValue: TValueType;
  30. begin
  31. Result := vaNull; { Necessary in FPC as TValueType is larger than 1 byte! }
  32. Read(Result, 1);
  33. end;
  34. function TBinaryObjectReader.NextValue: TValueType;
  35. begin
  36. Result := ReadValue;
  37. { We only 'peek' at the next value, so seek back to unget the read value: }
  38. Dec(FBufPos);
  39. end;
  40. procedure TBinaryObjectReader.BeginRootComponent;
  41. var
  42. Signature: LongInt;
  43. begin
  44. { Read filer signature }
  45. Read(Signature, 4);
  46. if Signature <> LongInt(FilerSignature) then
  47. raise EReadError.Create(SInvalidImage);
  48. end;
  49. procedure TBinaryObjectReader.BeginComponent(var Flags: TFilerFlags;
  50. var AChildPos: Integer; var CompClassName, CompName: String);
  51. var
  52. Prefix: Byte;
  53. ValueType: TValueType;
  54. begin
  55. { Every component can start with a special prefix: }
  56. Flags := [];
  57. if (Byte(NextValue) and $f0) = $f0 then
  58. begin
  59. Prefix := Byte(ReadValue);
  60. Flags := TFilerFlags(Prefix and $0f);
  61. if ffChildPos in Flags then
  62. begin
  63. ValueType := NextValue;
  64. case ValueType of
  65. vaInt8:
  66. AChildPos := ReadInt8;
  67. vaInt16:
  68. AChildPos := ReadInt16;
  69. vaInt32:
  70. AChildPos := ReadInt32;
  71. else
  72. raise EReadError.Create(SInvalidPropertyValue);
  73. end;
  74. end;
  75. end;
  76. CompClassName := ReadStr;
  77. CompName := ReadStr;
  78. end;
  79. function TBinaryObjectReader.BeginProperty: String;
  80. begin
  81. Result := ReadStr;
  82. end;
  83. procedure TBinaryObjectReader.ReadBinary(const DestData: TMemoryStream);
  84. var
  85. BinSize: LongInt;
  86. begin
  87. Read(BinSize, 4);
  88. DestData.Size := BinSize;
  89. Read(DestData.Memory^, BinSize);
  90. end;
  91. function TBinaryObjectReader.ReadFloat: Extended;
  92. begin
  93. Read(Result, SizeOf(Extended))
  94. end;
  95. function TBinaryObjectReader.ReadSingle: Single;
  96. begin
  97. Read(Result, SizeOf(Single))
  98. end;
  99. {!!!: function TBinaryObjectReader.ReadCurrency: Currency;
  100. begin
  101. Read(Result, SizeOf(Currency))
  102. end;}
  103. function TBinaryObjectReader.ReadDate: TDateTime;
  104. begin
  105. Read(Result, SizeOf(TDateTime))
  106. end;
  107. function TBinaryObjectReader.ReadIdent(ValueType: TValueType): String;
  108. var
  109. i: Byte;
  110. begin
  111. case ValueType of
  112. vaIdent:
  113. begin
  114. Read(i, 1);
  115. SetLength(Result, i);
  116. Read(Pointer(@Result[1])^, i);
  117. end;
  118. vaNil:
  119. Result := 'nil';
  120. vaFalse:
  121. Result := 'False';
  122. vaTrue:
  123. Result := 'True';
  124. vaNull:
  125. Result := 'Null';
  126. end;
  127. end;
  128. function TBinaryObjectReader.ReadInt8: ShortInt;
  129. begin
  130. Read(Result, 1);
  131. end;
  132. function TBinaryObjectReader.ReadInt16: SmallInt;
  133. begin
  134. Read(Result, 2);
  135. end;
  136. function TBinaryObjectReader.ReadInt32: LongInt;
  137. begin
  138. Read(Result, 4);
  139. end;
  140. function TBinaryObjectReader.ReadInt64: Int64;
  141. begin
  142. Read(Result, 8);
  143. end;
  144. function TBinaryObjectReader.ReadSet(EnumType: Pointer): Integer;
  145. var
  146. Name: String;
  147. Value: Integer;
  148. begin
  149. try
  150. Result := 0;
  151. while True do
  152. begin
  153. Name := ReadStr;
  154. if Length(Name) = 0 then
  155. break;
  156. Value := GetEnumValue(PTypeInfo(EnumType), Name);
  157. if Value = -1 then
  158. raise EReadError.Create(SInvalidPropertyValue);
  159. Result := Result or (1 shl Value);
  160. end;
  161. except
  162. SkipSetBody;
  163. raise;
  164. end;
  165. end;
  166. function TBinaryObjectReader.ReadStr: String;
  167. var
  168. i: Byte;
  169. begin
  170. Read(i, 1);
  171. SetLength(Result, i);
  172. Read(Pointer(@Result[1])^, i);
  173. end;
  174. function TBinaryObjectReader.ReadString(StringType: TValueType): String;
  175. var
  176. i: Integer;
  177. p: PChar;
  178. begin
  179. case StringType of
  180. vaString:
  181. begin
  182. i := 0;
  183. Read(i, 1);
  184. end;
  185. vaLString:
  186. Read(i, 4);
  187. end;
  188. // SetLength(Result, i);
  189. if i > 0 then
  190. begin
  191. // ###
  192. GetMem(p, i + 1);
  193. Read(p^, i);
  194. p[i] := #0;
  195. Result := p;
  196. FreeMem(p);
  197. end else
  198. SetLength(Result, 0);
  199. { Read(Pointer(@Result[1])^, i);}
  200. end;
  201. {!!!: function TBinaryObjectReader.ReadWideString: WideString;
  202. var
  203. i: Integer;
  204. begin
  205. FDriver.Read(i, 4);
  206. SetLength(Result, i);
  207. if i > 0 then
  208. Read(PWideChar(Result), i * 2);
  209. end;}
  210. procedure TBinaryObjectReader.SkipComponent(SkipComponentInfos: Boolean);
  211. var
  212. Flags: TFilerFlags;
  213. Dummy: Integer;
  214. CompClassName, CompName: String;
  215. begin
  216. if SkipComponentInfos then
  217. { Skip prefix, component class name and component object name }
  218. BeginComponent(Flags, Dummy, CompClassName, CompName);
  219. { Skip properties }
  220. while NextValue <> vaNull do
  221. SkipProperty;
  222. ReadValue;
  223. { Skip children }
  224. while NextValue <> vaNull do
  225. SkipComponent(True);
  226. ReadValue;
  227. end;
  228. procedure TBinaryObjectReader.SkipValue;
  229. procedure SkipBytes(Count: LongInt);
  230. var
  231. Dummy: array[0..1023] of Byte;
  232. SkipNow: Integer;
  233. begin
  234. while Count > 0 do
  235. begin
  236. if Count > 1024 then
  237. SkipNow := 1024
  238. else
  239. SkipNow := Count;
  240. Read(Dummy, SkipNow);
  241. Dec(Count, SkipNow);
  242. end;
  243. end;
  244. var
  245. Count: LongInt;
  246. begin
  247. case ReadValue of
  248. vaNull, vaFalse, vaTrue, vaNil: ;
  249. vaList:
  250. begin
  251. while NextValue <> vaNull do
  252. SkipValue;
  253. ReadValue;
  254. end;
  255. vaInt8:
  256. SkipBytes(1);
  257. vaInt16:
  258. SkipBytes(2);
  259. vaInt32:
  260. SkipBytes(4);
  261. vaExtended:
  262. SkipBytes(SizeOf(Extended));
  263. vaString, vaIdent:
  264. ReadStr;
  265. vaBinary, vaLString, vaWString:
  266. begin
  267. Read(Count, 4);
  268. SkipBytes(Count);
  269. end;
  270. vaSet:
  271. SkipSetBody;
  272. vaCollection:
  273. begin
  274. while NextValue <> vaNull do
  275. begin
  276. { Skip the order value if present }
  277. if NextValue in [vaInt8, vaInt16, vaInt32] then
  278. SkipValue;
  279. SkipBytes(1);
  280. while NextValue <> vaNull do
  281. SkipProperty;
  282. ReadValue;
  283. end;
  284. ReadValue;
  285. end;
  286. vaSingle:
  287. SkipBytes(Sizeof(Single));
  288. {!!!: vaCurrency:
  289. SkipBytes(SizeOf(Currency));}
  290. vaDate:
  291. SkipBytes(Sizeof(TDateTime));
  292. vaInt64:
  293. SkipBytes(8);
  294. end;
  295. end;
  296. { private methods }
  297. procedure TBinaryObjectReader.Read(var Buf; Count: LongInt);
  298. var
  299. CopyNow: LongInt;
  300. Dest: Pointer;
  301. begin
  302. Dest := @Buf;
  303. while Count > 0 do
  304. begin
  305. if FBufPos >= FBufEnd then
  306. begin
  307. FBufEnd := FStream.Read(FBuffer^, FBufSize);
  308. if FBufEnd = 0 then
  309. raise EReadError.Create(SReadError);
  310. FBufPos := 0;
  311. end;
  312. CopyNow := FBufEnd - FBufPos;
  313. if CopyNow > Count then
  314. CopyNow := Count;
  315. Move(PChar(FBuffer)[FBufPos], Dest^, CopyNow);
  316. Inc(FBufPos, CopyNow);
  317. Inc(Dest, CopyNow);
  318. Dec(Count, CopyNow);
  319. end;
  320. end;
  321. procedure TBinaryObjectReader.SkipProperty;
  322. begin
  323. { Skip property name, then the property value }
  324. ReadStr;
  325. SkipValue;
  326. end;
  327. procedure TBinaryObjectReader.SkipSetBody;
  328. begin
  329. while Length(ReadStr) > 0 do;
  330. end;
  331. {****************************************************************************}
  332. {* TREADER *}
  333. {****************************************************************************}
  334. // This may be better put somewhere else:
  335. type
  336. TFieldInfo = packed record
  337. FieldOffset: LongWord;
  338. ClassTypeIndex: Word;
  339. Name: ShortString;
  340. end;
  341. PFieldClassTable = ^TFieldClassTable;
  342. TFieldClassTable = packed record
  343. Count: Word;
  344. Entries: array[Word] of TPersistentClass;
  345. end;
  346. PFieldTable = ^TFieldTable;
  347. TFieldTable = packed record
  348. FieldCount: Word;
  349. ClassTable: PFieldClassTable;
  350. // Fields: array[Word] of TFieldInfo; Elements have variant size!
  351. end;
  352. function GetFieldClass(Instance: TObject; const ClassName: string): TPersistentClass;
  353. var
  354. UClassName: String;
  355. ClassType: TClass;
  356. ClassTable: PFieldClassTable;
  357. i: Integer;
  358. FieldTable: PFieldTable;
  359. begin
  360. // At first, try to locate the class in the class tables
  361. UClassName := UpperCase(ClassName);
  362. ClassType := Instance.ClassType;
  363. while ClassType <> TPersistent do
  364. begin
  365. FieldTable := PFieldTable((Pointer(ClassType) + vmtFieldTable)^);
  366. ClassTable := PFieldTable((Pointer(ClassType) + vmtFieldTable)^)^.ClassTable;
  367. if Assigned(ClassTable) then
  368. for i := 0 to ClassTable^.Count - 1 do
  369. begin
  370. Result := ClassTable^.Entries[i];
  371. if UpperCase(Result.ClassName) = UClassName then
  372. exit;
  373. end;
  374. // Try again with the parent class type
  375. ClassType := ClassType.ClassParent;
  376. end;
  377. Result := Classes.GetClass(ClassName);
  378. end;
  379. constructor TReader.Create(Stream: TStream; BufSize: Integer);
  380. begin
  381. inherited Create;
  382. FDriver := TBinaryObjectReader.Create(Stream, BufSize);
  383. end;
  384. destructor TReader.Destroy;
  385. begin
  386. FDriver.Free;
  387. inherited Destroy;
  388. end;
  389. procedure TReader.BeginReferences;
  390. begin
  391. FLoaded := TList.Create;
  392. try
  393. FFixups := TList.Create;
  394. except
  395. FLoaded.Free;
  396. raise;
  397. end;
  398. end;
  399. procedure TReader.CheckValue(Value: TValueType);
  400. begin
  401. if FDriver.NextValue <> Value then
  402. raise EReadError.Create(SInvalidPropertyValue)
  403. else
  404. FDriver.ReadValue;
  405. end;
  406. procedure TReader.DefineProperty(const Name: String; AReadData: TReaderProc;
  407. WriteData: TWriterProc; HasData: Boolean);
  408. begin
  409. if Assigned(AReadData) and (UpperCase(Name) = UpperCase(FPropName)) then
  410. begin
  411. AReadData(Self);
  412. SetLength(FPropName, 0);
  413. end;
  414. end;
  415. procedure TReader.DefineBinaryProperty(const Name: String;
  416. AReadData, WriteData: TStreamProc; HasData: Boolean);
  417. var
  418. MemBuffer: TMemoryStream;
  419. begin
  420. if Assigned(AReadData) and (UpperCase(Name) = UpperCase(FPropName)) then
  421. begin
  422. { Check if the next property really is a binary property}
  423. if FDriver.NextValue <> vaBinary then
  424. begin
  425. FDriver.SkipValue;
  426. FCanHandleExcepts := True;
  427. raise EReadError.Create(SInvalidPropertyValue);
  428. end else
  429. FDriver.ReadValue;
  430. MemBuffer := TMemoryStream.Create;
  431. try
  432. FDriver.ReadBinary(MemBuffer);
  433. FCanHandleExcepts := True;
  434. AReadData(MemBuffer);
  435. finally
  436. MemBuffer.Free;
  437. end;
  438. SetLength(FPropName, 0);
  439. end;
  440. end;
  441. function TReader.EndOfList: Boolean;
  442. begin
  443. Result := FDriver.NextValue = vaNull;
  444. end;
  445. procedure TReader.EndReferences;
  446. begin
  447. FreeFixups;
  448. FLoaded.Free;
  449. FLoaded := nil;
  450. end;
  451. function TReader.Error(const Message: String): Boolean;
  452. begin
  453. Result := False;
  454. if Assigned(FOnError) then
  455. FOnError(Self, Message, Result);
  456. end;
  457. function TReader.FindMethod(ARoot: TComponent; const AMethodName: String): Pointer;
  458. var
  459. ErrorResult: Boolean;
  460. begin
  461. Result := ARoot.MethodAddress(AMethodName);
  462. ErrorResult := Result = nil;
  463. { always give the OnFindMethod callback a chance to locate the method }
  464. if Assigned(FOnFindMethod) then
  465. FOnFindMethod(Self, AMethodName, Result, ErrorResult);
  466. if ErrorResult then
  467. raise EReadError.Create(SInvalidPropertyValue);
  468. end;
  469. procedure RemoveGlobalFixup(Fixup: TPropFixup);
  470. var
  471. i: Integer;
  472. begin
  473. with GlobalFixupList.LockList do
  474. try
  475. for i := Count - 1 downto 0 do
  476. with TPropFixup(Items[i]) do
  477. if (FInstance = Fixup.FInstance) and
  478. (FPropInfo = Fixup.FPropInfo) then
  479. begin
  480. Free;
  481. Delete(i);
  482. end;
  483. finally
  484. GlobalFixupList.UnlockList;
  485. end;
  486. end;
  487. procedure TReader.DoFixupReferences;
  488. var
  489. i: Integer;
  490. CurFixup: TPropFixup;
  491. CurName: String;
  492. Target: Pointer;
  493. begin
  494. if Assigned(FFixups) then
  495. try
  496. for i := 0 to FFixups.Count - 1 do
  497. begin
  498. CurFixup := TPropFixup(FFixups[i]);
  499. CurName := CurFixup.FName;
  500. if Assigned(FOnReferenceName) then
  501. FOnReferenceName(Self, CurName);
  502. Target := FindNestedComponent(CurFixup.FInstanceRoot, CurName);
  503. RemoveGlobalFixup(CurFixup);
  504. if (not Assigned(Target)) and CurFixup.MakeGlobalReference then
  505. begin
  506. GlobalFixupList.Add(CurFixup);
  507. FFixups[i] := nil;
  508. end else
  509. SetOrdProp(CurFixup.FInstance, CurFixup.FPropInfo, LongInt(Target));
  510. end;
  511. finally
  512. FreeFixups;
  513. end;
  514. end;
  515. procedure TReader.FixupReferences;
  516. var
  517. i: Integer;
  518. begin
  519. DoFixupReferences;
  520. GlobalFixupReferences;
  521. for i := 0 to FLoaded.Count - 1 do
  522. TComponent(FLoaded[I]).Loaded;
  523. end;
  524. procedure TReader.FreeFixups;
  525. var
  526. i: Integer;
  527. begin
  528. if Assigned(FFixups) then
  529. begin
  530. for i := 0 to FFixups.Count - 1 do
  531. TPropFixup(FFixups[I]).Free;
  532. FFixups.Free;
  533. FFixups := nil;
  534. end;
  535. end;
  536. function TReader.NextValue: TValueType;
  537. begin
  538. Result := FDriver.NextValue;
  539. end;
  540. procedure TReader.PropertyError;
  541. begin
  542. FDriver.SkipValue;
  543. raise EReadError.Create(SUnknownProperty);
  544. end;
  545. function TReader.ReadBoolean: Boolean;
  546. var
  547. ValueType: TValueType;
  548. begin
  549. ValueType := FDriver.ReadValue;
  550. if ValueType = vaTrue then
  551. Result := True
  552. else if ValueType = vaFalse then
  553. Result := False
  554. else
  555. raise EReadError.Create(SInvalidPropertyValue);
  556. end;
  557. function TReader.ReadChar: Char;
  558. var
  559. s: String;
  560. begin
  561. s := ReadString;
  562. if Length(s) = 1 then
  563. Result := s[1]
  564. else
  565. raise EReadError.Create(SInvalidPropertyValue);
  566. end;
  567. procedure TReader.ReadCollection(Collection: TCollection);
  568. var
  569. Item: TPersistent;
  570. begin
  571. Collection.BeginUpdate;
  572. try
  573. if not EndOfList then
  574. Collection.Clear;
  575. while not EndOfList do
  576. begin
  577. if FDriver.NextValue in [vaInt8, vaInt16, vaInt32] then
  578. ReadInteger; { Skip order value }
  579. Item := Collection.Add;
  580. ReadListBegin;
  581. while not EndOfList do
  582. ReadProperty(Item);
  583. ReadListEnd;
  584. end;
  585. ReadListEnd;
  586. finally
  587. Collection.EndUpdate;
  588. end;
  589. end;
  590. function TReader.ReadComponent(Component: TComponent): TComponent;
  591. var
  592. Flags: TFilerFlags;
  593. function Recover(var Component: TComponent): Boolean;
  594. begin
  595. Result := False;
  596. if ExceptObject.InheritsFrom(Exception) then
  597. begin
  598. if not ((ffInherited in Flags) or Assigned(Component)) then
  599. Component.Free;
  600. Component := nil;
  601. FDriver.SkipComponent(False);
  602. Result := Error(Exception(ExceptObject).Message);
  603. end;
  604. end;
  605. var
  606. CompClassName, Name: String;
  607. ChildPos: Integer;
  608. SavedParent, SavedLookupRoot: TComponent;
  609. ComponentClass: TComponentClass;
  610. NewComponent: TComponent;
  611. begin
  612. FDriver.BeginComponent(Flags, ChildPos, CompClassName, Name);
  613. SavedParent := Parent;
  614. SavedLookupRoot := FLookupRoot;
  615. try
  616. Result := Component;
  617. if not Assigned(Result) then
  618. try
  619. if ffInherited in Flags then
  620. begin
  621. { Try to locate the existing ancestor component }
  622. if Assigned(FLookupRoot) then
  623. Result := FLookupRoot.FindComponent(Name)
  624. else
  625. Result := nil;
  626. if not Assigned(Result) then
  627. begin
  628. if Assigned(FOnAncestorNotFound) then
  629. FOnAncestorNotFound(Self, Name,
  630. FindComponentClass(CompClassName), Result);
  631. if not Assigned(Result) then
  632. raise EReadError.CreateFmt(SAncestorNotFound, [Name]);
  633. end;
  634. Parent := Result.GetParentComponent;
  635. if not Assigned(Parent) then
  636. Parent := Root;
  637. end else
  638. begin
  639. Result := nil;
  640. ComponentClass := FindComponentClass(CompClassName);
  641. if Assigned(FOnCreateComponent) then
  642. FOnCreateComponent(Self, ComponentClass, Result);
  643. if not Assigned(Result) then
  644. begin
  645. NewComponent := TComponent(ComponentClass.NewInstance);
  646. //!!!: NewComponent := TComponentClass(ComponentClass).Create(Owner);
  647. if ffInline in Flags then
  648. NewComponent.FComponentState :=
  649. NewComponent.FComponentState + [csLoading, csInline];
  650. NewComponent.Create(Owner);
  651. { Don't set Result earlier because else we would come in trouble
  652. with the exception recover mechanism! (Result should be NIL if
  653. an error occured) }
  654. Result := NewComponent;
  655. end;
  656. Include(Result.FComponentState, csLoading);
  657. end;
  658. except
  659. if not Recover(Result) then
  660. raise;
  661. end;
  662. if Assigned(Result) then
  663. try
  664. Include(Result.FComponentState, csLoading);
  665. if not (ffInherited in Flags) then
  666. try
  667. Result.SetParentComponent(Parent);
  668. if Assigned(FOnSetName) then
  669. FOnSetName(Self, Result, Name);
  670. Result.Name := Name;
  671. if Assigned(FindGlobalComponent) and
  672. (FindGlobalComponent(Name) = Result) then
  673. Include(Result.FComponentState, csInline);
  674. except
  675. if not Recover(Result) then
  676. raise;
  677. end;
  678. if not Assigned(Result) then
  679. exit;
  680. if csInline in Result.ComponentState then
  681. FLookupRoot := Result;
  682. { Read the component state }
  683. Include(Result.FComponentState, csReading);
  684. Result.ReadState(Self);
  685. Exclude(Result.FComponentState, csReading);
  686. if ffChildPos in Flags then
  687. Parent.SetChildOrder(Result, ChildPos);
  688. { Add component to list of loaded components, if necessary }
  689. if (not ((ffInherited in Flags) or (csInline in Result.ComponentState))) or
  690. (FLoaded.IndexOf(Result) < 0) then
  691. FLoaded.Add(Result);
  692. except
  693. if ((ffInherited in Flags) or Assigned(Component)) then
  694. Result.Free;
  695. raise;
  696. end;
  697. finally
  698. Parent := SavedParent;
  699. FLookupRoot := SavedLookupRoot;
  700. end;
  701. end;
  702. procedure TReader.ReadData(Instance: TComponent);
  703. var
  704. DoFreeFixups: Boolean;
  705. SavedOwner, SavedParent: TComponent;
  706. begin
  707. if not Assigned(FFixups) then
  708. begin
  709. FFixups := TList.Create;
  710. DoFreeFixups := True;
  711. end else
  712. DoFreeFixups := False;
  713. try
  714. { Read properties }
  715. while not EndOfList do
  716. ReadProperty(Instance);
  717. ReadListEnd;
  718. { Read children }
  719. SavedOwner := Owner;
  720. SavedParent := Parent;
  721. try
  722. Owner := Instance.GetChildOwner;
  723. if not Assigned(Owner) then
  724. Owner := Root;
  725. Parent := Instance.GetChildParent;
  726. while not EndOfList do
  727. ReadComponent(nil);
  728. ReadListEnd;
  729. finally
  730. Owner := SavedOwner;
  731. Parent := SavedParent;
  732. end;
  733. { Fixup references if necessary (normally only if this is the root) }
  734. if DoFreeFixups then
  735. DoFixupReferences;
  736. finally
  737. if DoFreeFixups then
  738. FreeFixups;
  739. end;
  740. end;
  741. function TReader.ReadFloat: Extended;
  742. begin
  743. if FDriver.NextValue = vaExtended then
  744. begin
  745. ReadValue;
  746. Result := FDriver.ReadFloat
  747. end else
  748. Result := ReadInteger;
  749. end;
  750. function TReader.ReadSingle: Single;
  751. begin
  752. if FDriver.NextValue = vaSingle then
  753. begin
  754. FDriver.ReadValue;
  755. Result := FDriver.ReadSingle;
  756. end else
  757. Result := ReadInteger;
  758. end;
  759. {!!!: function TReader.ReadCurrency: Currency;
  760. begin
  761. if FDriver.NextValue = vaCurrency then
  762. begin
  763. FDriver.ReadValue;
  764. Result := FDriver.ReadCurrency;
  765. end else
  766. Result := ReadInteger;
  767. end;}
  768. function TReader.ReadDate: TDateTime;
  769. begin
  770. if FDriver.NextValue = vaDate then
  771. begin
  772. FDriver.ReadValue;
  773. Result := FDriver.ReadDate;
  774. end else
  775. Result := ReadInteger;
  776. end;
  777. function TReader.ReadIdent: String;
  778. var
  779. ValueType: TValueType;
  780. begin
  781. ValueType := FDriver.ReadValue;
  782. if ValueType in [vaIdent, vaNil, vaFalse, vaTrue, vaNull] then
  783. Result := FDriver.ReadIdent(ValueType)
  784. else
  785. raise EReadError.Create(SInvalidPropertyValue);
  786. end;
  787. function TReader.ReadInteger: LongInt;
  788. begin
  789. case FDriver.ReadValue of
  790. vaInt8:
  791. Result := FDriver.ReadInt8;
  792. vaInt16:
  793. Result := FDriver.ReadInt16;
  794. vaInt32:
  795. Result := FDriver.ReadInt32;
  796. else
  797. raise EReadError.Create(SInvalidPropertyValue);
  798. end;
  799. end;
  800. function TReader.ReadInt64: Int64;
  801. begin
  802. if FDriver.NextValue = vaInt64 then
  803. begin
  804. FDriver.ReadValue;
  805. Result := FDriver.ReadInt64;
  806. end else
  807. Result := ReadInteger;
  808. end;
  809. procedure TReader.ReadListBegin;
  810. begin
  811. CheckValue(vaList);
  812. end;
  813. procedure TReader.ReadListEnd;
  814. begin
  815. CheckValue(vaNull);
  816. end;
  817. procedure TReader.ReadProperty(AInstance: TPersistent);
  818. var
  819. Path: String;
  820. Instance: TPersistent;
  821. DotPos, NextPos: PChar;
  822. PropInfo: PPropInfo;
  823. Obj: TObject;
  824. Name: String;
  825. begin
  826. try
  827. Path := FDriver.BeginProperty;
  828. try
  829. Instance := AInstance;
  830. FCanHandleExcepts := True;
  831. DotPos := PChar(Path);
  832. while True do
  833. begin
  834. NextPos := StrScan(DotPos, '.');
  835. if Assigned(NextPos) then
  836. FPropName := Copy(String(DotPos), 1, Integer(NextPos - DotPos))
  837. else
  838. begin
  839. FPropName := DotPos;
  840. break;
  841. end;
  842. PropInfo := GetPropInfo(Instance.ClassInfo, FPropName);
  843. if not Assigned(PropInfo) then
  844. PropertyError;
  845. if PropInfo^.PropType^.Kind = tkClass then
  846. Obj := TObject(GetOrdProp(Instance, PropInfo))
  847. else
  848. Obj := nil;
  849. if not Obj.InheritsFrom(TPersistent) then
  850. begin
  851. { All path elements must be persistent objects! }
  852. FDriver.SkipValue;
  853. raise EReadError.Create(SInvalidPropertyPath);
  854. end;
  855. Instance := TPersistent(Obj);
  856. end;
  857. PropInfo := GetPropInfo(Instance.ClassInfo, FPropName);
  858. if Assigned(PropInfo) then
  859. ReadPropValue(Instance, PropInfo)
  860. else
  861. begin
  862. FCanHandleExcepts := False;
  863. Instance.DefineProperties(Self);
  864. FCanHandleExcepts := True;
  865. if Length(FPropName) > 0 then
  866. PropertyError;
  867. end;
  868. except
  869. on e: Exception do
  870. begin
  871. SetLength(Name, 0);
  872. if AInstance.InheritsFrom(TComponent) then
  873. Name := TComponent(AInstance).Name;
  874. if Length(Name) = 0 then
  875. Name := AInstance.ClassName;
  876. raise EReadError.CreateFmt(SPropertyException,
  877. [Name, DotSep, Path, e.Message]);
  878. end;
  879. end;
  880. except
  881. on e: Exception do
  882. if not FCanHandleExcepts or not Error(E.Message) then
  883. raise;
  884. end;
  885. end;
  886. procedure TReader.ReadPropValue(Instance: TPersistent; PropInfo: Pointer);
  887. const
  888. NullMethod: TMethod = (Code: nil; Data: nil);
  889. var
  890. PropType: PTypeInfo;
  891. Value: LongInt;
  892. IdentToIntFn: TIdentToInt;
  893. Ident: String;
  894. Method: TMethod;
  895. begin
  896. if not Assigned(PPropInfo(PropInfo)^.SetProc) then
  897. raise EReadError.Create(SReadOnlyProperty);
  898. PropType := PPropInfo(PropInfo)^.PropType;
  899. case PropType^.Kind of
  900. tkInteger:
  901. if FDriver.NextValue = vaIdent then
  902. begin
  903. IdentToIntFn := FindIdentToInt(PPropInfo(PropInfo)^.PropType);
  904. Ident := ReadIdent;
  905. if Assigned(IdentToIntFn) and IdentToIntFn(Ident, Value) then
  906. SetOrdProp(Instance, PropInfo, Value)
  907. else
  908. raise EReadError.Create(SInvalidPropertyValue);
  909. end else
  910. SetOrdProp(Instance, PropInfo, ReadInteger);
  911. tkBool:
  912. SetOrdProp(Instance, PropInfo, Ord(ReadBoolean));
  913. tkChar:
  914. SetOrdProp(Instance, PropInfo, Ord(ReadChar));
  915. tkEnumeration:
  916. begin
  917. Value := GetEnumValue(PropType, ReadIdent);
  918. if Value = -1 then
  919. raise EReadError.Create(SInvalidPropertyValue);
  920. SetOrdProp(Instance, PropInfo, Value);
  921. end;
  922. tkFloat:
  923. SetFloatProp(Instance, PropInfo, ReadFloat);
  924. tkSet:
  925. begin
  926. CheckValue(vaSet);
  927. SetOrdProp(Instance, PropInfo,
  928. FDriver.ReadSet(GetTypeData(PropType)^.CompType));
  929. end;
  930. tkMethod:
  931. if FDriver.NextValue = vaNil then
  932. begin
  933. FDriver.ReadValue;
  934. SetMethodProp(Instance, PropInfo, NullMethod);
  935. end else
  936. begin
  937. Method.Code := FindMethod(Root, ReadIdent);
  938. Method.Data := Root;
  939. if Assigned(Method.Code) then
  940. SetMethodProp(Instance, PropInfo, Method);
  941. end;
  942. tkSString, tkLString, tkAString, tkWString:
  943. SetStrProp(Instance, PropInfo, ReadString);
  944. {!!!: tkVariant}
  945. tkClass:
  946. case FDriver.NextValue of
  947. vaNil:
  948. begin
  949. FDriver.ReadValue;
  950. SetOrdProp(Instance, PropInfo, 0)
  951. end;
  952. vaCollection:
  953. begin
  954. FDriver.ReadValue;
  955. ReadCollection(TCollection(GetOrdProp(Instance, PropInfo)));
  956. end
  957. else
  958. FFixups.Add(TPropFixup.Create(Instance, Root, PropInfo, '', ReadIdent));
  959. end;
  960. tkInt64: SetInt64Prop(Instance, PropInfo, ReadInt64);
  961. else
  962. raise EReadError.CreateFmt(SUnknownPropertyType, [Ord(PropType^.Kind)]);
  963. end;
  964. end;
  965. function TReader.ReadRootComponent(ARoot: TComponent): TComponent;
  966. var
  967. Dummy, i: Integer;
  968. Flags: TFilerFlags;
  969. CompClassName, CompName, ResultName: String;
  970. begin
  971. FDriver.BeginRootComponent;
  972. Result := nil;
  973. {!!!: GlobalNameSpace.BeginWrite; // Loading from stream adds to name space
  974. try}
  975. try
  976. FDriver.BeginComponent(Flags, Dummy, CompClassName, CompName);
  977. if not Assigned(ARoot) then
  978. begin
  979. { Read the class name and the object name and create a new object: }
  980. Result := TComponentClass(FindClass(CompClassName)).Create(nil);
  981. Result.Name := CompName;
  982. end else
  983. begin
  984. Result := ARoot;
  985. if not (csDesigning in Result.ComponentState) then
  986. begin
  987. Result.FComponentState :=
  988. Result.FComponentState + [csLoading, csReading];
  989. if Assigned(FindGlobalComponent) then
  990. begin
  991. { We need an unique name }
  992. i := 0;
  993. { Don't use Result.Name directly, as this would influence
  994. FindGlobalComponent in successive loop runs }
  995. ResultName := CompName;
  996. while Assigned(FindGlobalComponent(ResultName)) do
  997. begin
  998. Inc(i);
  999. ResultName := CompName + '_' + IntToStr(i);
  1000. end;
  1001. Result.Name := ResultName;
  1002. end else
  1003. Result.Name := '';
  1004. end;
  1005. end;
  1006. FRoot := Result;
  1007. FLookupRoot := Result;
  1008. if Assigned(GlobalLoaded) then
  1009. FLoaded := GlobalLoaded
  1010. else
  1011. FLoaded := TList.Create;
  1012. try
  1013. if FLoaded.IndexOf(FRoot) < 0 then
  1014. FLoaded.Add(FRoot);
  1015. FOwner := FRoot;
  1016. FRoot.FComponentState := FRoot.FComponentState + [csLoading, csReading];
  1017. FRoot.ReadState(Self);
  1018. Exclude(FRoot.FComponentState, csReading);
  1019. if not Assigned(GlobalLoaded) then
  1020. for i := 0 to FLoaded.Count - 1 do
  1021. TComponent(FLoaded[i]).Loaded;
  1022. finally
  1023. if not Assigned(GlobalLoaded) then
  1024. FLoaded.Free;
  1025. FLoaded := nil;
  1026. end;
  1027. GlobalFixupReferences;
  1028. except
  1029. RemoveFixupReferences(ARoot, '');
  1030. if not Assigned(ARoot) then
  1031. Result.Free;
  1032. raise;
  1033. end;
  1034. {finally
  1035. GlobalNameSpace.EndWrite;
  1036. end;}
  1037. end;
  1038. procedure TReader.ReadComponents(AOwner, AParent: TComponent;
  1039. Proc: TReadComponentsProc);
  1040. var
  1041. Component: TComponent;
  1042. begin
  1043. Root := AOwner;
  1044. Owner := AOwner;
  1045. Parent := AParent;
  1046. BeginReferences;
  1047. try
  1048. while not EndOfList do
  1049. begin
  1050. FDriver.BeginRootComponent;
  1051. Component := ReadComponent(nil);
  1052. if Assigned(Proc) then
  1053. Proc(Component);
  1054. end;
  1055. ReadListEnd;
  1056. FixupReferences;
  1057. finally
  1058. EndReferences;
  1059. end;
  1060. end;
  1061. function TReader.ReadString: String;
  1062. var
  1063. StringType: TValueType;
  1064. begin
  1065. StringType := FDriver.ReadValue;
  1066. if StringType in [vaString, vaLString] then
  1067. Result := FDriver.ReadString(StringType)
  1068. else
  1069. raise EReadError.Create(SInvalidPropertyValue);
  1070. end;
  1071. {!!!: function TReader.ReadWideString: WideString;
  1072. begin
  1073. CheckValue(vaWString);
  1074. Result := FDriver.ReadWideString;
  1075. end;}
  1076. function TReader.ReadValue: TValueType;
  1077. begin
  1078. Result := FDriver.ReadValue;
  1079. end;
  1080. procedure TReader.CopyValue(Writer: TWriter);
  1081. procedure CopyBytes(Count: Integer);
  1082. var
  1083. Buffer: array[0..1023] of Byte;
  1084. begin
  1085. {!!!: while Count > 1024 do
  1086. begin
  1087. FDriver.Read(Buffer, 1024);
  1088. Writer.Driver.Write(Buffer, 1024);
  1089. Dec(Count, 1024);
  1090. end;
  1091. if Count > 0 then
  1092. begin
  1093. FDriver.Read(Buffer, Count);
  1094. Writer.Driver.Write(Buffer, Count);
  1095. end;}
  1096. end;
  1097. var
  1098. s: String;
  1099. Count: LongInt;
  1100. begin
  1101. case FDriver.NextValue of
  1102. vaNull:
  1103. Writer.WriteIdent('NULL');
  1104. vaFalse:
  1105. Writer.WriteIdent('FALSE');
  1106. vaTrue:
  1107. Writer.WriteIdent('TRUE');
  1108. vaNil:
  1109. Writer.WriteIdent('NIL');
  1110. {!!!: vaList, vaCollection:
  1111. begin
  1112. Writer.WriteValue(FDriver.ReadValue);
  1113. while not EndOfList do
  1114. CopyValue(Writer);
  1115. ReadListEnd;
  1116. Writer.WriteListEnd;
  1117. end;}
  1118. vaInt8, vaInt16, vaInt32:
  1119. Writer.WriteInteger(ReadInteger);
  1120. vaExtended:
  1121. Writer.WriteFloat(ReadFloat);
  1122. {!!!: vaString:
  1123. Writer.WriteStr(ReadStr);}
  1124. vaIdent:
  1125. Writer.WriteIdent(ReadIdent);
  1126. {!!!: vaBinary, vaLString, vaWString:
  1127. begin
  1128. Writer.WriteValue(FDriver.ReadValue);
  1129. FDriver.Read(Count, SizeOf(Count));
  1130. Writer.Driver.Write(Count, SizeOf(Count));
  1131. CopyBytes(Count);
  1132. end;}
  1133. {!!!: vaSet:
  1134. Writer.WriteSet(ReadSet);}
  1135. vaSingle:
  1136. Writer.WriteSingle(ReadSingle);
  1137. {!!!: vaCurrency:
  1138. Writer.WriteCurrency(ReadCurrency);}
  1139. vaDate:
  1140. Writer.WriteDate(ReadDate);
  1141. vaInt64:
  1142. Writer.WriteInteger(ReadInt64);
  1143. end;
  1144. end;
  1145. function TReader.FindComponentClass(const AClassName: String): TComponentClass;
  1146. begin
  1147. TPersistentClass(Result) := GetFieldClass(Root, AClassName);
  1148. if not Assigned(Result) and Assigned(FLookupRoot) and (FLookupRoot <> Root) then
  1149. TPersistentClass(Result) := GetFieldClass(FLookupRoot, AClassName);
  1150. if Assigned(FOnFindComponentClass) then
  1151. FOnFindComponentClass(Self, AClassName, Result);
  1152. if not (Assigned(Result) and Result.InheritsFrom(TComponent)) then
  1153. raise EClassNotFound.CreateFmt(SClassNotFound, [AClassName]);
  1154. end;
  1155. {
  1156. $Log$
  1157. Revision 1.3 2000-12-21 09:08:09 sg
  1158. * Applied bugfixes by Mattias Gaertner for TBinaryObjectReader.ReadSet
  1159. (uninitialized result and missing bit shifting) and
  1160. TReader.ReadRootComponent (finding an unique component name)
  1161. (merged from fixbranch)
  1162. Revision 1.2 2000/07/13 11:33:00 michael
  1163. + removed logs
  1164. }