{
Delphi IMC3 Client - Packet type and support routines
Based on client code by Samson of Alsherok.
$Id: imc3_packet.pas,v 1.1 2003/12/12 13:19:55 druid Exp $
}
unit imc3_packet;
interface
uses
Classes;
type
GPacket_I3 = class
public
original_msg : string;
packet_type : string;
ttl : integer;
originator_mudname : string;
originator_username : string;
target_mudname : string;
target_username : string;
fields : TList;
private
function listToString(list : TList; indent : integer = 0) : string;
published
function toString() : string;
end;
function parsePacket(msg : string) : GPacket_I3;
implementation
uses
SysUtils,
Contnrs,
StrUtils,
util,
dtypes;
function GPacket_I3.listToString(list : TList; indent : integer = 0) : string;
var
i : integer;
s : string;
begin
s := '';
for i := 0 to list.Count - 1 do
begin
if (TObject(list[i]) is GString) then
s := s + (DupeString(' ', indent) + '- ' + GString(list[i]).value) + #13#10
else
if (TObject(list[i]) is TList) then
s := s + listToString(list[i], indent + 4);
end;
Result := s;
end;
function GPacket_I3.toString() : string;
begin
Result := listToString(fields);
end;
function parsePacket(msg : string) : GPacket_I3;
var
packet : GPacket_I3;
backslash, quote : boolean;
count : array[1..256] of integer;
len, left, right : integer;
s : string;
stack : TObjectStack;
list : TList;
begin
backslash := false;
quote := false;
for left := 1 to 256 do count[left] := 0;
packet := GPacket_I3.Create();
stack := TObjectStack.Create();
list := TList.Create();
left := 1;
right := 1;
len := length(msg);
while (right <= len) do
begin
while (right <= len) do
begin
case msg[right] of
'(': if (not quote) then
begin
inc(count[ord('(')]);
inc(left);
end;
')': if (not quote) then
begin
inc(count[ord(')')]);
inc(left);
end;
'{': if (not quote) then
begin
inc(count[ord('{')]);
inc(left);
stack.Push(list);
list.Add(TList.Create());
list := list[list.Count - 1];
end;
'}': if (not quote) then
begin
inc(count[ord('}')]);
inc(left);
if (stack.Peek() <> nil) then
list := TList(stack.Pop());
end;
'[': if (not quote) then
begin
inc(count[ord('[')]);
inc(left);
stack.Push(list);
list.Add(TList.Create());
list := list[list.Count - 1];
end;
']': if (not quote) then
begin
inc(count[ord(']')]);
inc(left);
if (stack.Peek() <> nil) then
list := TList(stack.Pop());
end;
'\': backslash := not backslash;
'"': if (backslash) then backslash := false else quote := not quote;
',',
':': begin
if (quote or backslash) then
begin
inc(right);
continue;
end;
if (count[ord('(')] <> count[ord(')')]) then
break;
if (count[ord('{')] <> count[ord('}')]) then
break;
if (count[ord('[')] <> count[ord(']')]) then
break;
end;
end;
inc(right);
end;
s := MidBStr(msg, left, right - left);
if (length(s) > 0) then
list.Add(GString.Create(removeQuotes(s)));
inc(right);
left := right;
end;
packet.fields := TList.Create();
packet.fields.Assign(list[0]);
if (packet.fields.count < 6) then
begin
packet.packet_type := 'error';
packet.fields.Clear;
//('Invalid packet ' + msg);
end
else
begin
packet.packet_type := GString(packet.fields[0]).value;
packet.ttl := StrToIntDef(GString(packet.fields[1]).value, 0);
packet.originator_mudname := GString(packet.fields[2]).value;
packet.originator_username := GString(packet.fields[3]).value;
packet.target_mudname := GString(packet.fields[4]).value;
packet.target_username := GString(packet.fields[5]).value;
end;
packet.original_msg := msg;
Result := packet;
end;
end.