2
0

reader.inc 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824
  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 =
  491. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  492. packed
  493. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  494. record
  495. FieldOffset: SizeUInt;
  496. ClassTypeIndex: Word; // start at 1
  497. Name: ShortString;
  498. end;
  499. PFieldInfo = ^TFieldInfo;
  500. PPersistentClass = ^TPersistentClass;
  501. PersistentClassRef = PPersistentClass;
  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. PFieldClassTable = ^TFieldClassTable;
  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[0..0] of TFieldInfo;
  519. end;
  520. PFieldTable = ^TFieldTable;
  521. function GetFieldClass(Instance: TObject; const ClassName: string): TPersistentClass;
  522. var
  523. ShortClassName: shortstring;
  524. ClassType: TClass;
  525. ClassTable: PFieldClassTable;
  526. i: Integer;
  527. FieldTable: PFieldTable;
  528. begin
  529. // At first, try to locate the class in the class tables
  530. ShortClassName := ClassName;
  531. ClassType := Instance.ClassType;
  532. while ClassType <> TPersistent do
  533. begin
  534. FieldTable := PFieldTable(PVmt(ClassType)^.vFieldTable);
  535. if Assigned(FieldTable) then
  536. begin
  537. ClassTable := FieldTable^.ClassTable;
  538. for i := 0 to ClassTable^.Count - 1 do
  539. begin
  540. Result := ClassTable^.Entries[i]{$ifndef VER3_0}^{$endif};
  541. if Result.ClassNameIs(ShortClassName) then
  542. exit;
  543. end;
  544. end;
  545. // Try again with the parent class type
  546. ClassType := ClassType.ClassParent;
  547. end;
  548. Result := Classes.GetClass(ClassName);
  549. end;
  550. constructor TReader.Create(Stream: TStream; BufSize: Integer);
  551. begin
  552. inherited Create;
  553. If (Stream=Nil) then
  554. Raise EReadError.Create(SEmptyStreamIllegalReader);
  555. FDriver := CreateDriver(Stream, BufSize);
  556. {$ifdef FPC_HAS_FEATURE_THREADING}
  557. InitCriticalSection(FLock);
  558. {$ENDIF}
  559. end;
  560. destructor TReader.Destroy;
  561. begin
  562. {$ifdef FPC_HAS_FEATURE_THREADING}
  563. DoneCriticalSection(FLock);
  564. {$ENDIF}
  565. FDriver.Free;
  566. inherited Destroy;
  567. end;
  568. procedure TReader.Lock;
  569. begin
  570. {$ifdef FPC_HAS_FEATURE_THREADING}
  571. EnterCriticalSection(FLock);
  572. {$ENDIF}
  573. end;
  574. procedure TReader.Unlock;
  575. begin
  576. {$ifdef FPC_HAS_FEATURE_THREADING}
  577. LeaveCriticalSection(FLock);
  578. {$ENDIF}
  579. end;
  580. procedure TReader.FlushBuffer;
  581. begin
  582. Driver.FlushBuffer;
  583. end;
  584. function TReader.CreateDriver(Stream: TStream; BufSize: Integer): TAbstractObjectReader;
  585. begin
  586. Result := TBinaryObjectReader.Create(Stream, BufSize);
  587. end;
  588. procedure TReader.BeginReferences;
  589. begin
  590. FLoaded := TFpList.Create;
  591. end;
  592. procedure TReader.CheckValue(Value: TValueType);
  593. begin
  594. if FDriver.NextValue <> Value then
  595. raise EReadError.Create(SInvalidPropertyValue)
  596. else
  597. FDriver.ReadValue;
  598. end;
  599. procedure TReader.DefineProperty(const Name: String; AReadData: TReaderProc;
  600. WriteData: TWriterProc; HasData: Boolean);
  601. begin
  602. if Assigned(AReadData) and (UpperCase(Name) = UpperCase(FPropName)) then
  603. begin
  604. AReadData(Self);
  605. SetLength(FPropName, 0);
  606. end;
  607. end;
  608. procedure TReader.DefineBinaryProperty(const Name: String;
  609. AReadData, WriteData: TStreamProc; HasData: Boolean);
  610. var
  611. MemBuffer: TMemoryStream;
  612. begin
  613. if Assigned(AReadData) and (UpperCase(Name) = UpperCase(FPropName)) then
  614. begin
  615. { Check if the next property really is a binary property}
  616. if FDriver.NextValue <> vaBinary then
  617. begin
  618. FDriver.SkipValue;
  619. FCanHandleExcepts := True;
  620. raise EReadError.Create(SInvalidPropertyValue);
  621. end else
  622. FDriver.ReadValue;
  623. MemBuffer := TMemoryStream.Create;
  624. try
  625. FDriver.ReadBinary(MemBuffer);
  626. FCanHandleExcepts := True;
  627. AReadData(MemBuffer);
  628. finally
  629. MemBuffer.Free;
  630. end;
  631. SetLength(FPropName, 0);
  632. end;
  633. end;
  634. function TReader.EndOfList: Boolean;
  635. begin
  636. Result := FDriver.NextValue = vaNull;
  637. end;
  638. procedure TReader.EndReferences;
  639. begin
  640. FLoaded.Free;
  641. FLoaded := nil;
  642. end;
  643. function TReader.Error(const Message: String): Boolean;
  644. begin
  645. Result := False;
  646. if Assigned(FOnError) then
  647. FOnError(Self, Message, Result);
  648. end;
  649. function TReader.FindMethod(ARoot: TComponent; const AMethodName: String): CodePointer;
  650. var
  651. ErrorResult: Boolean;
  652. begin
  653. Result := ARoot.MethodAddress(AMethodName);
  654. ErrorResult := Result = nil;
  655. { always give the OnFindMethod callback a chance to locate the method }
  656. if Assigned(FOnFindMethod) then
  657. FOnFindMethod(Self, AMethodName, Result, ErrorResult);
  658. if ErrorResult then
  659. raise EReadError.Create(SInvalidPropertyValue);
  660. end;
  661. procedure TReader.DoFixupReferences;
  662. Var
  663. R,RN : TLocalUnresolvedReference;
  664. G : TUnresolvedInstance;
  665. Ref : String;
  666. C : TComponent;
  667. P : integer;
  668. L : TLinkedList;
  669. RI: Pointer; // raw interface
  670. IIDStr: ShortString;
  671. begin
  672. If Assigned(FFixups) then
  673. begin
  674. L:=TLinkedList(FFixups);
  675. R:=TLocalUnresolvedReference(L.Root);
  676. While (R<>Nil) do
  677. begin
  678. RN:=TLocalUnresolvedReference(R.Next);
  679. Ref:=R.FRelative;
  680. If Assigned(FOnReferenceName) then
  681. FOnReferenceName(Self,Ref);
  682. C:=FindNestedComponent(R.FRoot,Ref);
  683. If Assigned(C) then
  684. if R.FPropInfo^.PropType^.Kind = tkInterface then
  685. SetInterfaceProp(R.FInstance,R.FPropInfo,C)
  686. else if R.FPropInfo^.PropType^.Kind = tkInterfaceRaw then
  687. begin
  688. IIDStr := GetTypeData(R.FPropInfo^.PropType)^.IIDStr;
  689. if IIDStr = '' then
  690. raise EReadError.CreateFmt(SInterfaceNoIIDStr, [R.FPropInfo^.PropType^.Name]);
  691. if C.GetInterface(IIDStr, RI) then
  692. SetRawInterfaceProp(R.FInstance,R.FPropInfo,RI)
  693. else
  694. raise EReadError.CreateFmt(SComponentDoesntImplement, [C.ClassName, IIDStr]);
  695. end
  696. else
  697. SetObjectProp(R.FInstance,R.FPropInfo,C)
  698. else
  699. begin
  700. P:=Pos('.',R.FRelative);
  701. If (P<>0) then
  702. begin
  703. G:=AddToResolveList(R.FInstance);
  704. G.Addreference(R.FRoot,R.FPropInfo,Copy(R.FRelative,1,P-1),Copy(R.FRelative,P+1,Length(R.FRelative)-P));
  705. end;
  706. end;
  707. L.RemoveItem(R,True);
  708. R:=RN;
  709. end;
  710. FreeAndNil(FFixups);
  711. end;
  712. end;
  713. procedure TReader.FixupReferences;
  714. var
  715. i: Integer;
  716. begin
  717. DoFixupReferences;
  718. GlobalFixupReferences;
  719. for i := 0 to FLoaded.Count - 1 do
  720. TComponent(FLoaded[I]).Loaded;
  721. end;
  722. function TReader.NextValue: TValueType;
  723. begin
  724. Result := FDriver.NextValue;
  725. end;
  726. procedure TReader.Read(var Buf; Count: LongInt);
  727. begin
  728. //This should give an exception if read is not implemented (i.e. TTextObjectReader)
  729. //but should work with TBinaryObjectReader.
  730. Driver.Read(Buf, Count);
  731. end;
  732. procedure TReader.PropertyError;
  733. begin
  734. FDriver.SkipValue;
  735. raise EReadError.CreateFmt(SUnknownProperty,[FPropName]);
  736. end;
  737. function TReader.ReadBoolean: Boolean;
  738. var
  739. ValueType: TValueType;
  740. begin
  741. ValueType := FDriver.ReadValue;
  742. if ValueType = vaTrue then
  743. Result := True
  744. else if ValueType = vaFalse then
  745. Result := False
  746. else
  747. raise EReadError.Create(SInvalidPropertyValue);
  748. end;
  749. function TReader.ReadChar: Char;
  750. var
  751. s: String;
  752. begin
  753. s := ReadString;
  754. if Length(s) = 1 then
  755. Result := s[1]
  756. else
  757. raise EReadError.Create(SInvalidPropertyValue);
  758. end;
  759. function TReader.ReadWideChar: WideChar;
  760. var
  761. W: WideString;
  762. begin
  763. W := ReadWideString;
  764. if Length(W) = 1 then
  765. Result := W[1]
  766. else
  767. raise EReadError.Create(SInvalidPropertyValue);
  768. end;
  769. function TReader.ReadUnicodeChar: UnicodeChar;
  770. var
  771. U: UnicodeString;
  772. begin
  773. U := ReadUnicodeString;
  774. if Length(U) = 1 then
  775. Result := U[1]
  776. else
  777. raise EReadError.Create(SInvalidPropertyValue);
  778. end;
  779. procedure TReader.ReadCollection(Collection: TCollection);
  780. var
  781. Item: TCollectionItem;
  782. begin
  783. Collection.BeginUpdate;
  784. if not EndOfList then
  785. Collection.Clear;
  786. while not EndOfList do begin
  787. ReadListBegin;
  788. Item := Collection.Add;
  789. while NextValue<>vaNull do
  790. ReadProperty(Item);
  791. ReadListEnd;
  792. end;
  793. Collection.EndUpdate;
  794. ReadListEnd;
  795. end;
  796. function TReader.ReadComponent(Component: TComponent): TComponent;
  797. var
  798. Flags: TFilerFlags;
  799. function Recover(var aComponent: TComponent): Boolean;
  800. begin
  801. Result := False;
  802. if ExceptObject.InheritsFrom(Exception) then
  803. begin
  804. if not ((ffInherited in Flags) or Assigned(Component)) then
  805. aComponent.Free;
  806. aComponent := nil;
  807. FDriver.SkipComponent(False);
  808. Result := Error(Exception(ExceptObject).Message);
  809. end;
  810. end;
  811. var
  812. CompClassName, Name: String;
  813. n, ChildPos: Integer;
  814. SavedParent, SavedLookupRoot: TComponent;
  815. ComponentClass: TComponentClass;
  816. C, NewComponent: TComponent;
  817. SubComponents: TList;
  818. begin
  819. FDriver.BeginComponent(Flags, ChildPos, CompClassName, Name);
  820. SavedParent := Parent;
  821. SavedLookupRoot := FLookupRoot;
  822. SubComponents := nil;
  823. try
  824. Result := Component;
  825. if not Assigned(Result) then
  826. try
  827. if ffInherited in Flags then
  828. begin
  829. { Try to locate the existing ancestor component }
  830. if Assigned(FLookupRoot) then
  831. Result := FLookupRoot.FindComponent(Name)
  832. else
  833. Result := nil;
  834. if not Assigned(Result) then
  835. begin
  836. if Assigned(FOnAncestorNotFound) then
  837. FOnAncestorNotFound(Self, Name,
  838. FindComponentClass(Name,CompClassName), Result);
  839. if not Assigned(Result) then
  840. raise EReadError.CreateFmt(SAncestorNotFound, [Name]);
  841. end;
  842. Parent := Result.GetParentComponent;
  843. if not Assigned(Parent) then
  844. Parent := Root;
  845. end else
  846. begin
  847. Result := nil;
  848. ComponentClass := FindComponentClass(Name,CompClassName);
  849. if Assigned(FOnCreateComponent) then
  850. FOnCreateComponent(Self, ComponentClass, Result);
  851. if not Assigned(Result) then
  852. begin
  853. NewComponent := TComponent(ComponentClass.NewInstance);
  854. if ffInline in Flags then
  855. NewComponent.FComponentState :=
  856. NewComponent.FComponentState + [csLoading, csInline];
  857. NewComponent.Create(Owner);
  858. { Don't set Result earlier because else we would come in trouble
  859. with the exception recover mechanism! (Result should be NIL if
  860. an error occurred) }
  861. Result := NewComponent;
  862. end;
  863. Include(Result.FComponentState, csLoading);
  864. end;
  865. except
  866. if not Recover(Result) then
  867. raise;
  868. end;
  869. if Assigned(Result) then
  870. try
  871. Include(Result.FComponentState, csLoading);
  872. { create list of subcomponents and set loading}
  873. SubComponents := TList.Create;
  874. for n := 0 to Result.ComponentCount - 1 do
  875. begin
  876. C := Result.Components[n];
  877. if csSubcomponent in C.ComponentStyle
  878. then begin
  879. SubComponents.Add(C);
  880. Include(C.FComponentState, csLoading);
  881. end;
  882. end;
  883. if not (ffInherited in Flags) then
  884. try
  885. Result.SetParentComponent(Parent);
  886. if Assigned(FOnSetName) then
  887. FOnSetName(Self, Result, Name);
  888. Result.Name := Name;
  889. if FindGlobalComponent(Name) = Result then
  890. Include(Result.FComponentState, csInline);
  891. except
  892. if not Recover(Result) then
  893. raise;
  894. end;
  895. if not Assigned(Result) then
  896. exit;
  897. if csInline in Result.ComponentState then
  898. FLookupRoot := Result;
  899. { Read the component state }
  900. Include(Result.FComponentState, csReading);
  901. for n := 0 to Subcomponents.Count - 1 do
  902. Include(TComponent(Subcomponents[n]).FComponentState, csReading);
  903. Result.ReadState(Self);
  904. Exclude(Result.FComponentState, csReading);
  905. for n := 0 to Subcomponents.Count - 1 do
  906. Exclude(TComponent(Subcomponents[n]).FComponentState, csReading);
  907. if ffChildPos in Flags then
  908. Parent.SetChildOrder(Result, ChildPos);
  909. { Add component to list of loaded components, if necessary }
  910. if (not ((ffInherited in Flags) or (csInline in Result.ComponentState))) or
  911. (FLoaded.IndexOf(Result) < 0)
  912. then begin
  913. for n := 0 to Subcomponents.Count - 1 do
  914. FLoaded.Add(Subcomponents[n]);
  915. FLoaded.Add(Result);
  916. end;
  917. except
  918. if ((ffInherited in Flags) or Assigned(Component)) then
  919. Result.Free;
  920. raise;
  921. end;
  922. finally
  923. Parent := SavedParent;
  924. FLookupRoot := SavedLookupRoot;
  925. Subcomponents.Free;
  926. end;
  927. end;
  928. procedure TReader.ReadData(Instance: TComponent);
  929. var
  930. SavedOwner, SavedParent: TComponent;
  931. begin
  932. { Read properties }
  933. while not EndOfList do
  934. ReadProperty(Instance);
  935. ReadListEnd;
  936. { Read children }
  937. SavedOwner := Owner;
  938. SavedParent := Parent;
  939. try
  940. Owner := Instance.GetChildOwner;
  941. if not Assigned(Owner) then
  942. Owner := Root;
  943. Parent := Instance.GetChildParent;
  944. while not EndOfList do
  945. ReadComponent(nil);
  946. ReadListEnd;
  947. finally
  948. Owner := SavedOwner;
  949. Parent := SavedParent;
  950. end;
  951. { Fixup references if necessary (normally only if this is the root) }
  952. If (Instance=FRoot) then
  953. DoFixupReferences;
  954. end;
  955. {$ifndef FPUNONE}
  956. function TReader.ReadFloat: Extended;
  957. begin
  958. if FDriver.NextValue = vaExtended then
  959. begin
  960. ReadValue;
  961. Result := FDriver.ReadFloat
  962. end else
  963. Result := ReadInt64;
  964. end;
  965. procedure TReader.ReadSignature;
  966. begin
  967. FDriver.ReadSignature;
  968. end;
  969. function TReader.ReadSingle: Single;
  970. begin
  971. if FDriver.NextValue = vaSingle then
  972. begin
  973. FDriver.ReadValue;
  974. Result := FDriver.ReadSingle;
  975. end else
  976. Result := ReadInteger;
  977. end;
  978. {$endif}
  979. function TReader.ReadCurrency: Currency;
  980. begin
  981. if FDriver.NextValue = vaCurrency then
  982. begin
  983. FDriver.ReadValue;
  984. Result := FDriver.ReadCurrency;
  985. end else
  986. Result := ReadInteger;
  987. end;
  988. {$ifndef FPUNONE}
  989. function TReader.ReadDate: TDateTime;
  990. begin
  991. if FDriver.NextValue = vaDate then
  992. begin
  993. FDriver.ReadValue;
  994. Result := FDriver.ReadDate;
  995. end else
  996. Result := ReadInteger;
  997. end;
  998. {$endif}
  999. function TReader.ReadIdent: String;
  1000. var
  1001. ValueType: TValueType;
  1002. begin
  1003. ValueType := FDriver.ReadValue;
  1004. if ValueType in [vaIdent, vaNil, vaFalse, vaTrue, vaNull] then
  1005. Result := FDriver.ReadIdent(ValueType)
  1006. else
  1007. raise EReadError.Create(SInvalidPropertyValue);
  1008. end;
  1009. function TReader.ReadInteger: LongInt;
  1010. begin
  1011. case FDriver.ReadValue of
  1012. vaInt8:
  1013. Result := FDriver.ReadInt8;
  1014. vaInt16:
  1015. Result := FDriver.ReadInt16;
  1016. vaInt32:
  1017. Result := FDriver.ReadInt32;
  1018. else
  1019. raise EReadError.Create(SInvalidPropertyValue);
  1020. end;
  1021. end;
  1022. function TReader.ReadInt64: Int64;
  1023. begin
  1024. if FDriver.NextValue = vaInt64 then
  1025. begin
  1026. FDriver.ReadValue;
  1027. Result := FDriver.ReadInt64;
  1028. end else
  1029. Result := ReadInteger;
  1030. end;
  1031. function TReader.ReadSet(EnumType: Pointer): Integer;
  1032. begin
  1033. if FDriver.NextValue = vaSet then
  1034. begin
  1035. FDriver.ReadValue;
  1036. Result := FDriver.ReadSet(enumtype);
  1037. end
  1038. else
  1039. Result := ReadInteger;
  1040. end;
  1041. procedure TReader.ReadListBegin;
  1042. begin
  1043. CheckValue(vaList);
  1044. end;
  1045. procedure TReader.ReadListEnd;
  1046. begin
  1047. CheckValue(vaNull);
  1048. end;
  1049. function TReader.ReadVariant: variant;
  1050. var
  1051. nv: TValueType;
  1052. begin
  1053. { Ensure that a Variant manager is installed }
  1054. if not Assigned(VarClearProc) then
  1055. raise EReadError.Create(SErrNoVariantSupport);
  1056. FillChar(Result,sizeof(Result),0);
  1057. nv:=NextValue;
  1058. case nv of
  1059. vaNil:
  1060. begin
  1061. Result:=system.unassigned;
  1062. readvalue;
  1063. end;
  1064. vaNull:
  1065. begin
  1066. Result:=system.null;
  1067. readvalue;
  1068. end;
  1069. { all integer sizes must be split for big endian systems }
  1070. vaInt8,vaInt16,vaInt32:
  1071. begin
  1072. Result:=ReadInteger;
  1073. end;
  1074. vaInt64:
  1075. begin
  1076. Result:=ReadInt64;
  1077. end;
  1078. vaQWord:
  1079. begin
  1080. Result:=QWord(ReadInt64);
  1081. end;
  1082. vaFalse,vaTrue:
  1083. begin
  1084. Result:=(nv<>vaFalse);
  1085. readValue;
  1086. end;
  1087. vaCurrency:
  1088. begin
  1089. Result:=ReadCurrency;
  1090. end;
  1091. {$ifndef fpunone}
  1092. vaSingle:
  1093. begin
  1094. Result:=ReadSingle;
  1095. end;
  1096. vaExtended:
  1097. begin
  1098. Result:=ReadFloat;
  1099. end;
  1100. vaDate:
  1101. begin
  1102. Result:=ReadDate;
  1103. end;
  1104. {$endif fpunone}
  1105. vaWString,vaUTF8String:
  1106. begin
  1107. Result:=ReadWideString;
  1108. end;
  1109. vaString:
  1110. begin
  1111. Result:=ReadString;
  1112. end;
  1113. vaUString:
  1114. begin
  1115. Result:=ReadUnicodeString;
  1116. end;
  1117. else
  1118. raise EReadError.CreateFmt(SUnsupportedPropertyVariantType, [Ord(nv)]);
  1119. end;
  1120. end;
  1121. procedure TReader.ReadProperty(AInstance: TPersistent);
  1122. var
  1123. Path: String;
  1124. Instance: TPersistent;
  1125. DotPos, NextPos: PChar;
  1126. PropInfo: PPropInfo;
  1127. Obj: TObject;
  1128. Name: String;
  1129. Skip: Boolean;
  1130. Handled: Boolean;
  1131. OldPropName: String;
  1132. function HandleMissingProperty(IsPath: Boolean): boolean;
  1133. begin
  1134. Result:=true;
  1135. if Assigned(OnPropertyNotFound) then begin
  1136. // user defined property error handling
  1137. OldPropName:=FPropName;
  1138. Handled:=false;
  1139. Skip:=false;
  1140. OnPropertyNotFound(Self,Instance,FPropName,IsPath,Handled,Skip);
  1141. if Handled and (not Skip) and (OldPropName<>FPropName) then
  1142. // try alias property
  1143. PropInfo := GetPropInfo(Instance.ClassInfo, FPropName);
  1144. if Skip then begin
  1145. FDriver.SkipValue;
  1146. Result:=false;
  1147. exit;
  1148. end;
  1149. end;
  1150. end;
  1151. begin
  1152. try
  1153. Path := FDriver.BeginProperty;
  1154. try
  1155. Instance := AInstance;
  1156. FCanHandleExcepts := True;
  1157. DotPos := PChar(Path);
  1158. while True do
  1159. begin
  1160. NextPos := StrScan(DotPos, '.');
  1161. if Assigned(NextPos) then
  1162. FPropName := Copy(String(DotPos), 1, Integer(NextPos - DotPos))
  1163. else
  1164. begin
  1165. FPropName := DotPos;
  1166. break;
  1167. end;
  1168. DotPos := NextPos + 1;
  1169. PropInfo := GetPropInfo(Instance.ClassInfo, FPropName);
  1170. if not Assigned(PropInfo) then begin
  1171. if not HandleMissingProperty(true) then exit;
  1172. if not Assigned(PropInfo) then
  1173. PropertyError;
  1174. end;
  1175. if PropInfo^.PropType^.Kind = tkClass then
  1176. Obj := TObject(GetObjectProp(Instance, PropInfo))
  1177. //else if PropInfo^.PropType^.Kind = tkInterface then
  1178. // Obj := TObject(GetInterfaceProp(Instance, PropInfo))
  1179. else
  1180. Obj := nil;
  1181. if not (Obj is TPersistent) then
  1182. begin
  1183. { All path elements must be persistent objects! }
  1184. FDriver.SkipValue;
  1185. raise EReadError.Create(SInvalidPropertyPath);
  1186. end;
  1187. Instance := TPersistent(Obj);
  1188. end;
  1189. PropInfo := GetPropInfo(Instance.ClassInfo, FPropName);
  1190. if Assigned(PropInfo) then
  1191. ReadPropValue(Instance, PropInfo)
  1192. else
  1193. begin
  1194. FCanHandleExcepts := False;
  1195. Instance.DefineProperties(Self);
  1196. FCanHandleExcepts := True;
  1197. if Length(FPropName) > 0 then begin
  1198. if not HandleMissingProperty(false) then exit;
  1199. if not Assigned(PropInfo) then
  1200. PropertyError;
  1201. end;
  1202. end;
  1203. except
  1204. on e: Exception do
  1205. begin
  1206. SetLength(Name, 0);
  1207. if AInstance.InheritsFrom(TComponent) then
  1208. Name := TComponent(AInstance).Name;
  1209. if Length(Name) = 0 then
  1210. Name := AInstance.ClassName;
  1211. raise EReadError.CreateFmt(SPropertyException,
  1212. [Name, DotSep, Path, e.Message]);
  1213. end;
  1214. end;
  1215. except
  1216. on e: Exception do
  1217. if not FCanHandleExcepts or not Error(E.Message) then
  1218. raise;
  1219. end;
  1220. end;
  1221. procedure TReader.ReadPropValue(Instance: TPersistent; PropInfo: Pointer);
  1222. const
  1223. NullMethod: TMethod = (Code: nil; Data: nil);
  1224. var
  1225. PropType: PTypeInfo;
  1226. Value: LongInt;
  1227. { IdentToIntFn: TIdentToInt; }
  1228. Ident: String;
  1229. Method: TMethod;
  1230. Handled: Boolean;
  1231. TmpStr: String;
  1232. begin
  1233. if not Assigned(PPropInfo(PropInfo)^.SetProc) then
  1234. raise EReadError.Create(SReadOnlyProperty);
  1235. PropType := PPropInfo(PropInfo)^.PropType;
  1236. case PropType^.Kind of
  1237. tkInteger:
  1238. if FDriver.NextValue = vaIdent then
  1239. begin
  1240. Ident := ReadIdent;
  1241. if GlobalIdentToInt(Ident,Value) then
  1242. SetOrdProp(Instance, PropInfo, Value)
  1243. else
  1244. raise EReadError.Create(SInvalidPropertyValue);
  1245. end else
  1246. SetOrdProp(Instance, PropInfo, ReadInteger);
  1247. tkBool:
  1248. SetOrdProp(Instance, PropInfo, Ord(ReadBoolean));
  1249. tkChar:
  1250. SetOrdProp(Instance, PropInfo, Ord(ReadChar));
  1251. tkWChar,tkUChar:
  1252. SetOrdProp(Instance, PropInfo, Ord(ReadWideChar));
  1253. tkEnumeration:
  1254. begin
  1255. Value := GetEnumValue(PropType, ReadIdent);
  1256. if Value = -1 then
  1257. raise EReadError.Create(SInvalidPropertyValue);
  1258. SetOrdProp(Instance, PropInfo, Value);
  1259. end;
  1260. {$ifndef FPUNONE}
  1261. tkFloat:
  1262. SetFloatProp(Instance, PropInfo, ReadFloat);
  1263. {$endif}
  1264. tkSet:
  1265. begin
  1266. CheckValue(vaSet);
  1267. SetOrdProp(Instance, PropInfo,
  1268. FDriver.ReadSet(GetTypeData(PropType)^.CompType));
  1269. end;
  1270. tkMethod:
  1271. if FDriver.NextValue = vaNil then
  1272. begin
  1273. FDriver.ReadValue;
  1274. SetMethodProp(Instance, PropInfo, NullMethod);
  1275. end else
  1276. begin
  1277. Handled:=false;
  1278. Ident:=ReadIdent;
  1279. if Assigned(OnSetMethodProperty) then
  1280. OnSetMethodProperty(Self,Instance,PPropInfo(PropInfo),Ident,
  1281. Handled);
  1282. if not Handled then begin
  1283. Method.Code := FindMethod(Root, Ident);
  1284. Method.Data := Root;
  1285. if Assigned(Method.Code) then
  1286. SetMethodProp(Instance, PropInfo, Method);
  1287. end;
  1288. end;
  1289. tkSString, tkLString, tkAString:
  1290. begin
  1291. TmpStr:=ReadString;
  1292. if Assigned(FOnReadStringProperty) then
  1293. FOnReadStringProperty(Self,Instance,PropInfo,TmpStr);
  1294. SetStrProp(Instance, PropInfo, TmpStr);
  1295. end;
  1296. tkUstring:
  1297. SetUnicodeStrProp(Instance,PropInfo,ReadUnicodeString);
  1298. tkWString:
  1299. SetWideStrProp(Instance,PropInfo,ReadWideString);
  1300. tkVariant:
  1301. begin
  1302. SetVariantProp(Instance,PropInfo,ReadVariant);
  1303. end;
  1304. tkClass, tkInterface, tkInterfaceRaw:
  1305. case FDriver.NextValue of
  1306. vaNil:
  1307. begin
  1308. FDriver.ReadValue;
  1309. SetOrdProp(Instance, PropInfo, 0)
  1310. end;
  1311. vaCollection:
  1312. begin
  1313. FDriver.ReadValue;
  1314. ReadCollection(TCollection(GetObjectProp(Instance, PropInfo)));
  1315. end
  1316. else
  1317. begin
  1318. If Not Assigned(FFixups) then
  1319. FFixups:=TLinkedList.Create(TLocalUnresolvedReference);
  1320. With TLocalUnresolvedReference(TLinkedList(FFixups).Add) do
  1321. begin
  1322. FInstance:=Instance;
  1323. FRoot:=Root;
  1324. FPropInfo:=PropInfo;
  1325. FRelative:=ReadIdent;
  1326. end;
  1327. end;
  1328. end;
  1329. tkInt64, tkQWord: SetInt64Prop(Instance, PropInfo, ReadInt64);
  1330. else
  1331. raise EReadError.CreateFmt(SUnknownPropertyType, [Ord(PropType^.Kind)]);
  1332. end;
  1333. end;
  1334. function TReader.ReadRootComponent(ARoot: TComponent): TComponent;
  1335. var
  1336. Dummy, i: Integer;
  1337. Flags: TFilerFlags;
  1338. CompClassName, CompName, ResultName: String;
  1339. begin
  1340. FDriver.BeginRootComponent;
  1341. Result := nil;
  1342. {!!!: GlobalNameSpace.BeginWrite; // Loading from stream adds to name space
  1343. try}
  1344. try
  1345. FDriver.BeginComponent(Flags, Dummy, CompClassName, CompName);
  1346. if not Assigned(ARoot) then
  1347. begin
  1348. { Read the class name and the object name and create a new object: }
  1349. Result := TComponentClass(FindClass(CompClassName)).Create(nil);
  1350. Result.Name := CompName;
  1351. end else
  1352. begin
  1353. Result := ARoot;
  1354. if not (csDesigning in Result.ComponentState) then
  1355. begin
  1356. Result.FComponentState :=
  1357. Result.FComponentState + [csLoading, csReading];
  1358. { We need an unique name }
  1359. i := 0;
  1360. { Don't use Result.Name directly, as this would influence
  1361. FindGlobalComponent in successive loop runs }
  1362. ResultName := CompName;
  1363. Lock;
  1364. try
  1365. while Assigned(FindGlobalComponent(ResultName)) do
  1366. begin
  1367. Inc(i);
  1368. ResultName := CompName + '_' + IntToStr(i);
  1369. end;
  1370. Result.Name := ResultName;
  1371. finally
  1372. Unlock;
  1373. end;
  1374. end;
  1375. end;
  1376. FRoot := Result;
  1377. FLookupRoot := Result;
  1378. if Assigned(GlobalLoaded) then
  1379. FLoaded := GlobalLoaded
  1380. else
  1381. FLoaded := TFpList.Create;
  1382. try
  1383. if FLoaded.IndexOf(FRoot) < 0 then
  1384. FLoaded.Add(FRoot);
  1385. FOwner := FRoot;
  1386. FRoot.FComponentState := FRoot.FComponentState + [csLoading, csReading];
  1387. FRoot.ReadState(Self);
  1388. Exclude(FRoot.FComponentState, csReading);
  1389. if not Assigned(GlobalLoaded) then
  1390. for i := 0 to FLoaded.Count - 1 do
  1391. TComponent(FLoaded[i]).Loaded;
  1392. finally
  1393. if not Assigned(GlobalLoaded) then
  1394. FLoaded.Free;
  1395. FLoaded := nil;
  1396. end;
  1397. GlobalFixupReferences;
  1398. except
  1399. RemoveFixupReferences(ARoot, '');
  1400. if not Assigned(ARoot) then
  1401. Result.Free;
  1402. raise;
  1403. end;
  1404. {finally
  1405. GlobalNameSpace.EndWrite;
  1406. end;}
  1407. end;
  1408. procedure TReader.ReadComponents(AOwner, AParent: TComponent;
  1409. Proc: TReadComponentsProc);
  1410. var
  1411. Component: TComponent;
  1412. begin
  1413. Root := AOwner;
  1414. Owner := AOwner;
  1415. Parent := AParent;
  1416. BeginReferences;
  1417. try
  1418. while not EndOfList do
  1419. begin
  1420. FDriver.BeginRootComponent;
  1421. Component := ReadComponent(nil);
  1422. if Assigned(Proc) then
  1423. Proc(Component);
  1424. end;
  1425. ReadListEnd;
  1426. FixupReferences;
  1427. finally
  1428. EndReferences;
  1429. end;
  1430. end;
  1431. function TReader.ReadString: String;
  1432. var
  1433. StringType: TValueType;
  1434. begin
  1435. StringType := FDriver.ReadValue;
  1436. if StringType in [vaString, vaLString,vaUTF8String] then
  1437. begin
  1438. Result := FDriver.ReadString(StringType);
  1439. if (StringType=vaUTF8String) then
  1440. Result:=string(utf8Decode(Result));
  1441. end
  1442. else if StringType in [vaWString] then
  1443. Result:= string(FDriver.ReadWidestring)
  1444. else if StringType in [vaUString] then
  1445. Result:= string(FDriver.ReadUnicodeString)
  1446. else
  1447. raise EReadError.Create(SInvalidPropertyValue);
  1448. end;
  1449. function TReader.ReadWideString: WideString;
  1450. var
  1451. s: String;
  1452. i: Integer;
  1453. vt:TValueType;
  1454. begin
  1455. if NextValue in [vaWString,vaUString,vaUTF8String] then
  1456. //vaUTF8String needs conversion? 2008-09-06 mse, YES!! AntonK
  1457. begin
  1458. vt:=ReadValue;
  1459. if vt=vaUTF8String then
  1460. Result := utf8decode(fDriver.ReadString(vaLString))
  1461. else
  1462. Result := FDriver.ReadWideString
  1463. end
  1464. else
  1465. begin
  1466. //data probable from ObjectTextToBinary
  1467. s := ReadString;
  1468. setlength(result,length(s));
  1469. for i:= 1 to length(s) do begin
  1470. result[i]:= widechar(ord(s[i])); //no code conversion
  1471. end;
  1472. end;
  1473. end;
  1474. function TReader.ReadUnicodeString: UnicodeString;
  1475. var
  1476. s: String;
  1477. i: Integer;
  1478. vt:TValueType;
  1479. begin
  1480. if NextValue in [vaWString,vaUString,vaUTF8String] then
  1481. //vaUTF8String needs conversion? 2008-09-06 mse, YES!! AntonK
  1482. begin
  1483. vt:=ReadValue;
  1484. if vt=vaUTF8String then
  1485. Result := utf8decode(fDriver.ReadString(vaLString))
  1486. else
  1487. Result := FDriver.ReadWideString
  1488. end
  1489. else
  1490. begin
  1491. //data probable from ObjectTextToBinary
  1492. s := ReadString;
  1493. setlength(result,length(s));
  1494. for i:= 1 to length(s) do begin
  1495. result[i]:= UnicodeChar(ord(s[i])); //no code conversion
  1496. end;
  1497. end;
  1498. end;
  1499. function TReader.ReadValue: TValueType;
  1500. begin
  1501. Result := FDriver.ReadValue;
  1502. end;
  1503. procedure TReader.CopyValue(Writer: TWriter);
  1504. procedure CopyBytes(Count: Integer);
  1505. { var
  1506. Buffer: array[0..1023] of Byte; }
  1507. begin
  1508. {!!!: while Count > 1024 do
  1509. begin
  1510. FDriver.Read(Buffer, 1024);
  1511. Writer.Driver.Write(Buffer, 1024);
  1512. Dec(Count, 1024);
  1513. end;
  1514. if Count > 0 then
  1515. begin
  1516. FDriver.Read(Buffer, Count);
  1517. Writer.Driver.Write(Buffer, Count);
  1518. end;}
  1519. end;
  1520. {var
  1521. s: String;
  1522. Count: LongInt; }
  1523. begin
  1524. case FDriver.NextValue of
  1525. vaNull:
  1526. Writer.WriteIdent('NULL');
  1527. vaFalse:
  1528. Writer.WriteIdent('FALSE');
  1529. vaTrue:
  1530. Writer.WriteIdent('TRUE');
  1531. vaNil:
  1532. Writer.WriteIdent('NIL');
  1533. {!!!: vaList, vaCollection:
  1534. begin
  1535. Writer.WriteValue(FDriver.ReadValue);
  1536. while not EndOfList do
  1537. CopyValue(Writer);
  1538. ReadListEnd;
  1539. Writer.WriteListEnd;
  1540. end;}
  1541. vaInt8, vaInt16, vaInt32:
  1542. Writer.WriteInteger(ReadInteger);
  1543. {$ifndef FPUNONE}
  1544. vaExtended:
  1545. Writer.WriteFloat(ReadFloat);
  1546. {$endif}
  1547. {!!!: vaString:
  1548. Writer.WriteStr(ReadStr);}
  1549. vaIdent:
  1550. Writer.WriteIdent(ReadIdent);
  1551. {!!!: vaBinary, vaLString, vaWString:
  1552. begin
  1553. Writer.WriteValue(FDriver.ReadValue);
  1554. FDriver.Read(Count, SizeOf(Count));
  1555. Writer.Driver.Write(Count, SizeOf(Count));
  1556. CopyBytes(Count);
  1557. end;}
  1558. {!!!: vaSet:
  1559. Writer.WriteSet(ReadSet);}
  1560. {$ifndef FPUNONE}
  1561. vaSingle:
  1562. Writer.WriteSingle(ReadSingle);
  1563. {$endif}
  1564. {!!!: vaCurrency:
  1565. Writer.WriteCurrency(ReadCurrency);}
  1566. {$ifndef FPUNONE}
  1567. vaDate:
  1568. Writer.WriteDate(ReadDate);
  1569. {$endif}
  1570. vaInt64:
  1571. Writer.WriteInteger(ReadInt64);
  1572. end;
  1573. end;
  1574. function TReader.FindComponentClass(const AName, AClassName: String): TComponentClass;
  1575. var
  1576. PersistentClass: TPersistentClass;
  1577. ShortName, ShortClassName: shortstring;
  1578. function FindInFieldTable(Instance: TComponent): TComponentClass;
  1579. var
  1580. aClassType: TClass;
  1581. FieldTable: PFieldTable;
  1582. ClassTable: PFieldClassTable;
  1583. i: Integer;
  1584. FieldInfo: PFieldInfo;
  1585. PersistenClass: TPersistentClass;
  1586. begin
  1587. //writeln('FindInFieldTable Instance=',Instance.Name,':',Instance.UnitName,'>',Instance.ClassName,' ShortName="',ShortName,'" ShortClassName="',ShortClassName,'"');
  1588. Result:=nil;
  1589. // search field by name
  1590. aClassType := Instance.ClassType;
  1591. while aClassType <> TPersistent do
  1592. begin
  1593. FieldTable := PFieldTable(PVmt(aClassType)^.vFieldTable);
  1594. if Assigned(FieldTable) then
  1595. begin
  1596. ClassTable := FieldTable^.ClassTable;
  1597. FieldInfo := @FieldTable^.Fields[0];
  1598. for i := 0 to FieldTable^.FieldCount - 1 do
  1599. begin
  1600. //writeln('FindInFieldTable Instance=',Instance.ClassName,' FieldInfo ',i,'/',FieldTable^.FieldCount,' ',FieldInfo^.Name);
  1601. if ShortCompareText(FieldInfo^.Name,ShortName)=0 then
  1602. begin
  1603. PersistenClass := ClassTable^.Entries[FieldInfo^.ClassTypeIndex-1]^;
  1604. //writeln('FindInFieldTable Found Field "',FieldInfo^.Name,'" Class="',PersistenClass.UnitName,'>',PersistenClass.ClassName,'"');
  1605. if PersistenClass.ClassNameIs(ShortClassName)
  1606. and PersistenClass.InheritsFrom(TComponent) then
  1607. exit(TComponentClass(PersistenClass));
  1608. end;
  1609. FieldInfo := PFieldInfo(PByte(@FieldInfo^.Name) + 1 + Length(FieldInfo^.Name));
  1610. end;
  1611. end;
  1612. // Try again with the parent class type
  1613. aClassType := aClassType.ClassParent;
  1614. end;
  1615. // search class
  1616. aClassType := Instance.ClassType;
  1617. while aClassType <> TPersistent do
  1618. begin
  1619. FieldTable := PFieldTable(PVmt(aClassType)^.vFieldTable);
  1620. if Assigned(FieldTable) then
  1621. begin
  1622. ClassTable := FieldTable^.ClassTable;
  1623. for i := 0 to ClassTable^.Count - 1 do
  1624. begin
  1625. PersistenClass := ClassTable^.Entries[i]^;
  1626. if PersistenClass.ClassNameIs(ShortClassName)
  1627. and PersistenClass.InheritsFrom(TComponent) then
  1628. exit(TComponentClass(PersistenClass));
  1629. end;
  1630. end;
  1631. // Try again with the parent class type
  1632. aClassType := aClassType.ClassParent;
  1633. end;
  1634. Result:=nil;
  1635. end;
  1636. begin
  1637. ShortName:=AName;
  1638. ShortClassName:=AClassName;
  1639. Result:=FindInFieldTable(Root);
  1640. if (Result=nil) and assigned(LookupRoot) and (LookupRoot<>Root) then
  1641. FindInFieldTable(LookupRoot);
  1642. if (Result=nil) then begin
  1643. PersistentClass := GetClass(AClassName);
  1644. if PersistentClass.InheritsFrom(TComponent) then
  1645. Result := TComponentClass(PersistentClass);
  1646. end;
  1647. if (Result=nil) and assigned(OnFindComponentClass) then
  1648. OnFindComponentClass(Self, AClassName, Result);
  1649. if (Result=nil) or (not Result.InheritsFrom(TComponent)) then
  1650. raise EClassNotFound.CreateFmt(SNoFieldOfClassIn, [AClassName, Root.ClassName]);
  1651. end;
  1652. { TAbstractObjectReader }
  1653. procedure TAbstractObjectReader.FlushBuffer;
  1654. begin
  1655. // Do nothing
  1656. end;