/*
* 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.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
namespace OpenMetaverse.StructuredData
{
///
///
///
public enum OSDType
{
///
Unknown,
///
Boolean,
///
Integer,
///
Real,
///
String,
///
UUID,
///
Date,
///
URI,
///
Binary,
///
Map,
///
Array
}
public enum OSDFormat
{
Xml = 0,
Json,
Binary
}
///
///
///
public class OSDException : Exception
{
public OSDException(string message) : base(message) { }
}
///
///
///
public partial class OSD
{
public virtual OSDType Type { get { return OSDType.Unknown; } }
public virtual bool AsBoolean() { return false; }
public virtual int AsInteger() { return 0; }
public virtual uint AsUInteger() { return 0; }
public virtual long AsLong() { return 0; }
public virtual ulong AsULong() { return 0; }
public virtual double AsReal() { return 0d; }
public virtual string AsString() { return String.Empty; }
public virtual UUID AsUUID() { return UUID.Zero; }
public virtual DateTime AsDate() { return Utils.Epoch; }
public virtual Uri AsUri() { return null; }
public virtual byte[] AsBinary() { return Utils.EmptyBytes; }
public virtual Vector2 AsVector2() { return Vector2.Zero; }
public virtual Vector3 AsVector3() { return Vector3.Zero; }
public virtual Vector3d AsVector3d() { return Vector3d.Zero; }
public virtual Vector4 AsVector4() { return Vector4.Zero; }
public virtual Quaternion AsQuaternion() { return Quaternion.Identity; }
public virtual Color4 AsColor4() { return Color4.Black; }
public virtual OSD Copy() { return new OSD(); }
public override string ToString() { return "undef"; }
public static OSD FromBoolean(bool value) { return new OSDBoolean(value); }
public static OSD FromInteger(int value) { return new OSDInteger(value); }
public static OSD FromInteger(uint value) { return new OSDInteger((int)value); }
public static OSD FromInteger(short value) { return new OSDInteger((int)value); }
public static OSD FromInteger(ushort value) { return new OSDInteger((int)value); }
public static OSD FromInteger(sbyte value) { return new OSDInteger((int)value); }
public static OSD FromInteger(byte value) { return new OSDInteger((int)value); }
public static OSD FromUInteger(uint value) { return new OSDBinary(value); }
public static OSD FromLong(long value) { return new OSDBinary(value); }
public static OSD FromULong(ulong value) { return new OSDBinary(value); }
public static OSD FromReal(double value) { return new OSDReal(value); }
public static OSD FromReal(float value) { return new OSDReal((double)value); }
public static OSD FromString(string value) { return new OSDString(value); }
public static OSD FromUUID(UUID value) { return new OSDUUID(value); }
public static OSD FromDate(DateTime value) { return new OSDDate(value); }
public static OSD FromUri(Uri value) { return new OSDUri(value); }
public static OSD FromBinary(byte[] value) { return new OSDBinary(value); }
public static OSD FromVector2(Vector2 value)
{
OSDArray array = new OSDArray();
array.Add(OSD.FromReal(value.X));
array.Add(OSD.FromReal(value.Y));
return array;
}
public static OSD FromVector3(Vector3 value)
{
OSDArray array = new OSDArray();
array.Add(OSD.FromReal(value.X));
array.Add(OSD.FromReal(value.Y));
array.Add(OSD.FromReal(value.Z));
return array;
}
public static OSD FromVector3d(Vector3d value)
{
OSDArray array = new OSDArray();
array.Add(OSD.FromReal(value.X));
array.Add(OSD.FromReal(value.Y));
array.Add(OSD.FromReal(value.Z));
return array;
}
public static OSD FromVector4(Vector4 value)
{
OSDArray array = new OSDArray();
array.Add(OSD.FromReal(value.X));
array.Add(OSD.FromReal(value.Y));
array.Add(OSD.FromReal(value.Z));
array.Add(OSD.FromReal(value.W));
return array;
}
public static OSD FromQuaternion(Quaternion value)
{
OSDArray array = new OSDArray();
array.Add(OSD.FromReal(value.X));
array.Add(OSD.FromReal(value.Y));
array.Add(OSD.FromReal(value.Z));
array.Add(OSD.FromReal(value.W));
return array;
}
public static OSD FromColor4(Color4 value)
{
OSDArray array = new OSDArray();
array.Add(OSD.FromReal(value.R));
array.Add(OSD.FromReal(value.G));
array.Add(OSD.FromReal(value.B));
array.Add(OSD.FromReal(value.A));
return array;
}
public static OSD FromObject(object value)
{
if (value == null) { return new OSD(); }
else if (value is bool) { return new OSDBoolean((bool)value); }
else if (value is int) { return new OSDInteger((int)value); }
else if (value is uint) { return new OSDBinary((uint)value); }
else if (value is short) { return new OSDInteger((int)(short)value); }
else if (value is ushort) { return new OSDInteger((int)(ushort)value); }
else if (value is sbyte) { return new OSDInteger((int)(sbyte)value); }
else if (value is byte) { return new OSDInteger((int)(byte)value); }
else if (value is double) { return new OSDReal((double)value); }
else if (value is float) { return new OSDReal((double)(float)value); }
else if (value is string) { return new OSDString((string)value); }
else if (value is UUID) { return new OSDUUID((UUID)value); }
else if (value is DateTime) { return new OSDDate((DateTime)value); }
else if (value is Uri) { return new OSDUri((Uri)value); }
else if (value is byte[]) { return new OSDBinary((byte[])value); }
else if (value is long) { return new OSDBinary((long)value); }
else if (value is ulong) { return new OSDBinary((ulong)value); }
else if (value is Vector2) { return FromVector2((Vector2)value); }
else if (value is Vector3) { return FromVector3((Vector3)value); }
else if (value is Vector3d) { return FromVector3d((Vector3d)value); }
else if (value is Vector4) { return FromVector4((Vector4)value); }
else if (value is Quaternion) { return FromQuaternion((Quaternion)value); }
else if (value is Color4) { return FromColor4((Color4)value); }
else return new OSD();
}
public static object ToObject(Type type, OSD value)
{
if (type == typeof(ulong))
{
if (value.Type == OSDType.Binary)
{
byte[] bytes = value.AsBinary();
return Utils.BytesToUInt64(bytes);
}
else
{
return (ulong)value.AsInteger();
}
}
else if (type == typeof(uint))
{
if (value.Type == OSDType.Binary)
{
byte[] bytes = value.AsBinary();
return Utils.BytesToUInt(bytes);
}
else
{
return (uint)value.AsInteger();
}
}
else if (type == typeof(ushort))
{
return (ushort)value.AsInteger();
}
else if (type == typeof(byte))
{
return (byte)value.AsInteger();
}
else if (type == typeof(short))
{
return (short)value.AsInteger();
}
else if (type == typeof(string))
{
return value.AsString();
}
else if (type == typeof(bool))
{
return value.AsBoolean();
}
else if (type == typeof(float))
{
return (float)value.AsReal();
}
else if (type == typeof(double))
{
return value.AsReal();
}
else if (type == typeof(int))
{
return value.AsInteger();
}
else if (type == typeof(UUID))
{
return value.AsUUID();
}
else if (type == typeof(Vector3))
{
if (value.Type == OSDType.Array)
return ((OSDArray)value).AsVector3();
else
return Vector3.Zero;
}
else if (type == typeof(Vector4))
{
if (value.Type == OSDType.Array)
return ((OSDArray)value).AsVector4();
else
return Vector4.Zero;
}
else if (type == typeof(Quaternion))
{
if (value.Type == OSDType.Array)
return ((OSDArray)value).AsQuaternion();
else
return Quaternion.Identity;
}
else if (type == typeof(OSDArray))
{
OSDArray newArray = new OSDArray();
foreach (OSD o in (OSDArray)value)
newArray.Add(o);
return newArray;
}
else if (type == typeof(OSDMap))
{
OSDMap newMap = new OSDMap();
foreach (KeyValuePair o in (OSDMap)value)
newMap.Add(o);
return newMap;
}
else
{
return null;
}
}
#region Implicit Conversions
public static implicit operator OSD(bool value) { return new OSDBoolean(value); }
public static implicit operator OSD(int value) { return new OSDInteger(value); }
public static implicit operator OSD(uint value) { return new OSDInteger((int)value); }
public static implicit operator OSD(short value) { return new OSDInteger((int)value); }
public static implicit operator OSD(ushort value) { return new OSDInteger((int)value); }
public static implicit operator OSD(sbyte value) { return new OSDInteger((int)value); }
public static implicit operator OSD(byte value) { return new OSDInteger((int)value); }
public static implicit operator OSD(long value) { return new OSDBinary(value); }
public static implicit operator OSD(ulong value) { return new OSDBinary(value); }
public static implicit operator OSD(double value) { return new OSDReal(value); }
public static implicit operator OSD(float value) { return new OSDReal(value); }
public static implicit operator OSD(string value) { return new OSDString(value); }
public static implicit operator OSD(UUID value) { return new OSDUUID(value); }
public static implicit operator OSD(DateTime value) { return new OSDDate(value); }
public static implicit operator OSD(Uri value) { return new OSDUri(value); }
public static implicit operator OSD(byte[] value) { return new OSDBinary(value); }
public static implicit operator OSD(Vector2 value) { return OSD.FromVector2(value); }
public static implicit operator OSD(Vector3 value) { return OSD.FromVector3(value); }
public static implicit operator OSD(Vector3d value) { return OSD.FromVector3d(value); }
public static implicit operator OSD(Vector4 value) { return OSD.FromVector4(value); }
public static implicit operator OSD(Quaternion value) { return OSD.FromQuaternion(value); }
public static implicit operator OSD(Color4 value) { return OSD.FromColor4(value); }
public static implicit operator bool(OSD value) { return value.AsBoolean(); }
public static implicit operator int(OSD value) { return value.AsInteger(); }
public static implicit operator uint(OSD value) { return value.AsUInteger(); }
public static implicit operator long(OSD value) { return value.AsLong(); }
public static implicit operator ulong(OSD value) { return value.AsULong(); }
public static implicit operator double(OSD value) { return value.AsReal(); }
public static implicit operator float(OSD value) { return (float)value.AsReal(); }
public static implicit operator string(OSD value) { return value.AsString(); }
public static implicit operator UUID(OSD value) { return value.AsUUID(); }
public static implicit operator DateTime(OSD value) { return value.AsDate(); }
public static implicit operator Uri(OSD value) { return value.AsUri(); }
public static implicit operator byte[](OSD value) { return value.AsBinary(); }
public static implicit operator Vector2(OSD value) { return value.AsVector2(); }
public static implicit operator Vector3(OSD value) { return value.AsVector3(); }
public static implicit operator Vector3d(OSD value) { return value.AsVector3d(); }
public static implicit operator Vector4(OSD value) { return value.AsVector4(); }
public static implicit operator Quaternion(OSD value) { return value.AsQuaternion(); }
public static implicit operator Color4(OSD value) { return value.AsColor4(); }
#endregion Implicit Conversions
///
/// Uses reflection to create an SDMap from all of the SD
/// serializable types in an object
///
/// Class or struct containing serializable types
/// An SDMap holding the serialized values from the
/// container object
public static OSDMap SerializeMembers(object obj)
{
Type t = obj.GetType();
FieldInfo[] fields = t.GetFields();
OSDMap map = new OSDMap(fields.Length);
for (int i = 0; i < fields.Length; i++)
{
FieldInfo field = fields[i];
if (!Attribute.IsDefined(field, typeof(NonSerializedAttribute)))
{
OSD serializedField = OSD.FromObject(field.GetValue(obj));
if (serializedField.Type != OSDType.Unknown || field.FieldType == typeof(string) || field.FieldType == typeof(byte[]))
map.Add(field.Name, serializedField);
}
}
return map;
}
///
/// Uses reflection to deserialize member variables in an object from
/// an SDMap
///
/// Reference to an object to fill with deserialized
/// values
/// Serialized values to put in the target
/// object
public static void DeserializeMembers(ref object obj, OSDMap serialized)
{
Type t = obj.GetType();
FieldInfo[] fields = t.GetFields();
for (int i = 0; i < fields.Length; i++)
{
FieldInfo field = fields[i];
if (!Attribute.IsDefined(field, typeof(NonSerializedAttribute)))
{
OSD serializedField;
if (serialized.TryGetValue(field.Name, out serializedField))
field.SetValue(obj, ToObject(field.FieldType, serializedField));
}
}
}
}
///
///
///
public sealed class OSDBoolean : OSD
{
private bool value;
private static byte[] trueBinary = { 0x31 };
private static byte[] falseBinary = { 0x30 };
public override OSDType Type { get { return OSDType.Boolean; } }
public OSDBoolean(bool value)
{
this.value = value;
}
public override bool AsBoolean() { return value; }
public override int AsInteger() { return value ? 1 : 0; }
public override double AsReal() { return value ? 1d : 0d; }
public override string AsString() { return value ? "1" : "0"; }
public override byte[] AsBinary() { return value ? trueBinary : falseBinary; }
public override OSD Copy() { return new OSDBoolean(value); }
public override string ToString() { return AsString(); }
}
///
///
///
public sealed class OSDInteger : OSD
{
private int value;
public override OSDType Type { get { return OSDType.Integer; } }
public OSDInteger(int value)
{
this.value = value;
}
public override bool AsBoolean() { return value != 0; }
public override int AsInteger() { return value; }
public override uint AsUInteger() { return (uint)value; }
public override long AsLong() { return value; }
public override ulong AsULong() { return (ulong)value; }
public override double AsReal() { return (double)value; }
public override string AsString() { return value.ToString(); }
public override byte[] AsBinary() { return Utils.IntToBytesBig(value); }
public override OSD Copy() { return new OSDInteger(value); }
public override string ToString() { return AsString(); }
}
///
///
///
public sealed class OSDReal : OSD
{
private double value;
public override OSDType Type { get { return OSDType.Real; } }
public OSDReal(double value)
{
this.value = value;
}
public override bool AsBoolean() { return (!Double.IsNaN(value) && value != 0d); }
public override OSD Copy() { return new OSDReal(value); }
public override int AsInteger()
{
if (Double.IsNaN(value))
return 0;
if (value > (double)Int32.MaxValue)
return Int32.MaxValue;
if (value < (double)Int32.MinValue)
return Int32.MinValue;
return (int)Math.Round(value);
}
public override uint AsUInteger()
{
if (Double.IsNaN(value))
return 0;
if (value > (double)UInt32.MaxValue)
return UInt32.MaxValue;
if (value < (double)UInt32.MinValue)
return UInt32.MinValue;
return (uint)Math.Round(value);
}
public override long AsLong()
{
if (Double.IsNaN(value))
return 0;
if (value > (double)Int64.MaxValue)
return Int64.MaxValue;
if (value < (double)Int64.MinValue)
return Int64.MinValue;
return (long)Math.Round(value);
}
public override ulong AsULong()
{
if (Double.IsNaN(value))
return 0;
if (value > (double)UInt64.MaxValue)
return Int32.MaxValue;
if (value < (double)UInt64.MinValue)
return UInt64.MinValue;
return (ulong)Math.Round(value);
}
public override double AsReal() { return value; }
// "r" ensures the value will correctly round-trip back through Double.TryParse
public override string AsString() { return value.ToString("r", Utils.EnUsCulture); }
public override byte[] AsBinary() { return Utils.DoubleToBytesBig(value); }
public override string ToString() { return AsString(); }
}
///
///
///
public sealed class OSDString : OSD
{
private string value;
public override OSDType Type { get { return OSDType.String; } }
public override OSD Copy() { return new OSDString(value); }
public OSDString(string value)
{
// Refuse to hold null pointers
if (value != null)
this.value = value;
else
this.value = String.Empty;
}
public override bool AsBoolean()
{
if (String.IsNullOrEmpty(value))
return false;
if (value == "0" || value.ToLower() == "false")
return false;
return true;
}
public override int AsInteger()
{
double dbl;
if (Double.TryParse(value, out dbl))
return (int)Math.Floor(dbl);
else
return 0;
}
public override uint AsUInteger()
{
double dbl;
if (Double.TryParse(value, out dbl))
return (uint)Math.Floor(dbl);
else
return 0;
}
public override long AsLong()
{
double dbl;
if (Double.TryParse(value, out dbl))
return (long)Math.Floor(dbl);
else
return 0;
}
public override ulong AsULong()
{
double dbl;
if (Double.TryParse(value, out dbl))
return (ulong)Math.Floor(dbl);
else
return 0;
}
public override double AsReal()
{
double dbl;
if (Double.TryParse(value, out dbl))
return dbl;
else
return 0d;
}
public override string AsString() { return value; }
public override byte[] AsBinary() { return Encoding.UTF8.GetBytes(value); }
public override UUID AsUUID()
{
UUID uuid;
if (UUID.TryParse(value, out uuid))
return uuid;
else
return UUID.Zero;
}
public override DateTime AsDate()
{
DateTime dt;
if (DateTime.TryParse(value, out dt))
return dt;
else
return Utils.Epoch;
}
public override Uri AsUri()
{
Uri uri;
if (Uri.TryCreate(value, UriKind.RelativeOrAbsolute, out uri))
return uri;
else
return null;
}
public override string ToString() { return AsString(); }
}
///
///
///
public sealed class OSDUUID : OSD
{
private UUID value;
public override OSDType Type { get { return OSDType.UUID; } }
public OSDUUID(UUID value)
{
this.value = value;
}
public override OSD Copy() { return new OSDUUID(value); }
public override bool AsBoolean() { return (value == UUID.Zero) ? false : true; }
public override string AsString() { return value.ToString(); }
public override UUID AsUUID() { return value; }
public override byte[] AsBinary() { return value.GetBytes(); }
public override string ToString() { return AsString(); }
}
///
///
///
public sealed class OSDDate : OSD
{
private DateTime value;
public override OSDType Type { get { return OSDType.Date; } }
public OSDDate(DateTime value)
{
this.value = value;
}
public override string AsString()
{
string format;
if (value.Millisecond > 0)
format = "yyyy-MM-ddTHH:mm:ss.ffZ";
else
format = "yyyy-MM-ddTHH:mm:ssZ";
return value.ToUniversalTime().ToString(format);
}
public override int AsInteger()
{
return (int)Utils.DateTimeToUnixTime(value);
}
public override uint AsUInteger()
{
return Utils.DateTimeToUnixTime(value);
}
public override long AsLong()
{
return (long)Utils.DateTimeToUnixTime(value);
}
public override ulong AsULong()
{
return Utils.DateTimeToUnixTime(value);
}
public override byte[] AsBinary()
{
TimeSpan ts = value.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
return Utils.DoubleToBytes(ts.TotalSeconds);
}
public override OSD Copy() { return new OSDDate(value); }
public override DateTime AsDate() { return value; }
public override string ToString() { return AsString(); }
}
///
///
///
public sealed class OSDUri : OSD
{
private Uri value;
public override OSDType Type { get { return OSDType.URI; } }
public OSDUri(Uri value)
{
this.value = value;
}
public override string AsString()
{
if (value != null)
{
if (value.IsAbsoluteUri)
return value.AbsoluteUri;
else
return value.ToString();
}
return string.Empty;
}
public override OSD Copy() { return new OSDUri(value); }
public override Uri AsUri() { return value; }
public override byte[] AsBinary() { return Encoding.UTF8.GetBytes(AsString()); }
public override string ToString() { return AsString(); }
}
///
///
///
public sealed class OSDBinary : OSD
{
private byte[] value;
public override OSDType Type { get { return OSDType.Binary; } }
public OSDBinary(byte[] value)
{
if (value != null)
this.value = value;
else
this.value = Utils.EmptyBytes;
}
public OSDBinary(uint value)
{
this.value = new byte[]
{
(byte)((value >> 24) % 256),
(byte)((value >> 16) % 256),
(byte)((value >> 8) % 256),
(byte)(value % 256)
};
}
public OSDBinary(long value)
{
this.value = new byte[]
{
(byte)((value >> 56) % 256),
(byte)((value >> 48) % 256),
(byte)((value >> 40) % 256),
(byte)((value >> 32) % 256),
(byte)((value >> 24) % 256),
(byte)((value >> 16) % 256),
(byte)((value >> 8) % 256),
(byte)(value % 256)
};
}
public OSDBinary(ulong value)
{
this.value = new byte[]
{
(byte)((value >> 56) % 256),
(byte)((value >> 48) % 256),
(byte)((value >> 40) % 256),
(byte)((value >> 32) % 256),
(byte)((value >> 24) % 256),
(byte)((value >> 16) % 256),
(byte)((value >> 8) % 256),
(byte)(value % 256)
};
}
public override OSD Copy() { return new OSDBinary(value); }
public override string AsString() { return Convert.ToBase64String(value); }
public override byte[] AsBinary() { return value; }
public override uint AsUInteger()
{
return (uint)(
(value[0] << 24) +
(value[1] << 16) +
(value[2] << 8) +
(value[3] << 0));
}
public override long AsLong()
{
return (long)(
((long)value[0] << 56) +
((long)value[1] << 48) +
((long)value[2] << 40) +
((long)value[3] << 32) +
((long)value[4] << 24) +
((long)value[5] << 16) +
((long)value[6] << 8) +
((long)value[7] << 0));
}
public override ulong AsULong()
{
return (ulong)(
((ulong)value[0] << 56) +
((ulong)value[1] << 48) +
((ulong)value[2] << 40) +
((ulong)value[3] << 32) +
((ulong)value[4] << 24) +
((ulong)value[5] << 16) +
((ulong)value[6] << 8) +
((ulong)value[7] << 0));
}
public override string ToString()
{
return Utils.BytesToHexString(value, null);
}
}
///
///
///
public sealed class OSDMap : OSD, IDictionary
{
private Dictionary value;
public override OSDType Type { get { return OSDType.Map; } }
public OSDMap()
{
value = new Dictionary();
}
public OSDMap(int capacity)
{
value = new Dictionary(capacity);
}
public OSDMap(Dictionary value)
{
if (value != null)
this.value = value;
else
this.value = new Dictionary();
}
public override bool AsBoolean() { return value.Count > 0; }
public override string ToString()
{
return OSDParser.SerializeJsonString(this, true);
}
public override OSD Copy()
{
return new OSDMap(new Dictionary(value));
}
#region IDictionary Implementation
public int Count { get { return value.Count; } }
public bool IsReadOnly { get { return false; } }
public ICollection Keys { get { return value.Keys; } }
public ICollection Values { get { return value.Values; } }
public OSD this[string key]
{
get
{
OSD llsd;
if (this.value.TryGetValue(key, out llsd))
return llsd;
else
return new OSD();
}
set { this.value[key] = value; }
}
public bool ContainsKey(string key)
{
return value.ContainsKey(key);
}
public void Add(string key, OSD llsd)
{
value.Add(key, llsd);
}
public void Add(KeyValuePair kvp)
{
value.Add(kvp.Key, kvp.Value);
}
public bool Remove(string key)
{
return value.Remove(key);
}
public bool TryGetValue(string key, out OSD llsd)
{
return value.TryGetValue(key, out llsd);
}
public void Clear()
{
value.Clear();
}
public bool Contains(KeyValuePair kvp)
{
// This is a bizarre function... we don't really implement it
// properly, hopefully no one wants to use it
return value.ContainsKey(kvp.Key);
}
public void CopyTo(KeyValuePair[] array, int index)
{
throw new NotImplementedException();
}
public bool Remove(KeyValuePair kvp)
{
return this.value.Remove(kvp.Key);
}
public System.Collections.IDictionaryEnumerator GetEnumerator()
{
return value.GetEnumerator();
}
IEnumerator> IEnumerable>.GetEnumerator()
{
return null;
}
IEnumerator IEnumerable.GetEnumerator()
{
return value.GetEnumerator();
}
#endregion IDictionary Implementation
}
///
///
///
public sealed class OSDArray : OSD, IList
{
private List value;
public override OSDType Type { get { return OSDType.Array; } }
public OSDArray()
{
value = new List();
}
public OSDArray(int capacity)
{
value = new List(capacity);
}
public OSDArray(List value)
{
if (value != null)
this.value = value;
else
this.value = new List();
}
public override byte[] AsBinary()
{
byte[] binary = new byte[value.Count];
for (int i = 0; i < value.Count; i++)
binary[i] = (byte)value[i].AsInteger();
return binary;
}
public override long AsLong()
{
OSDBinary binary = new OSDBinary(AsBinary());
return binary.AsLong();
}
public override ulong AsULong()
{
OSDBinary binary = new OSDBinary(AsBinary());
return binary.AsULong();
}
public override uint AsUInteger()
{
OSDBinary binary = new OSDBinary(AsBinary());
return binary.AsUInteger();
}
public override Vector2 AsVector2()
{
Vector2 vector = Vector2.Zero;
if (this.Count == 2)
{
vector.X = (float)this[0].AsReal();
vector.Y = (float)this[1].AsReal();
}
return vector;
}
public override Vector3 AsVector3()
{
Vector3 vector = Vector3.Zero;
if (this.Count == 3)
{
vector.X = (float)this[0].AsReal();
vector.Y = (float)this[1].AsReal();
vector.Z = (float)this[2].AsReal();
}
return vector;
}
public override Vector3d AsVector3d()
{
Vector3d vector = Vector3d.Zero;
if (this.Count == 3)
{
vector.X = this[0].AsReal();
vector.Y = this[1].AsReal();
vector.Z = this[2].AsReal();
}
return vector;
}
public override Vector4 AsVector4()
{
Vector4 vector = Vector4.Zero;
if (this.Count == 4)
{
vector.X = (float)this[0].AsReal();
vector.Y = (float)this[1].AsReal();
vector.Z = (float)this[2].AsReal();
vector.W = (float)this[3].AsReal();
}
return vector;
}
public override Quaternion AsQuaternion()
{
Quaternion quaternion = Quaternion.Identity;
if (this.Count == 4)
{
quaternion.X = (float)this[0].AsReal();
quaternion.Y = (float)this[1].AsReal();
quaternion.Z = (float)this[2].AsReal();
quaternion.W = (float)this[3].AsReal();
}
return quaternion;
}
public override Color4 AsColor4()
{
Color4 color = Color4.Black;
if (this.Count == 4)
{
color.R = (float)this[0].AsReal();
color.G = (float)this[1].AsReal();
color.B = (float)this[2].AsReal();
color.A = (float)this[3].AsReal();
}
return color;
}
public override OSD Copy()
{
return new OSDArray(new List(value));
}
public override bool AsBoolean() { return value.Count > 0; }
public override string ToString()
{
return OSDParser.SerializeJsonString(this, true);
}
#region IList Implementation
public int Count { get { return value.Count; } }
public bool IsReadOnly { get { return false; } }
public OSD this[int index]
{
get { return value[index]; }
set { this.value[index] = value; }
}
public int IndexOf(OSD llsd)
{
return value.IndexOf(llsd);
}
public void Insert(int index, OSD llsd)
{
value.Insert(index, llsd);
}
public void RemoveAt(int index)
{
value.RemoveAt(index);
}
public void Add(OSD llsd)
{
value.Add(llsd);
}
public void Clear()
{
value.Clear();
}
public bool Contains(OSD llsd)
{
return value.Contains(llsd);
}
public bool Contains(string element)
{
for (int i = 0; i < value.Count; i++)
{
if (value[i].Type == OSDType.String && value[i].AsString() == element)
return true;
}
return false;
}
public void CopyTo(OSD[] array, int index)
{
throw new NotImplementedException();
}
public bool Remove(OSD llsd)
{
return value.Remove(llsd);
}
IEnumerator IEnumerable.GetEnumerator()
{
return value.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return value.GetEnumerator();
}
#endregion IList Implementation
}
public partial class OSDParser
{
const string LLSD_BINARY_HEADER = " llsd/binary ?>";
const string LLSD_XML_HEADER = "";
const string LLSD_XML_ALT_HEADER = "";
public static OSD Deserialize(byte[] data)
{
string header = Encoding.ASCII.GetString(data, 0, data.Length >= 17 ? 17 : data.Length);
try
{
string uHeader = Encoding.UTF8.GetString(data, 0, data.Length >= 17 ? 17 : data.Length).TrimStart();
if (uHeader.StartsWith(LLSD_XML_HEADER, StringComparison.InvariantCultureIgnoreCase) ||
uHeader.StartsWith(LLSD_XML_ALT_HEADER, StringComparison.InvariantCultureIgnoreCase) ||
uHeader.StartsWith(LLSD_XML_ALT2_HEADER, StringComparison.InvariantCultureIgnoreCase))
{
return DeserializeLLSDXml(data);
}
}
catch { }
if (header.StartsWith(LLSD_BINARY_HEADER, StringComparison.InvariantCultureIgnoreCase))
{
return DeserializeLLSDBinary(data);
}
else if (header.StartsWith(LLSD_XML_HEADER, StringComparison.InvariantCultureIgnoreCase) ||
header.StartsWith(LLSD_XML_ALT_HEADER, StringComparison.InvariantCultureIgnoreCase) ||
header.StartsWith(LLSD_XML_ALT2_HEADER, StringComparison.InvariantCultureIgnoreCase))
{
return DeserializeLLSDXml(data);
}
else
{
return DeserializeJson(Encoding.UTF8.GetString(data));
}
}
public static OSD Deserialize(string data)
{
if (data.StartsWith(LLSD_BINARY_HEADER, StringComparison.InvariantCultureIgnoreCase))
{
return DeserializeLLSDBinary(Encoding.UTF8.GetBytes(data));
}
else if (data.StartsWith(LLSD_XML_HEADER, StringComparison.InvariantCultureIgnoreCase) ||
data.StartsWith(LLSD_XML_ALT_HEADER, StringComparison.InvariantCultureIgnoreCase) ||
data.StartsWith(LLSD_XML_ALT2_HEADER, StringComparison.InvariantCultureIgnoreCase))
{
return DeserializeLLSDXml(data);
}
else
{
return DeserializeJson(data);
}
}
public static OSD Deserialize(Stream stream)
{
if (stream.CanSeek)
{
byte[] headerData = new byte[14];
stream.Read(headerData, 0, 14);
stream.Seek(0, SeekOrigin.Begin);
string header = Encoding.ASCII.GetString(headerData);
if (header.StartsWith(LLSD_BINARY_HEADER))
return DeserializeLLSDBinary(stream);
else if (header.StartsWith(LLSD_XML_HEADER) || header.StartsWith(LLSD_XML_ALT_HEADER) || header.StartsWith(LLSD_XML_ALT2_HEADER))
return DeserializeLLSDXml(stream);
else
return DeserializeJson(stream);
}
else
{
throw new OSDException("Cannot deserialize structured data from unseekable streams");
}
}
}
}