reader.inc 48 KB

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