reader.inc 42 KB

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