mirror of
https://gitlab.com/freepascal.org/fpc/pas2js.git
synced 2025-08-16 22:50:16 +02:00
* Implement TStringStream, ObjectBinaryToText
This commit is contained in:
parent
f76abc2f8d
commit
ca8aae9072
@ -834,6 +834,17 @@ type
|
|||||||
property Bytes: TBytes read GetBytes;
|
property Bytes: TBytes read GetBytes;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TStringStream }
|
||||||
|
|
||||||
|
TStringStream = class(TMemoryStream)
|
||||||
|
private
|
||||||
|
function GetDataString : String;
|
||||||
|
public
|
||||||
|
constructor Create(const aString: String); virtual; overload;
|
||||||
|
property DataString: String read GetDataString;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
TFilerFlag = (ffInherited, ffChildPos, ffInline);
|
TFilerFlag = (ffInherited, ffChildPos, ffInline);
|
||||||
TFilerFlags = set of TFilerFlag;
|
TFilerFlags = set of TFilerFlag;
|
||||||
|
|
||||||
@ -1201,6 +1212,46 @@ type
|
|||||||
property PropertyPath: string read FPropPath;
|
property PropertyPath: string read FPropPath;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TObjectStreamConverter }
|
||||||
|
|
||||||
|
TObjectTextEncoding = (oteDFM,oteLFM);
|
||||||
|
|
||||||
|
TObjectStreamConverter = Class
|
||||||
|
private
|
||||||
|
FIndent: String;
|
||||||
|
FInput : TStream;
|
||||||
|
FOutput : TStream;
|
||||||
|
FEncoding : TObjectTextEncoding;
|
||||||
|
Private
|
||||||
|
// Low level writing
|
||||||
|
procedure OutLn(s: String); virtual;
|
||||||
|
procedure OutStr(s: String); virtual;
|
||||||
|
procedure OutString(s: String); virtual;
|
||||||
|
// Low level reading
|
||||||
|
function ReadWord: word;
|
||||||
|
function ReadDWord: longword;
|
||||||
|
function ReadDouble: Double;
|
||||||
|
function ReadInt(ValueType: TValueType): NativeInt;
|
||||||
|
function ReadInt: NativeInt;
|
||||||
|
function ReadNativeInt: NativeInt;
|
||||||
|
function ReadStr: String;
|
||||||
|
function ReadString(StringType: TValueType): String; virtual;
|
||||||
|
// High-level
|
||||||
|
procedure ProcessBinary; virtual;
|
||||||
|
procedure ProcessValue(ValueType: TValueType; Indent: String); virtual;
|
||||||
|
procedure ReadObject(indent: String); virtual;
|
||||||
|
procedure ReadPropList(indent: String); virtual;
|
||||||
|
Public
|
||||||
|
procedure ObjectBinaryToText(aInput, aOutput: TStream);
|
||||||
|
procedure ObjectBinaryToText(aInput, aOutput: TStream; aEncoding: TObjectTextEncoding);
|
||||||
|
Procedure Execute;
|
||||||
|
Property Input : TStream Read FInput Write FInput;
|
||||||
|
Property Output : TStream Read Foutput Write FOutput;
|
||||||
|
Property Encoding : TObjectTextEncoding Read FEncoding Write FEncoding;
|
||||||
|
Property Indent : String Read FIndent Write Findent;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
type
|
type
|
||||||
TIdentMapEntry = record
|
TIdentMapEntry = record
|
||||||
Value: Integer;
|
Value: Integer;
|
||||||
@ -1231,6 +1282,8 @@ function CollectionsEqual(C1, C2: TCollection): Boolean;
|
|||||||
function CollectionsEqual(C1, C2: TCollection; Owner1, Owner2: TComponent): Boolean;
|
function CollectionsEqual(C1, C2: TCollection; Owner1, Owner2: TComponent): Boolean;
|
||||||
procedure GetFixupReferenceNames(Root: TComponent; Names: TStrings);
|
procedure GetFixupReferenceNames(Root: TComponent; Names: TStrings);
|
||||||
procedure GetFixupInstanceNames(Root: TComponent; const ReferenceRootName: string; Names: TStrings);
|
procedure GetFixupInstanceNames(Root: TComponent; const ReferenceRootName: string; Names: TStrings);
|
||||||
|
procedure ObjectBinaryToText(aInput, aOutput: TStream);
|
||||||
|
procedure ObjectBinaryToText(aInput, aOutput: TStream; aEncoding: TObjectTextEncoding);
|
||||||
|
|
||||||
Const
|
Const
|
||||||
vaSingle = vaDouble;
|
vaSingle = vaDouble;
|
||||||
@ -1261,6 +1314,46 @@ type
|
|||||||
AIntToIdent: TIntToIdent);
|
AIntToIdent: TIntToIdent);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TStringStream }
|
||||||
|
|
||||||
|
function TStringStream.GetDataString: String;
|
||||||
|
|
||||||
|
var
|
||||||
|
a : TJSUint16Array;
|
||||||
|
|
||||||
|
begin
|
||||||
|
Result:=''; // Silence warning
|
||||||
|
a:=TJSUint16Array.New(Memory.slice(0,Size));
|
||||||
|
asm
|
||||||
|
// Result=String.fromCharCode.apply(null, new Uint16Array(a));
|
||||||
|
Result=String.fromCharCode.apply(null, a);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TStringStream.Create(const aString: String);
|
||||||
|
|
||||||
|
Function StrToBuf(aLen : Integer) : TJSArrayBuffer;
|
||||||
|
|
||||||
|
var
|
||||||
|
I : Integer;
|
||||||
|
|
||||||
|
begin
|
||||||
|
Result:=TJSArrayBuffer.new(aLen*2);// 2 bytes for each char
|
||||||
|
With TJSUint16Array.new(Result) do
|
||||||
|
for i:=0 to aLen-1 do
|
||||||
|
values[i] := TJSString(aString).charCodeAt(i);
|
||||||
|
end;
|
||||||
|
|
||||||
|
var
|
||||||
|
Len : Integer;
|
||||||
|
|
||||||
|
begin
|
||||||
|
inherited Create;
|
||||||
|
Len:=Length(aString);
|
||||||
|
SetPointer(StrToBuf(len),Len*2);
|
||||||
|
FCapacity:=Len*2;
|
||||||
|
end;
|
||||||
|
|
||||||
constructor TIntConst.Create(AIntegerType: PTypeInfo; AIdentToInt: TIdentToInt;
|
constructor TIntConst.Create(AIntegerType: PTypeInfo; AIdentToInt: TIdentToInt;
|
||||||
AIntToIdent: TIntToIdent);
|
AIntToIdent: TIntToIdent);
|
||||||
begin
|
begin
|
||||||
@ -6471,6 +6564,25 @@ begin
|
|||||||
VisitResolveList(TReferenceInstancesVisitor.Create(Root,ReferenceRootName,Names));
|
VisitResolveList(TReferenceInstancesVisitor.Create(Root,ReferenceRootName,Names));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure ObjectBinaryToText(aInput, aOutput: TStream);
|
||||||
|
begin
|
||||||
|
ObjectBinaryToText(aInput,aOutput,oteLFM);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure ObjectBinaryToText(aInput, aOutput: TStream; aEncoding: TObjectTextEncoding);
|
||||||
|
|
||||||
|
var
|
||||||
|
Conv : TObjectStreamConverter;
|
||||||
|
|
||||||
|
begin
|
||||||
|
Conv:=TObjectStreamConverter.Create;
|
||||||
|
try
|
||||||
|
Conv.ObjectBinaryToText(aInput,aOutput,aEncoding);
|
||||||
|
finally
|
||||||
|
Conv.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure RedirectFixupReferences(Root: TComponent; const OldRootName, NewRootName: string);
|
procedure RedirectFixupReferences(Root: TComponent; const OldRootName, NewRootName: string);
|
||||||
|
|
||||||
begin
|
begin
|
||||||
@ -9030,6 +9142,348 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TObjectStreamConverter.OutStr(s: String);
|
||||||
|
|
||||||
|
Var
|
||||||
|
I : integer;
|
||||||
|
|
||||||
|
begin
|
||||||
|
For I:=1 to Length(S) do
|
||||||
|
Output.WriteBufferData(s[i]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TObjectStreamConverter.OutLn(s: String);
|
||||||
|
begin
|
||||||
|
OutStr(s + LineEnding);
|
||||||
|
end;
|
||||||
|
|
||||||
|
(*
|
||||||
|
procedure TObjectStreamConverter.Outchars(P, LastP : Pointer; CharToOrdFunc: CharToOrdFuncty; UseBytes: boolean = false);
|
||||||
|
|
||||||
|
var
|
||||||
|
res, NewStr: String;
|
||||||
|
w: Cardinal;
|
||||||
|
InString, NewInString: Boolean;
|
||||||
|
begin
|
||||||
|
if p = nil then begin
|
||||||
|
res:= '''''';
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
res := '';
|
||||||
|
InString := False;
|
||||||
|
while P < LastP do
|
||||||
|
begin
|
||||||
|
NewInString := InString;
|
||||||
|
w := CharToOrdfunc(P);
|
||||||
|
if w = ord('''') then
|
||||||
|
begin //quote char
|
||||||
|
if not InString then
|
||||||
|
NewInString := True;
|
||||||
|
NewStr := '''''';
|
||||||
|
end
|
||||||
|
else if (Ord(w) >= 32) and ((Ord(w) < 127) or (UseBytes and (Ord(w)<256))) then
|
||||||
|
begin //printable ascii or bytes
|
||||||
|
if not InString then
|
||||||
|
NewInString := True;
|
||||||
|
NewStr := char(w);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin //ascii control chars, non ascii
|
||||||
|
if InString then
|
||||||
|
NewInString := False;
|
||||||
|
NewStr := '#' + IntToStr(w);
|
||||||
|
end;
|
||||||
|
if NewInString <> InString then
|
||||||
|
begin
|
||||||
|
NewStr := '''' + NewStr;
|
||||||
|
InString := NewInString;
|
||||||
|
end;
|
||||||
|
res := res + NewStr;
|
||||||
|
end;
|
||||||
|
if InString then
|
||||||
|
res := res + '''';
|
||||||
|
end;
|
||||||
|
OutStr(res);
|
||||||
|
end;
|
||||||
|
*)
|
||||||
|
|
||||||
|
procedure TObjectStreamConverter.OutString(s: String);
|
||||||
|
begin
|
||||||
|
OutStr(S);
|
||||||
|
end;
|
||||||
|
|
||||||
|
(*
|
||||||
|
procedure TObjectStreamConverter.OutUtf8Str(s: String);
|
||||||
|
begin
|
||||||
|
if Encoding=oteLFM then
|
||||||
|
OutChars(Pointer(S),PChar(S)+Length(S),@CharToOrd)
|
||||||
|
else
|
||||||
|
OutChars(Pointer(S),PChar(S)+Length(S),@Utf8ToOrd);
|
||||||
|
end;
|
||||||
|
*)
|
||||||
|
|
||||||
|
function TObjectStreamConverter.ReadWord : word; {$ifdef CLASSESINLINE}inline;{$endif CLASSESINLINE}
|
||||||
|
begin
|
||||||
|
Input.ReadBufferData(Result);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TObjectStreamConverter.ReadDWord : longword; {$ifdef CLASSESINLINE}inline;{$endif CLASSESINLINE}
|
||||||
|
begin
|
||||||
|
Input.ReadBufferData(Result);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TObjectStreamConverter.ReadNativeInt : NativeInt; {$ifdef CLASSESINLINE}inline;{$endif CLASSESINLINE}
|
||||||
|
begin
|
||||||
|
Input.ReadBufferData(Result);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TObjectStreamConverter.ReadInt(ValueType: TValueType): NativeInt;
|
||||||
|
begin
|
||||||
|
case ValueType of
|
||||||
|
vaInt8: Result := ShortInt(Input.ReadByte);
|
||||||
|
vaInt16: Result := SmallInt(ReadWord);
|
||||||
|
vaInt32: Result := LongInt(ReadDWord);
|
||||||
|
vaNativeInt: Result := Int64(ReadNativeInt);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TObjectStreamConverter.ReadInt: NativeInt;
|
||||||
|
begin
|
||||||
|
Result := ReadInt(TValueType(Input.ReadByte));
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function TObjectStreamConverter.ReadDouble : Double;
|
||||||
|
|
||||||
|
begin
|
||||||
|
Input.ReadBufferData(Result);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TObjectStreamConverter.ReadStr: String;
|
||||||
|
|
||||||
|
var
|
||||||
|
l,i: Byte;
|
||||||
|
c : Char;
|
||||||
|
|
||||||
|
begin
|
||||||
|
Input.ReadBufferData(L);
|
||||||
|
SetLength(Result,L);
|
||||||
|
For I:=1 to L do
|
||||||
|
begin
|
||||||
|
Input.ReadBufferData(C);
|
||||||
|
Result[i]:=C;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TObjectStreamConverter.ReadString(StringType: TValueType): String;
|
||||||
|
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
C : Char;
|
||||||
|
|
||||||
|
begin
|
||||||
|
Result:='';
|
||||||
|
if StringType<>vaString then
|
||||||
|
Raise EFilerError.Create('Invalid string type passed to ReadString');
|
||||||
|
i:=ReadDWord;
|
||||||
|
SetLength(Result, i);
|
||||||
|
for I:=1 to Length(Result) do
|
||||||
|
begin
|
||||||
|
Input.ReadbufferData(C);
|
||||||
|
Result[i]:=C;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TObjectStreamConverter.ProcessBinary;
|
||||||
|
|
||||||
|
var
|
||||||
|
ToDo, DoNow, i: LongInt;
|
||||||
|
lbuf: TBytes;
|
||||||
|
s: String;
|
||||||
|
|
||||||
|
begin
|
||||||
|
ToDo := ReadDWord;
|
||||||
|
SetLength(lBuf,32);
|
||||||
|
OutLn('{');
|
||||||
|
while ToDo > 0 do
|
||||||
|
begin
|
||||||
|
DoNow := ToDo;
|
||||||
|
if DoNow > 32 then
|
||||||
|
DoNow := 32;
|
||||||
|
Dec(ToDo, DoNow);
|
||||||
|
s := Indent + ' ';
|
||||||
|
Input.ReadBuffer(lbuf, DoNow);
|
||||||
|
for i := 0 to DoNow - 1 do
|
||||||
|
s := s + IntToHex(lbuf[i], 2);
|
||||||
|
OutLn(s);
|
||||||
|
end;
|
||||||
|
OutLn(indent + '}');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TObjectStreamConverter.ProcessValue(ValueType: TValueType; Indent: String);
|
||||||
|
|
||||||
|
|
||||||
|
var
|
||||||
|
s: String;
|
||||||
|
{ len: LongInt; }
|
||||||
|
IsFirst: Boolean;
|
||||||
|
{$ifndef FPUNONE}
|
||||||
|
ext: Extended;
|
||||||
|
{$endif}
|
||||||
|
|
||||||
|
begin
|
||||||
|
case ValueType of
|
||||||
|
vaList: begin
|
||||||
|
OutStr('(');
|
||||||
|
IsFirst := True;
|
||||||
|
while True do begin
|
||||||
|
ValueType := TValueType(Input.ReadByte);
|
||||||
|
if ValueType = vaNull then break;
|
||||||
|
if IsFirst then begin
|
||||||
|
OutLn('');
|
||||||
|
IsFirst := False;
|
||||||
|
end;
|
||||||
|
OutStr(Indent + ' ');
|
||||||
|
ProcessValue(ValueType, Indent + ' ');
|
||||||
|
end;
|
||||||
|
OutLn(Indent + ')');
|
||||||
|
end;
|
||||||
|
vaInt8: OutLn(IntToStr(ShortInt(Input.ReadByte)));
|
||||||
|
vaInt16: OutLn( IntToStr(SmallInt(ReadWord)));
|
||||||
|
vaInt32: OutLn(IntToStr(LongInt(ReadDWord)));
|
||||||
|
vaNativeInt: OutLn(IntToStr(ReadNativeInt));
|
||||||
|
vaDouble: begin
|
||||||
|
ext:=ReadDouble;
|
||||||
|
Str(ext,S);// Do not use localized strings.
|
||||||
|
OutLn(S);
|
||||||
|
end;
|
||||||
|
vaString: begin
|
||||||
|
OutString(''''+StringReplace(ReadString(vaString),'''','''''',[rfReplaceAll])+'''');
|
||||||
|
OutLn('');
|
||||||
|
end;
|
||||||
|
vaIdent: OutLn(ReadStr);
|
||||||
|
vaFalse: OutLn('False');
|
||||||
|
vaTrue: OutLn('True');
|
||||||
|
vaBinary: ProcessBinary;
|
||||||
|
vaSet: begin
|
||||||
|
OutStr('[');
|
||||||
|
IsFirst := True;
|
||||||
|
while True do begin
|
||||||
|
s := ReadStr;
|
||||||
|
if Length(s) = 0 then break;
|
||||||
|
if not IsFirst then OutStr(', ');
|
||||||
|
IsFirst := False;
|
||||||
|
OutStr(s);
|
||||||
|
end;
|
||||||
|
OutLn(']');
|
||||||
|
end;
|
||||||
|
vaNil:
|
||||||
|
OutLn('nil');
|
||||||
|
vaCollection: begin
|
||||||
|
OutStr('<');
|
||||||
|
while Input.ReadByte <> 0 do begin
|
||||||
|
OutLn(Indent);
|
||||||
|
Input.Seek(-1, soCurrent);
|
||||||
|
OutStr(indent + ' item');
|
||||||
|
ValueType := TValueType(Input.ReadByte);
|
||||||
|
if ValueType <> vaList then
|
||||||
|
OutStr('[' + IntToStr(ReadInt(ValueType)) + ']');
|
||||||
|
OutLn('');
|
||||||
|
ReadPropList(indent + ' ');
|
||||||
|
OutStr(indent + ' end');
|
||||||
|
end;
|
||||||
|
OutLn('>');
|
||||||
|
end;
|
||||||
|
{vaSingle: begin OutLn('!!Single!!'); exit end;
|
||||||
|
vaCurrency: begin OutLn('!!Currency!!'); exit end;
|
||||||
|
vaDate: begin OutLn('!!Date!!'); exit end;}
|
||||||
|
else
|
||||||
|
Raise EReadError.CreateFmt(SErrInvalidPropertyType,[Ord(ValueType)]);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TObjectStreamConverter.ReadPropList(indent: String);
|
||||||
|
|
||||||
|
|
||||||
|
begin
|
||||||
|
while Input.ReadByte <> 0 do begin
|
||||||
|
Input.Seek(-1, soCurrent);
|
||||||
|
OutStr(indent + ReadStr + ' = ');
|
||||||
|
ProcessValue(TValueType(Input.ReadByte), Indent);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TObjectStreamConverter.ReadObject(indent: String);
|
||||||
|
|
||||||
|
var
|
||||||
|
b: Byte;
|
||||||
|
ObjClassName, ObjName: String;
|
||||||
|
ChildPos: LongInt;
|
||||||
|
|
||||||
|
begin
|
||||||
|
// Check for FilerFlags
|
||||||
|
b := Input.ReadByte;
|
||||||
|
if (b and $f0) = $f0 then begin
|
||||||
|
if (b and 2) <> 0 then ChildPos := ReadInt;
|
||||||
|
end else begin
|
||||||
|
b := 0;
|
||||||
|
Input.Seek(-1, soCurrent);
|
||||||
|
end;
|
||||||
|
|
||||||
|
ObjClassName := ReadStr;
|
||||||
|
ObjName := ReadStr;
|
||||||
|
|
||||||
|
OutStr(Indent);
|
||||||
|
if (b and 1) <> 0 then OutStr('inherited')
|
||||||
|
else
|
||||||
|
if (b and 4) <> 0 then OutStr('inline')
|
||||||
|
else OutStr('object');
|
||||||
|
OutStr(' ');
|
||||||
|
if ObjName <> '' then
|
||||||
|
OutStr(ObjName + ': ');
|
||||||
|
OutStr(ObjClassName);
|
||||||
|
if (b and 2) <> 0 then OutStr('[' + IntToStr(ChildPos) + ']');
|
||||||
|
OutLn('');
|
||||||
|
|
||||||
|
ReadPropList(indent + ' ');
|
||||||
|
|
||||||
|
while Input.ReadByte <> 0 do begin
|
||||||
|
Input.Seek(-1, soCurrent);
|
||||||
|
ReadObject(indent + ' ');
|
||||||
|
end;
|
||||||
|
OutLn(indent + 'end');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TObjectStreamConverter.ObjectBinaryToText(aInput, aOutput: TStream; aEncoding: TObjectTextEncoding);
|
||||||
|
|
||||||
|
begin
|
||||||
|
FInput:=aInput;
|
||||||
|
FOutput:=aOutput;
|
||||||
|
FEncoding:=aEncoding;
|
||||||
|
Execute;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TObjectStreamConverter.Execute;
|
||||||
|
|
||||||
|
begin
|
||||||
|
if FIndent = '' then FInDent:=' ';
|
||||||
|
If Not Assigned(Input) then
|
||||||
|
raise EReadError.Create('Missing input stream');
|
||||||
|
If Not Assigned(Output) then
|
||||||
|
raise EReadError.Create('Missing output stream');
|
||||||
|
if Input.ReadDWord <> FilerSignatureInt then
|
||||||
|
raise EReadError.Create('Illegal stream image');
|
||||||
|
ReadObject('');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TObjectStreamConverter.ObjectBinaryToText(aInput, aOutput: TStream);
|
||||||
|
begin
|
||||||
|
ObjectBinaryToText(aInput,aOutput,oteDFM);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
initialization
|
initialization
|
||||||
ClassList:=TJSObject.create(nil);
|
ClassList:=TJSObject.create(nil);
|
||||||
end.
|
end.
|
||||||
|
Loading…
Reference in New Issue
Block a user