• Welcome to PlanetSquires Forums.
 

Thoughts on linked lists, hash lists, etc.

Started by Paul Squires, January 11, 2018, 11:50:21 PM

Previous topic - Next topic

Paul Squires

Hi Jose, I know you have the dictionary class but have you thought about maybe adding a lightweight single or double linked list class? I have to write one that keeps track of dynamically allocated TYPE structures so it will be a linked list that will store ANY PTR's. I will certainly donate that to the cause when complete.

I wonder what other general purpose structures like lists that would helpful?
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

Paul Squires

Working on a lightweight linked list now. I'll post the code here for everyone to critique and improve before I use it in WinFBE.
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

Paul Squires

This is also helping me test the WinFBE autocomplete code. I've already found a couple of things that I need to add.  :)
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

José Roca

Sorry for the delay. I have been busy.

The dictionary object is implemented as a hash list. One way to store UDTs is as an array of bytes. For example:


'#CONSOLE ON
#define UNICODE
#INCLUDE ONCE "Afx/CVar.inc"
USING Afx

TYPE Foo
  x AS LONG
  y AS LONG
  b AS WSTRING * 260
END type

DIM t AS Foo
t.x = 12345
t.y = 72727
t.b = "Test string"
   
DIM cv AS CVAR
cv.PutBuffer(@t, SIZEOF(t))

DIM t2 as Foo
cv.ToBuffer(@t2, SIZEOF(t))

print t2.x
print t2.y
print t2.b

PRINT
PRINT "Press any key..."
SLEEP


Paul Squires

Thanks Jose, I appreciate the byte array approach. I have been using the NEW / DELETE approach to TYPE creation / deletion and only store a reference to the TYPE instance in the list. I will try using the byte array approach to see if that works better. I think it might. I wonder though if it would also work for more complicated TYPEs that contain subs/functions/constructors/destructors.
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

José Roca

With objects like CWSTR should not work, because if you call ToBuffer to fill another instance of the TYPE the pointer of the CWSTR member of the second instance will be overwritten (causing a memory leak) and you will end having two objects pointing to the same memory location. The problem will came when the two objects will try to deallocate the same memory in their destructors.

Paul Squires

Exactly. I understand completely and it confirms what I believe as well. I will continue on the path of NEW/DELETE and only store the pointer in the linked list. It is not as elegant as storing the TYPE itself but there doesn't seem like any way to create a generic list that can hold any type of TYPE (other than using some complicated and hackish MACRO approach).
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

Paul Squires

After working on this, I have not found an easy generic way to handle different data types. Linked Lists are simple to code so there is no need for me to continue with the code I was writing. For those interested, here is a link to an FB forum post that discusses the complexities of trying to create generic lists using FB. In C++, it is trivial because templates are built into the C++ Standard Library.  https://www.freebasic.net/forum/viewtopic.php?f=8&t=23544
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

José Roca

This is why I did choose the dictionary object. As it works with variants, it can deal with almost any kind of data. The problem is that working with UDTs is a bit complex, as it involves describing the UDT using the IRecordInfo interface.

José Roca

One way to use a CWSTR or another object in a TYPE and store it in a variant, that can be added to a dictionary object, would be to use a byref variant.


'#CONSOLE ON
#define _CWSTR_DEBUG_ 1
#define UNICODE
#INCLUDE ONCE "Afx/CVar.inc"
USING Afx

TYPE Foo
  x AS LONG
  y AS LONG
  b AS CWSTR
END type

DIM t AS Foo
t.x = 12345
t.y = 72727
t.b = "Test string"
   
DIM cv AS CVAR = CVAR(@t, "BYTE")
DIM t2 AS Foo PTR = CAST(Foo PTR, cv.vd.pcVal)
print t2->x
print t2->y
print t2->b

PRINT
PRINT "Press any key..."
SLEEP