My IsHex procedure

Share your advanced PureBasic knowledge/code with the community.
wallgod
User
User
Posts: 48
Joined: Wed Oct 06, 2010 2:03 pm

My IsHex procedure

Post by wallgod »

So I wrote this procedure to determine whether or not a given input is valid hexadecimal. Unlike similar methods, this one checks for uppercase or lowercase variants, confirms that the input string is divisible by 2, and allows a list of ignore characters, like spaces etc.

Code: Select all

Procedure IsHex(hex.s, ignore.s="")
    Protected LenI.i, x.i
    For x = 1 To Len(ignore)
        hex = RemoveString(hex, Mid(ignore, x, 1), 1)
    Next
    LenI = Len(hex)
    If LenI % 2 <> 0
        ProcedureReturn 0
    EndIf
    For x = 1 To LenI
        If FindString("AaBbCcDdEeFf0123456789", Mid(hex, x, 1), 1) = 0
            ProcedureReturn 0
        EndIf
    Next
    ProcedureReturn 1
EndProcedure
Procrastinators unite... tomorrow!
User avatar
idle
Always Here
Always Here
Posts: 5915
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: My IsHex procedure

Post by idle »

nice thanks for sharing
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
kenmo
Addict
Addict
Posts: 2047
Joined: Tue Dec 23, 2003 3:54 am

Re: My IsHex procedure

Post by kenmo »

Why must its length be a multiple of 2?

Something like 3D4 is valid hex, equivalent to 03D4.

Unless you have a reason otherwise...?
infratec
Always Here
Always Here
Posts: 7623
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: My IsHex procedure

Post by infratec »

Hi,

hm...

I extended my version by the 'ignore' stuff. It looks longer, but I think it is more simple.
Decide by yourself

Code: Select all

Procedure IsHex(Hex$, Ignore$ = "")
    
  *HexPtr = @Hex$
  *IgnorePtr = @Ignore$
  For i = 0 To Len(Hex$) - 1
    Help.a = PeekA(*HexPtr + i)
    
    Ignore = #False
    For j = 0 To Len(Ignore$) - 1
      If Help = PeekA(*IgnorePtr + j)
        Ignore = #True
        Break
      EndIf
    Next j
    
    If Not Ignore
      If Help < '0' : ProcedureReturn #False : EndIf
      If Help > '9'
        If Help < 'A' : ProcedureReturn #False : EndIf
        If Help > 'F'
          If Help < 'a' Or Help > 'f': ProcedureReturn #False : EndIf
        EndIf
      EndIf
    EndIf
    
  Next i
  
  ProcedureReturn #True
  
EndProcedure
Best regards,

Bernd
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Re: My IsHex procedure

Post by PB »

Here's my version. Upper or lower case doesn't matter.
No option is provided to remove any characters. Just
a straight test of the supplied string.

Code: Select all

; Returns 1 if string is all hex chars, or 0 if not.

Procedure IsHex(text$)

  For p=1 To Len(text$)
    c$=Mid(text$,p,1)
    If c$<>"0" And Val("$"+c$)=0
      s=1 : Break
    EndIf
  Next

  ProcedureReturn 1-s

EndProcedure

Debug IsHex("FF") ; Returns 1
Debug IsHex("0D0a") ; Returns 1
Debug IsHex("abCDef") ; Returns 1

Debug IsHex("C00L d00d!") ; Returns 0
Debug IsHex("abCDefG") ; Returns 0
Debug IsHex("#255") ; Returns 0
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Re: My IsHex procedure

Post by blueznl »

You could also match it to a regexp...

Code: Select all

