/// ****************************************************************************
/// @file   
/// @author Dr.Neeton
/// @date   2008/X/X - 2013/09/03
/// 
/// @brief  bit配列クラス。
/// 
/// ****************************************************************************

#pragma once

#include "../../Base/CPL_Core_Define.h"

namespace CPL {
namespace Core {
namespace Array {

  template<class T_TYPE, int BIT_SIZE, int BIT_OFFS>
  struct bit_N {
    T_TYPE dummy : BIT_OFFS;
    T_TYPE data  : BIT_SIZE;
  };
  template<class T_TYPE, int BIT_SIZE>
  struct bit_N<T_TYPE, BIT_SIZE, 0> {
    T_TYPE data : BIT_SIZE;
  };

  // _____________________________________________________________________________
  /// @brief bit array manager
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<class T_TYPE, int BIT_SIZE>
  class bit_arr_mng {
    void* ptr_buf;

  public:
    bit_arr_mng( void* ptr ) : ptr_buf(ptr) {}

    int get( int idx )
    {
      const int byte_idx = (idx * BIT_SIZE) >> 3;
      const int offs     = (idx * BIT_SIZE) - (byte_idx * 8);
      const U8* ptr_data = ((U8*)ptr_buf + byte_idx); // データ位置に近いバッファ

      switch( offs )
      {
      case  0: return ((const bit_N<T_TYPE, BIT_SIZE, 0>*)(ptr_data))->data;
      case  1: return ((const bit_N<T_TYPE, BIT_SIZE, 1>*)(ptr_data))->data;
      case  2: return ((const bit_N<T_TYPE, BIT_SIZE, 2>*)(ptr_data))->data;
      case  3: return ((const bit_N<T_TYPE, BIT_SIZE, 3>*)(ptr_data))->data;
      case  4: return ((const bit_N<T_TYPE, BIT_SIZE, 4>*)(ptr_data))->data;
      case  5: return ((const bit_N<T_TYPE, BIT_SIZE, 5>*)(ptr_data))->data;
      case  6: return ((const bit_N<T_TYPE, BIT_SIZE, 6>*)(ptr_data))->data;
      case  7: return ((const bit_N<T_TYPE, BIT_SIZE, 7>*)(ptr_data))->data;
      default: return ((const bit_N<T_TYPE, BIT_SIZE, 0>*)(ptr_data))->data;
      }
    }

    void set( int idx, T_TYPE value )
    {
      const int byte_idx = (idx * BIT_SIZE) >> 3;
      const int offs     = (idx * BIT_SIZE) - (byte_idx * 8);
      U8*       ptr_data = ((U8*)ptr_buf + byte_idx); // データ位置に近いバッファ

      switch( offs )
      {
      case  0: ((bit_N<T_TYPE, BIT_SIZE, 0>*)(ptr_data))->data = value; break;
      case  1: ((bit_N<T_TYPE, BIT_SIZE, 1>*)(ptr_data))->data = value; break;
      case  2: ((bit_N<T_TYPE, BIT_SIZE, 2>*)(ptr_data))->data = value; break;
      case  3: ((bit_N<T_TYPE, BIT_SIZE, 3>*)(ptr_data))->data = value; break;
      case  4: ((bit_N<T_TYPE, BIT_SIZE, 4>*)(ptr_data))->data = value; break;
      case  5: ((bit_N<T_TYPE, BIT_SIZE, 5>*)(ptr_data))->data = value; break;
      case  6: ((bit_N<T_TYPE, BIT_SIZE, 6>*)(ptr_data))->data = value; break;
      case  7: ((bit_N<T_TYPE, BIT_SIZE, 7>*)(ptr_data))->data = value; break;
      default: ((bit_N<T_TYPE, BIT_SIZE, 0>*)(ptr_data))->data = value; break;
      }
    }
  };

} // namespace Array
} // namespace Core
} // namespace CPL

