/// ****************************************************************************
/// @file   
/// @author Dr.Neeton
/// @date   200X/X/X - 2014/01/24
/// 
/// @brief  DirectX シェーダー用文字列？
/// 
/// ****************************************************************************

#pragma once

#include "CPL_DX_Kernel.h"

namespace CPL {
namespace DX {
namespace Shader {

//// =============================================================================
//// 要素使用方法フラグのビット割り当て
//// =============================================================================
//struct _ELEMENT_USAGE {
//  unsigned Position     : 1;//D3DDECLUSAGE_POSITION,
//  unsigned BlendWeight  : 1;//D3DDECLUSAGE_BLENDWEIGHT,
//  unsigned BlendIndices : 1;//D3DDECLUSAGE_BLENDINDICES,
//  unsigned Normal       : 1;//D3DDECLUSAGE_NORMAL,
//  unsigned PSize        : 1;//D3DDECLUSAGE_PSIZE,
//  unsigned TexCoord     : 4;//D3DDECLUSAGE_TEXCOORD,
//  unsigned Tangent      : 1;//D3DDECLUSAGE_TANGENT,
//  unsigned BINormal     : 1;//D3DDECLUSAGE_BINORMAL,
//  unsigned TessFactor   : 1;//D3DDECLUSAGE_TESSFACTOR,
//  unsigned PositionT    : 1;//D3DDECLUSAGE_POSITINT,
//  unsigned Color        : 4;//D3DDECLUSAGE_COLOR,
//  unsigned Fog          : 1;//D3DDECLUSAGE_FOG,
//  unsigned Depth        : 1;//D3DDECLUSAGE_DEPTH,
//  unsigned Sample       : 1;//D3DDECLUSAGE_SAMLE,
//  _ELEMENT_USAGE()
//  {
//    memset(this,0,sizeof(*this));
//  }
//};


// _____________________________________________________________________________
/// @brief シェーダコード文字列用基底クラス
///
// *****************************************************************************
class CodeStrings
{
private:
  // _____________________________________________________________________________
  struct zzz_stringAnalyzer_
  {
    template<class T_String, class... T_Params>
    static void proc( T_String& io_str, T_Params&&... in_args ){}

    template<class T_String, class T, class... T_Params>
    static void proc( T_String& io_str, T&& in_param0, T_Params&&... in_args )
    {
      io_str += in_param0;
      //io_str += ", ";
      proc( io_str, std::forward<T_Params>( in_args )... );
    }

    template<class T_String, class T>
    static void proc( T_String& io_str, T&& in_param )
    {
      io_str += in_param;
    }
  };
  // _____________________________________________________________________________
  struct zzz_sizeAnalyzer_
  {
    template<class... T_Params>
    static size_t proc( T_Params&&... in_args ){ return 0; }

    template<class... T_Params>
    static size_t proc( char_cptr in_param0, T_Params&&... in_args )
    {
      return
        (strlen( static_cast<char_cptr>(in_param0) ) + 1)
        //+ sizeof( ", " )
        + proc( std::forward<T_Params>( in_args )... );
    }
    template<class T, class... T_Params>
    static size_t proc( T&& in_param0, T_Params&&... in_args )
    {
      return 16 + proc( std::forward<T_Params>( in_args )... );
    }

    template<>
    static size_t proc( char_cptr in_param )
    {
      return strlen( static_cast<char_cptr>(in_param) ) + 1;
    }
    template<class T>
    static size_t proc( T&& in_param )
    {
      return 16;
    }

  };
  // _____________________________________________________________________________
  struct zzz_CommaAdditional_
  {
    template<class T_String, class... T_Params>
    static void proc( T_String& io_str, T_Params&&... in_args ){}

    template<class T_String, class T, class... T_Params>
    static void proc( T_String& io_str, T&& in_param0, T_Params&&... in_args )
    {
      io_str += in_param0;
      io_str += ", ";
      proc( io_str, std::forward<T_Params>( in_args )... );
    }

    template<class T_String, class T>
    static void proc( T_String& io_str, T&& in_param )
    {
      io_str += in_param;
    }
  };
public:

  // shader strings
  class ss
  {
    Core::StringA m_str;
    
  public:
    //ss( char_cptr str ) : m_str( ReserveSize( zzz_sizeAnalyzer_::proc( str ) ) ) { m_str = str; }
    //ss( int i )         : m_str( ReserveSize( zzz_sizeAnalyzer_::proc(i) ) ) { m_str = i; }
    //ss( U32 i )         : m_str( ReserveSize( zzz_sizeAnalyzer_::proc(i) ) ) { m_str = i; }
    //ss( float f )       : m_str( ReserveSize( zzz_sizeAnalyzer_::proc(f) ) ) { m_str = f; }
    ss()                : m_str( ReserveSize( 16 ) ) { m_str = ""; }
    //template<class T>
    //ss( T const& str )
    //  : m_str( ReserveSize( zzz_sizeAnalyzer_::proc( static_cast<char_cptr>(str) ) ) )
    //{
    //  m_str = static_cast<char_cptr>(str);
    //}
    template<class T, class... T_Params>
    ss( T&& in_param0, T_Params&&... in_args )
      : m_str
          ( ReserveSize
              ( zzz_sizeAnalyzer_::proc
                  ( std::forward<T>( in_param0 )
                  , std::forward<T_Params>( in_args )...
                  )
              )
          )
    {
      zzz_stringAnalyzer_::proc
        ( m_str
        , std::forward<T>( in_param0 )
        , std::forward<T_Params>( in_args )...
        );
    }

    bool   Release(){ m_str = ""; return true; }
    bool   Reserve( int size ){ return m_str.Reserve( size ); }
    bool   Reset( char_cptr str ){ m_str = str; return true; }
    size_t GetLength() const { return m_str.GetLength(); }
    bool   IsEmpty() const { return m_str == ""; }
    // メンバ参照
    ss&    member( char_cptr menber_ )
    {
      return (*this, ".", menber_);
    }
    ss&    member( char_cptr menber_, int No )
    {
      return (*this, ".", Core::StringA( menber_ ) + No);
    }

    bool   comp( char_cptr str ) const { return (m_str.Comp( str ) != 0); }

    operator char_ptr ()       { return m_str; }
    operator char_cptr() const { return m_str; }

    ss& operator , ( char_cptr str )       { m_str << str; return *this; }
    //ss  operator , ( char_cptr str ) const { return ss(m_str + str); }
    template<class T> ss& operator , ( T const& str ){ m_str << str; return *this; }
    //template<class T> ss  operator , ( T const& str ){ return ss(m_str + str); }
    
