script_read.cpp

Go to the documentation of this file.
00001 
00002 //            Copyright (C) 2004-2007 by The Allacrost Project
00003 //                         All Rights Reserved
00004 //
00005 // This code is licensed under the GNU GPL version 2. It is free software
00006 // and you may modify it and/or redistribute it under the terms of this license.
00007 // See http://www.gnu.org/copyleft/gpl.html for details.
00009 
00017 #include "utils.h"
00018 
00019 #include "script.h"
00020 #include "script_read.h"
00021 
00022 using namespace std;
00023 using namespace luabind;
00024 
00025 using namespace hoa_utils;
00026 using namespace hoa_script::private_script;
00027 
00028 namespace hoa_script {
00029 
00030 ReadScriptDescriptor::~ReadScriptDescriptor() {
00031   if (IsFileOpen()) {
00032     if (SCRIPT_DEBUG)
00033       cerr << "SCRIPT WARNING: ReadScriptDescriptor destructor was called when file was still open: "
00034         << _filename << endl;
00035     CloseFile();
00036   }
00037   
00038   _filename = "";
00039   _access_mode = SCRIPT_CLOSED;
00040   _error_messages.clear();
00041   _open_tables.clear();
00042 }
00043 
00044 //-----------------------------------------------------------------------------
00045 // File Access Functions
00046 //-----------------------------------------------------------------------------
00047 
00048 bool ReadScriptDescriptor::OpenFile(const string& file_name) {
00049   if (ScriptManager->IsFileOpen(file_name) == true) {
00050     if (SCRIPT_DEBUG)
00051       cerr << "SCRIPT WARNING: ReadScriptDescriptor::OpenFile() attempted to open file that is already opened: "
00052         << file_name << endl;
00053     return false;
00054   }
00055 
00056   // Increases the global stack size by 1 element. That is needed because the new thread will be pushed in the
00057   // stack and we have to be sure there is enough space there.
00058   lua_checkstack(ScriptManager->GetGlobalState(),1);
00059   _lstack = lua_newthread(ScriptManager->GetGlobalState());
00060 
00061   // Attempt to load the Lua file.
00062   if (lua_dofile(_lstack, file_name.c_str()) != 0) {
00063     cerr << "SCRIPT ERROR: ReadScriptDescriptor::OpenFile() could not open the file " << file_name << endl;
00064     _access_mode = SCRIPT_CLOSED;
00065     return false;
00066   }
00067 
00068   _filename = file_name;
00069   _access_mode = SCRIPT_READ;
00070   ScriptManager->_AddOpenFile(this);
00071   return true;
00072 } // bool ReadScriptDescriptor::OpenFile(string file_name)
00073 
00074 
00075 
00076 bool ReadScriptDescriptor::OpenFile() {
00077   if (_filename == "") {
00078     if (SCRIPT_DEBUG)
00079       cerr << "SCRIPT ERROR: ReadScriptDescriptor::OpenFile(), could not open file "
00080         << "because of an invalid file name (empty string)." << endl;
00081     return false;
00082   }
00083 
00084   return OpenFile(_filename);
00085 }
00086 
00087 
00088 
00089 void ReadScriptDescriptor::CloseFile() {
00090   if (IsFileOpen() == false) {
00091     if (SCRIPT_DEBUG)
00092       cerr << "SCRIPT ERROR: ReadScriptDescriptor::CloseFile() could not close the "
00093         << "file because it was not open." << endl;
00094     return;
00095   }
00096 
00097   if (SCRIPT_DEBUG && IsErrorDetected()) {
00098     cerr << "SCRIPT WARNING: In ReadScriptDescriptor::CloseFile(), the file " << _filename
00099       << " had error messages remaining. They are as follows:" << endl;
00100     cerr << _error_messages.str() << endl;
00101   }
00102 
00103   _lstack = NULL;
00104   _error_messages.clear();
00105   _open_tables.clear();
00106   _access_mode = SCRIPT_CLOSED;
00107   ScriptManager->_RemoveOpenFile(this);
00108 }
00109 
00110 //-----------------------------------------------------------------------------
00111 // Existence Checking Functions
00112 //-----------------------------------------------------------------------------
00113 
00114 bool ReadScriptDescriptor::_DoesDataExist(const string& key, int32 type) {
00115   // Check whether the user is trying to read a global variable or one stored in a table
00116   if (_open_tables.size() == 0) { // Variable is a global
00117     lua_getglobal(_lstack, key.c_str());
00118     luabind::object o(luabind::from_stack(_lstack, private_script::STACK_TOP));
00119     return _CheckDataType(type, o);
00120   }
00121 
00122   else { // Variable is a member of a table
00123     luabind::object o(luabind::from_stack(_lstack, private_script::STACK_TOP));
00124     if (luabind::type(o) != LUA_TTABLE) {
00125       _error_messages << "* _DoesDataExist() failed because the top of the stack was not "
00126         << "a table when trying to check for the table member: " << key << endl;
00127       return false;
00128     }
00129 
00130     luabind::object obj(o[key]);
00131     return _CheckDataType(type, obj);
00132   }
00133 }
00134 
00135 
00136 
00137 bool ReadScriptDescriptor::_DoesDataExist(int32 key, int32 type) {
00138   if (_open_tables.size() == 0) {
00139     _error_messages << "* _DoesDataExist() failed because no tables were open when trying to "
00140       << "examine the table member: " << key << endl;
00141     return false;
00142   }
00143 
00144   luabind::object o(luabind::from_stack(_lstack, private_script::STACK_TOP));
00145   if (luabind::type(o) != LUA_TTABLE) {
00146     _error_messages << "* _DoesDataExist() failed because the top of the stack was not "
00147       << "a table when trying to check for the table member: " << key << endl;
00148     return false;
00149   }
00150 
00151   luabind::object obj(o[key]);
00152   return _CheckDataType(type, obj);
00153 }
00154 
00155 
00156 
00157 bool ReadScriptDescriptor::_CheckDataType(int32 type, luabind::object& obj_check) {
00158   int32 object_type = luabind::type(obj_check);
00159 
00160   if (obj_check.is_valid() == false)
00161     return false;
00162 
00163   // When this type is passed to the function, we don't care what type the object is as long
00164   // as it was seen to be something
00165   if (type == LUA_TNIL) {
00166     return true;
00167   }
00168 
00169   // Simple type comparison is all that is needed for all non-numeric types
00170   else if (type == object_type) {
00171     return true;
00172   }
00173 
00174   // Because Lua only has a "number" type, we have to do perform a special cast 
00175   // to examine integer versus floating point types
00176   else if (object_type == LUA_TNUMBER) {
00177     if (type == INTEGER_TYPE) {
00178       try {
00179         luabind::object_cast<int32>(obj_check);
00180         lua_pop(_lstack, 1);
00181         return true;
00182       }
00183       catch (...) {
00184         return false;
00185       }
00186     }
00187     else if (type == UINTEGER_TYPE) {
00188       try {
00189         luabind::object_cast<uint32>(obj_check);
00190         lua_pop(_lstack, 1);
00191         return true;
00192       }
00193       catch (...) {
00194         return false;
00195       }
00196     }
00197     else if (type == FLOAT_TYPE) {
00198       try {
00199         luabind::object_cast<float>(obj_check);
00200         lua_pop(_lstack, 1);
00201         return true;
00202       }
00203       catch (...) {
00204         return false;
00205       }
00206     }
00207   }
00208 
00209   else {
00210     return false;
00211   }
00212 } // bool ReadScriptDescriptor::_CheckDataType(int32 type, luabind::object& obj_check)
00213 
00214 //-----------------------------------------------------------------------------
00215 // Function Pointer Read Functions
00216 //-----------------------------------------------------------------------------
00217 
00218 object ReadScriptDescriptor::ReadFunctionPointer(const string& key) {
00219   if (_open_tables.size() == 0) { // The function should be in the global space
00220     lua_getglobal(_lstack, key.c_str());
00221 
00222     luabind::object o(from_stack(_lstack, STACK_TOP));
00223 
00224     if (!o) {
00225       _error_messages << "* ReadFunctionPointer() failed because it was unable to access the function "
00226         << "for the global key: " << key << endl;
00227       return luabind::object();
00228     }
00229 
00230     if (type(o) != LUA_TFUNCTION) {
00231       _error_messages << "* ReadFunctionPointer() failed because the data retrieved was not a function "
00232         << "for the global key: " << key << endl;
00233       return luabind::object();
00234     }
00235 
00236     return o;
00237   }
00238 
00239   else { // The function should be an element of the most recently opened table
00240     luabind::object o(from_stack(_lstack, STACK_TOP));
00241     if (type(o) != LUA_TTABLE) {
00242       _error_messages << "* ReadFunctionPointer() failed because the top of the stack was not a table "
00243         << "for the table element key: " << key << endl;
00244       return luabind::object();
00245     }
00246   
00247     if (type(o[key]) != LUA_TFUNCTION) {
00248       _error_messages << "* ReadFunctionPointer() failed because the data retrieved was not a function "
00249         << "for the table element key: " << key << endl;
00250       return luabind::object();
00251     }
00252     
00253     return o[key];
00254   }
00255 } // object ReadScriptDescriptor::ReadFunctionPointer(string key)
00256 
00257 
00258 
00259 object ReadScriptDescriptor::ReadFunctionPointer(int32 key) {
00260   // Fucntion is always a table element for integer keys
00261   luabind::object o(from_stack(_lstack, STACK_TOP));
00262   if (type(o) != LUA_TTABLE) {
00263     _error_messages << "* _ReadFunctionPointer() failed because the top of the stack was not a table "
00264       << "for the table element key: " << key << endl;
00265     return o;
00266   }
00267 
00268   if (type(o[key]) != LUA_TFUNCTION) {
00269     _error_messages << "* _ReadFunctionPointer() failed because the data retrieved was not a function "
00270       << "for the table element key: " << key << endl;
00271     return o;
00272   }
00273 
00274   return o[key];
00275 } // object ReadScriptDescriptor::ReadFunctionPointer(int32 key)
00276 
00277 //-----------------------------------------------------------------------------
00278 // Table Operation Functions
00279 //-----------------------------------------------------------------------------
00280 
00281 void ReadScriptDescriptor::OpenTable(const string& table_name) {
00282   if (_open_tables.size() == 0) { // Fetch the table from the global space
00283     lua_getglobal(_lstack, table_name.c_str());
00284     if (!lua_istable(_lstack, STACK_TOP)) {
00285       _error_messages << "* OpenTable() failed because the data retrieved was not a table "
00286         << "or did not exist for the global key " << table_name << endl;
00287       return;
00288     }
00289     _open_tables.push_back(table_name);
00290   }
00291 
00292   else { // The table to fetch is an element of another table
00293     lua_pushstring(_lstack, table_name.c_str());
00294     lua_gettable(_lstack, STACK_TOP - 1);
00295     if (!lua_istable(_lstack, STACK_TOP)) {
00296       _error_messages << "* OpenTable() failed because the data retrieved was not a table "
00297         << "or did not exist for the table element key " << table_name << endl;
00298       return;
00299     }
00300     _open_tables.push_back(table_name);
00301   }
00302 } // void ReadScriptDescriptor::OpenTable(string key)
00303 
00304 
00305 
00306 void ReadScriptDescriptor::OpenTable(int32 table_name) {
00307   // At least one table must be open to use a numerical key
00308   if (_open_tables.size() == 0) {
00309     _error_messages << "* OpenTable() failed because there were no tables open when trying "
00310         << "to open the with the element key " << table_name << endl;
00311     return;
00312   }
00313 
00314   lua_pushnumber(_lstack, table_name);
00315   lua_gettable(_lstack, STACK_TOP - 1);
00316   if (!lua_istable(_lstack, STACK_TOP)) {
00317     _error_messages << "* OpenTable() failed because the data retrieved was not a table "
00318         << "or did not exist for the table element key " << table_name << endl;
00319     return;
00320   }
00321 
00322   _open_tables.push_back(NumberToString(table_name));
00323 } // void ReadScriptDescriptor::OpenTable(int32 key)
00324 
00325 
00326 
00327 void ReadScriptDescriptor::CloseTable() {
00328   if (_open_tables.size() == 0) {
00329     _error_messages << "* CloseTable() failed because there were no open tables to close" << endl;
00330     return;
00331   }
00332 
00333   _open_tables.pop_back();
00334   lua_pop(_lstack, 1);
00335 }
00336 
00337 
00338 
00339 void ReadScriptDescriptor::CloseAllTables() {
00340   while (_open_tables.size() != 0) {
00341     CloseTable();
00342   }
00343 }
00344 
00345 
00346 
00347 uint32 ReadScriptDescriptor::GetTableSize(const string& table_name) {
00348   uint32 size = 0;
00349 
00350   OpenTable(table_name);
00351   size = GetTableSize();
00352   CloseTable();
00353   return size;
00354 }
00355 
00356 
00357 
00358 uint32 ReadScriptDescriptor::GetTableSize(int32 table_name) {
00359   uint32 size = 0;
00360 
00361   OpenTable(table_name);
00362   size = GetTableSize();
00363   CloseTable();
00364 
00365   return size;
00366 }
00367 
00368 
00369 // Attempts to get the size of the most recently opened table
00370 uint32 ReadScriptDescriptor::GetTableSize() {
00371   if (_open_tables.size() == 0) {
00372     _error_messages << "* GetTableSize() failed because there were no open tables to get the size of" << endl;
00373     return 0;
00374   }
00375 
00376   return static_cast<uint32>(luaL_getn(_lstack, STACK_TOP));
00377 }
00378 
00379 //-----------------------------------------------------------------------------
00380 // Miscellaneous Functions
00381 //-----------------------------------------------------------------------------
00382 
00383 void ReadScriptDescriptor::DEBUG_PrintLuaStack() {
00384   int32 type; // a variable to temporarily hold the type of Lua data read
00385 
00386   cout << "SCRIPT DEBUG: Printing script's lua stack:" << endl;
00387   for (int32 i = lua_gettop(_lstack); i > 0; i--) {  // Print each element starting from the top of the stack
00388     type = lua_type(_lstack, i);
00389     switch (type) {
00390       case LUA_TNIL:
00391         cout << "* " << i << "= NIL" << endl;
00392         break;
00393       case LUA_TBOOLEAN:
00394         cout << "* " << i << "= BOOLEAN: " << lua_toboolean(_lstack, i) << endl;
00395         break;
00396       case LUA_TNUMBER:
00397         cout << "* " << i << "= NUMBER:  " << lua_tonumber(_lstack, i) << endl;
00398         break;
00399       case LUA_TSTRING:
00400         cout << "* " << i << "= STRING:  " << lua_tostring(_lstack, i) << endl;
00401         break;
00402       case LUA_TTABLE:
00403         cout << "* " << i << "= TABLE" << endl;
00404         break;
00405       case LUA_TFUNCTION:
00406         cout << "* " << i << "= FUNCTION" << endl;
00407         break;
00408       case LUA_TUSERDATA:
00409         cout << "* " << i << "= USERDATA " << endl;
00410         break;
00411       case LUA_TLIGHTUSERDATA:
00412         cout << "* " << i << "= LIGHTUSERDATA " << endl;
00413         break;
00414       case LUA_TTHREAD:
00415         cout << "* " << i << "= THREAD " << endl;
00416         break;
00417       default:
00418         cout << "* " << i << "= OTHER: " << lua_typename(_lstack, type) << endl;
00419         break;
00420     }
00421   }
00422   cout << endl;
00423 } // void ReadScriptDescriptor::DEBUG_PrintLuaStack()
00424 
00425 
00426 
00427 void ReadScriptDescriptor::DEBUG_PrintGlobals() {
00428   cout << "SCRIPT DEBUG: Printing script's global variables:" << endl;
00429 
00430   object o(from_stack(_lstack, LUA_GLOBALSINDEX));
00431   for (luabind::iterator it(o), end; it != end; ++it) {
00432     cout << it.key() << " = " << (*it) << " ::: data type = " << type(*it) << endl;
00433     if (luabind::type(*it) == LUA_TTABLE) {
00434       // TODO: what needs to go here? Printing out the table contents?
00435     }
00436   }
00437   cout << endl;
00438 }
00439 
00440 } // namespace hoa_script

Generated on Fri Jul 6 23:11:22 2007 for Hero of Allacrost by  doxygen 1.5.1