Page 1 of 1

Add SwapStructure(*Source, *Destination, Structure)

Posted: Wed Feb 29, 2012 12:17 am
by Demivec
Please add the command SwapStructure(*Source, *Destination, Structure) to swap the contents of the structures located at *Source and *Destination.

Alternatively this could also be accomplished by adding a command such as the previously requested SwapMemory(*Source, *Destination, length) discussed here.

Re: Add SwapStructure(*Source, *Destination, Structure)

Posted: Wed Feb 29, 2012 12:46 am
by STARGÅTE
or: Swap Source, Destination [, Structure]

but i think CopyStructure sufficient:

Code: Select all

Global *SwapStructureBuffer

Macro SwapStructure(Source, Destination, StructureName)
	*SwapStructureBuffer = AllocateMemory(SizeOf(StructureName))
	CopyStructure(Source, *SwapStructureBuffer, StructureName)
	CopyStructure(Destination, Source, StructureName)
	CopyStructure(*SwapStructureBuffer, Destination, StructureName)
	ClearStructure(*SwapStructureBuffer, StructureName)
	FreeMemory(*SwapStructureBuffer)
EndMacro



Structure Test
	List MyList.i()
	Map MyMap.s()
	Float.f
EndStructure

Dim Test.Test(10)

AddElement(Test(1)\MyList())
Test(2)\MyMap("Test") = "Test"

SwapStructure(Test(1), Test(2), Test)

Debug ListSize(Test(1)\MyList())
Debug ListSize(Test(2)\MyList())
Debug Test(1)\MyMap("Test")
Debug Test(2)\MyMap("Test")

Re: Add SwapStructure(*Source, *Destination, Structure)

Posted: Wed Feb 29, 2012 1:33 am
by Demivec
STARGÅTE wrote:or: Swap Source, Destination [, Structure]
I would favor this too but it may cause some confusion.


Thanks for your example code. I am not in need of a solution though. I just think a native implementation would be better. It would avoid allocating additional memory by instead exchanging a register's worth of data at a time. If that isn't ideal than I guess I'll continue with the usual 'tmp = a: a = b: b = tmp' solution. :)

Re: Add SwapStructure(*Source, *Destination, Structure)

Posted: Wed Feb 29, 2012 5:09 pm
by xorc1zt

Code: Select all

Procedure SwapStr( str.i, str2.i )
    define pa.i = PeekI(str)
    define pb.i = PeekI(str2)
    PokeI( str, pb)
    PokeI( str2, pa)
EndProcedure
example

Code: Select all

Procedure SwapStr( str.i, str2.i )
    define pa.i = PeekI(str)
    define pb.i = PeekI(str2)
    PokeI( str, pb)
    PokeI( str2, pa)
EndProcedure

str.string
str2.string

str\s = "HELLO"
str2\s = "WORLD"

debug "str ("+hex( str )+") = "+str\s
debug "str2 ("+hex( str2 )+") = "+str2\s

debug "=========="

SwapStr( str, str2 )

debug "str ("+hex( str )+") = "+str\s
debug "str2 ("+hex( str2 )+") = "+str2\s

debug "=========="

Structure TEST_STR
    a.f
    b.i
    c.d
EndStructure

test1.TEST_STR
test2.TEST_STR

with test1
    \a = 4.55
    \b = 984
    \c = 8.45648
EndWith

with test2
    \a = 1.545
    \b = 324
    \c = 77.124
EndWith

SwapStr( test1, test2 )

debug "test1:"
debug test1\a
debug test1\b
debug test1\c
debug ""
debug "test2:"
debug test2\a
debug test2\b
debug test2\c

Re: Add SwapStructure(*Source, *Destination, Structure)

Posted: Wed Feb 29, 2012 5:20 pm
by KJ67
Really nice code xorc1zt,
but what will it do is the structure is in a linked list or map.

+1 on Demivec's request.

Re: Add SwapStructure(*Source, *Destination, Structure)

Posted: Wed Feb 29, 2012 5:44 pm
by Trond
I understand you want this natively. But I still made this, which avoids using a temp variable:

Code: Select all

; Swap two memory areas
Procedure SwapMemory(*Source.Ascii, *Destination.Ascii, Size)
  For I = 1 To SIZE
    Swap *Source\a, *Destination\a
    *Source + 1
    *Destination + 1
  Next
EndProcedure

; Swap two structured memory areas (obviously of the same structure)
Macro SwapStructure(Source, Destination, Structure_)
  SwapMemory(Source, Destination, SizeOf(Structure_))
EndMacro

; Test code
Structure Test
   List MyList.i()
   Map MyMap.s()
   Float.f
EndStructure

Dim Test.Test(10)

AddElement(Test(1)\MyList())
Test(2)\MyMap("Test") = "Test"

SwapStructure(Test(1), Test(2), Test)

Debug ListSize(Test(1)\MyList())
Debug ListSize(Test(2)\MyList())
Debug Test(1)\MyMap("Test")
Debug Test(2)\MyMap("Test")

Re: Add SwapStructure(*Source, *Destination, Structure)

Posted: Wed Feb 29, 2012 5:52 pm
by xorc1zt
KJ67 wrote:Really nice code xorc1zt,
but what will it do is the structure is in a linked list or map.

+1 on Demivec's request.
you can swap structure inside a list if you grab the pointer.

example:

Code: Select all

SelectElement( testlist(), 0 )
struct1 = testlist() ; save the pointer of element 0

SelectElement( testlist(), 1 )
struct2 = testlist() ; save the pointer of element 1

SwapStr( struct1, struct2 ) ; swap the pointers
edit : there is already a function for this

http://www.purebasic.com/documentation/ ... ments.html

Re: Add SwapStructure(*Source, *Destination, Structure)

Posted: Wed Feb 29, 2012 9:32 pm
by Demivec
It is interesting to see the many approaches.
Trond wrote:I understand you want this natively. But I still made this, which avoids using a temp variable:
Though I am still interested in a native solution, I thought to improve a little on your suggested code. :)

I've timed this small optimization to your code sample. Your original code is faster for structures of 8 bytes or less. The optimizations are faster for all larger structure (i.e. 30% faster for the 16 - 20 byte structure you gave an example of) with the greatest increases for the largest structures:

Code: Select all

Structure bi_array
  StructureUnion
  b.b
  i.i
  EndStructureUnion
EndStructure

; Swap two memory areas
Procedure SwapMemory(*Source.bi_array, *Destination.bi_array, size)
  Protected i, bytes = size % SizeOf(Integer)
  
  For i = 1 To bytes
    Swap *Source\b, *Destination\b
    *Source + SizeOf(Byte)
    *Destination + SizeOf(Byte)
  Next
  
  size = (size - bytes) / SizeOf(Integer)
  For i = 1 To size
    Swap *Source\i, *Destination\i
    *Source + SizeOf(Integer)
    *Destination + SizeOf(Integer)
  Next
EndProcedure

; Swap two structured memory areas (obviously of the same structure)
Macro SwapStructure(source, Destination, Structure_)
  SwapMemory(source, Destination, SizeOf(Structure_))
EndMacro