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