PDA

View Full Version : heapy



ReneMiner
13-10-2014, 20:56
still in progress so i can not post all of it yet,

but a small Unit of it that is just to make a Dword behave like some dynamic string-array and that unit runs pretty well already.

It's really simple so it allows to append dynamic string arrays in a straight row of pointers as lines of text.

Now this is a demo-script to test the functions of the attached unit below.

here some tasty snoop-in (Edit: attachement removed, syntax changed a little, download far below contains actual example)



Uses "console"
' needs 1.9.13/14 + latest thincore.dll

#INCLUDE "Heap_Text.tBasicU"

' ----------------------------------------------------------------------------------
' TEST Heap_Text 01:
' --------------------------

' Heap_Text does only have a few public functions


Function TBMain()

Dim hText As Heap_Text
' usually would be part of udt...

hText.Set$("Hello world") ' _.Set$() to set data
PrintL hText.Get$() ' _.Get$() to get all data at once
PrintL
' _.Add$("...", LineNumber) to add to this line
hText.Add$("...how are you all?", 1)
' _.Add$("...") to add a new line
hText.Add$("this should be a new line")

PrintL hText.Get$(1) ' _.Get$(Linenumber) to get data of a certain line
PrintL hText.Get$(hText.Lines) ' _.Lines() will get the last line-number

PrintL $CRLF & "-----------------------key to continue"
WaitKey
PrintL

hText.Set$("this is one line", 1) ' _.Set$ will kill old lines
hText.Set$("this is a line too", 2) ' line number 2 will be overwritten also
' automatic creates empty lines...
hText.Set$("and a little lower", 5)

hText.Set$("this is line 6", 6)
hText.Set$("this is line 4", 4)

Local i As Long
' loop through all lines & read out

For i = 1 To hText.Lines() ' _.Lines() returns actual count of lines
PrintL i, hText.Get$(i) ' demand a certain line
Next


PrintL $CRLF & "-----------------------key to continue"
WaitKey
PrintL

' now insert a few lines at once
hText.Add$( "Hello world" & $TAB & "This is" & $TAB & "multiline" & $TAB & "inserting", _
3, $TAB ) ' starting at the 3rd line, delimiter is $Tab


' and list all at once, delimited by $CRLF - just don't pass a line-number
PrintL hText.Get$( , $CRLF)
PrintL

PrintL
PrintL $CRLF & "-----------------------key to continue"
WaitKey
PrintL
' free lines 2, 3, 4 and 5

hText.Free(2,5) ' _.Free(startLine, EndLine)
' no endline then only startline
' no line or 0 to free all

PrintL "freed 4 lines of text" & $CRLF & "..."


hText.Add$("just to test the add$-function") ' _.Add$ to add data at the end
htext.Add$("... try to enlarge line 3", 3) ' _.Add$("...", linenumber)
hText.Add$("far down as line 11 added", 11)
hText.Set$("overwrite two lines" & $CRLF & "starting at line 8", 8, $CRLF)

For i = 1 To hText.Lines()
PrintL i, HEAP_Get( hText.GetPtr(i) )
Next

PrintL
PrintL $CRLF & "-----------------------key to continue"
WaitKey
PrintL
PrintL "free 2 more lines:"
hText.Set$("", 6) ' kill line 6
htext.Free(10) ' kill what previously was line 11


PrintL hText.Get$(,$CRLF)

hText.Free() ' kill all

PrintL $CRLF & "----------------------------key to end"
WaitKey

End Function


We have an anniversary to celebrate on wednesday:
:drink::party::occasion::clapping:

