reader.inc 30 KB

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