Page 1 of 1

My IsHex procedure

Posted: Mon Oct 11, 2010 11:34 pm
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

Re: My IsHex procedure

Posted: Tue Oct 12, 2010 4:46 am
by idle
nice thanks for sharing

Re: My IsHex procedure

Posted: Tue Oct 12, 2010 5:05 am
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...?

Re: My IsHex procedure

Posted: Tue Oct 12, 2010 7:35 am
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

Re: My IsHex procedure

Posted: Tue Oct 12, 2010 10:45 am
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

Re: My IsHex procedure

Posted: Tue Oct 12, 2010 11:00 am
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

Re: My IsHex procedure

Posted: Tue Oct 12, 2010 11:32 am
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

Re: My IsHex procedure

Posted: Tue Oct 12, 2010 1:10 pm
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!

Re: My IsHex procedure

Posted: Wed Oct 13, 2010 2:39 am
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.)

Re: My IsHex procedure

Posted: Wed Oct 13, 2010 12:07 pm
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. ;)

Re: My IsHex procedure

Posted: Wed Oct 13, 2010 3:00 pm
by blueznl
What would you like to ignore? If only a space, then add the space to the acceptable characters. Please give an example...

Re: My IsHex procedure

Posted: Wed Oct 13, 2010 11:07 pm
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.

Re: My IsHex procedure

Posted: Thu Oct 14, 2010 7:36 am
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 :-)

Re: My IsHex procedure

Posted: Thu Oct 14, 2010 6:56 pm
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}