Author Topic: StringList Object  (Read 7215 times)

0 Members and 1 Guest are viewing this topic.

Offline rdc

  • Pentium
  • *****
  • Posts: 1495
  • Karma: 140
  • Yes, it is me.
    • View Profile
    • Clark Productions
StringList Object
« on: July 08, 2009 »
I posted this as example code on the FB forum, but I got to thinking that this is a handy little object to use when you want to manipulate string lists. Could be used to manage message lists and such.

Here is the code so far. I tested it some, but there may be problems lurking in there somewhere. Use -exx until you feel confident it is working properly.

Code: [Select]
' Basic String List Object
' Richard D. Clark
' Use at your own risk.
' Public Domain
' ================================================================
'Wrap out object in a custom namespace.
Namespace strlist

'Create a NULL values.
#Ifndef NULL
#Define NULL 0
#EndIf

'Create a boolean type.
enum sbool
FALSE = 0
TRUE = Not FALSE
End Enum

Type stringlist
Private:
_listcount As Integer 'The number of items in list.
_list As ZString Ptr Ptr 'List of pointers to zstrings.
Declare Sub _DestroyList () 'Used to clear the pointer list.
Declare function _AddItemToList(item As String) As sbool 'Adds a new item to the list.
Public:
Declare Destructor () 'Used to clean up list, calls DestroyList. Used when object goes out of scope.
Declare Property ListCount () As Integer 'Returns the number of items in list.
Declare Function LoadFromFile (fname As String) As sbool 'Loads data from file, loads into list.
Declare function AddItem (item As String) As sbool 'Adds an item to the list.
Declare Function GetItem (index As Integer) As String 'Returns list item based on index.
Declare Sub ClearList () 'Resets list. Calls DestroyList.
End Type

'Destroys the list, if any.
Sub stringlist._DestroyList ()
'Make sure we have some items in the list.
If _list Then
For i As Integer = _listcount - 1 To 0
'Delete each item in list.
DeAllocate _list[i]
Next
'Delete the list.
DeAllocate _list
'Set the list ptr to null.
_list = NULL
'Reset the list count.
_listcount = 0
EndIf
End Sub

'This adds an item to the string list.
function stringlist._AddItemToList(item As String) As sbool
Dim As Integer itemlen, lcount
Dim ret As sbool = TRUE

'We'll need this for the zstring.
itemlen = Len(item)
'Make sure we have a string value. Can't add null string.
If itemlen > 0 Then
'Get the current list count.
lcount = _listcount
'Increment the list count.
lcount += 1
'Add a new item to the list.
_list = ReAllocate (_list, lcount * SizeOf (ZString Ptr))
'Make sure we have a valid pointer.
If _list <> NULL Then
'Create a new zstring.
_list[lcount - 1] = Allocate(itemlen + 1) 'Add a space for the null terminator.
'Make sure we have a valid pointer.
If _list[lcount - 1] <> NULL Then
'Set the list item text.
*_list[lcount - 1] = item
'Save the current list count.
_listcount = lcount
Else
'Set the return value.
ret = FALSE
EndIf
Else
'Set the return value.
ret = FALSE
EndIf
Else
ret = FALSE
EndIf

Return ret
End Function

'This will be called when object goes out of scope. Needed to clean up.
Destructor stringlist ()
_DestroyList
End Destructor

'Returns the current number of items in list.
Property stringlist.ListCount () As Integer
Return _listcount
End Property

'Adds an item to the list. Wll create list if not created. Returns true if Item was successfully added.
Function stringlist.AddItem(item As String) As sbool
Return _AddItemToList(item)
End Function

'Loads a list of items from a file. Clears current list, if any.
Function stringlist.LoadFromFile (fname As String) As sbool
Dim ret As sbool = TRUE
Dim instring As String

