reader.inc 41 KB

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