How to do mass Bit shift calculation in C# - c#

I have 2 eight Byte of Data, received as the RX CAN message,
so in total 128 bit, but not all the bit carries message. Each byte gives boolean value in specified bit like in the picture.
NOTE: This is the structure of first 8 byte, and bit Var Names are not as clean as in the picture.
At the moment I receive 85 bit of message excluding the Reserved bit.
Reserved are for the future usage if a message is need to be added.
I have to check the boolean value of the specified bit, and store the boolean value in an Array.
I am having difficulty in checking each of 85 bit and storing them in array, is there any more efficient way like using a function to check the bool status, and store the value in array using iteration? or any other,

You could just create a class to store your 8 bytes, and create read only properties to get the different flags, through left shift and bitwise AND. Each flag can return something like this (for example, this is W1_A, bit 0 of first byte):
return (bytes[0] & (1 << 0)) != 0;
So something like this:
public class CanMessage
{
private byte[] _bytes = new byte[8];
public CanMessage(byte[] bytes)
{
if (bytes == null || bytes.Length != 8)
{
throw new ArgumentException(nameof(bytes));
}
_bytes = bytes;
}
public bool W1_A => (_bytes[0] & (1 << 0)) != 0;
// ...
}
Which you can then use like this:
var msg = new CanMessage(new byte[] { 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA });
var w1a = msg.W1_A;

Have a look at BitArray, I think it does exactly what you need.
BitArray bitArray = new(inputBytes);
bool set = bitArray.Get(bitIndex);

