reader.inc 41 KB

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