026393f9e622575870f6055d0f4853e3

It is something that we have to do lots of time, so it must be as simple and performante as possible.
I have this simple but horrible code.
The string/WideString here I have to change is like this:
‘CONFIG;Ver=1.0;MENUSOUND=ON;DEFAULTSEC=3456;SHowDate=ON;DATE=”” ’;
Separator is Blanks or ‘;’, so must check for both.
I must be able to get the Vars Values and change them.

Function TfrmProc.ChangeValue( pData : WideString; KeyVar: String; pIncr : Integer ) : WideString;
	VAR     X : Byte;
		 _lPosIni, _lPosEqual,	_lPosSep : smallint;
		_lStrBegin,	_lStrEnd : WideString;
		_lValue : Integer;
	Begin
		Result := pData;

		if NOT (Pos(AnsiUpperCase(KeyVar), AnsiUpperCase(pData)) > 0) then
   		   EXIT;

		_lPosIni := Pos(AnsiUpperCase(KeyVar), AnsiUpperCase(pData))

		_lPosEqual:=PosFrom( pData,'=', _lPosIni+Length(KeyVar)-1 );

		// Search for sep - 'B' OR ;
		for X := _lPosEqual to Length(pData) do
			if (pData[X]=';') OR (pData[X]=' ') then Begin
				_lPosSep := X;
				Break;
			end;

		_lStrBegin:= SubStr( pData, 0, _lPosEqual);

		_lValue 	:= StrToInt( SubStr( pData, _lPosEqual+1,	((_lPosSep-1)-_lPosEqual)) );
		_lValue 	:= _lValue + pIncr;

		_lStrEnd	:= SubStr( pData, _lPosSep+1 );

		Result := format('%s%d;%s',[_lStrBegin,_lValue,_lStrEnd])

	End;


function PosFrom(Text : WideString; search : Char; Position : Integer) : Integer;
var 	L, X : Integer;
begin
	Result := 0;
	L := Length(Text);

	if (Position > L) or (Position < 1) then
		Exit;

	for X := Position to L do begin
		if UpperCase(Text[X]) = String(Search) then Begin
			Result := X;
			Exit;
		end
	end;

end;

Refactorings

No refactoring yet !

92647e77af9606a13dc6ccc39dc37265

X-Ray

February 21, 2009, February 21, 2009 17:46, permalink

2 ratings. Login to rate!

this comment doesn't directly answer your question but here's how i do things like that.

i like to use TStringList's parsing. StringReplace hasn't been so fast but usually it doesn't matter much.

// not tested

var
  sl:TStringList;
begin
  sl:=TStringList.Create;
  try
    // i think Text property splits on space AND #13.  if it doesn't, you can repl space with #13 too
    sl.Text:=StringReplace(s, ';', #13, [rfReplaceAll]);
    sl.Values[sTokenName]:='something';
    Result:=sl.Values[sTokenName];
  finally
    sl.Free;
  end;
end;
7983135a9fcc8bcfe9d9de240225512a

ahuser

February 22, 2009, February 22, 2009 11:00, permalink

2 ratings. Login to rate!

This code is is based on your algorithm but it is optimized to not unnecessary convert strings and chars.

{$IFNDEF UNICODE} // pre Delphi 2009
type
  UnicodeString = WideString;
{$ENDIF ~UNICODE}

function ChangeValue(const AData: UnicodeString; const AKeyVar: UnicodeString; AIncr: Integer): UnicodeString;
var
  I: Integer;
  lPosIni, lPosEqual, lPosSep: Integer;
  lStrBegin, lStrEnd: UnicodeString;
  lValue: Integer;
  lDataLen: Integer;
Begin
  {$IFDEF UNICODE}
  lPosIni := Pos(AnsiUpperCase(AKeyVar), AnsiUpperCase(AData));
  {$ELSE}
  lPosIni := Pos(WideUpperCase(AKeyVar), WideUpperCase(AData));
  {$ENDIF UNICODE}
  if lPosIni = 0 then
  begin
    Result := AData;
    Exit;
  end;

  lDataLen := Length(AData);

  // Find equal symbol
  lPosEqual := 0;
  for I := lPosIni + Length(AKeyVar) to lDataLen do
  begin
    case AData[I] of
      '=':
        begin
          lPosEqual := I;
          Break;
        end;
      ' ', ';':
        Break; // no equal symbol for this KeyVar
    end;
  end;

  // Search for sep - 'B' OR ;
  if lPosEqual <> 0 then
  begin
    lPosSep := lDataLen + 1;
    for I := lPosEqual + 1 to lDataLen do
    begin
      if (AData[I] = ';') or (AData[I] = ' ') then
      begin
        lPosSep := I;
        Break;
      end;
    end;

    lStrBegin := Copy(AData, 1, lPosEqual);
    lValue := AIncr + StrToInt(Copy(AData, lPosEqual + 1, (lPosSep - 1) - lPosEqual));
    lStrEnd	:= Copy(AData, lPosSep, MaxInt);

    Result := Format('%s%d%s', [lStrBegin, lValue, lStrEnd])
  end
  else
    Result := AData;
end;
45af96802dc2ea89356c254bd9d0af06

Wouter van Nifterick

March 5, 2010, March 05, 2010 03:11, permalink

No rating. Login to rate!

The program below outputs the following:

CONFIG;Ver=1.0;MENUSOUND=ON;DEFAULTSEC=3456;SHowDate=ON;DATE=
CONFIG;Ver=1.0;MENUSOUND=ON;DEFAULTSEC=3356;SHowDate=ON;DATE=

Note that the value of DEFAULTSEC has been decreased by 100.

program TestChangeValue;
{$APPTYPE CONSOLE}
uses Classes, SysUtils;

function ChangeValue(const AData: UnicodeString; const AKeyVar: UnicodeString; AIncr: Integer): UnicodeString;
begin
  with TStringList.Create do
  try
    Delimiter       := ';';
    DelimitedText   := AData;
    Values[AKeyVar] := IntTostr(StrToIntDef(Values[AKeyVar],0)+AIncr);
    Result          := DelimitedText;
  finally
    Free;
  end;
end;

// test it
const OldStr = 'CONFIG;Ver=1.0;MENUSOUND=ON;DEFAULTSEC=3456;SHowDate=ON;DATE=';
var   NewStr:String;
begin
  NewStr := ChangeValue(OldStr, 'DEFAULTSEC', -100);
  WriteLn(OldStr,#13#10,NewStr);
  ReadLn;
end.

Your refactoring





Format Copy from initial code

or Cancel