reader.inc 46 KB

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