00001
00002
00003
00004
00005
00006
00007
00009
00017 #include "script.h"
00018 #include "script_modify.h"
00019 #include "script_read.h"
00020 #include "script_write.h"
00021
00022 using namespace std;
00023 using namespace luabind;
00024
00025 using namespace hoa_utils;
00026
00027 namespace hoa_script {
00028
00029 ModifyScriptDescriptor::~ModifyScriptDescriptor() {
00030 if (IsFileOpen()) {
00031 if (SCRIPT_DEBUG)
00032 cerr << "SCRIPT WARNING: ModifyScriptDescriptor destructor was called when file was still open: "
00033 << _filename << endl;
00034 CloseFile();
00035 }
00036
00037 _filename = "";
00038 _access_mode = SCRIPT_CLOSED;
00039 _error_messages.clear();
00040 _open_tables.clear();
00041 }
00042
00043
00044
00045
00046
00047 bool ModifyScriptDescriptor::OpenFile(const std::string& file_name) {
00048 if (ScriptManager->IsFileOpen(file_name) == true) {
00049 if (SCRIPT_DEBUG)
00050 cerr << "SCRIPT WARNING: ModifyScriptDescriptor::OpenFile() attempted to open file that is already opened: "
00051 << file_name << endl;
00052 return false;
00053 }
00054
00055
00056
00057 lua_checkstack(ScriptManager->GetGlobalState(),1);
00058 _lstack = lua_newthread(ScriptManager->GetGlobalState());
00059
00060
00061 if (lua_dofile(_lstack, file_name.c_str()) != 0) {
00062 cerr << "SCRIPT ERROR: ModifyScriptDescriptor::OpenFile() could not open the file " << file_name << endl;
00063 _access_mode = SCRIPT_CLOSED;
00064 return false;
00065 }
00066
00067 _filename = file_name;
00068 _access_mode = SCRIPT_READ;
00069 ScriptManager->_AddOpenFile(this);
00070 return true;
00071 }
00072
00073
00074
00075 bool ModifyScriptDescriptor::OpenFile() {
00076 if (_filename == "") {
00077 if (SCRIPT_DEBUG)
00078 cerr << "SCRIPT ERROR: ModifyScriptDescriptor::OpenFile(), could not open file "
00079 << "because of an invalid file name (empty string)." << endl;
00080 return false;
00081 }
00082
00083 return OpenFile(_filename);
00084 }
00085
00086
00087
00088 void ModifyScriptDescriptor::CloseFile() {
00089 if (IsFileOpen() == false) {
00090 if (SCRIPT_DEBUG)
00091 cerr << "SCRIPT ERROR: ModifyScriptDescriptor::CloseFile() could not close the "
00092 << "file because it was not open." << endl;
00093 return;
00094 }
00095
00096 if (SCRIPT_DEBUG && IsErrorDetected()) {
00097 cerr << "SCRIPT WARNING: In ModifyScriptDescriptor::CloseFile(), the file " << _filename
00098 << " had error messages remaining. They are as follows:" << endl;
00099 cerr << _error_messages.str() << endl;
00100 }
00101
00102 _lstack = NULL;
00103 _error_messages.clear();
00104 _open_tables.clear();
00105 _access_mode = SCRIPT_CLOSED;
00106 ScriptManager->_RemoveOpenFile(this);
00107 }
00108
00109
00110
00111
00112
00113 void ModifyScriptDescriptor::CommitChanges(bool leave_closed) {
00114 WriteScriptDescriptor file;
00115 string temp_filename = "TEMP" + _filename;
00116
00117 if (file.OpenFile(temp_filename) == false) {
00118 if (SCRIPT_DEBUG)
00119 _error_messages << "* ModifyScriptDescriptor::CommitChanges() failed because it could not open "
00120 << "the file to write the modifications to" << endl;
00121 return;
00122 }
00123
00124
00125
00126 object globals(luabind::from_stack(_lstack, LUA_GLOBALSINDEX));
00127 _CommitTable(file, globals);
00128
00129 file.CloseFile();
00130 CloseFile();
00131
00132
00133
00134 if (MoveFile(temp_filename, _filename) == false) {
00135 _error_messages << "* ModifyScriptDescriptor::CommitChanges() failed because after writing the temporary file "
00136 << temp_filename << ", it could not be moved to overwrite the original filename " << _filename << endl;
00137 }
00138
00139 if (leave_closed == false)
00140 OpenFile();
00141 }
00142
00143
00144
00145 void ModifyScriptDescriptor::_CommitTable(WriteScriptDescriptor& file, const luabind::object& table) {
00146 bool key_is_numeric;
00147 int32 num_key = 0;
00148 string str_key = "";
00149
00150 for (luabind::iterator it(table), end; it != end; ++it) {
00151 try {
00152 num_key = object_cast<int32>(it.key());
00153 key_is_numeric = true;
00154 } catch (...) {
00155 str_key = object_cast<string>(it.key());
00156 key_is_numeric = false;
00157 }
00158
00159 switch (luabind::type(*it)) {
00160 case LUA_TBOOLEAN:
00161 if (key_is_numeric)
00162 file.WriteBool(num_key, object_cast<bool>(*it));
00163 else
00164 file.WriteBool(str_key, object_cast<bool>(*it));
00165 break;
00166 case LUA_TNUMBER:
00167 try {
00168 if (key_is_numeric)
00169 file.WriteInt(num_key, object_cast<int32>(*it));
00170 else
00171 file.WriteInt(str_key, object_cast<int32>(*it));
00172 } catch (...) {
00173 if (key_is_numeric)
00174 file.WriteFloat(num_key, object_cast<float>(*it));
00175 else
00176 file.WriteFloat(str_key, object_cast<float>(*it));
00177 }
00178 break;
00179 case LUA_TSTRING:
00180 if (key_is_numeric)
00181 file.WriteString(num_key, object_cast<string>(*it));
00182 else
00183 file.WriteString(str_key, object_cast<string>(*it));
00184 break;
00185 case LUA_TTABLE:
00186 if (key_is_numeric)
00187 file.BeginTable(num_key);
00188 else
00189 file.BeginTable(str_key);
00190 _CommitTable(file, object(*it));
00191 file.EndTable();
00192 break;
00193 case LUA_TNIL:
00194 case LUA_TFUNCTION:
00195 case LUA_TUSERDATA:
00196 case LUA_TLIGHTUSERDATA:
00197 case LUA_TTHREAD:
00198 default:
00199 if (SCRIPT_DEBUG) {
00200 _error_messages << "* ModifyScriptDescriptor::_CommitTable() detected a ";
00201 if (type(*it) == LUA_TNIL) {
00202 _error_messages << "nil value ";
00203 } else if (type(*it) == LUA_TFUNCTION) {
00204 _error_messages << "function ";
00205 } else if (type(*it) == LUA_TFUNCTION) {
00206 _error_messages << "function ";
00207 } else if (type(*it) == LUA_TUSERDATA) {
00208 _error_messages << "user data ";
00209 } else if (type(*it) == LUA_TLIGHTUSERDATA) {
00210 _error_messages << "light user data ";
00211 } else if (type(*it) == LUA_TTHREAD) {
00212 _error_messages << "thread ";
00213 } else {
00214 _error_messages << "unknown data type ";
00215 }
00216
00217 if (key_is_numeric)
00218 _error_messages << "key: " << num_key;
00219 else
00220 _error_messages << str_key;
00221 _error_messages << ". It was not written to the modified file." << endl;
00222 }
00223 break;
00224 }
00225 }
00226 }
00227
00228 }