reader.inc 48 KB

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