Array as overlay

New to FreeBASIC? Post your questions here.
Post Reply
Juergen Kuehlwein
Posts: 284
Joined: Mar 07, 2018 13:59
Location: Germany

Array as overlay

Post by Juergen Kuehlwein »

I have a set of data in a string, which is arranged in an array like manner. In PowerBASIC i can do a "DIM ...AT ..." to create an array, which is in fact an overlay over the existing data. That is, the data isn´t initialized as usual, but the existing data at the specified address remains untouched and now can be accessed via this array. The basic concept is like an UNION but extended to an array, different variables known to the compiler with different data types share the same memory.

Example:
Let´s say "address" is a pointer to my data, i dim an array of longs (4 bytes each), and i give a lbound of 1 and a ubound of 10 (dim myarray(1 to 10) as long at address), then i would have the the first 4 bytes of my data in myarray(1), the next 4 bytes in myarray(2) and so on.

How can i do this FreeBASIC? This should work for UDTs too!


JK
grindstone
Posts: 862
Joined: May 05, 2015 5:35
Location: Germany

Re: Array as overlay

Post by grindstone »

You could abuse a ZString Ptr:

Code: Select all

Dim As String g = "abcd" + Chr(0,0,0,0) + "ijklmnop"
Dim As ZString*20 h = "abcd" + Chr(0,0,0,0) + "ijklmnop"
Dim As Integer a(1 To 4), b(1 To 4)

For x As Integer = 1 To 4
	Print a(x)
Next
Print
*Cast(ZString Ptr, @a(1)) = g
For x As Integer = 1 To 4
	Print a(x)
Next
Print
*Cast(ZString Ptr, @b(1)) = h
For x As Integer = 1 To 4
	Print b(x)
Next
Sleep
It's important to use a var-len string for the data, because a ZString terminates at the first 0 byte.
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Array as overlay

Post by dodicat »

Dim byref is not defined for arrays, only for single instances of a datatype
but for arrays inside a udt it works

Code: Select all

  



Type udt 
    Dim As String g(1 To 10)
End Type

Dim As udt s

For n As Long=1 To 10
    s.g(n)=Str(n)+"  Hello"
    Print @s.g(n),s.g(n)
Next
Print

Dim Byref As udt s2=s

For n As Long=1 To 10
    Print @s2.g(n),s2.g(n)
Next

Sleep
 
sancho3
Posts: 358
Joined: Sep 30, 2017 3:22

Re: Array as overlay

Post by sancho3 »

@grindstone
That code does not work on 64bit machines. If it works on 32bit, how do you get from a(x) back to a string?

@dodicat
I don't think that is what juergen kuehiwein is wanting.
It seems you are simply copying two arrays.
If I am not mistaken he wants something that can take the string containing "hello" and return an array where
a(1) = "h", a(2) = "e", a(3) = "l" etc. And by simply moving memory or pointer; not by copying char by char.
Or a string containing "abcdefghijklmnop" and return an array containing 4 x string * 4 members.
PaulSquires
Posts: 1002
Joined: Jul 14, 2005 23:41

Re: Array as overlay

Post by PaulSquires »

Here is a starting point. I stole it from someone in this forum (fxm?)

Code: Select all


TYPE EMPLOYEE
   empName    AS STRING
   empAddress AS STRING
   empSalary  AS DOUBLE
END TYPE


' Create a generaic block of memory
dim pMem as any ptr = CALLOCATE( 1024)

' Here is the DIM AT syntax. Notice the NEW(pMem) part. 
' Basically 10 new employee TYPE's are overlayed on the
' existing pMem area.
DIM pEmp AS EMPLOYEE Ptr = NEW(pMem) EMPLOYEE[10]

' Assign data to our employee
pEmp->empName = "Paul"
pEmp->empAddress = "Canada"
pEmp->empSalary = 10000000.00

? pEmp->empName
? pEmp->empAddress
? pEmp->empSalary

