如何在c#中的二进制整数前面追加“1”位

问题描述 投票:0回答:1

目前,我正在尝试找出一种方法,将“1”位附加到二进制 32 位整数的前面,但仅限于活动位的前面。例如,“101”将变成“1101”,000 000 将变成“1 000 000”。每个二进制整数本质上都会变成三元组。

我想这样做的原因是用莫顿编码实现哈希八叉树。我主要尝试在这里关注这篇文章:https://geidav.wordpress.com/2014/08/18/advanced-octrees-2-node-representations/

在本文中,它提到在 Morton 代码及其子代码的前面添加标志“1”位,以便将其位置代码与其他位置代码区分开来。

我当前的代码是这样的:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Collections;

using static Unity.Mathematics.math;

using Unity.Mathematics;

public struct Octree 
{
    NativeHashMap<int, OctreeNode> octreeNodes;

    OctreeNode GetParentNode(OctreeNode node)
    {
        int locCodeParent = node.LocCode >> 3;
        return LookupNode(locCodeParent);
    }

    OctreeNode LookupNode(int LocCode)
    {
        OctreeNode node;

        if(!octreeNodes.TryGetValue(LocCode, out node))
        {
            Debug.Log("You done oofed dude, the octree node could not be found with the LocCode provided, please try again or stay oofed");
        }

        return node;
    }

    int GetNodeTreeDepth(OctreeNode node)         
    {
        return (int)log2(node.LocCode)/3;
    }
}

public struct OctreeNode
{
    public int LocCode;
}
c# bit-manipulation
1个回答
0
投票

下面的

LongFlags
类将维护一组(64 位)
ulong
位标志,作为抽象。您可以查询已设置的位,包括查询设置的最高位。

您的代码未显示具体信息;但你似乎希望能够在另一个已经设置位之前添加一点:

“101”会变成“1101”

还有一个未设置的位:

000 000 会变成“1 000 000”

也许您会跟踪最高“当前”位的

int
值;然后使用此类设置下一位...您可以设置和清除任何单独的位。

例如,您可以将下面的

