Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wisp
GitHub Repository: wisp/impinj-reader-app
Path: blob/master/LLRP/LLRPUtil.cs
179 views
/*
 ***************************************************************************
 *  Copyright 2007 Impinj, Inc.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 ***************************************************************************
 */


/*
***************************************************************************
 * File Name:       LLRPUtil.cs
 * 
 * Author:          Impinj
 * Organization:    Impinj
 * Date:            September, 2007
 * 
 * Description:     This file contains data convertion and data operattion 
 *                  methods
***************************************************************************
*/

using System;
using System.IO;
using System.Text;
using System.Collections;
using System.Collections.Generic;

using System.ComponentModel;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.Schema;
using System.Runtime.InteropServices;

namespace LLRP.DataType
{
    /// <summary>
    /// Utility class contains data type conversion functions
    /// </summary>
    public class Util
    {
        /// <summary>
        /// Split string to string array based on specified seperator and string length
        /// </summary>
        /// <param name="str">string to be splitted</param>
        /// <param name="seperator">char array of seperators</param>
        /// <param name="splitted_string_length">length of each splitted string</param>
        /// <returns></returns>
        public static string[] SplitString(string str, char[] seperator, UInt16 splitted_string_length)
        {
            string[] s = str.Split(seperator);

            //if no seperator used.
            if (s.Length <= 1 && str.Length > splitted_string_length)
            {
                int remainder = 0;
                int length = (int)Math.DivRem(str.Length, splitted_string_length, out remainder);
                str = str.PadLeft(remainder, '0');

                string[] tmp_str = new string[remainder > 0 ? (length + 1) : length];
                for (int i = 0; i < tmp_str.Length; i++)
                {
                    try
                    {
                        for (int j = 0; j < splitted_string_length; j++) tmp_str[i] += str[splitted_string_length * i + j];
                    }
                    catch { }
                }
                return tmp_str;
            }
            else
                return s;
        }

        /// <summary>
        /// Convert byte array to Hex string
        /// </summary>
        /// <param name="byte_array"></param>
        /// <returns></returns>
        public static string ConvertByteArrayToHexString(byte[] byte_array)
        {
            string s = string.Empty;

            for (int i = 0; i < byte_array.Length; i++) s += string.Format("{0:X2}", byte_array[i]);
            return s;
        }

        /// <summary>
        /// Convert bitArray to byte array
        /// </summary>
        /// <param name="bit_array"></param>
        /// <returns></returns>
        public static byte[] ConvertBitArrayToByteArray(bool[] bit_array)
        {
            byte val = 0x00;
            int size = bit_array.Length / 8 + (int)(((bit_array.Length % 8) > 0) ? 1 : 0);
            byte[] data = new byte[size];

            int reserved = bit_array.Length > 8 ? 8 : bit_array.Length;

            for (int i = 0; i < size; i++)
            {
                for (int j = 0; j < reserved; j++)
                {
                    val = (byte)(val << 1);
                    val += (byte)(bit_array[i * 8 + j] ? 0x01 : 0x00);
                }
                data[i] = val;
            }

            return data;
        }

        /// <summary>
        /// Convert byte array to bit array
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static BitArray ConvertByteArrayToBitArray(byte[] data)
        {
            BitArray bit_array = new BitArray(data.Length * 8);
            for (int i = 0; i < data.Length; i++) for (int j = 0; j < 8; j++) bit_array[i * 8 + j] = (((data[i] >> (7 - j)) & 0x01) == 1) ? true : false;
            return bit_array;
        }

        /// <summary>
        /// find the field length
        /// </summary>
        /// <param name="bit_array"></param>
        /// <param name="cursor"></param>
        /// <returns></returns>
        public static int DetermineFieldLength(ref BitArray bit_array, ref int cursor)
        {
            return (int)(UInt64)CalculateVal(ref bit_array, ref cursor, 16);
        }

