////////////////////////////////////////////////////////////////////////////////
/// UNIT ProtocolUtils /////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// ///
/// Copyright © 2006 by Florian Bernd ///
/// [url]www.bernd-boppard.de[/url] ///
/// ///
/// Dieses Copyright darf nicht entfernt oder geändert werden! ///
/// Über eine Benennung in den Credits würde ich micht freuen, jedoch ist ///
/// dies nicht zwingend erforderlich. ///
/// ///
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
unit ProtocolUtils;
interface
uses
Classes, Windows, SysUtils;
//Paramter setzen
procedure SetParams(fDELIMITER, fCMDSIGN, fRETSIGN, fQUOTE, fPQUOTE: Char);
//Commando String erstellen
function GetCMDString(Command:
string; Params:
array of string):
string;
//Teilweisen Commando String erstellen
function GetPartitialCMDString(Parts:
array of string; CommandBegin,
EndOfData: boolean):
string;
//Commandos parsen
function ParseCommands(CmdLine, Buffer:
string; Commands: TStringList):
string;
//Commandostring erstellen und nach Zeichen begrenzt ausgeben
procedure GetLimitedCMDString(Command:
string; Params:
array of string;
Limit: integer; Parts: TStringList);
//Die Parameter eines Befehls bekommen
procedure ParseParameter(Command:
string; Params: TStringList);
var
DELIMITER: Char = '
|';
//Trennzeichen für Parameter
CMDSIGN : Char = '
*';
//Trennzeichen für die Befehle
RETSIGN : Char = '
#';
//Endzeichen für einen Befehl
QUOTE : Char = '
"';
//Quote Zeichen für die Befehle
PQUOTE : Char = '
~';
//Quote Zeichen für die Parameter
implementation
//Splittet einen Text anhand eines Delimiters in seine Einzelteile auf
function Split(
const fText:
String;
const fSep: Char; fTrim: Boolean = false;
fQuotes: Boolean = false; QuoteChar: Char = '
"'): TStringList;
var
vI,
vOffset: Integer;
vBuffer:
String;
vOn: Boolean;
begin
Result := TStringList.Create;
vBuffer := '
';
vOffset := 0;
vOn := true;
for vI := 1
to length(fText)
do
begin
if (fQuotes
and (fText[vI] = fSep )
and vOn)
or (
not (fQuotes)
and (fText[vI] = fSep))
then
begin
if fTrim
then vBuffer := Trim(vBuffer);
if vBuffer = '
'
then vBuffer := fSep;
// !!! sonst läuft z.B. split(',**',',') auf einen Hammer...
if vBuffer[1] = fSep
then
vBuffer := Copy(vBuffer, 2, Length(vBuffer));
Result.Add(vBuffer);
vBuffer := '
';
end;
if fQuotes
then
begin
if fText[vI] = QuoteChar
then
begin
vOn :=
Not(vOn);
if Copy(fText, vI + vOffset, 2) = QuoteChar + QuoteChar
then
begin
vBuffer := vBuffer + QuoteChar;
vOffset := vOffset + 1;
end
else
begin
vOffset := 0;
end;
Continue;
end;
if (fText[vI] <> fSep)
or ((fText[vI] = fSep)
and (vOn = false))
then
vBuffer := vBuffer + fText[vI];
end else
if fText[vI] <> fSep
then
vBuffer := vBuffer + fText[vI];
end;
if vBuffer <> '
'
then
begin
if fTrim
then vBuffer := Trim(vBuffer);
Result.Add(vBuffer);
end;
end;
//Ersetzt einfache Quotes in durch Zweifache
function Prepare(Text:
string):
string;
begin
Result := StringReplace(Text, QUOTE, QUOTE + QUOTE, [rfReplaceAll]);
Result := StringReplace(Result, PQUOTE, PQUOTE + PQUOTE, [rfReplaceAll]);
end;
procedure SetParams(fDELIMITER, fCMDSIGN, fRETSIGN, fQUOTE, fPQUOTE: Char);
begin
DELIMITER := fDELIMITER;
CMDSIGN := fCMDSIGN;
RETSIGN := fRETSIGN;
QUOTE := fQUOTE;
PQUOTE := fPQUOTE;
end;
function GetCMDString(Command:
string; Params:
array of string):
string;
var
i: integer;
begin
//Befehl hinzufügen
Result := QUOTE + CMDSIGN + PQUOTE + Prepare(Command) + PQUOTE + DELIMITER;
//Alle Parameter hinzufügen
for i := 0
to length(Params) -1
do
begin
Result := Result + PQUOTE + Prepare(Params[i]) + PQUOTE + DELIMITER;
end;
//Abschließende Befehlszeichen hinzufügen
Result := Result + QUOTE + RETSIGN + CMDSIGN;
end;
function GetPartitialCMDString(Parts:
array of string; CommandBegin,
EndOfData: boolean):
string;
var
i: integer;
begin
//Wenn CommandBegin, dann wird der erste Teil als Command verwendet
if CommandBegin
then
Result := QUOTE + CMDSIGN + PQUOTE;
//Alle Teile hinzufügen
for i := 0
to length(Parts) -1
do
begin
if CommandBegin
then
Result := Result + PQUOTE + DELIMITER + PQUOTE + Prepare(Parts[i]) + PQUOTE
else
Result := Result + DELIMITER + PQUOTE + Prepare(Parts[i]) + PQUOTE
end;
//Wenn EndOfData, dann werden die abschließenden Befehlszeichen angehängt
if EndOfData
then
Result := Result + DELIMITER + QUOTE + RETSIGN + CMDSIGN;
end;
function ParseCommands(CmdLine, Buffer:
string; Commands: TStringList):
string;
var
i: integer;
CMDList: TStringList;
begin
//Comammands leeren
Commands.Clear;
try
CMDList := Split(Buffer + CmdLine, CMDSIGN, false, true, QUOTE);
//Wenn kein vollständiger Befehl vorhanden ist ...
if CMDList.Count < 1
then
begin
//... und der Buffer nicht leer ist ... (Der Befehl kann nie vollständig
//werden, wenn nicht mindestens das Befehlszeichen im Buffer ist)
if Buffer <> '
'
then
begin
//... den neuen Buffer zurückgeben und die Stringliste leeren
Result := Buffer + CmdLine;
CMDList.Clear;
end;
end
else
begin
//Wenn mindestens ein vollständiger Befehl vorhanden ist die Befehlsliste
//in einer Schleife durchgehen und ...
for i := 0
to CMDList.Count -1
do
begin
//... fals das letzte Zeichen nicht das abschließende Befehlszeichen ist
//...
if Copy(CmdList[i], length(CmdList[i]), 1) <> RETSIGN
then
begin
//... muss dies die letzte Zeile der Stringliste sein und somit ist
//auch klar, dass der letzte Befehl nicht vollständig ist. Daher wird
//die komplette letzte unvollständige Befehlszeile als neuer Buffer
//zurückgegeben
Result := QUOTE + CmdList[i];
end
else
begin
//... fals doch, dann enthält die aktuelle Zeile einen vollständigen
//Befehl und kann in der Commando Stringliste eingetragen werden
Commands.Add(Copy(CMDList[i], 1, length(CmdList[i]) -1));
end;
end;
end;
finally
CMDList.Free;
end;
end;
procedure GetLimitedCMDString(Command:
string; Params:
array of string;
Limit: integer; Parts: TStringList);
var
i: integer;
TmpCmd,
TmpPart:
string;
begin
//Die Ergebnissliste leeren
Parts.Clear;
//Einen CMDString mit dem vorgegebenen Parametern generieren
TmpCmd := GetCMDString(Command, Params);
//Das Ergebniss in einer Schleife durchgehen und immer Limit Zeichen in die
//Ergebnissliste kopieren
for i := 0
to (length(TmpCmd)
div Limit)
do
begin
TmpPart := Copy(TmpCmd, (i * Limit) +1, Limit);
if TmpPart <> '
'
then
Parts.Add(TmpPart);
end;
end;
procedure ParseParameter(Command:
string; Params: TStringList);
var
ParamList: TStringList;
begin
ParamList := TStringList.Create;
try
//Die Parameter eines Befehls zurückgeben
ParamList := Split(Command, DELIMITER, false, true, PQUOTE);
Params.Text := ParamList.Text;
finally
ParamList.Free;
end;
end;
end.