reader.inc 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336
  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. TmpStr: String;
  915. begin
  916. if not Assigned(PPropInfo(PropInfo)^.SetProc) then
  917. raise EReadError.Create(SReadOnlyProperty);
  918. PropType := PPropInfo(PropInfo)^.PropType;
  919. case PropType^.Kind of
  920. tkInteger:
  921. if FDriver.NextValue = vaIdent then
  922. begin
  923. Ident := ReadIdent;
  924. if GlobalIdentToInt(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. begin
  970. TmpStr:=ReadString;
  971. if Assigned(FOnReadStringProperty) then
  972. FOnReadStringProperty(Self,Instance,PropInfo,TmpStr);
  973. SetStrProp(Instance, PropInfo, TmpStr);
  974. end;
  975. {!!!: tkVariant}
  976. tkClass:
  977. case FDriver.NextValue of
  978. vaNil:
  979. begin
  980. FDriver.ReadValue;
  981. SetOrdProp(Instance, PropInfo, 0)
  982. end;
  983. vaCollection:
  984. begin
  985. FDriver.ReadValue;
  986. ReadCollection(TCollection(GetOrdProp(Instance, PropInfo)));
  987. end
  988. else
  989. FFixups.Add(TPropFixup.Create(Instance, Root, PropInfo, '', ReadIdent));
  990. end;
  991. tkInt64: SetInt64Prop(Instance, PropInfo, ReadInt64);
  992. else
  993. raise EReadError.CreateFmt(SUnknownPropertyType, [Ord(PropType^.Kind)]);
  994. end;
  995. end;
  996. function TReader.ReadRootComponent(ARoot: TComponent): TComponent;
  997. var
  998. Dummy, i: Integer;
  999. Flags: TFilerFlags;
  1000. CompClassName, CompName, ResultName: String;
  1001. begin
  1002. FDriver.BeginRootComponent;
  1003. Result := nil;
  1004. {!!!: GlobalNameSpace.BeginWrite; // Loading from stream adds to name space
  1005. try}
  1006. try
  1007. FDriver.BeginComponent(Flags, Dummy, CompClassName, CompName);
  1008. if not Assigned(ARoot) then
  1009. begin
  1010. { Read the class name and the object name and create a new object: }
  1011. Result := TComponentClass(FindClass(CompClassName)).Create(nil);
  1012. Result.Name := CompName;
  1013. end else
  1014. begin
  1015. Result := ARoot;
  1016. if not (csDesigning in Result.ComponentState) then
  1017. begin
  1018. Result.FComponentState :=
  1019. Result.FComponentState + [csLoading, csReading];
  1020. if Assigned(FindGlobalComponent) then
  1021. begin
  1022. { We need an unique name }
  1023. i := 0;
  1024. { Don't use Result.Name directly, as this would influence
  1025. FindGlobalComponent in successive loop runs }
  1026. ResultName := CompName;
  1027. while Assigned(FindGlobalComponent(ResultName)) do
  1028. begin
  1029. Inc(i);
  1030. ResultName := CompName + '_' + IntToStr(i);
  1031. end;
  1032. Result.Name := ResultName;
  1033. end else
  1034. Result.Name := '';
  1035. end;
  1036. end;
  1037. FRoot := Result;
  1038. FLookupRoot := Result;
  1039. if Assigned(GlobalLoaded) then
  1040. FLoaded := GlobalLoaded
  1041. else
  1042. FLoaded := TList.Create;
  1043. try
  1044. if FLoaded.IndexOf(FRoot) < 0 then
  1045. FLoaded.Add(FRoot);
  1046. FOwner := FRoot;
  1047. FRoot.FComponentState := FRoot.FComponentState + [csLoading, csReading];
  1048. FRoot.ReadState(Self);
  1049. Exclude(FRoot.FComponentState, csReading);
  1050. if not Assigned(GlobalLoaded) then
  1051. for i := 0 to FLoaded.Count - 1 do
  1052. TComponent(FLoaded[i]).Loaded;
  1053. finally
  1054. if not Assigned(GlobalLoaded) then
  1055. FLoaded.Free;
  1056. FLoaded := nil;
  1057. end;
  1058. GlobalFixupReferences;
  1059. except
  1060. RemoveFixupReferences(ARoot, '');
  1061. if not Assigned(ARoot) then
  1062. Result.Free;
  1063. raise;
  1064. end;
  1065. {finally
  1066. GlobalNameSpace.EndWrite;
  1067. end;}
  1068. end;
  1069. procedure TReader.ReadComponents(AOwner, AParent: TComponent;
  1070. Proc: TReadComponentsProc);
  1071. var
  1072. Component: TComponent;
  1073. begin
  1074. Root := AOwner;
  1075. Owner := AOwner;
  1076. Parent := AParent;
  1077. BeginReferences;
  1078. try
  1079. while not EndOfList do
  1080. begin
  1081. FDriver.BeginRootComponent;
  1082. Component := ReadComponent(nil);
  1083. if Assigned(Proc) then
  1084. Proc(Component);
  1085. end;
  1086. ReadListEnd;
  1087. FixupReferences;
  1088. finally
  1089. EndReferences;
  1090. end;
  1091. end;
  1092. function TReader.ReadString: String;
  1093. var
  1094. StringType: TValueType;
  1095. begin
  1096. StringType := FDriver.ReadValue;
  1097. if StringType in [vaString, vaLString] then
  1098. Result := FDriver.ReadString(StringType)
  1099. else
  1100. raise EReadError.Create(SInvalidPropertyValue);
  1101. end;
  1102. {!!!: function TReader.ReadWideString: WideString;
  1103. begin
  1104. CheckValue(vaWString);
  1105. Result := FDriver.ReadWideString;
  1106. end;}
  1107. function TReader.ReadValue: TValueType;
  1108. begin
  1109. Result := FDriver.ReadValue;
  1110. end;
  1111. procedure TReader.CopyValue(Writer: TWriter);
  1112. procedure CopyBytes(Count: Integer);
  1113. var
  1114. Buffer: array[0..1023] of Byte;
  1115. begin
  1116. {!!!: while Count > 1024 do
  1117. begin
  1118. FDriver.Read(Buffer, 1024);
  1119. Writer.Driver.Write(Buffer, 1024);
  1120. Dec(Count, 1024);
  1121. end;
  1122. if Count > 0 then
  1123. begin
  1124. FDriver.Read(Buffer, Count);
  1125. Writer.Driver.Write(Buffer, Count);
  1126. end;}
  1127. end;
  1128. var
  1129. s: String;
  1130. Count: LongInt;
  1131. begin
  1132. case FDriver.NextValue of
  1133. vaNull:
  1134. Writer.WriteIdent('NULL');
  1135. vaFalse:
  1136. Writer.WriteIdent('FALSE');
  1137. vaTrue:
  1138. Writer.WriteIdent('TRUE');
  1139. vaNil:
  1140. Writer.WriteIdent('NIL');
  1141. {!!!: vaList, vaCollection:
  1142. begin
  1143. Writer.WriteValue(FDriver.ReadValue);
  1144. while not EndOfList do
  1145. CopyValue(Writer);
  1146. ReadListEnd;
  1147. Writer.WriteListEnd;
  1148. end;}
  1149. vaInt8, vaInt16, vaInt32:
  1150. Writer.WriteInteger(ReadInteger);
  1151. vaExtended:
  1152. Writer.WriteFloat(ReadFloat);
  1153. {!!!: vaString:
  1154. Writer.WriteStr(ReadStr);}
  1155. vaIdent:
  1156. Writer.WriteIdent(ReadIdent);
  1157. {!!!: vaBinary, vaLString, vaWString:
  1158. begin
  1159. Writer.WriteValue(FDriver.ReadValue);
  1160. FDriver.Read(Count, SizeOf(Count));
  1161. Writer.Driver.Write(Count, SizeOf(Count));
  1162. CopyBytes(Count);
  1163. end;}
  1164. {!!!: vaSet:
  1165. Writer.WriteSet(ReadSet);}
  1166. vaSingle:
  1167. Writer.WriteSingle(ReadSingle);
  1168. {!!!: vaCurrency:
  1169. Writer.WriteCurrency(ReadCurrency);}
  1170. vaDate:
  1171. Writer.WriteDate(ReadDate);
  1172. vaInt64:
  1173. Writer.WriteInteger(ReadInt64);
  1174. end;
  1175. end;
  1176. function TReader.FindComponentClass(const AClassName: String): TComponentClass;
  1177. begin
  1178. TPersistentClass(Result) := GetFieldClass(Root, AClassName);
  1179. if not Assigned(Result) and Assigned(FLookupRoot) and (FLookupRoot <> Root) then
  1180. TPersistentClass(Result) := GetFieldClass(FLookupRoot, AClassName);
  1181. if Assigned(FOnFindComponentClass) then
  1182. FOnFindComponentClass(Self, AClassName, Result);
  1183. if not (Assigned(Result) and Result.InheritsFrom(TComponent)) then
  1184. raise EClassNotFound.CreateFmt(SClassNotFound, [AClassName]);
  1185. end;
  1186. {
  1187. $Log$
  1188. Revision 1.3 2004-12-27 13:53:27 michael
  1189. + Patch for localization of string properties
  1190. Revision 1.2 2003/12/15 08:57:24 michael
  1191. Patch from Darek Mazur for reading idents from property stream
  1192. Revision 1.2 2003/12/15 08:55:56 michael
  1193. Patch from Darek Mazur for reading idents from property stream
  1194. Revision 1.1 2003/10/06 21:01:06 peter
  1195. * moved classes unit to rtl
  1196. Revision 1.8 2003/08/16 15:50:47 michael
  1197. + Fix from Mattias gaertner for IDE support
  1198. Revision 1.7 2002/12/02 12:04:07 sg
  1199. * Fixed handling of zero-length strings (classes.inc: When converting
  1200. empty strings from text forms to binary forms; reader.inc: When reading
  1201. an empty string from a binary serialization)
  1202. Revision 1.6 2002/09/07 15:15:25 peter
  1203. * old logs removed and tabs fixed
  1204. }