Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[D2009++] TStringStream constructor does not take initial value into account #183

Closed
uschuster opened this issue Sep 25, 2018 · 0 comments
Closed

Comments

@uschuster
Copy link
Contributor

When trying to create a TStringStream with Delphi 2009 or newer the initial value in the constructor is not taken into account, because TStringStream has multiple constructors and the pointer points to the wrong overload.

The console app below, which is based on the samples, does demonstrate this.

The expected output is:

6

The actual output is with D2009 and higher:

0

I have a fix with a helper function in mind and plan to provide a pull request in the next few days.

program StringStreamCreate;

{$APPTYPE CONSOLE}

uses
  uPSCompiler, uPSRuntime, uPSUtils, uPSC_Std, uPSC_classes, uPSR_std, uPSR_classes;

procedure OutputStringToConsole(const AStr: string);
begin
  WriteLn(AStr);
end;

{$IFDEF UNICODE}
function ScriptOnUses(Sender: TPSPascalCompiler; const Name: AnsiString): Boolean;
{$ELSE}
function ScriptOnUses(Sender: TPSPascalCompiler; const Name: string): Boolean;
{$ENDIF}
begin
  if Name = 'SYSTEM' then
  begin
    SIRegister_Std(Sender);
    SIRegister_Classes(Sender, True);
    Sender.AddDelphiFunction('procedure OutputStringToConsole(const AStr: string)');
    Result := True;
  end else
    Result := False;
end;

procedure ExecOnException(Sender: TPSExec; ExError: TPSError; const ExParam: tbtstring; ExObject: TObject; ProcNo, Position: Cardinal);
begin
  WriteLn('EXCEPTION: ' + PSErrorToString(ExError, ExParam));
end;

procedure ExecuteScript(const Script: string);
var
  Compiler: TPSPascalCompiler;
  Exec: TPSExec;
  I: Integer;
  {$IFDEF UNICODE}Data: AnsiString;{$ELSE}Data: string;{$ENDIF}
  CI: TPSRuntimeClassImporter;
begin
  Compiler := TPSPascalCompiler.Create;
  Compiler.OnUses := ScriptOnUses;
  if not Compiler.Compile(Script) then
  begin
    for I := 0 to Compiler.MsgCount -1 do
      Writeln(Compiler.Msg[I].MessageToString);
    Compiler.Free;
    Exit;
  end;

  Compiler.GetOutput(Data);
  Compiler.Free;

  CI := TPSRuntimeClassImporter.Create;
  RIRegister_Std(CI);
  RIRegister_Classes(CI, True);
  Exec := TPSExec.Create;
  RegisterClassLibraryRuntime(Exec, CI);
  Exec.RegisterDelphiFunction(@OutputStringToConsole, 'OutputStringToConsole', cdRegister);
  Exec.OnException := ExecOnException;
  if not Exec.LoadData(Data) then
  begin
    Exec.Free;
    Exit;
  end;

  Exec.RunScript;
  Exec.Free;
  CI.Free;
end;

const
  Script =
    'var' + #13#10 +
    '  StringStream: TStringStream;' + #13#10 +
    'begin' + #13#10 +
    '  StringStream := TStringStream.Create(''Stream'');' + #13#10 +
    '  try' + #13#10 +
    '    OutputStringToConsole(IntToStr(StringStream.Size));' + #13#10 +
    '  finally' + #13#10 +
    '    StringStream.Free;' + #13#10 +
    '  end;' + #13#10 +
    'end.';

begin
  ExecuteScript(Script);
  ReadLn;
end.
uschuster added a commit to uschuster/pascalscript that referenced this issue Sep 27, 2018
Added a wrapper for TStringStream.Create(const AString: string) because Unicode Delphi has multiple constructors and the pointer points to the wrong overload
carlokok pushed a commit that referenced this issue Sep 27, 2018
* Fix for #180 (#180)

- enables VarArrayGet/-Set for Delphi 6 or higher
- since D5 VarArrayGet seems not to be accessible the best solution is to negate $IFNDEF DELPHI6UP into $IFDEF DELPHI6UP

* Fix for #73 (#73)

Added an InputQuery wrapper because Delphi XE2 and higher have two additional versions of InputQuery, the pointer points to the wrong version and the execution fails with "Length of value array must be >= length of prompt array"

* Fix for #183 (#183)

Added a wrapper for TStringStream.Create(const AString: string) because Unicode Delphi has multiple constructors and the pointer points to the wrong overload
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant