/* *************************************************************************** * 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; } } }