unit uMarshal;

interface

uses
  SysUtils, Classes,
{$IFDEF VCL}
  Controls,
{$ELSE}
  QControls,
{$ENDIF}
  Rubies;

function ComponentToString1(real: TComponent; limit, depth: Integer): string;
function ComponentToString(Component: TComponent): string;
function StringToComponent(S: string): TComponent;

implementation

function ComponentToString1(real: TComponent; limit, depth: Integer): string;
const
  Terminus: string = 'end'#13#10;
var
  BinStream: TMemoryStream;
  StrStream: TStringStream;
  S: string;
  i: Integer;
begin
  BinStream := TMemoryStream.Create;
  try
  StrStream := TStringStream.Create(S);
  try
  try
    BinStream.WriteComponent(real);
    BinStream.Seek(0, soFromBeginning);
    ObjectBinaryToText(BinStream, StrStream);
    StrStream.Seek(0, soFromBeginning);
    Result := StrStream.DataString;
    if (0 <= limit) and (limit <= depth) then Exit;
    SetLength(Result, Length(Result)-Length(Terminus));
    if real is TWinControl then
    for i := 0 to TWinControl(real).ControlCount-1 do
      Result := Result +
      ComponentToString1(TWinControl(real).Controls[i], limit, depth+1);
(*
    for i := 0 to real.ComponentCount-1 do
      Result := Result +
      ComponentToString1(real.Components[i], limit, depth+1);
*)
    Result := Result + Terminus;
  except
    on E: Exception do
      ap_raise(ap_eIOError, E.message);
  end;
  finally
    StrStream.Free;
  end;
  finally
    BinStream.Free;
  end;
end;

function ComponentToString(Component: TComponent): string;
var
  BinStream: TMemoryStream;
  StrStream: TStringStream;
  S: string;
begin
  BinStream := TMemoryStream.Create;
  try
  StrStream := TStringStream.Create(S);
  try
  try
    BinStream.WriteComponent(Component);
    BinStream.Seek(0, soFromBeginning);
    ObjectBinaryToText(BinStream, StrStream);
    StrStream.Seek(0, soFromBeginning);
    Result := StrStream.DataString;
  except
    on E: Exception do
      ap_raise(ap_eIOError, E.message);
  end;
  finally
    StrStream.Free;
  end;
  finally
    BinStream.Free;
  end;
end;

function StringToComponent(S: string): TComponent;
var
  StrStream: TStringStream;
  BinStream: TMemoryStream;
begin
  StrStream := TStringStream.Create(S);
  try
  BinStream := TMemoryStream.Create;
  try
  Result := nil;
  try
    ObjectTextToBinary(StrStream, BinStream);
    BinStream.Seek(0, soFromBeginning);
    Result := BinStream.ReadComponent(nil);
  except
    on E: Exception do
      ap_raise(ap_eIOError, E.message);
  end;
  finally
    BinStream.Free;
  end;
  finally
    StrStream.Free;
  end;
end;

end.

