/* * Copyright (c) 2006-2014, openmetaverse.org * All rights reserved. * * - Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * - Neither the name of the openmetaverse.org nor the names * of its contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ using System; using System.Net; using System.Text; using System.Reflection; namespace OpenMetaverse { public static partial class Utils { #region String Arrays private static readonly string[] _AssetTypeNames = new string[] { "texture", // 0 "sound", // 1 "callcard", // 2 "landmark", // 3 "script", // 4 "clothing", // 5 "object", // 6 "notecard", // 7 "category", // 8 "root", // 9 "lsltext", // 10 "lslbyte", // 11 "txtr_tga", // 12 "bodypart", // 13 "trash", // 14 "snapshot", // 15 "lstndfnd", // 16 "snd_wav", // 17 "img_tga", // 18 "jpeg", // 19 "animatn", // 20 "gesture", // 21 "simstate", // 22 "favorite", // 23 "link", // 24 "linkfolder", // 25 String.Empty, // 26 String.Empty, // 27 String.Empty, // 28 String.Empty, // 29 String.Empty, // 30 String.Empty, // 31 String.Empty, // 32 String.Empty, // 33 String.Empty, // 34 String.Empty, // 35 String.Empty, // 36 String.Empty, // 37 String.Empty, // 38 String.Empty, // 39 String.Empty, // 40 String.Empty, // 41 String.Empty, // 42 String.Empty, // 43 String.Empty, // 44 String.Empty, // 45 "curoutfit", // 46 "outfit", // 47 "myoutfits", // 48 "mesh", // 49 }; private static readonly string[] _InventoryTypeNames = new string[] { "texture", // 0 "sound", // 1 "callcard", // 2 "landmark", // 3 String.Empty, // 4 String.Empty, // 5 "object", // 6 "notecard", // 7 "category", // 8 "root", // 9 "script", // 10 String.Empty, // 11 String.Empty, // 12 String.Empty, // 13 String.Empty, // 14 "snapshot", // 15 String.Empty, // 16 "attach", // 17 "wearable", // 18 "animation", // 19 "gesture", // 20 String.Empty, // 21 "mesh" // 22 }; private static readonly string[] _SaleTypeNames = new string[] { "not", "orig", "copy", "cntn" }; private static readonly string[] _AttachmentPointNames = new string[] { string.Empty, "ATTACH_CHEST", "ATTACH_HEAD", "ATTACH_LSHOULDER", "ATTACH_RSHOULDER", "ATTACH_LHAND", "ATTACH_RHAND", "ATTACH_LFOOT", "ATTACH_RFOOT", "ATTACH_BACK", "ATTACH_PELVIS", "ATTACH_MOUTH", "ATTACH_CHIN", "ATTACH_LEAR", "ATTACH_REAR", "ATTACH_LEYE", "ATTACH_REYE", "ATTACH_NOSE", "ATTACH_RUARM", "ATTACH_RLARM", "ATTACH_LUARM", "ATTACH_LLARM", "ATTACH_RHIP", "ATTACH_RULEG", "ATTACH_RLLEG", "ATTACH_LHIP", "ATTACH_LULEG", "ATTACH_LLLEG", "ATTACH_BELLY", "ATTACH_RPEC", "ATTACH_LPEC", "ATTACH_HUD_CENTER_2", "ATTACH_HUD_TOP_RIGHT", "ATTACH_HUD_TOP_CENTER", "ATTACH_HUD_TOP_LEFT", "ATTACH_HUD_CENTER_1", "ATTACH_HUD_BOTTOM_LEFT", "ATTACH_HUD_BOTTOM", "ATTACH_HUD_BOTTOM_RIGHT" }; public static bool InternStrings = false; #endregion String Arrays #region BytesTo /// /// Convert the first two bytes starting in the byte array in /// little endian ordering to a signed short integer /// /// An array two bytes or longer /// A signed short integer, will be zero if a short can't be /// read at the given position public static short BytesToInt16(byte[] bytes) { return BytesToInt16(bytes, 0); } /// /// Convert the first two bytes starting at the given position in /// little endian ordering to a signed short integer /// /// An array two bytes or longer /// Position in the array to start reading /// A signed short integer, will be zero if a short can't be /// read at the given position public static short BytesToInt16(byte[] bytes, int pos) { if (bytes.Length <= pos + 1) return 0; return (short)(bytes[pos] + (bytes[pos + 1] << 8)); } /// /// Convert the first four bytes starting at the given position in /// little endian ordering to a signed integer /// /// An array four bytes or longer /// Position to start reading the int from /// A signed integer, will be zero if an int can't be read /// at the given position public static int BytesToInt(byte[] bytes, int pos) { if (bytes.Length < pos + 4) return 0; return (int)(bytes[pos + 0] + (bytes[pos + 1] << 8) + (bytes[pos + 2] << 16) + (bytes[pos + 3] << 24)); } /// /// Convert the first four bytes of the given array in little endian /// ordering to a signed integer /// /// An array four bytes or longer /// A signed integer, will be zero if the array contains /// less than four bytes public static int BytesToInt(byte[] bytes) { return BytesToInt(bytes, 0); } /// /// Convert the first eight bytes of the given array in little endian /// ordering to a signed long integer /// /// An array eight bytes or longer /// A signed long integer, will be zero if the array contains /// less than eight bytes public static long BytesToInt64(byte[] bytes) { return BytesToInt64(bytes, 0); } /// /// Convert the first eight bytes starting at the given position in /// little endian ordering to a signed long integer /// /// An array eight bytes or longer /// Position to start reading the long from /// A signed long integer, will be zero if a long can't be read /// at the given position public static long BytesToInt64(byte[] bytes, int pos) { if (bytes.Length < pos + 8) return 0; return (long) ((long)bytes[pos + 0] + ((long)bytes[pos + 1] << 8) + ((long)bytes[pos + 2] << 16) + ((long)bytes[pos + 3] << 24) + ((long)bytes[pos + 4] << 32) + ((long)bytes[pos + 5] << 40) + ((long)bytes[pos + 6] << 48) + ((long)bytes[pos + 7] << 56)); } /// /// Convert the first two bytes starting at the given position in /// little endian ordering to an unsigned short /// /// Byte array containing the ushort /// Position to start reading the ushort from /// An unsigned short, will be zero if a ushort can't be read /// at the given position public static ushort BytesToUInt16(byte[] bytes, int pos) { if (bytes.Length <= pos + 1) return 0; return (ushort)(bytes[pos] + (bytes[pos + 1] << 8)); } /// /// Convert two bytes in little endian ordering to an unsigned short /// /// Byte array containing the ushort /// An unsigned short, will be zero if a ushort can't be /// read public static ushort BytesToUInt16(byte[] bytes) { return BytesToUInt16(bytes, 0); } /// /// Convert the first four bytes starting at the given position in /// little endian ordering to an unsigned integer /// /// Byte array containing the uint /// Position to start reading the uint from /// An unsigned integer, will be zero if a uint can't be read /// at the given position public static uint BytesToUInt(byte[] bytes, int pos) { if (bytes.Length < pos + 4) return 0; return (uint)(bytes[pos + 0] + (bytes[pos + 1] << 8) + (bytes[pos + 2] << 16) + (bytes[pos + 3] << 24)); } /// /// Convert the first four bytes of the given array in little endian /// ordering to an unsigned integer /// /// An array four bytes or longer /// An unsigned integer, will be zero if the array contains /// less than four bytes public static uint BytesToUInt(byte[] bytes) { return BytesToUInt(bytes, 0); } /// /// Convert the first eight bytes of the given array in little endian /// ordering to an unsigned 64-bit integer /// /// An array eight bytes or longer /// An unsigned 64-bit integer, will be zero if the array /// contains less than eight bytes public static ulong BytesToUInt64(byte[] bytes) { if (bytes.Length < 8) return 0; return (ulong) ((ulong)bytes[0] + ((ulong)bytes[1] << 8) + ((ulong)bytes[2] << 16) + ((ulong)bytes[3] << 24) + ((ulong)bytes[4] << 32) + ((ulong)bytes[5] << 40) + ((ulong)bytes[6] << 48) + ((ulong)bytes[7] << 56)); } /// /// Convert four bytes in little endian ordering to a floating point /// value /// /// Byte array containing a little ending floating /// point value /// Starting position of the floating point value in /// the byte array /// Single precision value public static float BytesToFloat(byte[] bytes, int pos) { if (!BitConverter.IsLittleEndian) { byte[] newBytes = new byte[4]; Buffer.BlockCopy(bytes, pos, newBytes, 0, 4); Array.Reverse(newBytes, 0, 4); return BitConverter.ToSingle(newBytes, 0); } else { return BitConverter.ToSingle(bytes, pos); } } public static double BytesToDouble(byte[] bytes, int pos) { if (!BitConverter.IsLittleEndian) { byte[] newBytes = new byte[8]; Buffer.BlockCopy(bytes, pos, newBytes, 0, 8); Array.Reverse(newBytes, 0, 8); return BitConverter.ToDouble(newBytes, 0); } else { return BitConverter.ToDouble(bytes, pos); } } #endregion BytesTo #region ToBytes public static byte[] Int16ToBytes(short value) { byte[] bytes = new byte[2]; bytes[0] = (byte)(value % 256); bytes[1] = (byte)((value >> 8) % 256); return bytes; } public static void Int16ToBytes(short value, byte[] dest, int pos) { dest[pos] = (byte)(value % 256); dest[pos + 1] = (byte)((value >> 8) % 256); } public static byte[] UInt16ToBytes(ushort value) { byte[] bytes = new byte[2]; bytes[0] = (byte)(value % 256); bytes[1] = (byte)((value >> 8) % 256); return bytes; } public static void UInt16ToBytes(ushort value, byte[] dest, int pos) { dest[pos] = (byte)(value % 256); dest[pos + 1] = (byte)((value >> 8) % 256); } public static void UInt16ToBytesBig(ushort value, byte[] dest, int pos) { dest[pos] = (byte)((value >> 8) % 256); dest[pos + 1] = (byte)(value % 256); } /// /// Convert an integer to a byte array in little endian format /// /// The integer to convert /// A four byte little endian array public static byte[] IntToBytes(int value) { byte[] bytes = new byte[4]; bytes[0] = (byte)(value % 256); bytes[1] = (byte)((value >> 8) % 256); bytes[2] = (byte)((value >> 16) % 256); bytes[3] = (byte)((value >> 24) % 256); return bytes; } /// /// Convert an integer to a byte array in big endian format /// /// The integer to convert /// A four byte big endian array public static byte[] IntToBytesBig(int value) { byte[] bytes = new byte[4]; bytes[0] = (byte)((value >> 24) % 256); bytes[1] = (byte)((value >> 16) % 256); bytes[2] = (byte)((value >> 8) % 256); bytes[3] = (byte)(value % 256); return bytes; } public static void IntToBytes(int value, byte[] dest, int pos) { dest[pos] = (byte)(value % 256); dest[pos + 1] = (byte)((value >> 8) % 256); dest[pos + 2] = (byte)((value >> 16) % 256); dest[pos + 3] = (byte)((value >> 24) % 256); } public static byte[] UIntToBytes(uint value) { byte[] bytes = new byte[4]; bytes[0] = (byte)(value % 256); bytes[1] = (byte)((value >> 8) % 256); bytes[2] = (byte)((value >> 16) % 256); bytes[3] = (byte)((value >> 24) % 256); return bytes; } public static void UIntToBytes(uint value, byte[] dest, int pos) { dest[pos] = (byte)(value % 256); dest[pos + 1] = (byte)((value >> 8) % 256); dest[pos + 2] = (byte)((value >> 16) % 256); dest[pos + 3] = (byte)((value >> 24) % 256); } public static void UIntToBytesBig(uint value, byte[] dest, int pos) { dest[pos] = (byte)((value >> 24) % 256); dest[pos + 1] = (byte)((value >> 16) % 256); dest[pos + 2] = (byte)((value >> 8) % 256); dest[pos + 3] = (byte)(value % 256); } /// /// Convert a 64-bit integer to a byte array in little endian format /// /// The value to convert /// An 8 byte little endian array public static byte[] Int64ToBytes(long value) { byte[] bytes = BitConverter.GetBytes(value); if (!BitConverter.IsLittleEndian) Array.Reverse(bytes); return bytes; } public static void Int64ToBytes(long value, byte[] dest, int pos) { byte[] bytes = Int64ToBytes(value); Buffer.BlockCopy(bytes, 0, dest, pos, 8); } /// /// Convert a 64-bit unsigned integer to a byte array in little endian /// format /// /// The value to convert /// An 8 byte little endian array public static byte[] UInt64ToBytes(ulong value) { byte[] bytes = BitConverter.GetBytes(value); if (!BitConverter.IsLittleEndian) Array.Reverse(bytes); return bytes; } public static byte[] UInt64ToBytesBig(ulong value) { byte[] bytes = BitConverter.GetBytes(value); if (BitConverter.IsLittleEndian) Array.Reverse(bytes); return bytes; } public static void UInt64ToBytes(ulong value, byte[] dest, int pos) { byte[] bytes = UInt64ToBytes(value); Buffer.BlockCopy(bytes, 0, dest, pos, 8); } public static void UInt64ToBytesBig(ulong value, byte[] dest, int pos) { byte[] bytes = UInt64ToBytesBig(value); Buffer.BlockCopy(bytes, 0, dest, pos, 8); } /// /// Convert a floating point value to four bytes in little endian /// ordering /// /// A floating point value /// A four byte array containing the value in little endian /// ordering public static byte[] FloatToBytes(float value) { byte[] bytes = BitConverter.GetBytes(value); if (!BitConverter.IsLittleEndian) Array.Reverse(bytes); return bytes; } public static void FloatToBytes(float value, byte[] dest, int pos) { byte[] bytes = FloatToBytes(value); Buffer.BlockCopy(bytes, 0, dest, pos, 4); } public static byte[] DoubleToBytes(double value) { byte[] bytes = BitConverter.GetBytes(value); if (!BitConverter.IsLittleEndian) Array.Reverse(bytes); return bytes; } public static byte[] DoubleToBytesBig(double value) { byte[] bytes = BitConverter.GetBytes(value); if (BitConverter.IsLittleEndian) Array.Reverse(bytes); return bytes; } public static void DoubleToBytes(double value, byte[] dest, int pos) { byte[] bytes = DoubleToBytes(value); Buffer.BlockCopy(bytes, 0, dest, pos, 8); } #endregion ToBytes #region Strings /// /// Converts an unsigned integer to a hexadecimal string /// /// An unsigned integer to convert to a string /// A hexadecimal string 10 characters long /// 0x7fffffff public static string UIntToHexString(uint i) { return string.Format("{0:x8}", i); } /// /// Convert a variable length UTF8 byte array to a string /// /// The UTF8 encoded byte array to convert /// The decoded string public static string BytesToString(byte[] bytes) { if (bytes.Length > 0 && bytes[bytes.Length - 1] == 0x00) return GetString(bytes, 0, bytes.Length - 1); else return GetString(bytes, 0, bytes.Length); } public static string BytesToString(byte[] bytes, int index, int count) { if (bytes.Length > index + count && bytes[index + count - 1] == 0x00) return GetString(bytes, index, count - 1); else return GetString(bytes, index, count); } private static string GetString(byte[] bytes, int index, int count) { string cnv = UTF8Encoding.UTF8.GetString(bytes, index, count); return InternStrings ? string.Intern(cnv) : cnv; } /// /// Converts a byte array to a string containing hexadecimal characters /// /// The byte array to convert to a string /// The name of the field to prepend to each /// line of the string /// A string containing hexadecimal characters on multiple /// lines. Each line is prepended with the field name public static string BytesToHexString(byte[] bytes, string fieldName) { string cnv = BytesToHexString(bytes, bytes.Length, fieldName); return InternStrings ? string.Intern(cnv) : cnv; } /// /// Converts a byte array to a string containing hexadecimal characters /// /// The byte array to convert to a string /// Number of bytes in the array to parse /// A string to prepend to each line of the hex /// dump /// A string containing hexadecimal characters on multiple /// lines. Each line is prepended with the field name public static string BytesToHexString(byte[] bytes, int length, string fieldName) { StringBuilder output = new StringBuilder(); for (int i = 0; i < length; i += 16) { if (i != 0) output.Append('\n'); if (!String.IsNullOrEmpty(fieldName)) { output.Append(fieldName); output.Append(": "); } for (int j = 0; j < 16; j++) { if ((i + j) < length) { if (j != 0) output.Append(' '); output.Append(String.Format("{0:X2}", bytes[i + j])); } } } return output.ToString(); } /// /// Convert a string to a UTF8 encoded byte array /// /// The string to convert /// A null-terminated UTF8 byte array public static byte[] StringToBytes(string str) { if (String.IsNullOrEmpty(str)) { return Utils.EmptyBytes; } if (!str.EndsWith("\0")) { str += "\0"; } return System.Text.UTF8Encoding.UTF8.GetBytes(str); } /// /// Converts a string containing hexadecimal characters to a byte array /// /// String containing hexadecimal characters /// If true, gracefully handles null, empty and /// uneven strings as well as stripping unconvertable characters /// The converted byte array public static byte[] HexStringToBytes(string hexString, bool handleDirty) { if (handleDirty) { if (String.IsNullOrEmpty(hexString)) return Utils.EmptyBytes; StringBuilder stripped = new StringBuilder(hexString.Length); char c; // remove all non A-F, 0-9, characters for (int i = 0; i < hexString.Length; i++) { c = hexString[i]; if (IsHexDigit(c)) stripped.Append(c); } hexString = stripped.ToString(); // if odd number of characters, discard last character if (hexString.Length % 2 != 0) { hexString = hexString.Substring(0, hexString.Length - 1); } } int byteLength = hexString.Length / 2; byte[] bytes = new byte[byteLength]; int j = 0; for (int i = 0; i < bytes.Length; i++) { bytes[i] = HexToByte(hexString.Substring(j, 2)); j += 2; } return bytes; } /// /// Returns true is c is a hexadecimal digit (A-F, a-f, 0-9) /// /// Character to test /// true if hex digit, false if not private static bool IsHexDigit(Char c) { const int numA = 65; const int num0 = 48; int numChar; c = Char.ToUpper(c); numChar = Convert.ToInt32(c); if (numChar >= numA && numChar < (numA + 6)) return true; else if (numChar >= num0 && numChar < (num0 + 10)) return true; else return false; } /// /// Converts 1 or 2 character string into equivalant byte value /// /// 1 or 2 character string /// byte private static byte HexToByte(string hex) { if (hex.Length > 2 || hex.Length <= 0) throw new ArgumentException("hex must be 1 or 2 characters in length"); byte newByte = Byte.Parse(hex, System.Globalization.NumberStyles.HexNumber); return newByte; } #endregion Strings #region Packed Values /// /// Convert a float value to a byte given a minimum and maximum range /// /// Value to convert to a byte /// Minimum value range /// Maximum value range /// A single byte representing the original float value public static byte FloatToByte(float val, float lower, float upper) { val = Utils.Clamp(val, lower, upper); // Normalize the value val -= lower; val /= (upper - lower); return (byte)Math.Floor(val * (float)byte.MaxValue); } /// /// Convert a byte to a float value given a minimum and maximum range /// /// Byte array to get the byte from /// Position in the byte array the desired byte is at /// Minimum value range /// Maximum value range /// A float value inclusively between lower and upper public static float ByteToFloat(byte[] bytes, int pos, float lower, float upper) { if (bytes.Length <= pos) return 0; return ByteToFloat(bytes[pos], lower, upper); } /// /// Convert a byte to a float value given a minimum and maximum range /// /// Byte to convert to a float value /// Minimum value range /// Maximum value range /// A float value inclusively between lower and upper public static float ByteToFloat(byte val, float lower, float upper) { const float ONE_OVER_BYTEMAX = 1.0f / (float)byte.MaxValue; float fval = (float)val * ONE_OVER_BYTEMAX; float delta = (upper - lower); fval *= delta; fval += lower; // Test for values very close to zero float error = delta * ONE_OVER_BYTEMAX; if (Math.Abs(fval) < error) fval = 0.0f; return fval; } public static float UInt16ToFloat(byte[] bytes, int pos, float lower, float upper) { ushort val = BytesToUInt16(bytes, pos); return UInt16ToFloat(val, lower, upper); } public static float UInt16ToFloat(ushort val, float lower, float upper) { const float ONE_OVER_U16_MAX = 1.0f / (float)UInt16.MaxValue; float fval = (float)val * ONE_OVER_U16_MAX; float delta = upper - lower; fval *= delta; fval += lower; // Make sure zeroes come through as zero float maxError = delta * ONE_OVER_U16_MAX; if (Math.Abs(fval) < maxError) fval = 0.0f; return fval; } public static ushort FloatToUInt16(float value, float lower, float upper) { float delta = upper - lower; value -= lower; value /= delta; value *= (float)UInt16.MaxValue; return (ushort)value; } #endregion Packed Values #region TryParse /// /// Attempts to parse a floating point value from a string, using an /// EN-US number format /// /// String to parse /// Resulting floating point number /// True if the parse was successful, otherwise false public static bool TryParseSingle(string s, out float result) { return Single.TryParse(s, System.Globalization.NumberStyles.Float, EnUsCulture.NumberFormat, out result); } /// /// Attempts to parse a floating point value from a string, using an /// EN-US number format /// /// String to parse /// Resulting floating point number /// True if the parse was successful, otherwise false public static bool TryParseDouble(string s, out double result) { // NOTE: Double.TryParse can't parse Double.[Min/Max]Value.ToString(), see: // http://blogs.msdn.com/bclteam/archive/2006/05/24/598169.aspx return Double.TryParse(s, System.Globalization.NumberStyles.Float, EnUsCulture.NumberFormat, out result); } /// /// Tries to parse an unsigned 32-bit integer from a hexadecimal string /// /// String to parse /// Resulting integer /// True if the parse was successful, otherwise false public static bool TryParseHex(string s, out uint result) { return UInt32.TryParse(s, System.Globalization.NumberStyles.HexNumber, EnUsCulture.NumberFormat, out result); } #endregion TryParse #region Enum String Conversion /// /// Returns text specified in EnumInfo attribute of the enumerator /// To add the text use [EnumInfo(Text = "Some nice text here")] before declaration /// of enum values /// /// Enum value /// Text representation of the enum public static string EnumToText(Enum value) { // Get the type Type type = value.GetType(); // Get fieldinfo for this type FieldInfo fieldInfo = type.GetField(value.ToString()); // Find extended attributes, if any EnumInfoAttribute[] attribs = (EnumInfoAttribute[])fieldInfo.GetCustomAttributes(typeof(EnumInfoAttribute), false); return attribs.Length > 0 ? attribs[0].Text : value.ToString(); } /// /// Takes an AssetType and returns the string representation /// /// The source /// The string version of the AssetType public static string AssetTypeToString(AssetType type) { return _AssetTypeNames[(int)type]; } /// /// Translate a string name of an AssetType into the proper Type /// /// A string containing the AssetType name /// The AssetType which matches the string name, or AssetType.Unknown if no match was found public static AssetType StringToAssetType(string type) { for (int i = 0; i < _AssetTypeNames.Length; i++) { if (_AssetTypeNames[i] == type) return (AssetType)i; } return AssetType.Unknown; } /// /// Convert an InventoryType to a string /// /// The to convert /// A string representation of the source public static string InventoryTypeToString(InventoryType type) { return _InventoryTypeNames[(int)type]; } /// /// Convert a string into a valid InventoryType /// /// A string representation of the InventoryType to convert /// A InventoryType object which matched the type public static InventoryType StringToInventoryType(string type) { for (int i = 0; i < _InventoryTypeNames.Length; i++) { if (_InventoryTypeNames[i] == type) return (InventoryType)i; } return InventoryType.Unknown; } /// /// Convert a SaleType to a string /// /// The to convert /// A string representation of the source public static string SaleTypeToString(SaleType type) { return _SaleTypeNames[(int)type]; } /// /// Convert a string into a valid SaleType /// /// A string representation of the SaleType to convert /// A SaleType object which matched the type public static SaleType StringToSaleType(string value) { for (int i = 0; i < _SaleTypeNames.Length; i++) { if (value == _SaleTypeNames[i]) return (SaleType)i; } return SaleType.Not; } /// /// Converts a string used in LLSD to AttachmentPoint type /// /// String representation of AttachmentPoint to convert /// AttachmentPoint enum public static AttachmentPoint StringToAttachmentPoint(string value) { for (int i = 0; i < _AttachmentPointNames.Length; i++) { if (value == _AttachmentPointNames[i]) return (AttachmentPoint)i; } return AttachmentPoint.Default; } #endregion Enum String Conversion #region Miscellaneous /// /// Copy a byte array /// /// Byte array to copy /// A copy of the given byte array public static byte[] CopyBytes(byte[] bytes) { if (bytes == null) return null; byte[] newBytes = new byte[bytes.Length]; Buffer.BlockCopy(bytes, 0, newBytes, 0, bytes.Length); return newBytes; } /// /// Packs to 32-bit unsigned integers in to a 64-bit unsigned integer /// /// The left-hand (or X) value /// The right-hand (or Y) value /// A 64-bit integer containing the two 32-bit input values public static ulong UIntsToLong(uint a, uint b) { return ((ulong)a << 32) | (ulong)b; } /// /// Unpacks two 32-bit unsigned integers from a 64-bit unsigned integer /// /// The 64-bit input integer /// The left-hand (or X) output value /// The right-hand (or Y) output value public static void LongToUInts(ulong a, out uint b, out uint c) { b = (uint)(a >> 32); c = (uint)(a & 0x00000000FFFFFFFF); } /// /// Convert an IP address object to an unsigned 32-bit integer /// /// IP address to convert /// 32-bit unsigned integer holding the IP address bits public static uint IPToUInt(System.Net.IPAddress address) { byte[] bytes = address.GetAddressBytes(); return (uint)((bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]); } /// /// Gets a unix timestamp for the current time /// /// An unsigned integer representing a unix timestamp for now public static uint GetUnixTime() { return (uint)(DateTime.UtcNow - Epoch).TotalSeconds; } /// /// Convert a UNIX timestamp to a native DateTime object /// /// An unsigned integer representing a UNIX /// timestamp /// A DateTime object containing the same time specified in /// the given timestamp public static DateTime UnixTimeToDateTime(uint timestamp) { DateTime dateTime = Epoch; // Add the number of seconds in our UNIX timestamp dateTime = dateTime.AddSeconds(timestamp); return dateTime; } /// /// Convert a UNIX timestamp to a native DateTime object /// /// A signed integer representing a UNIX /// timestamp /// A DateTime object containing the same time specified in /// the given timestamp public static DateTime UnixTimeToDateTime(int timestamp) { return UnixTimeToDateTime((uint)timestamp); } /// /// Convert a native DateTime object to a UNIX timestamp /// /// A DateTime object you want to convert to a /// timestamp /// An unsigned integer representing a UNIX timestamp public static uint DateTimeToUnixTime(DateTime time) { TimeSpan ts = (time - new DateTime(1970, 1, 1, 0, 0, 0)); return (uint)ts.TotalSeconds; } /// /// Swap two values /// /// Type of the values to swap /// First value /// Second value public static void Swap(ref T lhs, ref T rhs) { T temp = lhs; lhs = rhs; rhs = temp; } /// /// Try to parse an enumeration value from a string /// /// Enumeration type /// String value to parse /// Enumeration value on success /// True if the parsing succeeded, otherwise false public static bool EnumTryParse(string strType, out T result) { Type t = typeof(T); if (Enum.IsDefined(t, strType)) { result = (T)Enum.Parse(t, strType, true); return true; } else { foreach (string value in Enum.GetNames(typeof(T))) { if (value.Equals(strType, StringComparison.OrdinalIgnoreCase)) { result = (T)Enum.Parse(typeof(T), value); return true; } } result = default(T); return false; } } /// /// Swaps the high and low words in a byte. Converts aaaabbbb to bbbbaaaa /// /// Byte to swap the words in /// Byte value with the words swapped public static byte SwapWords(byte value) { return (byte)(((value & 0xF0) >> 4) | ((value & 0x0F) << 4)); } /// /// Attempts to convert a string representation of a hostname or IP /// address to a /// /// Hostname to convert to an IPAddress /// Converted IP address object, or null if the conversion /// failed public static IPAddress HostnameToIPv4(string hostname) { // Is it already a valid IP? IPAddress ip; if (IPAddress.TryParse(hostname, out ip)) return ip; IPAddress[] hosts = Dns.GetHostEntry(hostname).AddressList; for (int i = 0; i < hosts.Length; i++) { IPAddress host = hosts[i]; if (host.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) return host; } return null; } #endregion Miscellaneous } }