        /// <summary>
        /// Calculate the value of particular bits at particular position
        /// </summary>
        /// <param name="bit_array"></param>
        /// <param name="cursor"></param>
        /// <param name="len"></param>
        /// <returns></returns>
        public static object CalculateVal(ref BitArray bit_array, ref int cursor, int len)
        {
            UInt64 val = 0;
            for (int i = 0; i < len; i++)
            {
                val = val << 1;
                if (cursor >= bit_array.Length) return (object)0;
                val += (UInt64)(bit_array[cursor] ? 1 : 0);

                cursor++;
            }

            return (object)val;
        }

        /// <summary>
        /// Convert bit array to object based on position, type of object and length of the bits
        /// </summary>
        /// <param name="bit_array">the input bit array</param>
        /// <param name="cursor">the start position</param>
        /// <param name="obj">output value</param>
        /// <param name="type">conversion type</param>
        /// <param name="field_len">field length, if it's 0, the field length will be determined by type</param>
        public static void ConvertBitArrayToObj(ref BitArray bit_array, ref int cursor, out Object obj, Type type, int field_len)
        {
            if (type.Equals(typeof(bool)))
            {
                obj = bit_array[cursor];
                cursor++;
            }
            else if (type.Equals(typeof(byte)))
            {
                obj = (byte)(UInt64)CalculateVal(ref bit_array, ref cursor, 8);
            }
            else if (type.Equals(typeof(sbyte)))
            {
                obj = (sbyte)(UInt64)CalculateVal(ref bit_array, ref cursor, 8);
            }
            else if (type.Equals(typeof(UInt16)))
            {
                obj = (UInt16)(UInt64)CalculateVal(ref bit_array, ref cursor, 16);
            }
            else if (type.Equals(typeof(Int16)))
            {
                obj = (Int16)(UInt64)CalculateVal(ref bit_array, ref cursor, 16);
            }
            else if (type.Equals(typeof(UInt32)))
            {
                obj = (UInt32)(UInt64)CalculateVal(ref bit_array, ref cursor, field_len);
            }
            else if (type.Equals(typeof(Int32)))
            {
                obj = (Int32)(UInt64)CalculateVal(ref bit_array, ref cursor, 32);
            }
            else if (type.Equals(typeof(UInt64)))
            {
                obj = (UInt64)(UInt64)CalculateVal(ref bit_array, ref cursor, 64);
            }
            else if (type.Equals(typeof(Int64)))
            {
                obj = (Int64)(UInt64)CalculateVal(ref bit_array, ref cursor, 64);
            }
            else if (type.Equals(typeof(string)))
            {
                string s = string.Empty;
                for (int i = 0; i < field_len; i++)
                {
                    try
                    {
                        byte bd = (byte)(UInt64)CalculateVal(ref bit_array, ref cursor, 8);
                        System.Text.UTF8Encoding encoding = new UTF8Encoding();
                        byte[] bdarr = new byte[1] { bd };
                        s += encoding.GetString(bdarr);
                    }
                    catch
                    {
                    }
                }

                if (field_len > 1 && s[field_len - 1] == 0) s = s.Substring(0, field_len - 1);
                obj = s;
            }
            else if (type.Equals(typeof(ByteArray)))
            {
                obj = new ByteArray();
                for (int i = 0; i < field_len; i++) ((ByteArray)obj).Add((byte)(UInt64)CalculateVal(ref bit_array, ref cursor, 8));
            }
            else if (type.Equals(typeof(UInt16Array)))
            {
                obj = new UInt16Array();
                for (int i = 0; i < field_len; i++) ((UInt16Array)obj).Add((UInt16)(UInt64)CalculateVal(ref bit_array, ref cursor, 16));
            }
            else if (type.Equals(typeof(UInt32Array)))
            {
                obj = new UInt32Array();
                for (int i = 0; i < field_len; i++) ((UInt32Array)obj).Add((UInt32)(UInt64)CalculateVal(ref bit_array, ref cursor, 32));
            }
            else if (type.Equals(typeof(TwoBits)))
            {
                obj = new TwoBits(bit_array[cursor], bit_array[cursor + 1]);
                cursor += 2;
            }
            else if (type.Equals(typeof(BitArray)))
            {
                obj = new BitArray(field_len);

                for (int i = 0; i < field_len; i++)
                {
                    ((BitArray)obj)[i] = bit_array[cursor];
                    cursor++;
                }
            }
            else if (type.Equals(typeof(LLRPBitArray)))
            {
                obj = new LLRPBitArray();

                for (int i = 0; i < field_len; i++)
                {
                    ((LLRPBitArray)obj).Add(bit_array[cursor]);
                    cursor++;
                }
            }
            else
                obj = (UInt32)(UInt64)CalculateVal(ref bit_array, ref cursor, field_len);
        }

