Пример #1
0
        private string GenerateBinaryString(byte[] requestedOrderBytes, NumberByteOrder byteOrder)
        {
            StringBuilder sb = new StringBuilder(BitsPerByte * requestedOrderBytes.Length);

            foreach (byte currentByte in requestedOrderBytes)
            {
                if (sb.Length > 0 && this.options.UseByteSpaceSeparators)
                {
                    sb.Append(' ');
                }

                for (int i = BitsPerByte - 1; i >= 0; i--)
                {
                    bool isBitSet = (currentByte & (1 << i)) != 0;
                    sb.Append(isBitSet ? "1" : "0");
                }
            }

            string result = sb.ToString();

            if (this.ShouldTrimLeadingZeros(byteOrder))
            {
                result = TrimLeadingZeros(result);
            }

            return(result);
        }
Пример #2
0
        private static byte[] EnsureRequestedByteOrder(byte[] machineValueBytes, NumberByteOrder byteOrder)
        {
            if (!MachineOrderMatchesByteOrder(byteOrder))
            {
                Array.Reverse(machineValueBytes);
            }

            return(machineValueBytes);
        }
Пример #3
0
        private static bool MachineOrderMatchesByteOrder(NumberByteOrder byteOrder)
        {
            // As far as this function is concerned, numeric and big endian are the same because they
            // both order from most significant down to least significant.
            bool result = (BitConverter.IsLittleEndian && byteOrder == NumberByteOrder.LittleEndian) ||
                          (!BitConverter.IsLittleEndian && byteOrder != NumberByteOrder.LittleEndian);

            return(result);
        }
Пример #4
0
        private void InitializeFromHex(string textValue, NumberByteOrder byteOrder, NumberType numberType)
        {
            int requiredNumBytes = GetNumBytesForNumberType(numberType);

            byte[] machineValueBytes = GetMachineBytesFromText(textValue, byteOrder, NumberBase.Hex, requiredNumBytes);
            object convertedValue    = GetConvertedValueForBytes(machineValueBytes, numberType);

            if (convertedValue != null)
            {
                this.decimalValue = this.FormatDecimalValue(convertedValue);
                this.hexValue     = textValue;
                byte[] requestedOrderBytes = EnsureRequestedByteOrder(machineValueBytes, byteOrder);
                this.binaryValue = this.GenerateBinaryString(requestedOrderBytes, byteOrder);
            }
        }
