ReverseString() and ReverseMemory(), v1.1
Posted: Tue Oct 07, 2008 11:42 pm
As usual, I was working on something, I needed a ReverseString() function but PureBasic has none. So i wrote one. Which led to more code, and eventually this suite of reverse functions.
ReverseString()
which returns a new reversed string.
and these which does in-memory reversing.
ReverseMemory() variants:
ReverseMemoryB() ;Reverse a memory area of byte.
ReverseMemoryW() ;Reverse a memory area of word.
ReverseMemoryL() ;Reverse a memory area of long.
ReverseMemoryQ() ;Reverse a memory area of quad.
ReverseMemoryF() ;Reverse a memory area of float.
ReverseMemoryD() ;Reverse a memory area of double.
ReverseMemoryI() ;Reverse a memory area of integer.
ReverseMemoryC() ;Reverse a memory area of char.
As ReverseMemoryC() works on characters it can be used used as a in-memory string reversion as well, make sure you give it the real memory length rather than string length though.
Here is the code along with some quick tests.
ReverseMemory() should be quite fast, they are all basically the same, and in fact Double and Float are just macros re-using the Quad and Long code as Double and Quad, and Float and Long both use the same amount of memory for it's storage.
ReverseString() should be fast. (it uses the ReverseMemoryC() code after all) but with some extra features. Like optional start and length parameters that let you do some more fancy string reversing stuff.
I'm sure ReverseString() can be enhanced/improved a bit more, but I'll leave that to some of you other crazy people on the forum as I need to get back to what I was originally coding on, instead of these cute little functions. (PS! I'll also be requesting ReverseString() and ReverseMemory() in the features forum, hopefully a future PureBasic version will have these in native code for even more speed and features.)
This source is Public Domain.
v1.0 - Tue Oct 07, 2008
v1.1 - Sat Oct 10, 2008
Fixed procedure name copy/paste screwup.
Fixed the while loops to use greater than comparison, stupid mistake but oh so easy to forget.
ReverseString()
which returns a new reversed string.
and these which does in-memory reversing.
ReverseMemory() variants:
ReverseMemoryB() ;Reverse a memory area of byte.
ReverseMemoryW() ;Reverse a memory area of word.
ReverseMemoryL() ;Reverse a memory area of long.
ReverseMemoryQ() ;Reverse a memory area of quad.
ReverseMemoryF() ;Reverse a memory area of float.
ReverseMemoryD() ;Reverse a memory area of double.
ReverseMemoryI() ;Reverse a memory area of integer.
ReverseMemoryC() ;Reverse a memory area of char.
As ReverseMemoryC() works on characters it can be used used as a in-memory string reversion as well, make sure you give it the real memory length rather than string length though.
Here is the code along with some quick tests.
ReverseMemory() should be quite fast, they are all basically the same, and in fact Double and Float are just macros re-using the Quad and Long code as Double and Quad, and Float and Long both use the same amount of memory for it's storage.
ReverseString() should be fast. (it uses the ReverseMemoryC() code after all) but with some extra features. Like optional start and length parameters that let you do some more fancy string reversing stuff.
I'm sure ReverseString() can be enhanced/improved a bit more, but I'll leave that to some of you other crazy people on the forum as I need to get back to what I was originally coding on, instead of these cute little functions. (PS! I'll also be requesting ReverseString() and ReverseMemory() in the features forum, hopefully a future PureBasic version will have these in native code for even more speed and features.)
This source is Public Domain.
Code: Select all
EnableExplicit
Procedure ReverseMemoryB(*memory.Byte,length.i)
Protected *memend.Byte
If length>SizeOf(Byte)
*memend=(*memory+length)-SizeOf(Byte)
length>>1
While length>0
Swap *memory\b,*memend\b
*memory+SizeOf(Byte)
*memend-SizeOf(Byte)
length-SizeOf(Byte)
Wend
EndIf
EndProcedure
Procedure ReverseMemoryW(*memory.Word,length.i)
Protected *memend.Word
If length>SizeOf(Word)
*memend=(*memory+length)-SizeOf(Word)
length>>1
While length>0
Swap *memory\w,*memend\w
*memory+SizeOf(Word)
*memend-SizeOf(Word)
length-SizeOf(Word)
Wend
EndIf
EndProcedure
Procedure ReverseMemoryL(*memory.Long,length.i)
Protected *memend.Long
If length>SizeOf(Long)
*memend=(*memory+length)-SizeOf(Long)
length>>1
While length>0
Swap *memory\l,*memend\l
*memory+SizeOf(Long)
*memend-SizeOf(Long)
length-SizeOf(Long)
Wend
EndIf
EndProcedure
Procedure ReverseMemoryQ(*memory.Quad,length.i)
Protected *memend.Quad
If length>SizeOf(Quad)
*memend=(*memory+length)-SizeOf(Quad)
length>>1
While length>0
Swap *memory\q,*memend\q
*memory+SizeOf(Quad)
*memend-SizeOf(Quad)
length-SizeOf(Quad)
Wend
EndIf
EndProcedure
Macro ReverseMemoryF(memory,length)
ReverseMemoryL(memory,length)
EndMacro
Macro ReverseMemoryD(memory,length)
ReverseMemoryQ(memory,length)
EndMacro
Procedure ReverseMemoryI(*memory.Integer,length.i)
Protected *memend.Integer
If length>SizeOf(Integer)
*memend=(*memory+length)-SizeOf(Integer)
length>>1
While length>0
Swap *memory\i,*memend\i
*memory+SizeOf(Integer)
*memend-SizeOf(Integer)
length-SizeOf(Integer)
Wend
EndIf
EndProcedure
Procedure ReverseMemoryC(*memory.Character,length.i)
Protected *memend.Character
If length>SizeOf(Character)
*memend=(*memory+length)-SizeOf(Character)
length>>1
While length>0
Swap *memory\c,*memend\c
*memory+SizeOf(Character)
*memend-SizeOf(Character)
length-SizeOf(Character)
Wend
EndIf
EndProcedure
Procedure.s ReverseString(string$,start.i=1,length.i=0) ;Ascii and Unicode. To be consistent with other string functions this makes a new string rather than in-place swapping.
Protected newstring$,*memory.Character,*memend.Character,len.i
start-1
If start<0
start=0
EndIf
len=Len(string$)
If length<1
length=len-start
EndIf
If (length+start)>len
length=len
EndIf
len=length
newstring$=string$
If len>1
start*SizeOf(Character)
len*SizeOf(Character)
*memory=@newstring$+start
*memend=(*memory+len)-SizeOf(Character)
len>>1
While len>0
Swap *memory\c,*memend\c
*memory+SizeOf(Character)
*memend-SizeOf(Character)
len-SizeOf(Character)
Wend
EndIf
ProcedureReturn newstring$
EndProcedure
Define text$
;As this reverses the memory using Character, this will work in both ascii and unicode.
;Warning! All ReverseMemory() functions are in-place, ReverseString() might be a better choice in most cases.
text$="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
ReverseMemoryC(@text$,StringByteLength(text$))
Debug "ReverseMemory: "+text$
;Reverse the whole string.
text$="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Debug "ReverseString all: "+ReverseString(text$)
;Reverse from A to Q only.
text$="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Debug "ReverseString middle: "+ReverseString(text$,11,17)
;Reverse from A to Q only, then reverse all, resulting in a inversion so the middle is "non-reversed".
text$="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Debug "ReverseString ends: "+ReverseString(ReverseString(text$,11,17))
v1.1 - Sat Oct 10, 2008
Fixed procedure name copy/paste screwup.
Fixed the while loops to use greater than comparison, stupid mistake but oh so easy to forget.