        /// <summary>
        /// Convert Integer to bit array
        /// </summary>
        /// <param name="val"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        public static BitArray ConvertIntToBitArray(UInt32 val, int length)
        {
            BitArray bit_arr = new BitArray(length);
            string s = Convert.ToString(val, 2).PadLeft(length, '0');
            for (int i = 0; i < length; i++) bit_arr[i] = (s[i] == '1');

            return bit_arr;
        }

        /// <summary>
        /// Convert object to bit array
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="length">valid for string or unknow type.</param>
        /// <returns></returns>
        public static BitArray ConvertObjToBitArray(Object obj, int length)
        {
            BitArray bit_arr;

            Type type = obj.GetType();
            string s = string.Empty;

            if (type.Equals(typeof(bool)))
            {

                bit_arr = new BitArray(1);
                bit_arr[0] = (bool)obj;
                return bit_arr;
            }
            else if (type.Equals(typeof(TwoBits)))
            {
                bit_arr = new BitArray(2);
                bit_arr[0] = ((TwoBits)obj)[0];
                bit_arr[1] = ((TwoBits)obj)[1];
                return bit_arr;
            }
            else if (type.Equals(typeof(byte)))
            {
                bit_arr = new BitArray(8);
                s = Convert.ToString((byte)obj, 2).PadLeft(8, '0');
                for (int i = 0; i < 8; i++) bit_arr[i] = (s[i] == '1');
                return bit_arr;
            }
            else if (type.Equals(typeof(sbyte)))
            {
                bit_arr = new BitArray(8);
                s = Convert.ToString((sbyte)obj, 2).PadLeft(8, '0');
                for (int i = 0; i < 8; i++) bit_arr[i] = (s[i] == '1');
                return bit_arr;
            }
            else if (type.Equals(typeof(UInt16)))
            {
                bit_arr = new BitArray(16);
                s = Convert.ToString((UInt16)obj, 2).PadLeft(16, '0');
                for (int i = 0; i < 16; i++) bit_arr[i] = (s[i] == '1');
                return bit_arr;
            }
            else if (type.Equals(typeof(Int16)))
            {
                bit_arr = new BitArray(16);
                s = Convert.ToString((Int16)obj, 2).PadLeft(16, '0');
                for (int i = 0; i < 16; i++) bit_arr[i] = (s[i] == '1');
                return bit_arr;
            }
            else if (type.Equals(typeof(UInt32)))
            {
                bit_arr = new BitArray(32);
                s = Convert.ToString((UInt32)obj, 2).PadLeft(32, '0');
                for (int i = 0; i < 32; i++) bit_arr[i] = (s[i] == '1');
                return bit_arr;
            }
            else if (type.Equals(typeof(Int32)))
            {
                bit_arr = new BitArray(32);
                s = Convert.ToString((Int32)obj, 2).PadLeft(32, '0');
                for (int i = 0; i < 32; i++) bit_arr[i] = (s[i] == '1');
                return bit_arr;
            }
            else if (type.Equals(typeof(UInt64)))
            {
                bit_arr = new BitArray(64);
                Int64 tempV = (Int64)(UInt64)obj;
                s = Convert.ToString(tempV, 2).PadLeft(64, '0');
                for (int i = 0; i < 64; i++) bit_arr[i] = (s[i] == '1');
                return bit_arr;
            }
            else if (type.Equals(typeof(Int64)))
            {
                bit_arr = new BitArray(64);
                s = Convert.ToString((Int64)obj, 2).PadLeft(64, '0');
                for (int i = 0; i < 64; i++) bit_arr[i] = (s[i] == '1');
                return bit_arr;
            }
            else if (type.Equals(typeof(string)))
            {
                int len = ((string)obj).Length * 8;
                bit_arr = new BitArray(len);

                for (int k = 0; k < ((string)obj).Length; k++)
                {
                    s = Convert.ToString(((string)obj)[k], 2).PadLeft(8, '0');
                    for (int i = 0; i < 8; i++) bit_arr[k * 8 + i] = (s[i] == '1');
                }
                return bit_arr;
            }
            else if (type.Equals(typeof(BitArray)))
            {
                int len = ((BitArray)obj).Count * 1;
                bit_arr = new BitArray(len);
                for (int k = 0; k < len; k++) bit_arr[k] = ((BitArray)obj)[k];
                return bit_arr;
            }
            else if (type.Equals(typeof(LLRPBitArray)))
            {
                int len = ((LLRPBitArray)obj).Count * 1;
                bit_arr = new BitArray(len);
                for (int k = 0; k < len; k++) bit_arr[k] = ((LLRPBitArray)obj)[k];
                return bit_arr;
            }
            else if (type.Equals(typeof(ByteArray)))
            {
                int len = ((ByteArray)obj).Count * 8;
                bit_arr = new BitArray(len);

                for (int k = 0; k < ((ByteArray)obj).Count; k++)
                {
                    s = Convert.ToString((byte)(((ByteArray)obj)[k]), 2).PadLeft(8, '0');
                    for (int i = 0; i < 8; i++) bit_arr[k * 8 + i] = (s[i] == '1');
                }
                return bit_arr;
            }
            else if (type.Equals(typeof(UInt16Array)))
            {
                int len = ((UInt16Array)obj).Count * 16;
                bit_arr = new BitArray(len);

                for (int k = 0; k < ((UInt16Array)obj).Count; k++)
                {
                    s = Convert.ToString((UInt16)(((UInt16Array)obj)[k]), 2).PadLeft(16, '0');
                    for (int i = 0; i < 16; i++) bit_arr[k * 16 + i] = (s[i] == '1');
                }
                return bit_arr;
            }
            else if (type.Equals(typeof(UInt32Array)))
            {
                int len = ((UInt32Array)obj).Count * 32;
                bit_arr = new BitArray(len);

                for (int k = 0; k < ((UInt32Array)obj).Count; k++)
                {
                    s = Convert.ToString((UInt32)(((UInt32Array)obj)[k]), 2).PadLeft(32, '0');
                    for (int i = 0; i < 32; i++) bit_arr[k * 32 + i] = (s[i] == '1');
                }
                return bit_arr;
            }
            else
            {
                bit_arr = new BitArray(length);
                s = Convert.ToString((Int32)obj, 2).PadLeft(length, '0');
                for (int i = 0; i < length; i++) bit_arr[i] = (s[i] == '1');
                return bit_arr;

            }
        }

