reader.inc 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760
  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. function TReader.CreateDriver(Stream: TStream; BufSize: Integer): TAbstractObjectReader;
  562. begin
  563. Result := TBinaryObjectReader.Create(Stream, BufSize);
  564. end;
  565. procedure TReader.BeginReferences;
  566. begin
  567. FLoaded := TFpList.Create;
  568. end;
  569. procedure TReader.CheckValue(Value: TValueType);
  570. begin
  571. if FDriver.NextValue <> Value then
  572. raise EReadError.Create(SInvalidPropertyValue)
  573. else
  574. FDriver.ReadValue;
  575. end;
  576. procedure TReader.DefineProperty(const Name: String; AReadData: TReaderProc;
  577. WriteData: TWriterProc; HasData: Boolean);
  578. begin
  579. if Assigned(AReadData) and (UpperCase(Name) = UpperCase(FPropName)) then
  580. begin
  581. AReadData(Self);
  582. SetLength(FPropName, 0);
  583. end;
  584. end;
  585. procedure TReader.DefineBinaryProperty(const Name: String;
  586. AReadData, WriteData: TStreamProc; HasData: Boolean);
  587. var
  588. MemBuffer: TMemoryStream;
  589. begin
  590. if Assigned(AReadData) and (UpperCase(Name) = UpperCase(FPropName)) then
  591. begin
  592. { Check if the next property really is a binary property}
  593. if FDriver.NextValue <> vaBinary then
  594. begin
  595. FDriver.SkipValue;
  596. FCanHandleExcepts := True;
  597. raise EReadError.Create(SInvalidPropertyValue);
  598. end else
  599. FDriver.ReadValue;
  600. MemBuffer := TMemoryStream.Create;
  601. try
  602. FDriver.ReadBinary(MemBuffer);
  603. FCanHandleExcepts := True;
  604. AReadData(MemBuffer);
  605. finally
  606. MemBuffer.Free;
  607. end;
  608. SetLength(FPropName, 0);
  609. end;
  610. end;
  611. function TReader.EndOfList: Boolean;
  612. begin
  613. Result := FDriver.NextValue = vaNull;
  614. end;
  615. procedure TReader.EndReferences;
  616. begin
  617. FLoaded.Free;
  618. FLoaded := nil;
  619. end;
  620. function TReader.Error(const Message: String): Boolean;
  621. begin
  622. Result := False;
  623. if Assigned(FOnError) then
  624. FOnError(Self, Message, Result);
  625. end;
  626. function TReader.FindMethod(ARoot: TComponent; const AMethodName: String): CodePointer;
  627. var
  628. ErrorResult: Boolean;
  629. begin
  630. Result := ARoot.MethodAddress(AMethodName);
  631. ErrorResult := Result = nil;
  632. { always give the OnFindMethod callback a chance to locate the method }
  633. if Assigned(FOnFindMethod) then
  634. FOnFindMethod(Self, AMethodName, Result, ErrorResult);
  635. if ErrorResult then
  636. raise EReadError.Create(SInvalidPropertyValue);
  637. end;
  638. procedure TReader.DoFixupReferences;
  639. Var
  640. R,RN : TLocalUnresolvedReference;
  641. G : TUnresolvedInstance;
  642. Ref : String;
  643. C : TComponent;
  644. P : integer;
  645. L : TLinkedList;
  646. RI: Pointer; // raw interface
  647. IIDStr: ShortString;
  648. begin
  649. If Assigned(FFixups) then
  650. begin
  651. L:=TLinkedList(FFixups);
  652. R:=TLocalUnresolvedReference(L.Root);
  653. While (R<>Nil) do
  654. begin
  655. RN:=TLocalUnresolvedReference(R.Next);
  656. Ref:=R.FRelative;
  657. If Assigned(FOnReferenceName) then
  658. FOnReferenceName(Self,Ref);
  659. C:=FindNestedComponent(R.FRoot,Ref);
  660. If Assigned(C) then
  661. if R.FPropInfo^.PropType^.Kind = tkInterface then
  662. SetInterfaceProp(R.FInstance,R.FPropInfo,C)
  663. else if R.FPropInfo^.PropType^.Kind = tkInterfaceRaw then
  664. begin
  665. IIDStr := GetTypeData(R.FPropInfo^.PropType)^.IIDStr;
  666. if IIDStr = '' then
  667. raise EReadError.CreateFmt(SInterfaceNoIIDStr, [R.FPropInfo^.PropType^.Name]);
  668. if C.GetInterface(IIDStr, RI) then
  669. SetRawInterfaceProp(R.FInstance,R.FPropInfo,RI)
  670. else
  671. raise EReadError.CreateFmt(SComponentDoesntImplement, [C.ClassName, IIDStr]);
  672. end
  673. else
  674. SetObjectProp(R.FInstance,R.FPropInfo,C)
  675. else
  676. begin
  677. P:=Pos('.',R.FRelative);
  678. If (P<>0) then
  679. begin
  680. G:=AddToResolveList(R.FInstance);
  681. G.Addreference(R.FRoot,R.FPropInfo,Copy(R.FRelative,1,P-1),Copy(R.FRelative,P+1,Length(R.FRelative)-P));
  682. end;
  683. end;
  684. L.RemoveItem(R,True);
  685. R:=RN;
  686. end;
  687. FreeAndNil(FFixups);
  688. end;
  689. end;
  690. procedure TReader.FixupReferences;
  691. var
  692. i: Integer;
  693. begin
  694. DoFixupReferences;
  695. GlobalFixupReferences;
  696. for i := 0 to FLoaded.Count - 1 do
  697. TComponent(FLoaded[I]).Loaded;
  698. end;
  699. function TReader.NextValue: TValueType;
  700. begin
  701. Result := FDriver.NextValue;
  702. end;
  703. procedure TReader.Read(var Buf; Count: LongInt);
  704. begin
  705. //This should give an exception if read is not implemented (i.e. TTextObjectReader)
  706. //but should work with TBinaryObjectReader.
  707. Driver.Read(Buf, Count);
  708. end;
  709. procedure TReader.PropertyError;
  710. begin
  711. FDriver.SkipValue;
  712. raise EReadError.CreateFmt(SUnknownProperty,[FPropName]);
  713. end;
  714. function TReader.ReadBoolean: Boolean;
  715. var
  716. ValueType: TValueType;
  717. begin
  718. ValueType := FDriver.ReadValue;
  719. if ValueType = vaTrue then
  720. Result := True
  721. else if ValueType = vaFalse then
  722. Result := False
  723. else
  724. raise EReadError.Create(SInvalidPropertyValue);
  725. end;
  726. function TReader.ReadChar: Char;
  727. var
  728. s: String;
  729. begin
  730. s := ReadString;
  731. if Length(s) = 1 then
  732. Result := s[1]
  733. else
  734. raise EReadError.Create(SInvalidPropertyValue);
  735. end;
  736. function TReader.ReadWideChar: WideChar;
  737. var
  738. W: WideString;
  739. begin
  740. W := ReadWideString;
  741. if Length(W) = 1 then
  742. Result := W[1]
  743. else
  744. raise EReadError.Create(SInvalidPropertyValue);
  745. end;
  746. function TReader.ReadUnicodeChar: UnicodeChar;
  747. var
  748. U: UnicodeString;
  749. begin
  750. U := ReadUnicodeString;
  751. if Length(U) = 1 then
  752. Result := U[1]
  753. else
  754. raise EReadError.Create(SInvalidPropertyValue);
  755. end;
  756. procedure TReader.ReadCollection(Collection: TCollection);
  757. var
  758. Item: TCollectionItem;
  759. begin
  760. Collection.BeginUpdate;
  761. if not EndOfList then
  762. Collection.Clear;
  763. while not EndOfList do begin
  764. ReadListBegin;
  765. Item := Collection.Add;
  766. while NextValue<>vaNull do
  767. ReadProperty(Item);
  768. ReadListEnd;
  769. end;
  770. Collection.EndUpdate;
  771. ReadListEnd;
  772. end;
  773. function TReader.ReadComponent(Component: TComponent): TComponent;
  774. var
  775. Flags: TFilerFlags;
  776. function Recover(var aComponent: TComponent): Boolean;
  777. begin
  778. Result := False;
  779. if ExceptObject.InheritsFrom(Exception) then
  780. begin
  781. if not ((ffInherited in Flags) or Assigned(Component)) then
  782. aComponent.Free;
  783. aComponent := nil;
  784. FDriver.SkipComponent(False);
  785. Result := Error(Exception(ExceptObject).Message);
  786. end;
  787. end;
  788. var
  789. CompClassName, Name: String;
  790. n, ChildPos: Integer;
  791. SavedParent, SavedLookupRoot: TComponent;
  792. ComponentClass: TComponentClass;
  793. C, NewComponent: TComponent;
  794. SubComponents: TList;
  795. begin
  796. FDriver.BeginComponent(Flags, ChildPos, CompClassName, Name);
  797. SavedParent := Parent;
  798. SavedLookupRoot := FLookupRoot;
  799. SubComponents := nil;
  800. try
  801. Result := Component;
  802. if not Assigned(Result) then
  803. try
  804. if ffInherited in Flags then
  805. begin
  806. { Try to locate the existing ancestor component }
  807. if Assigned(FLookupRoot) then
  808. Result := FLookupRoot.FindComponent(Name)
  809. else
  810. Result := nil;
  811. if not Assigned(Result) then
  812. begin
  813. if Assigned(FOnAncestorNotFound) then
  814. FOnAncestorNotFound(Self, Name,
  815. FindComponentClass(CompClassName), Result);
  816. if not Assigned(Result) then
  817. raise EReadError.CreateFmt(SAncestorNotFound, [Name]);
  818. end;
  819. Parent := Result.GetParentComponent;
  820. if not Assigned(Parent) then
  821. Parent := Root;
  822. end else
  823. begin
  824. Result := nil;
  825. ComponentClass := FindComponentClass(CompClassName);
  826. if Assigned(FOnCreateComponent) then
  827. FOnCreateComponent(Self, ComponentClass, Result);
  828. if not Assigned(Result) then
  829. begin
  830. NewComponent := TComponent(ComponentClass.NewInstance);
  831. if ffInline in Flags then
  832. NewComponent.FComponentState :=
  833. NewComponent.FComponentState + [csLoading, csInline];
  834. NewComponent.Create(Owner);
  835. { Don't set Result earlier because else we would come in trouble
  836. with the exception recover mechanism! (Result should be NIL if
  837. an error occurred) }
  838. Result := NewComponent;
  839. end;
  840. Include(Result.FComponentState, csLoading);
  841. end;
  842. except
  843. if not Recover(Result) then
  844. raise;
  845. end;
  846. if Assigned(Result) then
  847. try
  848. Include(Result.FComponentState, csLoading);
  849. { create list of subcomponents and set loading}
  850. SubComponents := TList.Create;
  851. for n := 0 to Result.ComponentCount - 1 do
  852. begin
  853. C := Result.Components[n];
  854. if csSubcomponent in C.ComponentStyle
  855. then begin
  856. SubComponents.Add(C);
  857. Include(C.FComponentState, csLoading);
  858. end;
  859. end;
  860. if not (ffInherited in Flags) then
  861. try
  862. Result.SetParentComponent(Parent);
  863. if Assigned(FOnSetName) then
  864. FOnSetName(Self, Result, Name);
  865. Result.Name := Name;
  866. if FindGlobalComponent(Name) = Result then
  867. Include(Result.FComponentState, csInline);
  868. except
  869. if not Recover(Result) then
  870. raise;
  871. end;
  872. if not Assigned(Result) then
  873. exit;
  874. if csInline in Result.ComponentState then
  875. FLookupRoot := Result;
  876. { Read the component state }
  877. Include(Result.FComponentState, csReading);
  878. for n := 0 to Subcomponents.Count - 1 do
  879. Include(TComponent(Subcomponents[n]).FComponentState, csReading);
  880. Result.ReadState(Self);
  881. Exclude(Result.FComponentState, csReading);
  882. for n := 0 to Subcomponents.Count - 1 do
  883. Exclude(TComponent(Subcomponents[n]).FComponentState, csReading);
  884. if ffChildPos in Flags then
  885. Parent.SetChildOrder(Result, ChildPos);
  886. { Add component to list of loaded components, if necessary }
  887. if (not ((ffInherited in Flags) or (csInline in Result.ComponentState))) or
  888. (FLoaded.IndexOf(Result) < 0)
  889. then begin
  890. for n := 0 to Subcomponents.Count - 1 do
  891. FLoaded.Add(Subcomponents[n]);
  892. FLoaded.Add(Result);
  893. end;
  894. except
  895. if ((ffInherited in Flags) or Assigned(Component)) then
  896. Result.Free;
  897. raise;
  898. end;
  899. finally
  900. Parent := SavedParent;
  901. FLookupRoot := SavedLookupRoot;
  902. Subcomponents.Free;
  903. end;
  904. end;
  905. procedure TReader.ReadData(Instance: TComponent);
  906. var
  907. SavedOwner, SavedParent: TComponent;
  908. begin
  909. { Read properties }
  910. while not EndOfList do
  911. ReadProperty(Instance);
  912. ReadListEnd;
  913. { Read children }
  914. SavedOwner := Owner;
  915. SavedParent := Parent;
  916. try
  917. Owner := Instance.GetChildOwner;
  918. if not Assigned(Owner) then
  919. Owner := Root;
  920. Parent := Instance.GetChildParent;
  921. while not EndOfList do
  922. ReadComponent(nil);
  923. ReadListEnd;
  924. finally
  925. Owner := SavedOwner;
  926. Parent := SavedParent;
  927. end;
  928. { Fixup references if necessary (normally only if this is the root) }
  929. If (Instance=FRoot) then
  930. DoFixupReferences;
  931. end;
  932. {$ifndef FPUNONE}
  933. function TReader.ReadFloat: Extended;
  934. begin
  935. if FDriver.NextValue = vaExtended then
  936. begin
  937. ReadValue;
  938. Result := FDriver.ReadFloat
  939. end else
  940. Result := ReadInt64;
  941. end;
  942. procedure TReader.ReadSignature;
  943. begin
  944. FDriver.ReadSignature;
  945. end;
  946. function TReader.ReadSingle: Single;
  947. begin
  948. if FDriver.NextValue = vaSingle then
  949. begin
  950. FDriver.ReadValue;
  951. Result := FDriver.ReadSingle;
  952. end else
  953. Result := ReadInteger;
  954. end;
  955. {$endif}
  956. function TReader.ReadCurrency: Currency;
  957. begin
  958. if FDriver.NextValue = vaCurrency then
  959. begin
  960. FDriver.ReadValue;
  961. Result := FDriver.ReadCurrency;
  962. end else
  963. Result := ReadInteger;
  964. end;
  965. {$ifndef FPUNONE}
  966. function TReader.ReadDate: TDateTime;
  967. begin
  968. if FDriver.NextValue = vaDate then
  969. begin
  970. FDriver.ReadValue;
  971. Result := FDriver.ReadDate;
  972. end else
  973. Result := ReadInteger;
  974. end;
  975. {$endif}
  976. function TReader.ReadIdent: String;
  977. var
  978. ValueType: TValueType;
  979. begin
  980. ValueType := FDriver.ReadValue;
  981. if ValueType in [vaIdent, vaNil, vaFalse, vaTrue, vaNull] then
  982. Result := FDriver.ReadIdent(ValueType)
  983. else
  984. raise EReadError.Create(SInvalidPropertyValue);
  985. end;
  986. function TReader.ReadInteger: LongInt;
  987. begin
  988. case FDriver.ReadValue of
  989. vaInt8:
  990. Result := FDriver.ReadInt8;
  991. vaInt16:
  992. Result := FDriver.ReadInt16;
  993. vaInt32:
  994. Result := FDriver.ReadInt32;
  995. else
  996. raise EReadError.Create(SInvalidPropertyValue);
  997. end;
  998. end;
  999. function TReader.ReadInt64: Int64;
  1000. begin
  1001. if FDriver.NextValue = vaInt64 then
  1002. begin
  1003. FDriver.ReadValue;
  1004. Result := FDriver.ReadInt64;
  1005. end else
  1006. Result := ReadInteger;
  1007. end;
  1008. function TReader.ReadSet(EnumType: Pointer): Integer;
  1009. begin
  1010. if FDriver.NextValue = vaSet then
  1011. begin
  1012. FDriver.ReadValue;
  1013. Result := FDriver.ReadSet(enumtype);
  1014. end
  1015. else
  1016. Result := ReadInteger;
  1017. end;
  1018. procedure TReader.ReadListBegin;
  1019. begin
  1020. CheckValue(vaList);
  1021. end;
  1022. procedure TReader.ReadListEnd;
  1023. begin
  1024. CheckValue(vaNull);
  1025. end;
  1026. function TReader.ReadVariant: variant;
  1027. var
  1028. nv: TValueType;
  1029. begin
  1030. { Ensure that a Variant manager is installed }
  1031. if not Assigned(VarClearProc) then
  1032. raise EReadError.Create(SErrNoVariantSupport);
  1033. FillChar(Result,sizeof(Result),0);
  1034. nv:=NextValue;
  1035. case nv of
  1036. vaNil:
  1037. begin
  1038. Result:=system.unassigned;
  1039. readvalue;
  1040. end;
  1041. vaNull:
  1042. begin
  1043. Result:=system.null;
  1044. readvalue;
  1045. end;
  1046. { all integer sizes must be split for big endian systems }
  1047. vaInt8,vaInt16,vaInt32:
  1048. begin
  1049. Result:=ReadInteger;
  1050. end;
  1051. vaInt64:
  1052. begin
  1053. Result:=ReadInt64;
  1054. end;
  1055. vaQWord:
  1056. begin
  1057. Result:=QWord(ReadInt64);
  1058. end;
  1059. vaFalse,vaTrue:
  1060. begin
  1061. Result:=(nv<>vaFalse);
  1062. readValue;
  1063. end;
  1064. vaCurrency:
  1065. begin
  1066. Result:=ReadCurrency;
  1067. end;
  1068. {$ifndef fpunone}
  1069. vaSingle:
  1070. begin
  1071. Result:=ReadSingle;
  1072. end;
  1073. vaExtended:
  1074. begin
  1075. Result:=ReadFloat;
  1076. end;
  1077. vaDate:
  1078. begin
  1079. Result:=ReadDate;
  1080. end;
  1081. {$endif fpunone}
  1082. vaWString,vaUTF8String:
  1083. begin
  1084. Result:=ReadWideString;
  1085. end;
  1086. vaString:
  1087. begin
  1088. Result:=ReadString;
  1089. end;
  1090. vaUString:
  1091. begin
  1092. Result:=ReadUnicodeString;
  1093. end;
  1094. else
  1095. raise EReadError.CreateFmt(SUnsupportedPropertyVariantType, [Ord(nv)]);
  1096. end;
  1097. end;
  1098. procedure TReader.ReadProperty(AInstance: TPersistent);
  1099. var
  1100. Path: String;
  1101. Instance: TPersistent;
  1102. DotPos, NextPos: PChar;
  1103. PropInfo: PPropInfo;
  1104. Obj: TObject;
  1105. Name: String;
  1106. Skip: Boolean;
  1107. Handled: Boolean;
  1108. OldPropName: String;
  1109. function HandleMissingProperty(IsPath: Boolean): boolean;
  1110. begin
  1111. Result:=true;
  1112. if Assigned(OnPropertyNotFound) then begin
  1113. // user defined property error handling
  1114. OldPropName:=FPropName;
  1115. Handled:=false;
  1116. Skip:=false;
  1117. OnPropertyNotFound(Self,Instance,FPropName,IsPath,Handled,Skip);
  1118. if Handled and (not Skip) and (OldPropName<>FPropName) then
  1119. // try alias property
  1120. PropInfo := GetPropInfo(Instance.ClassInfo, FPropName);
  1121. if Skip then begin
  1122. FDriver.SkipValue;
  1123. Result:=false;
  1124. exit;
  1125. end;
  1126. end;
  1127. end;
  1128. begin
  1129. try
  1130. Path := FDriver.BeginProperty;
  1131. try
  1132. Instance := AInstance;
  1133. FCanHandleExcepts := True;
  1134. DotPos := PChar(Path);
  1135. while True do
  1136. begin
  1137. NextPos := StrScan(DotPos, '.');
  1138. if Assigned(NextPos) then
  1139. FPropName := Copy(String(DotPos), 1, Integer(NextPos - DotPos))
  1140. else
  1141. begin
  1142. FPropName := DotPos;
  1143. break;
  1144. end;
  1145. DotPos := NextPos + 1;
  1146. PropInfo := GetPropInfo(Instance.ClassInfo, FPropName);
  1147. if not Assigned(PropInfo) then begin
  1148. if not HandleMissingProperty(true) then exit;
  1149. if not Assigned(PropInfo) then
  1150. PropertyError;
  1151. end;
  1152. if PropInfo^.PropType^.Kind = tkClass then
  1153. Obj := TObject(GetObjectProp(Instance, PropInfo))
  1154. //else if PropInfo^.PropType^.Kind = tkInterface then
  1155. // Obj := TObject(GetInterfaceProp(Instance, PropInfo))
  1156. else
  1157. Obj := nil;
  1158. if not (Obj is TPersistent) then
  1159. begin
  1160. { All path elements must be persistent objects! }
  1161. FDriver.SkipValue;
  1162. raise EReadError.Create(SInvalidPropertyPath);
  1163. end;
  1164. Instance := TPersistent(Obj);
  1165. end;
  1166. PropInfo := GetPropInfo(Instance.ClassInfo, FPropName);
  1167. if Assigned(PropInfo) then
  1168. ReadPropValue(Instance, PropInfo)
  1169. else
  1170. begin
  1171. FCanHandleExcepts := False;
  1172. Instance.DefineProperties(Self);
  1173. FCanHandleExcepts := True;
  1174. if Length(FPropName) > 0 then begin
  1175. if not HandleMissingProperty(false) then exit;
  1176. if not Assigned(PropInfo) then
  1177. PropertyError;
  1178. end;
  1179. end;
  1180. except
  1181. on e: Exception do
  1182. begin
  1183. SetLength(Name, 0);
  1184. if AInstance.InheritsFrom(TComponent) then
  1185. Name := TComponent(AInstance).Name;
  1186. if Length(Name) = 0 then
  1187. Name := AInstance.ClassName;
  1188. raise EReadError.CreateFmt(SPropertyException,
  1189. [Name, DotSep, Path, e.Message]);
  1190. end;
  1191. end;
  1192. except
  1193. on e: Exception do
  1194. if not FCanHandleExcepts or not Error(E.Message) then
  1195. raise;
  1196. end;
  1197. end;
  1198. procedure TReader.ReadPropValue(Instance: TPersistent; PropInfo: Pointer);
  1199. const
  1200. NullMethod: TMethod = (Code: nil; Data: nil);
  1201. var
  1202. PropType: PTypeInfo;
  1203. Value: LongInt;
  1204. { IdentToIntFn: TIdentToInt; }
  1205. Ident: String;
  1206. Method: TMethod;
  1207. Handled: Boolean;
  1208. TmpStr: String;
  1209. begin
  1210. if not Assigned(PPropInfo(PropInfo)^.SetProc) then
  1211. raise EReadError.Create(SReadOnlyProperty);
  1212. PropType := PPropInfo(PropInfo)^.PropType;
  1213. case PropType^.Kind of
  1214. tkInteger:
  1215. if FDriver.NextValue = vaIdent then
  1216. begin
  1217. Ident := ReadIdent;
  1218. if GlobalIdentToInt(Ident,Value) then
  1219. SetOrdProp(Instance, PropInfo, Value)
  1220. else
  1221. raise EReadError.Create(SInvalidPropertyValue);
  1222. end else
  1223. SetOrdProp(Instance, PropInfo, ReadInteger);
  1224. tkBool:
  1225. SetOrdProp(Instance, PropInfo, Ord(ReadBoolean));
  1226. tkChar:
  1227. SetOrdProp(Instance, PropInfo, Ord(ReadChar));
  1228. tkWChar,tkUChar:
  1229. SetOrdProp(Instance, PropInfo, Ord(ReadWideChar));
  1230. tkEnumeration:
  1231. begin
  1232. Value := GetEnumValue(PropType, ReadIdent);
  1233. if Value = -1 then
  1234. raise EReadError.Create(SInvalidPropertyValue);
  1235. SetOrdProp(Instance, PropInfo, Value);
  1236. end;
  1237. {$ifndef FPUNONE}
  1238. tkFloat:
  1239. SetFloatProp(Instance, PropInfo, ReadFloat);
  1240. {$endif}
  1241. tkSet:
  1242. begin
  1243. CheckValue(vaSet);
  1244. SetOrdProp(Instance, PropInfo,
  1245. FDriver.ReadSet(GetTypeData(PropType)^.CompType));
  1246. end;
  1247. tkMethod:
  1248. if FDriver.NextValue = vaNil then
  1249. begin
  1250. FDriver.ReadValue;
  1251. SetMethodProp(Instance, PropInfo, NullMethod);
  1252. end else
  1253. begin
  1254. Handled:=false;
  1255. Ident:=ReadIdent;
  1256. if Assigned(OnSetMethodProperty) then
  1257. OnSetMethodProperty(Self,Instance,PPropInfo(PropInfo),Ident,
  1258. Handled);
  1259. if not Handled then begin
  1260. Method.Code := FindMethod(Root, Ident);
  1261. Method.Data := Root;
  1262. if Assigned(Method.Code) then
  1263. SetMethodProp(Instance, PropInfo, Method);
  1264. end;
  1265. end;
  1266. tkSString, tkLString, tkAString:
  1267. begin
  1268. TmpStr:=ReadString;
  1269. if Assigned(FOnReadStringProperty) then
  1270. FOnReadStringProperty(Self,Instance,PropInfo,TmpStr);
  1271. SetStrProp(Instance, PropInfo, TmpStr);
  1272. end;
  1273. tkUstring:
  1274. SetUnicodeStrProp(Instance,PropInfo,ReadUnicodeString);
  1275. tkWString:
  1276. SetWideStrProp(Instance,PropInfo,ReadWideString);
  1277. tkVariant:
  1278. begin
  1279. SetVariantProp(Instance,PropInfo,ReadVariant);
  1280. end;
  1281. tkClass, tkInterface, tkInterfaceRaw:
  1282. case FDriver.NextValue of
  1283. vaNil:
  1284. begin
  1285. FDriver.ReadValue;
  1286. SetOrdProp(Instance, PropInfo, 0)
  1287. end;
  1288. vaCollection:
  1289. begin
  1290. FDriver.ReadValue;
  1291. ReadCollection(TCollection(GetObjectProp(Instance, PropInfo)));
  1292. end
  1293. else
  1294. begin
  1295. If Not Assigned(FFixups) then
  1296. FFixups:=TLinkedList.Create(TLocalUnresolvedReference);
  1297. With TLocalUnresolvedReference(TLinkedList(FFixups).Add) do
  1298. begin
  1299. FInstance:=Instance;
  1300. FRoot:=Root;
  1301. FPropInfo:=PropInfo;
  1302. FRelative:=ReadIdent;
  1303. end;
  1304. end;
  1305. end;
  1306. tkInt64, tkQWord: SetInt64Prop(Instance, PropInfo, ReadInt64);
  1307. else
  1308. raise EReadError.CreateFmt(SUnknownPropertyType, [Ord(PropType^.Kind)]);
  1309. end;
  1310. end;
  1311. function TReader.ReadRootComponent(ARoot: TComponent): TComponent;
  1312. var
  1313. Dummy, i: Integer;
  1314. Flags: TFilerFlags;
  1315. CompClassName, CompName, ResultName: String;
  1316. begin
  1317. FDriver.BeginRootComponent;
  1318. Result := nil;
  1319. {!!!: GlobalNameSpace.BeginWrite; // Loading from stream adds to name space
  1320. try}
  1321. try
  1322. FDriver.BeginComponent(Flags, Dummy, CompClassName, CompName);
  1323. if not Assigned(ARoot) then
  1324. begin
  1325. { Read the class name and the object name and create a new object: }
  1326. Result := TComponentClass(FindClass(CompClassName)).Create(nil);
  1327. Result.Name := CompName;
  1328. end else
  1329. begin
  1330. Result := ARoot;
  1331. if not (csDesigning in Result.ComponentState) then
  1332. begin
  1333. Result.FComponentState :=
  1334. Result.FComponentState + [csLoading, csReading];
  1335. { We need an unique name }
  1336. i := 0;
  1337. { Don't use Result.Name directly, as this would influence
  1338. FindGlobalComponent in successive loop runs }
  1339. ResultName := CompName;
  1340. while Assigned(FindGlobalComponent(ResultName)) do
  1341. begin
  1342. Inc(i);
  1343. ResultName := CompName + '_' + IntToStr(i);
  1344. end;
  1345. Result.Name := ResultName;
  1346. end;
  1347. end;
  1348. FRoot := Result;
  1349. FLookupRoot := Result;
  1350. if Assigned(GlobalLoaded) then
  1351. FLoaded := GlobalLoaded
  1352. else
  1353. FLoaded := TFpList.Create;
  1354. try
  1355. if FLoaded.IndexOf(FRoot) < 0 then
  1356. FLoaded.Add(FRoot);
  1357. FOwner := FRoot;
  1358. FRoot.FComponentState := FRoot.FComponentState + [csLoading, csReading];
  1359. FRoot.ReadState(Self);
  1360. Exclude(FRoot.FComponentState, csReading);
  1361. if not Assigned(GlobalLoaded) then
  1362. for i := 0 to FLoaded.Count - 1 do
  1363. TComponent(FLoaded[i]).Loaded;
  1364. finally
  1365. if not Assigned(GlobalLoaded) then
  1366. FLoaded.Free;
  1367. FLoaded := nil;
  1368. end;
  1369. GlobalFixupReferences;
  1370. except
  1371. RemoveFixupReferences(ARoot, '');
  1372. if not Assigned(ARoot) then
  1373. Result.Free;
  1374. raise;
  1375. end;
  1376. {finally
  1377. GlobalNameSpace.EndWrite;
  1378. end;}
  1379. end;
  1380. procedure TReader.ReadComponents(AOwner, AParent: TComponent;
  1381. Proc: TReadComponentsProc);
  1382. var
  1383. Component: TComponent;
  1384. begin
  1385. Root := AOwner;
  1386. Owner := AOwner;
  1387. Parent := AParent;
  1388. BeginReferences;
  1389. try
  1390. while not EndOfList do
  1391. begin
  1392. FDriver.BeginRootComponent;
  1393. Component := ReadComponent(nil);
  1394. if Assigned(Proc) then
  1395. Proc(Component);
  1396. end;
  1397. ReadListEnd;
  1398. FixupReferences;
  1399. finally
  1400. EndReferences;
  1401. end;
  1402. end;
  1403. function TReader.ReadString: String;
  1404. var
  1405. StringType: TValueType;
  1406. begin
  1407. StringType := FDriver.ReadValue;
  1408. if StringType in [vaString, vaLString,vaUTF8String] then
  1409. begin
  1410. Result := FDriver.ReadString(StringType);
  1411. if (StringType=vaUTF8String) then
  1412. Result:=string(utf8Decode(Result));
  1413. end
  1414. else if StringType in [vaWString] then
  1415. Result:= string(FDriver.ReadWidestring)
  1416. else if StringType in [vaUString] then
  1417. Result:= string(FDriver.ReadUnicodeString)
  1418. else
  1419. raise EReadError.Create(SInvalidPropertyValue);
  1420. end;
  1421. function TReader.ReadWideString: WideString;
  1422. var
  1423. s: String;
  1424. i: Integer;
  1425. vt:TValueType;
  1426. begin
  1427. if NextValue in [vaWString,vaUString,vaUTF8String] then
  1428. //vaUTF8String needs conversion? 2008-09-06 mse, YES!! AntonK
  1429. begin
  1430. vt:=ReadValue;
  1431. if vt=vaUTF8String then
  1432. Result := utf8decode(fDriver.ReadString(vaLString))
  1433. else
  1434. Result := FDriver.ReadWideString
  1435. end
  1436. else
  1437. begin
  1438. //data probable from ObjectTextToBinary
  1439. s := ReadString;
  1440. setlength(result,length(s));
  1441. for i:= 1 to length(s) do begin
  1442. result[i]:= widechar(ord(s[i])); //no code conversion
  1443. end;
  1444. end;
  1445. end;
  1446. function TReader.ReadUnicodeString: UnicodeString;
  1447. var
  1448. s: String;
  1449. i: Integer;
  1450. vt:TValueType;
  1451. begin
  1452. if NextValue in [vaWString,vaUString,vaUTF8String] then
  1453. //vaUTF8String needs conversion? 2008-09-06 mse, YES!! AntonK
  1454. begin
  1455. vt:=ReadValue;
  1456. if vt=vaUTF8String then
  1457. Result := utf8decode(fDriver.ReadString(vaLString))
  1458. else
  1459. Result := FDriver.ReadWideString
  1460. end
  1461. else
  1462. begin
  1463. //data probable from ObjectTextToBinary
  1464. s := ReadString;
  1465. setlength(result,length(s));
  1466. for i:= 1 to length(s) do begin
  1467. result[i]:= UnicodeChar(ord(s[i])); //no code conversion
  1468. end;
  1469. end;
  1470. end;
  1471. function TReader.ReadValue: TValueType;
  1472. begin
  1473. Result := FDriver.ReadValue;
  1474. end;
  1475. procedure TReader.CopyValue(Writer: TWriter);
  1476. procedure CopyBytes(Count: Integer);
  1477. { var
  1478. Buffer: array[0..1023] of Byte; }
  1479. begin
  1480. {!!!: while Count > 1024 do
  1481. begin
  1482. FDriver.Read(Buffer, 1024);
  1483. Writer.Driver.Write(Buffer, 1024);
  1484. Dec(Count, 1024);
  1485. end;
  1486. if Count > 0 then
  1487. begin
  1488. FDriver.Read(Buffer, Count);
  1489. Writer.Driver.Write(Buffer, Count);
  1490. end;}
  1491. end;
  1492. {var
  1493. s: String;
  1494. Count: LongInt; }
  1495. begin
  1496. case FDriver.NextValue of
  1497. vaNull:
  1498. Writer.WriteIdent('NULL');
  1499. vaFalse:
  1500. Writer.WriteIdent('FALSE');
  1501. vaTrue:
  1502. Writer.WriteIdent('TRUE');
  1503. vaNil:
  1504. Writer.WriteIdent('NIL');
  1505. {!!!: vaList, vaCollection:
  1506. begin
  1507. Writer.WriteValue(FDriver.ReadValue);
  1508. while not EndOfList do
  1509. CopyValue(Writer);
  1510. ReadListEnd;
  1511. Writer.WriteListEnd;
  1512. end;}
  1513. vaInt8, vaInt16, vaInt32:
  1514. Writer.WriteInteger(ReadInteger);
  1515. {$ifndef FPUNONE}
  1516. vaExtended:
  1517. Writer.WriteFloat(ReadFloat);
  1518. {$endif}
  1519. {!!!: vaString:
  1520. Writer.WriteStr(ReadStr);}
  1521. vaIdent:
  1522. Writer.WriteIdent(ReadIdent);
  1523. {!!!: vaBinary, vaLString, vaWString:
  1524. begin
  1525. Writer.WriteValue(FDriver.ReadValue);
  1526. FDriver.Read(Count, SizeOf(Count));
  1527. Writer.Driver.Write(Count, SizeOf(Count));
  1528. CopyBytes(Count);
  1529. end;}
  1530. {!!!: vaSet:
  1531. Writer.WriteSet(ReadSet);}
  1532. {$ifndef FPUNONE}
  1533. vaSingle:
  1534. Writer.WriteSingle(ReadSingle);
  1535. {$endif}
  1536. {!!!: vaCurrency:
  1537. Writer.WriteCurrency(ReadCurrency);}
  1538. {$ifndef FPUNONE}
  1539. vaDate:
  1540. Writer.WriteDate(ReadDate);
  1541. {$endif}
  1542. vaInt64:
  1543. Writer.WriteInteger(ReadInt64);
  1544. end;
  1545. end;
  1546. function TReader.FindComponentClass(const AClassName: String): TComponentClass;
  1547. var
  1548. PersistentClass: TPersistentClass;
  1549. ShortClassName: shortstring;
  1550. procedure FindInFieldTable(RootComponent: TComponent);
  1551. var
  1552. FieldTable: PFieldTable;
  1553. FieldClassTable: PFieldClassTable;
  1554. Entry: TPersistentClass;
  1555. i: Integer;
  1556. ComponentClassType: TClass;
  1557. begin
  1558. ComponentClassType := RootComponent.ClassType;
  1559. // it is not necessary to look in the FieldTable of TComponent,
  1560. // because TComponent doesn't have published properties that are
  1561. // descendants of TComponent
  1562. while ComponentClassType<>TComponent do
  1563. begin
  1564. FieldTable:=PVmt(ComponentClassType)^.vFieldTable;
  1565. if assigned(FieldTable) then
  1566. begin
  1567. FieldClassTable := FieldTable^.ClassTable;
  1568. for i := 0 to FieldClassTable^.Count -1 do
  1569. begin
  1570. Entry := FieldClassTable^.Entries[i]{$ifndef VER3_0}^{$endif};
  1571. //writeln(format('Looking for %s in field table of class %s. Found %s',
  1572. //[AClassName, ComponentClassType.ClassName, Entry.ClassName]));
  1573. if Entry.ClassNameIs(ShortClassName) and
  1574. (Entry.InheritsFrom(TComponent)) then
  1575. begin
  1576. Result := TComponentClass(Entry);
  1577. Exit;
  1578. end;
  1579. end;
  1580. end;
  1581. // look in parent class
  1582. ComponentClassType := ComponentClassType.ClassParent;
  1583. end;
  1584. end;
  1585. begin
  1586. Result := nil;
  1587. ShortClassName:=AClassName;
  1588. FindInFieldTable(Root);
  1589. if (Result=nil) and assigned(LookupRoot) and (LookupRoot<>Root) then
  1590. FindInFieldTable(LookupRoot);
  1591. if (Result=nil) then begin
  1592. PersistentClass := GetClass(AClassName);
  1593. if PersistentClass.InheritsFrom(TComponent) then
  1594. Result := TComponentClass(PersistentClass);
  1595. end;
  1596. if (Result=nil) and assigned(OnFindComponentClass) then
  1597. OnFindComponentClass(Self, AClassName, Result);
  1598. if (Result=nil) or (not Result.InheritsFrom(TComponent)) then
  1599. raise EClassNotFound.CreateFmt(SClassNotFound, [AClassName]);
  1600. end;