LongFlags
包装在这样的助手中:

    /// <summary>
    /// Helper for bit flags, that tracks a <see cref="CurrentBit"/>.
    /// The <see cref="BitLimit"/> is limited to sixty-four.
    /// Bit positions are numbered from one to sixty-four,
    /// right-to-left (lsb is one, msb is 64).
    /// </summary>
    [DataContract]
    public class BitHelper
    {
        [DataMember]
        private LongFlags longFlags = new LongFlags();


        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="bitLimit">Required: sets <see cref="BitLimit"/>.</param>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public BitHelper(int bitLimit)
        {
            if ((bitLimit < 1)
                    || (bitLimit > 64))
                throw new ArgumentOutOfRangeException(nameof(bitLimit), bitLimit, @"[1, 64]");
            BitLimit = bitLimit;
        }


        /// <summary>
        /// Limits the highest bit that can be set. [1, 64].
        /// (Bit positions are numbered from one to a maximum of sixty-four,
        /// right-to-left (lsb is one, msb is 64).)
        /// </summary>
        [DataMember]
        public int BitLimit { get; private set; }

        /// <summary>
        /// Identifies the current working bit position.
        /// Defaults to one. Ranges: [1, BitLimit].
        /// (Bit positions are numbered from one to a maximum of sixty-four,
        /// right-to-left (lsb is one, msb is 64).)
        /// </summary>
        [DataMember]
        public int CurrentBit { get; private set; } = 1;


        /// <summary>
        /// Returns the state of the <see cref="CurrentBit"/>.
        /// </summary>
        /// <returns>True if one, false if zero.</returns>
        public bool IsCurrentBitSet
            => longFlags[CurrentBit];

        /// <summary>
        /// Increments the <see cref="CurrentBit"/>,
        /// making no changes to bit values.
        /// </summary>
        /// <returns>This object for chaining.</returns>
        /// <exception cref="InvalidOperationException">If the <see cref="CurrentBit"/>
        /// is already at the <see cref="BitLimit"/>.</exception>
        public BitHelper IncrementCurrentBit()
        {
            if (CurrentBit >= BitLimit)
                throw new InvalidOperationException(BitLimit.ToString());
            ++CurrentBit;
            return this;
        }

        /// <summary>
        /// Sets the <see cref="CurrentBit"/> to one.
        /// </summary>
        /// <returns>This object for chaining.</returns>
        public BitHelper SetCurrentBit()
        {
            longFlags.Set(CurrentBit);
            return this;
        }

        /// <summary>
        /// Sets the <see cref="CurrentBit"/> to zero.
        /// </summary>
        /// <returns>This object for chaining.</returns>
        public BitHelper ClearCurrentBit()
        {
            longFlags.Clear(CurrentBit);
            return this;
        }

        /// <summary>
        /// Inverts the value of the <see cref="CurrentBit"/>.
        /// </summary>
        /// <returns>This object for chaining.</returns>
        public BitHelper InvertCurrentBit()
        {
            longFlags[CurrentBit] = !longFlags[CurrentBit];
            return this;
        }


        /// <summary>
        /// Returns the position of the highest bit that is set:
        /// [0, BitLimit]. Returns zero if no bits are set.
        /// </summary>
        public int HighestSetBit
            => longFlags.HighestFlag;


        /// <summary>
        /// Returns all 64 bits as a ULong.
        /// </summary>
        /// <returns>All 64 bits, unsigned.</returns>
        public ulong ToULong()
            => longFlags.Flags;

        /// <summary>
        /// Returns all 64 bits as a Long.
        /// </summary>
        /// <returns>All 64 bits, signed.</returns>
        public long ToLong()
            => (long)longFlags.Flags;

        /// <summary>
        /// Returns the lower 32 bits as a UInt
        /// --- REGARDLESS of the setting of <see cref="BitLimit"/>.
        /// </summary>
        /// <returns>The lower 32 bits, unsigned.</returns>
        public uint ToUInt()
            => (uint)longFlags.Flags;

        /// <summary>
        /// Returns the lower 32 bits as an Int
        /// --- REGARDLESS of the setting of <see cref="BitLimit"/>.
        /// </summary>
        /// <returns>The lower 32 bits, signed.</returns>
        public int ToInt()
            => (int)longFlags.Flags;

        /// <summary>
        /// Returns the lower 16 bits as a UShort
        /// --- REGARDLESS of the setting of <see cref="BitLimit"/>.
        /// </summary>
        /// <returns>The lower 16 bits, unsigned.</returns>
        public ushort ToUShort()
            => (ushort)longFlags.Flags;

        /// <summary>
        /// Returns the lower 16 bits as a short
        /// --- REGARDLESS of the setting of <see cref="BitLimit"/>.
        /// </summary>
        /// <returns>The lower 16 bits, signed.</returns>
        public short ToShort()
            => (short)longFlags.Flags;

        /// <summary>
        /// Returns the lower 8 bits as a Byte
        /// --- REGARDLESS of the setting of <see cref="BitLimit"/>.
        /// </summary>
        /// <returns>The lower 8 bits, unsigned.</returns>
        public byte ToByte()
            => (byte)longFlags.Flags;

        /// <summary>
        /// Returns the lower 8 bits as an SByte
        /// --- REGARDLESS of the setting of <see cref="BitLimit"/>.
        /// </summary>
        /// <returns>The lower 8 bits, signed.</returns>
        public sbyte ToSByte()
            => (sbyte)longFlags.Flags;
    }

这是

LongFlags

using System;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;