        /// <summary>
        /// Convert control word to string, can't use ToString becuase it cut the header.
        /// </summary>
        /// <param name="lControlWord">Control Word, Long</param>
        /// <returns>converted string, string</returns>
        public static string ConvertLongToString(long lControlWord)
        {
            string strControlWord, strTemp;

            strTemp = lControlWord.ToString("X");

            string strHead = "";

            int nLen = 8 - strTemp.Length;

            if (nLen < 0) return null;				//prevent negtive length happened.

            for (int i = 0; i < nLen; i++)				//Fill enough '0' into the string
            {
                strHead += "0";
            }

            strControlWord = strHead + strTemp;

            return strControlWord;
        }

        /// <summary>
        /// convert string to byte array
        /// </summary>
        /// <param name="str">string to be converted, string</param>
        /// <returns>byte array</returns>
        public static byte[] ConvertHexStringToByteArray(string str)
        {
            float fLen = str.Length;
            int nSize = (int)Math.Ceiling(fLen / 2);

            string strArray = null;
            byte[] bytes = new byte[nSize];

            //Keep the string oven length.
            if (nSize * 2 > fLen)
            {
                strArray = "0" + str;
            }
            else
                strArray = str;

            for (int i = 0; i < nSize; i++)
            {
                int index = i * 2;
                char[] cArr = new char[] { strArray[index], strArray[index + 1] };

                string s = new string(cArr);

                try
                {
                    bytes[i] = Convert.ToByte(s, 16);
                }
                catch (System.OverflowException)
                {
                    System.Console.WriteLine(
                        "Conversion from string to byte overflowed.");
                }
                catch (System.FormatException)
                {
                    System.Console.WriteLine(
                        "The string is not formatted as a byte.");
                }
                catch (System.ArgumentNullException)
                {
                    System.Console.WriteLine(
                        "The string is null.");
                }

            }

            return bytes;
        }

