0

I have read through the answers here https://stackoverflow.com/a/14332574/44080

I've also tried to produce equivalent VB.net code:

Option Strict ON

Public Function ParseHex(hexString As String) As Byte()
    If (hexString.Length And 1) <> 0 Then
        Throw New ArgumentException("Input must have even number of characters")
    End If
    Dim length As Integer = hexString.Length \ 2
    Dim ret(length - 1) As Byte
    Dim i As Integer = 0
    Dim j As Integer = 0
    Do While i < length
        Dim high As Integer = ParseNybble(hexString.Chars(j))
        j += 1
        Dim low As Integer = ParseNybble(hexString.Chars(j))
        j += 1
        ret(i) = CByte((high << 4) Or low)
        i += 1
    Loop

    Return ret
End Function

Private Function ParseNybble(c As Char) As Integer
    If c >= "0"C AndAlso c <= "9"C Then
        Return c - "0"C
    End If
    c = ChrW(c And Not &H20)
    If c >= "A"C AndAlso c <= "F"C Then
        Return c - ("A"C - 10)
    End If
    Throw New ArgumentException("Invalid nybble: " & c)
End Function

Can we remove the compile errors in ParseNybble without introducing data conversions?

Return c - "0"c Operator '-' is not defined for types 'Char' and 'Char'

c = ChrW(c And Not &H20) Operator 'And' is not defined for types 'Char' and 'Integer'

Community
  • 1
  • 1
Charles Okwuagwu
  • 10,538
  • 16
  • 87
  • 157
  • Why `Do While` instead of `For`? – Konrad Rudolph Aug 18 '15 at 14:27
  • @KonradRudolph. Thanks for that. – Charles Okwuagwu Aug 18 '15 at 14:36
  • I don't know how the performance compares, but why re-invent? see: [SoapHexBinary Class](https://msdn.microsoft.com/en-us/library/system.runtime.remoting.metadata.w3cxsd2001.soaphexbinary%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396) `Dim bytes As Byte() = System.Runtime.Remoting.Metadata.W3cXsd2001.SoapHexBinary.Parse(hexString).Value` – TnTinMn Aug 18 '15 at 18:32

2 Answers2

1

As it stands, no.

However, you could change ParseNybble to take an integer and pass AscW(hexString.Chars(j)) to it, so that the data conversion takes place outside of ParseNybble.

Andrew Morton
  • 24,203
  • 9
  • 60
  • 84
  • Solves the Compiler errors but we still do a conversion AscW(hexString.Chars(j)). IS the C# variant also doing same conversion implicitly? – Charles Okwuagwu Aug 18 '15 at 14:21
  • @CharlesO Yes of course it is (actually no, but the code behind will be the same, because in both cases we’re actually just operating on raw numeric values). That said, why not use the `Select Case` variant? I somewhat doubt that the `If` variant is faster, although who knows what the compiler is doing here. – Konrad Rudolph Aug 18 '15 at 14:28
  • @KonradRudolph i am currently using the `Select Case` variant until i can find an alternative. IF you follow the discussion on that source SO post, you might see why the other variants *might* be faster – Charles Okwuagwu Aug 18 '15 at 14:33
  • @CharlesO I’ve seen the discussion, and “might be faster” is pretty vague. And microbenchmarks are hard to get right, very few posted on here do proper statistical analysis. At any rate, somebody mentioned using a lookup table and that’s indeed a good idea as well (but again, there may be a reason why this isn’t faster — the .NET compiler and JIT does a lot of funky stuff). – Konrad Rudolph Aug 18 '15 at 14:43
  • @KonradRudolph the lookup table option looks interesting. – Charles Okwuagwu Aug 18 '15 at 14:49
0

This solution is much much faster than all the alternative i have tried. And it avoids any ParseNybble lookup.

Function hex2byte(s As String) As Byte()
    Dim l = s.Length \ 2
    Dim hi, lo As Integer
    Dim b(l - 1) As Byte

    For i = 0 To l - 1
        hi = AscW(s(i + i))
        lo = AscW(s(i + i + 1))

        hi = (hi And 15) + ((hi And 64) >> 6) * 9
        lo = (lo And 15) + ((lo And 64) >> 6) * 9

        b(i) = CByte((hi << 4) Or lo)
    Next

    Return b
End Function
Charles Okwuagwu
  • 10,538
  • 16
  • 87
  • 157