PDA

View Full Version : Removing data from a pointer



Brainer
13-01-2008, 06:27 AM
Hello. :)

I've found this code somewhere and I'm going to use it my engine:

type
{ .: TDArray :. }
// By Tom Nyudens
TDArray = class(TObject)
private
{ Private declarations }
FCount: Integer;
procedure SetCount(C: Integer);
protected
{ Protected declarations }
FData: Pointer;
FItemSize: Integer;
procedure GetItem(I: Integer; var Result);
procedure SetItem(I: Integer; var Value);
public
{ Public declarations }
constructor Create(); virtual;
destructor Destroy(); override;

procedure DeleteItem(I: Integer);

property ItemSize: Integer read FItemSize;
property Count: Integer read FCount write SetCount;
property Data: Pointer read FData write FData;
end;

{ ... }

{ TDArray }

constructor TDArray.Create;
begin
inherited Create();

FItemSize := 1;
Count := 0;
end;

procedure TDArray.DeleteItem(I: Integer);
var
P: Pointer;
begin
if (I >= Count) then
raise Exception.Create('Array index out of bounds.')
else begin
P := FData;
Inc(Integer(P), I * FItemSize);
ZeroMemory(@P, FItemSize);
CopyMemory(FData, @P, FItemSize);
end;
end;

destructor TDArray.Destroy;
begin
FreeMem(FData, FCount * FItemSize);

inherited Destroy();
end;

procedure TDArray.GetItem(I: Integer; var Result);
var
P: Pointer;
begin
if (I >= Count) then
raise Exception.Create('Array index out of bounds.')
else begin
P := FData;
Inc(Integer(P), I * FItemSize);
CopyMemory(@Result, P, FItemSize);
end;
end;

procedure TDArray.SetCount(C: Integer);
begin
FCount := C;
ReallocMem(FData, FCount * FItemSize);
end;

procedure TDArray.SetItem(I: Integer; var Value);
var
P: Pointer;
begin
if (I >= Count) then
SetCount(I + 1);
P := FData;
Inc(Integer(P), FItemSize * I);
CopyMemory(P, @Value, FItemSize);
end;


Everything works fine except the DeleteItem procedure (which is written by me). It seems to delete the data from the pointer, but when I try to add a new item, I've got an AV. :?

How do I delete something from a pointer without touching the rest of data stored in this pointer?

Thank you in advance.

CheGueVerra
13-01-2008, 07:07 AM
I think that you should read about TList ... It does what you want, with a little tweak here and there

The containers classes that come with D7 are pretty cool once you get used to them.

BTW from the sdlsprites source code



TSpriteList = class( TList )
protected
function Get( Index : Integer ) : TSprite;
procedure Put( Index : Integer; Item : TSprite );
public
property Items[ Index : Integer ] : TSprite read Get write Put; default;
end;


CheGueVerra

Brainer
13-01-2008, 09:55 AM
I think that you should read about TList ... It does what you want, with a little tweak here and there


I know what TList is. I use it very often in my project. But I'd like to learn about removing data from a pointer. Do you have any tips?

CheGueVerra
13-01-2008, 01:03 PM
I didn't know you wanted to do it the hard way 8)

I've been working on my first game all night, so I'm tired, I'll set up a POC tomorrow.

CheGueVerra

Mirage
13-01-2008, 02:19 PM
P := FData;
Inc(Integer(P), I * FItemSize);
ZeroMemory(@P, FItemSize);
CopyMemory(FData, @P, FItemSize);

What should do this code?
Actually it fills the item to delete with zeros and copies these fresh zeros to stack (variable P is in stack). Of course this generates an AV.

May be this code will do the job:


ItemAdress := FData;
Inc(Integer(ItemAdress), I * FItemSize); // pointer to item to delete
NextItemAdress := ItemAdress;
Inc(Integer(NextItemAdress), FItemSize); // pointer to next item
Move(NextItemAdress^, ItemAdress^, (Count-I-1) * FItemSize); // Move the rest of data to deleting item's place

And why you are using windows-dependent procedures such as ZeroMemory and CopyMemory? There are crossplatform procedures FillChar and Move.

Brainer
13-01-2008, 06:51 PM
Thanks! :D It works. :)