reader.inc 48 KB

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