reader.inc 46 KB

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