Re: [fpc-pascal]TCollection question
On Sun, Jul 06, 2003 at 04:25:15PM +0200, Marco van de Voort wrote: Is there an example of using TCollection or something (without having to write the code myself) that manages a collection of FPC style classes (objects) ? I'd like to see one, code I have written to handle a dynamic array of objects has gone out of control... (Using FPC classes here) IIRC, TCollection only stores TCollectionItem derived classes. TList is closer to what you want probably. Is there an example other than list.pp in the fcl source ? Also just for the record of knowing... I have attached datanicks.pas which hold a dynamic array of TNick ... Is this what TList already does (if so I'm wasting my time writing my own code...) ? cheers James ___ fpc-pascal maillist - [EMAIL PROTECTED] http://lists.freepascal.org/mailman/listinfo/fpc-pascal -- - - James Mills Zero Defect Software Engineers Group - ZDSEG unit dataNicks; interface uses sysUtils, Functions, tokenizerClass, nickClass; var nicks: PNick; nNicks: Integer; procedure init; procedure done; procedure addNick(data: String); procedure addNick(data: String; index: Integer); function backupNick(nick: String): TNick; procedure copyNickData(srcNick: TNick; destNick: TNick); function getNick(nick: String): Integer; procedure delNick(nick: String); function isIdentified(nick: String): Boolean; function isIdentified(nick: String; otherNick: String): Boolean; implementation procedure init; begin nNicks := 0; getMem(nicks, sizeOf(TNick) * nNicks); end; procedure done; var I: Integer; begin for I := 0 to (nNicks - 1) do begin nicks[I].free; end; freeMem(nicks); end; procedure addNick(data: String); var tokens: TTokenizer; nick: String; hops: Integer; signon: longInt; ident: String; host: String; server: String; unused: String; name: String; begin tokens := TTokenizer.Create(data); nick := tokens.nextToken; hops := strToInt(tokens.nextToken); signon := strToInt(tokens.nextToken); ident := tokens.nextToken; host := tokens.nextToken; server := tokens.nextToken; unused := tokens.nextToken; name := strip(tokens.restOfTokens); tokens.free; inc(nNicks); reAllocMem(nicks, sizeOf(TNick) * nNicks); nicks[(nNicks - 1)] := TNick.Create(nick, hops, signon, ident, host, server, unused, name); end; procedure addNick(data: String; index: Integer); var tokens: TTokenizer; nick: String; hops: Integer; signon: longInt; ident: String; host: String; server: String; unused: String; name: String; tmpNick: TNick; I: Integer; begin tokens := TTokenizer.Create(data); nick := tokens.nextToken; hops := strToInt(tokens.nextToken); signon := strToInt(tokens.nextToken); ident := tokens.nextToken; host := tokens.nextToken; server := tokens.nextToken; unused := tokens.nextToken; name := strip(tokens.restOfTokens); tokens.free; if index nNicks then begin tmpNick := backupNick(nick); nicks[index].free; nicks[index] := TNick.Create(nick, hops, signon, ident, host, server, unused, name); copyNickData(tmpNick, nicks[index]); tmpNick.free; end; end; function backupNick(nick: String): TNick; var data: String; tokens: TTokenizer; hops: Integer; signon: longInt; ident: String; host: String; server: String; unused: String; name: String; index: Integer; I: Integer; tmpNick: TNick; begin index := getNick(nick); if index -1 then begin data := nicks[index].getData; tokens := TTokenizer.Create(data); tokens.nextToken; hops := strToInt(tokens.nextToken); signon := strToInt(tokens.nextToken); ident := tokens.nextToken; host := tokens.nextToken; server := tokens.nextToken; unused := tokens.nextToken; name := strip(tokens.restOfTokens); tokens.free; tmpNick := TNick.Create(nick, hops, signon, ident, host, server, unused, name); for I := 0 to (nicks[index].numAccess - 1) do begin tmpNick.addAccess(nicks[index].getAccess(I)); end; tmpNick.addMode(nicks[index].getModes); for I := 0 to (nicks[index].numChannels - 1) do begin tmpNick.addChannel(nicks[index].getChannel(I)); end; tmpNick.setUseMsg(nicks[index].getUseMsg); tmpNick.setAutoAdd(nicks[index].getAutoAdd); backupNick := tmpNick; end else begin backupNick := nil; end; end; procedure copyNickData(srcNick: TNick; destNick: TNick); var I: Integer; begin for I := 0 to (srcNick.numAccess - 1) do begin destNick.addAccess(srcNick.getAccess(I)); end; for I := 0 to (srcNick.numChannels - 1) do begin destNick.addChannel(srcNick.getChannel(I)); end; destNick.addMode(srcNick.getModes); destNick.setUseMsg(srcNick.getUseMsg); destNick.setAutoAdd(srcNick.getAutoAdd); end; function getNick(nick: String): Integer; var I: Integer; index: Integer; begin index := -1; for I := 0 to (nNicks - 1) do begin if upperCase(nicks[I].getNick) = upperCase(nick) then begin index :=
Re: [fpc-pascal]TCollection question
IIRC, TCollection only stores TCollectionItem derived classes. TList is closer to what you want probably. Is there an example other than list.pp in the fcl source ? Also just for the record of knowing... I have attached datanicks.pas which hold a dynamic array of TNick ... Is this what TList already does (if so I'm wasting my time writing my own code...) ? Pretty much yes, but in a class wrapper. You can add and remove items, iterate through them etc. Maybe you can derive a class from TList to customize it a bit. There are two things to think of: - you yourself have to make sure that elements are properly freed, so when deleting object A, get a reference to it, delete it from the list, and then free the object. (however that can be automized in the class warpper) - The internal list has two counters, instead of just nNicks. One (capacity) is the reserved space, the other (count) is the amount of elements filled. This avoids too many memory fragmenting reallocs. (but that's better, not worse) I learned to use the classes from code snippets written for Delphi. There is FCL documentation somewhere (and it will be in the next full release), but I couldn't find a recent version so fast. So I put down a very old version (April 2002) on the web here: www.stack.nl/~marcov/fcl.pdf it at least describes the tlist methods. ___ fpc-pascal maillist - [EMAIL PROTECTED] http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal]TCollection question
On Sun, Jul 06, 2003 at 05:11:17PM +0200, Marco van de Voort wrote: which hold a dynamic array of TNick ... Is this what TList already does (if so I'm wasting my time writing my own code...) ? Pretty much yes, but in a class wrapper. You can add and remove items, iterate through them etc. Maybe you can derive a class from TList to customize it a bit. However TList by itself would work though ? Basically yes. But derive it anyway, in case you want to extend it later. - you yourself have to make sure that elements are properly freed, so when deleting object A, get a reference to it, delete it from the list, and then free the object. (however that can be automized in the class warpper) Is this all done and automated in TList ? No. So you have to that yourself. This because TList can also store pointers to records, which don't have to be finalised. So deallocation is still manual. But it is trivial. Assume you want to delete entry 3, assuming that variable TheList is the TList: var t : MyObjectType t:=MyObjectType(TheList[3]); TheList.delete(3); t.free; You can solve it like this: (untested) type tmyTList = class TList public procedure DeleteCompletely(index :Integer); end; procedure tmyTList.DeleteCompletely(index: Integer); var t : MyObjecType; begin t:=MyObjectType(Items[3]); delete(3); if tNIL t.free; end; See TList as a versatile baseclass to quickly build a dedicated, very easy to use container on top of. There is FCL documentation somewhere (and it will be in the next full release), but I couldn't find a recent version so fast. So I put down a very old version (April 2002) on the web here: www.stack.nl/~marcov/fcl.pdf I think it's here also in html format: http://www.nl.freepascal.org/docs-html/fcl/classes/tlist.html That's the place I meant yes. ___ fpc-pascal maillist - [EMAIL PROTECTED] http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal]TCollection question
On Sun, Jul 06, 2003 at 05:31:59PM +0200, Marco van de Voort wrote: On Sun, Jul 06, 2003 at 05:11:17PM +0200, Marco van de Voort wrote: which hold a dynamic array of TNick ... Is this what TList already does (if so I'm wasting my time writing my own code...) ? Pretty much yes, but in a class wrapper. You can add and remove items, iterate through them etc. Maybe you can derive a class from TList to customize it a bit. However TList by itself would work though ? Basically yes. But derive it anyway, in case you want to extend it later. In this case then as I've both read your replies and the webpage about TList I shall extend it :) That'll probably be the best option. Right ? Thanks for your prompt help, I dunno why I'm coding at 0140 in the bloody morning but anyway :) cheers James - you yourself have to make sure that elements are properly freed, so when deleting object A, get a reference to it, delete it from the list, and then free the object. (however that can be automized in the class warpper) Is this all done and automated in TList ? No. So you have to that yourself. This because TList can also store pointers to records, which don't have to be finalised. So deallocation is still manual. But it is trivial. Assume you want to delete entry 3, assuming that variable TheList is the TList: var t : MyObjectType t:=MyObjectType(TheList[3]); TheList.delete(3); t.free; You can solve it like this: (untested) type tmyTList = class TList public procedure DeleteCompletely(index :Integer); end; procedure tmyTList.DeleteCompletely(index: Integer); var t : MyObjecType; begin t:=MyObjectType(Items[3]); delete(3); if tNIL t.free; end; See TList as a versatile baseclass to quickly build a dedicated, very easy to use container on top of. There is FCL documentation somewhere (and it will be in the next full release), but I couldn't find a recent version so fast. So I put down a very old version (April 2002) on the web here: www.stack.nl/~marcov/fcl.pdf I think it's here also in html format: http://www.nl.freepascal.org/docs-html/fcl/classes/tlist.html That's the place I meant yes. ___ fpc-pascal maillist - [EMAIL PROTECTED] http://lists.freepascal.org/mailman/listinfo/fpc-pascal -- - - James Mills Zero Defect Software Engineers Group - ZDSEG ___ fpc-pascal maillist - [EMAIL PROTECTED] http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal]TCollection question
Actually Michael, Could you possibly spare 5 mins and give a really simple example of a TList descandent ? I'm a tad confused here, (too slowly getting anywhere)... Thank you :) cheers James ___ fpc-pascal maillist - [EMAIL PROTECTED] http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal]TCollection question
Why not use a TObjectList?? IIRC that is available. In unit Contnrs.pas. It will do a lot more for you. It can 'own' the objects, and therefore free you from needing to manage them. Simple descendent (typed at speed, with no testing): N.B. This is a WRAPPER because it allows the programmer more control over the interface to the class. However a descendent would work the same way pretty much. You'd probably just alter the 'Add' to 'AddXXX' so as to not clash with 'Add' from TList. Otherwise you would hide the method and make in unavailable. This wrapper is really usefull... I use this basic design all the time!! TMyListItemClass = class; {your class to store} TMyList = class private FList: TList; protected procedure SetItem( Index: integer; Value: TMyListItemClass); function GetItem(Index: integer): TMyListItemClass; public Constructor Create; virtual; Destructor Destroy; override; function Add(AItem: TMyListItemClass): integer; procedure Delete( AIndex: integer ); function Count: integer; property Items[Index: integer]: TMyListItemClass read GetItem write SetItem; end; procedure SetItem( Index: integer; Value: TMyListItemClass); begin FList[Index] := Value; end; function GetItem(Index: integer): TMyListItemClass; begin Result := TMyListItemClass(FList[Index] ); end; Constructor Create; virtual; begin FList := TList.Create; end; Destructor Destroy; override; begin {don't forget some code to empty list} FList.Free; inherited; end; function Add(AItem: TMyListItemClass): integer; begin result := FList.Add(AItem); end; procedure Delete( AIndex: integer ); begin FList.Delete(AIndex); end; function Count: integer; begin Result := FList.Count; end; - Original Message - From: James Mills [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Sunday, July 06, 2003 4:56 PM Subject: Re: [fpc-pascal]TCollection question Actually Michael, Could you possibly spare 5 mins and give a really simple example of a TList descandent ? I'm a tad confused here, (too slowly getting anywhere)... Thank you :) cheers James ___ fpc-pascal maillist - [EMAIL PROTECTED] http://lists.freepascal.org/mailman/listinfo/fpc-pascal ___ fpc-pascal maillist - [EMAIL PROTECTED] http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal]TCollection question
On Sun, Jul 06, 2003 at 10:38:28PM +0100, Matt and Lisa Emson wrote: Why not use a TObjectList?? IIRC that is available. In unit Contnrs.pas. It will do a lot more for you. It can 'own' the objects, and therefore free you from needing to manage them. Simple descendent (typed at speed, with no testing): N.B. This is a WRAPPER because it allows the programmer more control over the interface to the class. However a descendent would work the same way pretty much. You'd probably just alter the 'Add' to 'AddXXX' so as to not clash with 'Add' from TList. Otherwise you would hide the method and make in unavailable. This wrapper is really usefull... I use this basic design all the time!! A question about your basic-design and using TList (and descandents in general)... Could I not do this: TMyList = class(TList); . . . And thereby extend the basic TList class into a custom List ? The way you use TList is as a private variable in a generic class. cheers James TMyListItemClass = class; {your class to store} TMyList = class private FList: TList; protected procedure SetItem( Index: integer; Value: TMyListItemClass); function GetItem(Index: integer): TMyListItemClass; public Constructor Create; virtual; Destructor Destroy; override; function Add(AItem: TMyListItemClass): integer; procedure Delete( AIndex: integer ); function Count: integer; property Items[Index: integer]: TMyListItemClass read GetItem write SetItem; end; procedure SetItem( Index: integer; Value: TMyListItemClass); begin FList[Index] := Value; end; function GetItem(Index: integer): TMyListItemClass; begin Result := TMyListItemClass(FList[Index] ); end; Constructor Create; virtual; begin FList := TList.Create; end; Destructor Destroy; override; begin {don't forget some code to empty list} FList.Free; inherited; end; function Add(AItem: TMyListItemClass): integer; begin result := FList.Add(AItem); end; procedure Delete( AIndex: integer ); begin FList.Delete(AIndex); end; function Count: integer; begin Result := FList.Count; end; - Original Message - From: James Mills [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Sunday, July 06, 2003 4:56 PM Subject: Re: [fpc-pascal]TCollection question Actually Michael, Could you possibly spare 5 mins and give a really simple example of a TList descandent ? I'm a tad confused here, (too slowly getting anywhere)... Thank you :) cheers James ___ fpc-pascal maillist - [EMAIL PROTECTED] http://lists.freepascal.org/mailman/listinfo/fpc-pascal ___ fpc-pascal maillist - [EMAIL PROTECTED] http://lists.freepascal.org/mailman/listinfo/fpc-pascal -- - - James Mills Zero Defect Software Engineers Group - ZDSEG ___ fpc-pascal maillist - [EMAIL PROTECTED] http://lists.freepascal.org/mailman/listinfo/fpc-pascal