Home > Delphi, Object Pascal > Lazy Params, again..

Lazy Params, again..

Right. A while back I posted an idea I had for extracting name/value pairs from a string. You know, typical “this=that” type parameters. This was just a concept, an idea, a scetch of how I could re-implement coding techniques from Smart Pascal in Delphi.

The point was actually not the name-value pair stuff at all, but rather setting up code in a way that allowed us to extract information on demand, objectively, and then just let the object die out when we dont need it anymore. Things common to C# and JS, but sometimes hard to get right in traditional languages like C++ and Delphi.

Come on you vicious bastard!

Monty Python feelings

Naturally, ideas and concepts are not carved in stone. When you sit down to scetch out a painting – you dont actually produce the complete work. You play around with the idea and flesh out a draft. Sadly this was missunderstood in that post, and I have gotten more than a few comments on it.

As I mentioned in the original post (towards the end), the code did include a few faults. Most notably a missing destructor to kill the dictionary – and also the lack of an interface to get the reference counting working.

It was also pointed out that -since only a string was being managed, it wouldnt actually invoke the destructor as planned.

Well, I think we have exhausted the topic, but I will repeat it one more time: This was just a rough scetch. A concept, and idea. It was not something carved in stone — and like many bloggers I just typed down the idea quickly, taking for granted that people interested in new ideas would add the missing bits without doing through the rough code with a fine tooth comb. Boy was I wrong.

Anyways, here is a working version of the idea. Complete with a padding integer, object isolation and the bare minimum. Place some breakpoints and you can verify that it indeed releases the instances (which is why the destructor for TSourceParameter does nothing but call inherited) as expected. So you can remove the destructor all together, its just there to place a breakpoint.

Just start a new VCL project, drop a button on the form, then copy and replace the form text with the code below. Hopefully this closes the subject once and for all.

Oh, and I would move TSourceParameter into the implementation section of the unit and only expose the interface.

 

unit Unit1;

interface

uses
  System.generics.collections,
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type

  TSourceParameters = Class(TInterfacedObject)
  private
    FLUT: TDictionary<string,string>;
  public
    type

    ISourceParameter = interface
      ['{C6C937DF-50FA-4984-BA6F-EBB0B367D3F3}']
      function Empty: boolean;
      function AsString: string;
      function AsInteger: integer;
      function AsBool: boolean;
      function AsFloat: double;
    end;

    TSourceParameter = Class(TInterfacedObject, ISourceParameter)
    private
      FData:      string;
      __pad:      integer;
    public
      function    Empty:Boolean;
      function    AsString:String;
      function    AsInteger:Integer;
      function    AsBool:Boolean;
      function    AsFloat:Double;
      Constructor Create(Data:String);virtual;
      Destructor Destroy;Override;
    end;

    function    Get(Name:String):ISourceParameter;
    Constructor Create(CommandText:String);virtual;
    Destructor Destroy;Override;
  end;

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

//#############################################################################
// TSourceParameters.TSourceParameter
//#############################################################################

Constructor TSourceParameters.TSourceParameter.Create(Data:String);
begin
  inherited Create;
  FData:=trim(Data);
end;

Destructor TSourceParameters.TSourceParameter.Destroy;
begin
  inherited;
end;

function TSourceParameters.TSourceParameter.Empty:Boolean;
begin
  result:=length(FData)<1;
end;

function TSourceParameters.TSourceParameter.AsString:String;
begin
  result:=FData;
end;

function TSourceParameters.TSourceParameter.AsInteger:Integer;
begin
  TryStrToInt(FData,Result);
end;

function TSourceParameters.TSourceParameter.AsBool:Boolean;
begin
  TryStrToBool(FData,Result);
end;

function TSourceParameters.TSourceParameter.AsFloat:Double;
begin
  TryStrToFloat(FData,Result);
end;

//#############################################################################
// TSourceParameters
//#############################################################################

Constructor TSourceParameters.Create(CommandText:String);
var
  mList:  TStringlist;
  x:      Integer;
  mId:    String;
begin
  inherited Create;
  FLUT:=TDictionary<string,string>.Create;

  commandText:=trim(commandText);
  if length(commandText)>0 then
  Begin
    (* Populate our lookup table *)
    mlist:=TStringList.Create;
    try
      mList.Text:=StringReplace(CommandText,';',#13,[rfReplaceAll]);
      for x:=0 to mList.Count-1 do
      begin
        mId:=lowercase(trim(mList.Names[x]));
        FLut.AddOrSetValue(mId, trim(mList.ValueFromIndex[x]) );
      end;
    finally
      mList.Free;
    end;
  end;
end;

Destructor TSourceParameters.Destroy;
begin
  if FLUT<>nil then
    FLut.Free;
  inherited;
end;

function TSourceParameters.Get(Name:String):ISourceParameter;
var
  mData:  String;
begin
  FLut.TryGetValue(name,mData);
  result:=TSourceParameter.Create(mData) as ISourceParameter;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  FParams: TSourceParameters;
  mText:  String;
  mFloat: Double;
  mBool:  Boolean;
  mInt:   Integer;
begin
  FParams:=TSourceParameters.Create('name=testing;color=12;number=94.5;gone=true');
  try
    mtext:=FParams.Get('name').AsString;
    mInt:=FParams.Get('color').AsInteger;
    mFloat:=FParams.Get('number').AsFloat;
    mBool:=FParams.Get('gone').AsBool;
  finally
    FParams.Free;
  end;
end;

end.

Advertisements
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: