using CommonLang.IO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CommonLang
{

    public struct BitSet8 : IExternalizable
    {
        private byte mMask;
        public byte Mask { get { return mMask; } set { mMask = value; } }
        public BitSet8(byte mask) { mMask = mask; }
        public bool Get(int i) 
        {
            return BitMask.BitGetMask(mMask, i);
        }
        public void Set(int i, bool value)
        {
            BitMask.BitSetMask(ref mMask, i, value);
        }
        public void WriteExternal(IOutputStream output)
        {
            output.PutU8(mMask);
        }
        public void ReadExternal(IInputStream input)
        {
            this.mMask = input.GetU8();
        }
    }
    public struct BitSet16 : IExternalizable
    {
        private short mMask;
        public short Mask { get { return mMask; } set { mMask = value; } }
        public BitSet16(short mask) { mMask = mask; }
        public bool Get(int i)
        {
            return BitMask.BitGetMask(mMask, i);
        }
        public void Set(int i, bool value)
        {
            BitMask.BitSetMask(ref mMask, i, value);
        }
        public void WriteExternal(IOutputStream output)
        {
            output.PutS16(mMask);
        }
        public void ReadExternal(IInputStream input)
        {
            this.mMask = input.GetS16();
        }
    }

    public struct BitSet32 : IExternalizable
    {
        private int mMask;
        public int Mask { get { return mMask; } set { mMask = value; } }
        public BitSet32(int mask) { mMask = mask; }
        public bool Get(int i)
        {
            return BitMask.BitGetMask(mMask, i);
        }
        public void Set(int i, bool value)
        {
            BitMask.BitSetMask(ref mMask, i, value);
        }
        public void WriteExternal(IOutputStream output)
        {
            output.PutS32(mMask);
        }
        public void ReadExternal(IInputStream input)
        {
            this.mMask = input.GetS32();
        }
    }

    public struct BitSet64 : IExternalizable
    {
        private long mMask;
        public long Mask { get { return mMask; } set { mMask = value; } }
        public BitSet64(long mask) { mMask = mask; }
        public bool Get(int i)
        {
            return BitMask.BitGetMask(mMask, i);
        }
        public void Set(int i, bool value)
        {
            BitMask.BitSetMask(ref mMask, i, value);
        }
        public void WriteExternal(IOutputStream output)
        {
            output.PutS64(mMask);
        }
        public void ReadExternal(IInputStream input)
        {
            this.mMask = input.GetS64();
        }
    } 

    public class BitMask
    {
        public static void BitSetMask(ref byte mask, int i, bool value)
        {
            if (value)
            {
                mask |= (byte)(1 << i);
            }
            else
            {
                mask &= (byte)(~(1 << i));
            }
        }
        public static bool BitGetMask(byte mask, int i)
        {
            return (mask & (1 << i)) != 0;
        }

        public static void BitSetMask(ref short mask, int i, bool value)
        {
            if (value)
            {
#pragma warning disable CS0675 // 对进行了带符号扩展的操作数使用了按位或运算符
                mask |= (short)(1 << i);
#pragma warning restore CS0675 // 对进行了带符号扩展的操作数使用了按位或运算符
            }
            else
            {
                mask &= (short)(~(1 << i));
            }
        }
        public static bool BitGetMask(short mask, int i)
        {
            return (mask & (1 << i)) != 0;
        }

        public static void BitSetMask(ref int mask, int i, bool value)
        {
            if (value)
            {
                mask |= (1 << i);
            }
            else
            {
                mask &= (~(1 << i));
            }
        }
        public static bool BitGetMask(int mask, int i)
        {
            return (mask & (1 << i)) != 0;
        }

        public static void BitSetMask(ref long mask, int i, bool value)
        {
            long m = (1L << i);
            if (value)
            {
                mask |= m;
            }
            else
            {
                mask &= ~m;
            }
        }
        public static bool BitGetMask(long mask, int i)
        {
            long m = (1L << i);
            return (mask & m) != 0;
        }
    }
}