' Deallocate our memory
DEALLOCATE(pMem)

sleep
fxm
Moderator
Posts: 12131
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Array as overlay

Post by fxm »

PaulSquires wrote:I stole it from someone in this forum (fxm?)
No, it's not my style.
In addition, I do not see the benefit of defining objects at a specified memory buffer address if these objects contain string descriptors.

@Juergen Kuehlwein,
Can you complete your request with a more precise example?
fxm
Moderator
Posts: 12131
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Array as overlay

Post by fxm »

But from what I understand (proposal with indexing pointer):

Code: Select all

Dim As String * 16 txt = "ABCDEFGHIJKLMNOP"

Union UDT
  Dim As Short s
  Type
    Dim As Ubyte u0
    Dim As Ubyte u1
    Dim As Ubyte u2
    Dim As Ubyte u3
  End Type
End Union

Dim As UDT Ptr p = Cptr(UDT Ptr, @txt)

Print txt
Print
For I As Integer = 0 To 3
  Print p[I].s,
  Print p[I].u0 & ":" & Chr(p[I].u0),
  Print p[I].u1 & ":" & Chr(p[I].u1),
  Print p[I].u2 & ":" & Chr(p[I].u2),
  Print p[I].u3 & ":" & Chr(p[I].u3)
Next I

Sleep
Little variant:

Code: Select all

Dim As String * 16 txt = "ABCDEFGHIJKLMNOP"

Union UDT
  Dim As Short s
  Type
    Dim As Ubyte u(0 To 3)
  End Type
End Union

Dim As UDT Ptr p = Cptr(UDT Ptr, @txt)

Print txt
Print
For I As Integer = 0 To 3
  Print p[I].s,
  For J As Integer = 0 To 3
    Print p[I].u(J) & ":" & Chr(p[I].u(J)),
  Next J
  Print
Next I

Sleep
With index base = 1 everywhere:

Code: Select all

Dim As String * 16 txt = "ABCDEFGHIJKLMNOP"

Union UDT
  Dim As Short s
  Type
    Dim As Ubyte u(1 To 4)
  End Type
End Union

Dim As UDT Ptr p = Cptr(UDT Ptr, @txt) - 1

Print txt
Print
For I As Integer = 1 To 4
  Print p[I].s,
  For J As Integer = 1 To 4
    Print p[I].u(J) & ":" & Chr(p[I].u(J)),
  Next J
  Print
Next I

Sleep
grindstone
Posts: 862
Joined: May 05, 2015 5:35
Location: Germany

Re: Array as overlay

Post by grindstone »

sancho3 wrote:@grindstone
That code does not work on 64bit machines. If it works on 32bit, how do you get from a(x) back to a string?
I can't help the 64bit issue due to lack of 64bit here.

The pointer acrobatics for the reverse conversion is a little more tricky :

Code: Select all

'string to array
Dim As String g = "abcd" + Chr(0,0,0,0) + "ijklmnop"
Dim As ZString*20 h = "abcd" + Chr(0,0,0,0) + "ijklmnop"
Dim As Integer a(1 To 4), b(1 To 4)

For x As Integer = 1 To 4
	Print a(x)
Next
Print
*Cast(ZString Ptr, @a(1)) = g
For x As Integer = 1 To 4
	Print a(x)
Next
Print
*Cast(ZString Ptr, @b(1)) = h
For x As Integer = 1 To 4
	Print b(x)
Next

'array to string
Dim As String s, t
Dim As UByte Ptr remember
Dim As Integer Ptr ip

t = String(SizeOf(a) * (UBound(a) - LBound(a) + 1), Chr(0)) 'create a string matching the array's memory size

ip = Cast(Integer Ptr, @t) 'get the pointer to the string descriptor of t
remember = Cast(UByte Ptr, *ip) 'save the pointer to the original text of t
*ip = Cast(Integer, @a(1)) 'replace the text pointer of t with the array pointer
s = t 'copy the array content as string
*ip = Cast(Integer, remember) 'restore the original text pointer of t

