I am doing me university project and facing a big issue. i am developing a UI on C# visual studio 2010. I need to open a serial connection and feed some values into the micro controller. basically i have nodes with 24 bits addresses (3 bytes) e.g 0x78A26F.
i take my input from user in the GUI in a text Box. the user shall enter this 78A26F and i want that the serial port sends the following data 0x6F 0xA2 0x78.
But the user input is saved as a string and when i send it through serial connection, the ASCII are sent e.g 0x37 0x38 0x41 0x32 0x36 0x46. i can do the processing in the uC and perform some checks to subtract 0x30 if between 0x30 and 0x39 or subtract 0x37 if between 0x41 and 0x46. but i do not want to use the uC for this calculations. i want to implement some algorithm in the GUI c# for sending the correct HEX value. So i wrote the following program. but i am getting an error. "Value was either too large or too small for an unsigned byte." at code line stating (data[2 - i] = Convert.ToByte(x*16 + y)).
I am unable to figure out this issue and fed up now as this should not happen in any case.
if anyone can help me in this regard, either with this code or any other algo/method, i will be really thankful. please, I would prefer never to implement some algo on uC.
Thanks
Maleeha
/***********************************************************************/
/*The code for opening the serial connection and converting it appropriately*/
/***********************************************************************/
byte[] conversion()
{
string text = label16.Text.ToUpper(); // if user enters not capital letters
byte[] data = new byte[3];
int x, y;
bool valid;
for (int i = 2; i >= 0; i--)
{
valid = true;
x = (Convert.ToInt32(Convert.ToChar(text[2 * i + 1])));
y = (Convert.ToInt32(Convert.ToChar(text[2 * i]))); // I want to first send the 0x6F then 0xA2 and finally 0x78. ToChar is so that i can check for A-F
if(x >= 48 || x <= 57) // i,e it is already a number
x = Convert.ToInt32(text[2 * i + 1]);
else if (x >= 65 || x <= 70) // it is between A-F
x = x - 55; // in case of A, i get 10
else // any other value i.e greater than F or any other.
{
valid = false;
break;
}
if (y >= 48 || y <= 57) // same for y
y = Convert.ToInt32(text[2 * i]);
else if (y >= 65 || y <= 70)
y = y - 55;
else
{
valid = false;
break;
}
if (valid == true)
data[2 - i] = Convert.ToByte(x*16 + y); // max will be 15*16 + 15 = 255 which should be OK for convert.ToByte.
}
return data;
}
void serial(byte[] text)
{
SerialPort serialPort1 = new SerialPort();
//configuring the serial port
serialPort1.PortName = "COM1";
serialPort1.BaudRate = 9600;
serialPort1.DataBits = 8;
serialPort1.Parity = Parity.None;
serialPort1.StopBits = StopBits.One;
//opening the serial port
serialPort1.Open();
//write data to serial port
serialPort1.Write(text, 0, 3);
//close the port
serialPort1.Close();
}
/***********************************************************************/
private void button3_Click(object sender, EventArgs e)
{
byte[] data = conversion();
serial(data);
}
The .NET framework already supports converting hex strings. Make your code look like this:
uint value;
if (!uint.TryParse(label16.Text, // Ought to be a text box
System.Globalization.NumberStyles.HexNumber, null, out value)) {
MessageBox.Show("Invalid hex value");
return;
}
serialPort1.Write(BitConverter.GetBytes(value), 0, 3);
Can you use the built in methods?
byte[] conversion()
{
string text = label16.Text;
for (int i = 0; i < text.length - 1; i+=2) //Make sure to increment by 2, currently ignores a trailing char.
{
string hex = text.Substring(i * 2, 2);
data[i / 2] = Convert.ToByte(hex, 16);
}
return data;
}
Not the cleanest code, but you get the idea.
You should wrap the data[i / 2] = Convert.ToByte(hex, 16); line in a try catch, but I am not sure if you want to do that for the line or just call the method in a try catch.
The problem with your code seems to be the lines x = Convert.ToInt32(text[2 * i + 1]); and y = Convert.ToInt32(text[2 * i]); which are converting the char directly to an int. to get your solution to work you should do something like x = ((byte)text[2 * i + 1]) - 48;
Your call to Convert.ToInt32() isn't doing what you think it's doing.
Here's an overview on different usages of Convert.ToInt32():
http://msdn.microsoft.com/en-us/library/bb311038.aspx
There are three problems with the logic:
Look at your if statements that determine if x and y fall within certain number ranges. Consider what happens if x = 100. Remember that || means "OR".
The conversion if x or y is a character representing a number using Convert.ToInt32() needs to take a string, not a character, in order to get the conversion you're looking for.
Once you get past those two, examine your output of your conversion() method. You should notice the final issue.
Related
I am currently reading data coming in continuously from an i2c sensor connected to an Arduino and capturing the data successfully in Visual Studios. The sensor is getting 4 different X, Y values and then sends them via Serial.Print in the format of:
X1,Y1,X2,Y2,X3,Y3,X4,Y4 (Where X1 - X4 and Y1 - Y4 are values that range betwen 0-1023 i.e., 1023,1023,1023,1023,1023,1023,1023,1023) which is then followed up with a Serial.println("") command. This whole process is repeated continuously until turned off. Arduino code:
for (i=0;i<16;i++) { data_buf[i]=0; }
i=0;
while(Wire.available() && i < 16) {
data_buf[i] = Wire.read();
i++;
}
Ix[0] = data_buf[1];
Iy[0] = data_buf[2];
s = data_buf[3];
//Ix[0] += (s & 0x30) <<4;
Ix[0] = data_buf[1] | ((data_buf[3] >> 4) & 0x03) << 8;
Iy[0] = data_buf[2] | ((data_buf[3] >> 6) & 0x03) << 8;
//Ix[0] = Ix[0] / test;
Ix[1] = data_buf[4];
Iy[1] = data_buf[5];
s = data_buf[6];
Ix[1] += (s & 0x30) <<4;
Iy[1] += (s & 0xC0) <<2;
Ix[2] = data_buf[7];
Iy[2] = data_buf[8];
s = data_buf[9];
Ix[2] += (s & 0x30) <<4;
Iy[2] += (s & 0xC0) <<2;
Ix[3] = data_buf[10];
Iy[3] = data_buf[11];
s = data_buf[12];
Ix[3] += (s & 0x30) <<4;
Iy[3] += (s & 0xC0) <<2;
for(i=0; i<4; i++)
{
if (Ix[i] < 1000)
Serial.print("");
if (Ix[i] < 100)
Serial.print("");
if (Ix[i] < 10)
Serial.print("");
Serial.print( int(Ix[i]) );
Serial.print(",");
if (Iy[i] < 1000)
Serial.print("");
if (Iy[i] < 100)
Serial.print("");
if (Iy[i] < 10)
Serial.print("");
Serial.print( int(Iy[i]) );
if (i<3)
Serial.print(",");
}
Serial.println("");
delay(15);
}
What I'm have problems with, is converting those values from within Visual Studios so that I can pass on the data as individual integer values. What I have now:
void _spManager_NewSerialDataRecieved(object sender, SerialDataEventArgs e)
{
if (this.InvokeRequired)
{
// Using this.Invoke causes deadlock when closing serial port, and BeginInvoke is good practice anyway.
this.BeginInvoke(new EventHandler<SerialDataEventArgs>(_spManager_NewSerialDataRecieved), new object[] { sender, e });
return;
}
int maxTextLength = 1000; // maximum text length in text box
if (tbData.TextLength > maxTextLength)
tbData.Text = tbData.Text.Remove(0, tbData.TextLength - maxTextLength);
// This application is connected to a Arduino sending ASCCI characters, so data is converted to text
string Rawstr = Encoding.ASCII.GetString(e.Data);
//Get values that are between the ',' from e.Data and store them in our new array
string[] str = Rawstr.Split(',');
//Convert str array into new int[] array (or similar) I've tried multiple things with no success
??????
//This results in a "Input string was not in a correct format" error.
int xx = Convert.ToInt32(str[0]);
tbData.AppendText(Rawstr);
tbData.ScrollToCaret();
}
This is where I am currently stuck. I believe I have an issue where pretty much an infant number of values are going into the string[] str because I don't have a limit on it before it starts to put new values into/and replacing the string values already in it.
Any guidance is appreciated.
You can use Linq.
First split on ,, skip the empty and whitespace characters, then trim of the first character (X or Y) and convert the remaining part to an integer.
String Rawstr = "x1,y1,x2,y2," + Environment.NewLine;
Int32[] integers = Rawstr.Split(new [] { ',' }, StringSplitOptions.None).Where(s => !String.IsNullOrWhiteSpace(s)).Select(s => Convert.ToInt32(s.Substring(1))).ToArray();
For "x1,y1,x2,y2," you get an integer array containing [1,1,2,2].
What is this function, I mean for the part where is 0x30? Hex value that points to ASCII table?
This is probably basic stuff, and I'm without knowledge currently.
getCompleteCode("11111");
private string getCompleteCode(string code)
{
var b1 = 10;
var b2 = 20;
var sum = 0;
for (var i = code.Length - 1; i >= 0; i--)
{
var z = code[i] - 0x30;
sum = sum + (z + b1) * b2;
}
Console.WriteLine(sum);
return code;
}
A wonderful example of how one should not implement a logic:
// why not static?
private string getCompleteCode(string code)
{
// what does "b1" as well as "b2" stand for?
var b1 = 10;
var b2 = 20;
var sum = 0;
// the reason for the loop being in reversed order?
for (var i = code.Length - 1; i >= 0; i--)
{
// the question put - what does 0x30 stand for - it's ascii code of '0' char
// so, why magic code 0x30 instead of evident '0'?
var z = code[i] - 0x30;
sum = sum + (z + b1) * b2;
}
// what if I want to compute it in, say, WinForms??
// Never mix business logic (computing some code) and UI (output)
Console.WriteLine(sum);
// we've done a lot of stuff just to return the initial input??
return code;
}
My suggestion for the implementation (providing that code is guaranteed to be a correct input):
//TODO: think on a better name for the method
private static int getCompleteCode(string code) {
return code.Sum(c => (c - '0' + 10) * 20);
}
...
Console.WriteLine(getCompleteCode("11111"));
As others have explained, var z = code[i] - 0x30 is standard code to get the value of a digit character. As Glorin Oakenfoot mentioned, this code doesn't do any bounds checking. So it works great for '0' - 0x30 (effectively, that's '0' - '0', by the way), and for '9' - 0x30. But it will also produce weirdness like 'A' - 0x30 = 32.
Glorin's comment is also right - the rest of the numbers seem very context specific. It seems likely to be a hash function - it calculates a mostly-unique number for a given string. I'll walk you through the loop, but what it's doing doesn't make any real sense. Rather than inputting "11111", let's look at "12345":
1st time through loop: i = 4, code[i] = '5', z = 5, sum = 0 + 15 * 20 = 300
2nd time through loop: i = 3, code[i] = '4', z = 4, sum = 300 + 14 * 20 = 580
3rd time through loop: i = 2, code[i] = '3', z = 3, sum = 580 + 13 * 20 = 840
4th time through loop: i = 1, code[i] = '2', z = 2, sum = 840 + 12 * 20 = 1080
5th time through loop: i = 0, code[i] = '1', z = 1, sum = 1080 + 11 * 20 = 1300
As I mentioned, it's likely this is used for hashing. Every string of digits you enter is likely to have a unique integer code. Hashing of strings can improve efficiency. If nothing else, it gives you a fairly robust test for comparison. See https://en.wikipedia.org/wiki/Hash_function
Of course, most string hash functions don't do the conversion from digit to int. And if the function requires that the input be only digits, as seems to be implied by the conversion to int, the simplest hash for this string is to just parse it to an integer.
The other thing this reminds me of is an attempt to parse an integer string to a digit. That would be very similar, but note the differences below:
var sum = 0
for (var i = 0; i < code.Length; i++)
{
var z = code[i] - '0' // this is the same as - 0x30, but more clear to read
sum = sum * 10 + z
}
Considering the name of the function, though, it seems much more likely that it's intended as a hash function.
0x30 is the ascii value of '0' ... it is normally used to subtract from a character, e.g. '8' - 0x30 = 8 after casting to an integer (either implicitly or explicitly like here).
0x30 y the hex ASCII code for number 0, so z will actually give you the digit in number type.
It removes decimals. It = whatever number rounded.
I'm having "Input string was not in a correct format." error from this code
rainTb.Text = " " + int.Parse(parsed[0]) * 100 / 1023;
There's no error in my code. Except for the error above. I've made a calculation to extract the analogue value (above calculation) from Arduino hardware via serial communication (cable). Arduino works fine though. Everything was fine though until this error shows up... Why? cries
p/s : I've gone through many solutions but still.. So here I am now. Sorry for my English
private void ProcessCOMRx(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(COMRx))
{
systemTb.Text = "Processing Data...";
systemTb.BackColor = System.Drawing.Color.Lime;
string [] parsed = COMRx.Split(',');
int curveNo;
if (parsed.Count() > zedAll.GraphPane.CurveList.Count())
curveNo = zedAll.GraphPane.CurveList.Count();
else
curveNo = parsed.Count();
for (int k = 0; k < curveNo; k++)
{
for (int j = zedAll.GraphPane.CurveList[k].NPts - 1; j > 0; j--)
{
zedAll.GraphPane.CurveList[k].Points[j].Y = zedAll.GraphPane.CurveList[k].Points[j - 1].Y;
}
double temp = 0;
try
{
temp = double.Parse(parsed[k]);
}
catch
{
systemTb.Text = "Parse Error";
systemTb.BackColor = System.Drawing.Color.Red;
}
rainTb.Text = "" + int.Parse(parsed[0]) * 100 / 1023;
phTb.Text = "" + (3.5 + int.Parse(parsed[1]) * 4.5 / 1023);
moistTb.Text = "" + int.Parse(parsed[2]) * 100 / 1023;
tempTb.Text = "" + int.Parse(parsed[3]) * 100 / 1023;
zedAll.GraphPane.CurveList[k].Points[0].X = 0;
zedAll.GraphPane.CurveList[k].Points[0].Y = temp;
}
}
else
{
this.BeginInvoke(new EventHandler(processPumpStates));
}
}
There are few possible cases why it happens. One is because (1) parsed[0] number is too big, another is because parsed[0] contains (2) non-number, (3) non-recognized thousand separators, or (4) decimal separator (which should not exist in int parsing) in the applied culture for your code.
In all cases, please check the value of parsed[0] with your Visual Studio debugger and make sure that it has purely-acceptable numerical format for int range. Something like:
1234
Also, you may consider of
using TryParse instead of Parse to ensure that the non-parsed number does not cause you exception problem.
use ToString() for printing your numerical calculation result,
check the result of TryParse and
beware of the integer division that you potentially do in the original int.Parse(parsed[0]) * 100 / 1023:
Something like this:
int val;
bool result = int.TryParse(parsed[0], out val);
if (!result)
return; //something has gone wrong
Textbox1.Text = " " + (val * 100d / 1023d).ToString(); //note the d
You are getting such error on the basics of the value contained in the parsed[0] if it is a convertible string your code works fine else it throws the exception that you got. ie, the content inside the parsed[0] is not convertible to an integer, in such situations you should Use int.TryParse instead for int.Parse, it is having internal error handling, which help you to determine whether the conversion is successful or not.
So the code will looks like:
int tempNumber=0;
if (int.TryParse(parsed[0], out tempNumber))
{
Textbox1.Text = " " + (tempNumber * 100 / 1023).ToString();
}
else
{
Textbox1.Text= "invalid zipCode";
}
In a low latency HFT application I have sockets receiving Byte[] messages containing stock market data.
In the vendor protocol stock prices fields are Byte[] containing an ASCII character sequence.
I.e. byte sequence [51-51-46-56] corresponds to ascii characters [3-3-.-8], equals the 33.8 number.
Actually during message parsing I convert Byte[] to string and then string to Single/float.
Is there a way to avoid such double conversion and convert directly Byte[] to single/float ?
Secondly is there a way to avoid the use of the string type which in NET is inefficient (immutable-garbage collection prone) ?
Thanks in advance.
Regards
[edit jan 2019]: this is the final solution working flawlessly from 3 years:
/// <summary> Read a Double precision float field in GL format from the stream and advances stream position of n (1 of field lenght flag + field lenght). </summary>
/// <returns>-1 in case of error, Double precision floating point value ROUNDED TO 8 DECIMAL PLACES in case of success </returns>
/// <param name="IniPos"> Initial Stream Position</param>
public double ReadGLFieldAsDouble(long IniPos = -1)
{
// --
if (IniPos >= 0)
Strm.Position = IniPos;
int FLenght = Strm.ReadByte - 32; // case of "01000" SW Snapshot, field 7 doesn't exists, but in the message is a blank (32)
// --early exit
if (FLenght <= 0)
return -1; // a blank field (byte 32) returns -1
if (Strm.Length - Strm.Position < FLenght)
return -1;
// --
double Dbl = 0;
int Cpos = -1;
int b = 0;
int sign = 1;
// --Builds as Integer with no point Separator
for (int i = 0; i < FLenght ; i++)
{
b = Strm.ReadByte;
switch (b)
{
case 45: // ASCII 45="-" sign
{
sign = -1;
break;
}
case 46: // ASCII 46 is decimal point="." ; ASCII 44 is comma=","
{
Cpos = i; // decimal point position
break;
}
default:
{
Dbl = Dbl * 10 + (b - 48); // increments as integer ASCII 48=0
break;
}
}
}
// --Transforms in floating point dividing by power of 10, multiplies by sign and returns
if (Cpos != -1)
Dbl = (Dbl / (Math.Pow(10, (FLenght - 1 - Cpos))));
return Math.Round(sign * Dbl, 8);
}
byte[] arr = new byte[] { 51, 51, 46, 56};
double res = 0, floatindex = 0.1;
bool isFraction = false;
for (int i = 0; i < arr.Length; i++)
{
if (arr[i] == 46)
{
isFraction = true;
continue;
}
if (!isFraction)
res = 10*res + arr[i] - 48;
else
{
res += (arr[i] - 48)*floatindex;
floatindex /= 10.0;
}
}
return res;
From a culture perspective, it assumes you always have a 'point' to mark the decimal separation (and not a coma like in French culture for instance)
It is possible. Assuming you know the format is always like that (digits, comma and decimal digit):
float v = 0.1f* (100.0f * (buf[0] - 48) + 10 * (buf[1] - 48) + (buf[3] - 48));
or:
float v = 0.1f * (100.0f * buf[0] + 10 * buf[1] + buf[3] - 4800 - 480 - 48);
I am using regular expression for checking the subnet masking. I use ajax txtbox with masking value but that is not working, then I switched to a textbox and applying a regular expression for that. unfortunatly that one is also not working.
Can you help me out to give a RE for subnet masking 255.255.255.255
Or any best way to do that?
Solution:
I was using masked text box and don't know how to put validation expression.
Finally I found a property of masked text box as validation expression, and there I put the RE and change the property validate to true.
No need to use validator expression explicitly.
Thanks
To do this with a regular expression, you have to ensure that the entire IPv4 dotted quad represents a 32 bit number with leading ones only. It is not enough to ensure that each number in the quad has only leading ones. For example, 255.192.255.0 is not a valid submask, even though each number in the quad has only leading ones. Building on the solution offered by #xanatos,
var leadingOnes = new Regex("255|254|252|248|240|224|192|128|0+");
defines a regular expression that will match any 8-bit (decimal) number with leading ones only. I have used "0+" to allow for .000, which is sometimes used in quads. Obviously, if you want to force a singe zero, use "0" instead.
You then have to build up a regular expression that matches any one of the four following patterns, which I represent as pseudo regular expressions to make it easer to understand:
255.255.255.leadingOnes
255.255.leadingOnes*.0
255.leadingOnes.0.0
leadingOnes.0.0.0
You can either write this out as a single string, or build it up through concatenation. Here's building it up:
var leadingOnes = "(255|254|252|248|240|224|192|128|0+);"
var allOnes = #"(255\.)";
var re = new Regex("^((" + allOnes + "{3}" + leadingOnes + ")|" +
"(" + allOnes + "{2}" + leadingOnes + #"\.0+)|" +
"(" + allOnes + leadingOnes + #"(\.0+){2})|" +
"(" + leadingOnes + #"(\.0+){3}))$");
And here's the entire string, if we ignore line breaks.
var re = new Regex(#"^(((255\.){3}(255|254|252|248|240|224|192|128|0+))|((255\.){2}(255|254|252|248|240|224|192|128|0+)\.0)|((255\.)(255|254|252|248|240|224|192|128|0+)(\.0+){2})|((255|254|252|248|240|224|192|128|0+)(\.0+){3}))$");
Following #Keith's suggestion, you could start with a simple regular expression such as
Regex("([0-9]{1,3}\.){3}[0-9]{1,3}" to get four 3-digit numbers separated by dots, and then write a function that extracts and evaluates the four pieces into a 32-bit integer that you then check to ensure that it has only leading ones. There are several ways to do that, but all of them require up to 31 compare operations to complete the validation.
If you want to accept any IP address as a subnet mask:
var num = #"(25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})";
var rx = new Regex("^" + num + #"\." + num + #"\." + num + #"\." + num + "$");
I considered easier to split the "repeating" match for a single group of numbers in a separate variable.
As an exercise for the reader, I'll give another variant of the expression. This one will capture all the numbers in the same group but different captures:
var rx = new Regex("^(?:" + num + #"(?:\.(?!$)|$)){4}$");
BUT it's wrong, you should use this
var num = #"(255|254|252|248|240|224|192|128|0+)";
var rx = new Regex("^" + num + #"\." + num + #"\." +num + #"\." +num + "$");
or
var rx = new Regex("^(?:" + num + #"(?:\.(?!$)|$)){4}$");
http://www.freesoft.org/CIE/Course/Subnet/6.htm
I know the question asked about a Regex expression, but for anyone else who's interested, here are two iterative solutions to the problem. The second function is a bit faster than the first.
private bool IsValidSubnet(IPAddress ip) {
byte[] validOctets = new byte[] { 255, 254, 252, 248, 240, 224, 192, 128, 0 };
byte[] ipOctets = ip.GetAddressBytes();
bool restAreZeros = false;
for (int i = 0; i < 4; i++) {
if (!validOctets.Contains(ipOctets[i]))
return false;
if (restAreZeros && ipOctets[i] != 0)
return false;
if (ipOctets[i] < 255)
restAreZeros = true;
}
return true;
}
// checks if the address is all leading ones followed by only zeroes
private bool IsValidSubnet2(IPAddress ip) {
byte[] ipOctets = ip.GetAddressBytes();
bool restAreOnes = false;
for (int i = 3; i >= 0; i--) {
for (int j = 0; j < 8; j++) {
bool bitValue = (ipOctets[i] >> j & 1) == 1;
if (restAreOnes && !bitValue)
return false;
restAreOnes = bitValue;
}
}
return true;
}
From http://pastebin.com/wTEKjKpP
var subnetRegex = /^((128|192|224|240|248|252|254)\.0\.0\.0)|(255\.(((0|128|192|224|240|248|252|254)\.0\.0)|(255\.(((0|128|192|224|240|248|252|254)\.0)|255\.(0|128|192|224|240|248|252|254)))))$/
Of course that's for javascript, but that should help.
you can use this regex to validate subnet
^(((255\.){3}(255|254|252|248|240|224|192|128+))|((255\.){2}(255|254|252|248|240|224|192|128|0+)\.0)|((255\.)(255|254|252|248|240|224|192|128|0+)(\.0+){2})|((255|254|252|248|240|224|192|128|0+)(\.0+){3}))$
Explanation
A little late to the party, but we can't do just a regex check on valid octets because:
A subnet must start with 255.X.X.X
A subnet cannot look like this: 255.254.128.X - once there is 0 bit, everything else must be 0 afterwards
The correct way to do this is to walk the bits from the MSB, checking for the first 0 bit. Once you discover the first 0 bit, check what position it's in. The largest legal subnet is a /8, or 255.0.0.0, meaning there needs to be 8 1 bits before the first zero. Then, make sure every bit after the first 0 is a zero. So in summary:
(Optionally verify that it's even a valid IP address...)
Start at MSB, walk down bits looking for the first 0
If you find a 0 (255.255.255.255 would still be valid), check position
Check that all remaining bits are zero
Code
private bool IsValidSubnet(string subnet)
{
//A subnet is a valid ipv4 address, so start checking there
if (!IsIPv4(subnet)) return false;
// Get the 4 bytes
byte[] subnetMaskBytes =
System.Net.IPAddress.Parse(subnet).GetAddressBytes();
//Shift to get uint representation of the bits
var UintSubnet = (uint)subnetMaskBytes[0] << 24;
UintSubnet += (uint)subnetMaskBytes[1] << 16;
UintSubnet += (uint)subnetMaskBytes[2] << 8;
UintSubnet += (uint)subnetMaskBytes[3];
int i = 31;
while (i >= 0)
{
UInt32 mask = (UInt32)(1 << i);
if ((UintSubnet & mask) == 0) break;
i--;
}
// It is not legal to have fewer than 8 bits of addressing
if (i >= 24) return false;
// Make sure that all remaining bits are 0
while (i >= 0)
{
UInt32 mask = (UInt32)(1 << i);
if ((UintSubnet & mask) != 0) return false;
i--;
}
return true;
}