12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772 |
- {
- This file is part of the Free Component Library (FCL)
- Copyright (c) 1999-2000 by the Free Pascal development team
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- {****************************************************************************}
- {* TBinaryObjectReader *}
- {****************************************************************************}
- {$ifndef FPUNONE}
- {$IFNDEF FPC_HAS_TYPE_EXTENDED}
- function ExtendedToDouble(e : pointer) : double;
- var mant : qword;
- exp : smallint;
- sign : boolean;
- d : qword;
- begin
- move(pbyte(e)[0],mant,8); //mantissa : bytes 0..7
- move(pbyte(e)[8],exp,2); //exponent and sign: bytes 8..9
- mant:=LEtoN(mant);
- exp:=LEtoN(word(exp));
- sign:=(exp and $8000)<>0;
- if sign then exp:=exp and $7FFF;
- case exp of
- 0 : mant:=0; //if denormalized, value is too small for double,
- //so it's always zero
- $7FFF : exp:=2047 //either infinity or NaN
- else
- begin
- dec(exp,16383-1023);
- if (exp>=-51) and (exp<=0) then //can be denormalized
- begin
- mant:=mant shr (-exp);
- exp:=0;
- end
- else
- if (exp<-51) or (exp>2046) then //exponent too large.
- begin
- Result:=0;
- exit;
- end
- else //normalized value
- mant:=mant shl 1; //hide most significant bit
- end;
- end;
- d:=word(exp);
- d:=d shl 52;
- mant:=mant shr 12;
- d:=d or mant;
- if sign then d:=d or $8000000000000000;
- Result:=pdouble(@d)^;
- end;
- {$ENDIF}
- {$endif}
- function TBinaryObjectReader.ReadWord : word; {$ifdef CLASSESINLINE}inline;{$endif CLASSESINLINE}
- begin
- Read(Result,2);
- Result:=LEtoN(Result);
- end;
- function TBinaryObjectReader.ReadDWord : longword; {$ifdef CLASSESINLINE}inline;{$endif CLASSESINLINE}
- begin
- Read(Result,4);
- Result:=LEtoN(Result);
- end;
- function TBinaryObjectReader.ReadQWord : qword; {$ifdef CLASSESINLINE}inline;{$endif CLASSESINLINE}
- begin
- Read(Result,8);
- Result:=LEtoN(Result);
- end;
- {$IFDEF FPC_DOUBLE_HILO_SWAPPED}
- procedure SwapDoubleHiLo(var avalue: double); {$ifdef CLASSESINLINE}inline{$endif CLASSESINLINE}
- var dwo1 : dword;
- type tdoublerec = array[0..1] of dword;
- begin
- dwo1:= tdoublerec(avalue)[0];
- tdoublerec(avalue)[0]:=tdoublerec(avalue)[1];
- tdoublerec(avalue)[1]:=dwo1;
- end;
- {$ENDIF FPC_DOUBLE_HILO_SWAPPED}
- {$ifndef FPUNONE}
- function TBinaryObjectReader.ReadExtended : extended; {$ifdef CLASSESINLINE}inline;{$endif CLASSESINLINE}
- {$IFNDEF FPC_HAS_TYPE_EXTENDED}
- var ext : array[0..9] of byte;
- {$ENDIF}
- begin
- {$IFNDEF FPC_HAS_TYPE_EXTENDED}
- Read(ext[0],10);
- Result:=ExtendedToDouble(@(ext[0]));
- {$IFDEF FPC_DOUBLE_HILO_SWAPPED}
- SwapDoubleHiLo(result);
- {$ENDIF}
- {$ELSE}
- Read(Result,sizeof(Result));
- {$ENDIF}
- end;
- {$endif}
- constructor TBinaryObjectReader.Create(Stream: TStream; BufSize: Integer);
- begin
- inherited Create;
- If (Stream=Nil) then
- Raise EReadError.Create(SEmptyStreamIllegalReader);
- FStream := Stream;
- FBufSize := BufSize;
- GetMem(FBuffer, BufSize);
- end;
- destructor TBinaryObjectReader.Destroy;
- begin
- { Seek back the amount of bytes that we didn't process until now: }
- FStream.Seek(Integer(FBufPos) - Integer(FBufEnd), soFromCurrent);
- if Assigned(FBuffer) then
- FreeMem(FBuffer, FBufSize);
- inherited Destroy;
- end;
- function TBinaryObjectReader.ReadValue: TValueType;
- var
- b: byte;
- begin
- Read(b, 1);
- Result := TValueType(b);
- end;
- function TBinaryObjectReader.NextValue: TValueType;
- begin
- Result := ReadValue;
- { We only 'peek' at the next value, so seek back to unget the read value: }
- Dec(FBufPos);
- end;
- procedure TBinaryObjectReader.BeginRootComponent;
- begin
- { Read filer signature }
- ReadSignature;
- end;
- procedure TBinaryObjectReader.BeginComponent(var Flags: TFilerFlags;
- var AChildPos: Integer; var CompClassName, CompName: String);
- var
- Prefix: Byte;
- ValueType: TValueType;
- begin
- { Every component can start with a special prefix: }
- Flags := [];
- if (Byte(NextValue) and $f0) = $f0 then
- begin
- Prefix := Byte(ReadValue);
- Flags := TFilerFlags(TFilerFlagsInt(Prefix and $0f));
- if ffChildPos in Flags then
- begin
- ValueType := ReadValue;
- case ValueType of
- vaInt8:
- AChildPos := ReadInt8;
- vaInt16:
- AChildPos := ReadInt16;
- vaInt32:
- AChildPos := ReadInt32;
- else
- raise EReadError.Create(SInvalidPropertyValue);
- end;
- end;
- end;
- CompClassName := ReadStr;
- CompName := ReadStr;
- end;
- function TBinaryObjectReader.BeginProperty: String;
- begin
- Result := ReadStr;
- end;
- procedure TBinaryObjectReader.ReadBinary(const DestData: TMemoryStream);
- var
- BinSize: LongInt;
- begin
- BinSize:=LongInt(ReadDWord);
- DestData.Size := BinSize;
- Read(DestData.Memory^, BinSize);
- end;
- {$ifndef FPUNONE}
- function TBinaryObjectReader.ReadFloat: Extended;
- begin
- Result:=ReadExtended;
- end;
- function TBinaryObjectReader.ReadSingle: Single;
- var
- r: record
- case byte of
- 1: (d: dword);
- 2: (s: single);
- end;
- begin
- r.d:=ReadDWord;
- Result:=r.s;
- end;
- {$endif}
- function TBinaryObjectReader.ReadCurrency: Currency;
- var
- r: record
- case byte of
- 1: (q: qword);
- 2: (c: currency);
- end;
- begin
- r.c:=ReadQWord;
- Result:=r.c;
- end;
- {$ifndef FPUNONE}
- function TBinaryObjectReader.ReadDate: TDateTime;
- var
- r: record
- case byte of
- 1: (q: qword);
- 2: (d: TDateTime);
- end;
- begin
- r.q:=ReadQWord;
- Result:=r.d;
- end;
- {$endif}
- function TBinaryObjectReader.ReadIdent(ValueType: TValueType): String;
- var
- i: Byte;
- begin
- case ValueType of
- vaIdent:
- begin
- Read(i, 1);
- SetLength(Result, i);
- Read(Pointer(@Result[1])^, i);
- end;
- vaNil:
- Result := 'nil';
- vaFalse:
- Result := 'False';
- vaTrue:
- Result := 'True';
- vaNull:
- Result := 'Null';
- end;
- end;
- function TBinaryObjectReader.ReadInt8: ShortInt;
- begin
- Read(Result, 1);
- end;
- function TBinaryObjectReader.ReadInt16: SmallInt;
- begin
- Result:=SmallInt(ReadWord);
- end;
- function TBinaryObjectReader.ReadInt32: LongInt;
- begin
- Result:=LongInt(ReadDWord);
- end;
- function TBinaryObjectReader.ReadInt64: Int64;
- begin
- Result:=Int64(ReadQWord);
- end;
- function TBinaryObjectReader.ReadSet(EnumType: Pointer): Integer;
- type
- {$packset 1}
- tset = set of 0..(SizeOf(Integer)*8-1);
- {$packset default}
- var
- Name: String;
- Value: Integer;
- begin
- try
- Result := 0;
- while True do
- begin
- Name := ReadStr;
- if Length(Name) = 0 then
- break;
- Value := GetEnumValue(PTypeInfo(EnumType), Name);
- if Value = -1 then
- raise EReadError.Create(SInvalidPropertyValue);
- include(tset(result),Value);
- end;
- except
- SkipSetBody;
- raise;
- end;
- end;
- procedure TBinaryObjectReader.ReadSignature;
- var
- Signature: LongInt;
- begin
- Read(Signature, 4);
- if Signature <> LongInt(unaligned(FilerSignature)) then
- raise EReadError.Create(SInvalidImage);
- end;
- function TBinaryObjectReader.ReadStr: String;
- var
- i: Byte;
- begin
- Read(i, 1);
- SetLength(Result, i);
- if i > 0 then
- Read(Pointer(@Result[1])^, i);
- end;
- function TBinaryObjectReader.ReadString(StringType: TValueType): String;
- var
- b: Byte;
- i: Integer;
- begin
- case StringType of
- vaLString, vaUTF8String:
- i:=ReadDWord;
- else
- //vaString:
- begin
- Read(b, 1);
- i := b;
- end;
- end;
- SetLength(Result, i);
- if i > 0 then
- Read(Pointer(@Result[1])^, i);
- end;
- function TBinaryObjectReader.ReadWideString: WideString;
- var
- len: DWord;
- {$IFDEF ENDIAN_BIG}
- i : integer;
- {$ENDIF}
- begin
- len := ReadDWord;
- SetLength(Result, len);
- if (len > 0) then
- begin
- Read(Pointer(@Result[1])^, len*2);
- {$IFDEF ENDIAN_BIG}
- for i:=1 to len do
- Result[i]:=widechar(SwapEndian(word(Result[i])));
- {$ENDIF}
- end;
- end;
- function TBinaryObjectReader.ReadUnicodeString: UnicodeString;
- var
- len: DWord;
- {$IFDEF ENDIAN_BIG}
- i : integer;
- {$ENDIF}
- begin
- len := ReadDWord;
- SetLength(Result, len);
- if (len > 0) then
- begin
- Read(Pointer(@Result[1])^, len*2);
- {$IFDEF ENDIAN_BIG}
- for i:=1 to len do
- Result[i]:=UnicodeChar(SwapEndian(word(Result[i])));
- {$ENDIF}
- end;
- end;
- procedure TBinaryObjectReader.SkipComponent(SkipComponentInfos: Boolean);
- var
- Flags: TFilerFlags;
- Dummy: Integer;
- CompClassName, CompName: String;
- begin
- if SkipComponentInfos then
- { Skip prefix, component class name and component object name }
- BeginComponent(Flags, Dummy, CompClassName, CompName);
- { Skip properties }
- while NextValue <> vaNull do
- SkipProperty;
- ReadValue;
- { Skip children }
- while NextValue <> vaNull do
- SkipComponent(True);
- ReadValue;
- end;
- procedure TBinaryObjectReader.SkipValue;
- procedure SkipBytes(Count: LongInt);
- var
- Dummy: array[0..1023] of Byte;
- SkipNow: Integer;
- begin
- while Count > 0 do
- begin
- if Count > 1024 then
- SkipNow := 1024
- else
- SkipNow := Count;
- Read(Dummy, SkipNow);
- Dec(Count, SkipNow);
- end;
- end;
- var
- Count: LongInt;
- begin
- case ReadValue of
- vaNull, vaFalse, vaTrue, vaNil: ;
- vaList:
- begin
- while NextValue <> vaNull do
- SkipValue;
- ReadValue;
- end;
- vaInt8:
- SkipBytes(1);
- vaInt16:
- SkipBytes(2);
- vaInt32:
- SkipBytes(4);
- vaExtended:
- SkipBytes(10);
- vaString, vaIdent:
- ReadStr;
- vaBinary, vaLString:
- begin
- Count:=LongInt(ReadDWord);
- SkipBytes(Count);
- end;
- vaWString:
- begin
- Count:=LongInt(ReadDWord);
- SkipBytes(Count*sizeof(widechar));
- end;
- vaUString:
- begin
- Count:=LongInt(ReadDWord);
- SkipBytes(Count*sizeof(widechar));
- end;
- vaSet:
- SkipSetBody;
- vaCollection:
- begin
- while NextValue <> vaNull do
- begin
- { Skip the order value if present }
- if NextValue in [vaInt8, vaInt16, vaInt32] then
- SkipValue;
- SkipBytes(1);
- while NextValue <> vaNull do
- SkipProperty;
- ReadValue;
- end;
- ReadValue;
- end;
- vaSingle:
- {$ifndef FPUNONE}
- SkipBytes(Sizeof(Single));
- {$else}
- SkipBytes(4);
- {$endif}
- {!!!: vaCurrency:
- SkipBytes(SizeOf(Currency));}
- vaDate, vaInt64:
- SkipBytes(8);
- end;
- end;
- { private methods }
- procedure TBinaryObjectReader.Read(var Buf; Count: LongInt);
- var
- CopyNow: LongInt;
- Dest: Pointer;
- begin
- Dest := @Buf;
- while Count > 0 do
- begin
- if FBufPos >= FBufEnd then
- begin
- FBufEnd := FStream.Read(FBuffer^, FBufSize);
- if FBufEnd = 0 then
- raise EReadError.Create(SReadError);
- FBufPos := 0;
- end;
- CopyNow := FBufEnd - FBufPos;
- if CopyNow > Count then
- CopyNow := Count;
- Move(PChar(FBuffer)[FBufPos], Dest^, CopyNow);
- Inc(FBufPos, CopyNow);
- Inc(Dest, CopyNow);
- Dec(Count, CopyNow);
- end;
- end;
- procedure TBinaryObjectReader.SkipProperty;
- begin
- { Skip property name, then the property value }
- ReadStr;
- SkipValue;
- end;
- procedure TBinaryObjectReader.SkipSetBody;
- begin
- while Length(ReadStr) > 0 do;
- end;
- {****************************************************************************}
- {* TREADER *}
- {****************************************************************************}
- type
- TFieldInfo = packed record
- FieldOffset: LongWord;
- ClassTypeIndex: Word;
- Name: ShortString;
- end;
- {$ifdef VER3_0}
- PersistentClassRef = TPersistentClass;
- {$else VER3_0}
- PPersistentClass = ^TPersistentClass;
- PersistentClassRef = PPersistentClass;
- {$endif VER3_0}
- PFieldClassTable = ^TFieldClassTable;
- TFieldClassTable =
- {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
- packed
- {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
- record
- Count: Word;
- Entries: array[{$ifdef cpu16}0..16384 div sizeof(PersistentClassRef){$else}Word{$endif}] of PersistentClassRef;
- end;
- PFieldTable = ^TFieldTable;
- TFieldTable =
- {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
- packed
- {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
- record
- FieldCount: Word;
- ClassTable: PFieldClassTable;
- // Fields: array[Word] of TFieldInfo; Elements have variant size!
- end;
- function GetFieldClass(Instance: TObject; const ClassName: string): TPersistentClass;
- var
- ShortClassName: shortstring;
- ClassType: TClass;
- ClassTable: PFieldClassTable;
- i: Integer;
- FieldTable: PFieldTable;
- begin
- // At first, try to locate the class in the class tables
- ShortClassName := ClassName;
- ClassType := Instance.ClassType;
- while ClassType <> TPersistent do
- begin
- FieldTable := PFieldTable(PVmt(ClassType)^.vFieldTable);
- if Assigned(FieldTable) then
- begin
- ClassTable := FieldTable^.ClassTable;
- for i := 0 to ClassTable^.Count - 1 do
- begin
- Result := ClassTable^.Entries[i]{$ifndef VER3_0}^{$endif};
- if Result.ClassNameIs(ShortClassName) then
- exit;
- end;
- end;
- // Try again with the parent class type
- ClassType := ClassType.ClassParent;
- end;
- Result := Classes.GetClass(ClassName);
- end;
- constructor TReader.Create(Stream: TStream; BufSize: Integer);
- begin
- inherited Create;
- If (Stream=Nil) then
- Raise EReadError.Create(SEmptyStreamIllegalReader);
- FDriver := CreateDriver(Stream, BufSize);
- end;
- destructor TReader.Destroy;
- begin
- FDriver.Free;
- inherited Destroy;
- end;
- procedure TReader.FlushBuffer;
- begin
- Driver.FlushBuffer;
- end;
- function TReader.CreateDriver(Stream: TStream; BufSize: Integer): TAbstractObjectReader;
- begin
- Result := TBinaryObjectReader.Create(Stream, BufSize);
- end;
- procedure TReader.BeginReferences;
- begin
- FLoaded := TFpList.Create;
- end;
- procedure TReader.CheckValue(Value: TValueType);
- begin
- if FDriver.NextValue <> Value then
- raise EReadError.Create(SInvalidPropertyValue)
- else
- FDriver.ReadValue;
- end;
- procedure TReader.DefineProperty(const Name: String; AReadData: TReaderProc;
- WriteData: TWriterProc; HasData: Boolean);
- begin
- if Assigned(AReadData) and (UpperCase(Name) = UpperCase(FPropName)) then
- begin
- AReadData(Self);
- SetLength(FPropName, 0);
- end;
- end;
- procedure TReader.DefineBinaryProperty(const Name: String;
- AReadData, WriteData: TStreamProc; HasData: Boolean);
- var
- MemBuffer: TMemoryStream;
- begin
- if Assigned(AReadData) and (UpperCase(Name) = UpperCase(FPropName)) then
- begin
- { Check if the next property really is a binary property}
- if FDriver.NextValue <> vaBinary then
- begin
- FDriver.SkipValue;
- FCanHandleExcepts := True;
- raise EReadError.Create(SInvalidPropertyValue);
- end else
- FDriver.ReadValue;
- MemBuffer := TMemoryStream.Create;
- try
- FDriver.ReadBinary(MemBuffer);
- FCanHandleExcepts := True;
- AReadData(MemBuffer);
- finally
- MemBuffer.Free;
- end;
- SetLength(FPropName, 0);
- end;
- end;
- function TReader.EndOfList: Boolean;
- begin
- Result := FDriver.NextValue = vaNull;
- end;
- procedure TReader.EndReferences;
- begin
- FLoaded.Free;
- FLoaded := nil;
- end;
- function TReader.Error(const Message: String): Boolean;
- begin
- Result := False;
- if Assigned(FOnError) then
- FOnError(Self, Message, Result);
- end;
- function TReader.FindMethod(ARoot: TComponent; const AMethodName: String): CodePointer;
- var
- ErrorResult: Boolean;
- begin
- Result := ARoot.MethodAddress(AMethodName);
- ErrorResult := Result = nil;
- { always give the OnFindMethod callback a chance to locate the method }
- if Assigned(FOnFindMethod) then
- FOnFindMethod(Self, AMethodName, Result, ErrorResult);
- if ErrorResult then
- raise EReadError.Create(SInvalidPropertyValue);
- end;
- procedure TReader.DoFixupReferences;
- Var
- R,RN : TLocalUnresolvedReference;
- G : TUnresolvedInstance;
- Ref : String;
- C : TComponent;
- P : integer;
- L : TLinkedList;
- RI: Pointer; // raw interface
- IIDStr: ShortString;
-
- begin
- If Assigned(FFixups) then
- begin
- L:=TLinkedList(FFixups);
- R:=TLocalUnresolvedReference(L.Root);
- While (R<>Nil) do
- begin
- RN:=TLocalUnresolvedReference(R.Next);
- Ref:=R.FRelative;
- If Assigned(FOnReferenceName) then
- FOnReferenceName(Self,Ref);
- C:=FindNestedComponent(R.FRoot,Ref);
- If Assigned(C) then
- if R.FPropInfo^.PropType^.Kind = tkInterface then
- SetInterfaceProp(R.FInstance,R.FPropInfo,C)
- else if R.FPropInfo^.PropType^.Kind = tkInterfaceRaw then
- begin
- IIDStr := GetTypeData(R.FPropInfo^.PropType)^.IIDStr;
- if IIDStr = '' then
- raise EReadError.CreateFmt(SInterfaceNoIIDStr, [R.FPropInfo^.PropType^.Name]);
- if C.GetInterface(IIDStr, RI) then
- SetRawInterfaceProp(R.FInstance,R.FPropInfo,RI)
- else
- raise EReadError.CreateFmt(SComponentDoesntImplement, [C.ClassName, IIDStr]);
- end
- else
- SetObjectProp(R.FInstance,R.FPropInfo,C)
- else
- begin
- P:=Pos('.',R.FRelative);
- If (P<>0) then
- begin
- G:=AddToResolveList(R.FInstance);
- G.Addreference(R.FRoot,R.FPropInfo,Copy(R.FRelative,1,P-1),Copy(R.FRelative,P+1,Length(R.FRelative)-P));
- end;
- end;
- L.RemoveItem(R,True);
- R:=RN;
- end;
- FreeAndNil(FFixups);
- end;
- end;
- procedure TReader.FixupReferences;
- var
- i: Integer;
- begin
- DoFixupReferences;
- GlobalFixupReferences;
- for i := 0 to FLoaded.Count - 1 do
- TComponent(FLoaded[I]).Loaded;
- end;
- function TReader.NextValue: TValueType;
- begin
- Result := FDriver.NextValue;
- end;
- procedure TReader.Read(var Buf; Count: LongInt);
- begin
- //This should give an exception if read is not implemented (i.e. TTextObjectReader)
- //but should work with TBinaryObjectReader.
- Driver.Read(Buf, Count);
- end;
- procedure TReader.PropertyError;
- begin
- FDriver.SkipValue;
- raise EReadError.CreateFmt(SUnknownProperty,[FPropName]);
- end;
- function TReader.ReadBoolean: Boolean;
- var
- ValueType: TValueType;
- begin
- ValueType := FDriver.ReadValue;
- if ValueType = vaTrue then
- Result := True
- else if ValueType = vaFalse then
- Result := False
- else
- raise EReadError.Create(SInvalidPropertyValue);
- end;
- function TReader.ReadChar: Char;
- var
- s: String;
- begin
- s := ReadString;
- if Length(s) = 1 then
- Result := s[1]
- else
- raise EReadError.Create(SInvalidPropertyValue);
- end;
- function TReader.ReadWideChar: WideChar;
- var
- W: WideString;
-
- begin
- W := ReadWideString;
- if Length(W) = 1 then
- Result := W[1]
- else
- raise EReadError.Create(SInvalidPropertyValue);
- end;
-
- function TReader.ReadUnicodeChar: UnicodeChar;
- var
- U: UnicodeString;
-
- begin
- U := ReadUnicodeString;
- if Length(U) = 1 then
- Result := U[1]
- else
- raise EReadError.Create(SInvalidPropertyValue);
- end;
-
- procedure TReader.ReadCollection(Collection: TCollection);
- var
- Item: TCollectionItem;
- begin
- Collection.BeginUpdate;
- if not EndOfList then
- Collection.Clear;
- while not EndOfList do begin
- ReadListBegin;
- Item := Collection.Add;
- while NextValue<>vaNull do
- ReadProperty(Item);
- ReadListEnd;
- end;
- Collection.EndUpdate;
- ReadListEnd;
- end;
- function TReader.ReadComponent(Component: TComponent): TComponent;
- var
- Flags: TFilerFlags;
- function Recover(var aComponent: TComponent): Boolean;
- begin
- Result := False;
- if ExceptObject.InheritsFrom(Exception) then
- begin
- if not ((ffInherited in Flags) or Assigned(Component)) then
- aComponent.Free;
- aComponent := nil;
- FDriver.SkipComponent(False);
- Result := Error(Exception(ExceptObject).Message);
- end;
- end;
- var
- CompClassName, Name: String;
- n, ChildPos: Integer;
- SavedParent, SavedLookupRoot: TComponent;
- ComponentClass: TComponentClass;
- C, NewComponent: TComponent;
- SubComponents: TList;
- begin
- FDriver.BeginComponent(Flags, ChildPos, CompClassName, Name);
- SavedParent := Parent;
- SavedLookupRoot := FLookupRoot;
- SubComponents := nil;
- try
- Result := Component;
- if not Assigned(Result) then
- try
- if ffInherited in Flags then
- begin
- { Try to locate the existing ancestor component }
- if Assigned(FLookupRoot) then
- Result := FLookupRoot.FindComponent(Name)
- else
- Result := nil;
- if not Assigned(Result) then
- begin
- if Assigned(FOnAncestorNotFound) then
- FOnAncestorNotFound(Self, Name,
- FindComponentClass(CompClassName), Result);
- if not Assigned(Result) then
- raise EReadError.CreateFmt(SAncestorNotFound, [Name]);
- end;
- Parent := Result.GetParentComponent;
- if not Assigned(Parent) then
- Parent := Root;
- end else
- begin
- Result := nil;
- ComponentClass := FindComponentClass(CompClassName);
- if Assigned(FOnCreateComponent) then
- FOnCreateComponent(Self, ComponentClass, Result);
- if not Assigned(Result) then
- begin
- NewComponent := TComponent(ComponentClass.NewInstance);
- if ffInline in Flags then
- NewComponent.FComponentState :=
- NewComponent.FComponentState + [csLoading, csInline];
- NewComponent.Create(Owner);
- { Don't set Result earlier because else we would come in trouble
- with the exception recover mechanism! (Result should be NIL if
- an error occurred) }
- Result := NewComponent;
- end;
- Include(Result.FComponentState, csLoading);
- end;
- except
- if not Recover(Result) then
- raise;
- end;
- if Assigned(Result) then
- try
- Include(Result.FComponentState, csLoading);
- { create list of subcomponents and set loading}
- SubComponents := TList.Create;
- for n := 0 to Result.ComponentCount - 1 do
- begin
- C := Result.Components[n];
- if csSubcomponent in C.ComponentStyle
- then begin
- SubComponents.Add(C);
- Include(C.FComponentState, csLoading);
- end;
- end;
- if not (ffInherited in Flags) then
- try
- Result.SetParentComponent(Parent);
- if Assigned(FOnSetName) then
- FOnSetName(Self, Result, Name);
- Result.Name := Name;
- if FindGlobalComponent(Name) = Result then
- Include(Result.FComponentState, csInline);
- except
- if not Recover(Result) then
- raise;
- end;
- if not Assigned(Result) then
- exit;
- if csInline in Result.ComponentState then
- FLookupRoot := Result;
- { Read the component state }
- Include(Result.FComponentState, csReading);
- for n := 0 to Subcomponents.Count - 1 do
- Include(TComponent(Subcomponents[n]).FComponentState, csReading);
- Result.ReadState(Self);
- Exclude(Result.FComponentState, csReading);
- for n := 0 to Subcomponents.Count - 1 do
- Exclude(TComponent(Subcomponents[n]).FComponentState, csReading);
- if ffChildPos in Flags then
- Parent.SetChildOrder(Result, ChildPos);
- { Add component to list of loaded components, if necessary }
- if (not ((ffInherited in Flags) or (csInline in Result.ComponentState))) or
- (FLoaded.IndexOf(Result) < 0)
- then begin
- for n := 0 to Subcomponents.Count - 1 do
- FLoaded.Add(Subcomponents[n]);
- FLoaded.Add(Result);
- end;
- except
- if ((ffInherited in Flags) or Assigned(Component)) then
- Result.Free;
- raise;
- end;
- finally
- Parent := SavedParent;
- FLookupRoot := SavedLookupRoot;
- Subcomponents.Free;
- end;
- end;
- procedure TReader.ReadData(Instance: TComponent);
- var
- SavedOwner, SavedParent: TComponent;
-
- begin
- { Read properties }
- while not EndOfList do
- ReadProperty(Instance);
- ReadListEnd;
- { Read children }
- SavedOwner := Owner;
- SavedParent := Parent;
- try
- Owner := Instance.GetChildOwner;
- if not Assigned(Owner) then
- Owner := Root;
- Parent := Instance.GetChildParent;
- while not EndOfList do
- ReadComponent(nil);
- ReadListEnd;
- finally
- Owner := SavedOwner;
- Parent := SavedParent;
- end;
- { Fixup references if necessary (normally only if this is the root) }
- If (Instance=FRoot) then
- DoFixupReferences;
- end;
- {$ifndef FPUNONE}
- function TReader.ReadFloat: Extended;
- begin
- if FDriver.NextValue = vaExtended then
- begin
- ReadValue;
- Result := FDriver.ReadFloat
- end else
- Result := ReadInt64;
- end;
- procedure TReader.ReadSignature;
- begin
- FDriver.ReadSignature;
- end;
- function TReader.ReadSingle: Single;
- begin
- if FDriver.NextValue = vaSingle then
- begin
- FDriver.ReadValue;
- Result := FDriver.ReadSingle;
- end else
- Result := ReadInteger;
- end;
- {$endif}
- function TReader.ReadCurrency: Currency;
- begin
- if FDriver.NextValue = vaCurrency then
- begin
- FDriver.ReadValue;
- Result := FDriver.ReadCurrency;
- end else
- Result := ReadInteger;
- end;
- {$ifndef FPUNONE}
- function TReader.ReadDate: TDateTime;
- begin
- if FDriver.NextValue = vaDate then
- begin
- FDriver.ReadValue;
- Result := FDriver.ReadDate;
- end else
- Result := ReadInteger;
- end;
- {$endif}
- function TReader.ReadIdent: String;
- var
- ValueType: TValueType;
- begin
- ValueType := FDriver.ReadValue;
- if ValueType in [vaIdent, vaNil, vaFalse, vaTrue, vaNull] then
- Result := FDriver.ReadIdent(ValueType)
- else
- raise EReadError.Create(SInvalidPropertyValue);
- end;
- function TReader.ReadInteger: LongInt;
- begin
- case FDriver.ReadValue of
- vaInt8:
- Result := FDriver.ReadInt8;
- vaInt16:
- Result := FDriver.ReadInt16;
- vaInt32:
- Result := FDriver.ReadInt32;
- else
- raise EReadError.Create(SInvalidPropertyValue);
- end;
- end;
- function TReader.ReadInt64: Int64;
- begin
- if FDriver.NextValue = vaInt64 then
- begin
- FDriver.ReadValue;
- Result := FDriver.ReadInt64;
- end else
- Result := ReadInteger;
- end;
- function TReader.ReadSet(EnumType: Pointer): Integer;
- begin
- if FDriver.NextValue = vaSet then
- begin
- FDriver.ReadValue;
- Result := FDriver.ReadSet(enumtype);
- end
- else
- Result := ReadInteger;
- end;
- procedure TReader.ReadListBegin;
- begin
- CheckValue(vaList);
- end;
- procedure TReader.ReadListEnd;
- begin
- CheckValue(vaNull);
- end;
- function TReader.ReadVariant: variant;
- var
- nv: TValueType;
- begin
- { Ensure that a Variant manager is installed }
- if not Assigned(VarClearProc) then
- raise EReadError.Create(SErrNoVariantSupport);
- FillChar(Result,sizeof(Result),0);
- nv:=NextValue;
- case nv of
- vaNil:
- begin
- Result:=system.unassigned;
- readvalue;
- end;
- vaNull:
- begin
- Result:=system.null;
- readvalue;
- end;
- { all integer sizes must be split for big endian systems }
- vaInt8,vaInt16,vaInt32:
- begin
- Result:=ReadInteger;
- end;
- vaInt64:
- begin
- Result:=ReadInt64;
- end;
- vaQWord:
- begin
- Result:=QWord(ReadInt64);
- end;
- vaFalse,vaTrue:
- begin
- Result:=(nv<>vaFalse);
- readValue;
- end;
- vaCurrency:
- begin
- Result:=ReadCurrency;
- end;
- {$ifndef fpunone}
- vaSingle:
- begin
- Result:=ReadSingle;
- end;
- vaExtended:
- begin
- Result:=ReadFloat;
- end;
- vaDate:
- begin
- Result:=ReadDate;
- end;
- {$endif fpunone}
- vaWString,vaUTF8String:
- begin
- Result:=ReadWideString;
- end;
- vaString:
- begin
- Result:=ReadString;
- end;
- vaUString:
- begin
- Result:=ReadUnicodeString;
- end;
- else
- raise EReadError.CreateFmt(SUnsupportedPropertyVariantType, [Ord(nv)]);
- end;
- end;
- procedure TReader.ReadProperty(AInstance: TPersistent);
- var
- Path: String;
- Instance: TPersistent;
- DotPos, NextPos: PChar;
- PropInfo: PPropInfo;
- Obj: TObject;
- Name: String;
- Skip: Boolean;
- Handled: Boolean;
- OldPropName: String;
- function HandleMissingProperty(IsPath: Boolean): boolean;
- begin
- Result:=true;
- if Assigned(OnPropertyNotFound) then begin
- // user defined property error handling
- OldPropName:=FPropName;
- Handled:=false;
- Skip:=false;
- OnPropertyNotFound(Self,Instance,FPropName,IsPath,Handled,Skip);
- if Handled and (not Skip) and (OldPropName<>FPropName) then
- // try alias property
- PropInfo := GetPropInfo(Instance.ClassInfo, FPropName);
- if Skip then begin
- FDriver.SkipValue;
- Result:=false;
- exit;
- end;
- end;
- end;
- begin
- try
- Path := FDriver.BeginProperty;
- try
- Instance := AInstance;
- FCanHandleExcepts := True;
- DotPos := PChar(Path);
- while True do
- begin
- NextPos := StrScan(DotPos, '.');
- if Assigned(NextPos) then
- FPropName := Copy(String(DotPos), 1, Integer(NextPos - DotPos))
- else
- begin
- FPropName := DotPos;
- break;
- end;
- DotPos := NextPos + 1;
- PropInfo := GetPropInfo(Instance.ClassInfo, FPropName);
- if not Assigned(PropInfo) then begin
- if not HandleMissingProperty(true) then exit;
- if not Assigned(PropInfo) then
- PropertyError;
- end;
- if PropInfo^.PropType^.Kind = tkClass then
- Obj := TObject(GetObjectProp(Instance, PropInfo))
- //else if PropInfo^.PropType^.Kind = tkInterface then
- // Obj := TObject(GetInterfaceProp(Instance, PropInfo))
- else
- Obj := nil;
- if not (Obj is TPersistent) then
- begin
- { All path elements must be persistent objects! }
- FDriver.SkipValue;
- raise EReadError.Create(SInvalidPropertyPath);
- end;
- Instance := TPersistent(Obj);
- end;
- PropInfo := GetPropInfo(Instance.ClassInfo, FPropName);
- if Assigned(PropInfo) then
- ReadPropValue(Instance, PropInfo)
- else
- begin
- FCanHandleExcepts := False;
- Instance.DefineProperties(Self);
- FCanHandleExcepts := True;
- if Length(FPropName) > 0 then begin
- if not HandleMissingProperty(false) then exit;
- if not Assigned(PropInfo) then
- PropertyError;
- end;
- end;
- except
- on e: Exception do
- begin
- SetLength(Name, 0);
- if AInstance.InheritsFrom(TComponent) then
- Name := TComponent(AInstance).Name;
- if Length(Name) = 0 then
- Name := AInstance.ClassName;
- raise EReadError.CreateFmt(SPropertyException,
- [Name, DotSep, Path, e.Message]);
- end;
- end;
- except
- on e: Exception do
- if not FCanHandleExcepts or not Error(E.Message) then
- raise;
- end;
- end;
- procedure TReader.ReadPropValue(Instance: TPersistent; PropInfo: Pointer);
- const
- NullMethod: TMethod = (Code: nil; Data: nil);
- var
- PropType: PTypeInfo;
- Value: LongInt;
- { IdentToIntFn: TIdentToInt; }
- Ident: String;
- Method: TMethod;
- Handled: Boolean;
- TmpStr: String;
- begin
- if not Assigned(PPropInfo(PropInfo)^.SetProc) then
- raise EReadError.Create(SReadOnlyProperty);
- PropType := PPropInfo(PropInfo)^.PropType;
- case PropType^.Kind of
- tkInteger:
- if FDriver.NextValue = vaIdent then
- begin
- Ident := ReadIdent;
- if GlobalIdentToInt(Ident,Value) then
- SetOrdProp(Instance, PropInfo, Value)
- else
- raise EReadError.Create(SInvalidPropertyValue);
- end else
- SetOrdProp(Instance, PropInfo, ReadInteger);
- tkBool:
- SetOrdProp(Instance, PropInfo, Ord(ReadBoolean));
- tkChar:
- SetOrdProp(Instance, PropInfo, Ord(ReadChar));
- tkWChar,tkUChar:
- SetOrdProp(Instance, PropInfo, Ord(ReadWideChar));
- tkEnumeration:
- begin
- Value := GetEnumValue(PropType, ReadIdent);
- if Value = -1 then
- raise EReadError.Create(SInvalidPropertyValue);
- SetOrdProp(Instance, PropInfo, Value);
- end;
- {$ifndef FPUNONE}
- tkFloat:
- SetFloatProp(Instance, PropInfo, ReadFloat);
- {$endif}
- tkSet:
- begin
- CheckValue(vaSet);
- SetOrdProp(Instance, PropInfo,
- FDriver.ReadSet(GetTypeData(PropType)^.CompType));
- end;
- tkMethod:
- if FDriver.NextValue = vaNil then
- begin
- FDriver.ReadValue;
- SetMethodProp(Instance, PropInfo, NullMethod);
- end else
- begin
- Handled:=false;
- Ident:=ReadIdent;
- if Assigned(OnSetMethodProperty) then
- OnSetMethodProperty(Self,Instance,PPropInfo(PropInfo),Ident,
- Handled);
- if not Handled then begin
- Method.Code := FindMethod(Root, Ident);
- Method.Data := Root;
- if Assigned(Method.Code) then
- SetMethodProp(Instance, PropInfo, Method);
- end;
- end;
- tkSString, tkLString, tkAString:
- begin
- TmpStr:=ReadString;
- if Assigned(FOnReadStringProperty) then
- FOnReadStringProperty(Self,Instance,PropInfo,TmpStr);
- SetStrProp(Instance, PropInfo, TmpStr);
- end;
- tkUstring:
- SetUnicodeStrProp(Instance,PropInfo,ReadUnicodeString);
- tkWString:
- SetWideStrProp(Instance,PropInfo,ReadWideString);
- tkVariant:
- begin
- SetVariantProp(Instance,PropInfo,ReadVariant);
- end;
- tkClass, tkInterface, tkInterfaceRaw:
- case FDriver.NextValue of
- vaNil:
- begin
- FDriver.ReadValue;
- SetOrdProp(Instance, PropInfo, 0)
- end;
- vaCollection:
- begin
- FDriver.ReadValue;
- ReadCollection(TCollection(GetObjectProp(Instance, PropInfo)));
- end
- else
- begin
- If Not Assigned(FFixups) then
- FFixups:=TLinkedList.Create(TLocalUnresolvedReference);
- With TLocalUnresolvedReference(TLinkedList(FFixups).Add) do
- begin
- FInstance:=Instance;
- FRoot:=Root;
- FPropInfo:=PropInfo;
- FRelative:=ReadIdent;
- end;
- end;
- end;
- tkInt64, tkQWord: SetInt64Prop(Instance, PropInfo, ReadInt64);
- else
- raise EReadError.CreateFmt(SUnknownPropertyType, [Ord(PropType^.Kind)]);
- end;
- end;
- function TReader.ReadRootComponent(ARoot: TComponent): TComponent;
- var
- Dummy, i: Integer;
- Flags: TFilerFlags;
- CompClassName, CompName, ResultName: String;
- begin
- FDriver.BeginRootComponent;
- Result := nil;
- {!!!: GlobalNameSpace.BeginWrite; // Loading from stream adds to name space
- try}
- try
- FDriver.BeginComponent(Flags, Dummy, CompClassName, CompName);
- if not Assigned(ARoot) then
- begin
- { Read the class name and the object name and create a new object: }
- Result := TComponentClass(FindClass(CompClassName)).Create(nil);
- Result.Name := CompName;
- end else
- begin
- Result := ARoot;
- if not (csDesigning in Result.ComponentState) then
- begin
- Result.FComponentState :=
- Result.FComponentState + [csLoading, csReading];
- { We need an unique name }
- i := 0;
- { Don't use Result.Name directly, as this would influence
- FindGlobalComponent in successive loop runs }
- ResultName := CompName;
- while Assigned(FindGlobalComponent(ResultName)) do
- begin
- Inc(i);
- ResultName := CompName + '_' + IntToStr(i);
- end;
- Result.Name := ResultName;
- end;
- end;
- FRoot := Result;
- FLookupRoot := Result;
- if Assigned(GlobalLoaded) then
- FLoaded := GlobalLoaded
- else
- FLoaded := TFpList.Create;
- try
- if FLoaded.IndexOf(FRoot) < 0 then
- FLoaded.Add(FRoot);
- FOwner := FRoot;
- FRoot.FComponentState := FRoot.FComponentState + [csLoading, csReading];
- FRoot.ReadState(Self);
- Exclude(FRoot.FComponentState, csReading);
- if not Assigned(GlobalLoaded) then
- for i := 0 to FLoaded.Count - 1 do
- TComponent(FLoaded[i]).Loaded;
- finally
- if not Assigned(GlobalLoaded) then
- FLoaded.Free;
- FLoaded := nil;
- end;
- GlobalFixupReferences;
- except
- RemoveFixupReferences(ARoot, '');
- if not Assigned(ARoot) then
- Result.Free;
- raise;
- end;
- {finally
- GlobalNameSpace.EndWrite;
- end;}
- end;
- procedure TReader.ReadComponents(AOwner, AParent: TComponent;
- Proc: TReadComponentsProc);
- var
- Component: TComponent;
- begin
- Root := AOwner;
- Owner := AOwner;
- Parent := AParent;
- BeginReferences;
- try
- while not EndOfList do
- begin
- FDriver.BeginRootComponent;
- Component := ReadComponent(nil);
- if Assigned(Proc) then
- Proc(Component);
- end;
- ReadListEnd;
- FixupReferences;
- finally
- EndReferences;
- end;
- end;
- function TReader.ReadString: String;
- var
- StringType: TValueType;
- begin
- StringType := FDriver.ReadValue;
- if StringType in [vaString, vaLString,vaUTF8String] then
- begin
- Result := FDriver.ReadString(StringType);
- if (StringType=vaUTF8String) then
- Result:=string(utf8Decode(Result));
- end
- else if StringType in [vaWString] then
- Result:= string(FDriver.ReadWidestring)
- else if StringType in [vaUString] then
- Result:= string(FDriver.ReadUnicodeString)
- else
- raise EReadError.Create(SInvalidPropertyValue);
- end;
- function TReader.ReadWideString: WideString;
- var
- s: String;
- i: Integer;
- vt:TValueType;
- begin
- if NextValue in [vaWString,vaUString,vaUTF8String] then
- //vaUTF8String needs conversion? 2008-09-06 mse, YES!! AntonK
- begin
- vt:=ReadValue;
- if vt=vaUTF8String then
- Result := utf8decode(fDriver.ReadString(vaLString))
- else
- Result := FDriver.ReadWideString
- end
- else
- begin
- //data probable from ObjectTextToBinary
- s := ReadString;
- setlength(result,length(s));
- for i:= 1 to length(s) do begin
- result[i]:= widechar(ord(s[i])); //no code conversion
- end;
- end;
- end;
- function TReader.ReadUnicodeString: UnicodeString;
- var
- s: String;
- i: Integer;
- vt:TValueType;
- begin
- if NextValue in [vaWString,vaUString,vaUTF8String] then
- //vaUTF8String needs conversion? 2008-09-06 mse, YES!! AntonK
- begin
- vt:=ReadValue;
- if vt=vaUTF8String then
- Result := utf8decode(fDriver.ReadString(vaLString))
- else
- Result := FDriver.ReadWideString
- end
- else
- begin
- //data probable from ObjectTextToBinary
- s := ReadString;
- setlength(result,length(s));
- for i:= 1 to length(s) do begin
- result[i]:= UnicodeChar(ord(s[i])); //no code conversion
- end;
- end;
- end;
- function TReader.ReadValue: TValueType;
- begin
- Result := FDriver.ReadValue;
- end;
- procedure TReader.CopyValue(Writer: TWriter);
- procedure CopyBytes(Count: Integer);
- { var
- Buffer: array[0..1023] of Byte; }
- begin
- {!!!: while Count > 1024 do
- begin
- FDriver.Read(Buffer, 1024);
- Writer.Driver.Write(Buffer, 1024);
- Dec(Count, 1024);
- end;
- if Count > 0 then
- begin
- FDriver.Read(Buffer, Count);
- Writer.Driver.Write(Buffer, Count);
- end;}
- end;
- {var
- s: String;
- Count: LongInt; }
- begin
- case FDriver.NextValue of
- vaNull:
- Writer.WriteIdent('NULL');
- vaFalse:
- Writer.WriteIdent('FALSE');
- vaTrue:
- Writer.WriteIdent('TRUE');
- vaNil:
- Writer.WriteIdent('NIL');
- {!!!: vaList, vaCollection:
- begin
- Writer.WriteValue(FDriver.ReadValue);
- while not EndOfList do
- CopyValue(Writer);
- ReadListEnd;
- Writer.WriteListEnd;
- end;}
- vaInt8, vaInt16, vaInt32:
- Writer.WriteInteger(ReadInteger);
- {$ifndef FPUNONE}
- vaExtended:
- Writer.WriteFloat(ReadFloat);
- {$endif}
- {!!!: vaString:
- Writer.WriteStr(ReadStr);}
- vaIdent:
- Writer.WriteIdent(ReadIdent);
- {!!!: vaBinary, vaLString, vaWString:
- begin
- Writer.WriteValue(FDriver.ReadValue);
- FDriver.Read(Count, SizeOf(Count));
- Writer.Driver.Write(Count, SizeOf(Count));
- CopyBytes(Count);
- end;}
- {!!!: vaSet:
- Writer.WriteSet(ReadSet);}
- {$ifndef FPUNONE}
- vaSingle:
- Writer.WriteSingle(ReadSingle);
- {$endif}
- {!!!: vaCurrency:
- Writer.WriteCurrency(ReadCurrency);}
- {$ifndef FPUNONE}
- vaDate:
- Writer.WriteDate(ReadDate);
- {$endif}
- vaInt64:
- Writer.WriteInteger(ReadInt64);
- end;
- end;
- function TReader.FindComponentClass(const AClassName: String): TComponentClass;
- var
- PersistentClass: TPersistentClass;
- ShortClassName: shortstring;
- procedure FindInFieldTable(RootComponent: TComponent);
- var
- FieldTable: PFieldTable;
- FieldClassTable: PFieldClassTable;
- Entry: TPersistentClass;
- i: Integer;
- ComponentClassType: TClass;
- begin
- ComponentClassType := RootComponent.ClassType;
- // it is not necessary to look in the FieldTable of TComponent,
- // because TComponent doesn't have published properties that are
- // descendants of TComponent
- while ComponentClassType<>TComponent do
- begin
- FieldTable:=PVmt(ComponentClassType)^.vFieldTable;
- if assigned(FieldTable) then
- begin
- FieldClassTable := FieldTable^.ClassTable;
- for i := 0 to FieldClassTable^.Count -1 do
- begin
- Entry := FieldClassTable^.Entries[i]{$ifndef VER3_0}^{$endif};
- //writeln(format('Looking for %s in field table of class %s. Found %s',
- //[AClassName, ComponentClassType.ClassName, Entry.ClassName]));
- if Entry.ClassNameIs(ShortClassName) and
- (Entry.InheritsFrom(TComponent)) then
- begin
- Result := TComponentClass(Entry);
- Exit;
- end;
- end;
- end;
- // look in parent class
- ComponentClassType := ComponentClassType.ClassParent;
- end;
- end;
-
- begin
- Result := nil;
- ShortClassName:=AClassName;
- FindInFieldTable(Root);
-
- if (Result=nil) and assigned(LookupRoot) and (LookupRoot<>Root) then
- FindInFieldTable(LookupRoot);
- if (Result=nil) then begin
- PersistentClass := GetClass(AClassName);
- if PersistentClass.InheritsFrom(TComponent) then
- Result := TComponentClass(PersistentClass);
- end;
-
- if (Result=nil) and assigned(OnFindComponentClass) then
- OnFindComponentClass(Self, AClassName, Result);
- if (Result=nil) or (not Result.InheritsFrom(TComponent)) then
- raise EClassNotFound.CreateFmt(SClassNotFound, [AClassName]);
- end;
- { TAbstractObjectReader }
- procedure TAbstractObjectReader.FlushBuffer;
- begin
- // Do nothing
- end;
|