reader.inc 41 KB

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