reader.inc 49 KB

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