Web Wispers 1.2.2 C++ Unit Test Coverage
Current view: top level - ssrc/wispers/lua - Properties.cc (source / functions) Hit Total Coverage
Test: Web Wispers 1.2.2 C++ Unit Tests Lines: 89 106 84.0 %
Date: 2012-04-09 Functions: 12 13 92.3 %
Branches: 48 101 47.5 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright 2006-2009 Savarese Software Research Corporation
       3                 :            :  *
       4                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
       5                 :            :  * you may not use this file except in compliance with the License.
       6                 :            :  * You may obtain a copy of the License at
       7                 :            :  *
       8                 :            :  *     https://www.savarese.com/software/ApacheLicense-2.0
       9                 :            :  *
      10                 :            :  * Unless required by applicable law or agreed to in writing, software
      11                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
      12                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      13                 :            :  * See the License for the specific language governing permissions and
      14                 :            :  * limitations under the License.
      15                 :            :  */
      16                 :            : 
      17                 :            : #include <ssrc/wispers/lua/Properties.h>
      18                 :            : 
      19                 :            : __BEGIN_NS_SSRC_WSPR_LUA
      20                 :            : 
      21                 :          3 : void PropertiesToTable::PushValue::operator()(const primitive_property_vector & v) const
      22                 :            : {
      23                 :          3 :   lua_createtable(state, v.size(), 0);
      24                 :          3 :   int i = 1;
      25         [ +  + ]:         33 :   for(primitive_property_vector::const_iterator && it = v.begin(), && end = v.end(); it != end; ++it)
      26                 :            :   {
      27                 :         30 :     lua_pushinteger(state, i++);
      28                 :         30 :     boost::apply_visitor(*this, *it);
      29                 :         30 :     lua_settable(state, -3);
      30                 :            :   }
      31                 :          3 : }
      32                 :            : 
      33                 :         62 : void PropertiesToTable::PushValue::operator()(const Properties & properties)
      34                 :            :   const
      35                 :            : {
      36                 :            :   using NS_SSRC_WSPR_UTILITY::property_type;
      37                 :         62 :   const property_type *v = properties.value();
      38                 :            : 
      39         [ -  + ]:         62 :   if(properties.is_leaf()) {
      40         [ #  # ]:          0 :     if(v != 0) {
      41                 :          0 :       boost::apply_visitor(*this, *v);
      42                 :            :     } else {
      43                 :          0 :       lua_pushnil(state);
      44                 :            :     }
      45                 :            :   } else {
      46                 :         62 :     lua_newtable(state);
      47                 :            : 
      48         [ -  + ]:         62 :     if(v != 0) {
      49                 :          0 :       boost::apply_visitor(*this, *v);
      50                 :          0 :       lua_setfield(state, -2, "_value");
      51                 :            :     }
      52                 :            : 
      53                 :         62 :     properties.visit(to_table);
      54                 :            :   }
      55                 :         62 : }
      56                 :            : 
      57                 :         34 : void PropertiesToTable::PushValue::operator()(const property_vector & v) const
      58                 :            : {
      59                 :         34 :   lua_createtable(state, v.size(), 0);
      60                 :         34 :   int i = 1;
      61         [ +  + ]:         96 :   for(property_vector::const_iterator && it = v.begin(), && end = v.end(); it != end; ++it)
      62                 :            :   {
      63                 :         62 :     lua_pushinteger(state, i++);
      64                 :         62 :     PropertiesToTable::PushValue::operator()(*it);
      65                 :         62 :     lua_settable(state, -3);
      66                 :            :   }
      67                 :         34 : }
      68                 :            : 
      69                 :        125 : void PropertiesToTable::enter(const std::string key,
      70                 :            :                               const Properties *properties,
      71                 :            :                               const bool)
      72                 :            :   const
      73                 :            : {
      74                 :            :   using NS_SSRC_WSPR_UTILITY::property_type;
      75                 :        125 :   const property_type *v = properties->value();
      76                 :            : 
      77         [ +  + ]:        125 :   if(!properties->is_leaf()) {
      78                 :         13 :     lua_newtable(state());
      79                 :            : 
      80         [ -  + ]:         13 :     if(v != 0) {
      81                 :          0 :       boost::apply_visitor(push, *v);
      82                 :          0 :       lua_setfield(state(), -2, "_value");
      83                 :            :     }
      84                 :            :   } else {
      85         [ +  - ]:        112 :     if(v != 0) {
      86                 :        112 :       boost::apply_visitor(push, *v);
      87                 :            :     } else {
      88                 :          0 :       lua_pushnil(state());
      89                 :            :     }
      90                 :            :   }
      91                 :        125 : }
      92                 :            : 
      93                 :        125 : void PropertiesToTable::leave(const std::string key,
      94                 :            :                               const Properties *properties,
      95                 :            :                               const bool)
      96                 :            :   const
      97                 :            : {
      98                 :        125 :   lua_setfield(state(), -2, key.c_str());
      99                 :        125 : }
     100                 :            : 
     101                 :            : /**
     102                 :            :  * Copies a Lua table into a Properties instance.  Tables must either
     103                 :            :  * be pure arrays of primitive values, pure arrays of tables, or a
     104                 :            :  * zero-length table with key value pairs where all the keys are strings.
     105                 :            :  *
     106                 :            :  * @param state A pointer to the Lua state containing the table to convert
     107                 :            :  *        at the top of the stack.
     108                 :            :  * @param properties The Properties instance to convert.
     109                 :            :  */
     110                 :        161 : void table_to_properties(lua_State *state, Properties & properties) {
     111                 :        161 :   const size_t size = lua_objlen(state, -1);
     112                 :            : 
     113         [ +  + ]:        161 :   if(size == 0) {
     114                 :        141 :     lua_pushnil(state);
     115         [ +  + ]:        797 :     while(lua_next(state, -2)) {
     116                 :        515 :       const int ltype = lua_type(state, -1);
     117                 :       1030 :       const string && key = convert<string>(state, -2);
     118                 :            : 
     119                 :            :       // TODO: key == "_value" should use set_value(v) instead of set(v, k)
     120   [ +  +  +  +  :        515 :       switch(ltype) {
                      - ]
     121                 :            :       case LUA_TNUMBER:
     122   [ +  -  +  - ]:         35 :         properties.set(convert<lua_Number>(state, -1), key);
     123                 :         35 :         break;
     124                 :            :       case LUA_TBOOLEAN:
     125   [ +  -  +  - ]:          4 :         properties.set(convert<bool>(state, -1), key);
     126                 :          4 :         break;
     127                 :            :       case LUA_TSTRING:
     128   [ +  -  +  -  :        364 :         properties.set(convert<string>(state, -1), key);
          +  -  +  -  +  
                      - ]
     129                 :        364 :         break; 
     130                 :            :       case LUA_TTABLE: {
     131         [ +  - ]:        112 :         Properties *node = properties.create_node(key);
     132         [ +  - ]:        112 :         table_to_properties(state, *node);
     133                 :            :       }
     134                 :        112 :         break;
     135                 :            :       default:
     136                 :          0 :         break;
     137                 :            :       };
     138                 :            : 
     139         [ +  - ]:        515 :       lua_pop(state, 1);
     140                 :            :     }
     141                 :            :   } else {
     142                 :         20 :     lua_pushnil(state);
     143                 :            :     // Determine type of array elements (primitive or table).
     144         [ +  - ]:         20 :     if(lua_next(state, -2)) {
     145         [ +  + ]:         20 :       if(lua_istable(state, -1)) {
     146                 :            :         Properties *node;
     147                 :         15 :         property_vector & v = properties.create_property_vector();
     148                 :         15 :         v.reserve(size);
     149         [ +  + ]:         28 :         do {
     150         [ +  - ]:         28 :           v.push_back(node = new Properties);
     151                 :         28 :           table_to_properties(state, *node);
     152                 :         28 :           lua_pop(state, 1);
     153                 :         28 :         } while(lua_next(state, -2));
     154                 :            :       } else {
     155                 :            :         primitive_property_vector & v =
     156                 :          5 :           properties.create_primitive_property_vector();
     157                 :          5 :         v.reserve(size);
     158         [ +  + ]:         22 :         do {
     159                 :         22 :           const int ltype = lua_type(state, -1);
     160   [ +  -  -  - ]:         22 :           switch(ltype) {
     161         [ +  - ]:         22 :           case LUA_TNUMBER: v.push_back(convert<lua_Number>(state, -1)); break;
     162         [ #  # ]:          0 :           case LUA_TBOOLEAN: v.push_back(convert<bool>(state, -1)); break;
     163   [ #  #  #  #  :          0 :           case LUA_TSTRING: v.push_back(convert<string>(state, -1)); break;
                   #  # ]
     164                 :          0 :           default: break;
     165                 :            :           };
     166                 :         22 :           lua_pop(state, 1);
     167                 :         22 :         } while(lua_next(state, -2));
     168                 :            :       }
     169                 :            :     }
     170                 :            :   }
     171                 :        161 : }
     172                 :            : 
     173                 :            : /**
     174                 :            :  * This function is a kluge to work around a SWIG library relocation error.
     175                 :            :  * For some reason, table_to_properties doesn't resolve when called within
     176                 :            :  * a SWIG wrapper function.  Removing lua_State* from the function signature
     177                 :            :  * allows the function to be located, which then resolves table_to_properties
     178                 :            :  * within the same relocation unit instead of crossing module boundaries.
     179                 :            :  */
     180                 :          1 : void swig_table_to_properties(void *state, Properties & properties) {
     181                 :          1 :   table_to_properties(reinterpret_cast<lua_State*>(state), properties);
     182                 :          1 : }
     183                 :            : 
     184                 :            : namespace {
     185                 :         20 :   inline properties_ptr load_properties(lua_State *state, int err)
     186                 :            :     SSRC_DECL_THROW(LuaCallError)
     187                 :            :   {
     188         [ -  + ]:         20 :     if(err != 0) {
     189   [ #  #  #  # ]:          0 :       string msg(lua_tostring(state, -1));
     190         [ #  # ]:          0 :       lua_pop(state, 1);
     191         [ #  # ]:          0 :       throw LuaCallError(msg, err);
     192                 :            :     }
     193                 :            : 
     194                 :         20 :     pcall_nopop(0, LUA_MULTRET, state);
     195                 :            : 
     196         [ -  + ]:         20 :     if(!lua_istable(state, -1)) {
     197                 :          0 :       lua_pop(state, 1);
     198                 :            :       throw LuaCallError("properties definition does not return table",
     199   [ #  #  #  # ]:          0 :                          LUA_ERRSYNTAX);
     200                 :            :     }
     201                 :            : 
     202   [ +  -  +  - ]:         20 :     properties_ptr properties(new Properties);
     203                 :            : 
     204         [ +  - ]:         20 :     table_to_properties(state, *properties);
     205         [ +  - ]:         20 :     lua_pop(state, 1);
     206                 :            :   
     207                 :         20 :     return properties;
     208                 :            :   }
     209                 :            : }
     210                 :            : 
     211                 :         18 : properties_ptr load_properties(lua_State *state, const std::string & filename)
     212                 :            :   SSRC_DECL_THROW(LuaCallError)
     213                 :            : {
     214                 :         18 :   int err = luaL_loadfile(state, filename.c_str());
     215                 :         18 :   return load_properties(state, err);
     216                 :            : }
     217                 :            : 
     218                 :          2 : properties_ptr load_string_properties(lua_State *state,
     219                 :            :                                       const std::string & code_str)
     220                 :            :   SSRC_DECL_THROW(LuaCallError)
     221                 :            : {
     222                 :          2 :   int err = luaL_loadstring(state, code_str.c_str());
     223                 :          2 :   return load_properties(state, err);
     224                 :            : }
     225                 :            : 
     226   [ +  -  +  - ]:         18 : __END_NS_SSRC_WSPR_LUA