    template<class T> ss& operator =  ( T const& str ){ return *this, " = "   , str; }
    template<class T> ss& operator += ( T const& str ){ return *this, " += "  , str; }
    template<class T> ss& operator -= ( T const& str ){ return *this, " -= "  , str; }
    template<class T> ss& operator *= ( T const& str ){ return *this, " *= "  , str; }
    template<class T> ss& operator /= ( T const& str ){ return *this, " /= "  , str; }
    template<class T> ss& operator %= ( T const& str ){ return *this, " %= "  , str; }
    template<class T> ss& operator +  ( T const& str ){ return *this, " + "   , str; }
    template<class T> ss& operator -  ( T const& str ){ return *this, " - "   , str; }
    template<class T> ss& operator *  ( T const& str ){ return *this, " * "   , str; }
    template<class T> ss& operator /  ( T const& str ){ return *this, " / "   , str; }
    template<class T> ss& operator %  ( T const& str ){ return *this, " % "   , str; }
    template<class T> ss& operator ^  ( T const& str ){ return *this, " ^ "   , str; }
    template<class T> ss& operator == ( T const& str ){ return *this, " == "  , str; }
    template<class T> ss& operator != ( T const& str ){ return *this, " != "  , str; }
    template<class T> ss& operator &= ( T const& str ){ return *this, " &= "  , str; }
    template<class T> ss& operator |= ( T const& str ){ return *this, " |= "  , str; }
    template<class T> ss& operator <  ( T const& str ){ return *this, " < "   , str; }
    template<class T> ss& operator >  ( T const& str ){ return *this, " > "   , str; }
    template<class T> ss& operator <= ( T const& str ){ return *this, " <= "  , str; }
    template<class T> ss& operator >= ( T const& str ){ return *this, " >= "  , str; }
    template<class T> ss& operator << ( T const& str ){ return *this, " << "  , str; }
    template<class T> ss& operator >> ( T const& str ){ return *this, " >> "  , str; }
    template<class T> ss& operator <<=( T const& str ){ return *this, " <<= " , str; }
    template<class T> ss& operator >>=( T const& str ){ return *this, " >>= " , str; }
    ss& operator =  ( ss const& in_str ){ return *this, " = ", in_str; }
    ss& operator ++ (int){ return *this, "++ "; }
    ss& operator -- (int){ return *this, "-- "; }
    ss& operator ++ (){ m_str = Core::StringA(" ++") + m_str; return *this; }
    ss& operator -- (){ m_str = Core::StringA(" --") + m_str; return *this; }
    ss& operator ~  (){ m_str = Core::StringA(" ~") + m_str; return *this; }
    ss& operator !  (){ m_str = Core::StringA(" !") + m_str; return *this; }
    ss& operator &  ()
    {
      m_str = Core::StringA("(") + m_str + ")";
      return *this;
    }

    ss& operator []( char_cptr str_idx ){ return *this, "[", str_idx, "]"; }
    ss& operator []( int       idx     ){ return *this, "[", Core::StringA(idx), "]"; }

    // 文字列に続く数値用
    ss& operator()( int   N ){ return *this, Core::StringA(N); }
    ss& operator()( float N ){ return *this, Core::StringA(N); }

    ss*       toAddress()       { return this; }
    ss const* toAddress() const { return this; }

    // 括弧表記用（引数１個）
    ss operator()( char_cptr a0 )
    {
      return *this, "(", a0, ")";
    }
    // 括弧表記用（引数２個以上）
    template<class... T_Params>
    ss operator()( char_cptr a0, char_cptr a1, T_Params... in_args )
    {
      decltype(m_str) tmp_str( m_str );
      tmp_str += "(";
      zzz_CommaAdditional_::proc( tmp_str, a0, a1, std::forward<T_Params>( in_args )... );
      tmp_str += ")";
      return ss( tmp_str );
    }
    //// 括弧表記用（可変個引数ではchar_cptrに暗黙変換できないので、この仕様）
    //ss& operator()( char_cptr a0 ){ return *this,"(",a0,")"; }
    //ss& operator()( char_cptr a0, char_cptr a1 ){ return *this,"(",a0,",",a1,")"; }
    //ss& operator()( char_cptr a0, char_cptr a1, char_cptr a2 )
    //{
    //  return *this,"(",a0,",",a1,",",a2,")";
    //}
    //ss& operator()( char_cptr a0, char_cptr a1, char_cptr a2, char_cptr a3 )
    //{
    //  return *this,"(",a0,",",a1,",",a2,",",a3,")";
    //}
    //ss& operator()( char_cptr a0, char_cptr a1, char_cptr a2, char_cptr a3, char_cptr a4 )
    //{
    //  return *this,"(",a0,",",a1,",",a2,",",a3,",",a4,")";
    //}
    //// 3x3
    //ss& operator()(
    //  char_cptr a0, char_cptr a1, char_cptr a2,
    //  char_cptr a3, char_cptr a4, char_cptr a5,
    //  char_cptr a6, char_cptr a7, char_cptr a8 )
    //{
    //  return *this,"(",
    //    a0,",",a1,",",a2,",",
    //    a3,",",a4,",",a5,",",
    //    a6,",",a7,",",a8,")";
    //}
    //// 4x4
    //ss& operator()(
    //  char_cptr a0, char_cptr a1, char_cptr a2, char_cptr a3,
    //  char_cptr a4, char_cptr a5, char_cptr a6, char_cptr a7,
    //  char_cptr a8, char_cptr a9, char_cptr aA, char_cptr aB,
    //  char_cptr aC, char_cptr aD, char_cptr aE, char_cptr aF )
    //{
    //  return *this,"(",
    //    a0,",",a1,",",a2,",",a3,",",
    //    a4,",",a5,",",a6,",",a7,",",
    //    a8,",",a9,",",aA,",",aB,",",
    //    aC,",",aD,",",aE,",",aF,")";
    //}
    // 対応メンバ
#define CPL_DX_DEF_SS_MEMBER( nameX ) ss nameX(){ return this->member( CPL_STRING(nameX) ); }
    CPL_DX_DEF_SS_MEMBER( x   );
    CPL_DX_DEF_SS_MEMBER( y   );
    CPL_DX_DEF_SS_MEMBER( z   );
    CPL_DX_DEF_SS_MEMBER( w   );
    CPL_DX_DEF_SS_MEMBER( xy  );
    CPL_DX_DEF_SS_MEMBER( xyz );
    CPL_DX_DEF_SS_MEMBER( r   );
    CPL_DX_DEF_SS_MEMBER( g   );
    CPL_DX_DEF_SS_MEMBER( b   );
    CPL_DX_DEF_SS_MEMBER( a   );
    CPL_DX_DEF_SS_MEMBER( rg  );
    CPL_DX_DEF_SS_MEMBER( rgb );
    CPL_DX_DEF_SS_MEMBER( _11 );
    CPL_DX_DEF_SS_MEMBER( _12 );
    CPL_DX_DEF_SS_MEMBER( _13 );
    CPL_DX_DEF_SS_MEMBER( _14 );
    CPL_DX_DEF_SS_MEMBER( _21 );
    CPL_DX_DEF_SS_MEMBER( _22 );
    CPL_DX_DEF_SS_MEMBER( _23 );
    CPL_DX_DEF_SS_MEMBER( _24 );
    CPL_DX_DEF_SS_MEMBER( _31 );
    CPL_DX_DEF_SS_MEMBER( _32 );
    CPL_DX_DEF_SS_MEMBER( _33 );
    CPL_DX_DEF_SS_MEMBER( _34 );
    CPL_DX_DEF_SS_MEMBER( _41 );
    CPL_DX_DEF_SS_MEMBER( _42 );
    CPL_DX_DEF_SS_MEMBER( _43 );
    CPL_DX_DEF_SS_MEMBER( _44 );
    CPL_DX_DEF_SS_MEMBER( Sample );
  };

private:
  // const shader strings base class
  template<int SIZE>
  class css
  {
  protected:
    Core::SStringA<SIZE> m_str;

    //struct zzz_stringAnalyzer_
    //{
      //template<class T_SString, class... T_Params>
      //void zzz_stringAnalyzer_( T_SString& io_str, T_Params&&... in_args ){}

      //template<class T_SString, class T, class... T_Params>
      //void zzz_stringAnalyzer_( T_SString& io_str, T&& in_param0, T_Params&&... in_args )
      //{
      //  io_str += in_param0;
      //  zzz_stringAnalyzer_( io_str, std::forward<T_Params>( in_args )... );
      //}

      //template<class T_SString, class T>
      //void zzz_stringAnalyzer_( T_SString& io_str, T&& in_param )
      //{
      //  io_str += in_param;
      //}
    //};
  public:
    css() : m_str("") {}
    //css( char_cptr str )     : m_str( str ) {}
    //css( int i )             : m_str(  i  ) {}
    //css( U32 i )             : m_str(  i  ) {}
    //css( float f )           : m_str(  f  ) {}
    //template<class T>
    //css( T const& s )
    //  : m_str( static_cast<char_cptr>(s) )
    //{}
    template<class T, class... T_Params>
    css( T&& in_param0, T_Params&&... in_args )
      : m_str("")
    {
      zzz_stringAnalyzer_::proc
        ( m_str
        , std::forward<T>( in_param0 )
        , std::forward<T_Params>( in_args )...
        );
    }

