reader.inc 40 KB

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