reader.inc 30 KB

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