    //bool Release(){ m_str = ""; return true; }
    //bool Reserve( int size ){ return m_str.Reserve( size ); }
    bool   Reset( char_cptr str ){ m_str = str; return true; }
    size_t GetLength() const { return m_str.GetLength(); }
    bool   IsEmpty()   const { return m_str == ""; }
    ss     member( char_cptr menber_ ) const // メンバ参照
    {
      return ss(m_str), ".", menber_;
    }
    ss     member( char_cptr in_str_member, int No ) const
    {
      return ss(m_str), ".", in_str_member, No;
    }
    template<int N>
    css<SIZE+N> member( css<N> const& in_str_member ) const
    {
      return ss(m_str), ".", in_str_member;
    }
    template<int N>
    css<SIZE + N> member( css<N> const& in_str_member, int No ) const
    {
      return ss(m_str), ".", in_str_member, No;
    }

    bool comp( char_cptr str ) const { return (m_str.Comp( str ) != 0); }

    operator char_cptr() const { return m_str; }

    ss operator , ( char_cptr str ) const
    {
      return ss(m_str), str;
    }
    //ss operator , ( int N ) const
    //{
    //  return ss( m_str, N );
    //}
    template<class T>
    ss operator , ( cref<T> str ) const
    {
      return ss(m_str), str;
    }
    template<int N>
    css<SIZE+N> operator , ( cref<Core::SStringA<N>> str ) const
    {
      Core::SStringA<SIZE+N> new_str( m_str );
      new_str += str;
      return new_str;
    }
    template<int N>
    css<SIZE+N> operator , ( cref<css<N>> str ) const
    {
      Core::SStringA<SIZE+N> new_str( m_str );
      new_str += str;
      return new_str;
    }

    css<SIZE*2+4> operator = ( cref<css<SIZE>> str ) const
    {
      return
        css<SIZE * 2 + 4>
          ( Core::SStringA<SIZE * 2 + 4>(m_str) + " = " + str );
    }

