reader.inc 37 KB

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