reader.inc 45 KB

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