Пример #5
0
        private static bool ValidateAndNormalizeByteText(ref string textValue, NumberByteOrder byteOrder, NumberBase numBase, int numRequiredBytes)
        {
            // Ignore whitespace (leading, trailing, and between digit groups) and non-printable control characters.
            textValue = new string(textValue.Where(ch => !char.IsWhiteSpace(ch) && !char.IsControl(ch)).ToArray());

            // Ignore 0x prefix for hex
            if (numBase == NumberBase.Hex && textValue.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
            {
                textValue = textValue.Substring(2);
            }

            int numCharsPerByte = numBase == NumberBase.Binary ? BitsPerByte : 2;
            int numCharsTotal   = textValue.Length;

            // I'm depending on the truncation of integer division here.
            int  numWholeBytes         = numCharsTotal / numCharsPerByte;
            int  numLeftoverCharacters = numCharsTotal % numCharsPerByte;
            bool validLength           = numWholeBytes == numRequiredBytes && numLeftoverCharacters == 0;

            // If necessary, we can pad up to the number of required bytes, but we can never truncate.
            if (!validLength && numWholeBytes < numRequiredBytes)
            {
                int numRequiredChars = numCharsPerByte * numRequiredBytes;
                if (byteOrder == NumberByteOrder.Numeric)
                {
                    textValue   = new string('0', numRequiredChars - numCharsTotal) + textValue;
                    validLength = true;
                }
                else
                {
                    // For big and little endian, we'll left pad up to the next full byte, then we'll right pad the rest of the data.
                    // This seems the most reasonable strategy since entering a single byte's data is a "Numeric" entry, which
                    // normally zero pads on the left.  But since Endianness deals with storage and we enter data from left to
                    // right, it seems reasonable to zero pad on the right to fill up the remaining unspecified bytes. For example,
                    // if "F" is entered for a Hex Int32, we'll left pad that up to "0F" and then right pad it to "0F000000".
                    int numLeftPadChars = numLeftoverCharacters == 0 ? 0 : numCharsPerByte - numLeftoverCharacters;
                    textValue = new string('0', numLeftPadChars) + textValue + new string('0', numRequiredChars - numCharsTotal - numLeftPadChars);

                    validLength = true;
                }
            }

            return(validLength);
        }
Пример #6
0
        public BaseConverter(string textValue, Options options, NumberBase numBase, NumberByteOrder byteOrder, NumberType numberType)
        {
            this.options = options;

            if (!string.IsNullOrEmpty(textValue))
            {
                switch (numBase)
                {
                case NumberBase.Binary:
                    this.InitializeFromBinary(textValue, byteOrder, numberType);
                    break;

                case NumberBase.Decimal:
                    this.InitializeFromDecimal(textValue, byteOrder, numberType);
                    break;

                case NumberBase.Hex:
                    this.InitializeFromHex(textValue, byteOrder, numberType);
                    break;
                }
            }
        }
Пример #7
0
        private string GenerateHexString(byte[] requestedOrderBytes, NumberByteOrder byteOrder)
        {
            StringBuilder sb = new StringBuilder(2 * requestedOrderBytes.Length);

            foreach (byte b in requestedOrderBytes)
            {
                if (sb.Length > 0 && this.options.UseByteSpaceSeparators)
                {
                    sb.Append(' ');
                }

                sb.AppendFormat("{0:X2}", b);
            }

            string result = sb.ToString();

            if (this.ShouldTrimLeadingZeros(byteOrder))
            {
                result = TrimLeadingZeros(result);
            }

            return(result);
        }
Пример #8
0
        private static byte[] GetMachineBytesFromText(string textValue, NumberByteOrder byteOrder, NumberBase numBase, int requiredNumBytes)
        {
            Debug.Assert(numBase == NumberBase.Binary || numBase == NumberBase.Hex, "GetMachineBytesFromText is only for binary and hex values.");

            byte[] result      = null;
            bool   validLength = ValidateAndNormalizeByteText(ref textValue, byteOrder, numBase, requiredNumBytes);

            if (validLength)
            {
                bool        valid       = true;
                string[]    byteStrings = SplitIntoByteStrings(textValue, numBase == NumberBase.Binary ? BitsPerByte : 2);
                List <byte> byteList    = new List <byte>(requiredNumBytes);
                foreach (string byteString in byteStrings)
                {
                    if (TryParse(byteString, numBase, out byte byteValue))
                    {
                        byteList.Add(byteValue);
                    }
                    else
                    {
                        valid = false;
                        break;
                    }
                }

                if (valid)
                {
                    result = byteList.ToArray();

                    // Regardless of input byte order we must return bytes that match machine byte order
                    // (i.e., BitConverter.IsLittleEndian) because our output will be passed to BitConverter.
                    result = EnsureRequestedByteOrder(result, byteOrder);
                }
            }

            return(result);
        }
Пример #9
0
        private bool ShouldTrimLeadingZeros(NumberByteOrder byteOrder)
        {
            bool result = byteOrder == NumberByteOrder.Numeric ? this.options.TrimLeadingZerosNumeric : this.options.TrimLeadingZerosEndian;

            return(result);
        }
Пример #10
0
        private void InitializeFromDecimal(string textValue, NumberByteOrder byteOrder, NumberType numberType)
        {
            const NumberStyles IntegerStyles = NumberStyles.Integer | NumberStyles.AllowThousands;

            byte[] machineValueBytes = null;
            switch (numberType)
            {
            case NumberType.Byte:
                byte byteValue;
                if (byte.TryParse(textValue, IntegerStyles, null, out byteValue))
                {
                    machineValueBytes = new byte[1] {
                        byteValue
                    };
                }

                break;

            case NumberType.Int16:
                short shortValue;
                if (short.TryParse(textValue, IntegerStyles, null, out shortValue))
                {
                    machineValueBytes = BitConverter.GetBytes(shortValue);
                }

                break;

            case NumberType.Int32:
                int intValue;
                if (int.TryParse(textValue, IntegerStyles, null, out intValue))
                {
                    machineValueBytes = BitConverter.GetBytes(intValue);
                }

                break;

            case NumberType.Int64:
                long longValue;
                if (long.TryParse(textValue, IntegerStyles, null, out longValue))
                {
                    machineValueBytes = BitConverter.GetBytes(longValue);
                }

                break;

            case NumberType.Single:
                float singleValue;
                if (float.TryParse(textValue, out singleValue))
                {
                    machineValueBytes = BitConverter.GetBytes(singleValue);
                }

                break;

            case NumberType.Double:
                double doubleValue;
                if (double.TryParse(textValue, out doubleValue))
                {
                    machineValueBytes = BitConverter.GetBytes(doubleValue);
                }

                break;

            case NumberType.Decimal:
                decimal decimalValue;
                if (decimal.TryParse(textValue, out decimalValue))
                {
                    machineValueBytes = GetBytes(decimalValue);
                }

                break;

            case NumberType.SByte:
                sbyte sbyteValue;
                if (sbyte.TryParse(textValue, IntegerStyles, null, out sbyteValue))
                {
                    unchecked
                    {
                        byte castValue = (byte)sbyteValue;
                        machineValueBytes = new byte[1] {
                            castValue
                        };
                    }
                }

                break;

            case NumberType.UInt16:
                ushort ushortValue;
                if (ushort.TryParse(textValue, IntegerStyles, null, out ushortValue))
                {
                    machineValueBytes = BitConverter.GetBytes(ushortValue);
                }

                break;

            case NumberType.UInt32:
                uint uintValue;
                if (uint.TryParse(textValue, IntegerStyles, null, out uintValue))
                {
                    machineValueBytes = BitConverter.GetBytes(uintValue);
                }

                break;

            case NumberType.UInt64:
                ulong ulongValue;
                if (ulong.TryParse(textValue, IntegerStyles, null, out ulongValue))
                {
                    machineValueBytes = BitConverter.GetBytes(ulongValue);
                }

                break;
            }

            if (machineValueBytes != null)
            {
                this.decimalValue = textValue;
                byte[] requestedOrderBytes = EnsureRequestedByteOrder(machineValueBytes, byteOrder);
                this.hexValue    = this.GenerateHexString(requestedOrderBytes, byteOrder);
                this.binaryValue = this.GenerateBinaryString(requestedOrderBytes, byteOrder);
            }
        }