reader.inc 41 KB

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