reader.inc 40 KB

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