grendel-1.0.0a7/backup/
grendel-1.0.0a7/bin/
grendel-1.0.0a7/boards/
grendel-1.0.0a7/clans/
grendel-1.0.0a7/documentation/todo/
grendel-1.0.0a7/help/
grendel-1.0.0a7/logs/
grendel-1.0.0a7/players/
grendel-1.0.0a7/progs/
grendel-1.0.0a7/races/
grendel-1.0.0a7/src/contrib/
grendel-1.0.0a7/src/modules/speller/
grendel-1.0.0a7/src/modules/status/
grendel-1.0.0a7/src/tests/
grendel-1.0.0a7/src/tests/dunit/
{
	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.