        /// <summary>
        /// Convert Hex string to string
        /// </summary>
        /// <param name="strHexString">Hex string to be converted, string</param>
        /// <returns>string</returns>
        public static string CovertHexStringToString(string strHexString)
        {
            byte[] byy = ConvertHexStringToByteArray(strHexString);
            int size = byy.Length;
            char[] chh = new char[size];

            for (int k = 0; k < size; k++) chh[k] = (char)byy[k];

            return new string(chh);
        }

        /// <summary>
        /// Convert string to Hex string	
        /// </summary>
        /// <param name="strString">string to be converted</param>
        /// <returns>string</returns>
        public static string CovertStringToHexString(string strString)
        {
            char[] ch = strString.ToCharArray();
            int nSize = ch.Length;
            byte[] by = new byte[nSize];

            for (int i = 0; i < nSize; i++)
                by[i] = (byte)ch[i];

            return ConvertByteArrayToHexString(by);
        }

        /// <summary>
        /// Convert HexString to binary string
        /// </summary>
        /// <param name="strHex"></param>
        /// <returns></returns>
        public static string ConvertHexStringToBinaryString(string strHex)
        {
            string binStr = string.Empty;
            int strLen = strHex.Length;

            try
            {
                for (int i = 0; i < strLen; i++)
                {
                    binStr += CharToBinaryString(strHex[i]);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return binStr;
        }

        /// <summary>
        /// Convert binary string to hex string
        /// </summary>
        /// <param name="strBinary"></param>
        /// <returns></returns>
        public static string ConvertBinaryStringToHexString(string strBinary)
        {
            StringBuilder strHex = new StringBuilder();
            string tmp = strBinary;

            while (tmp.Length > 0)
            {
                int index = tmp.Length > 4 ? (tmp.Length - 4) : 0;
                int length = tmp.Length > 4 ? 4 : tmp.Length;

                string str = tmp.Substring(index, length);
                tmp = tmp.Remove(index, length);

                UInt64 dec = ConvertBinaryStringToDecimal(str);

                string s = Convert.ToString((long)dec, 16);

                strHex = strHex.Insert(0, s);
            }

            return strHex.ToString().ToUpper();
        }

        /// <summary>
        /// Convert binary string to decimail
        /// </summary>
        /// <param name="strBinary"></param>
        /// <returns></returns>
        public static UInt64 ConvertBinaryStringToDecimal(string strBinary)
        {
            UInt64 dec = 0;

            if (strBinary.Length > 64)
            {
                throw new Exception("String is longer than 64 bits, less than 64 bits is required");
            }

            for (int i = strBinary.Length; i > 0; i--)
            {
                if (strBinary[i - 1] != '1' && strBinary[i - 1] != '0')
                    throw new Exception("String is not in binary string format");

                UInt64 temp = (UInt64)((strBinary[i - 1] == '1') ? 1 : 0);

                dec += temp << (strBinary.Length - i);
            }

            return dec;
        }

        /// <summary>
        /// Convert decimal to binary string
        /// </summary>
        /// <param name="dec">decimal number</param>
        /// <param name="strLen">expected string length</param>
        /// <returns></returns>
        public static string ConvertDecimalToBinaryString(UInt64 dec, int strLen)
        {
            string strConverted = string.Empty;
            string s = Convert.ToString((long)dec, 2);

            if (s.Length > strLen)
                throw new Exception("Converted string is longer than expected!");

            int nDeff = strLen - s.Length;

            strConverted = s.PadLeft(strLen, '0');

            return strConverted;
        }

        /// <summary>
        /// Convert decimal to decimal string
        /// </summary>
        /// <param name="dec">decimal number</param>
        /// <param name="strLen">expected string length</param>
        /// <returns></returns>
        public static string ConvertDecimalToDecimalString(UInt64 dec, int strLen)
        {
            string strConverted = string.Empty;
            string s = dec.ToString();

            if (s.Length > strLen)
                throw new Exception("Converted string is longer than expected!");

            int nDeff = strLen - s.Length;

            strConverted = s.PadLeft(strLen, '0');


            return strConverted;
        }

        private static string CharToBinaryString(char c)
        {
            switch (c)
            {
                case '0':
                    return "0000";
                case '1':
                    return "0001";
                case '2':
                    return "0010";
                case '3':
                    return "0011";
                case '4':
                    return "0100";
                case '5':
                    return "0101";
                case '6':
                    return "0110";
                case '7':
                    return "0111";
                case '8':
                    return "1000";
                case '9':
                    return "1001";
                case 'a':
                case 'A':
                    return "1010";
                case 'b':
                case 'B':
                    return "1011";
                case 'c':
                case 'C':
                    return "1100";
                case 'd':
                case 'D':
                    return "1101";
                case 'e':
                case 'E':
                    return "1110";
                case 'f':
                case 'F':
                    return "1111";
                default:
                    throw new Exception("Input is not a  Hex. string");
            }
        }
    }

    /// <summary>
    /// Utility class for XML manipulation
    /// </summary>
    public class XmlUtil
    {
        /// <summary>
        /// Get the inner text of particular child node
        /// </summary>
        /// <param name="node">Xml node to be evaluated</param>
        /// <param name="child_node_name">Name of the child node</param>
        /// <returns></returns>
        public static string GetNodeValue(XmlNode node, string child_node_name)
        {
            foreach (XmlNode cn in node.ChildNodes)
            {
                if (cn.Name == child_node_name) return cn.InnerText;
            }

            return string.Empty;
        }

        /// <summary>
        /// Get all the child nodes has same name
        /// </summary>
        /// <param name="node">Xml node to be evaluated</param>
        /// <param name="child_node_name">Name of the child nodes</param>
        /// <returns></returns>
        public static XmlNodeList GetXmlNodes(XmlNode node, string child_node_name)
        {
            return node.SelectNodes(child_node_name);
        }

        /// <summary>
        /// Get child nodes' child nodes.
        /// </summary>
        /// <param name="node">Xml node to be evaluated</param>
        /// <param name="child_node_name"></param>
        /// <returns></returns>
        public static XmlNodeList GetXmlNodeChildren(XmlNode node, string child_node_name)
        {
            XmlNode cNode = node.SelectSingleNode(child_node_name);
            if (cNode != null)
            {
                return cNode.ChildNodes;
            }
            else
                return null;
        }

        /// <summary>
        /// Get child node's custom nodes.
        /// </summary>
        /// <param name="node">Array of custom node list</param>
        /// <returns></returns>
        public static ArrayList GetXmlNodeCustomChildren(XmlNode node)
        {
            ArrayList arr = new ArrayList();
            foreach (XmlNode cnode in node.ChildNodes)
                if (cnode.Name.Contains(":")) arr.Add(cnode);

            return arr;
        }

        /// <summary>
        /// Get node attibute value
        /// </summary>
        /// <param name="node">Xml node to be evaluated</param>
        /// <param name="attr_name">Attributes</param>
        /// <returns></returns>
        public static string GetNodeAttrValue(XmlNode node, string attr_name)
        {
            foreach (XmlAttribute attr in node.Attributes)
            {
                if (attr.Name == attr_name) return attr.Value;
            }
            return string.Empty;
        }
    }
}