diff --git a/shaders.cc b/shaders.cc index 2d4e08b..4e45f37 100644 --- a/shaders.cc +++ b/shaders.cc @@ -3,134 +3,139 @@ namespace { - const std::regex PreprocDirective_( "^\\s*//!\\s*([a-z]+(\\s+([^\\s]+))*)\\s*$" ); - const std::map< std::string , E_ShaderInput > InputTypes_( ([] { - std::map< std::string , E_ShaderInput > t; - t.emplace( "chunk" , E_ShaderInput::CHUNK ); - t.emplace( "library" , E_ShaderInput::LIBRARY ); - t.emplace( "lib" , E_ShaderInput::LIBRARY ); - t.emplace( "vertex" , E_ShaderInput::VERTEX ); - t.emplace( "fragment" , E_ShaderInput::FRAGMENT ); - return t; - })()); +const std::regex PreprocDirective_( "^\\s*//!\\s*([a-z]+(\\s+([^\\s]+))*)\\s*$" ); +const std::map< std::string , E_ShaderInput > InputTypes_( ([] { + std::map< std::string , E_ShaderInput > t; + t.emplace( "chunk" , E_ShaderInput::CHUNK ); + t.emplace( "library" , E_ShaderInput::LIBRARY ); + t.emplace( "lib" , E_ShaderInput::LIBRARY ); + t.emplace( "vertex" , E_ShaderInput::VERTEX ); + t.emplace( "fragment" , E_ShaderInput::FRAGMENT ); + return t; +})()); - struct T_InputReader_ - { - using T_Tokens_ = std::vector< std::string >; +/*============================================================================*/ - FILE* const file; - T_ShaderInput& input; - uint32_t line{ 0 }; +// Input reader state and functions, used when loading a source file +struct T_InputReader_ +{ + using T_Tokens_ = std::vector< std::string >; - char* buffer{ nullptr }; - ssize_t readCount; + FILE* const file; + T_ShaderInput& input; + uint32_t line{ 0 }; - std::string accumulator{ }; - uint32_t accumLines{ 0 }; + char* buffer{ nullptr }; + ssize_t readCount; - T_InputReader_( __rd__ FILE* const file , - __rw__ T_ShaderInput& input ) - : file( file ) , input( input ) - { } - ~T_InputReader_( ); + std::string accumulator{ }; + uint32_t accumLines{ 0 }; - void read( ); - void nl( ); - void addAccumulated( ); - void handleDirective( - __rd__ T_Tokens_ const& tokens ); - void error( __rd__ std::string const& err ); - }; + T_InputReader_( __rd__ FILE* const file , + __rw__ T_ShaderInput& input ) + : file( file ) , input( input ) + { } + ~T_InputReader_( ); - T_InputReader_::~T_InputReader_( ) - { - if ( buffer ) { - free( buffer ); - } - fclose( file ); + void read( ); + void nl( ); + void addAccumulated( ); + void handleDirective( + __rd__ T_Tokens_ const& tokens ); + void error( __rd__ std::string const& err ); +}; + +/*----------------------------------------------------------------------------*/ + +T_InputReader_::~T_InputReader_( ) +{ + if ( buffer ) { + free( buffer ); } + fclose( file ); +} - void T_InputReader_::read( ) - { - size_t bsz( 0 ); - while ( ( readCount = getline( &buffer , &bsz , file ) ) != -1 ) { - line ++; - std::cmatch match; - if ( std::regex_match( buffer , match , PreprocDirective_ ) ) { - const T_Tokens_ tokens( ([](std::string const& a) { - using stri = std::istream_iterator< std::string >; - std::istringstream iss( a ); - return T_Tokens_{ stri( iss ) , stri( ) }; - })( match[ 1 ].str( ) ) ); - assert( tokens.size( ) >= 1 ); - handleDirective( tokens ); - } else { - accumulator += buffer; - accumLines ++; - } +void T_InputReader_::read( ) +{ + size_t bsz( 0 ); + while ( ( readCount = getline( &buffer , &bsz , file ) ) != -1 ) { + line ++; + std::cmatch match; + if ( std::regex_match( buffer , match , PreprocDirective_ ) ) { + const T_Tokens_ tokens( ([](std::string const& a) { + using stri = std::istream_iterator< std::string >; + std::istringstream iss( a ); + return T_Tokens_{ stri( iss ) , stri( ) }; + })( match[ 1 ].str( ) ) ); + assert( tokens.size( ) >= 1 ); + handleDirective( tokens ); + } else { + accumulator += buffer; + accumLines ++; + } + } + addAccumulated( ); +} + +void T_InputReader_::nl( ) +{ + accumLines ++; + accumulator += '\n'; +} + +void T_InputReader_::addAccumulated( ) +{ + if ( accumLines ) { + auto& ck( input.chunks ); + ck.emplace_back( E_ShaderInputChunk::CODE , + std::move( accumulator ) , accumLines ); + accumulator = {}; + accumLines = 0; + } +} + +void T_InputReader_::handleDirective( + __rd__ T_Tokens_ const& tokens ) +{ + auto const& directive( tokens[ 0 ] ); + + if ( directive == "include" ) { + if ( tokens.size( ) != 2 ) { + nl( ); + error( "invalid arguments" ); + return; } addAccumulated( ); - } + auto& ck( input.chunks ); + ck.emplace_back( E_ShaderInputChunk::INCLUDE , tokens[ 1 ] , 1 ); - void T_InputReader_::nl( ) - { - accumLines ++; - accumulator += '\n'; - } - - void T_InputReader_::addAccumulated( ) - { - if ( accumLines ) { - auto& ck( input.chunks ); - ck.emplace_back( E_ShaderInputChunk::CODE , - std::move( accumulator ) , accumLines ); - accumulator = {}; - accumLines = 0; + } else if ( directive == "type" ) { + nl( ); + if ( tokens.size( ) != 2 ) { + error( "invalid arguments" ); + return; } - } - - void T_InputReader_::handleDirective( - __rd__ T_Tokens_ const& tokens ) - { - auto const& directive( tokens[ 0 ] ); - - if ( directive == "include" ) { - if ( tokens.size( ) != 2 ) { - nl( ); - error( "invalid arguments" ); - return; - } - addAccumulated( ); - auto& ck( input.chunks ); - ck.emplace_back( E_ShaderInputChunk::INCLUDE , tokens[ 1 ] , 1 ); - - } else if ( directive == "type" ) { - nl( ); - if ( tokens.size( ) != 2 ) { - error( "invalid arguments" ); - return; - } - auto pos( InputTypes_.find( tokens[ 1 ] ) ); - if ( pos == InputTypes_.end( ) ) { - error( "unknown type" ); - } else { - input.type = pos->second; - } - + auto pos( InputTypes_.find( tokens[ 1 ] ) ); + if ( pos == InputTypes_.end( ) ) { + error( "unknown type" ); } else { - nl( ); - error( "unknown directive" ); + input.type = pos->second; } - } - void T_InputReader_::error( - __rd__ std::string const& err ) - { - input.errors.push_back( T_ShaderInputError{ - line , err } ); + } else { + nl( ); + error( "unknown directive" ); } +} + +void T_InputReader_::error( + __rd__ std::string const& err ) +{ + input.errors.push_back( T_ShaderInputError{ + line , err } ); +} } // namespace