reader.inc 41 KB

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