reader.inc 43 KB

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