Savarese Software Research Corporation
Properties.cc
Go to the documentation of this file.
00001 /*
00002  * Copyright 2006-2009 Savarese Software Research Corporation
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     https://www.savarese.com/software/ApacheLicense-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #include <ssrc/wispers/lua/Properties.h>
00018 
00019 __BEGIN_NS_SSRC_WSPR_LUA
00020 
00021 void PropertiesToTable::PushValue::operator()(const primitive_property_vector & v) const
00022 {
00023   lua_createtable(state, v.size(), 0);
00024   int i = 1;
00025   for(primitive_property_vector::const_iterator && it = v.begin(), && end = v.end(); it != end; ++it)
00026   {
00027     lua_pushinteger(state, i++);
00028     boost::apply_visitor(*this, *it);
00029     lua_settable(state, -3);
00030   }
00031 }
00032 
00033 void PropertiesToTable::PushValue::operator()(const Properties & properties)
00034   const
00035 {
00036   using NS_SSRC_WSPR_UTILITY::property_type;
00037   const property_type *v = properties.value();
00038 
00039   if(properties.is_leaf()) {
00040     if(v != 0) {
00041       boost::apply_visitor(*this, *v);
00042     } else {
00043       lua_pushnil(state);
00044     }
00045   } else {
00046     lua_newtable(state);
00047 
00048     if(v != 0) {
00049       boost::apply_visitor(*this, *v);
00050       lua_setfield(state, -2, "_value");
00051     }
00052 
00053     properties.visit(to_table);
00054   }
00055 }
00056 
00057 void PropertiesToTable::PushValue::operator()(const property_vector & v) const
00058 {
00059   lua_createtable(state, v.size(), 0);
00060   int i = 1;
00061   for(property_vector::const_iterator && it = v.begin(), && end = v.end(); it != end; ++it)
00062   {
00063     lua_pushinteger(state, i++);
00064     PropertiesToTable::PushValue::operator()(*it);
00065     lua_settable(state, -3);
00066   }
00067 }
00068 
00069 void PropertiesToTable::enter(const std::string key,
00070                               const Properties *properties,
00071                               const bool)
00072   const
00073 {
00074   using NS_SSRC_WSPR_UTILITY::property_type;
00075   const property_type *v = properties->value();
00076 
00077   if(!properties->is_leaf()) {
00078     lua_newtable(state());
00079 
00080     if(v != 0) {
00081       boost::apply_visitor(push, *v);
00082       lua_setfield(state(), -2, "_value");
00083     }
00084   } else {
00085     if(v != 0) {
00086       boost::apply_visitor(push, *v);
00087     } else {
00088       lua_pushnil(state());
00089     }
00090   }
00091 }
00092 
00093 void PropertiesToTable::leave(const std::string key,
00094                               const Properties *properties,
00095                               const bool)
00096   const
00097 {
00098   lua_setfield(state(), -2, key.c_str());
00099 }
00100 
00110 void table_to_properties(lua_State *state, Properties & properties) {
00111   const size_t size = lua_objlen(state, -1);
00112 
00113   if(size == 0) {
00114     lua_pushnil(state);
00115     while(lua_next(state, -2)) {
00116       const int ltype = lua_type(state, -1);
00117       const string && key = convert<string>(state, -2);
00118 
00119       // TODO: key == "_value" should use set_value(v) instead of set(v, k)
00120       switch(ltype) {
00121       case LUA_TNUMBER:
00122         properties.set(convert<lua_Number>(state, -1), key);
00123         break;
00124       case LUA_TBOOLEAN:
00125         properties.set(convert<bool>(state, -1), key);
00126         break;
00127       case LUA_TSTRING:
00128         properties.set(convert<string>(state, -1), key);
00129         break; 
00130       case LUA_TTABLE: {
00131         Properties *node = properties.create_node(key);
00132         table_to_properties(state, *node);
00133       }
00134         break;
00135       default:
00136         break;
00137       };
00138 
00139       lua_pop(state, 1);
00140     }
00141   } else {
00142     lua_pushnil(state);
00143     // Determine type of array elements (primitive or table).
00144     if(lua_next(state, -2)) {
00145       if(lua_istable(state, -1)) {
00146         Properties *node;
00147         property_vector & v = properties.create_property_vector();
00148         v.reserve(size);
00149         do {
00150           v.push_back(node = new Properties);
00151           table_to_properties(state, *node);
00152           lua_pop(state, 1);
00153         } while(lua_next(state, -2));
00154       } else {
00155         primitive_property_vector & v =
00156           properties.create_primitive_property_vector();
00157         v.reserve(size);
00158         do {
00159           const int ltype = lua_type(state, -1);
00160           switch(ltype) {
00161           case LUA_TNUMBER: v.push_back(convert<lua_Number>(state, -1)); break;
00162           case LUA_TBOOLEAN: v.push_back(convert<bool>(state, -1)); break;
00163           case LUA_TSTRING: v.push_back(convert<string>(state, -1)); break;
00164           default: break;
00165           };
00166           lua_pop(state, 1);
00167         } while(lua_next(state, -2));
00168       }
00169     }
00170   }
00171 }
00172 
00180 void swig_table_to_properties(void *state, Properties & properties) {
00181   table_to_properties(reinterpret_cast<lua_State*>(state), properties);
00182 }
00183 
00184 namespace {
00185   inline properties_ptr load_properties(lua_State *state, int err)
00186     SSRC_DECL_THROW(LuaCallError)
00187   {
00188     if(err != 0) {
00189       string msg(lua_tostring(state, -1));
00190       lua_pop(state, 1);
00191       throw LuaCallError(msg, err);
00192     }
00193 
00194     pcall_nopop(0, LUA_MULTRET, state);
00195 
00196     if(!lua_istable(state, -1)) {
00197       lua_pop(state, 1);
00198       throw LuaCallError("properties definition does not return table",
00199                          LUA_ERRSYNTAX);
00200     }
00201 
00202     properties_ptr properties(new Properties);
00203 
00204     table_to_properties(state, *properties);
00205     lua_pop(state, 1);
00206   
00207     return properties;
00208   }
00209 }
00210 
00211 properties_ptr load_properties(lua_State *state, const std::string & filename)
00212   SSRC_DECL_THROW(LuaCallError)
00213 {
00214   int err = luaL_loadfile(state, filename.c_str());
00215   return load_properties(state, err);
00216 }
00217 
00218 properties_ptr load_string_properties(lua_State *state,
00219                                       const std::string & code_str)
00220   SSRC_DECL_THROW(LuaCallError)
00221 {
00222   int err = luaL_loadstring(state, code_str.c_str());
00223   return load_properties(state, err);
00224 }
00225 
00226 __END_NS_SSRC_WSPR_LUA

Savarese Software Research Corporation
Copyright © 2006-2011 Savarese Software Research Corporation. All rights reserved.