부품 설계도

[C#]Bit_Builder 전체 코드

밤말팅 2020. 11. 15. 20:22

 

 

[C#] Int를 비트단위로 저장해주는 클래스

안녕하십니까 밤말팅입니다. 블로그를 열고 첫 포스팅인데요, 앞으로 게임 개발에 도움이 될 여러 가지 클래스를 구상하고 제작하는 대로 포스팅 할 예정입니다. 내용이 괜찮다고 생각하시면

game-part-factory.tistory.com

 

이 글은 위에서 설명하는 클래스의 전체 코드입니다!

 

내용이 궁금하시면 해당 포스팅을 참고해주시면 감사드리겠습니다~

 

public enum Bit_Type
{
	FLOAT,
	BOOL
}

public class Bit_Builder
{
  private Bit_Type[] containTypeArray;
  private byte[] containByteArray;
  private int[] locationBitArray;

  public int Length { get { return containTypeArray.Length; } }

  public object this[int targetIndex]
  {
    get
    {
      if(targetIndex > containTypeArray.Length)
      {
          return null;
      };

      if (containTypeArray[targetIndex] == Bit_Type.BOOL)
      {
          return GetBool(targetIndex);
      }
      else if (containTypeArray[targetIndex] == Bit_Type.FLOAT)
      {
          return BitConverter.ToSingle(GetByte(targetIndex), 0);
      }
      else
      {
          return BitConverter.ToInt32(GetByte(targetIndex), 0);
      };
    }

    set
    {
      if(targetIndex > containTypeArray.Length)
      {
          return;
      };

      if (containTypeArray[targetIndex] == Bit_Type.BOOL)
      {
          SetBool(targetIndex, (bool)value);
      }
      else
      {
        Type valueType = value.GetType();
        byte[] wantByte = new byte[0];

        if (valueType == typeof(float))
        {
          wantByte = BitConverter.GetBytes((float)value);
        }
        else
        {
          wantByte = BitConverter.GetBytes((int)value);
        };

        if(wantByte.Length > 0)
        {
          SetByte(targetIndex, wantByte);
        };
      };
    }
  }

  public Bit_Builder(Bit_Type[] wantTypes)
  {
    int bitLength = 0;

    containTypeArray = wantTypes;
    locationBitArray = new int[wantTypes.Length];

    for (int i = 0; i < containTypeArray.Length; ++i)
    {
      if (containTypeArray[i] > (Bit_Type)32)
      {
      	containTypeArray[i] = (Bit_Type)32;
      };

      locationBitArray[i] = bitLength;
      bitLength += TypeLength(containTypeArray[i]);
    };
    containByteArray = new byte[(int)Math.Ceiling(bitLength / 8.0d)];
  }

  private static int TypeLength(Bit_Type wantType)
  {
    if(wantType == Bit_Type.FLOAT)
    {
    	return 32;
    }
    else
    {
    	return (int)wantType;
    };
  }

  private void SetBool(int targetIndex, bool value)
  {
    int bitLocation = locationBitArray[targetIndex] % 8;
    int byteLocation = locationBitArray[targetIndex] >> 3;

    if (value)
    {
    	containByteArray[byteLocation] |= (byte)(0x80 >> bitLocation);
    }
    else
    {
    	containByteArray[byteLocation] &= (byte)~(0x80 >> bitLocation);
    };
  }

  private bool GetBool(int targetIndex)
  {
    int bitLocation = locationBitArray[targetIndex] % 8;
    byte targetByte = containByteArray[locationBitArray[targetIndex] >> 3];

    return (targetByte & (0x80 >> bitLocation)) > 0;
  }

  private void SetByte(int targetIndex, byte[] wantByte)
  {
    int bitLocation = locationBitArray[targetIndex] % 8;
    int byteLocation = locationBitArray[targetIndex] >> 3;
    int bitEnd = bitLocation + TypeLength(containTypeArray[targetIndex]);
    int byteEnd = (locationBitArray[targetIndex] + TypeLength(containTypeArray[targetIndex])) >> 3;
    int wholeByte = TypeLength(containTypeArray[targetIndex]) >> 3;
    int leftBit = TypeLength(containTypeArray[targetIndex]) % 8;
    int lastBit = leftBit + bitLocation;

    if (byteEnd > containByteArray.Length)
    {
    	return;
    };

    if (1 < TypeLength(containTypeArray[targetIndex]) && TypeLength(containTypeArray[targetIndex]) < 8)
    {
      if (bitEnd < 9)
      {
        int bitMask = (0xff >> bitLocation) ^ (0xff >> bitEnd);

        containByteArray[byteLocation] &= (byte)~bitMask;
        containByteArray[byteLocation] |= (byte)(bitMask & (wantByte[0] << (8 - bitEnd)));
        return;
      }
      else
      {
        int bitMask = (0xff >> bitLocation);

        containByteArray[byteLocation] &= (byte)~bitMask;
        containByteArray[byteLocation] |= (byte)(bitMask & wantByte[0]);

        bitMask = ~(0xff >> (bitEnd - 8));

        containByteArray[byteLocation + 1] &= (byte)~bitMask;
        containByteArray[byteLocation + 1] |= (byte)(bitMask & (wantByte[0] << (8 - TypeLength(containTypeArray[targetIndex]))));
      };
    }
    else
    {
      if (bitLocation == 0)
      {
        for (int i = 0; i < wholeByte; ++i)
        {
          containByteArray[byteLocation + i] = wantByte[i];
        };

        if(leftBit > 0)
        {
          containByteArray[byteLocation + wholeByte] &= (byte)~(0xff >> bitEnd % 8);
          containByteArray[byteLocation + wholeByte] |= (byte)(wantByte[wholeByte] << (8 - leftBit));
        };

      return;
      }
      else
      {
        int bitMask = 0xFF >> bitLocation;

        byte firstByte = (byte)(wantByte[0] & bitMask);
        byte lastByte = (byte)(wantByte[0] & ~bitMask);

        for (int i = 1; i < wholeByte; ++i)
        {
        	containByteArray[byteLocation + i] = wantByte[i];
        };

        containByteArray[byteLocation] &= (byte)~bitMask;
        containByteArray[byteLocation] |= firstByte;

        containByteArray[byteLocation + wholeByte] &= (byte)bitMask;
        containByteArray[byteLocation + wholeByte] |= lastByte;

        if(wholeByte < 4)
        {
          if (lastBit > 8)
          {
            containByteArray[byteLocation + wholeByte] &= (byte)~bitMask;
            containByteArray[byteLocation + wholeByte] |= (byte)(wantByte[wholeByte] & bitMask);

            bitMask = ~(0xff >> lastBit % 8);
            containByteArray[byteLocation + wholeByte + 1] &= (byte)~bitMask;
            containByteArray[byteLocation + wholeByte + 1] |= (byte)((wantByte[wholeByte] << (8 - leftBit)) & bitMask);
          }
          else if (leftBit > 0)
          {
            bitMask = ~(~bitMask | (0xff >> bitLocation + leftBit));

            containByteArray[byteLocation + wholeByte] &= (byte)~bitMask;
            containByteArray[byteLocation + wholeByte] |= (byte)((wantByte[wholeByte] << (8 - lastBit)) & bitMask);
          };
      	};

      return;
      };
    };
  }

  private byte[] GetByte(int targetIndex)
  {
    int bitLocation = locationBitArray[targetIndex] % 8;
    int byteLocation = locationBitArray[targetIndex] >> 3;
    int bitEnd = bitLocation + TypeLength(containTypeArray[targetIndex]);
    int byteEnd = (locationBitArray[targetIndex] + TypeLength(containTypeArray[targetIndex])) >> 3;
    int wholeByte = TypeLength(containTypeArray[targetIndex]) >> 3;
    int leftBit = TypeLength(containTypeArray[targetIndex]) % 8;
    int lastBit = leftBit + bitLocation;

    byte[] result = new byte[4];

    if (byteEnd > containByteArray.Length)
    {
    	return result;
    };

    if (1 < TypeLength(containTypeArray[targetIndex]) && TypeLength(containTypeArray[targetIndex]) < 8)
    {
      if (bitEnd < 9)
      {
        int bitMask = (0xff >> bitLocation) ^ (0xff >> bitEnd);

        result[0] = (byte)((containByteArray[byteLocation] & bitMask) >> (8 - bitEnd));
      }
      else
      {
        int bitMask = (0xff >> bitLocation);

        result[0] = (byte)(containByteArray[byteLocation] & bitMask);

        bitMask = ~(0xff >> (bitEnd - 8));

        result[0] |= (byte)((containByteArray[byteLocation + 1] & bitMask) >> (8 - TypeLength(containTypeArray[targetIndex])));
      };
    }
    else
    {
      if (bitLocation == 0)
      {
        for (int i = 0; i < wholeByte; ++i)
        {
          result[i] = containByteArray[byteLocation + i];
        };

        if (leftBit > 0)
        {
          result[wholeByte] = (byte)(containByteArray[byteLocation + wholeByte] & ~(0xff >> bitEnd % 8));
          result[wholeByte] = (byte)(result[wholeByte] >> (8 - leftBit));
        };
      }
      else
      {
        int bitMask = 0xFF >> bitLocation;

        result[0] = (byte)(containByteArray[byteLocation] & bitMask);
        result[0] |= (byte)(containByteArray[byteLocation + wholeByte] & ~bitMask);

        for (int i = 1; i < wholeByte; ++i)
        {
          result[i] = containByteArray[byteLocation + i];
        };
        if(wholeByte != 4)
        {
          if (lastBit > 8)
          {
            result[wholeByte] = (byte)(containByteArray[byteLocation + wholeByte] & bitMask);

            bitMask = ~(0xff >> lastBit % 8);
            result[wholeByte] |= (byte)((containByteArray[byteLocation + wholeByte + 1] & bitMask) >> (8 - leftBit));
          }
          else if(leftBit > 0)
          {
            bitMask = ~(~bitMask | (0xff >> bitLocation + leftBit));
            result[wholeByte] = (byte)((containByteArray[byteLocation + wholeByte] & bitMask) >> (8 - lastBit));
          };
        };				
      };
    };

    if(TypeLength(containTypeArray[targetIndex]) % 8 == 0)
    {
      if (wholeByte <= result.Length && (result[wholeByte - 1] & (0x80)) > 0)
      {
        for (int i = 3; i>=wholeByte; --i)
        {
        	result[i] = 0xff;
        };
      };
    }
    else
    {
      if (wholeByte < result.Length && (result[wholeByte] & (0x01 << leftBit - 1)) > 0)
      {
        for (int i = 3; i > wholeByte; --i)
        {
        	result[i] = 0xff;
        };
        result[wholeByte] |= (byte)(0xff << leftBit);
      };
    };

    return result;
  }

  public bool SetByteArray(byte[] wantArray)
  {
    if (wantArray.Length == containByteArray.Length)
    {
    	containByteArray = wantArray;
    	return true;
    }
    else
    {
    	return false;
    };
  }

  public byte[] GetByteArray()
  {
  	return containByteArray;
  }
}