This is what I'm talking about. It's a struct, so it should be immutable. If you need mutability, you probably want a class, but with a way to work with a [StructLayout(LayoutKind.Sequential)] struct to do interop with your CAN driver (and initialize instances of your class.
I'm doing this with two uints because you only show 64 bits, not 128. To access 128 bits, I'd use two ulongs and adjust my magic numbers.
Here's the basic struct. We'll be adding members to this:
[StructLayout(LayoutKind.Sequential)]
public struct CanBuffer
{
private uint First;
private uint Second;
}
We need a way to read a bit from that struct. I'm using two bytes here to index into the struct. The first one will tell you which byte you are interested in, the second which bit. So, to get the value of W3_C, it would be whichByte == 2, bitNum == 3:
private bool ReadBit(byte whichByte, byte bitNum)
{
uint whichItem = whichByte switch
{
(>= 0 and <= 3) => First,
(>= 4 and <= 8) => Second,
_ => throw new ArgumentOutOfRangeException(nameof(whichByte), "WhichByte is out of range")
};
if (bitNum > 31)
{
throw new ArgumentOutOfRangeException(nameof(bitNum), "BitNum is out of range");
}
var shiftBy = whichByte * 8 + bitNum;
return ((whichItem & (1 << shiftBy)) != 0);
}
With that in place, I can write a ton of properties that look like this:
public bool W1A => ReadBit(0, 0);
//skip a bunch
public bool W3D => ReadBit(2, 4);
//etc.
Now what I need is a way to map an array index to a (byte whichByte, byte bitNum) tuple that I can use with ReadBit:
private static Dictionary<int, (byte whichByte, byte bitNum)> addresses = new()
{
{1, (0, 0) },
{2, (0, 1) },
{3, (0, 3) }, //notice that (0, 2) is skipped
{4, (0, 5) },
{5, (1, 0) },
{6, (1, 1) },
//and so on
};
Note that the syntax (byte whichByte, byte bitNum) indicates a two-byte tuple.
With that in place, writing an indexer is easy:
public bool this[int index]
{
get
{
if (index < 0 || index > 84)
{
throw new IndexOutOfRangeException("Index is out of range");
}
var (whichByte, bitNum) = addresses[index];
return ReadBit(whichByte, bitNum);
}
}
With that all in place, you can populated a CanBuffer from a call to your CAN driver (treating it as a 64 or 128 bit buffer).
CanBuffer myBuffer;
InteropCallToCanDriverToPopulateBuffer(myBuffer); // this is up to you
Then to get the bit corresponding to W3_B (which, skipping the holes, is index 10), you'd do something like this:
bool w3_B = myBuffer[10];
Note that you are not creating an array, copying into an array, or doing anything else with an array. What you are doing is pretending to be an array by implementing an int-based indexer.
Also note, I haven't really tested this code (testing would be a lot of work - I figure you can figure it out)

Related

How to efficiently search raw byte data for first instance of specific DWORD value in C#?

In C/C++ you could do this O(n) with a pointer to a buffer and casting to 32bit datatype, but in C# given byte[] or IEnumerable<byte> and an int32 how might you efficiently find the first position of the DWORD in the byte buffer, ideally using built-in library methods?
I don't want to venture into unsafe code so I can of course search for a 4-element byte sub-buffer. But is there a neater way to take advantage of my search value being 32bits long?
Trivial workup (pseudo-ish):
int Find(IEnumerable<byte> buf, int val)
{
byte d = val & 0xff, c = (val >>8) & 0xff, b = (val >>16) & 0xff, a = (val>>24) & 0xff;
for(int i=0;i<buf.Length - 3;++i)
{
if(buf[i] == d && buf[i+1] == c && buf[i+2] == b && buf[i+3] == a)
return i
}
return -1;
}
Basically wondering if I can combine all 4 byte-wise checks with a single 32-bit check.
wondering if I can combine all 4 byte-wise checks with a single 32-bit check
Not without violating alignment. Some options you do have are:
a masked 32-bit comparison against the first part of the value for each of the 4 possible alignments (this will be testing 32, 24, 16, or 8 bits). After you get a success, you'll still have to test against the remaining bits
A SIMD comparison looking for the first byte (or most unique -- I certainly wouldn't want to search for 0x00 since there will be far more than 0.5% false positives) of the needle at 16 or so possible adjacent locations simultaneously. Once you get a match you need to test the three following bytes also.

C# private function, IncrementArray

Can someone please explain in layman's terms the workings of this C# code?
for (int pos = 0; pos < EncryptedData.Length; pos += AesKey.Length);
{
Array.Copy(incPKGFileKey, 0, PKGFileKeyConsec, pos, PKGFileKey.Length);
IncrementArray(ref incPKGFileKey, PKGFileKey.Length - 1);
}
private Boolean IncrementArray(ref byte[] sourceArray, int position)
{
if (sourceArray[position] == 0xFF)
{
if (position != 0)
{
if (IncrementArray(ref sourceArray, position - 1))
{
sourceArray[position] = 0x00;
return true;
}
else return false;
}
else return false;
}
else
{
sourceArray[position] += 1;
return true;
}
}
I'm trying to port an app to Ruby but I'm having trouble understanding how the IncrementArray function works.
IncrementArray increments all entries of a byte array, with any overflow being added to the previous index, unless it's index 0 already.
The entire thing looks like some kind of encryption or decryption code. You might want to look for additional hints on which algorithm is used, as this kind of code is usually not self-explaining.
It looks to me like a big-endian addition algorithm:
Let's say you've got a long (64 bit, 8 byte) number:
var bigNumber = 0x123456FFFFFFFF;
But for some reason, we've got it coming to us as a byte array in Big-endian format:
// Get the little endian byte array representation of the number:
// [0xff 0xff 0xff 0xff 0xff 0x56 0x34 0x12]
byte[] source = BitConverter.GetBytes(bigNumber);
// BigEndian-ify it by reversing the byte array
source = source.Reverse().ToArray();
So now you want to add one to this "number" in it's current form, while maintaining any carrys/overflows like you would in normal arithmetic:
// increment the least significant byte by one, respecting carry
// (as it's bigendian, the least significant byte will be the last one)
IncrementArray(ref source, source.Length-1);
// we'll re-little-endian-ify it so we can convert it back
source = source.Reverse().ToArray();
// now we convert the array back into a long
var bigNumberIncremented = BitConverter.ToInt64(source, 0);
// Outputs: "Before +1:123456FFFFFFFF"
Console.WriteLine("Before +1:" + bigNumber);
// Outputs: "After +1:12345700000000"
Console.WriteLine("After +1:" + bigNumberIncremented);

How can I save space when storing boolean data in c#

I need to store boolean data in Windows Azure. I want to make the space these take up as small as possible. What I have is about fifteen fields with values that are true of false.
field_1 = true;
field_2 = true;
field_a = false;
field_xx = true;
I had an idea that I could take these, convert the true and false to 1s and 0s and then store as a string something like 1101. Is there a simple way that I could do this coding and then uncode when getting the data out? Note that the field names are all different and so I can't use a fancy for loop to go through field names.
int bits = (field_1 ? 1 : 0) | (field_2 ? 2 : 0) | (field_3 ? 4 : 0) | (field_4 ? 8 : 0) | ...
field_1 = (bits & 1) != 0;
field_2 = (bits & 2) != 0;
field_3 = (bits & 4) != 0;
field_4 = (bits & 8) != 0;
...
I don't think you can even imagine how skeptical I am that this will help in any way, shape or form. 15 booleans is literally nothing.
Now, if you insist on going down this path, the best way would be to store them as a single int and use & to read them out and | to write them back in.
You can use a BitArray to pack the booleans into an int:
BitArray b = new BitArray(new bool[] { field_1, field_2, ..., field_xy });
int[] buffer = new int[1];
b.CopyTo(buffer, 0);
int data = buffer[0];
You can use a byte or int array. A byte can hold up to 8 booleans, an int up to 32. To hold up to 16 booleans you could use a byte array with two bytes, or a single int, depending on whether the overhead of an array or the unused bits in the int take up more space. You could also use the BitConverter class to convert a two byte array into a short.
To get the booleans back you create a BitArray from an array of byte or int:
BitArray b = new BitArray(new int[] { data });
field_1 = b[0];
field_2 = b[1];
...
field_xy = b[14];
Consider an enumeration with the [Flags] attribute
[Flags]
public enum Values
{
Field1 = 1,
Field2 = 2,
Field3 = 4,
Field4 = 8
}
Values obj = Field1 | Field2;
obj.HasValue(Field1); //true
obj.HasValue(Field3); //false
int storage = (int)obj;// 3
Don't bother. You're using boolean values, which are already about as small (for an individual value) as you can get (1 byte I believe). And the small amount of space that you might be able to save would not be worth the added complexity of your code, plus the time it would take you to develop it.
A few more thoughts: think how you'd use such a construct. Currently, if you look at field_1 and see a value of true, you don't have to look further into the implementation to figure out the actual value. However, let's say you had the following string: "100101011011010" (or an integer value of 19162, which would be more efficient). Is field_1 true, or is it false? It's not inherently obvious -- you need to go find the implementation. And what happens when you need to support more fields somewhere down the line? You'll save yourself a lot of heartache by sticking with what you've got.
Storing these as characters will take either 8 or 16 bits per value. I'd pack them into the an array of the longest unsigned integer available, using bit-shifting operations.
There is a great post on this at:
http://blog.millermedeiros.com/2010/12/using-integers-to-store-multiple-boolean-values/
You could do this with an int and using xor http://www.dotnetperls.com/xor
I saw a project that did this about 15 years ago. But it ended up with a limitation of 32 roles in the system (it used a 32 bit number). That product does not exist today :)
So do not do it, store values in an array or seperate fields.
you could use Enum with the flags attribute. You say you have 15 fields. So you could try using something like
[Flags]
enum Fieldvals
{
Field1, Field2, ....
}
take a look at http://msdn.microsoft.com/en-us/library/system.flagsattribute.aspx for the guidelines
Check out the BitArray class, it should do exactly what you need.
Example:
BitArray bits = new BitArray
(
new bool[]
{
false, true, false, false, true,
false, true, false, true, false,
false, true, false, true, false
}
);
short values = 0;
for( int index = 0; index < bits.Length; index++ )
{
if( bits[ index ] )
values |= ( short )( values | ( 1 << index ) );
}
Console.WriteLine( Convert.ToString( values, 2 ) );
You now have 15 bool variables stored in a single 16 bit field.
You can store your flags in an integer value. Here are some helper methods to accomplish that:
// Sets the given bit position in the UInt32 to the specified boolean value
public static UInt32 Set(UInt32 u, int position, bool newBitValue)
{
UInt32 mask = (UInt32)(1 << position);
if (newBitValue)
return (u | mask)
else
return (u & ~mask);
}
// Gets a bit value from the supplied UInt32
public static bool Get(UInt32 u, int position)
{
return ((u & (UInt32)(1 << position)) != 0);
}

Convert into to byte array and insert into other array

I work in a c# wpf application in which I want to do several things. I'm working with byte arrays to compose MIDI Show Control messages (specified in the MSC Specification 1.0).
The structure of this message is that a 0x00 byte is like a comma between all the parts of the message. I compose a message like this:
byte[] data =
{(byte)0xF0, // SysEx
(byte)0x7F, // Realtime
(byte)0x7F, // Device id
(byte)0x02, // Constant
(byte)0x01, // Lighting format
(commandbyte), // GO
(qnumber), // qnumber
(byte)0x00, // comma
(qlist), // qlist
(byte)0x00, // comma
(byte)0xF7, // End of SysEx
};
I want the user to fill in unsigned integers (like 215.5) and I want to convert these numbers to bytes (without 0x00 bytes because then the message is interpreted wrong).
What is the best way to convert the numbers and place the byte array in the places mentioned above?
You might want to take a look at the BitConverter class, which is designed to convert base types into byte arrays.
http://msdn.microsoft.com/en-us/library/system.bitconverter.aspx
But I'm not sure what guidance you are seeking for placing the items into your array. Array.Copy can work to simply copy the bytes in, but maybe I am misunderstanding.
Found it out like this:
Used someone else's converter code like this:
static byte[] VlqEncode(int value)
{
uint uvalue = (uint)value;
if (uvalue < 128)
return new byte[] { (byte)uvalue };
// simplest case
// calculate length of buffer required
int len = 0;
do
{
uvalue >>= 7;
} while (uvalue != 0);
// encode
uvalue = (uint)value;
byte[] buffer = new byte[len];
int offset = 0;
do { buffer[offset] = (byte)(uvalue & 127);
// only the last 7 bits
uvalue >>= 7; if(uvalue != 0) buffer[offset++] |= 128;
// continuation bit
} while (uvalue != 0);
return buffer;
}
Then I use this to convert the integer:
byte[] mybytearray = VlqEncode(integer);
I then make a new arraylist in which I add each item in sequence:
ArrayList mymessage = new ArrayList();
foreach(byte uvalue in mymessage)
{
mymessage.Add((byte)uvalue);
}
mymessage.Add((byte)0x00);
`
and so on until I have the correct message. I then only have to convert this a byte array like this:
byte[] data = new byte[mymessage.count];
data = (byte[])mymessage.ToArray(typeof(byte));`

Why does the BitConverter return Bytes and how can I get the bits then?

As input I get an int (well, actually a string I should convert to an int).
This int should be converted to bits.
For each bit position that has a 1, I should get the position.
In my database, I want all records that have an int value field that has this position as value.
I currently have the following naive code that should ask my entity(holding the databaseValue) if it matches the position, but obviously doesn't work correctly:
Byte[] bits = BitConverter.GetBytes(theDatabaseValue);
return bits[position].equals(1);
Firstly, I have an array of byte because there apparantly is no bit type. Should I use Boolean[] ?
Then, how can I fill this array?
Lastly, if previous statements are solved, I should just return bits[position]
I feel like this should somehow be solved with bitmasks, but I don't know where to start..
Any help would be appreciated
Your feeling is correct. This should be solved with bitmasks. BitConverter does not return bits (and how could it? "bits" isn't an actual data type), it converts raw bytes to CLR data types. Whenever you want to extract the bits out of something, you should think bitmasks.
If you want to check if a bit at a certain position is set, use the & operator. Bitwise & is only true if both bits are set. For example if you had two bytes 109 and 33, the result of & would be
0110 1101
& 0010 0001
-----------
0010 0001
If you just want to see if a bit is set in an int, you & it with a number that has only the bit you're checking set (ie 1, 2, 4, 8, 16, 32 and so forth) and check if the result is not zero.
List<int> BitPositions(uint input) {
List<int> result = new List<int>();
uint mask = 1;
int position = 0;
do {
if (input & mask != 0) {
result.Add(position);
}
mask <<= 1;
position++;
} while (mask != 0);
return result;
}
I suspect BitArray is what you're after. Alternatively, using bitmasks yourself isn't hard:
for (int i=0; i < 32; i++)
{
if ((value & (1 << i)) != 0)
{
Console.WriteLine("Bit {0} was set!", i);
}
}
Do not use Boolean. Although boolean has only two values, it is actually stored using 32 bits like an int.
EDIT: Actually, in array form Booleans will be packed into bytes, not 4 bytes.

Categories

Resources