2
0

reader.inc 30 KB

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