Re: PeekHexBytes() and PokeHexBytes()
Posted: Mon Aug 23, 2010 1:15 pm
Oops => done now.
yrreti, thanks for telling me!
Regards, Little John
yrreti, thanks for telling me!
Regards, Little John
http://www.purebasic.com
https://www.purebasic.fr/english/
Code: Select all
For i = 15 To 26
c = i
c | %00100000
If c < '0' Or (c > '9' And (c < 'a' Or c > 'f'))
Debug "Failed input: " + Chr(i)
Else
Debug "Accepted input: " + Chr(i) + " (thought to be " + Chr(c) + ")"
EndIf
Next
Code: Select all
Procedure _GetString(*M.Character, S.s)
l = StringByteLength(S)
If CompareMemory(*M, @S, L)
ProcedureReturn *M+l
EndIf
ProcedureReturn *M
EndProcedure
Procedure IsHexChar(*Source.Character)
Select *Source\c
Case '0' To '9', 'A' To 'Z', 'a' To 'z'
ProcedureReturn 1
EndSelect
EndProcedure
Procedure _GetHexLength(*Source)
If IsHexChar(*Source)
If IsHexChar(*Source+SizeOf(Character))
If IsHexChar(*Source+2*SizeOf(Character))
ProcedureReturn 0 ; Error in input
EndIf
ProcedureReturn 2
EndIf
ProcedureReturn 1
EndIf
EndProcedure
; Return number of bytes written
Procedure.i PokeHexBytes(*Dest.Ascii, Bytelist.s, Separator.s = "", Prefix.s = "")
Protected *Source.Character = @Bytelist
Protected *OrigDest = *Dest
While *Source\c
*Source = _GetString(*Source, Prefix)
HexL = _GetHexLength(*Source)
If HexL = 0
Break
EndIf
PokeA(*Dest, Val("$" + PeekS(*Source, HexL)))
*Source + HexL * SizeOf(Character)
*Dest + 1
*Source = _GetString(*Source, separator)
Wend
ProcedureReturn *Dest - *OrigDest
EndProcedure
Oops I'm making so many stupid mistakes lately ... Thanks again!Trond wrote:There is a problem with your input verification, it accepts illegal characters:
Code: Select all
Macro CheckHexDigit ()
Select *source\c
Case '0' To '9', 'A' To 'F', 'a' To 'f'
; OK, do nothing
Default
ProcedureReturn 0 ; error
EndSelect
*source + SizeOf(Character)
EndMacro
My procedure returns the number of written bytes only on success, and 0 otherwise. I like to get a clear indicator in case of an error (-1 instead of 0 might be better, since poking "" is not really an error, and will also return 0.) Accepting a single character as a hex number is not what I personally want.Trond wrote:This should be relatively bullet-proof, it return the number of bytes written. It also accept a single character as a hex number (so you don't need to pad with 0 first), but rejects three hex digits in a row.
I understand, I just worked on my own code because that was simplest to me.That's why I changed the code, so that both lengths are determined only once at the beginning, and then passed as parameter.
Code: Select all
Macro SkipString (_s_, _length_)
If CompareMemory(*Source, @_s_, _length_)
*source + _length_
EndIf
EndMacro
Procedure IsHexChar(*Source.Character)
Select *Source\c
Case '0' To '9', 'A' To 'Z', 'a' To 'z'
ProcedureReturn 1
EndSelect
EndProcedure
; Return number of bytes written or -1 on failure
Procedure.i PokeHexBytes(*Dest.Ascii, Bytelist.s, Separator.s = "", Prefix.s = "")
Protected *Source.Character = @Bytelist
Protected *OrigDest = *Dest
Protected lenPre = StringByteLength(Prefix)
Protected lenSep = StringByteLength(Separator)
While *Source\c
SkipString(Prefix, lenPre)
If IsHexChar(*Source) And IsHexChar(*Source+SizeOf(Character))
PokeA(*Dest, Val("$" + PeekS(*Source, 2)))
*Source + 2 * SizeOf(Character)
*Dest + 1
SkipString(Separator, lenSep)
Else
ProcedureReturn -1
EndIf
Wend
ProcedureReturn *Dest - *OrigDest
EndProcedure