    #define CPL_DEF_SADER_CODESTRINGS_CSS_OPERATOR_TYPE1( typestr_ )\
      template<int N>\
      css<SIZE+N+sizeof(CPL_STRING(typestr_))>\
        operator typestr_ ( cref<css<N>> in_str ) const\
      {\
        return\
          css<SIZE+N+sizeof(CPL_STRING(typestr_))>\
            ( Core::SStringA<SIZE+N+sizeof(CPL_STRING(typestr_))>(m_str) + CPL_STRING(typestr_) + in_str );\
      }\
      template<class T>\
      ss operator typestr_ ( cref<T> in_str ) const\
      {\
        return ss(m_str), CPL_STRING(typestr_), in_str;\
      }
    CPL_DEF_SADER_CODESTRINGS_CSS_OPERATOR_TYPE1( =   )
    CPL_DEF_SADER_CODESTRINGS_CSS_OPERATOR_TYPE1( +=  )
    CPL_DEF_SADER_CODESTRINGS_CSS_OPERATOR_TYPE1( -=  )
    CPL_DEF_SADER_CODESTRINGS_CSS_OPERATOR_TYPE1( *=  )
    CPL_DEF_SADER_CODESTRINGS_CSS_OPERATOR_TYPE1( /=  )
    CPL_DEF_SADER_CODESTRINGS_CSS_OPERATOR_TYPE1( %=  )
    CPL_DEF_SADER_CODESTRINGS_CSS_OPERATOR_TYPE1( +   )
    CPL_DEF_SADER_CODESTRINGS_CSS_OPERATOR_TYPE1( -   )
    CPL_DEF_SADER_CODESTRINGS_CSS_OPERATOR_TYPE1( *   )
    CPL_DEF_SADER_CODESTRINGS_CSS_OPERATOR_TYPE1( /   )
    CPL_DEF_SADER_CODESTRINGS_CSS_OPERATOR_TYPE1( %   )
    CPL_DEF_SADER_CODESTRINGS_CSS_OPERATOR_TYPE1( ^   )
    CPL_DEF_SADER_CODESTRINGS_CSS_OPERATOR_TYPE1( ==  )
    CPL_DEF_SADER_CODESTRINGS_CSS_OPERATOR_TYPE1( !=  )
    CPL_DEF_SADER_CODESTRINGS_CSS_OPERATOR_TYPE1( &=  )
    CPL_DEF_SADER_CODESTRINGS_CSS_OPERATOR_TYPE1( |=  )
    CPL_DEF_SADER_CODESTRINGS_CSS_OPERATOR_TYPE1( <   )
    CPL_DEF_SADER_CODESTRINGS_CSS_OPERATOR_TYPE1( >   )
    CPL_DEF_SADER_CODESTRINGS_CSS_OPERATOR_TYPE1( <=  )
    CPL_DEF_SADER_CODESTRINGS_CSS_OPERATOR_TYPE1( >=  )
    CPL_DEF_SADER_CODESTRINGS_CSS_OPERATOR_TYPE1( <<  )
    CPL_DEF_SADER_CODESTRINGS_CSS_OPERATOR_TYPE1( >>  )
    CPL_DEF_SADER_CODESTRINGS_CSS_OPERATOR_TYPE1( <<= )
    CPL_DEF_SADER_CODESTRINGS_CSS_OPERATOR_TYPE1( >>= )

    css<SIZE + 4> operator ++ (int) const { return css<SIZE + 4>( (*this, "++ ") ); }
    css<SIZE + 4> operator -- (int) const { return css<SIZE + 4>( (*this, "-- ") ); }
    css<SIZE + 4> operator ++ () const { return css<SIZE + 4>( Core::SStringA<SIZE+4>(" ++") + m_str ); }
    css<SIZE + 4> operator -- () const { return css<SIZE + 4>( Core::SStringA<SIZE+4>(" --") + m_str ); }
    css<SIZE + 4> operator ~  () const { return css<SIZE + 4>( Core::SStringA<SIZE+4>(" ~" ) + m_str ); }
    css<SIZE + 4> operator !  () const { return css<SIZE + 4>( Core::SStringA<SIZE+4>(" !" ) + m_str ); }
    css<SIZE + 4> operator &  () const
    {
      return css<SIZE + 4>( ss("("), *this, ")" );
    }

