reader.inc 48 KB

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