unit dansitemp;

{$MODE FPC}
{$MODESWITCH ADVANCEDRECORDS}
{$MODESWITCH RESULT}

interface

type
TAnsiTemp = packed record
  ExternalData: PAnsiChar;
  Size: SizeUInt;
  SmallBuffer: array[0 .. 48 - 1] of AnsiChar;
  function IsExternal: Boolean; inline;
  function Data: PAnsiChar;
end;

// Implicit conversions
operator := (C: AnsiChar): TAnsiTemp;
operator := (const S: AnsiString): TAnsiTemp;
operator := (const P: PAnsiChar): TAnsiTemp;
operator := (I: Int64): TAnsiTemp;

implementation

function TAnsiTemp.IsExternal: Boolean;
begin
  Exit(SmallBuffer[High(SmallBuffer)] <> #0);
end;

function TAnsiTemp.Data: PAnsiChar;
begin
  if SmallBuffer[High(SmallBuffer)] <> #0 then begin
    Result := ExternalData;
  end else
    Result := @SmallBuffer[0];
end;

operator := (C: AnsiChar): TAnsiTemp;
begin
  Result.SmallBuffer[0] := C;
  Result.SmallBuffer[1] := #0;
  Result.ExternalData := @Result.SmallBuffer[0];
  Result.Size := 1;
  Result.SmallBuffer[High(Result.SmallBuffer)] := #0;
end;

operator := (const S: AnsiString): TAnsiTemp;
begin
  Result.ExternalData := @S[1];
  Result.Size := Length(S);
  Result.SmallBuffer[High(Result.SmallBuffer)] := #255;
end;

operator := (const P: PAnsiChar): TAnsiTemp;
begin
  Result.ExternalData := P;
  Result.Size := StrLen(P);
  Result.SmallBuffer[High(Result.SmallBuffer)] := #255;
end;

operator := (I: Int64): TAnsiTemp;
var
  S: ShortString;
begin
  Str(I, S);
  Move(S[1], Result.SmallBuffer[0], Length(S));
  Result.ExternalData := @Result.SmallBuffer[0];
  Result.SmallBuffer[High(Result.SmallBuffer)] := #0;
  if Length(S) > High(Result.SmallBuffer) then begin
    Result.Size := Length(Result.SmallBuffer) - 1;
  end else begin
    Result.SmallBuffer[Length(S)] := #0;
    Result.Size := Length(S);
  end;
end;

end.
