PokeBit(), PeekBit(), PokeBits() and PeekBits()

Share your advanced PureBasic knowledge/code with the community.
Froggerprogger
Enthusiast
Enthusiast
Posts: 423
Joined: Fri Apr 25, 2003 5:22 pm
Contact:

PokeBit(), PeekBit(), PokeBits() and PeekBits()

Post by Froggerprogger »

Code updated for 5.20+

Here are 2 procedures to Peek/Poke single bits inside large memoryblocks.
Further there are 2 procedures to Peek/Poke the value of 1-31 Bits inside large memoryblocks.
This is useful for example to store a lot of LONG-values which do not exactly use all 32 Bits with only the needed bits per value.

Code: Select all

;- Froggerprogger 16.09.03
;-
;- This program gives you the Procedures PokeBit(), PeekBit(), PokeBits() and PeekBits()
;- Because of PB using signed variables, all bitfields are interpretated as signed values, too
;-
;- Announcements:
;- 1. Byteoffset + (Bitoffset/8) < 2147483647
;-    (because sum is of type signed Long)
;-
;- 2. The resulting Bitposition is the sum of the Byteoffset (0-2147483647) and Bitoffset (0-2147483647)
;-    Is the Byteoffset 0, the maximum direct adressable Bitposition is 2147483647 (Bitoffset of type signed Long),
;-    and so these Bits lay in range of 0 to 2147483647 / 8 = 268435456 Bytes - 1 Bit
;-
;-    Examples:
;-    (Byteoffset ; Bitoffset) = (Byteoffset + 1*n ; Bitoffset - 8*n)
;-
;-      (0 ; 32769) = (1 ; 32761) = (4096 ; 1) = (4097 ; -7) = ...
;-      (0 ; 2147483640) = (268435455 ; 0) = ...
;-      (0 ; 2147483647) = (268435455 ; 7) = ...  + 1 Bit => (268435456 ; 0) = (1 ; 2147483640)
;-


;- PokeBit-parameter:
;   *memory - pointer to preallocated memory
;   Byteoffset - Byteoffset (0 - 2147483647)
;   Bitoffset - Bitoffset (0 - 2147483647)
;   value - the value to set (0 or 1)
Procedure PokeBit(*memory, Byteoffset.l, Bitoffset.l, value.l)
  Protected PositionMod.l     : PositionMod = Bitoffset - Bitoffset / 8 * 8 ; Modulo - don't use 64 instead of 8*8
  Protected ByteAlignedPosition.l : ByteAlignedPosition = (Bitoffset - PositionMod)>>3 + Byteoffset

  If value = 0
    PokeB(*memory + ByteAlignedPosition, PeekB(*memory + ByteAlignedPosition) & ~(1 << PositionMod))
  Else
    PokeB(*memory + ByteAlignedPosition, PeekB(*memory + ByteAlignedPosition) | (1 << PositionMod))
  EndIf

EndProcedure

;- PeekBit-parameter:
;   *memory - pointer to preallocated memory
;   Byteoffset - Byteoffset (0 - 2147483647)
;   Bitoffset - Bitoffset (0 - 2147483647)
;   Procedurereturn - LONG-value of the specified Bit (0 or 1)
Procedure.l PeekBit(*memory, Byteoffset.l, Bitoffset.l)
  Protected result.l          : result = 0
  Protected PositionMod.l     : PositionMod = Bitoffset - Bitoffset / 8 * 8 ; Modulo - don't use 64 instead of 8*8
  Protected ByteAlignedPosition.l : ByteAlignedPosition = (Bitoffset - PositionMod)>>3 + Byteoffset

  If PeekB(*memory + ByteAlignedPosition) >> PositionMod & 1
    result = 1
  EndIf

  ProcedureReturn result
EndProcedure

;- PokeBits-parameter
;   *memory - pointer to preallocated memory
;   Byteoffset - Byteoffset (0 - 2147483647)
;   Bitoffset - Bitoffset (0 - 2147483647)
;   Length - number of Bits to write (1 to 32)
;   value - value to write (-1*Pow(2,Length) < value < Pow(2, Length)-1) for correct results)
Procedure PokeBits(*memory, Byteoffset.l, Bitoffset.l, Length.l, value.l)
  Protected i.l
 
  If Bitoffset > 2147483615 : Byteoffset + 4 : Bitoffset - 32 : EndIf ; avoid Bitoffset-Overrun

  For i=0 To Length - 1
    PokeBit(*memory, Byteoffset, Bitoffset + i, 1 & value >> (Length - 1 - i))
  Next
 
EndProcedure

;- PeekBits-parameter
;   *memory - pointer to preallocated memory
;   Byteoffset - Byteoffset (0 - 2147483647)
;   Bitoffset - Bitoffset (0 - 2147483647)
;   Length - number of Bits to write (1 to 32)
;   Procedurereturn - LONG-value of the specified Bitfield
  ;- annotation
  ; PeekBits() for a one-bit-value returns 0 or 1, though 0 or -1 would be
  ; mathematically correct for a signed one-bit-value - but not as practical.
  ; [See the term If Length > 1 for this]
Procedure.l PeekBits(*memory, Byteoffset.l, Bitoffset.l, Length.l)
  Protected i.l
  Protected result.l
 
  If Bitoffset > 2147483615 : Byteoffset + 4 : Bitoffset - 32 : EndIf ; avoid Bitoffset-Overrun
 
  For i=0 To Length - 1
    result + PeekBit(*memory, Byteoffset, Bitoffset + (Length - 1 - i)) << i
  Next
 
  If Length > 1 And result>>(Length-1) ; "if Length > 1 and it is a negative result in a 'Length'Bit-Bitfield"
    result | $FFFFFFFF<<(Length-1)  ; "fill all the Bits > Length with 1, so it is a negative result in the 32Bit-Bitfield, too."
  EndIf
 
  ProcedureReturn result
EndProcedure



;- an example
*mem = AllocateMemory(4096)
bits = 7
p=0
For i=2 To 62 Step 2
  PokeBits(*mem, 3, p, bits, i)
  p+bits
Next

p=0
For i=2 To 62 Step 2
  Debug PeekBits(*mem, 3, p, bits)
  p+bits
Next 
%1>>1+1*1/1-1!1|1&1<<$1=1
eriansa
Enthusiast
Enthusiast
Posts: 277
Joined: Wed Mar 17, 2004 12:31 am
Contact:

Post by eriansa »

Thanks! I surely can use this for a rewire-implementation in PB.
Post Reply