program EmptyStringWriter;

{$mode objfpc}{$h+}

uses
  SysUtils, Classes;

type
  TMyComp = class(TComponent)
  public const
    cDefS = 'default';
  private
    fS: string;
    fT: string;
    fU: string;
    fSn: string;
    fTn: string;
    fUn: string;
    fSdef: string;
    function SStored: Boolean;
    function SnStored: Boolean;
    function SdefStored: Boolean;
  public
    constructor Create(AOwner: TComponent); override;
  published
    property S: string read fS write fS stored SStored nodefault;
    property T: string read fT write fT nodefault;
    property U: string read fU write fU;
    property Sn: string read fSn write fSn stored SnStored nodefault;
    property Tn: string read fTn write fTn nodefault;
    property Un: string read fUn write fUn;
    property Sdef: string read fSdef write fSdef stored SdefStored nodefault;
  end;

{ TMyComp }

constructor TMyComp.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);

  fS := cDefS;
  fSn := cDefS;
  fSdef := cDefS;
end;

function TMyComp.SdefStored: Boolean;
begin
  Result := fSdef <> cDefS;
end;

function TMyComp.SnStored: Boolean;
begin
  Result := fSn <> cDefS;
end;

function TMyComp.SStored: Boolean;
begin
  Result := fS <> cDefS;
end;

const
  ExpectedOutput: RawByteString = #7#84#77#121#67#111#109#112#0#1#83#6#0#1#84#6#0#2#83#110#6#1#110#2#84#110#6#1#110#2#85#110#6#1#110#0#0;
var
  xStream: TStream;
  xWriter: TWriter;
  C: TMyComp;
  xReader: TReader;
  B: Byte;
  I: Integer;
begin
  xStream := TMemoryStream.Create;
  C := TMyComp.Create(nil);
  C.S := '';
  C.T := '';
  C.U := '';
  C.Sn := 'n';
  C.Tn := 'n';
  C.Un := 'n';
  //keep SDef to default value -> won't be streamed
  xWriter := TWriter.Create(xStream, 1024);
  xWriter.WriteComponent(C);
  C.Free;
  xWriter.Free;
  xStream.Position := 0;
  I := 1;
  while xStream.Read(B, 1) = 1 do
  begin
    if (I>Length(ExpectedOutput)) or (B<>Ord(ExpectedOutput[I])) then
      raise Exception.CreateFmt('Wrong output at character index: %d', [I]);
    Inc(I);
  end;
  xStream.Position := 0;
  C := TMyComp.Create(nil);
  xReader := TReader.Create(xStream, 1024);
  xReader.BeginReferences;
  xReader.ReadComponent(C);
  xReader.EndReferences;
  if C.S<>'' then
    raise Exception.Create('S invalid.');
  if C.T<>'' then
    raise Exception.Create('T invalid.');
  if C.U<>'' then
    raise Exception.Create('U invalid.');
  if C.Sn<>'n' then
    raise Exception.Create('Sn invalid.');
  if C.Tn<>'n' then
    raise Exception.Create('Tn invalid.');
  if C.Un<>'n' then
    raise Exception.Create('Un invalid.');
  if C.Sdef<>TMyComp.cDefS then
    raise Exception.Create('Un invalid.');
  C.Free;
  xReader.Free;
  xStream.Free;
end.