QLua
Lua-Qt bindings
LuaQtTypes.h
Go to the documentation of this file.
00001 #pragma once
00002 // QLua - Copyright (c) 2012, Ugo Varetto
00003 // All rights reserved.
00004 //
00005 // Redistribution and use in source and binary forms, with or without
00006 // modification, are permitted provided that the following conditions are met:
00007 //     * Redistributions of source code must retain the above copyright
00008 //       notice, this list of conditions and the following disclaimer.
00009 //     * Redistributions in binary form must reproduce the above copyright
00010 //       notice, this list of conditions and the following disclaimer in the
00011 //       documentation and/or other materials provided with the distribution.
00012 //     * Neither the name of the <organization> nor the
00013 //       names of its contributors may be used to endorse or promote products
00014 //       derived from this software without specific prior written permission.
00015 //
00016 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00017 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00018 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00019 // DISCLAIMED. IN NO EVENT SHALL UGO VARETTO BE LIABLE FOR ANY
00020 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00021 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00022 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00023 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00024 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00025 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026 
00029 
00030 extern "C" {
00031 #include "lua.h"
00032 #include "lauxlib.h"
00033 #include "lualib.h"
00034 }
00035 
00036 #include <iostream>
00037 #include <string>
00038 
00039 #include <QString>
00040 #include <QVariant>
00041 #include <QVariantMap>
00042 #include <QGenericArgument>
00043 #include <QList>
00044 #include <QVector>
00045 
00046 #define QLUA_LIST_FLOAT64 "QList<double>"
00047 #define QLUA_LIST_FLOAT32 "QList<float>"
00048 #define QLUA_LIST_INT "QList<int>"
00049 #define QLUA_LIST_SHORT "QList<short>"
00050 #define QLUA_VECTOR_FLOAT64 "QVector<double>"
00051 #define QLUA_VECTOR_FLOAT32 "QVector<float>"
00052 #define QLUA_VECTOR_INT "QVector<int>"
00053 #define QLUA_VECTOR_SHORT "QVector<short>"
00054 #define QLUA_STRING_LIST "QList<QString>"
00055 
00057 namespace qlua {
00058 
00059 //------------------------------------------------------------------------------
00060 template < typename T > const char* TypeName();
00061 
00062 template <> inline const char* TypeName< QList< double > >() { return QLUA_LIST_FLOAT64; }
00063 template <> inline const char* TypeName< QList< float > >() { return QLUA_LIST_FLOAT32; }
00064 template <> inline const char* TypeName< QList< int > >() { return QLUA_LIST_INT; }
00065 template <> inline const char* TypeName< QList< short > >() { return QLUA_LIST_SHORT; }
00066 template <> inline const char* TypeName< QVector< double > >() { return QLUA_VECTOR_FLOAT64; }
00067 template <> inline const char* TypeName< QVector< float > >() { return QLUA_VECTOR_FLOAT32; }
00068 template <> inline const char* TypeName< QVector< int > >() { return QLUA_VECTOR_INT; }
00069 template <> inline const char* TypeName< QVector< short > >() { return QLUA_VECTOR_SHORT; }
00070 template <> inline const char* TypeName< QList< QString > >() { return QLUA_STRING_LIST; }
00071 
00072 //------------------------------------------------------------------------------
00073 inline
00074 QString LuaKeyToQString( lua_State* L, int idx ) {
00075     if( lua_isnumber( L, idx ) ) {
00076         return QString( "%1" ).arg( lua_tointeger( L, idx ) );
00077     } else if( lua_isstring( L, idx ) ) {
00078         return lua_tostring( L, idx );
00079     } else return "";
00080 }
00081 
00082 //------------------------------------------------------------------------------
00083 template < typename ToT, typename FromT >
00084 bool ConvertibleTo( FromT v ) {
00085     return FromT( ToT( v ) ) == v;
00086 }
00087 
00088 //==============================================================================
00089 // Lua -> C++
00090 
00091 //------------------------------------------------------------------------------
00095 inline
00096 QVariant LuaValueToQVariant( lua_State* L, int idx ) {
00097     if( lua_isboolean( L, idx ) ) {
00098         return bool( lua_toboolean( L, idx ) );
00099     } else if( lua_isnumber( L, idx ) ) {   
00100 #ifdef QLUA_CONVERT_NUMBER
00101         const double N = lua_tonumber( L, idx );
00102         if( ConvertibleTo< int >( N ) ) return int( N );
00103         else if( ConvertibleTo< unsigned int >( N ) ) return (unsigned int)( N );
00104         else if( ConvertibleTo< long long >( N ) ) return long( N );
00105         else if( ConvertibleTo< unsigned long long >( N ) ) return (unsigned long long)( N );
00106         else if( ConvertibleTo< float >( N ) ) return float( N );
00107         else return N;
00108 #else
00109         return lua_tonumber( L, idx );
00110 #endif
00111     } else if( lua_islightuserdata( L, idx ) ) {
00112         return lua_topointer( L, idx ); 
00113     } else if( lua_isstring( L, idx ) ) {
00114         return lua_tostring( L, idx );
00115     } else return QVariant();
00116 }
00117 
00118 //------------------------------------------------------------------------------
00123 template < typename T >
00124 QList< T > ParseLuaTableAsNumberList( lua_State* L, int stackTableIndex ) {
00125       luaL_checktype( L, stackTableIndex, LUA_TTABLE );
00126 #if LUA_VERSION_NUM > 501 
00127     int tableSize = int( lua_rawlen( L, stackTableIndex ) );
00128 #else
00129     int tableSize = int( lua_objlen( L, stackTableIndex ) );
00130 #endif
00131     QList< T > list;
00132     list.reserve( int( tableSize ) );
00133     ++tableSize;
00134     for( int i = 1; i != tableSize; ++i ) {
00135         lua_rawgeti( L, stackTableIndex, i );
00136         list.push_back( T( lua_tonumber( L, -1 ) ) );
00137         lua_pop( L, 1 );
00138     }
00139     return list;
00140 }
00141 //------------------------------------------------------------------------------
00146 inline
00147 QStringList ParseLuaTableAsStringList( lua_State* L, int stackTableIndex ) {
00148       luaL_checktype( L, stackTableIndex, LUA_TTABLE );
00149 #if LUA_VERSION_NUM > 501 
00150     int tableSize = int( lua_rawlen( L, stackTableIndex ) );
00151 #else
00152     int tableSize = int( lua_objlen( L, stackTableIndex ) );
00153 #endif
00154     QStringList list;
00155     list.reserve( int( tableSize ) );
00156     ++tableSize;
00157     for( int i = 1; i != tableSize; ++i ) {
00158         lua_rawgeti( L, stackTableIndex, i );
00159         list.push_back( QString( lua_tostring( L, -1 ) ) );
00160         lua_pop( L, 1 );
00161     }
00162     return list;
00163 }
00164 //------------------------------------------------------------------------------
00169 template < typename T >
00170 QVector< T > ParseLuaTableAsNumberVector( lua_State* L, int stackTableIndex ) {
00171 #if LUA_VERSION_NUM > 501 
00172     int tableSize = int( lua_rawlen( L, stackTableIndex ) );
00173 #else
00174     int tableSize = int( lua_objlen( L, stackTableIndex ) );
00175 #endif
00176     QVector< T > v;
00177     v.resize( int( tableSize ) );
00178     ++tableSize;
00179     typename QVector< T >::iterator vi = v.begin();
00180     for( int i = 1; i != tableSize; ++i, ++vi ) {
00181         lua_rawgeti( L, stackTableIndex, i );
00182         *vi = T( lua_tonumber( L, -1 ) );
00183         lua_pop( L, 1 );
00184     }
00185     return v;
00186 }
00187 
00188 //------------------------------------------------------------------------------
00196 inline
00197 QVariantMap ParseLuaTable( lua_State* L, int stackTableIndex, bool removeTable = true ) {
00198     luaL_checktype( L, stackTableIndex, LUA_TTABLE );
00199     QVariantMap m;
00200     lua_pushnil(L);  // first key
00201     stackTableIndex = stackTableIndex < 0 ? stackTableIndex - 1 : stackTableIndex;
00202     while( lua_next( L, stackTableIndex ) != 0 ) {
00203         /* uses 'key' (at index -2) and 'value' (at index -1) */
00204         QString key = LuaKeyToQString( L, -2 );
00205         QVariant value = lua_istable( L, -1 ) ? ParseLuaTable( L, -1, false ) : 
00206                          LuaValueToQVariant( L, -1 );
00207         m[ key ] = value;
00208         lua_pop(L, 1);
00209     }
00210     if( removeTable ) lua_pop( L, 1 ); // remvove table
00211     return m;
00212 }
00213 //------------------------------------------------------------------------------
00218 inline
00219 QVariantList ParseLuaTableAsVariantList( lua_State* L, int stackTableIndex ) {
00220     luaL_checktype( L, stackTableIndex, LUA_TTABLE );
00221     QVariantList l;
00222     lua_pushnil(L);  // first key
00223     stackTableIndex = stackTableIndex < 0 ? stackTableIndex - 1 : stackTableIndex;
00224     while( lua_next( L, stackTableIndex ) != 0 ) {
00225         /* uses 'key' (at index -2) and 'value' (at index -1) */
00226         QVariant value = lua_istable( L, -1 ) ? ParseLuaTable( L, -1, false ) : 
00227                          LuaValueToQVariant( L, -1 );
00228         l.push_back( value );
00229         lua_pop(L, 1);
00230     }
00231     return l;
00232 }
00233 
00234 
00235 //=============================================================================
00236 // C++ -> Lua
00237 
00238 void VariantMapToLuaTable( const QVariantMap&, lua_State* );
00239 void VariantListToLuaTable( const QVariantList&, lua_State* );
00240 
00241 //------------------------------------------------------------------------------
00246 inline
00247 void VariantToLuaValue( const QVariant& v, lua_State* L ) {
00248 
00249     switch( v.type() ) {
00250         case QVariant::Map: VariantMapToLuaTable( v.toMap(), L );
00251                             break;
00252         case QVariant::List: VariantListToLuaTable( v.toList(), L );
00253                              break;
00254         case QVariant::String: lua_pushstring( L, v.toString().toAscii().constData() );
00255                                break; 
00256         case QVariant::Int: lua_pushinteger( L, v.toInt() );
00257                             break;
00258         case QVariant::UInt: lua_pushnumber( L, v.toUInt() );
00259                              break;
00260         case QVariant::LongLong: lua_pushnumber( L, v.toLongLong() );
00261                                  break;
00262         case QVariant::ULongLong: lua_pushnumber( L, v.toULongLong() );
00263                                   break;
00264         case QVariant::Bool: lua_pushboolean( L, v.toBool() );
00265                              break;
00266         case QVariant::Double: lua_pushnumber( L, v.toDouble() );
00267                                break;
00268         default: break;
00269     }
00270 }
00271 
00272 //------------------------------------------------------------------------------
00277 inline
00278 void VariantMapToLuaTable( const QVariantMap& vm, lua_State* L ) {
00279     lua_newtable( L ); 
00280     for( QVariantMap::const_iterator i = vm.begin(); i != vm.end(); ++i ) {
00281         lua_pushstring( L, i.key().toAscii().constData() );
00282         VariantToLuaValue( i.value(), L );
00283         lua_rawset( L, -3 );
00284     }
00285 }
00286 //------------------------------------------------------------------------------
00291 inline
00292 void VariantListToLuaTable( const QVariantList& vl, lua_State* L ) {
00293     lua_newtable( L ); 
00294     int i = 1;
00295     for( QVariantList::const_iterator v = vl.begin(); v != vl.end(); ++v, ++i ) {
00296         lua_pushinteger( L, i );
00297         VariantToLuaValue( *v, L );
00298         lua_rawset( L, -3 );
00299     }
00300 }
00301 //------------------------------------------------------------------------------
00306 template < typename T >
00307 void NumberListToLuaTable( const QList< T >& l, lua_State* L ) {
00308     lua_newtable( L ); 
00309     int i = 1;
00310     for( typename QList< T >::const_iterator v = l.begin(); v != l.end(); ++v, ++i ) {
00311         lua_pushnumber( L, *v );
00312         lua_rawseti( L, -2, i );
00313     }
00314 }
00315 //------------------------------------------------------------------------------
00320 template < typename T >
00321 void NumberVectorToLuaTable( const QVector< T >& v, lua_State* L ) {
00322     lua_newtable( L ); 
00323     int i = 1;
00324     for( typename QVector< T >::const_iterator vi = v.begin(); vi != v.end(); ++vi, ++i ) {
00325         lua_pushnumber( L, *vi );
00326         lua_rawseti( L, -2, i );
00327     }
00328 }
00329 //------------------------------------------------------------------------------
00334 inline
00335 void StringListToLuaTable( const QStringList& sl, lua_State* L ) {
00336     lua_newtable( L ); 
00337     int i = 1;
00338     for( QStringList::const_iterator v = sl.begin(); v != sl.end(); ++v, ++i ) {
00339         lua_pushinteger( L, i );
00340         lua_pushstring( L, v->toAscii().constData() );
00341         lua_rawset( L, -3 );
00342     }
00343 }
00344 }
 All Classes Namespaces Files Functions Variables Enumerations Enumerator