reader.inc 46 KB

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