    //template<class T> ss operator =  ( cref<T> str ) const { return ss(m_str, " = "  , str); }
    //template<class T> ss operator += ( cref<T> str ) const { return ss(m_str, " += " , str); }
    //template<class T> ss operator -= ( cref<T> str ) const { return ss(m_str, " -= " , str); }
    //template<class T> ss operator *= ( cref<T> str ) const { return ss(m_str, " *= " , str); }
    //template<class T> ss operator /= ( cref<T> str ) const { return ss(m_str, " /= " , str); }
    //template<class T> ss operator %= ( cref<T> str ) const { return ss(m_str, " %= " , str); }
    //template<class T> ss operator +  ( cref<T> str ) const { return ss(m_str, " + "  , str); }
    //template<class T> ss operator -  ( cref<T> str ) const { return ss(m_str, " - "  , str); }
    //template<class T> ss operator *  ( cref<T> str ) const { return ss(m_str, " * "  , str); }
    //template<class T> ss operator /  ( cref<T> str ) const { return ss(m_str, " / "  , str); }
    //template<class T> ss operator %  ( cref<T> str ) const { return ss(m_str, " % "  , str); }
    //template<class T> ss operator ^  ( cref<T> str ) const { return ss(m_str, " ^ "  , str); }
    //template<class T> ss operator == ( cref<T> str ) const { return ss(m_str, " == " , str); }
    //template<class T> ss operator != ( cref<T> str ) const { return ss(m_str, " != " , str); }
    //template<class T> ss operator &= ( cref<T> str ) const { return ss(m_str, " &= " , str); }
    //template<class T> ss operator |= ( cref<T> str ) const { return ss(m_str, " |= " , str); }
    //template<class T> ss operator <  ( cref<T> str ) const { return ss(m_str, " < "  , str); }
    //template<class T> ss operator >  ( cref<T> str ) const { return ss(m_str, " > "  , str); }
    //template<class T> ss operator <= ( cref<T> str ) const { return ss(m_str, " <= " , str); }
    //template<class T> ss operator >= ( cref<T> str ) const { return ss(m_str, " >= " , str); }
    //template<class T> ss operator << ( cref<T> str ) const { return ss(m_str, " << " , str); }
    //template<class T> ss operator >> ( cref<T> str ) const { return ss(m_str, " >> " , str); }
    //template<class T> ss operator <<=( cref<T> str ) const { return ss(m_str, " <<= ", str); }
    //template<class T> ss operator >>=( cref<T> str ) const { return ss(m_str, " >>= ", str); }
    //ss operator ++ (int) const { return *this, css<4>("++ "); }
    //ss operator -- (int) const { return *this, css<4>("-- "); }
    //ss operator ++ () const { return css<SIZE+8>(" ++") , m_str; }
    //ss operator -- () const { return css<SIZE+8>(" --") , m_str; }
    //ss operator ~  () const { return css<SIZE+8>(" ~")  , m_str; }
    //ss operator !  () const { return css<SIZE+8>(" !")  , m_str; }
    //ss operator &  () const { return css<SIZE+8>("(")   , m_str, css<4>(")"); }

    template<int N>
    ss operator []( css<N> const& str_idx ) const
    {
      return ss(m_str), "[", str_idx, "]";
    }
    template<class T>
    ss operator []( T const& idx ) const
    {
      return ss(m_str), "[", idx, "]";
    }

    // 文字列に続く数値用
    //auto operator()( int   N ) const { return *this, css<16>(N); }
    //auto operator()( float N ) const { return *this, css<16>(N); }
    //template<class IDX_TYPE>
    //ss operator()( IDX_TYPE N ) const { return ss(m_str, N); }

    css*       toAddress()       { return this; }
    css const* toAddress() const { return this; }
    // 括弧表記用（引数１個）
    ss operator()( char_cptr a0 )
    {
      return ss(m_str), "(", a0, ")";
    }
    // 括弧表記用（引数２個以上）
    template<class... T_Params>
    ss operator()( char_cptr a0, char_cptr a1, T_Params... in_args )
    {
      ss tmp_str( m_str );
      return tmp_str( a0, a1, std::forward<T_Params>( in_args )... );
    }
    //// 括弧表記用（可変個引数ではchar_cptrに暗黙変換できないので、この仕様）
    //ss operator()( char_cptr a0 ) const { return *this,"(",a0,")"; }
    //ss operator()( char_cptr a0, char_cptr a1 ) const { return *this,"(",a0,",",a1,")"; }
    //ss operator()( char_cptr a0, char_cptr a1, char_cptr a2 ) const
    //{
    //  return *this,"(",a0,",",a1,",",a2,")";
    //}
    //ss operator()(
    //    char_cptr a0, char_cptr a1,
    //    char_cptr a2, char_cptr a3 ) const
    //{
    //  return *this,"(",a0,",",a1,",",a2,",",a3,")";
    //}
    //ss operator()(
    //    char_cptr a0, char_cptr a1,
    //    char_cptr a2, char_cptr a3, char_cptr a4 ) const
    //{
    //  return *this,"(",a0,",",a1,",",a2,",",a3,",",a4,")";
    //}
    //// 3x3
    //ss operator()(
    //  char_cptr a0, char_cptr a1, char_cptr a2,
    //  char_cptr a3, char_cptr a4, char_cptr a5,
    //  char_cptr a6, char_cptr a7, char_cptr a8 ) const
    //{
    //  return *this,"(",
    //    a0,",",a1,",",a2,",",
    //    a3,",",a4,",",a5,",",
    //    a6,",",a7,",",a8,")";
    //}
    //// 4x4
    //ss operator()(
    //  char_cptr a0, char_cptr a1, char_cptr a2, char_cptr a3,
    //  char_cptr a4, char_cptr a5, char_cptr a6, char_cptr a7,
    //  char_cptr a8, char_cptr a9, char_cptr aA, char_cptr aB,
    //  char_cptr aC, char_cptr aD, char_cptr aE, char_cptr aF ) const
    //{
    //  return *this,"(",
    //    a0,",",a1,",",a2,",",a3,",",
    //    a4,",",a5,",",a6,",",a7,",",
    //    a8,",",a9,",",aA,",",aB,",",
    //    aC,",",aD,",",aE,",",aF,")";
    //}
    