Print
Print s

Sleep
The original text pointer of the redirected string must be restored, otherwise the program will crash at the next write access to that string.
Last edited by grindstone on Jan 08, 2019 10:19, edited 1 time in total.
Juergen Kuehlwein
Posts: 284
Joined: Mar 07, 2018 13:59
Location: Germany

Re: Array as overlay

Post by Juergen Kuehlwein »

sancho3 got it! Of course i could fill any array with data element by element, but i want to do it in one go without making intermediate copies.

NEW(Placement) is the key - thanks Paul

Code: Select all

dim n as long
dim z as zstring ptr
dim b() as byte


  redim b(1 to 17)

  z = new(@b(1)) byte[17]
  *z = "Hello " + chr(0) + "everybody"

  for n = 1 to 17
    print b(n) & !"\t - " & chr(b(n))
  next n


  sleep
Thanks to all

JK
Juergen Kuehlwein
Posts: 284
Joined: Mar 07, 2018 13:59
Location: Germany

Re: Array as overlay

Post by Juergen Kuehlwein »

grindstone,

we cross posted - thanks!

Code: Select all

*Cast(ZString Ptr, @a(1)) = g
does essentially the same, but is more compact, i like it!

JK
fxm
Moderator
Posts: 12131
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Array as overlay

Post by fxm »

Your question was the opposite that I thought (and therefore simpler):
How to overlay a zstring buffer on an array 1D?

Note: if you resize the array after in the code, its address may change.
Juergen Kuehlwein wrote:NEW(Placement) is the key
No, you can simplify:
z = new(@b(1)) byte[17]
with:
z = @b(1)
Juergen Kuehlwein
Posts: 284
Joined: Mar 07, 2018 13:59
Location: Germany

Re: Array as overlay

Post by Juergen Kuehlwein »

Your question was the opposite that I thought (and therefore simpler):
How to overlay a zstring buffer on an array 1D?
Indeed my initial question was how to overlay an array on a (z)string buffer. But in this case the order is meaningless for the result. If it´s easier to overlay a zstring on an array than the other way round, then let´s do it.

I realized that i don´t need "NEW" here, using pointers does the trick.


Thanks

JK
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Array as overlay

Post by dodicat »

Well, I have been messing around trying to overlay a block of memory used by a string by an array.
Now you opt for the reverse.
OK, I didn't read your first post correctly initially and I used a byref with a udt.
Then I did read your first post and was trying resolve the request, but unfortunately I didn't read your last post (The switch).

Hardly worth putting in a feature request probably, but for things like overlaying chunks of memory an array of references should be supported.
at the moment we get
Array of references - not supported yet
So all hinges on the yet bit.
Anyway now I now have a memory block in my head so I am off for a cup of tea.
fxm
Moderator
Posts: 12131
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Array as overlay

Post by fxm »

Instead of overlaying a 1D array, why not just use the string index operator (specific FreeBASIC keyword that returns the indexed byte value) that looks like a 1D array:

Code: Select all

dim z as zstring * 16+1 = "Hello " + chr(0) + "everybody"

for n as integer = 0 to 16
  print z[n] & !"\t - " & chr(z[n])
next n

sleep
Juergen Kuehlwein
Posts: 284
Joined: Mar 07, 2018 13:59
Location: Germany

Re: Array as overlay

Post by Juergen Kuehlwein »

Now you opt for the reverse
Well, sorry - sometimes everyone of us tends to approach a problem with a specific solution in mind (just because this kind of solution worked elsewhere). This mind set prevents you from taking a step back.

The solution here is so easy, if you just do it the other way round. But it took me some time to realize this!

why not just use the string index operator

It should work for all kinds of arrays, not only for my simplified example.


Thanks again - problem solved


JK
Post Reply