git-svn-id: http://libopenmetaverse.googlecode.com/svn/trunk@1998 52acb1d6-8a22-11de-b505-999d5b087335
637 lines
20 KiB
C#
637 lines
20 KiB
C#
/*
|
|
* Copyright (c) 2007-2008, 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.Text;
|
|
|
|
namespace OpenMetaverse.StructuredData
|
|
{
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
public enum LLSDType
|
|
{
|
|
/// <summary></summary>
|
|
Unknown,
|
|
/// <summary></summary>
|
|
Boolean,
|
|
/// <summary></summary>
|
|
Integer,
|
|
/// <summary></summary>
|
|
Real,
|
|
/// <summary></summary>
|
|
String,
|
|
/// <summary></summary>
|
|
UUID,
|
|
/// <summary></summary>
|
|
Date,
|
|
/// <summary></summary>
|
|
URI,
|
|
/// <summary></summary>
|
|
Binary,
|
|
/// <summary></summary>
|
|
Map,
|
|
/// <summary></summary>
|
|
Array
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
public class LLSDException : Exception
|
|
{
|
|
public LLSDException(string message) : base(message) { }
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
public partial class LLSD
|
|
{
|
|
public virtual LLSDType Type { get { return LLSDType.Unknown; } }
|
|
|
|
public virtual bool AsBoolean() { return false; }
|
|
public virtual int AsInteger() { 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 Helpers.Epoch; }
|
|
public virtual Uri AsUri() { return new Uri(String.Empty); }
|
|
public virtual byte[] AsBinary() { return new byte[0]; }
|
|
public override string ToString() { return "undef"; }
|
|
|
|
public static LLSD FromBoolean(bool value) { return new LLSDBoolean(value); }
|
|
public static LLSD FromInteger(int value) { return new LLSDInteger(value); }
|
|
public static LLSD FromInteger(uint value) { return new LLSDInteger((int)value); }
|
|
public static LLSD FromInteger(short value) { return new LLSDInteger((int)value); }
|
|
public static LLSD FromInteger(ushort value) { return new LLSDInteger((int)value); }
|
|
public static LLSD FromInteger(sbyte value) { return new LLSDInteger((int)value); }
|
|
public static LLSD FromInteger(byte value) { return new LLSDInteger((int)value); }
|
|
public static LLSD FromReal(double value) { return new LLSDReal(value); }
|
|
public static LLSD FromReal(float value) { return new LLSDReal((double)value); }
|
|
public static LLSD FromString(string value) { return new LLSDString(value); }
|
|
public static LLSD FromUUID(UUID value) { return new LLSDUUID(value); }
|
|
public static LLSD FromDate(DateTime value) { return new LLSDDate(value); }
|
|
public static LLSD FromUri(Uri value) { return new LLSDURI(value); }
|
|
public static LLSD FromBinary(byte[] value) { return new LLSDBinary(value); }
|
|
public static LLSD FromBinary(long value) { return new LLSDBinary(value); }
|
|
public static LLSD FromBinary(ulong value) { return new LLSDBinary(value); }
|
|
public static LLSD FromObject(object value)
|
|
{
|
|
if (value == null) { return new LLSD(); }
|
|
else if (value is bool) { return new LLSDBoolean((bool)value); }
|
|
else if (value is int) { return new LLSDInteger((int)value); }
|
|
else if (value is uint) { return new LLSDInteger((int)(uint)value); }
|
|
else if (value is short) { return new LLSDInteger((int)(short)value); }
|
|
else if (value is ushort) { return new LLSDInteger((int)(ushort)value); }
|
|
else if (value is sbyte) { return new LLSDInteger((int)(sbyte)value); }
|
|
else if (value is byte) { return new LLSDInteger((int)(byte)value); }
|
|
else if (value is double) { return new LLSDReal((double)value); }
|
|
else if (value is float) { return new LLSDReal((double)(float)value); }
|
|
else if (value is string) { return new LLSDString((string)value); }
|
|
else if (value is UUID) { return new LLSDUUID((UUID)value); }
|
|
else if (value is DateTime) { return new LLSDDate((DateTime)value); }
|
|
else if (value is Uri) { return new LLSDURI((Uri)value); }
|
|
else if (value is byte[]) { return new LLSDBinary((byte[])value); }
|
|
else if (value is long) { return new LLSDBinary((long)value); }
|
|
else if (value is ulong) { return new LLSDBinary((ulong)value); }
|
|
else return new LLSD();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
public class LLSDBoolean : LLSD
|
|
{
|
|
private bool value;
|
|
|
|
private static byte[] trueBinary = { 0x31 };
|
|
private static byte[] falseBinary = { 0x30 };
|
|
|
|
public override LLSDType Type { get { return LLSDType.Boolean; } }
|
|
|
|
public LLSDBoolean(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 string ToString() { return AsString(); }
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
public class LLSDInteger : LLSD
|
|
{
|
|
private int value;
|
|
|
|
public override LLSDType Type { get { return LLSDType.Integer; } }
|
|
|
|
public LLSDInteger(int value)
|
|
{
|
|
this.value = value;
|
|
}
|
|
|
|
public override bool AsBoolean() { return value != 0; }
|
|
public override int AsInteger() { return value; }
|
|
public override double AsReal() { return (double)value; }
|
|
|
|
public override string AsString() { return value.ToString(); }
|
|
|
|
public override byte[] AsBinary() {
|
|
int bigEndInt = System.Net.IPAddress.HostToNetworkOrder( value );
|
|
byte[] binary = BitConverter.GetBytes(bigEndInt);
|
|
return binary;
|
|
}
|
|
|
|
public override string ToString() { return AsString(); }
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
public class LLSDReal : LLSD
|
|
{
|
|
private double value;
|
|
|
|
public override LLSDType Type { get { return LLSDType.Real; } }
|
|
|
|
public LLSDReal(double value)
|
|
{
|
|
this.value = value;
|
|
}
|
|
|
|
public override bool AsBoolean() { return (!Double.IsNaN(value) && value != 0d); }
|
|
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 double AsReal() { return value; }
|
|
public override string AsString() { return value.ToString(Helpers.EnUsCulture); }
|
|
|
|
public override byte[] AsBinary() {
|
|
byte[] bytesHostEnd = BitConverter.GetBytes( value );
|
|
long longHostEnd = BitConverter.ToInt64( bytesHostEnd, 0 );
|
|
long longNetEnd = System.Net.IPAddress.HostToNetworkOrder( longHostEnd );
|
|
byte[] bytesNetEnd = BitConverter.GetBytes( longNetEnd );
|
|
return bytesNetEnd;
|
|
}
|
|
public override string ToString() { return AsString(); }
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
public class LLSDString : LLSD
|
|
{
|
|
private string value;
|
|
|
|
public override LLSDType Type { get { return LLSDType.String; } }
|
|
|
|
public LLSDString(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 (Helpers.TryParse(value, out dbl))
|
|
return (int)Math.Floor( dbl );
|
|
else
|
|
return 0;
|
|
}
|
|
public override double AsReal()
|
|
{
|
|
double dbl;
|
|
if (Helpers.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 Helpers.Epoch;
|
|
}
|
|
public override Uri AsUri() { return new Uri(value); }
|
|
|
|
public override string ToString() { return AsString(); }
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
public class LLSDUUID : LLSD
|
|
{
|
|
private UUID value;
|
|
|
|
public override LLSDType Type { get { return LLSDType.UUID; } }
|
|
|
|
public LLSDUUID(UUID value)
|
|
{
|
|
this.value = 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(); }
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
public class LLSDDate : LLSD
|
|
{
|
|
private DateTime value;
|
|
|
|
public override LLSDType Type { get { return LLSDType.Date; } }
|
|
|
|
public LLSDDate(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 byte[] AsBinary() {
|
|
TimeSpan ts = value.ToUniversalTime() - new DateTime( 1970, 1, 1, 0, 0, 0, DateTimeKind.Utc );
|
|
double timestamp = (double)ts.TotalSeconds;
|
|
byte[] bytesHostEnd = BitConverter.GetBytes( timestamp );
|
|
long longHostEnd = BitConverter.ToInt64( bytesHostEnd, 0 );
|
|
long longNetEnd = System.Net.IPAddress.HostToNetworkOrder( longHostEnd );
|
|
byte[] bytesNetEnd = BitConverter.GetBytes( longNetEnd );
|
|
return bytesNetEnd;
|
|
}
|
|
|
|
public override DateTime AsDate() { return value; }
|
|
public override string ToString() { return AsString(); }
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
public class LLSDURI : LLSD
|
|
{
|
|
private Uri value;
|
|
|
|
public override LLSDType Type { get { return LLSDType.URI; } }
|
|
|
|
public LLSDURI(Uri value)
|
|
{
|
|
this.value = value;
|
|
}
|
|
|
|
public override string AsString() { return value.ToString(); }
|
|
public override Uri AsUri() { return value; }
|
|
public override byte[] AsBinary() { return Encoding.UTF8.GetBytes(value.ToString()); }
|
|
public override string ToString() { return AsString(); }
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
public class LLSDBinary : LLSD
|
|
{
|
|
private byte[] value;
|
|
|
|
public override LLSDType Type { get { return LLSDType.Binary; } }
|
|
|
|
public LLSDBinary(byte[] value)
|
|
{
|
|
if (value != null)
|
|
this.value = value;
|
|
else
|
|
this.value = new byte[0];
|
|
}
|
|
|
|
public LLSDBinary(long value)
|
|
{
|
|
this.value = BitConverter.GetBytes(value);
|
|
}
|
|
|
|
public LLSDBinary(ulong value)
|
|
{
|
|
this.value = BitConverter.GetBytes(value);
|
|
}
|
|
|
|
public override string AsString() { return Convert.ToBase64String(value); }
|
|
public override byte[] AsBinary() { return value; }
|
|
|
|
public override string ToString()
|
|
{
|
|
// TODO: ToString() is only meant for friendly display, a hex string would
|
|
// be more friendly then a base64 string
|
|
return AsString();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
public class LLSDMap : LLSD, IDictionary<string, LLSD>
|
|
{
|
|
private Dictionary<string, LLSD> value;
|
|
|
|
public override LLSDType Type { get { return LLSDType.Map; } }
|
|
|
|
public LLSDMap()
|
|
{
|
|
value = new Dictionary<string, LLSD>();
|
|
}
|
|
|
|
public LLSDMap(int capacity)
|
|
{
|
|
value = new Dictionary<string, LLSD>(capacity);
|
|
}
|
|
|
|
public LLSDMap(Dictionary<string, LLSD> value)
|
|
{
|
|
if (value != null)
|
|
this.value = value;
|
|
else
|
|
this.value = new Dictionary<string, LLSD>();
|
|
}
|
|
|
|
public override bool AsBoolean() { return value.Count > 0; }
|
|
|
|
public override string ToString()
|
|
{
|
|
return LLSDParser.SerializeNotationFormatted(this);
|
|
}
|
|
|
|
#region IDictionary Implementation
|
|
|
|
public int Count { get { return value.Count; } }
|
|
public bool IsReadOnly { get { return false; } }
|
|
public ICollection<string> Keys { get { return value.Keys; } }
|
|
public ICollection<LLSD> Values { get { return value.Values; } }
|
|
public LLSD this[string key]
|
|
{
|
|
get
|
|
{
|
|
LLSD llsd;
|
|
if (this.value.TryGetValue(key, out llsd))
|
|
return llsd;
|
|
else
|
|
return new LLSD();
|
|
}
|
|
set { this.value[key] = value; }
|
|
}
|
|
|
|
public bool ContainsKey(string key)
|
|
{
|
|
return value.ContainsKey(key);
|
|
}
|
|
|
|
public void Add(string key, LLSD llsd)
|
|
{
|
|
value.Add(key, llsd);
|
|
}
|
|
|
|
public void Add(KeyValuePair<string, LLSD> kvp)
|
|
{
|
|
value.Add(kvp.Key, kvp.Value);
|
|
}
|
|
|
|
public bool Remove(string key)
|
|
{
|
|
return value.Remove(key);
|
|
}
|
|
|
|
public bool TryGetValue(string key, out LLSD llsd)
|
|
{
|
|
return value.TryGetValue(key, out llsd);
|
|
}
|
|
|
|
public void Clear()
|
|
{
|
|
value.Clear();
|
|
}
|
|
|
|
public bool Contains(KeyValuePair<string, LLSD> 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<string, LLSD>[] array, int index)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public bool Remove(KeyValuePair<string, LLSD> kvp)
|
|
{
|
|
return this.value.Remove(kvp.Key);
|
|
}
|
|
|
|
public System.Collections.IDictionaryEnumerator GetEnumerator()
|
|
{
|
|
return value.GetEnumerator();
|
|
}
|
|
|
|
IEnumerator<KeyValuePair<string, LLSD>> IEnumerable<KeyValuePair<string, LLSD>>.GetEnumerator()
|
|
{
|
|
return null;
|
|
}
|
|
|
|
IEnumerator IEnumerable.GetEnumerator()
|
|
{
|
|
return value.GetEnumerator();
|
|
}
|
|
|
|
#endregion IDictionary Implementation
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
public class LLSDArray : LLSD, IList<LLSD>
|
|
{
|
|
private List<LLSD> value;
|
|
|
|
public override LLSDType Type { get { return LLSDType.Array; } }
|
|
|
|
public LLSDArray()
|
|
{
|
|
value = new List<LLSD>();
|
|
}
|
|
|
|
public LLSDArray(int capacity)
|
|
{
|
|
value = new List<LLSD>(capacity);
|
|
}
|
|
|
|
public LLSDArray(List<LLSD> value)
|
|
{
|
|
if (value != null)
|
|
this.value = value;
|
|
else
|
|
this.value = new List<LLSD>();
|
|
}
|
|
|
|
public override bool AsBoolean() { return value.Count > 0; }
|
|
|
|
public override string ToString()
|
|
{
|
|
return LLSDParser.SerializeNotationFormatted(this);
|
|
}
|
|
|
|
#region IList Implementation
|
|
|
|
public int Count { get { return value.Count; } }
|
|
public bool IsReadOnly { get { return false; } }
|
|
public LLSD this[int index]
|
|
{
|
|
get { return value[index]; }
|
|
set { this.value[index] = value; }
|
|
}
|
|
|
|
public int IndexOf(LLSD llsd)
|
|
{
|
|
return value.IndexOf(llsd);
|
|
}
|
|
|
|
public void Insert(int index, LLSD llsd)
|
|
{
|
|
value.Insert(index, llsd);
|
|
}
|
|
|
|
public void RemoveAt(int index)
|
|
{
|
|
value.RemoveAt(index);
|
|
}
|
|
|
|
public void Add(LLSD llsd)
|
|
{
|
|
value.Add(llsd);
|
|
}
|
|
|
|
public void Add(string str)
|
|
{
|
|
// This is so common that we throw a little helper in here
|
|
value.Add(LLSD.FromString(str));
|
|
}
|
|
|
|
public void Clear()
|
|
{
|
|
value.Clear();
|
|
}
|
|
|
|
public bool Contains(LLSD llsd)
|
|
{
|
|
return value.Contains(llsd);
|
|
}
|
|
|
|
public bool Contains(string element)
|
|
{
|
|
for (int i = 0; i < value.Count; i++)
|
|
{
|
|
if (value[i].Type == LLSDType.String && value[i].AsString() == element)
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public void CopyTo(LLSD[] array, int index)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public bool Remove(LLSD llsd)
|
|
{
|
|
return value.Remove(llsd);
|
|
}
|
|
|
|
IEnumerator IEnumerable.GetEnumerator()
|
|
{
|
|
return value.GetEnumerator();
|
|
}
|
|
|
|
IEnumerator<LLSD> IEnumerable<LLSD>.GetEnumerator()
|
|
{
|
|
return value.GetEnumerator();
|
|
}
|
|
|
|
#endregion IList Implementation
|
|
}
|
|
}
|