View Full Version : String-in-String-Pointers?
ReneMiner
25-03-2013, 15:08
Today I need some idea or advice how to get the following done:
I'm creating own UI for my current app. Now I want to create a listbox-alike control that shall be multiple usable and show different arrays of strings.
So for example the box is supposed to show a list of files, stored to
Dim sFile() as String
and the next time/another listbox is to show a list of sCountries() or sNames() or whatever. The problem is, how can I store a pointer to the correct array, so the listbox-drawing-routine "knows" which array and how many items to fill in, since the arrays are all dynamic string-arrays and they might change their location in memory when redimensioned?
Is there a cool way alike calling functions? - So I could store the arrays name (!) in another string like this:
'...
Gadget(%gListboxFile).ArrayToUse = "sFile()"
Gadget(%gListboxName).ArrayToUse = "sName()"
'...
Sub DrawListbox(Byval Index as Long)
Static i as Long
' -- pseudo-code:
Local sString() Alias Gadget(Index).ArrayToUse As String
For i = 1 to Ubound(sString)
PrintL sString(i)
Next i
End Sub
ErosOlmi
26-03-2013, 00:04
Wow Renč, you always find some interesting ways of doing things :D
Alias of a variable name using a string is something I really like.
Do not know how to implement but I like the idea!
Maybe in near future ... who knows
Back to what could be done right now, it comes to my mind 2 quick ways:
Uses "Console"
Dim sFile(2) As String = "123", "456"
Dim sName(3) As String = "ABC", "DEF", "EFG"
'--------------------------------------------------------------
'---Method 1: just pass the string array
'--------------------------------------------------------------
Sub DrawListbox_Method1(ByRef sString() As String)
Static i As Long
PrintL "Inside function: " & Function_Name
For i = 1 To UBound(sString)
PrintL i, sString(i)
Next '<<<---Do not indicate for variable, thinBasic knows it
End Sub
DrawListbox_Method1(sFile)
DrawListbox_Method1(sName)
'--------------------------------------------------------------
'---Method 2: pass a string representing the name and then SELECT CASE ... using the name
' thinBasic will Declare just one sString that will fall into the CASE
'--------------------------------------------------------------
Sub DrawListbox_Method2(ByVal sArrayName As String)
Static i As Long
Dim InvalidName As Boolean
PrintL "Inside function: " & Function_Name
Select Case Ucase$(sArrayName)
Case "SFILE"
Dim sString(UBound(sFile)) As String At VarPtr(sFile(1))
Case "SNAME"
Dim sString(UBound(sName)) As String At VarPtr(sName(1))
Case Else
InvalidName = %TRUE
End Select
If Not InvalidName Then
For i = 1 To UBound(sString)
PrintL i, sString(i)
Next '<<<---Do not indicate for variable, thinBasic knows it
Else
PrintL "Variable " & sArrayName & " seems ... vanished :D"
End If
End Sub
DrawListbox_Method2("sFile")
DrawListbox_Method2("sName")
DrawListbox_Method2("ThisWillNotExists")
WaitKey
BUT ATTENTION: there is a BUG in thinCore.dll also in versions previous 1.9.4
It free memory also for variables created using DIM ... AT ... when variables are strings while it should not do it!
I do not understand how I could have introduced such a stupid bug ????????
So please get attached thinCore.dll and place into your \thinBasic\ directory before executing above examples
ErosOlmi
26-03-2013, 09:31
No, bug has always be there.
And this explains also some strange behaves I was facing in the past.
I'm making changes and some tests than I will publish a new beta version (maybe this evening CET)
@Renč: I will publish (this evening) more info with some pictures about dynamic strings and StrPtr/VarPtr meaning hoping this will give more ideas and clarify dynamic strings memory handling.
Sent from my iPhone using Tapatalk
ReneMiner
26-03-2013, 12:14
OK, thanks Eros, I'm alway happy to have and use the latest available Version, so I got the feeling my computer understands an up-to-date language.
Your second example comes closest to my needs but the point is, I wanted to get around using "Select Case" and "If" as much as possible and prefer to give quick straight orders rather than cumbersome comparing before. It'll do the job for my current project- but not as flexible that I could use the handling for Gadget "listbox" from another script without any changes.
That's why I think, it would be great improvement if thinBasic could "recognize" a variable from it's name - and not just through a pointer - as it can do already with subs & functions. It would make computers that run thinBasic real smart-asses compared to others and might start a(n/r)evolution in basic programming since it's real understandable, easy Basic. And I'm unable to predict how many ways people find to use it, if they got the possibillities.
A 2-year old child recognizes stuff from names after pointing to it a few times - and not just from looks - it's a precondition to thinking.
- Pointers we have...
A 4-year old will understand that there are often more than just one word for the same thing.
- Virtual Variables we have also...
A 6-year old can read his and others names and "imagine" a face to the name...
- hmm,... :unsure:
Grown-ups don't care what others do nor think, they make up their own mind...
- yep, :beach:
Some small questions I wonder about: to ReDim uses up lots of time. How is that with virtual variables?
It should be pretty much faster since it doesn't really allocate additional space - but I'm not sure about it...
and additional to that:
Is possible to ReDim the size of the real variable through the virtual one?
(senseless example since the array-name is present in Sub):
Dim A() as Long
Redim A(100)
....
Sub SomeSub()
Local dummy() As Long At 0
Redim dummy(Ubound(A)) At Varptr(A(1))
...
Redim dummy(200) ' At VarPtr(A(1)) ???
' can Ubound(A) return 200 now?
End Sub
ErosOlmi
26-03-2013, 13:42
Quick reply while I have 5 minutes pause at work.
to ReDim uses up lots of time. How is that with virtual variables?
It should be pretty much faster since it doesn't really allocate additional space - but I'm not sure about it...
Yes: virtual variables are much faster because memory is not allocated/de-allocated/re-allocated.
They just use the memory virtual variables points to.
Is possible to ReDim the size of the real variable through the virtual one?
(senseless example since the array-name is present in Sub):
Dim A() as Long
Redim A(100)
....
Sub SomeSub()
Local dummy() As Long At 0
Redim dummy(Ubound(A)) At Varptr(A(1))
...
Redim dummy(200) ' At VarPtr(A(1)) ???
' can Ubound(A) return 200 now?
End Sub
No.
Virtual variable can just use the memory and not allocate/de-allocate/redim memory allocated by other part of your application.
They would not be "virtual" but real variables.
ReneMiner
09-04-2013, 13:06
Just because fits this topic, I got some new weired stuff in mind - related to that String "somewhat special inside"-thing.
Because currently I think about FAST loading meshes into TBGL in any way - don't care how - I came to the conclusion the fastest would be to pump the data from HD directly to a displaylist.
small example here some code snippet to visualize what data to await:
TBGL_NewList %ListID
TBGL_BeginPoly %GL_TRIANGLES
TBGL_Normal 1.23, 2.34, 3.45
TBGL_Color 12, 34, 45
TBGL_TexCoord2d 0.1, 1.2
TBGL_Vertex 1.23, 2.34, 3.45
TBGL_EndPoly
TBGL_EndList
I already made a routine to save my data this way (plain *.txt-file) so user can import his 3d-stuff directly to his script by copy & paste from texteditor.
However - if I save the data to binary - which might be the fastest way to load & save - I would have to run through my binary data and convert somehow to parameters for all those TBGL-Methods which would use somewhat of calculation-time and a few steps from binary saved data to create valid codelines in the right order.
Now my thoughts going to
local myFile as Dword = File_Open(fName, "INPUT")
local sRead as String
'...
While Not File_EOF(myFile)
sRead = File_LineInput(myFile)
' now sRead holds one line as in code above...
' Call_IfExists sRead ??? - naa - almost...
' because i had to make Val() from the parameters,
' that would mean to parse the line sRead in advance
' no - I think about some
Execute$(sRead)
Wend
so basically - treat the string-content as it would be a thinBasic-code-line in the script.
I know it will not work with Select Case nor multiline-if, so just one statement per line is limit i think,
-variables inside or constants ? - complicated but maybe...
That way I could save data to plain scriptlines in the order they shall be executed without any need to order them again. Of course I won't read line-by-line as in the example, but so example becomes clearer. I could give the statements directly from file to tB to be executed.
The lines would not stay in memory forever as they would in an include-unit-file and I think there are more uses possible, imagine to save all visual-designer-stuff somehow like this, or other run-once-at-startup-stuff...all lines from top to bottom get executed once - and then they're done & gone from memory...
As usual the programmer is responsible which strings shall be executed here.
maybe can be more versions of this:
to CORE/String-Functions:
Execute$(sString) as in this example
to CORE/String
ExecuteArray$(sStringArray[,startIndex[,endIndex]])
to CORE/String
ExecuteParse$(sString) ' $crlf as delimiter expected i'd say...
to FILE-Module which directly does
LineInput + executes it in one call.
File_ExecuteLine$(nFilenum) ' similar to File_LineInput + Execute$()
File_ExecuteFile$(sFilename) ' similar to File_Load + ExecuteParse$()
:locomotive: always have such weired ideas...
ErosOlmi
10-04-2013, 08:46
... great idea :idea:
Not just around the corner and I cannot still promise anything but I think there will be the possibility to load an external text file on request when needed and interpret it as "on the fly script source code" like it would be part of the script itself.
In my mind I still have to find solutions for few technical problems but at first sight it seems doable.
:comp5:
ReneMiner
10-04-2013, 17:19
OK, I would suggest new file-extension for these too, so thinAir will open it for edit from the built-in explorer and not just through File\Open from menu to open a *.txt -file. maybe *.tBasicE or *.TBTxt
- or make thinAir display & open *.txt from list below explorer-treeview...would be nice to use thinAir for quick writing/changing ReadMe.txt without changing to notepad also.
ReneMiner
17-05-2013, 17:08
I got some solution in the meantime to get String-In-String-Pointers done - so I am able to assign some UDT-variable to some object - in this example is a small listview just for demonstration-purpose. You'll need the latest thinCore.dll to run this. Run NewTest.tBasic but put SHEET.tBasicU into the same folder.
Uses "TBGL"
#INCLUDE "SHEET.tBasicU"
Type t_myType
Identity As String
Phone As String
Reputation As Long
Cash As Double
End Type
Dim myList() As t_myType
Dim mySheet As Long
Dim hWnd As DWord
Dim lCharwidth, lCharHeight As Long
Function TBMain()
' -- Create and show window
hWnd = TBGL_CreateWindowEx("TBGL script - press ESC to quit", 640, 480, 32, %TBGL_WS_WINDOWED)
TBGL_ShowWindow
TBGL_BuildFont TBGL_FontHandle("Lucida Console", 12), 1
TBGL_SetActiveFont 1
TBGL_GetFontTextSize("X", lCharWidth, lCharHeight)
' make the rows a little higher
lCharHeight += 4
Fill_myList() ' just fill the demonstration-UDT-array with some data
' now "bind" the data-structure to some sheet which manages the grid to sort those
' items and draw them all below their headers, so tell every header which UDT-Element to use
' name of variable, size of one element
mySheet = SHEET_Create("myList", SizeOf(t_myType))
' sheetID, Header-Caption, Variable-Type, Flags, Offset from first Element, number of chars = width of header
SHEET_AddHeader(mySheet, "Name", %VarType_String, 0, UDT_ElementOffset(myList(1).Identity), 10)
SHEET_AddHeader(mySheet, "Phone", %VarType_String, 0, UDT_ElementOffset(myList(1).Phone) , 12)
SHEET_AddHeader(mySheet, "Reputation", %VarType_Long, 0, UDT_ElementOffset(myList(1).Reputation))
SHEET_AddHeader(mySheet, "Cash", %VarType_Double, 0, UDT_ElementOffset(myList(1).Cash), 10)
' -- Resets status of all keys
TBGL_ResetKeyState()
TBGL_UseTexturing(FALSE) ' will just draw text and boxes...
TBGL_RenderMatrix2D(0, 480, 640, 0) ' and just 2D
TBGL_DepthFunc(%TBGL_ALWAYS)
TBGL_SetActiveFont 1
TBGL_Color 255, 255, 127
' -- Main loop
While TBGL_IsWindow(hWnd)
TBGL_ClearFrame
' call to draw some Listview-alike sheet now...
Draw_Sheet(mySheet)
TBGL_DrawFrame
' -- ESCAPE key to exit application
If TBGL_GetWindowKeyState(hWnd, %VK_ESCAPE) Then Exit While
Wend
TBGL_DestroyWindow
End Function
' -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Sub Draw_Sheet(ByVal Index As Long)
Static sHeader As String
Static X, Y, Vartype, Flags, Offset, nChars, lLeft As Long
Static MainType, SubType, IsArray, DataPtr, nElements As Long
Static pPtr As DWord
' as you see- this sub does not know anything about myList() but displays it's content...
thinBasic_VariableGetInfoEX(Sheet(Index).VarName, MainType, SubType, IsArray, DataPtr, nElements)
lLeft = 8 ' leave a little border
For X = 1 To Sheet(Index).nHeaders
If SHEET_GetHeaderInfo(Index, X, sHeader, VarType, Flags, Offset, nChars) Then
TBGL_PrintFont sHeader, lLeft, lCharHeight
If nElements Then
For Y = 1 To nElements
pPtr = DataPtr + Offset + (Y-1) * Sheet(Index).Varsize
Select Case VarType
Case %VarType_Long
TBGL_PrintFont( TStr$(Peek(Long, pPtr)), lLeft, (1+Y) * lCharHeight)
Case %VarType_Double
TBGL_PrintFont( Format$(Peek(Double, pPtr), "0.00" ), lLeft, (1+Y) * lCharHeight )
Case %VarType_String
TBGL_PrintFont( Peek$(Peek(DWord, pPtr), StrPtrLen(Peek(DWord, pPtr)) ), lLeft, (1+Y) * lCharHeight)
' for this script I just used those 3 VarTypes- more would be too confusing here
End Select
Next
End If
EndIf
' calculate left margin for next header:
lLeft += nChars * lCharWidth + 8
Next
End Sub
' ----------------------------------------------------------------------------------------
Sub Fill_myList()
ReDim myList(5)
With myList(1)
.Identity = "Petr"
.Phone = "unknown"
.Reputation = 10000
.Cash = 12345.67
End With
With myList(2)
.Identity = "Eros"
.Phone = "busy"
.Reputation = 10000
.Cash = 23456.78
End With
With myList(3)
.Identity = "John"
.Phone = "911"
End With
With myList(4)
.Identity = "Michael"
.Phone = "iPhone 4"
.Reputation = 5000
.Cash = -5.67
End With
With myList(5)
.Identity = "Max"
.Phone = "000-000-0000"
.Reputation = 10
.Cash = 1.00
End With
'add more elements to myList or change the content... Draw_Sheet() will be up-to-date anytime
End Sub
' ---------------------------------------------------------------------------------------
Maybe this is an idea to populate UI-Controls as MLGrid or Listview.
PS. I could not find built-in Equates to specify var-types - I think there should be some...
and- in SHEET_AddHeader could be some Sheet(Index).Width += nChars * something + some border - but I did not use it here, neither did I use flags as %align_left or %align_right here to not too complicate it.
The 169-lines Sheet-Unit consists of declarations for the functions and three subs to handle the sheets.
ReneMiner
11-06-2013, 14:55
Variables ByString work already but still urge for some solution for the following.
Some users might remember I was creating some UI-controls that have different properties. The solution was to use Union, but this wastes a lot of memory since all controls use as much as the largest control - the one with the most properties- does.
Now I attempt to Extend single elements of my main-CTRL/Gadget-Array as in this simplyfied example, so imagine Subtype1 would be a button or timer and the other one would be a property-list or grid or whatever...
Uses "Console"
Alias DWord As SomeSubType
Type t_mySubType1
A As Long
B As Byte
C As DWord
End Type
Type t_mySubType2
A As Long
B As Byte
C As DWord
D As Double
End Type
Type t_myMainType
Style As String
X As Long
Y As Long
pST As SomeSubType
End Type
Dim foo(5) As t_myMainType
foo(1).Style = "t_mySubtype1"
foo(1).pST = HEAP_Alloc(SizeOf(t_mySubtype1))
foo(2).Style = "t_mySubtype2"
foo(2).pST = HEAP_Alloc(SizeOf(t_mySubtype2))
fine till here- you see what I'm up to...
' now I'm stuck...
' I would need a method to get the UDT-Structure
' from the name stored in foo().Style
' would have to work as follows:
foo(1).Style = "t_mySubtype1"
foo(1).pST = HEAP_Alloc(SizeOf( ByString(foo(1).Style) )
' and also will not work
Dim Subtype As ByString(foo(1).Style) At foo(1).pST
' because
Dim Subtype As ByString(foo(2).Style) At foo(2).pST
' will now throw Error: Variable already exists
' also
ReDim Subtype As ByString(foo(2).Style) At foo(2).pST
' is not possible because SubType is not an array...
Reset Subtype As ByString(foo(2).Style) At foo(2).pST
' also not possible...
WaitKey
I need something that holds the information of the UDT-structure. In thinCore.inc I've not found such thing :(
Also would be great if a virtual layover could be changed in Type somehow