'Reset the current state of the object.
_DestroyList
'Make sure we get a file name.
If Len(fname) > 0 Then
'Get a file handle.
Dim fh As Integer = FreeFile
'make sure we can open the file.
If Open (fname For Input As #fh) = 0 Then
Do While Not Eof(fh)
'Load up each item in the file.
Line Input #fh, instring
If Len(instring) > 0 Then
'Add the item to the list.
If _AddItemToList(instring) = FALSE Then
'Set the return value.
ret = FALSE
'Can't go on since we have some memory problem.
Exit Do
EndIf
EndIf
Loop
'Close file.
Close #fh
Else
ret = FALSE
EndIf
Else
ret = FALSE
EndIf
'If ret = false, clean up any partial list that may have been created.
If ret = FALSE Then
_DestroyList
EndIf
'Return the result. True = list created, False = some error.
Return ret
End Function

'Gets an item from the list.
Function stringlist.GetItem (index As Integer) As String
Dim ret As String = ""

'Make sure we have a valid list.
If _list Then
'Make sure index is within bounds.
If (index >= 0) And (index <= _listcount - 1) Then
ret = *_list[index]
EndIf
End If

Return ret
End Function

'Clear current list.
Sub stringlist.ClearList()
_DestroyList
End Sub

End Namespace

'Set the namespace.
Using strlist
 
'Create a new string list object.
Dim myList As stringlist
Dim flname As String = "items.txt"

'Load in some items.
Print "Loading some items from file "; flname; "."
If myList.LoadFromFile(flname) = FALSE Then
Print "Could not load items from "; flname; "."
Else
'Print out the number of items.
Print "Number of list items: " & myList.ListCount
'Print out each item.
For i As Integer = 0 To myList.ListCount - 1
Print i & ": ";myList.GetItem(i)
Next
Print
Print "Add new item to list using AddItem member: Item6."
Print
'Add an item to the list.
If myList.AddItem("Item6") = FALSE Then
Print "Could not add item to list."
EndIf
'Print out the number of items.
Print "Number of list items: " & myList.ListCount
'Print out each item.
For i As Integer = 0 To myList.ListCount - 1
Print i & ": ";myList.GetItem(i)
Next
Print
Print "Calling ClearList member function."
'Clear the list.
myList.ClearList
'Print out the number of items.
Print "Number of list items after clear: " & myList.ListCount
Print
'Try an get a nonexistent item.
Print "Lets see what happens when we try to get an item from a cleared list:"
Print "Item: ";myList.GetItem(0)
Print "Should be empty string."
Print
Print "Lets add some items to empty list using AddItem."
Print
For i As Integer = 1 To 10
If myList.AddItem("Item" & i) = FALSE Then
Print "Could not add item to list."
Exit For
Else
Print myList.GetItem(i - 1); " added."
EndIf
Next
Print
'Print out the number of items.
Print "Number of list items: " & myList.ListCount
Print
'Print out each item.
For i As Integer = 0 To myList.ListCount - 1
Print i & ": ";myList.GetItem(i)
Next

EndIf
Print
Print "Press any key."
Sleep

Output:

Quote
Loading some items from file items.txt.
Number of list items: 5
0: Item1
1: Item2
2: Item3
3: Item4
4: Item5

Add new item to list using AddItem member: Item6.

Number of list items: 6
0: Item1
1: Item2
2: Item3
3: Item4
4: Item5
5: Item6

Calling ClearList member function.
Number of list items after clear: 0

Lets see what happens when we try to get an item from a cleared list:
Item:
Should be empty string.

Lets add some items to empty list using AddItem.

Item1 added.
Item2 added.
Item3 added.
Item4 added.
Item5 added.
Item6 added.
Item7 added.
Item8 added.
Item9 added.
Item10 added.

Number of list items: 10

0: Item1
1: Item2
2: Item3
3: Item4
4: Item5
5: Item6
6: Item7
7: Item8
8: Item9
9: Item10

Press any key.

Input text file, items.txt:

Quote
Item1
Item2
Item3
Item4
Item5

Could be expanded to include a sort function, maybe an insert function and probably some other things as well.

Offline benny!

  • Senior Member
  • DBF Aficionado
  • ********
  • Posts: 4384
  • Karma: 228
  • in this place forever!
    • View Profile
    • bennyschuetz.com - mycroBlog
Re: StringList Object
« Reply #1 on: July 08, 2009 »
Had a quick view through the source and I have a general question- is this
freebasic approach to support objects ? Very interesting to see...

Since I do not use FB I did not test it - looks useful though. I just would
suggest to seperate the object including its methods in a seperate include
file.

Nevertheless, thanks for sharing!
[ mycroBLOG - POUET :: whatever keeps us longing - for another breath of air - is getting rare ]

Challenge Trophies Won:

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: StringList Object
« Reply #2 on: July 08, 2009 »
This reminds me of those old classic text adventure games.
Types are quite versatile, as ive been finding out and very different to the ones used in Blitz. And as I'm slowly reading up on C++, are you using the types as a class structure?
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline rdc

  • Pentium
  • *****
  • Posts: 1495
  • Karma: 140
  • Yes, it is me.
    • View Profile
    • Clark Productions
Re: StringList Object
« Reply #3 on: July 08, 2009 »
Had a quick view through the source and I have a general question- is this
freebasic approach to support objects ? Very interesting to see...

Yes, this is the object model of FreeBasic. No inheritance though.

Quote
Since I do not use FB I did not test it - looks useful though. I just would
suggest to seperate the object including its methods in a seperate include
file.

Yes, normally I would create this as an include file, which is the approach I will be taking with the Screen Object.

Quote
Nevertheless, thanks for sharing!

Thanks for the comments.

Offline rdc

  • Pentium
  • *****
  • Posts: 1495
  • Karma: 140
  • Yes, it is me.
    • View Profile
    • Clark Productions
Re: StringList Object
« Reply #4 on: July 08, 2009 »
This reminds me of those old classic text adventure games.
Types are quite versatile, as ive been finding out and very different to the ones used in Blitz. And as I'm slowly reading up on C++, are you using the types as a class structure?

Yes. FB doesn't support inheritance though.

Offline rdc

  • Pentium
  • *****
  • Posts: 1495
  • Karma: 140
  • Yes, it is me.
    • View Profile
    • Clark Productions
Re: StringList Object
« Reply #5 on: July 08, 2009 »
One thing I realize I left out was a RemoveItem method. I'll need to add that in.

Offline rdc

  • Pentium
  • *****
  • Posts: 1495
  • Karma: 140
  • Yes, it is me.
    • View Profile
    • Clark Productions
Re: StringList Object
« Reply #6 on: July 08, 2009 »
This has turned out to be a fun little project. I dug up my docs on the FreePascal TStringList (clone of Delphi's class) and decided to see how much of that I could implement in this little object. I have most of the methods implemented, but I am still trying to figure out the others. I'll post an update when I get it finished enough to try out. :)


Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: StringList Object
« Reply #7 on: July 08, 2009 »
Might be worth checking out .NET's List class to see what other methods might be useful
http://msdn.microsoft.com/en-us/library/d9hw1as6.aspx
It's very powerful and I use it all the time.

Jim
Challenge Trophies Won:

Offline rdc

  • Pentium
  • *****
  • Posts: 1495
  • Karma: 140
  • Yes, it is me.
    • View Profile
    • Clark Productions
Re: StringList Object
« Reply #8 on: July 09, 2009 »
Thanks Jim, I'll take a look at it.

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: StringList Object
« Reply #9 on: July 09, 2009 »
I'd suggest to allocate some "spare space" so you don't have to reallocate the list with every 'AddItem'.
Challenge Trophies Won:

Offline rdc

  • Pentium
  • *****
  • Posts: 1495
  • Karma: 140
  • Yes, it is me.
    • View Profile
    • Clark Productions
Re: StringList Object
« Reply #10 on: July 12, 2009 »
FB StringList v.0.1

This is a FreeBsic implementation of a StringList similiar to the Delphi/FP TStringList class. The StringList manages a list of strings, allowing you to load and save strings, move strings around and sort strings.

You can grab it on my Skydrive:

stringlistv01

The package includes the bi file, manual and example programs. I haven't tested this a whole lot, so it is strongly recommended that you compile this with -exx until you feel confident it is working properly.

I have some ideas of things to add to this, but it has enough functionality now to be useful. Any feedback is appreciated, especially if it breaks.

Offline rdc

  • Pentium
  • *****
  • Posts: 1495
  • Karma: 140
  • Yes, it is me.
    • View Profile
    • Clark Productions
Re: StringList Object
« Reply #11 on: July 13, 2009 »
I thought I would stress test this a little and see how long it would take to add a million strings to a list. On my old NT box it took 6.5 seconds. On my Vista box it 2.5 seconds. Not bad performance imo.

Here is the code I used:

Code: [Select]
' StringList Test Program
' Richard D. Clark
' Use at your own risk.
' Public Domain
' Stress Test: Add a million strings to list.
' ================================================================
'Include the stringlist.
#Include "stringlist.bi"

'Set the namespace.
Using strlist
 
'Create a new string list object.
Dim myList As stringlist
Dim idx As Integer
Dim ok As sbool
Dim As Double t1, t2

'Add a million strings.
Print "Lets add a million strings."
Print
t1 = Timer
For i As Integer = 1 To 1000000
idx = myList.Add("Item" & i)
If  idx = -1 Then
Print "Could not add item to list."
Exit For
EndIf
Next
t2 = Timer
Print "Elapsed time: " & t2 - t1
Print "List count is " & myList.Count & "."
Print
Print "Saving file to amill.txt"
ok = myList.SaveToFile("amill.txt")
If ok = FALSE Then
Print "Could not save file."
Else
Print "File saved."
EndIf
Print
Print "Press any key."
Sleep

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: StringList Object
« Reply #12 on: July 13, 2009 »
For comparism I tried adding 1.000.000 Strings to a QStringList on my Intel Core2 3GHz which takes ~220ms.
Here most of the time goes into Ascii/Unicode-Conversion.
When the string is already available in Unicode-Format it takes just 60ms.
Challenge Trophies Won:

Offline rdc

  • Pentium
  • *****
  • Posts: 1495
  • Karma: 140
  • Yes, it is me.
    • View Profile
    • Clark Productions
Re: StringList Object
« Reply #13 on: July 13, 2009 »
No big surprise there. FB's strings are probably less efficient than the C++ string class and there isn't much optimization going on in the compiler or in my code. I think it will be plenty fast enough for most applications; you are probably not going to be manipulating a million strings too often. :)


Offline rdc

  • Pentium
  • *****
  • Posts: 1495
  • Karma: 140
  • Yes, it is me.
    • View Profile
    • Clark Productions
Re: StringList Object
« Reply #14 on: July 14, 2009 »
I updated the Stringlist to v. 0.1.1. I ran into problems with the sbool Enum and replaced it with a define for the True/False values. (So much for being clever.) I had to change the methods that were using the sbool type to Integers. Not a bit change and should be easy to correct in your code if you happen to be using this. I updated the manual, example programs and bumped the internal version to 0.1.1.

You can get it here.