2017-09-01 08:47:09 +08:00
// The MIT License (MIT)
// Copyright (c) 2013-2017 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# ifndef SOL_ERROR_HANDLER_HPP
# define SOL_ERROR_HANDLER_HPP
# include "types.hpp"
2017-09-06 08:29:21 +08:00
# include "demangle.hpp"
2017-09-01 08:47:09 +08:00
namespace sol {
inline int type_panic_string ( lua_State * L , int index , type expected , type actual , const std : : string & message = " " ) noexcept ( false ) {
const char * err = message . empty ( ) ? " stack index %d, expected %s, received %s " : " stack index %d, expected %s, received %s with message %s " ;
return luaL_error ( L , err , index ,
expected = = type : : poly ? " anything " : lua_typename ( L , static_cast < int > ( expected ) ) ,
actual = = type : : poly ? " anything " : lua_typename ( L , static_cast < int > ( actual ) ) ,
message . c_str ( )
) ;
}
inline int type_panic_c_str ( lua_State * L , int index , type expected , type actual , const char * message = nullptr ) noexcept ( false ) {
const char * err = message = = nullptr | | ( std : : char_traits < char > : : length ( message ) = = 0 ) ? " stack index %d, expected %s, received %s " : " stack index %d, expected %s, received %s with message %s " ;
return luaL_error ( L , err , index ,
expected = = type : : poly ? " anything " : lua_typename ( L , static_cast < int > ( expected ) ) ,
actual = = type : : poly ? " anything " : lua_typename ( L , static_cast < int > ( actual ) ) ,
message
) ;
}
struct type_panic_t {
int operator ( ) ( lua_State * L , int index , type expected , type actual ) const noexcept ( false ) {
return type_panic_c_str ( L , index , expected , actual , nullptr ) ;
}
int operator ( ) ( lua_State * L , int index , type expected , type actual , const char * message ) const noexcept ( false ) {
return type_panic_c_str ( L , index , expected , actual , message ) ;
}
int operator ( ) ( lua_State * L , int index , type expected , type actual , const std : : string & message ) const noexcept ( false ) {
return type_panic_string ( L , index , expected , actual , message ) ;
}
} ;
const type_panic_t type_panic = { } ;
struct constructor_handler {
int operator ( ) ( lua_State * L , int index , type expected , type actual , const std : : string & message ) const noexcept ( false ) {
return type_panic_string ( L , index , expected , actual , message + " (type check failed in constructor) " ) ;
}
} ;
2017-09-06 01:58:17 +08:00
template < typename F = void >
2017-09-01 08:47:09 +08:00
struct argument_handler {
int operator ( ) ( lua_State * L , int index , type expected , type actual , const std : : string & message ) const noexcept ( false ) {
return type_panic_string ( L , index , expected , actual , message + " (bad argument to variable or function call) " ) ;
}
} ;
2017-09-06 01:58:17 +08:00
template < typename R , typename . . . Args >
struct argument_handler < types < R , Args . . . > > {
int operator ( ) ( lua_State * L , int index , type expected , type actual , const std : : string & message ) const noexcept ( false ) {
std : : string addendum = " (bad argument to type expecting ' " ;
addendum + = detail : : demangle < R > ( ) ;
addendum + = " ( " ;
int marker = 0 ;
auto action = [ & addendum , & marker ] ( const std : : string & n ) {
if ( marker > 0 ) {
addendum + = " , " ;
}
addendum + = n ;
+ + marker ;
2017-09-06 09:07:33 +08:00
} ;
2017-09-06 01:58:17 +08:00
( void ) detail : : swallow { int ( ) , ( action ( detail : : demangle < Args > ( ) ) , int ( ) ) . . . } ;
addendum + = " )') " ;
return type_panic_string ( L , index , expected , actual , message + addendum ) ;
}
} ;
2017-09-01 08:47:09 +08:00
// Specify this function as the handler for lua::check if you know there's nothing wrong
inline int no_panic ( lua_State * , int , type , type , const char * = nullptr ) noexcept {
return 0 ;
}
inline void type_error ( lua_State * L , int expected , int actual ) noexcept ( false ) {
luaL_error ( L , " expected %s, received %s " , lua_typename ( L , expected ) , lua_typename ( L , actual ) ) ;
}
inline void type_error ( lua_State * L , type expected , type actual ) noexcept ( false ) {
type_error ( L , static_cast < int > ( expected ) , static_cast < int > ( actual ) ) ;
}
inline void type_assert ( lua_State * L , int index , type expected , type actual ) noexcept ( false ) {
if ( expected ! = type : : poly & & expected ! = actual ) {
type_panic_c_str ( L , index , expected , actual , nullptr ) ;
}
}
inline void type_assert ( lua_State * L , int index , type expected ) {
type actual = type_of ( L , index ) ;
type_assert ( L , index , expected , actual ) ;
}
} // sol
# endif // SOL_ERROR_HANDLER_HPP