Page 1 of 1

Swap structure addresses?

Posted: Wed Jun 28, 2006 10:02 pm
by jonljacobi
Is it possible to swap the addresses of structures and not just their fields if they are of the same type?

I searched and found some possible methods, but nothing specific.


Cheers, Jon

Posted: Wed Jun 28, 2006 10:44 pm
by Flype
something like this ?

Code: Select all

Procedure SwapStruct(*a, *b, nByte.l)
  Protected *temp = AllocateMemory(nByte)
  If *temp
    CopyMemory(*a, *temp, nByte)
    CopyMemory(*b,    *a, nByte)
    CopyMemory(*temp, *b, nByte)
  EndIf
EndProcedure

Structure TEST
  id.s
  name.s
EndStructure

a.TEST
a\id = "0123"
a\name = "donald"

b.TEST
b\id = "4567"
b\name = "mickey"

Debug a\id
Debug a\name

Debug b\id
Debug b\name

SwapStruct(a, b, SizeOf(TEST))

Debug a\id
Debug a\name

Debug b\id
Debug b\name


Posted: Wed Jun 28, 2006 11:36 pm
by Kale
hmmm... interesting:

Code: Select all

Structure TEST
  id.s
  name.s
EndStructure

a.TEST
a\id = "1"
a\name = "donald"
*a.TEST = @a

b.TEST
b\id = "2"
b\name = "mickey"
*b.TEST = @b

Debug *a\id + " : " + *a\name
Debug *b\id + " : " + *b\name
Debug ""

Swap *a, *b

Debug *a\id + " : " + *a\name
Debug *b\id + " : " + *b\name
Debug ""

Swap *a\id, *b\id

Debug *a\id + " : " + *a\name
Debug *b\id + " : " + *b\name
Debug ""

Swap *a\name, *b\name

Debug *a\id + " : " + *a\name
Debug *b\id + " : " + *b\name
Debug ""

Posted: Wed Jun 28, 2006 11:46 pm
by netmaestro
I'm making fairly heavy use of this concept here:

http://www.purebasic.fr/english/viewtopic.php?t=21245

Posted: Thu Jun 29, 2006 12:37 am
by jonljacobi
Haven't tried this stuff yet, but I'm figuring that since a structure is an array of pointers (correct?) it should work if you just swapped out the addresses as in:

@TempStructA(0) = @TempStructB(0)

Of course, that doesn't actually work but it's the concept I had in mind. I can just implement a procedure that swaps the elements with the Swap command, but this would be a lot quicker and easier.

Thanks all.

Cheers, Jon

Posted: Thu Jun 29, 2006 10:07 pm
by jonljacobi
Tried the CopyMemory approach and it seems to work fine... until I DIM the structure again to clear it. Then I get an invalid memory access error. Oh well...

Cheers, Jon

Posted: Thu Jun 29, 2006 10:22 pm
by Trond

Code: Select all

; This works ONLY when you use a pointer to a structure
*Obnoxious.POINT = AllocateMemory(SizeOf(POINT))
*Nox.POINT = AllocateMemory(SizeOf(POINT))

*Obnoxious\x = 1
*Obnoxious\y = 2
*Nox\x = 3
*Nox\y = 4

Swap *Obnoxious, *Nox

Debug *Obnoxious\x
Debug *Obnoxious\y
Debug *Nox\x
Debug *Nox\y
However, you can setup a pointer to your ordinary structure and then swap the pointers. :wink:

Posted: Thu Jun 29, 2006 10:45 pm
by jonljacobi
Tried the CopyMemory approach and it seems to work fine... until I DIM the structure again to clear it. Then I get an invalid memory access error. Oh well...

Cheers, Jon

Posted: Thu Jun 29, 2006 11:07 pm
by Flype
DIM again ? do you have a sample code ?

notice that:
i forgot an important line in my above axample : FreeMemory(*Temp)

Posted: Fri Jun 30, 2006 8:35 pm
by jonljacobi
I noticed the memory leak and added the FreeMemory.

However, I was just using a straight CopyMemory command as in CopyMemory(@StructureA, @StructureB, SizeOf(Structure)). Worked like a charm until reDIMing to clear the array. Unfortunately, I've gone back to longhand and I never saved a version that used the redim problem. I'll try it in a new file and post it.

Code: Select all

Procedure SwapStructure(*StructureAddressA, *StructureAddressB, SizeOfStructureInBytes.l)
  Protected *CopyBuffer = AllocateMemory(SizeOfStructureInBytes)
  
  If *CopyBuffer
    CopyMemory(*StructureAddressA, *CopyBuffer, SizeOfStructureInBytes)
    CopyMemory(*StructureAddressB, *StructureAddressA, SizeOfStructureInBytes)
    CopyMemory(*CopyBuffer, *StructureAddressB, SizeOfStructureInBytes)
    FreeMemory(*CopyBuffer)
    
  EndIf
  
EndProcedure
Cheers, Jon

Posted: Fri Jun 30, 2006 8:44 pm
by jonljacobi

Code: Select all

Structure Test
  a.l
  b.l
  c.l
  d.s
EndStructure

Global Dim Testa.Test(10)
Global Dim Testb.Test(10)

Testa(1)\a = 10
Testa(1)\d = "Varmint"
CopyMemory(@Testa(1), @Testb(1), SizeOf(Test))
Debug Testb(1)\a
Debug Testb(1)\d

Global Dim Testa.Test(10)
Global Dim Testb.Test(10)

Well, this doesn't seem to break anything, but in my 25,000 line program it does happen. The re-DIM in the program is within a procedure.

Jon :?:

Posted: Fri Jun 30, 2006 10:38 pm
by Dräc
Kale wrote:hmmm... interesting
Very, Yes!

Posted: Fri Jun 30, 2006 10:59 pm
by Dräc
... but normal in fact.

Posted: Sat Jul 15, 2006 2:21 am
by jonljacobi
Well, I must've been doing something wrong, because swapping the addresses of the structures now works like a charm. I'm being careful to make sure everything is swapped back before I DIM again, but it doesn't seem as if I have to. Had to go to this method because I was swapping a lot of variables a number of times during a redraw. (Painting two sets of musical structures, question/answer, on the same staff, piano, and guitar.)

Cheers, Jon :D :?: