Getting and setting single bits in a byte-array using vb.net - vb.net

I have a byte array with 512 Elements and need to get and set a single bit of a byte in this array.
The operation must not change any other bits, only the specified one.
So if I have a byte like &B00110011 and would like to change the third bit to 1 it should be &B00110111.
Like this:
Dim myarray(511) as byte
myarray(3).2 = 1 ---> This would change the third bit (start counting at 0) of the third byte to 1
I know it should be easily possible using bit-masking but I don't have the time to try for days to get it working.
Thanks for help!!!
Jan

A simple way to do this is using shifts. If you want to set the Nth bit of a number to 1:
mask = 1 << n ' if n is 3, mask results in 00001000
bytevalue = bytevalue or mask
To set a bit as 0:
mask = 255 - (1 << n) ' if n is 3, mask results in 11110111
bytevalue = bytevalue and mask
In both examples, bytevalue is the byte in which you want to alter and mask is also a byte.
EDIT: To retrieve the state of a bit easily is a lot like setting a bit, Where IsSet is a boolean:
mask = 1 << n ' just as above
IsSet = (bytevalue and mask) <> 0

Why don't you use the BitArray class?

Related

Convert 8 bytes into a Double in VB.net

I'm reading an ancient data file that is basically a flattened object store with type flags - for instance, 1=Int16, 2=Int32. To read the Int32's, for instance, I read 4 bytes out of the stream and then did this:
If B.Length >= 2 + Offset Then
Ans = Convert.ToUInt16(B(1 + Offset) * 256 + B(0 + Offset))
End If
Now I am at a bit of a loss how to do the 3=Double. These are 8-byte values, IEEE I assume. There is a Convert.ToDouble(byte), but that's not the same thing, that just returns a Double containing a value from 0 to 255. Likewise, Convert.ToDouble(Int64) basically just casts the value to Double.
So what's the trick here? I found threads for doing it in VB6 and C, but not VB.net.

How to Hash/checksum of string

So I have a generator that creates a 26 hexadecimal character string that has a balance of ones and zeros when converted to binary. Actually 26.5.the first half of the 27th characters binary value is stored in a buf. and the last half is used to make the first 106 bits nice and even. Or should at least. How would I use the binary remnants in the buf to generate the the 27th char and to make the last 22 bits into a hash/checksum for the first 106? below is my generator.
Dim rnd As New Random()
Dim bin As New StringBuilder()
Dim buf As Integer = 0, bufLen As Integer = 0, left As Integer = 53
For i As Integer = 106 To 0 Step -1
buf <<= 1
If rnd.[Next](i) < left Then
buf += 1
left -= 1
End If
If System.Threading.Interlocked.Increment(bufLen) = 4 Then
bin.Append("0123456789abcdef"(buf))
bufLen = 0
buf = 0
End If
Next
Dim b As String = bin.ToString()
TextBox1.Text = (b)
How would I add on to this completing the process?
You've got 106 to 0 step -1, which means 107 iterations creating 26 hex digits with three further bits in buf (though the last one's guaranteed to be 0)... you might as well make it 108 and have it add an extra hex digit to bin - it doesn't matter that it's also 0, then you can apply any >=22 bit hash/checksum algo you like to the data in bin and append the hash/checksum value - you obviously know how to slice the least significant 4 bits off the left, generate the hex digit, and rotate - the last time you can AND with 3 and OR or XOR the value over the final hex digit you generated - setting the two trailing 0s added above. Googling "VB checksum" turns up lots of example code. If you get stuck, post your code and specific problem.
Separately, I don't know VB so maybe there's some weird reason, but I can't imagine why you're using what appears to be a threadsafe increment for a local variable which I'd assume in on the executing thread's stack and inaccessible to other threads?

Bitwise operations, combining 3 bytes to long

I am trying to combine three Byte values to one Long value, like System.Drawing.Color.ToArgb() does.
I've looked up reference source code to find it and converted it to VB .NET:
Return CLng((CInt(red) << 16 Or CInt(green) << 8 Or blue Or CInt(alpha) << 24) And -1)
It works fine of course, but I don't really understand why alpha shifted by 24 is last, not first (so it would be in nice order 24, 16, 8). I don't really understand bitwise operations a lot. Also, this code snippet works for 4 bytes, which is redundant for me, I need just three bytes and I wonder if Long is still required when bytes are only three, wouldn't Integer do just fine in this case?
So, my question is, how do I rewrite this code to work with just 3 parameters? Do I need to use Long? And, I know this is silly, but is it possible to make byte shifting in order 16,8,0 instead of 16,8,0,24? It's really just aesthetics, but I am awful perfectionist.
Thanks in advance!
Aaron
Here are some different ways. The order of the OR's does not matter. I added some debugs so you can see the results as you go.
Private Sub Button1_Click(sender As System.Object, _
e As System.EventArgs) Handles Button1.Click
Dim bar As Integer '32 bits
'three byte values
Dim x As Byte = 66
Dim y As Byte = 65
Dim z As Byte = 82
'desired byte order
'0xyz
'one byte at a time
bar = 0
bar = bar Or (CInt(x) << 16)
Debug.WriteLine(Convert.ToString(bar, 2).PadLeft(32, "0"c))
bar = bar Or (CInt(y) << 8)
Debug.WriteLine(Convert.ToString(bar, 2).PadLeft(32, "0"c))
bar = bar Or (CInt(z) << 0) 'bar Or CInt(z)
Debug.WriteLine(Convert.ToString(bar, 2).PadLeft(32, "0"c))
'or as single statement
bar = 0 Or (CInt(x) << 16) Or (CInt(y) << 8) Or CInt(z)
Debug.WriteLine(Convert.ToString(bar, 2).PadLeft(32, "0"c))
'in any order
bar = 0 Or CInt(z) Or (CInt(y) << 8) Or (CInt(x) << 16)
Debug.WriteLine(Convert.ToString(bar, 2).PadLeft(32, "0"c))
'check results
Dim foo() As Byte = BitConverter.GetBytes(bar) 'get the individual bytes
Array.Reverse(foo) 'reverse
Debug.WriteLine(System.Text.ASCIIEncoding.ASCII.GetChars(foo, 1, 3))
End Sub
It doesn't matter, a OR b is the same value as b OR a. The OR operator is commutative, just like the + and * operators.
An Integer can store the value just fine, it has 32 bits. Using UInteger instead can be useful to deal with alpha values larger than 127 turning the value negative. Which will give you a bit of a headache when you try to read the alpha value back. Sign extension produces a large value, fixed by AND-ing with 255. Long was common in VB6 code since its Integer type had only 16 bits, not an issue in vb.net.
I'm not familiar with VB.NET, but in general there is no right or wrong order of the shift count. It can be 24, 16, 8, 0 or 16, 24, 0, 8 or any other order.
And regrading the variable type: There are 8-bit, 16-bit and 32-bit variables. That means you must define a 32-bit type (long) in order to have room for your three bytes.
For easy access, leave the 8 MSB bits as 0 so you can use it as a 24-bit value (0x00YYYYYY).

vb.net - hex, bitwise question

I'm trying to figure out how to calculate the lower 7 bits and 7-13 bits of two hex numbers.
Here is some example c code, just need this in vb.net:
serialBytes[2] = 0x64 & 0x7F; // Second byte holds the lower 7 bits of target.
serialBytes[3] = (0x64 >> 7) & 0x7F; // Third data byte holds the bits 7-13 of target
The 0x7F is a constant so the only number that changes based off input is the 0x64.
Can someone help me out?
The code translates into this VB code:
serialBytes(2) = &h64 And &h7F
serialBytes(3) = (&h64 >> 7) And &h7F
If the hex value 64 is actually a variable input, just replace &h64 with the input variable. If the input is an integer, you have to cast the results to byte, though:
serialBytes(2) = CType(value And &H7F, Byte)
serialBytes(3) = CType((value >> 7) And &H7F, Byte)
VB.NET has no bit shift operators, but does have the bitwise operator And:
set bits1to7 = value And &H007F
set bits8to14 = value And &H3F80
Edit:
VB.NET does have bit shift operators (my bad) since .NET Framework 1.1, so the more systematic approach is indeed also possible:
set bits1to7 = value And &H7F
set bits8to14 = (value >> 7) And &H7F

first 16 bit of a 32 bit hex

Please excuse my lack of knowledge here but could someone let me know how i can get the first 16 bits of a 32 bit hex number.
That depends on what you mean by "first". Given a number, such as 0xdeadbeef, would you consider 0xdead or 0xbeef to be "first"?
If the former, divide the number by 65536 (as an integer). If the latter, compute the modulus to 65536.
This is of course also doable with binary operators such as shift/and, I'm just not sure sure how to express that in your desired language. I'm sure there will be other answers with more precise details.
Assuming by first, you mean least value?
if My32BitNumber is an int
dim f16 as integer = &hFFFF and My32BitNumber
If you're actually looking at a 32 bit number e.g. Gee, what are the first 16 bits of DEADBEEF
that would be the last four hex digits BEEF
& it with 0xffff.
int input = 0xabcd;
int first2Bytes = input & 0xffff;
Dim i As Integer = &HDEADBEEF
Dim s16 As UShort
s16 = i And &HFFFF 'BEEF
'or
s16 = (i >> 16) And &HFFFF 'DEAD
This will get you the 32 bit number as a four byte array:
Dim bytes As Byte() = BitConverter.GetBytes(number)
To get the first two bytes as a signed 16 bit number:
Dim first As Int16 = BitConverter.ToInt16(bytes, 0)
To get the first two bytes as an unsigned 16 bit number:
Dim first As UInt16 = BitConverter.ToUInt16(bytes, 0)
This is of course a bit slower than using bit shifts or division, but it handles the sign bit (the most significant bit) correctly, which you may have problems with using bit shift or division.
You can also get the first two bytes as a 16 bit unsigned number and assign it to an Integer:
Dim first As Integer = BitConverter.ToUInt16(bytes, 0)
(Getting a signed 16 bit number and assign to an Integer means that the sign bit would also be copied to the top 16 bits of the Integer, which is probably not desired.)
If you want the last two bytes (least significant) instead of the first two (most significant), just change the index in the ToUInt16/ToInt16 call from 0 to 2.