#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 } }