    // 対応メンバ
    #define CPL_DX_DEF_CSS_MEMBER( X )\
      css<SIZE+8> X() const { return this->member( css<4>( CPL_STRING(X) ) ); }
    #define CPL_DX_DEF_CSS_MEMBER_FUNC2( X )\
      ss X( char_cptr a0, char_cptr a1 ) const {\
        return this->member( css<sizeof(CPL_STRING(X))+1>( CPL_STRING(X) ) )( a0, a1 );\
      }
    CPL_DX_DEF_CSS_MEMBER( x   );
    CPL_DX_DEF_CSS_MEMBER( y   );
    CPL_DX_DEF_CSS_MEMBER( z   );
    CPL_DX_DEF_CSS_MEMBER( w   );
    CPL_DX_DEF_CSS_MEMBER( xy  );
    CPL_DX_DEF_CSS_MEMBER( xyz );
    CPL_DX_DEF_CSS_MEMBER( r   );
    CPL_DX_DEF_CSS_MEMBER( g   );
    CPL_DX_DEF_CSS_MEMBER( b   );
    CPL_DX_DEF_CSS_MEMBER( a   );
    CPL_DX_DEF_CSS_MEMBER( rg  );
    CPL_DX_DEF_CSS_MEMBER( rgb );
    CPL_DX_DEF_CSS_MEMBER( _11 );
    CPL_DX_DEF_CSS_MEMBER( _12 );
    CPL_DX_DEF_CSS_MEMBER( _13 );
    CPL_DX_DEF_CSS_MEMBER( _14 );
    CPL_DX_DEF_CSS_MEMBER( _21 );
    CPL_DX_DEF_CSS_MEMBER( _22 );
    CPL_DX_DEF_CSS_MEMBER( _23 );
    CPL_DX_DEF_CSS_MEMBER( _24 );
    CPL_DX_DEF_CSS_MEMBER( _31 );
    CPL_DX_DEF_CSS_MEMBER( _32 );
    CPL_DX_DEF_CSS_MEMBER( _33 );
    CPL_DX_DEF_CSS_MEMBER( _34 );
    CPL_DX_DEF_CSS_MEMBER( _41 );
    CPL_DX_DEF_CSS_MEMBER( _42 );
    CPL_DX_DEF_CSS_MEMBER( _43 );
    CPL_DX_DEF_CSS_MEMBER( _44 );

    CPL_DX_DEF_CSS_MEMBER_FUNC2( Sample );
  };
public:
  typedef css<16>  css16;
  typedef css<32>  css32;
  typedef css<64>  css64;
  typedef css<128> css128;
  typedef css<256> css256;

public:
  //typedef ss_<false> ss;  // string stream
  //typedef ss_<true>  css; // const string stream
};



} // namespace Shader
} // namespace DX
} // namespace CPL
