reader.inc 42 KB

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