Global re_ishex = CreateRegularExpression(#PB_Any,"^[$]?[0-9a-fA-F]+$")

Procedure.i x_ishex(s.s)
  ProcedureReturn MatchRegularExpression(re_ishex,s)
EndProcedure

Debug x_ishex("a")
http://www.xs4all.nl/~bluez/purebasic/p ... 26.htm#top
Last edited by blueznl on Tue Oct 12, 2010 5:01 pm, edited 1 time in total.
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
breeze4me
Enthusiast
Enthusiast
Posts: 633
Joined: Thu Mar 09, 2006 9:24 am
Location: S. Kor

Re: My IsHex procedure

Post by breeze4me »

These don't depend on any PB functions.

Code: Select all

;DisableDebugger

Structure CharArray
  c.c[0]
EndStructure

Procedure IsHexStrPtr(*string.CharArray, *ignore.CharArray = 0)
  Protected i, idx, x, res
  If *string
    IsHexStrPtr_Loop:
    x = *string\c[i]
    i + 1
    
    If x = 0 : Goto IsHexStrPtr_Exit : EndIf  ;if null character then exit.
    
    If *ignore    ;skip over some characters.(case sensitive)
      idx = 0
      While *ignore\c[idx]
        If x = *ignore\c[idx] : Goto IsHexStrPtr_Loop : EndIf
        idx + 1
      Wend
    EndIf
    
    res = 1
    If x < '0' : Goto IsHexStrPtr_NotHex : EndIf
    If x <= '9' : Goto IsHexStrPtr_Loop : EndIf
    
    x | $20   ;into lowercase character.
    If x < 'a' : Goto IsHexStrPtr_NotHex : EndIf
    If x <= 'f' : Goto IsHexStrPtr_Loop : EndIf
    
    IsHexStrPtr_NotHex:
    res = 0
    IsHexStrPtr_Exit:
  EndIf
  ProcedureReturn res
EndProcedure

Procedure IsHexStr(string.s, ignore.s = "")
  Protected i, idx, x, res
  Protected *str.CharArray = @string, *ignore.CharArray = @ignore
  If string
    IsHexStr_Loop:
    x = *str\c[i]
    i + 1
    
    If x = 0 : Goto IsHexStr_Exit : EndIf  ;if null character then exit.
    
    If *ignore    ;skip over some characters.(case sensitive)
      idx = 0
      While *ignore\c[idx]
        If x = *ignore\c[idx] : Goto IsHexStr_Loop : EndIf
        idx + 1
      Wend
    EndIf
    
    res = 1
    If x < '0' : Goto IsHexStr_NotHex : EndIf
    If x <= '9' : Goto IsHexStr_Loop : EndIf
    
    x | $20   ;into lowercase character.
    If x < 'a' : Goto IsHexStr_NotHex : EndIf
    If x <= 'f' : Goto IsHexStr_Loop : EndIf
    
    IsHexStr_NotHex:
    res = 0
    IsHexStr_Exit:
  EndIf
  ProcedureReturn res
EndProcedure


;test.

Debug IsHexStrPtr(0, 0)  ;0
Debug IsHexStrPtr(0)  ;0
Debug IsHexStrPtr(@"", @"")  ;0
Debug IsHexStrPtr(@"", @" ")  ;0
Debug IsHexStrPtr(@"")  ;0
Debug IsHexStrPtr(@"      z", @" ")  ;0
Debug IsHexStrPtr(@"      ", @" ")  ;0
Debug IsHexStrPtr(@"      ")  ;0
Debug " "
Debug IsHexStrPtr(@"a d 1 9 84fdc1", @" ")  ;1
Debug IsHexStrPtr(@"a0 ad fe 99 84", @" ")  ;1
Debug IsHexStrPtr(@"a0 ad fe 99 84")  ;0
Debug IsHexStrPtr(@"0123456789abcdefABCDEF", @"")  ;1
Debug IsHexStrPtr(@"0123456789abcdefABCDEF")  ;1
Debug IsHexStrPtr(@"0123456789abcdefABCDEFg", @"")  ;0
Debug IsHexStrPtr(@"0123456789abcdefABCDEFg")  ;0
Debug IsHexStrPtr(@"0 ", @" ")  ;1
Debug IsHexStrPtr(@"0 g", @" ")  ;0
Debug IsHexStrPtr(@"0 aaG", @" g")  ;0

Debug " "
Debug IsHexStr("", "")  ;0
Debug IsHexStr("", " ")  ;0
Debug IsHexStr("")  ;0
Debug IsHexStr("      z", " ")  ;0
Debug IsHexStr("      ", " ")  ;0
Debug IsHexStr("      ")  ;0
Debug " "
Debug IsHexStr("a d 1 9 84fdc1", " ")  ;1
Debug IsHexStr("a0 ad fe 99 84", " ")  ;1
Debug IsHexStr("a0 ad fe 99 84")  ;0
Debug IsHexStr("0123456789abcdefABCDEF", "")  ;1
Debug IsHexStr("0123456789abcdefABCDEF")  ;1
Debug IsHexStr("0123456789abcdefABCDEFg", "")  ;0
Debug IsHexStr("0123456789abcdefABCDEFg")  ;0
Debug IsHexStr("0 ", " ")  ;1
Debug IsHexStr("0 g", " ")  ;0
Debug IsHexStr("0 aaG", " g")  ;0
wallgod
User
User
Posts: 48
Joined: Wed Oct 06, 2010 2:03 pm

Re: My IsHex procedure

Post by wallgod »

Here's my updated one, which doesn't require the input's length to be divisible by 2, and also makes sure the input isn't empty (which would have previously returned a false positive).

Code: Select all

Procedure.i IsHex(hex.s,ignore.s="")
    Protected x.i
    For x=1 To Len(ignore)
        hex=RemoveString(hex,Mid(ignore,x,1),1)
    Next
    If hex=""
        ProcedureReturn 0
    EndIf
    For x=1 To Len(hex)
        If FindString("AaBbCcDdEeFf0123456789",Mid(hex,x,1),1)=0
            ProcedureReturn 0
        EndIf
    Next
    ProcedureReturn 1
EndProcedure
And I'm very impressed by these two (PB & blueznl):
PB wrote:

Code: Select all

Procedure IsHex(text$)

  For p=1 To Len(text$)
    c$=Mid(text$,p,1)
    If c$<>"0" And Val("$"+c$)=0
      s=1 : Break
    EndIf
  Next

  ProcedureReturn 1-s

EndProcedure
blueznl wrote:

Code: Select all

Global re_ishex = CreateRegularExpression(#PB_Any,"^[$]?[0-9a-fA-F]+$")

Procedure x_ishex(s.s)
  ProcedureReturn MatchRegularExpression(re_ishex,s)
EndProcedure
Well done!
Procrastinators unite... tomorrow!
User avatar
kenmo
Addict
Addict
Posts: 2047
Joined: Tue Dec 23, 2003 3:54 am

Re: My IsHex procedure

Post by kenmo »

blueznl wrote:You could also match it to a regexp...
I was waiting for someone to say that. :)

The hex-checking part is easy with regexs, but how would you go about including the Ignore functionality? (No really, I'd like to know.)
wallgod
User
User
Posts: 48
Joined: Wed Oct 06, 2010 2:03 pm

Re: My IsHex procedure

Post by wallgod »

kenmo wrote:
blueznl wrote:You could also match it to a regexp...
I was waiting for someone to say that. :)

The hex-checking part is easy with regexs, but how would you go about including the Ignore functionality? (No really, I'd like to know.)
By removing the ignore characters from the string before checking against the regular expression. ;)
Procrastinators unite... tomorrow!
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Re: My IsHex procedure

Post by blueznl »

What would you like to ignore? If only a space, then add the space to the acceptable characters. Please give an example...
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
User avatar
kenmo
Addict
Addict
Posts: 2047
Joined: Tue Dec 23, 2003 3:54 am

Re: My IsHex procedure

Post by kenmo »

wallgod wrote:By removing the ignore characters from the string before checking against the regular expression. ;)
Well.... yes.... but I'm wondering how you would write character removal USING a regexp? I just started learning them this past year.
blueznl wrote:What would you like to ignore? If only a space, then add the space to the acceptable characters. Please give an example...
Nothing specific, I just figured you may want to incorporate the functionality in Wallgod's original posted code.
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Re: My IsHex procedure