namespace Sc.Util.System
{
    /// <summary>
    /// A class holding <see langword="ulong"/> bit <see cref="Flags"/>.
    /// Flags are numbered from one to sixty-four, from right-to-left in the
    /// <see langword="ulong"/> value --- but the abstraction allows you to
    /// ignore that as an implementation detail. This class implements
    /// methods to set and clear flags, and set and clear flags from other
    /// instances. This also implements implicit conversions to and from
    /// <see langword="ulong"/> --- and therefore you may invoke methods with
    /// <see langword="ulong"/> values. This is also
    /// <see cref="IXmlSerializable"/> and <see cref="ICloneable"/>.
    /// </summary>
    [Serializable]
    public sealed class LongFlags
            : ICloneable,
                    IXmlSerializable
    {
        /// <summary>
        /// Counts the bits that are set on the argument.
        /// </summary>
        /// <param name="flags">Arbitrary.</param>
        /// <returns>A count of bits that are set.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static int CountBits(ulong flags)
        {
            int result = 0;
            for (int i = 0; i < 64; ++i) {
                if ((flags & 1) == 1)
                    ++result;
                flags >>= 1;
            }
            return result;
        }


        /// <summary>
        /// Returns the <see langword="ulong"/> VALUE of the SINGLE
        /// highest bit that is set on the argument.
        /// </summary>
        /// <param name="flags">Arbitrary.</param>
        /// <returns>The value of the single highest bit that is set.
        /// Returns zero if no bits are set.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static ulong GetHighestBitValue(ulong flags)
        {
            int highestBit = LongFlags.GetHighestBitPosition(flags);
            return highestBit == 0
                    ? 0UL
                    : 1UL << (highestBit - 1);
        }

        /// <summary>
        /// Returns the <see langword="ulong"/> VALUE of the SINGLE
        /// lowest bit that is set on the argument.
        /// </summary>
        /// <param name="flags">Arbitrary.</param>
        /// <returns>The value of the single lowest bit that is set.
        /// Returns zero if no bits are set.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static ulong GetLowestBitValue(ulong flags)
        {
            int lowestBit = LongFlags.GetLowestBitPosition(flags);
            return lowestBit == 0
                    ? 0UL
                    : 1UL << (lowestBit - 1);
        }


        /// <summary>
        /// Returns the position of highest bit that is set on the argument:
        /// where the right-most bit is position one; and the left-most is sixty-four.
        /// </summary>
        /// <param name="flags">Arbitrary.</param>
        /// <returns>The position of the highest bit that is set.
        /// Returns zero if no bits are set.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static int GetHighestBitPosition(ulong flags)
        {
            if (flags == 0UL)
                return 0;
            for (int i = 63; i >= 0; --i) {
                if (((flags >> i) & 1) == 1)
                    return i + 1;
            }
            Debug.Fail($"Value is '{flags}' but iteration failed to find a set bit.");
            return 0;
        }

        /// <summary>
        /// Returns the position of lowest bit that is set on the argument:
        /// where the right-most bit is position one; and the left-most is sixty-four.
        /// </summary>
        /// <param name="flags">Arbitrary.</param>
        /// <returns>The position of the lowest bit that is set.
        /// Returns zero if no bits are set.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static int GetLowestBitPosition(ulong flags)
        {
            if (flags == 0UL)
                return 0;
            for (int i = 0; i < 64; ++i) {
                if (((flags >> i) & 1) == 1)
                    return i + 1;
            }
            Debug.Fail($"Value is '{flags}' but iteration failed to find a set bit.");
            return 0;
        }

        /// <summary>
        /// Returns a new value from the <paramref name="flags"/>
        /// with the <paramref name="predicate"/> removed.
        /// </summary>
        /// <param name="flags">Arbitrary.</param>
        /// <param name="predicate">Arbitrary.</param>
        /// <returns>Returns <paramref name="flags"/> <c>&</c> the
        /// complement of the <paramref name="predicate"/>.</returns>
        public static ulong Excluding(ulong flags, ulong predicate)
            => flags & ~predicate;


        /// <summary>
        /// Returns true if the <paramref name="source"/> has ANY of the bits that
        /// are set on the <paramref name="flags"/>. Notice that if the
        /// <paramref name="flags"/> are zero, this will return false.
        /// </summary>
        /// <param name="source">The source flags.
        /// If zero, this will return false.</param>
        /// <param name="flags">Arbitrary bits to search for.
        /// If zero, this will return false.</param>
        /// <returns>True if ANY <The name="flags"/> are present on the
        /// <paramref name="source"/> (and at least one flags bit is set).</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool HasAnyBits(ulong source, ulong flags)
            => (source & flags) != 0UL;

        /// <summary>
        /// Returns true if the <paramref name="source"/> has ALL of the bits that
        /// are set on the <paramref name="flags"/>. Notice that if the
        /// <paramref name="flags"/> are zero, this will return false.
        /// </summary>
        /// <param name="source">The source flags.
        /// If zero, this will return false.</param>
        /// <param name="flags">Arbitrary bits to search for.
        /// If zero, this will return false.</param>
        /// <returns>True if ALL <The name="flags"/> are present on the
        /// <paramref name="source"/> (and at least one flags bit is set).</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool HasAllBits(ulong source, ulong flags)
            => (flags != 0UL) && ((source & flags) == flags);

        /// <summary>
        /// Returns true if the <paramref name="source"/> has ONLY bits that are set
        /// on the <paramref name="flags"/> --- false if any bit is set on the source
        /// that is not defined on the flags. Notice that if the
        /// <paramref name="flags"/> are zero, this will return false.
        /// </summary>
        /// <param name="source">The source flags.
        /// If zero, this will return false.</param>
        /// <param name="flags">Arbitrary bits to search for.
        /// If zero, this will return false.</param>
        /// <param name="requiresAll">If true, then <paramref name="source"/>
        /// MUST contain ALL <paramref name="flags"/> AND NO other bits.
        /// If false, the source may contain zero or more bits
        /// present on the flags --- and no bits that are not present on the flags
        /// (source need not contain all, but can only contain a bit on the flags).</param>
        /// <returns>True if only the flags are present on the source --- false if any bit is
        /// set on th source that is not defined on the flags.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool HasOnlyBits(ulong source, ulong flags, bool requiresAll)
            => (flags != 0UL)
                    && (source != 0UL)
                    && ((source & ~flags) == 0UL)
                    && (!requiresAll
                    || ((source & flags) == flags));

        /// <summary>
        /// Returns true if the <paramref name="source"/> has NONE of the
        /// bits that are set on <paramref name="flags"/>. Notice that if the
        /// <paramref name="flags"/> are zero, this will return TRUE.
        /// </summary>
        /// <param name="source">The source flags.
        /// If zero, this will return true.</param>
        /// <param name="flags">Arbitrary flags to search for.
        /// If zero, this will return true.</param>
        /// <returns>True if no flags bits are set here.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool HasNoBits(ulong source, ulong flags)
            => (source & flags) == 0UL;


        /// <summary>
        /// Checks the range.
        /// </summary>
        /// <param name="position">[1,64].</param>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private static void rangeCheckPosition(int position)
        {
            if ((position <= 0)
                    || (position > 64))
                throw new ArgumentOutOfRangeException(nameof(position), position, @"[1,64]");
        }


        /// <summary>
        /// Default constructor creates an empty instance.
        /// </summary>
        public LongFlags() { }

        /// <summary>
        /// Creates a new instance with each flag position in the argument array set.
        /// </summary>
        /// <param name="flags">The flags to set.</param>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public LongFlags(params int[] flags)
            => Set(flags);

        /// <summary>
        /// Creates a new instance with the given bits set.
        /// </summary>
        /// <param name="flags">The bits to copy. This directly
        /// sets <see cref="Flags"/>.</param>
        public LongFlags(ulong flags)
            => Flags = flags;

        /// <summary>
        /// Creates a deep clone of the argument.
        /// </summary>
        /// <param name="clone">The value to copy.</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private LongFlags(LongFlags clone)
            => Flags = clone.Flags;


        XmlSchema IXmlSerializable.GetSchema()
            => null;

        void IXmlSerializable.WriteXml(XmlWriter writer)
            => writer.WriteString(Flags.ToString(CultureInfo.InvariantCulture));

        void IXmlSerializable.ReadXml(XmlReader reader)
        {
            if (reader.IsEmptyElement)
                Flags = 0UL;
            else {
                reader.Read();
                switch (reader.NodeType) {
                    case XmlNodeType.EndElement :
                        Flags = 0UL; // empty after all...
                        break;
                    case XmlNodeType.Text :
                    case XmlNodeType.CDATA :
                        Flags = ulong.Parse(reader.ReadContentAsString(), CultureInfo.InvariantCulture);
                        break;
                    default :
                        throw new InvalidOperationException("Expected text/cdata");
                }
            }
        }


        /// <summary>
        /// The current bit flags. Flags are numbered from one to sixty-four: where
        /// the right-most bit is one, and the left-most is sixty four.
        /// Methods do not require knowledge of the flag positions; and flags
        /// are simply numbered [1,64].
        /// </summary>
        public ulong Flags
        {
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            get;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            private set;
        }


        /// <summary>
        /// An indexer that gets or sets a boolean indicating if the flag at the
        /// given <paramref name="position"/> is set.
        /// </summary>
        /// <param name="position">[1,64].</param>
        /// <returns>True if the flag is set.</returns>
        public bool this[int position]
        {
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            get => IsSet(position);
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            set {
                if (value)
                    Set(position);
                else
                    Clear(position);
            }
        }

        /// <summary>
        /// Returns true if the flag at the given position is set.
        /// </summary>
        /// <param name="position">The position to test: [1,64].</param>
        /// <returns>True if the flag is set.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public bool IsSet(int position)
        {
            LongFlags.rangeCheckPosition(position);
            return LongFlags.HasAnyBits(Flags, 1UL << (position - 1));
        }

        /// <summary>
        /// Returns true if each flag in the argument array is set.
        /// This will return FALSE if none are provided.
        /// </summary>
        /// <param name="positions">[1,64].</param>
        /// <returns>True if all provided flags are set. NOTICE: this will
        /// return FALSE if none are provided.</returns>
        public bool IsAllSet(params int[] positions)
        {
            if (positions.Length == 0)
                return false;
            foreach (int position in positions) {
                if (!IsSet(position))
                    return false;
            }
            return true;
        }

        /// <summary>
        /// Returns true if ANY flag in the argument array is set.
        /// This will return FALSE if none are provided.
        /// </summary>
        /// <param name="positions">[1,64].</param>
        /// <returns>True if ANY provided flag is set; AND if AT LEAST ONE
        /// is provided.</returns>
        public bool IsAnySet(params int[] positions)
        {
            foreach (int position in positions) {
                if (IsSet(position))
                    return true;
            }
            return false;
        }

        /// <summary>
        /// Returns true if all flags are set.
        /// </summary>
        public bool IsFull
        {
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            get => Flags == ulong.MaxValue;
        }

        /// <summary>
        /// Returns true if no flags are set.
        /// </summary>
        public bool IsEmpty
        {
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            get => Flags == 0UL;
        }


        /// <summary>
        /// Counts the flags that are set.
        /// </summary>
        /// <returns>A count of <see cref="Flags"/> bits that are set.</returns>
        public int Count
        {
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            get => LongFlags.CountBits(Flags);
        }

        /// <summary>
        /// Returns the position of highest flag that is set.
        /// </summary>
        /// <returns>The position of the highest bit that is set on <see cref="Flags"/>.</returns>
        public int HighestFlag
        {
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            get => LongFlags.GetHighestBitPosition(Flags);
        }

        /// <summary>
        /// Returns the position of lowest flag that is set.
        /// </summary>
        /// <returns>The position of the lowest bit that is set on <see cref="Flags"/>.</returns>
        public int LowestFlag
        {
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            get => LongFlags.GetLowestBitPosition(Flags);
        }

        /// <summary>
        /// Returns the <see langword="ulong"/> VALUE of the SINGLE
        /// highest bit that is set.
        /// </summary>
        /// <returns>The value of the single highest bit that is set on <see cref="Flags"/>.</returns>
        public ulong HighestFlagValue
        {
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            get => LongFlags.GetHighestBitValue(Flags);
        }

        /// <summary>
        /// Returns the <see langword="ulong"/> VALUE of the SINGLE
        /// lowest bit that is set.
        /// </summary>
        /// <returns>The value of the single lowest bit that is set on <see cref="Flags"/>.</returns>
        public ulong LowestFlagValue
        {
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            get => LongFlags.GetLowestBitValue(Flags);
        }


        /// <summary>
        /// Sets the flag at the position specified by the argument.
        /// </summary>
        /// <param name="position">[1,64].</param>
        /// <returns>This object for chaining.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public LongFlags Set(int position)
        {
            LongFlags.rangeCheckPosition(position);
            Flags |= 1UL << (position - 1);
            return this;
        }

        /// <summary>
        /// Sets the flag at each specified position.
        /// </summary>
        /// <param name="positions">[1,64].</param>
        /// <returns>This object for chaining.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public LongFlags Set(params int[] positions)
        {
            ulong flags = Flags;
            try {
                foreach (int position in positions) {
                    Set(position);
                }
                return this;
            } catch {
                Flags = flags;
                throw;
            }
        }

        /// <summary>
        /// Sets all flags to one.
        /// </summary>
        /// <returns>This object for chaining.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public LongFlags SetAll()
        {
            Flags = ulong.MaxValue;
            return this;
        }

        /// <summary>
        /// Clears the flag at the position specified by the argument.
        /// </summary>
        /// <param name="position">[1,64].</param>
        /// <returns>This object for chaining.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public LongFlags Clear(int position)
        {
            LongFlags.rangeCheckPosition(position);
            Flags &= ~(1UL << (position - 1));
            return this;
        }

        /// <summary>
        /// Clears the flag at each position specified in the argument array.
        /// </summary>
        /// <param name="positions">[1,64].</param>
        /// <returns>This object for chaining.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public LongFlags Clear(params int[] positions)
        {
            ulong flags = Flags;
            try {
                foreach (int position in positions) {
                    Clear(position);
                }
                return this;
            } catch {
                Flags = flags;
                throw;
            }
        }

        /// <summary>
        /// Resets all <see cref="Flags"/> to zero.
        /// </summary>
        /// <returns>This object for chaining.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public LongFlags Clear()
        {
            Flags = 0UL;
            return this;
        }


        /// <summary>
        /// Sets <see cref="Flags"/> to the argument's value.
        /// </summary>
        /// <param name="clone">The value to copy.</param>
        /// <returns>This object for chaining.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public LongFlags SetFrom(LongFlags clone)
        {
            Flags = clone.Flags;
            return this;
        }

        /// <summary>
        /// Sets <see cref="Flags"/> to the argument's value.
        /// </summary>
        /// <param name="clone">The value to copy.</param>
        /// <returns>This object for chaining.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public LongFlags SetFrom(ulong clone)
        {
            Flags = clone;
            return this;
        }

        /// <summary>
        /// Adds all of the flags in the argument to this instance.
        /// </summary>
        /// <param name="flags">Arbitrary flags to add.</param>
        /// <returns>This object for chaining.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public LongFlags AddAllFlags(LongFlags flags)
        {
            Flags |= flags.Flags;
            return this;
        }

        /// <summary>
        /// Removes all flags defined on the argument from this instance.
        /// </summary>
        /// <param name="flags">Arbitrary flags to remove.</param>
        /// <returns>This object for chaining.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public LongFlags RemoveAllFlags(LongFlags flags)
        {
            Flags &= ~flags.Flags;
            return this;
        }


        /// <summary>
        /// Returns true if this instance has ANY of the <see cref="Flags"/>
        /// defined on the argument. Notice that if the
        /// <paramref name="flags"/> are zero, this will return false.
        /// </summary>
        /// <param name="flags">Arbitrary flags to search for.</param>
        /// <returns>True if any flags are present here
        /// (and at least one flag bit is set).</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public bool HasAny(LongFlags flags)
            => LongFlags.HasAnyBits(Flags, flags.Flags);

        /// <summary>
        /// Returns true if this instance has ALL of the <see cref="Flags"/>
        /// defined on the argument. Notice that if the
        /// <paramref name="flags"/> are zero, this will return false.
        /// </summary>
        /// <param name="flags">Arbitrary flags to search for.</param>
        /// <returns>True if ALL flags are present here
        /// (and at least one flag bit is set).</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public bool HasAll(LongFlags flags)
            => LongFlags.HasAllBits(Flags, flags.Flags);

        /// <summary>
        /// Returns true if this instance has ONLY flags that are set
        /// on the <paramref name="flags"/> --- false if any flag is set here
        /// that is not defined on the flags. Notice that if the
        /// <paramref name="flags"/> are zero, this will return false
        /// --- and if this <see cref="Flags"/> is zero this returns false.
        /// </summary>
        /// <param name="flags">Arbitrary flags to search for.
        /// If zero, this will return false.</param>
        /// <param name="requiresAll">If true, then this
        /// MUST contain ALL <paramref name="flags"/> AND NO other flags.
        /// If false, this may contain zero or more flags
        /// present on the flags --- and no flags that are not present on the flags
        /// (this need not contain all, but can only contain a flag on the flags).</param>
        /// <returns>True if only the flags are present here --- false if any flag is
        /// set here that is not defined on the flags.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public bool HasOnly(LongFlags flags, bool requiresAll)
            => LongFlags.HasOnlyBits(Flags, flags.Flags, requiresAll);

        /// <summary>
        /// Returns true if this instance has NONE of the <see cref="Flags"/>
        /// defined on the argument.
        /// </summary>
        /// <param name="flags">Arbitrary.</param>
        /// <returns>True if no flags are present here.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public bool HasNone(LongFlags flags)
            => LongFlags.HasNoBits(Flags, flags.Flags);


        /// <summary>
        /// Returns a deep clone of this object.
        /// </summary>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public LongFlags Clone()
            => new LongFlags(this);

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        object ICloneable.Clone()
            => Clone();


        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static implicit operator ulong(LongFlags longFlags)
            => longFlags.Flags;

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static implicit operator LongFlags(ulong flags)
            => new LongFlags(flags);


        public override string ToString()
            => $"{nameof(LongFlags)}"
                    + "["
                    + $"{Convert.ToString((byte)(Flags >> 56), 2)}"
                    + $" {Convert.ToString((byte)(Flags >> 48), 2)}"
                    + $" {Convert.ToString((byte)(Flags >> 40), 2)}"
                    + $" {Convert.ToString((byte)(Flags >> 32), 2)}"
                    + $" {Convert.ToString((byte)(Flags >> 24), 2)}"
                    + $" {Convert.ToString((byte)(Flags >> 16), 2)}"
                    + $" {Convert.ToString((byte)(Flags >> 8), 2)}"
                    + $" {Convert.ToString((byte)Flags, 2)}"
                    + "]";
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.