#region Arthea License
/***********************************************************************
* Arthea MUD by R. Jennings (2007) http://arthea.googlecode.com/ *
* By using this code you comply with the Artistic and GPLv2 Licenses. *
***********************************************************************/
#endregion
using System;
using System.Reflection;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using Arthea.Connections.Players;
using Arthea.Creation;
using Arthea.Interfaces;
namespace Arthea
{
/// <summary>
/// Implements a flag
/// </summary>
public abstract class Flag : CustomEditType, IXmlSerializable, IEquatable<Flag>
{
#region [rgn] Fields (2)
private ulong bits;
#endregion [rgn]
#region [rgn] Constructors (4)
/// <summary>
/// Initializes a new instance of the <see cref="Flag"/> class.
/// </summary>
/// <param name="value">The value.</param>
public Flag(ulong value)
{
bits = value;
}
/// <summary>
/// Initializes a new instance of the <see cref="Flag"/> class.
/// </summary>
/// <param name="flag">The bit bits.</param>
public Flag(Flag flag)
{
bits = flag.bits;
}
/// <summary>
/// Initializes a new instance of the <see cref="Flag"/> class.
/// </summary>
/// <param name="value">The value.</param>
public Flag(string value)
{
Parse(value);
}
/// <summary>
/// Initializes a new instance of the <see cref="Flag"/> class.
/// </summary>
public Flag()
{
bits = 0;
}
#endregion [rgn]
#region [rgn] Properties (1)
/// <summary>
/// Gets or sets the bits.
/// </summary>
/// <value>The bits.</value>
public ulong Bits
{
get { return bits; }
set { bits = value; }
}
#endregion [rgn]
#region [rgn] Methods (13)
// [rgn] Public Methods (13)
/// <summary>
/// Equalses the specified flag.
/// </summary>
/// <param name="flag">The flag.</param>
/// <returns></returns>
public bool Equals(Flag flag)
{
if (flag == null) return false;
return bits == flag.bits;
}
/// <summary>
/// Determines whether the specified <see cref="T:System.Object"></see> is equal to the current <see cref="T:System.Object"></see>.
/// </summary>
/// <param name="obj">The <see cref="T:System.Object"></see> to compare with the current <see cref="T:System.Object"></see>.</param>
/// <returns>
/// true if the specified <see cref="T:System.Object"></see> is equal to the current <see cref="T:System.Object"></see>; otherwise, false.
/// </returns>
public override bool Equals(object obj)
{
if (ReferenceEquals(this, obj)) return true;
return Equals(obj as Flag);
}
/// <summary>
/// Return a comma delimited string of names for each bit
/// that is set.
/// </summary>
/// <returns>names of each set bit</returns>
public string GetBitNames()
{
if (Bits == 0)
return string.Empty;
StringBuilder buf = new StringBuilder();
foreach (FieldInfo field in GetType().GetFields())
{
if (field.FieldType != typeof (ulong))
continue;
if (Has((ulong) field.GetValue(this)))
{
buf.Append(",");
buf.Append(field.Name);
}
}
if (buf.Length > 0)
buf.Remove(0, 1);
return buf.ToString();
}
/// <summary>
/// Serves as a hash function for a particular type. <see cref="M:System.Object.GetHashCode"></see> is suitable for use in hashing algorithms and data structures like a hash table.
/// </summary>
/// <returns>
/// A hash code for the current <see cref="T:System.Object"></see>.
/// </returns>
public override int GetHashCode()
{
return (int) bits;
}
/// <summary>
/// Determines whether [has] [the specified mask].
/// </summary>
/// <param name="mask">The mask.</param>
/// <returns>
/// <c>true</c> if [has] [the specified mask]; otherwise, <c>false</c>.
/// </returns>
public bool Has(ulong mask)
{
return (bits & mask) != 0;
}
/// <summary>
/// Determines whether [has] [the specified flag].
/// </summary>
/// <param name="flag">The flag.</param>
/// <returns>
/// <c>true</c> if [has] [the specified flag]; otherwise, <c>false</c>.
/// </returns>
public bool Has(Flag flag)
{
return (bits & flag.bits) != 0;
}
/// <summary>
/// Converts a comma-delimited string into bit values
/// </summary>
/// <param name="value">the string with bit names</param>
public Flag Parse(string value)
{
if (string.IsNullOrEmpty(value))
return this;
string[] names = value.Split(',');
foreach (string name in names)
{
FieldInfo flag =
GetType().GetField(name, BindingFlags.Static | BindingFlags.IgnoreCase | BindingFlags.Public);
if (flag != null)
Set((ulong) flag.GetValue(this));
}
return this;
}
/// <summary>
/// Removes the specified mask.
/// </summary>
/// <param name="mask">The mask.</param>
public void Remove(ulong mask)
{
bits &= ~mask;
}
/// <summary>
/// Sets the specified mask.
/// </summary>
/// <param name="mask">The mask.</param>
public void Set(ulong mask)
{
bits |= mask;
}
/// <summary>
/// Sets the specified bit bits.
/// </summary>
/// <param name="flag">The bit bits.</param>
public void Set(Flag flag)
{
bits |= flag.bits;
}
/// <summary>
/// Toggles the specified mask.
/// </summary>
/// <param name="mask">The mask.</param>
public void Toggle(ulong mask)
{
bits ^= mask;
}
/// <summary>
/// Toggles the specified bit bits.
/// </summary>
/// <param name="flag">The bit bits.</param>
public void Toggle(Flag flag)
{
bits ^= flag.bits;
}
/// <summary>
/// Returns a <see cref="T:System.String"></see> that represents the current <see cref="T:System.Object"></see>.
/// </summary>
/// <returns>
/// A <see cref="T:System.String"></see> that represents the current <see cref="T:System.Object"></see>.
/// </returns>
public override string ToString()
{
return GetBitNames();
}
#endregion [rgn]
#region CustomEditType Members
/// <summary>
/// Allows custom editing of this type by player.
/// </summary>
/// <param name="player">The player.</param>
/// <param name="editor">The editor values.</param>
/// <param name="argument">The argument.</param>
public void CustomEdit(Player player, OlcField editor, String argument)
{
if (string.IsNullOrEmpty(argument))
{
player.WriteLine("Set {0} to what?", editor.Name);
return;
}
String[] names = argument.GetArgs();
FieldInfo flag = null;
foreach (String name in names)
{
flag = GetType().GetField(name, BindingFlags.Static | BindingFlags.IgnoreCase | BindingFlags.Public);
if (flag != null)
Toggle((ulong) flag.GetValue(this));
else
player.WriteLine("Could not find flag '{0}'.", name);
}
if (flag != null)
player.WriteLine("{0}: flag(s) toggled.", editor.Name);
}
#endregion
#region IXmlSerializable Members
///<summary>
///This property is reserved, apply the <see cref="T:System.Xml.Serialization.XmlSchemaProviderAttribute"></see> to the class instead.
///</summary>
///
///<returns>
///An <see cref="T:System.Xml.Schema.XmlSchema"></see> that describes the XML representation of the object that is produced by the <see cref="M:System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter)"></see> method and consumed by the <see cref="M:System.Xml.Serialization.IXmlSerializable.ReadXml(System.Xml.XmlReader)"></see> method.
///</returns>
///
public XmlSchema GetSchema()
{
return null;
}
///<summary>
///Generates an object from its XML representation.
///</summary>
///
///<param name="reader">The <see cref="T:System.Xml.XmlReader"></see> stream from which the object is deserialized. </param>
public void ReadXml(XmlReader reader)
{
if (reader.IsEmptyElement)
return;
Parse(reader.ReadElementString());
}
///<summary>
///Converts an object into its XML representation.
///</summary>
///
///<param name="writer">The <see cref="T:System.Xml.XmlWriter"></see> stream to which the object is serialized. </param>
public void WriteXml(XmlWriter writer)
{
if (Bits == 0)
return;
writer.WriteString(GetBitNames());
}
#region Operators
/// <summary>
/// Implements the operator !=.
/// </summary>
/// <param name="flag1">The flag1.</param>
/// <param name="flag2">The flag2.</param>
/// <returns>The result of the operator.</returns>
public static bool operator !=(Flag flag1, Flag flag2)
{
return !Equals(flag1, flag2);
}
/// <summary>
/// Implements the operator ==.
/// </summary>
/// <param name="flag1">The flag1.</param>
/// <param name="flag2">The flag2.</param>
/// <returns>The result of the operator.</returns>
public static bool operator ==(Flag flag1, Flag flag2)
{
return Equals(flag1, flag2);
}
#endregion
#endregion
}
}