reader.inc 41 KB

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