reader.inc 32 KB

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