Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I prevent TStringlist removing key value pair when value set to empty

Tags:

delphi

Can I prevent TStringList from removing key-value-pair when value is set to empty? I use Delphi XE8 and Lazarus which work differently. I want the pair to be left in the TStringlist object even when the value is set to an empty string. For example:

procedure TMyClass.Set(const Key, Value: String);
begin
  // FData is a TStringList object
  FData.Values[Key] := Value; // Removes pair when value is empty. Count decreases and Key is lost.
end;

Problem that I'm having is that when I compile with Delphi the pair with empty values is removed and I don't know afterwards was a value with a key never set or was it explicitly set to be an empty string. Also I can't get all the keys that have been used. Now I need to hold another collection of keys that holds information about empty ones.

MyKeyValues.Set('foo', 'bar'); // Delphi FData.Count = 1; Lazarus FData.Count = 1
MyKeyValues.Set('foo', '');    // Delphi FData.Count = 0; Lazarus FData.Count = 1
like image 898
Allan Ojala Avatar asked Nov 24 '15 12:11

Allan Ojala


People also ask

How to store key-value pairs in a TStringlist?

You can use a TStringList to store Key-Value pairs. This can be useful if you want to store settings, for example. A settings consists of a Key (The Identifier of the setting) and the value. Each Key-Value pair is stored in one line of the StringList in Key=Value format.

What is a key and value in a string list?

A settings consists of a Key (The Identifier of the setting) and the value. Each Key-Value pair is stored in one line of the StringList in Key=Value format.

What is the use of TStringlist?

TStringList has a variety of user cases including string manipulation, sorting, indexing, key-value pairing and delimiter separation among them. You can use a TStringList to store Key-Value pairs. This can be useful if you want to store settings, for example. A settings consists of a Key (The Identifier of the setting) and the value.

What happens to a stringlist before it is destroyed?

In this example, the Stringlist has the following content before it is destroyed: Under the hood TStringList performs key search by straight looping through all items, searching for separator inside every item and comparing the name part against the given key.


2 Answers

You can write a class helper to implement a new behaviour of the SetValue method of the TStrings class.

If you don't like a solution based on a class helper, you can use a custom class which inherits from TStringList and, again, override its Values property behaviour - the code is very similar to this helper-based implementation.

I'd prefer to use the second choice because the helper will define a new behaviour for all the TStringList objects.

type
  TStringsHelper = class helper for TStrings
    private
      function GetValue(const Name: string): string;
      procedure SetValue(const Name, Value: string); reintroduce;
    public
      property Values[const Name: string]: string read GetValue write SetValue;
  end;


function TStringsHelper.GetValue(const Name: string): string;
begin
  Result := Self.GetValue(Name);
end;

procedure TStringsHelper.SetValue(const Name, Value: string);
var
  I: Integer;
begin
  I := IndexOfName(Name);
  if I < 0 then I := Add('');
  Put(I, Name + NameValueSeparator + Value);
end;
like image 81
fantaghirocco Avatar answered Sep 25 '22 06:09

fantaghirocco


What about this?

procedure TMyClass.Set(const Key, Value: String);
var
  i:integer;
begin
  i := FData.IndexOfName(Key);
  if i = -1 then
    FData.Add(Key + '=' + Value)
  else
    FData[i] := Key + '=' + Value;
end;

You can choose wether to set FData.Sorted:=true; or not.

like image 20
Stijn Sanders Avatar answered Sep 23 '22 06:09

Stijn Sanders