reader.inc 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695
  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. readvalue;
  986. end;
  987. vaNull:
  988. begin
  989. Result:=system.null;
  990. readvalue;
  991. end;
  992. { all integer sizes must be split for big endian systems }
  993. vaInt8,vaInt16,vaInt32:
  994. begin
  995. Result:=ReadInteger;
  996. end;
  997. vaInt64:
  998. begin
  999. Result:=ReadInt64;
  1000. end;
  1001. vaQWord:
  1002. begin
  1003. Result:=QWord(ReadInt64);
  1004. end;
  1005. vaFalse,vaTrue:
  1006. begin
  1007. Result:=(nv<>vaFalse);
  1008. end;
  1009. vaCurrency:
  1010. begin
  1011. Result:=ReadCurrency;
  1012. end;
  1013. {$ifndef fpunone}
  1014. vaSingle:
  1015. begin
  1016. Result:=ReadSingle;
  1017. end;
  1018. vaExtended:
  1019. begin
  1020. Result:=ReadFloat;
  1021. end;
  1022. vaDate:
  1023. begin
  1024. Result:=ReadDate;
  1025. end;
  1026. {$endif fpunone}
  1027. vaWString,vaUTF8String:
  1028. begin
  1029. Result:=ReadWideString;
  1030. end;
  1031. vaString:
  1032. begin
  1033. Result:=ReadString;
  1034. end;
  1035. vaUString:
  1036. begin
  1037. Result:=ReadUnicodeString;
  1038. end;
  1039. else
  1040. raise EReadError.CreateFmt(SUnsupportedPropertyVariantType, [Ord(nv)]);
  1041. end;
  1042. end;
  1043. procedure TReader.ReadProperty(AInstance: TPersistent);
  1044. var
  1045. Path: String;
  1046. Instance: TPersistent;
  1047. DotPos, NextPos: PChar;
  1048. PropInfo: PPropInfo;
  1049. Obj: TObject;
  1050. Name: String;
  1051. Skip: Boolean;
  1052. Handled: Boolean;
  1053. OldPropName: String;
  1054. function HandleMissingProperty(IsPath: Boolean): boolean;
  1055. begin
  1056. Result:=true;
  1057. if Assigned(OnPropertyNotFound) then begin
  1058. // user defined property error handling
  1059. OldPropName:=FPropName;
  1060. Handled:=false;
  1061. Skip:=false;
  1062. OnPropertyNotFound(Self,Instance,FPropName,IsPath,Handled,Skip);
  1063. if Handled and (not Skip) and (OldPropName<>FPropName) then
  1064. // try alias property
  1065. PropInfo := GetPropInfo(Instance.ClassInfo, FPropName);
  1066. if Skip then begin
  1067. FDriver.SkipValue;
  1068. Result:=false;
  1069. exit;
  1070. end;
  1071. end;
  1072. end;
  1073. begin
  1074. try
  1075. Path := FDriver.BeginProperty;
  1076. try
  1077. Instance := AInstance;
  1078. FCanHandleExcepts := True;
  1079. DotPos := PChar(Path);
  1080. while True do
  1081. begin
  1082. NextPos := StrScan(DotPos, '.');
  1083. if Assigned(NextPos) then
  1084. FPropName := Copy(String(DotPos), 1, Integer(NextPos - DotPos))
  1085. else
  1086. begin
  1087. FPropName := DotPos;
  1088. break;
  1089. end;
  1090. DotPos := NextPos + 1;
  1091. PropInfo := GetPropInfo(Instance.ClassInfo, FPropName);
  1092. if not Assigned(PropInfo) then begin
  1093. if not HandleMissingProperty(true) then exit;
  1094. if not Assigned(PropInfo) then
  1095. PropertyError;
  1096. end;
  1097. if PropInfo^.PropType^.Kind = tkClass then
  1098. Obj := TObject(GetObjectProp(Instance, PropInfo))
  1099. else
  1100. Obj := nil;
  1101. if not (Obj is TPersistent) then
  1102. begin
  1103. { All path elements must be persistent objects! }
  1104. FDriver.SkipValue;
  1105. raise EReadError.Create(SInvalidPropertyPath);
  1106. end;
  1107. Instance := TPersistent(Obj);
  1108. end;
  1109. PropInfo := GetPropInfo(Instance.ClassInfo, FPropName);
  1110. if Assigned(PropInfo) then
  1111. ReadPropValue(Instance, PropInfo)
  1112. else
  1113. begin
  1114. FCanHandleExcepts := False;
  1115. Instance.DefineProperties(Self);
  1116. FCanHandleExcepts := True;
  1117. if Length(FPropName) > 0 then begin
  1118. if not HandleMissingProperty(false) then exit;
  1119. if not Assigned(PropInfo) then
  1120. PropertyError;
  1121. end;
  1122. end;
  1123. except
  1124. on e: Exception do
  1125. begin
  1126. SetLength(Name, 0);
  1127. if AInstance.InheritsFrom(TComponent) then
  1128. Name := TComponent(AInstance).Name;
  1129. if Length(Name) = 0 then
  1130. Name := AInstance.ClassName;
  1131. raise EReadError.CreateFmt(SPropertyException,
  1132. [Name, DotSep, Path, e.Message]);
  1133. end;
  1134. end;
  1135. except
  1136. on e: Exception do
  1137. if not FCanHandleExcepts or not Error(E.Message) then
  1138. raise;
  1139. end;
  1140. end;
  1141. procedure TReader.ReadPropValue(Instance: TPersistent; PropInfo: Pointer);
  1142. const
  1143. NullMethod: TMethod = (Code: nil; Data: nil);
  1144. var
  1145. PropType: PTypeInfo;
  1146. Value: LongInt;
  1147. { IdentToIntFn: TIdentToInt; }
  1148. Ident: String;
  1149. Method: TMethod;
  1150. Handled: Boolean;
  1151. TmpStr: String;
  1152. begin
  1153. if not Assigned(PPropInfo(PropInfo)^.SetProc) then
  1154. raise EReadError.Create(SReadOnlyProperty);
  1155. PropType := PPropInfo(PropInfo)^.PropType;
  1156. case PropType^.Kind of
  1157. tkInteger:
  1158. if FDriver.NextValue = vaIdent then
  1159. begin
  1160. Ident := ReadIdent;
  1161. if GlobalIdentToInt(Ident,Value) then
  1162. SetOrdProp(Instance, PropInfo, Value)
  1163. else
  1164. raise EReadError.Create(SInvalidPropertyValue);
  1165. end else
  1166. SetOrdProp(Instance, PropInfo, ReadInteger);
  1167. tkBool:
  1168. SetOrdProp(Instance, PropInfo, Ord(ReadBoolean));
  1169. tkChar:
  1170. SetOrdProp(Instance, PropInfo, Ord(ReadChar));
  1171. tkWChar,tkUChar:
  1172. SetOrdProp(Instance, PropInfo, Ord(ReadWideChar));
  1173. tkEnumeration:
  1174. begin
  1175. Value := GetEnumValue(PropType, ReadIdent);
  1176. if Value = -1 then
  1177. raise EReadError.Create(SInvalidPropertyValue);
  1178. SetOrdProp(Instance, PropInfo, Value);
  1179. end;
  1180. {$ifndef FPUNONE}
  1181. tkFloat:
  1182. SetFloatProp(Instance, PropInfo, ReadFloat);
  1183. {$endif}
  1184. tkSet:
  1185. begin
  1186. CheckValue(vaSet);
  1187. SetOrdProp(Instance, PropInfo,
  1188. FDriver.ReadSet(GetTypeData(PropType)^.CompType));
  1189. end;
  1190. tkMethod:
  1191. if FDriver.NextValue = vaNil then
  1192. begin
  1193. FDriver.ReadValue;
  1194. SetMethodProp(Instance, PropInfo, NullMethod);
  1195. end else
  1196. begin
  1197. Handled:=false;
  1198. Ident:=ReadIdent;
  1199. if Assigned(OnSetMethodProperty) then
  1200. OnSetMethodProperty(Self,Instance,PPropInfo(PropInfo),Ident,
  1201. Handled);
  1202. if not Handled then begin
  1203. Method.Code := FindMethod(Root, Ident);
  1204. Method.Data := Root;
  1205. if Assigned(Method.Code) then
  1206. SetMethodProp(Instance, PropInfo, Method);
  1207. end;
  1208. end;
  1209. tkSString, tkLString, tkAString:
  1210. begin
  1211. TmpStr:=ReadString;
  1212. if Assigned(FOnReadStringProperty) then
  1213. FOnReadStringProperty(Self,Instance,PropInfo,TmpStr);
  1214. SetStrProp(Instance, PropInfo, TmpStr);
  1215. end;
  1216. tkUstring:
  1217. SetUnicodeStrProp(Instance,PropInfo,ReadUnicodeString);
  1218. tkWString:
  1219. SetWideStrProp(Instance,PropInfo,ReadWideString);
  1220. tkVariant:
  1221. begin
  1222. SetVariantProp(Instance,PropInfo,ReadVariant);
  1223. end;
  1224. tkClass:
  1225. case FDriver.NextValue of
  1226. vaNil:
  1227. begin
  1228. FDriver.ReadValue;
  1229. SetOrdProp(Instance, PropInfo, 0)
  1230. end;
  1231. vaCollection:
  1232. begin
  1233. FDriver.ReadValue;
  1234. ReadCollection(TCollection(GetObjectProp(Instance, PropInfo)));
  1235. end
  1236. else
  1237. begin
  1238. If Not Assigned(FFixups) then
  1239. FFixups:=TLinkedList.Create(TLocalUnresolvedReference);
  1240. With TLocalUnresolvedReference(TLinkedList(FFixups).Add) do
  1241. begin
  1242. FInstance:=Instance;
  1243. FRoot:=Root;
  1244. FPropInfo:=PropInfo;
  1245. FRelative:=ReadIdent;
  1246. end;
  1247. end;
  1248. end;
  1249. tkInt64, tkQWord: SetInt64Prop(Instance, PropInfo, ReadInt64);
  1250. else
  1251. raise EReadError.CreateFmt(SUnknownPropertyType, [Ord(PropType^.Kind)]);
  1252. end;
  1253. end;
  1254. function TReader.ReadRootComponent(ARoot: TComponent): TComponent;
  1255. var
  1256. Dummy, i: Integer;
  1257. Flags: TFilerFlags;
  1258. CompClassName, CompName, ResultName: String;
  1259. begin
  1260. FDriver.BeginRootComponent;
  1261. Result := nil;
  1262. {!!!: GlobalNameSpace.BeginWrite; // Loading from stream adds to name space
  1263. try}
  1264. try
  1265. FDriver.BeginComponent(Flags, Dummy, CompClassName, CompName);
  1266. if not Assigned(ARoot) then
  1267. begin
  1268. { Read the class name and the object name and create a new object: }
  1269. Result := TComponentClass(FindClass(CompClassName)).Create(nil);
  1270. Result.Name := CompName;
  1271. end else
  1272. begin
  1273. Result := ARoot;
  1274. if not (csDesigning in Result.ComponentState) then
  1275. begin
  1276. Result.FComponentState :=
  1277. Result.FComponentState + [csLoading, csReading];
  1278. { We need an unique name }
  1279. i := 0;
  1280. { Don't use Result.Name directly, as this would influence
  1281. FindGlobalComponent in successive loop runs }
  1282. ResultName := CompName;
  1283. while Assigned(FindGlobalComponent(ResultName)) do
  1284. begin
  1285. Inc(i);
  1286. ResultName := CompName + '_' + IntToStr(i);
  1287. end;
  1288. Result.Name := ResultName;
  1289. end;
  1290. end;
  1291. FRoot := Result;
  1292. FLookupRoot := Result;
  1293. if Assigned(GlobalLoaded) then
  1294. FLoaded := GlobalLoaded
  1295. else
  1296. FLoaded := TFpList.Create;
  1297. try
  1298. if FLoaded.IndexOf(FRoot) < 0 then
  1299. FLoaded.Add(FRoot);
  1300. FOwner := FRoot;
  1301. FRoot.FComponentState := FRoot.FComponentState + [csLoading, csReading];
  1302. FRoot.ReadState(Self);
  1303. Exclude(FRoot.FComponentState, csReading);
  1304. if not Assigned(GlobalLoaded) then
  1305. for i := 0 to FLoaded.Count - 1 do
  1306. TComponent(FLoaded[i]).Loaded;
  1307. finally
  1308. if not Assigned(GlobalLoaded) then
  1309. FLoaded.Free;
  1310. FLoaded := nil;
  1311. end;
  1312. GlobalFixupReferences;
  1313. except
  1314. RemoveFixupReferences(ARoot, '');
  1315. if not Assigned(ARoot) then
  1316. Result.Free;
  1317. raise;
  1318. end;
  1319. {finally
  1320. GlobalNameSpace.EndWrite;
  1321. end;}
  1322. end;
  1323. procedure TReader.ReadComponents(AOwner, AParent: TComponent;
  1324. Proc: TReadComponentsProc);
  1325. var
  1326. Component: TComponent;
  1327. begin
  1328. Root := AOwner;
  1329. Owner := AOwner;
  1330. Parent := AParent;
  1331. BeginReferences;
  1332. try
  1333. while not EndOfList do
  1334. begin
  1335. FDriver.BeginRootComponent;
  1336. Component := ReadComponent(nil);
  1337. if Assigned(Proc) then
  1338. Proc(Component);
  1339. end;
  1340. ReadListEnd;
  1341. FixupReferences;
  1342. finally
  1343. EndReferences;
  1344. end;
  1345. end;
  1346. function TReader.ReadString: String;
  1347. var
  1348. StringType: TValueType;
  1349. begin
  1350. StringType := FDriver.ReadValue;
  1351. if StringType in [vaString, vaLString,vaUTF8String] then
  1352. begin
  1353. Result := FDriver.ReadString(StringType);
  1354. if (StringType=vaUTF8String) then
  1355. Result:=utf8Decode(Result);
  1356. end
  1357. else if StringType in [vaWString] then
  1358. Result:= FDriver.ReadWidestring
  1359. else if StringType in [vaUString] then
  1360. Result:= FDriver.ReadUnicodeString
  1361. else
  1362. raise EReadError.Create(SInvalidPropertyValue);
  1363. end;
  1364. function TReader.ReadWideString: WideString;
  1365. var
  1366. s: String;
  1367. i: Integer;
  1368. vt:TValueType;
  1369. begin
  1370. if NextValue in [vaWString,vaUString,vaUTF8String] then
  1371. //vaUTF8String needs conversion? 2008-09-06 mse, YES!! AntonK
  1372. begin
  1373. vt:=ReadValue;
  1374. if vt=vaUTF8String then
  1375. Result := utf8decode(fDriver.ReadString(vaLString))
  1376. else
  1377. Result := FDriver.ReadWideString
  1378. end
  1379. else
  1380. begin
  1381. //data probable from ObjectTextToBinary
  1382. s := ReadString;
  1383. setlength(result,length(s));
  1384. for i:= 1 to length(s) do begin
  1385. result[i]:= widechar(ord(s[i])); //no code conversion
  1386. end;
  1387. end;
  1388. end;
  1389. function TReader.ReadUnicodeString: UnicodeString;
  1390. var
  1391. s: String;
  1392. i: Integer;
  1393. vt:TValueType;
  1394. begin
  1395. if NextValue in [vaWString,vaUString,vaUTF8String] then
  1396. //vaUTF8String needs conversion? 2008-09-06 mse, YES!! AntonK
  1397. begin
  1398. vt:=ReadValue;
  1399. if vt=vaUTF8String then
  1400. Result := utf8decode(fDriver.ReadString(vaLString))
  1401. else
  1402. Result := FDriver.ReadWideString
  1403. end
  1404. else
  1405. begin
  1406. //data probable from ObjectTextToBinary
  1407. s := ReadString;
  1408. setlength(result,length(s));
  1409. for i:= 1 to length(s) do begin
  1410. result[i]:= UnicodeChar(ord(s[i])); //no code conversion
  1411. end;
  1412. end;
  1413. end;
  1414. function TReader.ReadValue: TValueType;
  1415. begin
  1416. Result := FDriver.ReadValue;
  1417. end;
  1418. procedure TReader.CopyValue(Writer: TWriter);
  1419. procedure CopyBytes(Count: Integer);
  1420. { var
  1421. Buffer: array[0..1023] of Byte; }
  1422. begin
  1423. {!!!: while Count > 1024 do
  1424. begin
  1425. FDriver.Read(Buffer, 1024);
  1426. Writer.Driver.Write(Buffer, 1024);
  1427. Dec(Count, 1024);
  1428. end;
  1429. if Count > 0 then
  1430. begin
  1431. FDriver.Read(Buffer, Count);
  1432. Writer.Driver.Write(Buffer, Count);
  1433. end;}
  1434. end;
  1435. {var
  1436. s: String;
  1437. Count: LongInt; }
  1438. begin
  1439. case FDriver.NextValue of
  1440. vaNull:
  1441. Writer.WriteIdent('NULL');
  1442. vaFalse:
  1443. Writer.WriteIdent('FALSE');
  1444. vaTrue:
  1445. Writer.WriteIdent('TRUE');
  1446. vaNil:
  1447. Writer.WriteIdent('NIL');
  1448. {!!!: vaList, vaCollection:
  1449. begin
  1450. Writer.WriteValue(FDriver.ReadValue);
  1451. while not EndOfList do
  1452. CopyValue(Writer);
  1453. ReadListEnd;
  1454. Writer.WriteListEnd;
  1455. end;}
  1456. vaInt8, vaInt16, vaInt32:
  1457. Writer.WriteInteger(ReadInteger);
  1458. {$ifndef FPUNONE}
  1459. vaExtended:
  1460. Writer.WriteFloat(ReadFloat);
  1461. {$endif}
  1462. {!!!: vaString:
  1463. Writer.WriteStr(ReadStr);}
  1464. vaIdent:
  1465. Writer.WriteIdent(ReadIdent);
  1466. {!!!: vaBinary, vaLString, vaWString:
  1467. begin
  1468. Writer.WriteValue(FDriver.ReadValue);
  1469. FDriver.Read(Count, SizeOf(Count));
  1470. Writer.Driver.Write(Count, SizeOf(Count));
  1471. CopyBytes(Count);
  1472. end;}
  1473. {!!!: vaSet:
  1474. Writer.WriteSet(ReadSet);}
  1475. {$ifndef FPUNONE}
  1476. vaSingle:
  1477. Writer.WriteSingle(ReadSingle);
  1478. {$endif}
  1479. {!!!: vaCurrency:
  1480. Writer.WriteCurrency(ReadCurrency);}
  1481. {$ifndef FPUNONE}
  1482. vaDate:
  1483. Writer.WriteDate(ReadDate);
  1484. {$endif}
  1485. vaInt64:
  1486. Writer.WriteInteger(ReadInt64);
  1487. end;
  1488. end;
  1489. function TReader.FindComponentClass(const AClassName: String): TComponentClass;
  1490. var
  1491. PersistentClass: TPersistentClass;
  1492. UClassName: shortstring;
  1493. procedure FindInFieldTable(RootComponent: TComponent);
  1494. var
  1495. FieldClassTable: PFieldClassTable;
  1496. Entry: TPersistentClass;
  1497. i: Integer;
  1498. ComponentClassType: TClass;
  1499. begin
  1500. ComponentClassType := RootComponent.ClassType;
  1501. // it is not necessary to look in the FieldTable of TComponent,
  1502. // because TComponent doesn't have published properties that are
  1503. // descendants of TComponent
  1504. while ComponentClassType<>TComponent do begin
  1505. FieldClassTable :=
  1506. PFieldTable((Pointer(ComponentClassType)+vmtFieldTable)^)^.ClassTable;
  1507. if assigned(FieldClassTable) then begin
  1508. for i := 0 to FieldClassTable^.Count -1 do begin
  1509. Entry := FieldClassTable^.Entries[i];
  1510. //writeln(format('Looking for %s in field table of class %s. Found %s',
  1511. //[AClassName, ComponentClassType.ClassName, Entry.ClassName]));
  1512. if (UpperCase(Entry.ClassName)=UClassName) and
  1513. (Entry.InheritsFrom(TComponent)) then begin
  1514. Result := TComponentClass(Entry);
  1515. Exit;
  1516. end;
  1517. end;
  1518. end;
  1519. // look in parent class
  1520. ComponentClassType := ComponentClassType.ClassParent;
  1521. end;
  1522. end;
  1523. begin
  1524. Result := nil;
  1525. UClassName:=UpperCase(AClassName);
  1526. FindInFieldTable(Root);
  1527. if (Result=nil) and assigned(LookupRoot) and (LookupRoot<>Root) then
  1528. FindInFieldTable(LookupRoot);
  1529. if (Result=nil) then begin
  1530. PersistentClass := GetClass(AClassName);
  1531. if PersistentClass.InheritsFrom(TComponent) then
  1532. Result := TComponentClass(PersistentClass);
  1533. end;
  1534. if (Result=nil) and assigned(OnFindComponentClass) then
  1535. OnFindComponentClass(Self, AClassName, Result);
  1536. if (Result=nil) or (not Result.InheritsFrom(TComponent)) then
  1537. raise EClassNotFound.CreateFmt(SClassNotFound, [AClassName]);
  1538. end;