thinBasic has type-functions (http://www.thinbasic.com/community/project.php?issueid=440#note2773) for one year already

ReneMiner
14-10-2014, 09:39
One more unit "Heap_Array" - plus the base-unit "Heap_Manager".


Now what's this?

The Manager is the basetype that cares for enumerating Type-names mostly. Also for enumerating names but for another kind of data...

Heap_Array is an extended type of Heap_Manager - and that holds the only variable "_.ID" - which is a Long.

You can use a Heap_Array-type to store any array of fixed size elements or arrays of pointers to dynamic elements in unlimited dimensions.

So it's multidimensional, it's dynamic - and has only the FIX size of one Long - so can be attached to almost anything. Arrays here are any data that is a row/or multidimensional grid of fixed size elements. Even if they consist of just one element.

A Heap_Array provides you with a lot of functions onto its elements - that allows to loop through the data without the need of additional local variables and it comes with a lot of functions for easy access to your data.

some overview about the structure:



Type Heap_Array Extends Heap_Manager
ID As Long ': "slot-number"
Static DataPtr As DWord ': is your best friend

Static hDataPtrs As Dword
Static hDataTypes As Dword
Static hDataBounds As Dword ' : 3 dwords that store information about your data

Static hElements As Dword ' : they save you to dim real variables...
' elements are the single members of your stored
' data. for each slot there is a "current element"

'
' back to the static h...-Dwords. All of them hold a pointer to some heap.
' so there are 4 arrays, 3 hold dwords, 1 holds long...

' p = Ptr to your data
' t = Ptr to some heap where can read typename out
' b = Ptr to some heap where the dimensions of data are stored
' e = current element in your data-array
' 1,2,3... = slot numbers
' [] Dword
' () Long
' heap at _.hDataPtrs : "[p1][p2][p3][p5][p6][p7][p8][p9]..."
' heap at _.hDataTypes : "[t1][t2][t3][t5][t6][t7][t8][t9]..."
' heap at _.hDataBounds : "[b1][b2][b3][b5][b6][b7][b8][b9]..."
' heap at _.hElements : "(e1)(e2)(e3)(e5)(e6)(e7)(e8)(e9)..."


You see, the _.ID is just the number of the slot which is used to store information about your data.
Change the ID and you access another slot...

Pointers to dynamic subdata can be arranged either as 1-based simple row or multidimensional, however you need it.
There are 2 functions just for pointers - and the pointers themselves are treated as array-elements then.

Heap_Array provides you with a bunch of functions,


' informational
NumDataPtrs As Function ' returns total of slots (highest _.ID)
ListType As Function ' creates a list of all slots containing requested type
' creation:
SetFreeID As Function ' returns ID of a free slot and assigns it to _.ID

Create As Function ' instantly set data, returns type, sets _.DataPtr
Alloc As Function ' alloc space for data, returns type, sets _.DataPtr

BoundsBe As Function ' setup multiple Dimensions - see also Dimensions-UDT
SetUBound As Function ' setup standard-array, 1 dimensional, 1-based
' just that one don't need to pass this value twice
' access:
LayOver As Function ' returns Type, sets _.DataPtr
GetType As Function ' returns Type
GetPtr As Function ' returns pointer to heap, sets _.DataPtr

LoBound As Function ' returns lowbound of a dimension
HiBound As Function ' returns hibound of a dimension

GetNumDims As Function ' returns number of dimensions for this slot
GetDimPtr As Function ' returns pointer to dimensions-structure

' remove
Free As Function ' free this slot (_.ID)

' -- functions on 1-Based, 1-dimensional arrays only:
AppendData As Function ' returns pointer to first appended element
' makes it to be current element
' sets _.DataPtr to this element

' -- special functions for pointer-Element-arrays (DWord!)
PtrsAlloc As Function ' returns "DWord", sets _.DataPtr
PtrsFree As Function ' free noded data (at this level only)

' -- functions on all elements



ElementCount As Function ' returns number of stored elements
ElementIndex As Function ' returns index of current element (1-based)
ElementFirst As Function ' returns pointer of first element
' and makes it to be the current
' sets _.DataPtr
ElementNext As Function ' returns pointer of next element or 0 if none
' and makes it to be the current
' sets _.DataPtr
ElementLast As Function ' returns pointer of last element or 0 if none
' and makes it to be the current
' sets _.DataPtr
ElementPrevious As Function ' returns pointer to previous or 0 if none
' and makes it to be the current
' sets _.DataPtr
ElementPtr As Function ' returns pointer to certain element
' and makes it to be the current
' sets _.DataPtr


' most functions will accept an optional ID (where it makes sense), then
' it's possible to request information by passing a Long to access a slot


The ElementPtr-Function will return you the pointer to your desired element but since the count of dimensions is meant to be dynamic there is only the way to pass the single indices as string, so you'll request element(x,y,z) alike _.ElementPtr(MKL$(x,y,z))

The other element-functions allow for example nice clean readeable code as:


Dim harry as Heap_Array
'...
Local myData Like harry.GetType() At harry.ElementFirst()

While VarPtr(myData)
'...do something with current element...

SetAt( myData, harry.ElementNext ) ' please harry, do Me the favour
Wend


There are some example-testscripts included - currently Heap_Array & Heap_Manager are just a preview, it needs some fix for Type_Exists() and great were an "Alias Dword As Heap_Ptr" (see support-section (http://www.thinbasic.com/community/project.php?projectid=1)) since one can not Dim Like "aliasname".

attachement removed, see below

ReneMiner
16-10-2014, 13:37
and one more...

This time it's 2 new units one as Heap_Organized and one as organized_Data. Both depend onto each other.
Also a little polishing & makeover at the previous units.

New now: the Heap_Manager does not provide any variables but just functions to enumerate types & names. The ID As Long & Static DataPtr i changed to be members of the extending types. So it's secured that any extension of Heap_Manager can have its own type & subsets-name and all extensions use globally the same enumerations.

Now what is Heap_Organized?

At first it allows you to have an array of elements that are all different types. But all those elements need to have something in common: a very basetype that holds a little information which is common to all elements.
All elements are of different Type, so the very first property the organized_Data needs to have is an information of which type it is. At very first- so we can peek it easy out from above...
Therefor the Heap_Manager enumerates them type-names and stores them to heap. It will return a pointer where the name can be read out. So the data needs just to store this pointer - and the good thing about this is: the data "knows" by itself of what type it is. A Type-Function can check if Me is in reality some extended type etc.

Also common to organized_Data is: every element can have an arbitrary name and index that can be used to find the data as well as to compose function-names etc. So the Heap_Manager will store all names the same way as it does with types and the data just holds the pointer where to read out the name. Index we store right there - 1-Based by default but you can assign any Long you want.
To allow pre-selecting any type of data it can be flagged with some user-defined Long values, so there's also a _.Flags-property at organized_Data.

And on top of it, organized_Data is nodeable. So each can have a _.Parent (or none) and be _.Expanded (or not). So organized_Data comes with a bunch of noding-functions.

Some example script:



#MINVERSION 1.9.14.0

Uses "console"

#INCLUDE "Heap_Organized.tBasicU"

'Type Heap_Manager ' this is the very basetype
' Static hAllTypes As DWord ' store all typenames at the very basetype
' Static hAllNames As DWord ' organized data can get accessed by name
'
' EnumType As Function
' EnumName As Function
'End Type
'
'Type Heap_Organized Extends Heap_Manager
' ID As Long
' Static DataPtr As DWord ' additional Function-Result in many cases
'
' Static hDataPtrs As DWord ' stores a list of pointers, ID tells which is meant
' ' each of those pointers occupies a "slot"

' Create As Function ' create new data
' Free As Function ' free that slot and the data contained within
' GetPtr As Function ' returns Ptr, sets _.DataPtr
' GetID As Function ' returns ID of a certain name + index
'
' SetID As Function ' set Me.ID to _.ID of a certain name + index
' ' sets _.DataPtr
' FindID As Function ' returns slot number of a passed dataptr

' GetSize As Function ' returns Heap_Size for slot _.ID
' LayOver As Function ' returns type, sets _.DataPtr
' SetFreeID As Function ' to use an empty slot
' NumPtrs As Function ' total of slots

' ListType As Function ' lists all IDs of that type
' ListName As Function ' lists all IDs with that name
'
'End Type

'Type organized_Data
' pType As DWord ' this gets assigned a pointer where the type can be read out

' pName As DWord ' this will contain a pointer where a name can be read out
' Index As Long ' this is an individual index for same named data

' Flags As Long ' allow some binary switches at this level so its possible
' ' to pre-select certain objects of a special group very early
' for this example you'd probaly use flags as
' %is_a_Timer = &H00000001
' %is_a_Window = &H00000002
' %is_a_popup = &H00000004
' %always_on_top = &H....

' Parent As Long ' organized data can be noded to be a tree-structure
' Expanded As Boolean ' so is expandeable if desired

' hText As HEAP_Text ' to node dynamic any text (= 1 DWord)
' (included Unit)
' GetType As Function ' returns own type-name
' GetName As Function ' returns name if assigned

' Free As Function ' gets invoked by the slot! write this function
' for your extended types if they have noded subdata

' FindID As Function ' the data can find out which slot it's in

' ' basic noding-functions
' IsChildOf As Function ' returns true if passed ID is child of Me
' HasChildren As Function ' returns true if data has children
' ListChildren As Function ' returns list of children only ( no grandchildren! )
' ListExpanded As Function ' returns a list of all noded below thats visible
' GetTopParent As Function ' returns the parent that is noded to root
' CollapseAll As Function ' will collapse Me & all noded children
' RootDistance As Function ' returns distance from it's root-node
' RootID As Function ' returns root-ID of this tree

'End Type

Type t_Area Extends organized_Data ' your basic-user-type
X1 As Long
Y1 As Long
X2 As Long
Y2 As Long
'Backcolor As TBGL_TRGBA
'"a lot of" As Functions for positioning etc..
End Type

Type t_Timer Extends organized_Data ' timer won't need an area to cover...
Interval As Long
Enabled As Boolean
'...
End Type

Type t_Window Extends t_Area
hWnd As DWord
' ...
End Type

Type t_Button Extends t_Area
Align As Long
Enabled As Boolean
' ...
End Type



Function TBMain()

' it needs a variable of type Heap_Organized

Local horga As Heap_Organized

' virtually local create a t_window named "myWindow" at the allocated space:
Local win Like horga.Create("t_Window", "myWindow") At horga.DataPtr
' now access the "window"
win.hText.Set$("I am some window") ' normally you'd call something alike win.Init(...)

' create a layover as t_Button at allocated place instantly:
Local btn Like horga.Create("t_Button", "myButton") At horga.DataPtr
' set _.hText-property of btn
btn.hText.Set$("i am the first button")
'btn.Parent = horga.GetID("myWindow") -could instantly node this...
' (see other example)

' allocate another t_Button, place the local btn there
horga.Create("t_Button", "myButton") : SetAt( btn, horga.DataPtr )
' and access it:
btn.hText.Set$("i am the second button")
'btn.Parent = win.FindID()

' read out with a very-basetype-layover
Local data As organized_Data At 0
Local slot As Long At VarPtr(horga)

For slot = 1 To horga.NumPtrs()
SetAt( data, horga.GetPtr )
PrintL data.hText.Get$()
Next

PrintL $CRLF & "----------------------------key to continue"
WaitKey
PrintL
' there's NOT ANY GLOBAL variable- all is local, but watch this

testSub("myWindow")

testSub("myButton", 1)
testSub("myButton", 2)



PrintL $CRLF & "----------------------------key to end"
WaitKey



End Function

Sub TestSub(ByVal sName As String, _
Optional ByVal Index As Long )


Local lHeap As Heap_Organized ' need some variable of Heap_organized again...

' request type & pointer and instantly place a virtual variable onto:

Local data Like lHeap.Layover(sName, Index) At lHeap.DataPtr ' <<< whoops there it is

PrintL data.GetName(), data.Index

PrintL Heap_Get( Peek(DWord, VarPtr(data)) )
' could use "PrintL data.GetType()" as well- but it's as easy as this to retrieve a type-name

PrintL data.hText.Get$()
PrintL

End Sub


There would also be another approach simply to identify data by its pointer (since it's unque) but then i fear it gets messy when it comes to dynamically free & adding new data - so the _.ID/slot-way seems safer to me.

ReneMiner
17-10-2014, 22:44
my very first .chm-file :D

attached doc for my heapy-stuff above.

ReneMiner
11-11-2014, 14:03
still - or again - at the heap-stuff. I added another, very small unit: Heap_Stack.

It's a common stack that you can define to hold any type of (fixed-sized) data. It has only 4 functions as there are

_.Create to assign the type
_.Current to retrieve a pointer to the current element (on top of stack)
_._Push to do what it says
_._Pop to pop, sorry for the underscore but keywords as Push & Pop are somehow not available for this

it has to work with pointers so it allows any type without having to cast using MKx$() nor Memory_Get(cumbersome calculation)

they are all so small, i post them altogether including the manager-type which enables all dimensioned stacks to enumerate types due Extends...

Heap_Manager.tBasicU


#MINVERSION 1.9.14.0

' ------------------------------------------------------------------------
' "alien-function" inside this unit but i need it all the time when using heap:

Function HEAP_ReAllocByStr(ByVal hPtr As DWord, _
ByVal s As String, _
Optional ByVal allowEmptyStringAllocation As Boolean _
) As DWord
' very useful, i suggested it already...

HEAP_Free(hPtr)
Function = HEAP_AllocByStr(s, allowEmptyStringAllocation)

End Function
' ------------------------------------------------------------------------


Type Heap_Manager ' this is the very basetype
Static hAllTypes As DWord ' store all typenames at the very basetype
Static hAllNames As DWord ' organized data can get accessed by name

EnumType As Function
EnumName As Function
End Type

' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Function Heap_Manager.EnumType(ByVal sType As String, _
Optional ByVal TestExist As Boolean _
) As DWord
' returns pointer to heap where the type-name can be read out
Local i As Long

' usually this would check If Type_Exists(sType) but sadly not working correct on standard variables...
' so just check if any string-content...

If StrPtrLen(StrPtr(sType)) < 1 Then Return 0

Local vPtr() As DWord At 0

sType = Ucase$(sType)

If HEAP_Size(Me.hAllTypes) Then
ReDim vPtr(HEAP_Size(Me.hAllTypes)/4) At Me.hAllTypes
i = Array Scan vPtr Ptr, Collate Ucase, = sType
If i Then
Return vPtr(i)
Else
If TestExist Then Return 0
EndIf
Else
If TestExist Then Return 0
EndIf

Me.hAllTypes = HEAP_ReAllocByStr(Me.hAllTypes, HEAP_Get(Me.hAllTypes) & MKDWD$(0) )

ReDim vPtr(HEAP_Size(Me.hAllTypes)/4) At Me.hAllTypes
vPtr(UBound(vPtr)) = HEAP_AllocByStr(sType)

Function = vPtr(UBound(vPtr))

End Function

' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Function Heap_Manager.EnumName(ByVal sName As String, _
Optional ByVal TestExist As Boolean _
) As DWord

Local i As Long

' names (if any used) must meet file-name & variable-name requirements
' have to start with a char, no spaces, no special chars, only chars,
' numerals, underscore allowed

If StrPtrLen(StrPtr(sName)) < 1 Then Return 0

Local vPtr() As DWord At 0

If HEAP_Size(Me.hAllNames) Then
ReDim vPtr(HEAP_Size(Me.hAllNames)/4) At Me.hAllNames
i = Array Scan vPtr Ptr, Collate Ucase, = Ucase$(sName)
If i Then
Return vPtr(i)
Else
If TestExist Then Return 0
EndIf
Else
If TestExist Then Return 0
EndIf

Local lChar(StrPtrLen(StrPtr(sName))) As Byte At StrPtr(sName)

For i = 1 To UBound(lChar)
Select Case lChar(i)
Case < 48
' invalid char
Return 0
Case 48 To 57
' have to start with a char!
If i = 1 Then Return 0
Case 58 To 64
' invalid char
Return 0
Case 91, 92, 93, 94, 96
' invalid char
Return 0
Case 95
' have to start with a char!
If i = 1 Then Return 0
Case > 122
' invalid char
Return 0
End Select
Next

Me.hAllNames = HEAP_ReAllocByStr(Me.hAllNames, HEAP_Get(Me.hAllNames) & MKDWD$(0))

ReDim vPtr(HEAP_Size(Me.hAllNames)/4) At Me.hAllNames

vPtr(UBound(vPtr)) = HEAP_AllocByStr(sName)

Function = vPtr(UBound(vPtr))

End Function



Heap_Stack.tBasicU



#MINVERSION 1.9.14.0

#INCLUDE Once "Heap_Manager.tBasicU" ' the depending basetype

Type Heap_Stack Extends Heap_Manager
pData As DWord ' the actual stack at heap
pType As DWord ' the type-name can be read out at this heap_ptr

Create As Function
current As Function
_Push As Function
_Pop As Function
End Type

Function Heap_Stack.Create(ByVal sType As String) As String
' assign the type once
Me.pType = Me.EnumType(sType)
Function = HEAP_Get(Me.pType)
End Function

Function Heap_Stack.Current() As DWord
' returns pointer to top-element on this stack or 0 if none
If HEAP_Size( Me.pData ) Then
Local data Like HEAP_Get(Me.pType) At 0
Function = HEAP_End(Me.pData) - SizeOf(data) + 1
EndIf

End Function

Function Heap_Stack._Push(ByVal pData As DWord)
' pass pointer where to find the data to push
If Me.pType Then
Local data Like HEAP_Get(Me.pType) At 0
Me.pData = Heap_ReAllocByStr(Me.pData, HEAP_Get(Me.pData) & Memory_Get(pData, SizeOf(data) ))
EndIf
End Function

Function Heap_Stack._Pop()
' just call...
If Me.pType Then
Local data Like HEAP_Get(Me.pType) At 0
If HEAP_Size(Me.pData) > SizeOf(data) Then
Me.pData = Heap_ReAllocbyStr(Me.pData, HEAP_Left(Me.pData, HEAP_Size(Me.pData)-SizeOf(data)))
Else
HEAP_Free(Me.pData)
Me.pData = 0
EndIf
EndIf
End Function


Heap_Stack_test01.tBasic


#MINVERSION 1.9.14.0

Uses "console"

#INCLUDE "Heap_Stack.tBasicU"


Function TBMain()

' dim a stack
Local lStack As Heap_Stack
' create this one for type long, the same as i

Local i Like lStack.Create("Long")

' push a few values into a variable
For i = 1 To 50 Step 7
PrintL i
' and tell stack where to find data
lStack._Push( VarPtr i )
Next
PrintL

' read out from top to bottom
Local lRead Like HEAP_Get(lStack.pType) At lStack.Current()
While VarPtr(lRead)
PrintL lRead
' pop the top-value:
lStack._Pop()
SetAt( lRead, lStack.Current )
Wend


PrintL $CRLF & "----------------------------key to end"
WaitKey

End Function


Why the Stack-idea came?

I was trying something out (very succesful) to create Private variables (http://www.thinbasic.com/community/project.php?issueid=454)...(see attachement!) where i needed to emulate a function-pointer-stack...

ReneMiner
11-11-2014, 22:48
Eros, if you read this, see attachement 2 posts above.

Is your helpfile-editor able to decompile any of the following file-types:
.chm, .html, .pdf, .epub, .mobi ?

can you easy insert these to tB-documentation?

then i could support in catching up on filling empty spaces - i think there are a few that i could at least "prepare in advance" so you would just need to re-check and insert, maybe add correct links for "see also" and some keywords for the search-functions of help.