reader.inc 39 KB

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