reader.inc 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293
  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. DotPos := NextPos + 1;
  843. PropInfo := GetPropInfo(Instance.ClassInfo, FPropName);
  844. if not Assigned(PropInfo) then
  845. PropertyError;
  846. if PropInfo^.PropType^.Kind = tkClass then
  847. Obj := TObject(GetOrdProp(Instance, PropInfo))
  848. else
  849. Obj := nil;
  850. if not Obj.InheritsFrom(TPersistent) then
  851. begin
  852. { All path elements must be persistent objects! }
  853. FDriver.SkipValue;
  854. raise EReadError.Create(SInvalidPropertyPath);
  855. end;
  856. Instance := TPersistent(Obj);
  857. end;
  858. PropInfo := GetPropInfo(Instance.ClassInfo, FPropName);
  859. if Assigned(PropInfo) then
  860. ReadPropValue(Instance, PropInfo)
  861. else
  862. begin
  863. FCanHandleExcepts := False;
  864. Instance.DefineProperties(Self);
  865. FCanHandleExcepts := True;
  866. if Length(FPropName) > 0 then
  867. PropertyError;
  868. end;
  869. except
  870. on e: Exception do
  871. begin
  872. SetLength(Name, 0);
  873. if AInstance.InheritsFrom(TComponent) then
  874. Name := TComponent(AInstance).Name;
  875. if Length(Name) = 0 then
  876. Name := AInstance.ClassName;
  877. raise EReadError.CreateFmt(SPropertyException,
  878. [Name, DotSep, Path, e.Message]);
  879. end;
  880. end;
  881. except
  882. on e: Exception do
  883. if not FCanHandleExcepts or not Error(E.Message) then
  884. raise;
  885. end;
  886. end;
  887. procedure TReader.ReadPropValue(Instance: TPersistent; PropInfo: Pointer);
  888. const
  889. NullMethod: TMethod = (Code: nil; Data: nil);
  890. var
  891. PropType: PTypeInfo;
  892. Value: LongInt;
  893. IdentToIntFn: TIdentToInt;
  894. Ident: String;
  895. Method: TMethod;
  896. begin
  897. if not Assigned(PPropInfo(PropInfo)^.SetProc) then
  898. raise EReadError.Create(SReadOnlyProperty);
  899. PropType := PPropInfo(PropInfo)^.PropType;
  900. case PropType^.Kind of
  901. tkInteger:
  902. if FDriver.NextValue = vaIdent then
  903. begin
  904. IdentToIntFn := FindIdentToInt(PPropInfo(PropInfo)^.PropType);
  905. Ident := ReadIdent;
  906. if Assigned(IdentToIntFn) and IdentToIntFn(Ident, Value) then
  907. SetOrdProp(Instance, PropInfo, Value)
  908. else
  909. raise EReadError.Create(SInvalidPropertyValue);
  910. end else
  911. SetOrdProp(Instance, PropInfo, ReadInteger);
  912. tkBool:
  913. SetOrdProp(Instance, PropInfo, Ord(ReadBoolean));
  914. tkChar:
  915. SetOrdProp(Instance, PropInfo, Ord(ReadChar));
  916. tkEnumeration:
  917. begin
  918. Value := GetEnumValue(PropType, ReadIdent);
  919. if Value = -1 then
  920. raise EReadError.Create(SInvalidPropertyValue);
  921. SetOrdProp(Instance, PropInfo, Value);
  922. end;
  923. tkFloat:
  924. SetFloatProp(Instance, PropInfo, ReadFloat);
  925. tkSet:
  926. begin
  927. CheckValue(vaSet);
  928. SetOrdProp(Instance, PropInfo,
  929. FDriver.ReadSet(GetTypeData(PropType)^.CompType));
  930. end;
  931. tkMethod:
  932. if FDriver.NextValue = vaNil then
  933. begin
  934. FDriver.ReadValue;
  935. SetMethodProp(Instance, PropInfo, NullMethod);
  936. end else
  937. begin
  938. Method.Code := FindMethod(Root, ReadIdent);
  939. Method.Data := Root;
  940. if Assigned(Method.Code) then
  941. SetMethodProp(Instance, PropInfo, Method);
  942. end;
  943. tkSString, tkLString, tkAString, tkWString:
  944. SetStrProp(Instance, PropInfo, ReadString);
  945. {!!!: tkVariant}
  946. tkClass:
  947. case FDriver.NextValue of
  948. vaNil:
  949. begin
  950. FDriver.ReadValue;
  951. SetOrdProp(Instance, PropInfo, 0)
  952. end;
  953. vaCollection:
  954. begin
  955. FDriver.ReadValue;
  956. ReadCollection(TCollection(GetOrdProp(Instance, PropInfo)));
  957. end
  958. else
  959. FFixups.Add(TPropFixup.Create(Instance, Root, PropInfo, '', ReadIdent));
  960. end;
  961. tkInt64: SetInt64Prop(Instance, PropInfo, ReadInt64);
  962. else
  963. raise EReadError.CreateFmt(SUnknownPropertyType, [Ord(PropType^.Kind)]);
  964. end;
  965. end;
  966. function TReader.ReadRootComponent(ARoot: TComponent): TComponent;
  967. var
  968. Dummy, i: Integer;
  969. Flags: TFilerFlags;
  970. CompClassName, CompName, ResultName: String;
  971. begin
  972. FDriver.BeginRootComponent;
  973. Result := nil;
  974. {!!!: GlobalNameSpace.BeginWrite; // Loading from stream adds to name space
  975. try}
  976. try
  977. FDriver.BeginComponent(Flags, Dummy, CompClassName, CompName);
  978. if not Assigned(ARoot) then
  979. begin
  980. { Read the class name and the object name and create a new object: }
  981. Result := TComponentClass(FindClass(CompClassName)).Create(nil);
  982. Result.Name := CompName;
  983. end else
  984. begin
  985. Result := ARoot;
  986. if not (csDesigning in Result.ComponentState) then
  987. begin
  988. Result.FComponentState :=
  989. Result.FComponentState + [csLoading, csReading];
  990. if Assigned(FindGlobalComponent) then
  991. begin
  992. { We need an unique name }
  993. i := 0;
  994. { Don't use Result.Name directly, as this would influence
  995. FindGlobalComponent in successive loop runs }
  996. ResultName := CompName;
  997. while Assigned(FindGlobalComponent(ResultName)) do
  998. begin
  999. Inc(i);
  1000. ResultName := CompName + '_' + IntToStr(i);
  1001. end;
  1002. Result.Name := ResultName;
  1003. end else
  1004. Result.Name := '';
  1005. end;
  1006. end;
  1007. FRoot := Result;
  1008. FLookupRoot := Result;
  1009. if Assigned(GlobalLoaded) then
  1010. FLoaded := GlobalLoaded
  1011. else
  1012. FLoaded := TList.Create;
  1013. try
  1014. if FLoaded.IndexOf(FRoot) < 0 then
  1015. FLoaded.Add(FRoot);
  1016. FOwner := FRoot;
  1017. FRoot.FComponentState := FRoot.FComponentState + [csLoading, csReading];
  1018. FRoot.ReadState(Self);
  1019. Exclude(FRoot.FComponentState, csReading);
  1020. if not Assigned(GlobalLoaded) then
  1021. for i := 0 to FLoaded.Count - 1 do
  1022. TComponent(FLoaded[i]).Loaded;
  1023. finally
  1024. if not Assigned(GlobalLoaded) then
  1025. FLoaded.Free;
  1026. FLoaded := nil;
  1027. end;
  1028. GlobalFixupReferences;
  1029. except
  1030. RemoveFixupReferences(ARoot, '');
  1031. if not Assigned(ARoot) then
  1032. Result.Free;
  1033. raise;
  1034. end;
  1035. {finally
  1036. GlobalNameSpace.EndWrite;
  1037. end;}
  1038. end;
  1039. procedure TReader.ReadComponents(AOwner, AParent: TComponent;
  1040. Proc: TReadComponentsProc);
  1041. var
  1042. Component: TComponent;
  1043. begin
  1044. Root := AOwner;
  1045. Owner := AOwner;
  1046. Parent := AParent;
  1047. BeginReferences;
  1048. try
  1049. while not EndOfList do
  1050. begin
  1051. FDriver.BeginRootComponent;
  1052. Component := ReadComponent(nil);
  1053. if Assigned(Proc) then
  1054. Proc(Component);
  1055. end;
  1056. ReadListEnd;
  1057. FixupReferences;
  1058. finally
  1059. EndReferences;
  1060. end;
  1061. end;
  1062. function TReader.ReadString: String;
  1063. var
  1064. StringType: TValueType;
  1065. begin
  1066. StringType := FDriver.ReadValue;
  1067. if StringType in [vaString, vaLString] then
  1068. Result := FDriver.ReadString(StringType)
  1069. else
  1070. raise EReadError.Create(SInvalidPropertyValue);
  1071. end;
  1072. {!!!: function TReader.ReadWideString: WideString;
  1073. begin
  1074. CheckValue(vaWString);
  1075. Result := FDriver.ReadWideString;
  1076. end;}
  1077. function TReader.ReadValue: TValueType;
  1078. begin
  1079. Result := FDriver.ReadValue;
  1080. end;
  1081. procedure TReader.CopyValue(Writer: TWriter);
  1082. procedure CopyBytes(Count: Integer);
  1083. var
  1084. Buffer: array[0..1023] of Byte;
  1085. begin
  1086. {!!!: while Count > 1024 do
  1087. begin
  1088. FDriver.Read(Buffer, 1024);
  1089. Writer.Driver.Write(Buffer, 1024);
  1090. Dec(Count, 1024);
  1091. end;
  1092. if Count > 0 then
  1093. begin
  1094. FDriver.Read(Buffer, Count);
  1095. Writer.Driver.Write(Buffer, Count);
  1096. end;}
  1097. end;
  1098. var
  1099. s: String;
  1100. Count: LongInt;
  1101. begin
  1102. case FDriver.NextValue of
  1103. vaNull:
  1104. Writer.WriteIdent('NULL');
  1105. vaFalse:
  1106. Writer.WriteIdent('FALSE');
  1107. vaTrue:
  1108. Writer.WriteIdent('TRUE');
  1109. vaNil:
  1110. Writer.WriteIdent('NIL');
  1111. {!!!: vaList, vaCollection:
  1112. begin
  1113. Writer.WriteValue(FDriver.ReadValue);
  1114. while not EndOfList do
  1115. CopyValue(Writer);
  1116. ReadListEnd;
  1117. Writer.WriteListEnd;
  1118. end;}
  1119. vaInt8, vaInt16, vaInt32:
  1120. Writer.WriteInteger(ReadInteger);
  1121. vaExtended:
  1122. Writer.WriteFloat(ReadFloat);
  1123. {!!!: vaString:
  1124. Writer.WriteStr(ReadStr);}
  1125. vaIdent:
  1126. Writer.WriteIdent(ReadIdent);
  1127. {!!!: vaBinary, vaLString, vaWString:
  1128. begin
  1129. Writer.WriteValue(FDriver.ReadValue);
  1130. FDriver.Read(Count, SizeOf(Count));
  1131. Writer.Driver.Write(Count, SizeOf(Count));
  1132. CopyBytes(Count);
  1133. end;}
  1134. {!!!: vaSet:
  1135. Writer.WriteSet(ReadSet);}
  1136. vaSingle:
  1137. Writer.WriteSingle(ReadSingle);
  1138. {!!!: vaCurrency:
  1139. Writer.WriteCurrency(ReadCurrency);}
  1140. vaDate:
  1141. Writer.WriteDate(ReadDate);
  1142. vaInt64:
  1143. Writer.WriteInteger(ReadInt64);
  1144. end;
  1145. end;
  1146. function TReader.FindComponentClass(const AClassName: String): TComponentClass;
  1147. begin
  1148. TPersistentClass(Result) := GetFieldClass(Root, AClassName);
  1149. if not Assigned(Result) and Assigned(FLookupRoot) and (FLookupRoot <> Root) then
  1150. TPersistentClass(Result) := GetFieldClass(FLookupRoot, AClassName);
  1151. if Assigned(FOnFindComponentClass) then
  1152. FOnFindComponentClass(Self, AClassName, Result);
  1153. if not (Assigned(Result) and Result.InheritsFrom(TComponent)) then
  1154. raise EClassNotFound.CreateFmt(SClassNotFound, [AClassName]);
  1155. end;
  1156. {
  1157. $Log$
  1158. Revision 1.4 2001-03-08 19:32:22 michael
  1159. Fixes merged
  1160. Revision 1.3 2000/12/21 09:08:09 sg
  1161. * Applied bugfixes by Mattias Gaertner for TBinaryObjectReader.ReadSet
  1162. (uninitialized result and missing bit shifting) and
  1163. TReader.ReadRootComponent (finding an unique component name)
  1164. (merged from fixbranch)
  1165. Revision 1.2 2000/07/13 11:33:00 michael
  1166. + removed logs
  1167. }