Post by blueznl »

Well, I've stopped my fooling around with regexp when it started to get too confusing, so I limited myself to the simple things :-)
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
wallgod
User
User
Posts: 48
Joined: Wed Oct 06, 2010 2:03 pm

Re: My IsHex procedure

Post by wallgod »

kenmo wrote:
wallgod wrote:By removing the ignore characters from the string before checking against the regular expression. ;)
Well.... yes.... but I'm wondering how you would write character removal USING a regexp? I just started learning them this past year.
blueznl wrote:What would you like to ignore? If only a space, then add the space to the acceptable characters. Please give an example...
Nothing specific, I just figured you may want to incorporate the functionality in Wallgod's original posted code.
You wouldn't add the ignore characters using a regular expression because that defeats the point of making it customizable by a procedure parameter. Here's an example of how to use the regular expression method coupled with an ignore sequence:

Code: Select all

Global re_ishex = CreateRegularExpression(#PB_Any,"^[$]?[0-9a-fA-F]+$")

Procedure.i x_ishex(s.s,ignore.s="")
    Protected x.i
    For x=1 To Len(ignore):s=RemoveString(s,Mid(ignore,x,1),1):Next
    ProcedureReturn MatchRegularExpression(re_ishex,s)
EndProcedure

Debug x_ishex("x4A:xbf:x0d:x5B:x0F:x0F"); returns 0 {false}
Debug x_ishex("x4A:xbf:x0d:x5B:x0F:x0F", ":x"); returns 1 {true}

Debug x_ishex("4A bf 0d 5B 0F 0F"); returns 0 {false}
Debug x_ishex("4A bf 0d 5B 0F 0F", " "); returns 1 {true}
Procrastinators unite... tomorrow!
Post Reply