#include "scriptfile.h" #include #include #include #include #include #ifdef _WIN32_WCE #include // For GetModuleFileName #ifdef GetObject #undef GetObject #endif #endif using namespace std; BEGIN_AS_NAMESPACE CScriptFile *ScriptFile_Factory() { return new CScriptFile(); } void ScriptFile_Factory_Generic(asIScriptGeneric *gen) { *(CScriptFile**)gen->GetAddressOfReturnLocation() = ScriptFile_Factory(); } void ScriptFile_AddRef_Generic(asIScriptGeneric *gen) { CScriptFile *file = (CScriptFile*)gen->GetObject(); file->AddRef(); } void ScriptFile_Release_Generic(asIScriptGeneric *gen) { CScriptFile *file = (CScriptFile*)gen->GetObject(); file->Release(); } void ScriptFile_Open_Generic(asIScriptGeneric *gen) { CScriptFile *file = (CScriptFile*)gen->GetObject(); std::string *f = (std::string*)gen->GetArgAddress(0); std::string *m = (std::string*)gen->GetArgAddress(1); int r = file->Open(*f, *m); gen->SetReturnDWord(r); } void ScriptFile_Close_Generic(asIScriptGeneric *gen) { CScriptFile *file = (CScriptFile*)gen->GetObject(); int r = file->Close(); gen->SetReturnDWord(r); } void ScriptFile_GetSize_Generic(asIScriptGeneric *gen) { CScriptFile *file = (CScriptFile*)gen->GetObject(); int r = file->GetSize(); gen->SetReturnDWord(r); } void ScriptFile_ReadString_Generic(asIScriptGeneric *gen) { CScriptFile *file = (CScriptFile*)gen->GetObject(); int len = gen->GetArgDWord(0); string str = file->ReadString(len); gen->SetReturnObject(&str); } void ScriptFile_ReadLine_Generic(asIScriptGeneric *gen) { CScriptFile *file = (CScriptFile*)gen->GetObject(); std::string str = file->ReadLine(); gen->SetReturnObject(&str); } void ScriptFile_ReadInt_Generic(asIScriptGeneric *gen) { CScriptFile *file = (CScriptFile*)gen->GetObject(); asUINT bytes = *(asUINT*)gen->GetAddressOfArg(0); *(asINT64*)gen->GetAddressOfReturnLocation() = file->ReadInt(bytes); } void ScriptFile_ReadUInt_Generic(asIScriptGeneric *gen) { CScriptFile *file = (CScriptFile*)gen->GetObject(); asUINT bytes = *(asUINT*)gen->GetAddressOfArg(0); *(asQWORD*)gen->GetAddressOfReturnLocation() = file->ReadUInt(bytes); } void ScriptFile_ReadFloat_Generic(asIScriptGeneric *gen) { CScriptFile *file = (CScriptFile*)gen->GetObject(); *(float*)gen->GetAddressOfReturnLocation() = file->ReadFloat(); } void ScriptFile_ReadDouble_Generic(asIScriptGeneric *gen) { CScriptFile *file = (CScriptFile*)gen->GetObject(); *(double*)gen->GetAddressOfReturnLocation() = file->ReadDouble(); } void ScriptFile_WriteString_Generic(asIScriptGeneric *gen) { CScriptFile *file = (CScriptFile*)gen->GetObject(); std::string *str = (std::string*)gen->GetArgAddress(0); gen->SetReturnDWord(file->WriteString(*str)); } void ScriptFile_WriteInt_Generic(asIScriptGeneric *gen) { CScriptFile *file = (CScriptFile*)gen->GetObject(); asINT64 val = *(asINT64*)gen->GetAddressOfArg(0); asUINT bytes = *(asUINT*)gen->GetAddressOfArg(1); *(int*)gen->GetAddressOfReturnLocation() = file->WriteInt(val, bytes); } void ScriptFile_WriteUInt_Generic(asIScriptGeneric *gen) { CScriptFile *file = (CScriptFile*)gen->GetObject(); asQWORD val = *(asQWORD*)gen->GetAddressOfArg(0); asUINT bytes = *(asUINT*)gen->GetAddressOfArg(1); *(int*)gen->GetAddressOfReturnLocation() = file->WriteUInt(val, bytes); } void ScriptFile_WriteFloat_Generic(asIScriptGeneric *gen) { CScriptFile *file = (CScriptFile*)gen->GetObject(); float val = *(float*)gen->GetAddressOfArg(0); *(int*)gen->GetAddressOfReturnLocation() = file->WriteFloat(val); } void ScriptFile_WriteDouble_Generic(asIScriptGeneric *gen) { CScriptFile *file = (CScriptFile*)gen->GetObject(); double val = *(double*)gen->GetAddressOfArg(0); *(int*)gen->GetAddressOfReturnLocation() = file->WriteDouble(val); } void ScriptFile_IsEOF_Generic(asIScriptGeneric *gen) { CScriptFile *file = (CScriptFile*)gen->GetObject(); bool r = file->IsEOF(); gen->SetReturnByte(r); } void ScriptFile_GetPos_Generic(asIScriptGeneric *gen) { CScriptFile *file = (CScriptFile*)gen->GetObject(); gen->SetReturnDWord(file->GetPos()); } void ScriptFile_SetPos_Generic(asIScriptGeneric *gen) { CScriptFile *file = (CScriptFile*)gen->GetObject(); int pos = (int)gen->GetArgDWord(0); gen->SetReturnDWord(file->SetPos(pos)); } void ScriptFile_MovePos_Generic(asIScriptGeneric *gen) { CScriptFile *file = (CScriptFile*)gen->GetObject(); int delta = (int)gen->GetArgDWord(0); gen->SetReturnDWord(file->MovePos(delta)); } void RegisterScriptFile_Native(asIScriptEngine *engine) { int r; r = engine->RegisterObjectType("file", 0, asOBJ_REF); assert( r >= 0 ); r = engine->RegisterObjectBehaviour("file", asBEHAVE_FACTORY, "file @f()", asFUNCTION(ScriptFile_Factory), asCALL_CDECL); assert( r >= 0 ); r = engine->RegisterObjectBehaviour("file", asBEHAVE_ADDREF, "void f()", asMETHOD(CScriptFile,AddRef), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectBehaviour("file", asBEHAVE_RELEASE, "void f()", asMETHOD(CScriptFile,Release), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod("file", "int open(const string &in, const string &in)", asMETHOD(CScriptFile,Open), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod("file", "int close()", asMETHOD(CScriptFile,Close), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod("file", "int getSize() const", asMETHOD(CScriptFile,GetSize), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod("file", "bool isEndOfFile() const", asMETHOD(CScriptFile,IsEOF), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod("file", "string readString(uint)", asMETHOD(CScriptFile,ReadString), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod("file", "string readLine()", asMETHOD(CScriptFile,ReadLine), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod("file", "int64 readInt(uint)", asMETHOD(CScriptFile,ReadInt), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod("file", "uint64 readUInt(uint)", asMETHOD(CScriptFile,ReadUInt), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod("file", "float readFloat()", asMETHOD(CScriptFile,ReadFloat), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod("file", "double readDouble()", asMETHOD(CScriptFile,ReadDouble), asCALL_THISCALL); assert( r >= 0 ); #if AS_WRITE_OPS == 1 r = engine->RegisterObjectMethod("file", "int writeString(const string &in)", asMETHOD(CScriptFile,WriteString), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod("file", "int writeInt(int64, uint)", asMETHOD(CScriptFile,WriteInt), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod("file", "int writeUInt(uint64, uint)", asMETHOD(CScriptFile,WriteUInt), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod("file", "int writeFloat(float)", asMETHOD(CScriptFile,WriteFloat), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod("file", "int writeDouble(double)", asMETHOD(CScriptFile,WriteDouble), asCALL_THISCALL); assert( r >= 0 ); #endif r = engine->RegisterObjectMethod("file", "int getPos() const", asMETHOD(CScriptFile,GetPos), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod("file", "int setPos(int)", asMETHOD(CScriptFile,SetPos), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod("file", "int movePos(int)", asMETHOD(CScriptFile,MovePos), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectProperty("file", "bool mostSignificantByteFirst", asOFFSET(CScriptFile, mostSignificantByteFirst)); assert( r >= 0 ); } void RegisterScriptFile_Generic(asIScriptEngine *engine) { int r; r = engine->RegisterObjectType("file", 0, asOBJ_REF); assert( r >= 0 ); r = engine->RegisterObjectBehaviour("file", asBEHAVE_FACTORY, "file @f()", asFUNCTION(ScriptFile_Factory_Generic), asCALL_GENERIC); assert( r >= 0 ); r = engine->RegisterObjectBehaviour("file", asBEHAVE_ADDREF, "void f()", asFUNCTION(ScriptFile_AddRef_Generic), asCALL_GENERIC); assert( r >= 0 ); r = engine->RegisterObjectBehaviour("file", asBEHAVE_RELEASE, "void f()", asFUNCTION(ScriptFile_Release_Generic), asCALL_GENERIC); assert( r >= 0 ); r = engine->RegisterObjectMethod("file", "int open(const string &in, const string &in)", asFUNCTION(ScriptFile_Open_Generic), asCALL_GENERIC); assert( r >= 0 ); r = engine->RegisterObjectMethod("file", "int close()", asFUNCTION(ScriptFile_Close_Generic), asCALL_GENERIC); assert( r >= 0 ); r = engine->RegisterObjectMethod("file", "int getSize() const", asFUNCTION(ScriptFile_GetSize_Generic), asCALL_GENERIC); assert( r >= 0 ); r = engine->RegisterObjectMethod("file", "bool isEndOfFile() const", asFUNCTION(ScriptFile_IsEOF_Generic), asCALL_GENERIC); assert( r >= 0 ); r = engine->RegisterObjectMethod("file", "string readString(uint)", asFUNCTION(ScriptFile_ReadString_Generic), asCALL_GENERIC); assert( r >= 0 ); r = engine->RegisterObjectMethod("file", "string readLine()", asFUNCTION(ScriptFile_ReadLine_Generic), asCALL_GENERIC); assert( r >= 0 ); r = engine->RegisterObjectMethod("file", "int64 readInt(uint)", asFUNCTION(ScriptFile_ReadInt_Generic), asCALL_GENERIC); assert( r >= 0 ); r = engine->RegisterObjectMethod("file", "uint64 readUInt(uint)", asFUNCTION(ScriptFile_ReadUInt_Generic), asCALL_GENERIC); assert( r >= 0 ); r = engine->RegisterObjectMethod("file", "float readFloat()", asFUNCTION(ScriptFile_ReadFloat_Generic), asCALL_GENERIC); assert( r >= 0 ); r = engine->RegisterObjectMethod("file", "double readDouble()", asFUNCTION(ScriptFile_ReadDouble_Generic), asCALL_GENERIC); assert( r >= 0 ); #if AS_WRITE_OPS == 1 r = engine->RegisterObjectMethod("file", "int writeString(const string &in)", asFUNCTION(ScriptFile_WriteString_Generic), asCALL_GENERIC); assert( r >= 0 ); r = engine->RegisterObjectMethod("file", "int writeInt(int64, uint)", asFUNCTION(ScriptFile_WriteInt_Generic), asCALL_GENERIC); assert( r >= 0 ); r = engine->RegisterObjectMethod("file", "int writeUInt(uint64, uint)", asFUNCTION(ScriptFile_WriteUInt_Generic), asCALL_GENERIC); assert( r >= 0 ); r = engine->RegisterObjectMethod("file", "int writeFloat(float)", asFUNCTION(ScriptFile_WriteFloat_Generic), asCALL_GENERIC); assert( r >= 0 ); r = engine->RegisterObjectMethod("file", "int writeDouble(double)", asFUNCTION(ScriptFile_WriteDouble_Generic), asCALL_GENERIC); assert( r >= 0 ); #endif r = engine->RegisterObjectMethod("file", "int getPos() const", asFUNCTION(ScriptFile_GetPos_Generic), asCALL_GENERIC); assert( r >= 0 ); r = engine->RegisterObjectMethod("file", "int setPos(int)", asFUNCTION(ScriptFile_SetPos_Generic), asCALL_GENERIC); assert( r >= 0 ); r = engine->RegisterObjectMethod("file", "int movePos(int)", asFUNCTION(ScriptFile_MovePos_Generic), asCALL_GENERIC); assert( r >= 0 ); r = engine->RegisterObjectProperty("file", "bool mostSignificantByteFirst", asOFFSET(CScriptFile, mostSignificantByteFirst)); assert( r >= 0 ); } void RegisterScriptFile(asIScriptEngine *engine) { if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") ) RegisterScriptFile_Generic(engine); else RegisterScriptFile_Native(engine); } CScriptFile::CScriptFile() { refCount = 1; file = 0; mostSignificantByteFirst = false; } CScriptFile::~CScriptFile() { Close(); } void CScriptFile::AddRef() const { asAtomicInc(refCount); } void CScriptFile::Release() const { if( asAtomicDec(refCount) == 0 ) delete this; } int CScriptFile::Open(const std::string &filename, const std::string &mode) { // Close the previously opened file handle if( file ) Close(); std::string myFilename = filename; // Validate the mode string m; #if AS_WRITE_OPS == 1 if( mode != "r" && mode != "w" && mode != "a" ) #else if( mode != "r" ) #endif return -1; else m = mode; #ifdef _WIN32_WCE // no relative pathing on CE char buf[MAX_PATH]; static TCHAR apppath[MAX_PATH] = TEXT(""); if (!apppath[0]) { GetModuleFileName(NULL, apppath, MAX_PATH); int appLen = _tcslen(apppath); while (appLen > 1) { if (apppath[appLen-1] == TEXT('\\')) break; appLen--; } // Terminate the string after the trailing backslash apppath[appLen] = TEXT('\0'); } #ifdef _UNICODE wcstombs(buf, apppath, wcslen(apppath)+1); #else memcpy(buf, apppath, strlen(apppath)); #endif myFilename = buf + myFilename; #endif // By default windows translates "\r\n" to "\n", but we want to read the file as-is. m += "b"; // Open the file #if _MSC_VER >= 1400 && !defined(__S3E__) // MSVC 8.0 / 2005 introduced new functions // Marmalade doesn't use these, even though it uses the MSVC compiler fopen_s(&file, myFilename.c_str(), m.c_str()); #else file = fopen(myFilename.c_str(), m.c_str()); #endif if( file == 0 ) return -1; return 0; } int CScriptFile::Close() { if( file == 0 ) return -1; fclose(file); file = 0; return 0; } int CScriptFile::GetSize() const { if( file == 0 ) return -1; int pos = ftell(file); fseek(file, 0, SEEK_END); int size = ftell(file); fseek(file, pos, SEEK_SET); return size; } int CScriptFile::GetPos() const { if( file == 0 ) return -1; return ftell(file); } int CScriptFile::SetPos(int pos) { if( file == 0 ) return -1; int r = fseek(file, pos, SEEK_SET); // Return -1 on error return r ? -1 : 0; } int CScriptFile::MovePos(int delta) { if( file == 0 ) return -1; int r = fseek(file, delta, SEEK_CUR); // Return -1 on error return r ? -1 : 0; } string CScriptFile::ReadString(unsigned int length) { if( file == 0 ) return ""; // Read the string string str; str.resize(length); int size = (int)fread(&str[0], 1, length, file); str.resize(size); return str; } string CScriptFile::ReadLine() { if( file == 0 ) return ""; // Read until the first new-line character string str; char buf[256]; do { // Get the current position so we can determine how many characters were read int start = ftell(file); // Set the last byte to something different that 0, so that we can check if the buffer was filled up buf[255] = 1; // Read the line (or first 255 characters, which ever comes first) char *r = fgets(buf, 256, file); if( r == 0 ) break; // Get the position after the read int end = ftell(file); // Add the read characters to the output buffer str.append(buf, end-start); } while( !feof(file) && buf[255] == 0 && buf[254] != '\n' ); return str; } asINT64 CScriptFile::ReadInt(asUINT bytes) { if( file == 0 ) return 0; if( bytes > 8 ) bytes = 8; if( bytes == 0 ) return 0; unsigned char buf[8]; size_t r = fread(buf, bytes, 1, file); if( r == 0 ) return 0; asINT64 val = 0; if( mostSignificantByteFirst ) { unsigned int n = 0; for( ; n < bytes; n++ ) val |= asQWORD(buf[n]) << ((bytes-n-1)*8); // Check the most significant byte to determine if the rest // of the qword must be filled to give a negative value if( buf[0] & 0x80 ) for( ; n < 8; n++ ) val |= asQWORD(0xFF) << (n*8); } else { unsigned int n = 0; for( ; n < bytes; n++ ) val |= asQWORD(buf[n]) << (n*8); // Check the most significant byte to determine if the rest // of the qword must be filled to give a negative value if( buf[bytes-1] & 0x80 ) for( ; n < 8; n++ ) val |= asQWORD(0xFF) << (n*8); } return val; } asQWORD CScriptFile::ReadUInt(asUINT bytes) { if( file == 0 ) return 0; if( bytes > 8 ) bytes = 8; if( bytes == 0 ) return 0; unsigned char buf[8]; size_t r = fread(buf, bytes, 1, file); if( r == 0 ) return 0; asQWORD val = 0; if( mostSignificantByteFirst ) { unsigned int n = 0; for( ; n < bytes; n++ ) val |= asQWORD(buf[n]) << ((bytes-n-1)*8); } else { unsigned int n = 0; for( ; n < bytes; n++ ) val |= asQWORD(buf[n]) << (n*8); } return val; } float CScriptFile::ReadFloat() { if( file == 0 ) return 0; unsigned char buf[4]; size_t r = fread(buf, 4, 1, file); if( r == 0 ) return 0; asUINT val = 0; if( mostSignificantByteFirst ) { unsigned int n = 0; for( ; n < 4; n++ ) val |= asUINT(buf[n]) << ((3-n)*8); } else { unsigned int n = 0; for( ; n < 4; n++ ) val |= asUINT(buf[n]) << (n*8); } return *reinterpret_cast(&val); } double CScriptFile::ReadDouble() { if( file == 0 ) return 0; unsigned char buf[8]; size_t r = fread(buf, 8, 1, file); if( r == 0 ) return 0; asQWORD val = 0; if( mostSignificantByteFirst ) { unsigned int n = 0; for( ; n < 8; n++ ) val |= asQWORD(buf[n]) << ((7-n)*8); } else { unsigned int n = 0; for( ; n < 8; n++ ) val |= asQWORD(buf[n]) << (n*8); } return *reinterpret_cast(&val); } bool CScriptFile::IsEOF() const { if( file == 0 ) return true; return feof(file) ? true : false; } #if AS_WRITE_OPS == 1 int CScriptFile::WriteString(const std::string &str) { if( file == 0 ) return -1; // Write the entire string size_t r = fwrite(&str[0], 1, str.length(), file); return int(r); } int CScriptFile::WriteInt(asINT64 val, asUINT bytes) { if( file == 0 ) return 0; unsigned char buf[8]; if( mostSignificantByteFirst ) { for( unsigned int n = 0; n < bytes; n++ ) buf[n] = (val >> ((bytes-n-1)*8)) & 0xFF; } else { for( unsigned int n = 0; n < bytes; n++ ) buf[n] = (val >> (n*8)) & 0xFF; } size_t r = fwrite(&buf, bytes, 1, file); return int(r); } int CScriptFile::WriteUInt(asQWORD val, asUINT bytes) { if( file == 0 ) return 0; unsigned char buf[8]; if( mostSignificantByteFirst ) { for( unsigned int n = 0; n < bytes; n++ ) buf[n] = (val >> ((bytes-n-1)*8)) & 0xFF; } else { for( unsigned int n = 0; n < bytes; n++ ) buf[n] = (val >> (n*8)) & 0xFF; } size_t r = fwrite(&buf, bytes, 1, file); return int(r); } int CScriptFile::WriteFloat(float f) { if( file == 0 ) return 0; unsigned char buf[4]; asUINT val = *reinterpret_cast(&f); if( mostSignificantByteFirst ) { for( unsigned int n = 0; n < 4; n++ ) buf[n] = (val >> ((3-n)*4)) & 0xFF; } else { for( unsigned int n = 0; n < 4; n++ ) buf[n] = (val >> (n*8)) & 0xFF; } size_t r = fwrite(&buf, 4, 1, file); return int(r); } int CScriptFile::WriteDouble(double d) { if( file == 0 ) return 0; unsigned char buf[8]; asQWORD val = *reinterpret_cast(&d); if( mostSignificantByteFirst ) { for( unsigned int n = 0; n < 8; n++ ) buf[n] = (val >> ((7-n)*8)) & 0xFF; } else { for( unsigned int n = 0; n < 8; n++ ) buf[n] = (val >> (n*8)) & 0xFF; } size_t r = fwrite(&buf, 8, 1, file); return int(r); } #endif END_AS_NAMESPACE