reader.inc 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509
  1. {
  2. This file is part of the Free Component Library (FCL)
  3. Copyright (c) 1999-2000 by the Free Pascal development team
  4. See the file COPYING.FPC, included in this distribution,
  5. for details about the copyright.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. **********************************************************************}
  10. {****************************************************************************}
  11. {* TBinaryObjectReader *}
  12. {****************************************************************************}
  13. {$ifndef FPUNONE}
  14. {$IFNDEF FPC_HAS_TYPE_EXTENDED}
  15. function ExtendedToDouble(e : pointer) : double;
  16. var mant : qword;
  17. exp : smallint;
  18. sign : boolean;
  19. d : qword;
  20. begin
  21. move(pbyte(e)[0],mant,8); //mantissa : bytes 0..7
  22. move(pbyte(e)[8],exp,2); //exponent and sign: bytes 8..9
  23. mant:=LEtoN(mant);
  24. exp:=LEtoN(word(exp));
  25. sign:=(exp and $8000)<>0;
  26. if sign then exp:=exp and $7FFF;
  27. case exp of
  28. 0 : mant:=0; //if denormalized, value is too small for double,
  29. //so it's always zero
  30. $7FFF : exp:=2047 //either infinity or NaN
  31. else
  32. begin
  33. dec(exp,16383-1023);
  34. if (exp>=-51) and (exp<=0) then //can be denormalized
  35. begin
  36. mant:=mant shr (-exp);
  37. exp:=0;
  38. end
  39. else
  40. if (exp<-51) or (exp>2046) then //exponent too large.
  41. begin
  42. Result:=0;
  43. exit;
  44. end
  45. else //normalized value
  46. mant:=mant shl 1; //hide most significant bit
  47. end;
  48. end;
  49. d:=word(exp);
  50. d:=d shl 52;
  51. mant:=mant shr 12;
  52. d:=d or mant;
  53. if sign then d:=d or $8000000000000000;
  54. Result:=pdouble(@d)^;
  55. end;
  56. {$ENDIF}
  57. {$endif}
  58. function TBinaryObjectReader.ReadWord : word; {$ifdef CLASSESINLINE}inline;{$endif CLASSESINLINE}
  59. begin
  60. Read(Result,2);
  61. Result:=LEtoN(Result);
  62. end;
  63. function TBinaryObjectReader.ReadDWord : longword; {$ifdef CLASSESINLINE}inline;{$endif CLASSESINLINE}
  64. begin
  65. Read(Result,4);
  66. Result:=LEtoN(Result);
  67. end;
  68. function TBinaryObjectReader.ReadQWord : qword; {$ifdef CLASSESINLINE}inline;{$endif CLASSESINLINE}
  69. begin
  70. Read(Result,8);
  71. Result:=LEtoN(Result);
  72. end;
  73. {$ifndef FPUNONE}
  74. function TBinaryObjectReader.ReadExtended : extended; {$ifdef CLASSESINLINE}inline;{$endif CLASSESINLINE}
  75. {$IFNDEF FPC_HAS_TYPE_EXTENDED}
  76. var ext : array[0..9] of byte;
  77. {$ENDIF}
  78. begin
  79. {$IFNDEF FPC_HAS_TYPE_EXTENDED}
  80. Read(ext[0],10);
  81. Result:=ExtendedToDouble(@(ext[0]));
  82. {$ELSE}
  83. Read(Result,sizeof(Result));
  84. {$ENDIF}
  85. end;
  86. {$endif}
  87. constructor TBinaryObjectReader.Create(Stream: TStream; BufSize: Integer);
  88. begin
  89. inherited Create;
  90. If (Stream=Nil) then
  91. Raise EReadError.Create(SEmptyStreamIllegalReader);
  92. FStream := Stream;
  93. FBufSize := BufSize;
  94. GetMem(FBuffer, BufSize);
  95. end;
  96. destructor TBinaryObjectReader.Destroy;
  97. begin
  98. { Seek back the amount of bytes that we didn't process until now: }
  99. FStream.Seek(Integer(FBufPos) - Integer(FBufEnd), soFromCurrent);
  100. if Assigned(FBuffer) then
  101. FreeMem(FBuffer, FBufSize);
  102. inherited Destroy;
  103. end;
  104. function TBinaryObjectReader.ReadValue: TValueType;
  105. var
  106. b: byte;
  107. begin
  108. Read(b, 1);
  109. Result := TValueType(b);
  110. end;
  111. function TBinaryObjectReader.NextValue: TValueType;
  112. begin
  113. Result := ReadValue;
  114. { We only 'peek' at the next value, so seek back to unget the read value: }
  115. Dec(FBufPos);
  116. end;
  117. procedure TBinaryObjectReader.BeginRootComponent;
  118. var
  119. Signature: LongInt;
  120. begin
  121. { Read filer signature }
  122. Read(Signature, 4);
  123. if Signature <> LongInt({$ifdef FPC_SUPPORTS_UNALIGNED}unaligned{$endif}(FilerSignature)) then
  124. raise EReadError.Create(SInvalidImage);
  125. end;
  126. procedure TBinaryObjectReader.BeginComponent(var Flags: TFilerFlags;
  127. var AChildPos: Integer; var CompClassName, CompName: String);
  128. var
  129. Prefix: Byte;
  130. ValueType: TValueType;
  131. begin
  132. { Every component can start with a special prefix: }
  133. Flags := [];
  134. if (Byte(NextValue) and $f0) = $f0 then
  135. begin
  136. Prefix := Byte(ReadValue);
  137. Flags := TFilerFlags(longint(Prefix and $0f));
  138. if ffChildPos in Flags then
  139. begin
  140. ValueType := ReadValue;
  141. case ValueType of
  142. vaInt8:
  143. AChildPos := ReadInt8;
  144. vaInt16:
  145. AChildPos := ReadInt16;
  146. vaInt32:
  147. AChildPos := ReadInt32;
  148. else
  149. raise EReadError.Create(SInvalidPropertyValue);
  150. end;
  151. end;
  152. end;
  153. CompClassName := ReadStr;
  154. CompName := ReadStr;
  155. end;
  156. function TBinaryObjectReader.BeginProperty: String;
  157. begin
  158. Result := ReadStr;
  159. end;
  160. procedure TBinaryObjectReader.ReadBinary(const DestData: TMemoryStream);
  161. var
  162. BinSize: LongInt;
  163. begin
  164. BinSize:=LongInt(ReadDWord);
  165. DestData.Size := BinSize;
  166. Read(DestData.Memory^, BinSize);
  167. end;
  168. {$ifndef FPUNONE}
  169. function TBinaryObjectReader.ReadFloat: Extended;
  170. begin
  171. Result:=ReadExtended;
  172. end;
  173. function TBinaryObjectReader.ReadSingle: Single;
  174. begin
  175. Result:=single(ReadDWord);
  176. end;
  177. {$endif}
  178. function TBinaryObjectReader.ReadCurrency: Currency;
  179. begin
  180. Result:=currency(ReadQWord);
  181. end;
  182. {$ifndef FPUNONE}
  183. function TBinaryObjectReader.ReadDate: TDateTime;
  184. begin
  185. Result:=TDateTime(ReadQWord);
  186. end;
  187. {$endif}
  188. function TBinaryObjectReader.ReadIdent(ValueType: TValueType): String;
  189. var
  190. i: Byte;
  191. begin
  192. case ValueType of
  193. vaIdent:
  194. begin
  195. Read(i, 1);
  196. SetLength(Result, i);
  197. Read(Pointer(@Result[1])^, i);
  198. end;
  199. vaNil:
  200. Result := 'nil';
  201. vaFalse:
  202. Result := 'False';
  203. vaTrue:
  204. Result := 'True';
  205. vaNull:
  206. Result := 'Null';
  207. end;
  208. end;
  209. function TBinaryObjectReader.ReadInt8: ShortInt;
  210. begin
  211. Read(Result, 1);
  212. end;
  213. function TBinaryObjectReader.ReadInt16: SmallInt;
  214. begin
  215. Result:=SmallInt(ReadWord);
  216. end;
  217. function TBinaryObjectReader.ReadInt32: LongInt;
  218. begin
  219. Result:=LongInt(ReadDWord);
  220. end;
  221. function TBinaryObjectReader.ReadInt64: Int64;
  222. begin
  223. Result:=Int64(ReadQWord);
  224. end;
  225. function TBinaryObjectReader.ReadSet(EnumType: Pointer): Integer;
  226. var
  227. Name: String;
  228. Value: Integer;
  229. begin
  230. try
  231. Result := 0;
  232. while True do
  233. begin
  234. Name := ReadStr;
  235. if Length(Name) = 0 then
  236. break;
  237. Value := GetEnumValue(PTypeInfo(EnumType), Name);
  238. if Value = -1 then
  239. raise EReadError.Create(SInvalidPropertyValue);
  240. Result := Result or (1 shl Value);
  241. end;
  242. except
  243. SkipSetBody;
  244. raise;
  245. end;
  246. end;
  247. function TBinaryObjectReader.ReadStr: String;
  248. var
  249. i: Byte;
  250. begin
  251. Read(i, 1);
  252. SetLength(Result, i);
  253. if i > 0 then
  254. Read(Pointer(@Result[1])^, i);
  255. end;
  256. function TBinaryObjectReader.ReadString(StringType: TValueType): String;
  257. var
  258. b: Byte;
  259. i: Integer;
  260. begin
  261. case StringType of
  262. vaString:
  263. begin
  264. Read(b, 1);
  265. i := b;
  266. end;
  267. vaLString:
  268. i:=ReadDWord;
  269. end;
  270. SetLength(Result, i);
  271. if i > 0 then
  272. Read(Pointer(@Result[1])^, i);
  273. end;
  274. function TBinaryObjectReader.ReadWideString: WideString;
  275. var
  276. len: DWord;
  277. {$IFDEF ENDIAN_BIG}
  278. i : integer;
  279. {$ENDIF}
  280. begin
  281. len := ReadDWord;
  282. SetLength(Result, len);
  283. if (len > 0) then
  284. begin
  285. Read(Pointer(@Result[1])^, len*2);
  286. {$IFDEF ENDIAN_BIG}
  287. for i:=1 to len do
  288. Result[i]:=widechar(SwapEndian(word(Result[i])));
  289. {$ENDIF}
  290. end;
  291. end;
  292. procedure TBinaryObjectReader.SkipComponent(SkipComponentInfos: Boolean);
  293. var
  294. Flags: TFilerFlags;
  295. Dummy: Integer;
  296. CompClassName, CompName: String;
  297. begin
  298. if SkipComponentInfos then
  299. { Skip prefix, component class name and component object name }
  300. BeginComponent(Flags, Dummy, CompClassName, CompName);
  301. { Skip properties }
  302. while NextValue <> vaNull do
  303. SkipProperty;
  304. ReadValue;
  305. { Skip children }
  306. while NextValue <> vaNull do
  307. SkipComponent(True);
  308. ReadValue;
  309. end;
  310. procedure TBinaryObjectReader.SkipValue;
  311. procedure SkipBytes(Count: LongInt);
  312. var
  313. Dummy: array[0..1023] of Byte;
  314. SkipNow: Integer;
  315. begin
  316. while Count > 0 do
  317. begin
  318. if Count > 1024 then
  319. SkipNow := 1024
  320. else
  321. SkipNow := Count;
  322. Read(Dummy, SkipNow);
  323. Dec(Count, SkipNow);
  324. end;
  325. end;
  326. var
  327. Count: LongInt;
  328. begin
  329. case ReadValue of
  330. vaNull, vaFalse, vaTrue, vaNil: ;
  331. vaList:
  332. begin
  333. while NextValue <> vaNull do
  334. SkipValue;
  335. ReadValue;
  336. end;
  337. vaInt8:
  338. SkipBytes(1);
  339. vaInt16:
  340. SkipBytes(2);
  341. vaInt32:
  342. SkipBytes(4);
  343. vaExtended:
  344. SkipBytes(10);
  345. vaString, vaIdent:
  346. ReadStr;
  347. vaBinary, vaLString:
  348. begin
  349. Count:=LongInt(ReadDWord);
  350. SkipBytes(Count);
  351. end;
  352. vaWString:
  353. begin
  354. Count:=LongInt(ReadDWord);
  355. SkipBytes(Count*sizeof(widechar));
  356. end;
  357. vaSet:
  358. SkipSetBody;
  359. vaCollection:
  360. begin
  361. while NextValue <> vaNull do
  362. begin
  363. { Skip the order value if present }
  364. if NextValue in [vaInt8, vaInt16, vaInt32] then
  365. SkipValue;
  366. SkipBytes(1);
  367. while NextValue <> vaNull do
  368. SkipProperty;
  369. ReadValue;
  370. end;
  371. ReadValue;
  372. end;
  373. vaSingle:
  374. {$ifndef FPUNONE}
  375. SkipBytes(Sizeof(Single));
  376. {$else}
  377. SkipBytes(4);
  378. {$endif}
  379. {!!!: vaCurrency:
  380. SkipBytes(SizeOf(Currency));}
  381. vaDate, vaInt64:
  382. SkipBytes(8);
  383. end;
  384. end;
  385. { private methods }
  386. procedure TBinaryObjectReader.Read(var Buf; Count: LongInt);
  387. var
  388. CopyNow: LongInt;
  389. Dest: Pointer;
  390. begin
  391. Dest := @Buf;
  392. while Count > 0 do
  393. begin
  394. if FBufPos >= FBufEnd then
  395. begin
  396. FBufEnd := FStream.Read(FBuffer^, FBufSize);
  397. if FBufEnd = 0 then
  398. raise EReadError.Create(SReadError);
  399. FBufPos := 0;
  400. end;
  401. CopyNow := FBufEnd - FBufPos;
  402. if CopyNow > Count then
  403. CopyNow := Count;
  404. Move(PChar(FBuffer)[FBufPos], Dest^, CopyNow);
  405. Inc(FBufPos, CopyNow);
  406. Inc(Dest, CopyNow);
  407. Dec(Count, CopyNow);
  408. end;
  409. end;
  410. procedure TBinaryObjectReader.SkipProperty;
  411. begin
  412. { Skip property name, then the property value }
  413. ReadStr;
  414. SkipValue;
  415. end;
  416. procedure TBinaryObjectReader.SkipSetBody;
  417. begin
  418. while Length(ReadStr) > 0 do;
  419. end;
  420. {****************************************************************************}
  421. {* TREADER *}
  422. {****************************************************************************}
  423. type
  424. TFieldInfo = packed record
  425. FieldOffset: LongWord;
  426. ClassTypeIndex: Word;
  427. Name: ShortString;
  428. end;
  429. PFieldClassTable = ^TFieldClassTable;
  430. TFieldClassTable =
  431. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  432. packed
  433. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  434. record
  435. Count: Word;
  436. Entries: array[Word] of TPersistentClass;
  437. end;
  438. PFieldTable = ^TFieldTable;
  439. TFieldTable =
  440. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  441. packed
  442. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  443. record
  444. FieldCount: Word;
  445. ClassTable: PFieldClassTable;
  446. // Fields: array[Word] of TFieldInfo; Elements have variant size!
  447. end;
  448. function GetFieldClass(Instance: TObject; const ClassName: string): TPersistentClass;
  449. var
  450. UClassName: String;
  451. ClassType: TClass;
  452. ClassTable: PFieldClassTable;
  453. i: Integer;
  454. { FieldTable: PFieldTable; }
  455. begin
  456. // At first, try to locate the class in the class tables
  457. UClassName := UpperCase(ClassName);
  458. ClassType := Instance.ClassType;
  459. while ClassType <> TPersistent do
  460. begin
  461. { FieldTable := PFieldTable((Pointer(ClassType) + vmtFieldTable)^); }
  462. ClassTable := PFieldTable((Pointer(ClassType) + vmtFieldTable)^)^.ClassTable;
  463. if Assigned(ClassTable) then
  464. for i := 0 to ClassTable^.Count - 1 do
  465. begin
  466. Result := ClassTable^.Entries[i];
  467. if UpperCase(Result.ClassName) = UClassName then
  468. exit;
  469. end;
  470. // Try again with the parent class type
  471. ClassType := ClassType.ClassParent;
  472. end;
  473. Result := Classes.GetClass(ClassName);
  474. end;
  475. constructor TReader.Create(Stream: TStream; BufSize: Integer);
  476. begin
  477. inherited Create;
  478. If (Stream=Nil) then
  479. Raise EReadError.Create(SEmptyStreamIllegalReader);
  480. FDriver := CreateDriver(Stream, BufSize);
  481. end;
  482. destructor TReader.Destroy;
  483. begin
  484. FDriver.Free;
  485. inherited Destroy;
  486. end;
  487. function TReader.CreateDriver(Stream: TStream; BufSize: Integer): TAbstractObjectReader;
  488. begin
  489. Result := TBinaryObjectReader.Create(Stream, BufSize);
  490. end;
  491. procedure TReader.BeginReferences;
  492. begin
  493. FLoaded := TList.Create;
  494. end;
  495. procedure TReader.CheckValue(Value: TValueType);
  496. begin
  497. if FDriver.NextValue <> Value then
  498. raise EReadError.Create(SInvalidPropertyValue)
  499. else
  500. FDriver.ReadValue;
  501. end;
  502. procedure TReader.DefineProperty(const Name: String; AReadData: TReaderProc;
  503. WriteData: TWriterProc; HasData: Boolean);
  504. begin
  505. if Assigned(AReadData) and (UpperCase(Name) = UpperCase(FPropName)) then
  506. begin
  507. AReadData(Self);
  508. SetLength(FPropName, 0);
  509. end;
  510. end;
  511. procedure TReader.DefineBinaryProperty(const Name: String;
  512. AReadData, WriteData: TStreamProc; HasData: Boolean);
  513. var
  514. MemBuffer: TMemoryStream;
  515. begin
  516. if Assigned(AReadData) and (UpperCase(Name) = UpperCase(FPropName)) then
  517. begin
  518. { Check if the next property really is a binary property}
  519. if FDriver.NextValue <> vaBinary then
  520. begin
  521. FDriver.SkipValue;
  522. FCanHandleExcepts := True;
  523. raise EReadError.Create(SInvalidPropertyValue);
  524. end else
  525. FDriver.ReadValue;
  526. MemBuffer := TMemoryStream.Create;
  527. try
  528. FDriver.ReadBinary(MemBuffer);
  529. FCanHandleExcepts := True;
  530. AReadData(MemBuffer);
  531. finally
  532. MemBuffer.Free;
  533. end;
  534. SetLength(FPropName, 0);
  535. end;
  536. end;
  537. function TReader.EndOfList: Boolean;
  538. begin
  539. Result := FDriver.NextValue = vaNull;
  540. end;
  541. procedure TReader.EndReferences;
  542. begin
  543. FLoaded.Free;
  544. FLoaded := nil;
  545. end;
  546. function TReader.Error(const Message: String): Boolean;
  547. begin
  548. Result := False;
  549. if Assigned(FOnError) then
  550. FOnError(Self, Message, Result);
  551. end;
  552. function TReader.FindMethod(ARoot: TComponent; const AMethodName: String): Pointer;
  553. var
  554. ErrorResult: Boolean;
  555. begin
  556. Result := ARoot.MethodAddress(AMethodName);
  557. ErrorResult := Result = nil;
  558. { always give the OnFindMethod callback a chance to locate the method }
  559. if Assigned(FOnFindMethod) then
  560. FOnFindMethod(Self, AMethodName, Result, ErrorResult);
  561. if ErrorResult then
  562. raise EReadError.Create(SInvalidPropertyValue);
  563. end;
  564. procedure TReader.DoFixupReferences;
  565. Var
  566. R,RN : TLocalUnresolvedReference;
  567. G : TUnresolvedInstance;
  568. Ref : String;
  569. C : TComponent;
  570. P : integer;
  571. L : TLinkedList;
  572. begin
  573. If Assigned(FFixups) then
  574. begin
  575. L:=TLinkedList(FFixups);
  576. R:=TLocalUnresolvedReference(L.Root);
  577. While (R<>Nil) do
  578. begin
  579. RN:=TLocalUnresolvedReference(R.Next);
  580. Ref:=R.FRelative;
  581. If Assigned(FOnReferenceName) then
  582. FOnReferenceName(Self,Ref);
  583. C:=FindNestedComponent(R.FRoot,Ref);
  584. If Assigned(C) then
  585. SetObjectProp(R.FInstance,R.FPropInfo,C)
  586. else
  587. begin
  588. P:=Pos('.',R.FRelative);
  589. If (P<>0) then
  590. begin
  591. G:=AddToResolveList(R.FInstance);
  592. G.Addreference(R.FRoot,R.FPropInfo,Copy(R.FRelative,1,P-1),Copy(R.FRelative,P+1,Length(R.FRelative)-P));
  593. end;
  594. end;
  595. L.RemoveItem(R,True);
  596. R:=RN;
  597. end;
  598. FreeAndNil(FFixups);
  599. end;
  600. end;
  601. procedure TReader.FixupReferences;
  602. var
  603. i: Integer;
  604. begin
  605. DoFixupReferences;
  606. GlobalFixupReferences;
  607. for i := 0 to FLoaded.Count - 1 do
  608. TComponent(FLoaded[I]).Loaded;
  609. end;
  610. function TReader.NextValue: TValueType;
  611. begin
  612. Result := FDriver.NextValue;
  613. end;
  614. procedure TReader.Read(var Buf; Count: LongInt);
  615. begin
  616. //This should give an exception if read is not implemented (i.e. TTextObjectReader)
  617. //but should work with TBinaryObjectReader.
  618. Driver.Read(Buf, Count);
  619. end;
  620. procedure TReader.PropertyError;
  621. begin
  622. FDriver.SkipValue;
  623. raise EReadError.CreateFmt(SUnknownProperty,[FPropName]);
  624. end;
  625. function TReader.ReadBoolean: Boolean;
  626. var
  627. ValueType: TValueType;
  628. begin
  629. ValueType := FDriver.ReadValue;
  630. if ValueType = vaTrue then
  631. Result := True
  632. else if ValueType = vaFalse then
  633. Result := False
  634. else
  635. raise EReadError.Create(SInvalidPropertyValue);
  636. end;
  637. function TReader.ReadChar: Char;
  638. var
  639. s: String;
  640. begin
  641. s := ReadString;
  642. if Length(s) = 1 then
  643. Result := s[1]
  644. else
  645. raise EReadError.Create(SInvalidPropertyValue);
  646. end;
  647. function TReader.ReadWideChar: WideChar;
  648. var
  649. W: WideString;
  650. begin
  651. W := ReadWideString;
  652. if Length(W) = 1 then
  653. Result := W[1]
  654. else
  655. raise EReadError.Create(SInvalidPropertyValue);
  656. end;
  657. procedure TReader.ReadCollection(Collection: TCollection);
  658. var
  659. Item: TCollectionItem;
  660. begin
  661. Collection.BeginUpdate;
  662. Collection.Clear;
  663. while not EndOfList do begin
  664. ReadListBegin;
  665. Item := Collection.Add;
  666. while NextValue<>vaNull do
  667. ReadProperty(Item);
  668. ReadListEnd;
  669. end;
  670. Collection.EndUpdate;
  671. ReadListEnd;
  672. end;
  673. function TReader.ReadComponent(Component: TComponent): TComponent;
  674. var
  675. Flags: TFilerFlags;
  676. function Recover(var Component: TComponent): Boolean;
  677. begin
  678. Result := False;
  679. if ExceptObject.InheritsFrom(Exception) then
  680. begin
  681. if not ((ffInherited in Flags) or Assigned(Component)) then
  682. Component.Free;
  683. Component := nil;
  684. FDriver.SkipComponent(False);
  685. Result := Error(Exception(ExceptObject).Message);
  686. end;
  687. end;
  688. var
  689. CompClassName, Name: String;
  690. n, ChildPos: Integer;
  691. SavedParent, SavedLookupRoot: TComponent;
  692. ComponentClass: TComponentClass;
  693. C, NewComponent: TComponent;
  694. SubComponents: TList;
  695. begin
  696. FDriver.BeginComponent(Flags, ChildPos, CompClassName, Name);
  697. SavedParent := Parent;
  698. SavedLookupRoot := FLookupRoot;
  699. SubComponents := nil;
  700. try
  701. Result := Component;
  702. if not Assigned(Result) then
  703. try
  704. if ffInherited in Flags then
  705. begin
  706. { Try to locate the existing ancestor component }
  707. if Assigned(FLookupRoot) then
  708. Result := FLookupRoot.FindComponent(Name)
  709. else
  710. Result := nil;
  711. if not Assigned(Result) then
  712. begin
  713. if Assigned(FOnAncestorNotFound) then
  714. FOnAncestorNotFound(Self, Name,
  715. FindComponentClass(CompClassName), Result);
  716. if not Assigned(Result) then
  717. raise EReadError.CreateFmt(SAncestorNotFound, [Name]);
  718. end;
  719. Parent := Result.GetParentComponent;
  720. if not Assigned(Parent) then
  721. Parent := Root;
  722. end else
  723. begin
  724. Result := nil;
  725. ComponentClass := FindComponentClass(CompClassName);
  726. if Assigned(FOnCreateComponent) then
  727. FOnCreateComponent(Self, ComponentClass, Result);
  728. if not Assigned(Result) then
  729. begin
  730. NewComponent := TComponent(ComponentClass.NewInstance);
  731. if ffInline in Flags then
  732. NewComponent.FComponentState :=
  733. NewComponent.FComponentState + [csLoading, csInline];
  734. NewComponent.Create(Owner);
  735. { Don't set Result earlier because else we would come in trouble
  736. with the exception recover mechanism! (Result should be NIL if
  737. an error occured) }
  738. Result := NewComponent;
  739. end;
  740. Include(Result.FComponentState, csLoading);
  741. end;
  742. except
  743. if not Recover(Result) then
  744. raise;
  745. end;
  746. if Assigned(Result) then
  747. try
  748. Include(Result.FComponentState, csLoading);
  749. { create list of subcomponents and set loading}
  750. SubComponents := TList.Create;
  751. for n := 0 to Result.ComponentCount - 1 do
  752. begin
  753. C := Result.Components[n];
  754. if csSubcomponent in C.ComponentStyle
  755. then begin
  756. SubComponents.Add(C);
  757. Include(C.FComponentState, csLoading);
  758. end;
  759. end;
  760. if not (ffInherited in Flags) then
  761. try
  762. Result.SetParentComponent(Parent);
  763. if Assigned(FOnSetName) then
  764. FOnSetName(Self, Result, Name);
  765. Result.Name := Name;
  766. if FindGlobalComponent(Name) = Result then
  767. Include(Result.FComponentState, csInline);
  768. except
  769. if not Recover(Result) then
  770. raise;
  771. end;
  772. if not Assigned(Result) then
  773. exit;
  774. if csInline in Result.ComponentState then
  775. FLookupRoot := Result;
  776. { Read the component state }
  777. Include(Result.FComponentState, csReading);
  778. for n := 0 to Subcomponents.Count - 1 do
  779. Include(TComponent(Subcomponents[n]).FComponentState, csReading);
  780. Result.ReadState(Self);
  781. Exclude(Result.FComponentState, csReading);
  782. for n := 0 to Subcomponents.Count - 1 do
  783. Exclude(TComponent(Subcomponents[n]).FComponentState, csReading);
  784. if ffChildPos in Flags then
  785. Parent.SetChildOrder(Result, ChildPos);
  786. { Add component to list of loaded components, if necessary }
  787. if (not ((ffInherited in Flags) or (csInline in Result.ComponentState))) or
  788. (FLoaded.IndexOf(Result) < 0)
  789. then begin
  790. for n := 0 to Subcomponents.Count - 1 do
  791. FLoaded.Add(Subcomponents[n]);
  792. FLoaded.Add(Result);
  793. end;
  794. except
  795. if ((ffInherited in Flags) or Assigned(Component)) then
  796. Result.Free;
  797. raise;
  798. end;
  799. finally
  800. Parent := SavedParent;
  801. FLookupRoot := SavedLookupRoot;
  802. Subcomponents.Free;
  803. end;
  804. end;
  805. procedure TReader.ReadData(Instance: TComponent);
  806. var
  807. SavedOwner, SavedParent: TComponent;
  808. begin
  809. { Read properties }
  810. while not EndOfList do
  811. ReadProperty(Instance);
  812. ReadListEnd;
  813. { Read children }
  814. SavedOwner := Owner;
  815. SavedParent := Parent;
  816. try
  817. Owner := Instance.GetChildOwner;
  818. if not Assigned(Owner) then
  819. Owner := Root;
  820. Parent := Instance.GetChildParent;
  821. while not EndOfList do
  822. ReadComponent(nil);
  823. ReadListEnd;
  824. finally
  825. Owner := SavedOwner;
  826. Parent := SavedParent;
  827. end;
  828. { Fixup references if necessary (normally only if this is the root) }
  829. If (Instance=FRoot) then
  830. DoFixupReferences;
  831. end;
  832. {$ifndef FPUNONE}
  833. function TReader.ReadFloat: Extended;
  834. begin
  835. if FDriver.NextValue = vaExtended then
  836. begin
  837. ReadValue;
  838. Result := FDriver.ReadFloat
  839. end else
  840. Result := ReadInteger;
  841. end;
  842. function TReader.ReadSingle: Single;
  843. begin
  844. if FDriver.NextValue = vaSingle then
  845. begin
  846. FDriver.ReadValue;
  847. Result := FDriver.ReadSingle;
  848. end else
  849. Result := ReadInteger;
  850. end;
  851. {$endif}
  852. function TReader.ReadCurrency: Currency;
  853. begin
  854. if FDriver.NextValue = vaCurrency then
  855. begin
  856. FDriver.ReadValue;
  857. Result := FDriver.ReadCurrency;
  858. end else
  859. Result := ReadInteger;
  860. end;
  861. {$ifndef FPUNONE}
  862. function TReader.ReadDate: TDateTime;
  863. begin
  864. if FDriver.NextValue = vaDate then
  865. begin
  866. FDriver.ReadValue;
  867. Result := FDriver.ReadDate;
  868. end else
  869. Result := ReadInteger;
  870. end;
  871. {$endif}
  872. function TReader.ReadIdent: String;
  873. var
  874. ValueType: TValueType;
  875. begin
  876. ValueType := FDriver.ReadValue;
  877. if ValueType in [vaIdent, vaNil, vaFalse, vaTrue, vaNull] then
  878. Result := FDriver.ReadIdent(ValueType)
  879. else
  880. raise EReadError.Create(SInvalidPropertyValue);
  881. end;
  882. function TReader.ReadInteger: LongInt;
  883. begin
  884. case FDriver.ReadValue of
  885. vaInt8:
  886. Result := FDriver.ReadInt8;
  887. vaInt16:
  888. Result := FDriver.ReadInt16;
  889. vaInt32:
  890. Result := FDriver.ReadInt32;
  891. else
  892. raise EReadError.Create(SInvalidPropertyValue);
  893. end;
  894. end;
  895. function TReader.ReadInt64: Int64;
  896. begin
  897. if FDriver.NextValue = vaInt64 then
  898. begin
  899. FDriver.ReadValue;
  900. Result := FDriver.ReadInt64;
  901. end else
  902. Result := ReadInteger;
  903. end;
  904. procedure TReader.ReadListBegin;
  905. begin
  906. CheckValue(vaList);
  907. end;
  908. procedure TReader.ReadListEnd;
  909. begin
  910. CheckValue(vaNull);
  911. end;
  912. procedure TReader.ReadProperty(AInstance: TPersistent);
  913. var
  914. Path: String;
  915. Instance: TPersistent;
  916. DotPos, NextPos: PChar;
  917. PropInfo: PPropInfo;
  918. Obj: TObject;
  919. Name: String;
  920. Skip: Boolean;
  921. Handled: Boolean;
  922. OldPropName: String;
  923. function HandleMissingProperty(IsPath: Boolean): boolean;
  924. begin
  925. Result:=true;
  926. if Assigned(OnPropertyNotFound) then begin
  927. // user defined property error handling
  928. OldPropName:=FPropName;
  929. Handled:=false;
  930. Skip:=false;
  931. OnPropertyNotFound(Self,Instance,FPropName,IsPath,Handled,Skip);
  932. if Handled and (not Skip) and (OldPropName<>FPropName) then
  933. // try alias property
  934. PropInfo := GetPropInfo(Instance.ClassInfo, FPropName);
  935. if Skip then begin
  936. FDriver.SkipValue;
  937. Result:=false;
  938. exit;
  939. end;
  940. end;
  941. end;
  942. begin
  943. try
  944. Path := FDriver.BeginProperty;
  945. try
  946. Instance := AInstance;
  947. FCanHandleExcepts := True;
  948. DotPos := PChar(Path);
  949. while True do
  950. begin
  951. NextPos := StrScan(DotPos, '.');
  952. if Assigned(NextPos) then
  953. FPropName := Copy(String(DotPos), 1, Integer(NextPos - DotPos))
  954. else
  955. begin
  956. FPropName := DotPos;
  957. break;
  958. end;
  959. DotPos := NextPos + 1;
  960. PropInfo := GetPropInfo(Instance.ClassInfo, FPropName);
  961. if not Assigned(PropInfo) then begin
  962. if not HandleMissingProperty(true) then exit;
  963. if not Assigned(PropInfo) then
  964. PropertyError;
  965. end;
  966. if PropInfo^.PropType^.Kind = tkClass then
  967. Obj := TObject(GetObjectProp(Instance, PropInfo))
  968. else
  969. Obj := nil;
  970. if not (Obj is TPersistent) then
  971. begin
  972. { All path elements must be persistent objects! }
  973. FDriver.SkipValue;
  974. raise EReadError.Create(SInvalidPropertyPath);
  975. end;
  976. Instance := TPersistent(Obj);
  977. end;
  978. PropInfo := GetPropInfo(Instance.ClassInfo, FPropName);
  979. if Assigned(PropInfo) then
  980. ReadPropValue(Instance, PropInfo)
  981. else
  982. begin
  983. FCanHandleExcepts := False;
  984. Instance.DefineProperties(Self);
  985. FCanHandleExcepts := True;
  986. if Length(FPropName) > 0 then begin
  987. if not HandleMissingProperty(false) then exit;
  988. if not Assigned(PropInfo) then
  989. PropertyError;
  990. end;
  991. end;
  992. except
  993. on e: Exception do
  994. begin
  995. SetLength(Name, 0);
  996. if AInstance.InheritsFrom(TComponent) then
  997. Name := TComponent(AInstance).Name;
  998. if Length(Name) = 0 then
  999. Name := AInstance.ClassName;
  1000. raise EReadError.CreateFmt(SPropertyException,
  1001. [Name, DotSep, Path, e.Message]);
  1002. end;
  1003. end;
  1004. except
  1005. on e: Exception do
  1006. if not FCanHandleExcepts or not Error(E.Message) then
  1007. raise;
  1008. end;
  1009. end;
  1010. procedure TReader.ReadPropValue(Instance: TPersistent; PropInfo: Pointer);
  1011. const
  1012. NullMethod: TMethod = (Code: nil; Data: nil);
  1013. var
  1014. PropType: PTypeInfo;
  1015. Value: LongInt;
  1016. { IdentToIntFn: TIdentToInt; }
  1017. Ident: String;
  1018. Method: TMethod;
  1019. Handled: Boolean;
  1020. TmpStr: String;
  1021. begin
  1022. if not Assigned(PPropInfo(PropInfo)^.SetProc) then
  1023. raise EReadError.Create(SReadOnlyProperty);
  1024. PropType := PPropInfo(PropInfo)^.PropType;
  1025. case PropType^.Kind of
  1026. tkInteger:
  1027. if FDriver.NextValue = vaIdent then
  1028. begin
  1029. Ident := ReadIdent;
  1030. if GlobalIdentToInt(Ident,Value) then
  1031. SetOrdProp(Instance, PropInfo, Value)
  1032. else
  1033. raise EReadError.Create(SInvalidPropertyValue);
  1034. end else
  1035. SetOrdProp(Instance, PropInfo, ReadInteger);
  1036. tkBool:
  1037. SetOrdProp(Instance, PropInfo, Ord(ReadBoolean));
  1038. tkChar:
  1039. SetOrdProp(Instance, PropInfo, Ord(ReadChar));
  1040. tkWChar:
  1041. SetOrdProp(Instance, PropInfo, Ord(ReadWideChar));
  1042. tkEnumeration:
  1043. begin
  1044. Value := GetEnumValue(PropType, ReadIdent);
  1045. if Value = -1 then
  1046. raise EReadError.Create(SInvalidPropertyValue);
  1047. SetOrdProp(Instance, PropInfo, Value);
  1048. end;
  1049. {$ifndef FPUNONE}
  1050. tkFloat:
  1051. SetFloatProp(Instance, PropInfo, ReadFloat);
  1052. {$endif}
  1053. tkSet:
  1054. begin
  1055. CheckValue(vaSet);
  1056. SetOrdProp(Instance, PropInfo,
  1057. FDriver.ReadSet(GetTypeData(PropType)^.CompType));
  1058. end;
  1059. tkMethod:
  1060. if FDriver.NextValue = vaNil then
  1061. begin
  1062. FDriver.ReadValue;
  1063. SetMethodProp(Instance, PropInfo, NullMethod);
  1064. end else
  1065. begin
  1066. Handled:=false;
  1067. Ident:=ReadIdent;
  1068. if Assigned(OnSetMethodProperty) then
  1069. OnSetMethodProperty(Self,Instance,PPropInfo(PropInfo),Ident,
  1070. Handled);
  1071. if not Handled then begin
  1072. Method.Code := FindMethod(Root, Ident);
  1073. Method.Data := Root;
  1074. if Assigned(Method.Code) then
  1075. SetMethodProp(Instance, PropInfo, Method);
  1076. end;
  1077. end;
  1078. tkSString, tkLString, tkAString:
  1079. begin
  1080. TmpStr:=ReadString;
  1081. if Assigned(FOnReadStringProperty) then
  1082. FOnReadStringProperty(Self,Instance,PropInfo,TmpStr);
  1083. SetStrProp(Instance, PropInfo, TmpStr);
  1084. end;
  1085. tkWstring:
  1086. SetWideStrProp(Instance,PropInfo,ReadWideString);
  1087. {!!!: tkVariant}
  1088. tkClass:
  1089. case FDriver.NextValue of
  1090. vaNil:
  1091. begin
  1092. FDriver.ReadValue;
  1093. SetOrdProp(Instance, PropInfo, 0)
  1094. end;
  1095. vaCollection:
  1096. begin
  1097. FDriver.ReadValue;
  1098. ReadCollection(TCollection(GetObjectProp(Instance, PropInfo)));
  1099. end
  1100. else
  1101. begin
  1102. If Not Assigned(FFixups) then
  1103. FFixups:=TLinkedList.Create(TLocalUnresolvedReference);
  1104. With TLocalUnresolvedReference(TLinkedList(FFixups).Add) do
  1105. begin
  1106. FInstance:=Instance;
  1107. FRoot:=Root;
  1108. FPropInfo:=PropInfo;
  1109. FRelative:=ReadIdent;
  1110. end;
  1111. end;
  1112. end;
  1113. tkInt64, tkQWord: SetInt64Prop(Instance, PropInfo, ReadInt64);
  1114. else
  1115. raise EReadError.CreateFmt(SUnknownPropertyType, [Ord(PropType^.Kind)]);
  1116. end;
  1117. end;
  1118. function TReader.ReadRootComponent(ARoot: TComponent): TComponent;
  1119. var
  1120. Dummy, i: Integer;
  1121. Flags: TFilerFlags;
  1122. CompClassName, CompName, ResultName: String;
  1123. begin
  1124. FDriver.BeginRootComponent;
  1125. Result := nil;
  1126. {!!!: GlobalNameSpace.BeginWrite; // Loading from stream adds to name space
  1127. try}
  1128. try
  1129. FDriver.BeginComponent(Flags, Dummy, CompClassName, CompName);
  1130. if not Assigned(ARoot) then
  1131. begin
  1132. { Read the class name and the object name and create a new object: }
  1133. Result := TComponentClass(FindClass(CompClassName)).Create(nil);
  1134. Result.Name := CompName;
  1135. end else
  1136. begin
  1137. Result := ARoot;
  1138. if not (csDesigning in Result.ComponentState) then
  1139. begin
  1140. Result.FComponentState :=
  1141. Result.FComponentState + [csLoading, csReading];
  1142. { We need an unique name }
  1143. i := 0;
  1144. { Don't use Result.Name directly, as this would influence
  1145. FindGlobalComponent in successive loop runs }
  1146. ResultName := CompName;
  1147. while Assigned(FindGlobalComponent(ResultName)) do
  1148. begin
  1149. Inc(i);
  1150. ResultName := CompName + '_' + IntToStr(i);
  1151. end;
  1152. Result.Name := ResultName;
  1153. end;
  1154. end;
  1155. FRoot := Result;
  1156. FLookupRoot := Result;
  1157. if Assigned(GlobalLoaded) then
  1158. FLoaded := GlobalLoaded
  1159. else
  1160. FLoaded := TList.Create;
  1161. try
  1162. if FLoaded.IndexOf(FRoot) < 0 then
  1163. FLoaded.Add(FRoot);
  1164. FOwner := FRoot;
  1165. FRoot.FComponentState := FRoot.FComponentState + [csLoading, csReading];
  1166. FRoot.ReadState(Self);
  1167. Exclude(FRoot.FComponentState, csReading);
  1168. if not Assigned(GlobalLoaded) then
  1169. for i := 0 to FLoaded.Count - 1 do
  1170. TComponent(FLoaded[i]).Loaded;
  1171. finally
  1172. if not Assigned(GlobalLoaded) then
  1173. FLoaded.Free;
  1174. FLoaded := nil;
  1175. end;
  1176. GlobalFixupReferences;
  1177. except
  1178. RemoveFixupReferences(ARoot, '');
  1179. if not Assigned(ARoot) then
  1180. Result.Free;
  1181. raise;
  1182. end;
  1183. {finally
  1184. GlobalNameSpace.EndWrite;
  1185. end;}
  1186. end;
  1187. procedure TReader.ReadComponents(AOwner, AParent: TComponent;
  1188. Proc: TReadComponentsProc);
  1189. var
  1190. Component: TComponent;
  1191. begin
  1192. Root := AOwner;
  1193. Owner := AOwner;
  1194. Parent := AParent;
  1195. BeginReferences;
  1196. try
  1197. while not EndOfList do
  1198. begin
  1199. FDriver.BeginRootComponent;
  1200. Component := ReadComponent(nil);
  1201. if Assigned(Proc) then
  1202. Proc(Component);
  1203. end;
  1204. ReadListEnd;
  1205. FixupReferences;
  1206. finally
  1207. EndReferences;
  1208. end;
  1209. end;
  1210. function TReader.ReadString: String;
  1211. var
  1212. StringType: TValueType;
  1213. begin
  1214. StringType := FDriver.ReadValue;
  1215. if StringType in [vaString, vaLString] then
  1216. Result := FDriver.ReadString(StringType)
  1217. else if StringType in [vaWString,vaUTF8String] then
  1218. Result:= FDriver.ReadWidestring
  1219. else
  1220. raise EReadError.Create(SInvalidPropertyValue);
  1221. end;
  1222. function TReader.ReadWideString: WideString;
  1223. var
  1224. s: String;
  1225. i: Integer;
  1226. begin
  1227. if NextValue in [vaWString,vaUTF8String] then
  1228. begin
  1229. ReadValue;
  1230. Result := FDriver.ReadWideString
  1231. end
  1232. else begin
  1233. //data probable from ObjectTextToBinary
  1234. s := ReadString;
  1235. setlength(result,length(s));
  1236. for i:= 1 to length(s) do begin
  1237. result[i]:= widechar(ord(s[i])); //no code conversion
  1238. end;
  1239. end;
  1240. end;
  1241. function TReader.ReadValue: TValueType;
  1242. begin
  1243. Result := FDriver.ReadValue;
  1244. end;
  1245. procedure TReader.CopyValue(Writer: TWriter);
  1246. procedure CopyBytes(Count: Integer);
  1247. { var
  1248. Buffer: array[0..1023] of Byte; }
  1249. begin
  1250. {!!!: while Count > 1024 do
  1251. begin
  1252. FDriver.Read(Buffer, 1024);
  1253. Writer.Driver.Write(Buffer, 1024);
  1254. Dec(Count, 1024);
  1255. end;
  1256. if Count > 0 then
  1257. begin
  1258. FDriver.Read(Buffer, Count);
  1259. Writer.Driver.Write(Buffer, Count);
  1260. end;}
  1261. end;
  1262. {var
  1263. s: String;
  1264. Count: LongInt; }
  1265. begin
  1266. case FDriver.NextValue of
  1267. vaNull:
  1268. Writer.WriteIdent('NULL');
  1269. vaFalse:
  1270. Writer.WriteIdent('FALSE');
  1271. vaTrue:
  1272. Writer.WriteIdent('TRUE');
  1273. vaNil:
  1274. Writer.WriteIdent('NIL');
  1275. {!!!: vaList, vaCollection:
  1276. begin
  1277. Writer.WriteValue(FDriver.ReadValue);
  1278. while not EndOfList do
  1279. CopyValue(Writer);
  1280. ReadListEnd;
  1281. Writer.WriteListEnd;
  1282. end;}
  1283. vaInt8, vaInt16, vaInt32:
  1284. Writer.WriteInteger(ReadInteger);
  1285. {$ifndef FPUNONE}
  1286. vaExtended:
  1287. Writer.WriteFloat(ReadFloat);
  1288. {$endif}
  1289. {!!!: vaString:
  1290. Writer.WriteStr(ReadStr);}
  1291. vaIdent:
  1292. Writer.WriteIdent(ReadIdent);
  1293. {!!!: vaBinary, vaLString, vaWString:
  1294. begin
  1295. Writer.WriteValue(FDriver.ReadValue);
  1296. FDriver.Read(Count, SizeOf(Count));
  1297. Writer.Driver.Write(Count, SizeOf(Count));
  1298. CopyBytes(Count);
  1299. end;}
  1300. {!!!: vaSet:
  1301. Writer.WriteSet(ReadSet);}
  1302. {$ifndef FPUNONE}
  1303. vaSingle:
  1304. Writer.WriteSingle(ReadSingle);
  1305. {$endif}
  1306. {!!!: vaCurrency:
  1307. Writer.WriteCurrency(ReadCurrency);}
  1308. {$ifndef FPUNONE}
  1309. vaDate:
  1310. Writer.WriteDate(ReadDate);
  1311. {$endif}
  1312. vaInt64:
  1313. Writer.WriteInteger(ReadInt64);
  1314. end;
  1315. end;
  1316. function TReader.FindComponentClass(const AClassName: String): TComponentClass;
  1317. var
  1318. PersistentClass: TPersistentClass;
  1319. UClassName: shortstring;
  1320. procedure FindInFieldTable(RootComponent: TComponent);
  1321. var
  1322. FieldClassTable: PFieldClassTable;
  1323. Entry: TPersistentClass;
  1324. i: Integer;
  1325. ComponentClassType: TClass;
  1326. begin
  1327. ComponentClassType := RootComponent.ClassType;
  1328. // it is not necessary to look in the FieldTable of TComponent,
  1329. // because TComponent doesn't have published properties that are
  1330. // descendants of TComponent
  1331. while ComponentClassType<>TComponent do begin
  1332. FieldClassTable :=
  1333. PFieldTable((Pointer(ComponentClassType)+vmtFieldTable)^)^.ClassTable;
  1334. if assigned(FieldClassTable) then begin
  1335. for i := 0 to FieldClassTable^.Count -1 do begin
  1336. Entry := FieldClassTable^.Entries[i];
  1337. //writeln(format('Looking for %s in field table of class %s. Found %s',
  1338. //[AClassName, ComponentClassType.ClassName, Entry.ClassName]));
  1339. if (UpperCase(Entry.ClassName)=UClassName) and
  1340. (Entry.InheritsFrom(TComponent)) then begin
  1341. Result := TComponentClass(Entry);
  1342. Exit;
  1343. end;
  1344. end;
  1345. end;
  1346. // look in parent class
  1347. ComponentClassType := ComponentClassType.ClassParent;
  1348. end;
  1349. end;
  1350. begin
  1351. Result := nil;
  1352. UClassName:=UpperCase(AClassName);
  1353. FindInFieldTable(Root);
  1354. if (Result=nil) and assigned(LookupRoot) and (LookupRoot<>Root) then
  1355. FindInFieldTable(LookupRoot);
  1356. if (Result=nil) then begin
  1357. PersistentClass := GetClass(AClassName);
  1358. if PersistentClass.InheritsFrom(TComponent) then
  1359. Result := TComponentClass(PersistentClass);
  1360. end;
  1361. if (Result=nil) and assigned(OnFindComponentClass) then
  1362. OnFindComponentClass(Self, AClassName, Result);
  1363. if (Result=nil) or (not Result.InheritsFrom(TComponent)) then
  1364. raise EClassNotFound.CreateFmt(SClassNotFound, [AClassName]);
  1365. end;