Page 1 of 1

PeekH() and PokeH()

Posted: Wed Nov 06, 2019 1:24 am
by swhite
Hi

I would like to see two functions that can peek and poke hex strings (i.e. $e17d9f6604a700400082022000950500000000005f). This would avoid problems with ASCII/Unicode string conversion etc.

PeekH(*Buffer,Len.i) : Reads the memory buffer and returns the data in Hex format. Used to read binary data from a memory buffer.

PokeS(*Buffer, Hex.s,len.i) : Puts the hex string into the memory buffer. Used to put binary data into a memory buffer.

Thanks
Simon

Re: PeekH() and PokeH()

Posted: Wed Nov 06, 2019 6:38 am
by Josh
-1

It is counterproductive if there is a native command for all possible cases that can be handled by a simple procedure. Especially if it's such a special case that's rarely needed.

Re: PeekH() and PokeH()

Posted: Wed Nov 06, 2019 8:42 pm
by mk-soft
You build little things like that for yourself.

Code: Select all

Structure ByteArray
  b.b[0]
EndStructure

Procedure.s PeekH(*Buffer.ByteArray, Len)
  Protected r1.s, index
  len - 1
  For index = 0 To Len
    r1 + RSet(Hex(*Buffer\b[index], #PB_Byte), 2, "0")
  Next
  ProcedureReturn r1
EndProcedure

value.q = $01020304AABBCCDD

Debug PeekH(@value, 8)

Re: PeekH() and PokeH()

Posted: Wed Nov 06, 2019 10:06 pm
by swhite
The reason I asked is because I did build my own code for this but I needed it to be much faster. So I figured if PureBasic had such a function it would be much faster than repeated calls to Hex() and RSet().

As far as rarely used, it depends on your application. In the payment industry the EMV readers and Tap & Go readers send all their strings as binary data but most of the routines assume the data has been converted to HEX strings. So it is used all the time when communicating with these devices.

Simon

Re: PeekH() and PokeH()

Posted: Thu Nov 07, 2019 1:04 am
by mk-soft
ASM is also not faster when working with tables. String and Hex functions are always slower

Unicode Version

Code: Select all

;-TOP

Structure ByteArray
  a.a[0]
  b.b[0]
EndStructure

Structure LongArray
  l.l[0]
EndStructure

Structure HexData
  l.l
  w.w
EndStructure

Structure HexArray
  hex.HexData[0]
EndStructure

Global *HexList.HexArray = ?HexList
  
Procedure.s PeekH_V1(*Buffer.ByteArray, Len)
  Protected r1.s, index
  len - 1
  For index = 0 To Len
    r1 + RSet(Hex(*Buffer\b[index], #PB_Byte), 2, "0")
  Next
  ProcedureReturn r1
EndProcedure

Procedure.s PeekH_V2(*Buffer.ByteArray, Len)
  Protected r1.s, *r1.LongArray, index
  r1 = Space(len * 2)
  *r1 = @r1
  len - 1
  For index = 0 To Len
    *r1\l[index] = *HexList\hex[*Buffer\a[index]]\l
  Next
  ProcedureReturn r1
EndProcedure


value.q = $01020304AABBCCDD

start = ElapsedMilliseconds()
For i = 1 To 1000000
  t1.s = PeekH_V1(@value, 8)
Next
ende = ElapsedMilliseconds()

MessageRequester("Time V1", "" + Str(ende - start) + "ms")

start = ElapsedMilliseconds()
For i = 1 To 1000000
  t1.s = PeekH_V2(@value, 8)
Next
ende = ElapsedMilliseconds()

MessageRequester("Time V2", "" + Str(ende - start) + "ms")

DataSection
  HexList:
  Data.s "00"
  Data.s "01"
  Data.s "02"
  Data.s "03"
  Data.s "04"
  Data.s "05"
  Data.s "06"
  Data.s "07"
  Data.s "08"
  Data.s "09"
  Data.s "0A"
  Data.s "0B"
  Data.s "0C"
  Data.s "0D"
  Data.s "0E"
  Data.s "0F"
  Data.s "10"
  Data.s "11"
  Data.s "12"
  Data.s "13"
  Data.s "14"
  Data.s "15"
  Data.s "16"
  Data.s "17"
  Data.s "18"
  Data.s "19"
  Data.s "1A"
  Data.s "1B"
  Data.s "1C"
  Data.s "1D"
  Data.s "1E"
  Data.s "1F"
  Data.s "20"
  Data.s "21"
  Data.s "22"
  Data.s "23"
  Data.s "24"
  Data.s "25"
  Data.s "26"
  Data.s "27"
  Data.s "28"
  Data.s "29"
  Data.s "2A"
  Data.s "2B"
  Data.s "2C"
  Data.s "2D"
  Data.s "2E"
  Data.s "2F"
  Data.s "30"
  Data.s "31"
  Data.s "32"
  Data.s "33"
  Data.s "34"
  Data.s "35"
  Data.s "36"
  Data.s "37"
  Data.s "38"
  Data.s "39"
  Data.s "3A"
  Data.s "3B"
  Data.s "3C"
  Data.s "3D"
  Data.s "3E"
  Data.s "3F"
  Data.s "40"
  Data.s "41"
  Data.s "42"
  Data.s "43"
  Data.s "44"
  Data.s "45"
  Data.s "46"
  Data.s "47"
  Data.s "48"
  Data.s "49"
  Data.s "4A"
  Data.s "4B"
  Data.s "4C"
  Data.s "4D"
  Data.s "4E"
  Data.s "4F"
  Data.s "50"
  Data.s "51"
  Data.s "52"
  Data.s "53"
  Data.s "54"
  Data.s "55"
  Data.s "56"
  Data.s "57"
  Data.s "58"
  Data.s "59"
  Data.s "5A"
  Data.s "5B"
  Data.s "5C"
  Data.s "5D"
  Data.s "5E"
  Data.s "5F"
  Data.s "60"
  Data.s "61"
  Data.s "62"
  Data.s "63"
  Data.s "64"
  Data.s "65"
  Data.s "66"
  Data.s "67"
  Data.s "68"
  Data.s "69"
  Data.s "6A"
  Data.s "6B"
  Data.s "6C"
  Data.s "6D"
  Data.s "6E"
  Data.s "6F"
  Data.s "70"
  Data.s "71"
  Data.s "72"
  Data.s "73"
  Data.s "74"
  Data.s "75"
  Data.s "76"
  Data.s "77"
  Data.s "78"
  Data.s "79"
  Data.s "7A"
  Data.s "7B"
  Data.s "7C"
  Data.s "7D"
  Data.s "7E"
  Data.s "7F"
  Data.s "80"
  Data.s "81"
  Data.s "82"
  Data.s "83"
  Data.s "84"
  Data.s "85"
  Data.s "86"
  Data.s "87"
  Data.s "88"
  Data.s "89"
  Data.s "8A"
  Data.s "8B"
  Data.s "8C"
  Data.s "8D"
  Data.s "8E"
  Data.s "8F"
  Data.s "90"
  Data.s "91"
  Data.s "92"
  Data.s "93"
  Data.s "94"
  Data.s "95"
  Data.s "96"
  Data.s "97"
  Data.s "98"
  Data.s "99"
  Data.s "9A"
  Data.s "9B"
  Data.s "9C"
  Data.s "9D"
  Data.s "9E"
  Data.s "9F"
  Data.s "A0"
  Data.s "A1"
  Data.s "A2"
  Data.s "A3"
  Data.s "A4"
  Data.s "A5"
  Data.s "A6"
  Data.s "A7"
  Data.s "A8"
  Data.s "A9"
  Data.s "AA"
  Data.s "AB"
  Data.s "AC"
  Data.s "AD"
  Data.s "AE"
  Data.s "AF"
  Data.s "B0"
  Data.s "B1"
  Data.s "B2"
  Data.s "B3"
  Data.s "B4"
  Data.s "B5"
  Data.s "B6"
  Data.s "B7"
  Data.s "B8"
  Data.s "B9"
  Data.s "BA"
  Data.s "BB"
  Data.s "BC"
  Data.s "BD"
  Data.s "BE"
  Data.s "BF"
  Data.s "C0"
  Data.s "C1"
  Data.s "C2"
  Data.s "C3"
  Data.s "C4"
  Data.s "C5"
  Data.s "C6"
  Data.s "C7"
  Data.s "C8"
  Data.s "C9"
  Data.s "CA"
  Data.s "CB"
  Data.s "CC"
  Data.s "CD"
  Data.s "CE"
  Data.s "CF"
  Data.s "D0"
  Data.s "D1"
  Data.s "D2"
  Data.s "D3"
  Data.s "D4"
  Data.s "D5"
  Data.s "D6"
  Data.s "D7"
  Data.s "D8"
  Data.s "D9"
  Data.s "DA"
  Data.s "DB"
  Data.s "DC"
  Data.s "DD"
  Data.s "DE"
  Data.s "DF"
  Data.s "E0"
  Data.s "E1"
  Data.s "E2"
  Data.s "E3"
  Data.s "E4"
  Data.s "E5"
  Data.s "E6"
  Data.s "E7"
  Data.s "E8"
  Data.s "E9"
  Data.s "EA"
  Data.s "EB"
  Data.s "EC"
  Data.s "ED"
  Data.s "EE"
  Data.s "EF"
  Data.s "F0"
  Data.s "F1"
  Data.s "F2"
  Data.s "F3"
  Data.s "F4"
  Data.s "F5"
  Data.s "F6"
  Data.s "F7"
  Data.s "F8"
  Data.s "F9"
  Data.s "FA"
  Data.s "FB"
  Data.s "FC"
  Data.s "FD"
  Data.s "FE"
  Data.s "FF"
  Data.w 0
EndDataSection

Re: PeekH() and PokeH()

Posted: Thu Nov 07, 2019 7:24 am
by wilbert
mk-soft wrote:ASM is also not faster when working with tables.
ASM is faster but your PB code is also very fast. :)

By the way, the PB code can be made faster by using a result buffer combined with PeekS.
Example :

Code: Select all

Global Dim HexList.l(255)

Procedure InitHexList()
  Protected i.i
  For i = 0 To 255
    PokeS(@HexList(i), RSet(Hex(i), 2, "0"), 2, #PB_String_NoZero)   
  Next
EndProcedure
InitHexList()

Procedure.s PeekH(*Buffer.Ascii, Len)
  Protected Dim Result.l(Len)
  Protected *Result.Long = @Result()
  While Len
    Len - 1
    *Result\l = HexList(*Buffer\a)
    *Result + 4
    *Buffer + 1
  Wend
  ProcedureReturn PeekS(@Result())
EndProcedure

Re: PeekH() and PokeH()

Posted: Thu Nov 07, 2019 7:17 pm
by mk-soft
Nice idee Wilbert

Here now PokeH over table... Link: viewtopic.php?f=13&t=73946&p=544255#p544255

Re: PeekH() and PokeH()

Posted: Thu Nov 07, 2019 8:27 pm
by Little John
+1 for the original request, BTW.

It would be nice to have something like this built-in into PureBasic, especially since those are rather basic functions (no pun intended).

Re: PeekH() and PokeH()

Posted: Fri Nov 08, 2019 6:40 am
by wilbert
Little John wrote:+1 for the original request, BTW.

It would be nice to have something like this built-in into PureBasic, especially since those are rather basic functions (no pun intended).
I agree with the request but I think it would be more logical to have the functions as Base16Encoder / Base16Decoder as the behavior is very similar to the Base64 functions.

Re: PeekH() and PokeH()

Posted: Fri Nov 08, 2019 1:26 pm
by Joris
Wouldn't it be nice if the full string of hex-values can be viewed, each value seperated with a space-character (like in a hex-editor or something) ?
How can this be done best without loosing to much speed ?

Re: PeekH() and PokeH()

Posted: Fri Nov 08, 2019 2:21 pm
by wilbert
Joris wrote:Wouldn't it be nice if the full string of hex-values can be viewed, each value seperated with a space-character (like in a hex-editor or something) ?
How can this be done best without loosing to much speed ?
Something like this ?

Code: Select all

Global Dim HexList.l(255)

Procedure InitHexList()
  Protected i.i
  For i = 0 To 255
    PokeS(@HexList(i), RSet(Hex(i), 2, "0"), 2, #PB_String_NoZero)   
  Next
EndProcedure
InitHexList()

Procedure.s PeekH(*Buffer.Ascii, Len)
  Protected Dim Result.l(Len)
  Protected *Result.Long = @Result()
  While Len
    Len - 1
    *Result\l = HexList(*Buffer\a)
    *Result + 4
    *Buffer + 1
  Wend
  ProcedureReturn PeekS(@Result())
EndProcedure

Procedure.s PeekHSeparated(*Buffer.Ascii, Len)
  Protected Dim Result.u(Len * 3)
  Protected *Result.Long = @Result()
  Protected *Separator.Unicode = *Result + 4
  While Len
    Len - 1
    *Result\l = HexList(*Buffer\a)
    *Result + 6
    *Separator\u = 32
    *Separator + 6
    *Buffer + 1
  Wend
  ProcedureReturn PeekS(@Result())
EndProcedure


q.q = $0123456789abcdef
Debug PeekH(@q, 8)
Debug PeekHSeparated(@q, 8)
It is slower.
Asm could be used to speed it up a bit.

Re: PeekH() and PokeH()

Posted: Fri Nov 08, 2019 3:33 pm
by Little John
Joris wrote:Wouldn't it be nice if the full string of hex-values can be viewed, each value seperated with a space-character (like in a hex-editor or something) ?
How can this be done best without loosing to much speed ?
When using PeekHexBytes(), you can optionally define your own separator (e.g. " " or ";") and your own prefix (e.g. "$" or "0x").

Re: PeekH() and PokeH()

Posted: Fri Nov 08, 2019 3:48 pm
by swhite
Hi

Base16Encoder/Base16Decoder are both good ideas to me. The idea of having an optional separator for both is also a good idea. I would be willing to sponsor these two functions if Fred was open to the idea. It makes handling ASCII strings in Unicode very easy. I would hope Fred might use Wilbert's high speed methods so the functions are very fast.
wilbert wrote:
Little John wrote:+1 for the original request, BTW.

It would be nice to have something like this built-in into PureBasic, especially since those are rather basic functions (no pun intended).
I agree with the request but I think it would be more logical to have the functions as Base16Encoder / Base16Decoder as the behavior is very similar to the Base64 functions.

Re: PeekH() and PokeH()

Posted: Fri Nov 08, 2019 8:37 pm
by Joris
Wilbert and Little John thanks.

Wilbert I'm already satified, as this coding I can understand (ASM ...hmmm, mostly just admiring).

Re: PeekH() and PokeH()

Posted: Mon Nov 11, 2019 12:55 pm
by Mijikai
Here is my try on it :)
Its also uses lookup tables to increase the speed.

Code:

Code: Select all

Procedure.s PeekH(*Buffer.Ascii,BufferSize.i)
  Protected ho.i,hs.s,*hx.String = @ho
  BufferSize + *Buffer
  Repeat
    ho = ?hex + *Buffer\a << 3:hs + *hx\s:*Buffer + 1
  Until *Buffer = BufferSize
  ProcedureReturn hs
  hex:
  !du '00',0,0,'01',0,0,'02',0,0,'03',0,0,'04',0,0,'05',0,0,'06',0,0,'07',0,0,'08',0,0,'09',0,0,'0A',0,0,'0B',0,0,'0C',0,0,'0D',0,0,'0E',0,0,'0F',0,0
  !du '10',0,0,'11',0,0,'12',0,0,'13',0,0,'14',0,0,'15',0,0,'16',0,0,'17',0,0,'18',0,0,'19',0,0,'1A',0,0,'1B',0,0,'1C',0,0,'1D',0,0,'1E',0,0,'1F',0,0
  !du '20',0,0,'21',0,0,'22',0,0,'23',0,0,'24',0,0,'25',0,0,'26',0,0,'27',0,0,'28',0,0,'29',0,0,'2A',0,0,'2B',0,0,'2C',0,0,'2D',0,0,'2E',0,0,'2F',0,0
  !du '30',0,0,'31',0,0,'32',0,0,'33',0,0,'34',0,0,'35',0,0,'36',0,0,'37',0,0,'38',0,0,'39',0,0,'3A',0,0,'3B',0,0,'3C',0,0,'3D',0,0,'3E',0,0,'3F',0,0
  !du '40',0,0,'41',0,0,'42',0,0,'43',0,0,'44',0,0,'45',0,0,'46',0,0,'47',0,0,'48',0,0,'49',0,0,'4A',0,0,'4B',0,0,'4C',0,0,'4D',0,0,'4E',0,0,'4F',0,0
  !du '50',0,0,'51',0,0,'52',0,0,'53',0,0,'54',0,0,'55',0,0,'56',0,0,'57',0,0,'58',0,0,'59',0,0,'5A',0,0,'5B',0,0,'5C',0,0,'5D',0,0,'5E',0,0,'5F',0,0
  !du '60',0,0,'61',0,0,'62',0,0,'63',0,0,'64',0,0,'65',0,0,'66',0,0,'67',0,0,'68',0,0,'69',0,0,'6A',0,0,'6B',0,0,'6C',0,0,'6D',0,0,'6E',0,0,'6F',0,0
  !du '70',0,0,'71',0,0,'72',0,0,'73',0,0,'74',0,0,'75',0,0,'76',0,0,'77',0,0,'78',0,0,'79',0,0,'7A',0,0,'7B',0,0,'7C',0,0,'7D',0,0,'7E',0,0,'7F',0,0
  !du '80',0,0,'81',0,0,'82',0,0,'83',0,0,'84',0,0,'85',0,0,'86',0,0,'87',0,0,'88',0,0,'89',0,0,'8A',0,0,'8B',0,0,'8C',0,0,'8D',0,0,'8E',0,0,'8F',0,0
  !du '90',0,0,'91',0,0,'92',0,0,'93',0,0,'94',0,0,'95',0,0,'96',0,0,'97',0,0,'98',0,0,'99',0,0,'9A',0,0,'9B',0,0,'9C',0,0,'9D',0,0,'9E',0,0,'9F',0,0
  !du 'A0',0,0,'A1',0,0,'A2',0,0,'A3',0,0,'A4',0,0,'A5',0,0,'A6',0,0,'A7',0,0,'A8',0,0,'A9',0,0,'AA',0,0,'AB',0,0,'AC',0,0,'AD',0,0,'AE',0,0,'AF',0,0
  !du 'B0',0,0,'B1',0,0,'B2',0,0,'B3',0,0,'B4',0,0,'B5',0,0,'B6',0,0,'B7',0,0,'B8',0,0,'B9',0,0,'BA',0,0,'BB',0,0,'BC',0,0,'BD',0,0,'BE',0,0,'BF',0,0
  !du 'C0',0,0,'C1',0,0,'C2',0,0,'C3',0,0,'C4',0,0,'C5',0,0,'C6',0,0,'C7',0,0,'C8',0,0,'C9',0,0,'CA',0,0,'CB',0,0,'CC',0,0,'CD',0,0,'CE',0,0,'CF',0,0
  !du 'D0',0,0,'D1',0,0,'D2',0,0,'D3',0,0,'D4',0,0,'D5',0,0,'D6',0,0,'D7',0,0,'D8',0,0,'D9',0,0,'DA',0,0,'DB',0,0,'DC',0,0,'DD',0,0,'DE',0,0,'DF',0,0
  !du 'E0',0,0,'E1',0,0,'E2',0,0,'E3',0,0,'E4',0,0,'E5',0,0,'E6',0,0,'E7',0,0,'E8',0,0,'E9',0,0,'EA',0,0,'EB',0,0,'EC',0,0,'ED',0,0,'EE',0,0,'EF',0,0
  !du 'F0',0,0,'F1',0,0,'F2',0,0,'F3',0,0,'F4',0,0,'F5',0,0,'F6',0,0,'F7',0,0,'F8',0,0,'F9',0,0,'FA',0,0,'FB',0,0,'FC',0,0,'FD',0,0,'FE',0,0,'FF',0,0
EndProcedure

Procedure.i PokeH(*Buffer.Ascii,Hex.s)
  Protected hi.i,*hc.Long,*hx.Long = @Hex
  Repeat
    For hi = 0 To 255:*hc = ?hex + (hi << 2):If *hc\l = *hx\l:*Buffer\a = hi:EndIf:Next
    *Buffer + 1:*hx + 4    
  Until *hx\l = #Null
  ProcedureReturn #Null
  hex:
  !du '00','01','02','03','04','05','06','07','08','09','0A','0B','0C','0D','0E','0F'
  !du '10','11','12','13','14','15','16','17','18','19','1A','1B','1C','1D','1E','1F'
  !du '20','21','22','23','24','25','26','27','28','29','2A','2B','2C','2D','2E','2F'
  !du '30','31','32','33','34','35','36','37','38','39','3A','3B','3C','3D','3E','3F'
  !du '40','41','42','43','44','45','46','47','48','49','4A','4B','4C','4D','4E','4F'
  !du '50','51','52','53','54','55','56','57','58','59','5A','5B','5C','5D','5E','5F'
  !du '60','61','62','63','64','65','66','67','68','69','6A','6B','6C','6D','6E','6F'
  !du '70','71','72','73','74','75','76','77','78','79','7A','7B','7C','7D','7E','7F'
  !du '80','81','82','83','84','85','86','87','88','89','8A','8B','8C','8D','8E','8F'
  !du '90','91','92','93','94','95','96','97','98','99','9A','9B','9C','9D','9E','9F'
  !du 'A0','A1','A2','A3','A4','A5','A6','A7','A8','A9','AA','AB','AC','AD','AE','AF'
  !du 'B0','B1','B2','B3','B4','B5','B6','B7','B8','B9','BA','BB','BC','BD','BE','BF'
  !du 'C0','C1','C2','C3','C4','C5','C6','C7','C8','C9','CA','CB','CC','CD','CE','CF'
  !du 'D0','D1','D2','D3','D4','D5','D6','D7','D8','D9','DA','DB','DC','DD','DE','DF'
  !du 'E0','E1','E2','E3','E4','E5','E6','E7','E8','E9','EA','EB','EC','ED','EE','EF'
  !du 'F0','F1','F2','F3','F4','F5','F6','F7','F8','F9','FA','FB','FC','FD','FE','FF'
EndProcedure