initial commit
This commit is contained in:
660
add_on/scriptfile/scriptfile.cpp
Normal file
660
add_on/scriptfile/scriptfile.cpp
Normal file
@@ -0,0 +1,660 @@
|
||||
#include "scriptfile.h"
|
||||
#include <new>
|
||||
#include <assert.h>
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef _WIN32_WCE
|
||||
#include <windows.h> // 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<float*>(&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<double*>(&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<asUINT*>(&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<asQWORD*>(&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
|
||||
101
add_on/scriptfile/scriptfile.h
Normal file
101
add_on/scriptfile/scriptfile.h
Normal file
@@ -0,0 +1,101 @@
|
||||
//
|
||||
// CScriptFile
|
||||
//
|
||||
// This class encapsulates a FILE pointer in a reference counted class for
|
||||
// use within AngelScript.
|
||||
//
|
||||
|
||||
#ifndef SCRIPTFILE_H
|
||||
#define SCRIPTFILE_H
|
||||
|
||||
//---------------------------
|
||||
// Compilation settings
|
||||
//
|
||||
|
||||
// Set this flag to turn on/off write support
|
||||
// 0 = off
|
||||
// 1 = on
|
||||
|
||||
#ifndef AS_WRITE_OPS
|
||||
#define AS_WRITE_OPS 1
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
//---------------------------
|
||||
// Declaration
|
||||
//
|
||||
|
||||
#ifndef ANGELSCRIPT_H
|
||||
// Avoid having to inform include path if header is already include before
|
||||
#include <angelscript.h>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
|
||||
BEGIN_AS_NAMESPACE
|
||||
|
||||
class CScriptFile
|
||||
{
|
||||
public:
|
||||
CScriptFile();
|
||||
|
||||
void AddRef() const;
|
||||
void Release() const;
|
||||
|
||||
// TODO: Implement the "r+", "w+" and "a+" modes
|
||||
// mode = "r" -> open the file for reading
|
||||
// "w" -> open the file for writing (overwrites existing file)
|
||||
// "a" -> open the file for appending
|
||||
int Open(const std::string &filename, const std::string &mode);
|
||||
int Close();
|
||||
int GetSize() const;
|
||||
bool IsEOF() const;
|
||||
|
||||
// Reading
|
||||
std::string ReadString(unsigned int length);
|
||||
std::string ReadLine();
|
||||
asINT64 ReadInt(asUINT bytes);
|
||||
asQWORD ReadUInt(asUINT bytes);
|
||||
float ReadFloat();
|
||||
double ReadDouble();
|
||||
|
||||
// Writing
|
||||
int WriteString(const std::string &str);
|
||||
int WriteInt(asINT64 v, asUINT bytes);
|
||||
int WriteUInt(asQWORD v, asUINT bytes);
|
||||
int WriteFloat(float v);
|
||||
int WriteDouble(double v);
|
||||
|
||||
// Cursor
|
||||
int GetPos() const;
|
||||
int SetPos(int pos);
|
||||
int MovePos(int delta);
|
||||
|
||||
// Big-endian = most significant byte first
|
||||
bool mostSignificantByteFirst;
|
||||
|
||||
protected:
|
||||
~CScriptFile();
|
||||
|
||||
mutable int refCount;
|
||||
FILE *file;
|
||||
};
|
||||
|
||||
// This function will determine the configuration of the engine
|
||||
// and use one of the two functions below to register the file type
|
||||
void RegisterScriptFile(asIScriptEngine *engine);
|
||||
|
||||
// Call this function to register the file type
|
||||
// using native calling conventions
|
||||
void RegisterScriptFile_Native(asIScriptEngine *engine);
|
||||
|
||||
// Use this one instead if native calling conventions
|
||||
// are not supported on the target platform
|
||||
void RegisterScriptFile_Generic(asIScriptEngine *engine);
|
||||
|
||||
END_AS_NAMESPACE
|
||||
|
||||
#endif
|
||||
629
add_on/scriptfile/scriptfilesystem.cpp
Normal file
629
add_on/scriptfile/scriptfilesystem.cpp
Normal file
@@ -0,0 +1,629 @@
|
||||
#include "scriptfilesystem.h"
|
||||
#include "../autowrapper/aswrappedcall.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <direct.h> // _getcwd
|
||||
#include <Windows.h> // FindFirstFile, GetFileAttributes
|
||||
|
||||
#undef DeleteFile
|
||||
#undef CopyFile
|
||||
|
||||
#else
|
||||
#include <unistd.h> // getcwd
|
||||
#include <dirent.h> // opendir, readdir, closedir
|
||||
#include <sys/stat.h> // stat
|
||||
#endif
|
||||
#include <assert.h> // assert
|
||||
|
||||
using namespace std;
|
||||
|
||||
BEGIN_AS_NAMESPACE
|
||||
|
||||
// TODO: The file system should have a way to allow the application to define in
|
||||
// which sub directories it is allowed to make changes and/or read
|
||||
|
||||
CScriptFileSystem *ScriptFileSystem_Factory()
|
||||
{
|
||||
return new CScriptFileSystem();
|
||||
}
|
||||
|
||||
void RegisterScriptFileSystem_Native(asIScriptEngine *engine)
|
||||
{
|
||||
int r;
|
||||
|
||||
assert( engine->GetTypeInfoByName("string") );
|
||||
assert( engine->GetTypeInfoByDecl("array<string>") );
|
||||
assert( engine->GetTypeInfoByName("datetime") );
|
||||
|
||||
r = engine->RegisterObjectType("filesystem", 0, asOBJ_REF); assert( r >= 0 );
|
||||
r = engine->RegisterObjectBehaviour("filesystem", asBEHAVE_FACTORY, "filesystem @f()", asFUNCTION(ScriptFileSystem_Factory), asCALL_CDECL); assert( r >= 0 );
|
||||
r = engine->RegisterObjectBehaviour("filesystem", asBEHAVE_ADDREF, "void f()", asMETHOD(CScriptFileSystem,AddRef), asCALL_THISCALL); assert( r >= 0 );
|
||||
r = engine->RegisterObjectBehaviour("filesystem", asBEHAVE_RELEASE, "void f()", asMETHOD(CScriptFileSystem,Release), asCALL_THISCALL); assert( r >= 0 );
|
||||
|
||||
r = engine->RegisterObjectMethod("filesystem", "bool changeCurrentPath(const string &in)", asMETHOD(CScriptFileSystem, ChangeCurrentPath), asCALL_THISCALL); assert( r >= 0 );
|
||||
r = engine->RegisterObjectMethod("filesystem", "string getCurrentPath() const", asMETHOD(CScriptFileSystem, GetCurrentPath), asCALL_THISCALL); assert( r >= 0 );
|
||||
r = engine->RegisterObjectMethod("filesystem", "array<string> @getDirs() const", asMETHOD(CScriptFileSystem, GetDirs), asCALL_THISCALL); assert( r >= 0 );
|
||||
r = engine->RegisterObjectMethod("filesystem", "array<string> @getFiles() const", asMETHOD(CScriptFileSystem, GetFiles), asCALL_THISCALL); assert( r >= 0 );
|
||||
r = engine->RegisterObjectMethod("filesystem", "bool isDir(const string &in) const", asMETHOD(CScriptFileSystem, IsDir), asCALL_THISCALL); assert( r >= 0 );
|
||||
r = engine->RegisterObjectMethod("filesystem", "bool isLink(const string &in) const", asMETHOD(CScriptFileSystem, IsLink), asCALL_THISCALL); assert(r >= 0);
|
||||
r = engine->RegisterObjectMethod("filesystem", "int64 getSize(const string &in) const", asMETHOD(CScriptFileSystem, GetSize), asCALL_THISCALL); assert(r >= 0);
|
||||
r = engine->RegisterObjectMethod("filesystem", "int makeDir(const string &in)", asMETHOD(CScriptFileSystem, MakeDir), asCALL_THISCALL); assert(r >= 0);
|
||||
r = engine->RegisterObjectMethod("filesystem", "int removeDir(const string &in)", asMETHOD(CScriptFileSystem, RemoveDir), asCALL_THISCALL); assert(r >= 0);
|
||||
r = engine->RegisterObjectMethod("filesystem", "int deleteFile(const string &in)", asMETHOD(CScriptFileSystem, DeleteFile), asCALL_THISCALL); assert(r >= 0);
|
||||
r = engine->RegisterObjectMethod("filesystem", "int copyFile(const string &in, const string &in)", asMETHOD(CScriptFileSystem, CopyFile), asCALL_THISCALL); assert(r >= 0);
|
||||
r = engine->RegisterObjectMethod("filesystem", "int move(const string &in, const string &in)", asMETHOD(CScriptFileSystem, Move), asCALL_THISCALL); assert(r >= 0);
|
||||
r = engine->RegisterObjectMethod("filesystem", "datetime getCreateDateTime(const string &in) const", asMETHOD(CScriptFileSystem, GetCreateDateTime), asCALL_THISCALL); assert(r >= 0);
|
||||
r = engine->RegisterObjectMethod("filesystem", "datetime getModifyDateTime(const string &in) const", asMETHOD(CScriptFileSystem, GetModifyDateTime), asCALL_THISCALL); assert(r >= 0);
|
||||
}
|
||||
|
||||
void RegisterScriptFileSystem_Generic(asIScriptEngine *engine)
|
||||
{
|
||||
int r;
|
||||
|
||||
assert( engine->GetTypeInfoByName("string") );
|
||||
assert( engine->GetTypeInfoByDecl("array<string>") );
|
||||
assert( engine->GetTypeInfoByName("datetime") );
|
||||
|
||||
r = engine->RegisterObjectType("filesystem", 0, asOBJ_REF); assert( r >= 0 );
|
||||
r = engine->RegisterObjectBehaviour("filesystem", asBEHAVE_FACTORY, "filesystem @f()", WRAP_FN(ScriptFileSystem_Factory), asCALL_GENERIC); assert( r >= 0 );
|
||||
r = engine->RegisterObjectBehaviour("filesystem", asBEHAVE_ADDREF, "void f()", WRAP_MFN(CScriptFileSystem,AddRef), asCALL_GENERIC); assert( r >= 0 );
|
||||
r = engine->RegisterObjectBehaviour("filesystem", asBEHAVE_RELEASE, "void f()", WRAP_MFN(CScriptFileSystem,Release), asCALL_GENERIC); assert( r >= 0 );
|
||||
|
||||
r = engine->RegisterObjectMethod("filesystem", "bool changeCurrentPath(const string &in)", WRAP_MFN(CScriptFileSystem, ChangeCurrentPath), asCALL_GENERIC); assert( r >= 0 );
|
||||
r = engine->RegisterObjectMethod("filesystem", "string getCurrentPath() const", WRAP_MFN(CScriptFileSystem, GetCurrentPath), asCALL_GENERIC); assert( r >= 0 );
|
||||
r = engine->RegisterObjectMethod("filesystem", "array<string> @getDirs() const", WRAP_MFN(CScriptFileSystem, GetDirs), asCALL_GENERIC); assert( r >= 0 );
|
||||
r = engine->RegisterObjectMethod("filesystem", "array<string> @getFiles() const", WRAP_MFN(CScriptFileSystem, GetFiles), asCALL_GENERIC); assert( r >= 0 );
|
||||
r = engine->RegisterObjectMethod("filesystem", "bool isDir(const string &in) const", WRAP_MFN(CScriptFileSystem, IsDir), asCALL_GENERIC); assert( r >= 0 );
|
||||
r = engine->RegisterObjectMethod("filesystem", "bool isLink(const string &in) const", WRAP_MFN(CScriptFileSystem, IsLink), asCALL_GENERIC); assert(r >= 0);
|
||||
r = engine->RegisterObjectMethod("filesystem", "int64 getSize(const string &in) const", WRAP_MFN(CScriptFileSystem, GetSize), asCALL_GENERIC); assert(r >= 0);
|
||||
r = engine->RegisterObjectMethod("filesystem", "int makeDir(const string &in)", WRAP_MFN(CScriptFileSystem, MakeDir), asCALL_GENERIC); assert(r >= 0);
|
||||
r = engine->RegisterObjectMethod("filesystem", "int removeDir(const string &in)", WRAP_MFN(CScriptFileSystem, RemoveDir), asCALL_GENERIC); assert(r >= 0);
|
||||
r = engine->RegisterObjectMethod("filesystem", "int deleteFile(const string &in)", WRAP_MFN(CScriptFileSystem, DeleteFile), asCALL_GENERIC); assert(r >= 0);
|
||||
r = engine->RegisterObjectMethod("filesystem", "int copyFile(const string &in, const string &in)", WRAP_MFN(CScriptFileSystem, CopyFile), asCALL_GENERIC); assert(r >= 0);
|
||||
r = engine->RegisterObjectMethod("filesystem", "int move(const string &in, const string &in)", WRAP_MFN(CScriptFileSystem, Move), asCALL_GENERIC); assert(r >= 0);
|
||||
r = engine->RegisterObjectMethod("filesystem", "datetime getCreateDateTime(const string &in) const", WRAP_MFN(CScriptFileSystem, GetCreateDateTime), asCALL_GENERIC); assert(r >= 0);
|
||||
r = engine->RegisterObjectMethod("filesystem", "datetime getModifyDateTime(const string &in) const", WRAP_MFN(CScriptFileSystem, GetModifyDateTime), asCALL_GENERIC); assert(r >= 0);
|
||||
}
|
||||
|
||||
void RegisterScriptFileSystem(asIScriptEngine *engine)
|
||||
{
|
||||
if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") )
|
||||
RegisterScriptFileSystem_Generic(engine);
|
||||
else
|
||||
RegisterScriptFileSystem_Native(engine);
|
||||
}
|
||||
|
||||
CScriptFileSystem::CScriptFileSystem()
|
||||
{
|
||||
refCount = 1;
|
||||
|
||||
// Gets the application's current working directory as the starting point
|
||||
// TODO: Replace backslash with slash to keep a unified naming convention
|
||||
char buffer[1000];
|
||||
#if defined(_WIN32)
|
||||
currentPath = _getcwd(buffer, 1000);
|
||||
#else
|
||||
currentPath = getcwd(buffer, 1000);
|
||||
#endif
|
||||
}
|
||||
|
||||
CScriptFileSystem::~CScriptFileSystem()
|
||||
{
|
||||
}
|
||||
|
||||
void CScriptFileSystem::AddRef() const
|
||||
{
|
||||
asAtomicInc(refCount);
|
||||
}
|
||||
|
||||
void CScriptFileSystem::Release() const
|
||||
{
|
||||
if( asAtomicDec(refCount) == 0 )
|
||||
delete this;
|
||||
}
|
||||
|
||||
CScriptArray *CScriptFileSystem::GetFiles() const
|
||||
{
|
||||
// Obtain a pointer to the engine
|
||||
asIScriptContext *ctx = asGetActiveContext();
|
||||
asIScriptEngine *engine = ctx->GetEngine();
|
||||
|
||||
// TODO: This should only be done once
|
||||
// TODO: This assumes that CScriptArray was already registered
|
||||
asITypeInfo *arrayType = engine->GetTypeInfoByDecl("array<string>");
|
||||
|
||||
// Create the array object
|
||||
CScriptArray *array = CScriptArray::Create(arrayType);
|
||||
|
||||
#if defined(_WIN32)
|
||||
// Windows uses UTF16 so it is necessary to convert the string
|
||||
wchar_t bufUTF16[10000];
|
||||
string searchPattern = currentPath + "/*";
|
||||
MultiByteToWideChar(CP_UTF8, 0, searchPattern.c_str(), -1, bufUTF16, 10000);
|
||||
|
||||
WIN32_FIND_DATAW ffd;
|
||||
HANDLE hFind = FindFirstFileW(bufUTF16, &ffd);
|
||||
if( INVALID_HANDLE_VALUE == hFind )
|
||||
return array;
|
||||
|
||||
do
|
||||
{
|
||||
// Skip directories
|
||||
if( (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
|
||||
continue;
|
||||
|
||||
// Convert the file name back to UTF8
|
||||
char bufUTF8[10000];
|
||||
WideCharToMultiByte(CP_UTF8, 0, ffd.cFileName, -1, bufUTF8, 10000, 0, 0);
|
||||
|
||||
// Add the file to the array
|
||||
array->Resize(array->GetSize()+1);
|
||||
((string*)(array->At(array->GetSize()-1)))->assign(bufUTF8);
|
||||
}
|
||||
while( FindNextFileW(hFind, &ffd) != 0 );
|
||||
|
||||
FindClose(hFind);
|
||||
#else
|
||||
dirent *ent = 0;
|
||||
DIR *dir = opendir(currentPath.c_str());
|
||||
while( (ent = readdir(dir)) != NULL )
|
||||
{
|
||||
const string filename = ent->d_name;
|
||||
|
||||
// Skip . and ..
|
||||
if( filename[0] == '.' )
|
||||
continue;
|
||||
|
||||
// Skip sub directories
|
||||
const string fullname = currentPath + "/" + filename;
|
||||
struct stat st;
|
||||
if( stat(fullname.c_str(), &st) == -1 )
|
||||
continue;
|
||||
if( (st.st_mode & S_IFDIR) != 0 )
|
||||
continue;
|
||||
|
||||
// Add the file to the array
|
||||
array->Resize(array->GetSize()+1);
|
||||
((string*)(array->At(array->GetSize()-1)))->assign(filename);
|
||||
}
|
||||
closedir(dir);
|
||||
#endif
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
CScriptArray *CScriptFileSystem::GetDirs() const
|
||||
{
|
||||
// Obtain a pointer to the engine
|
||||
asIScriptContext *ctx = asGetActiveContext();
|
||||
asIScriptEngine *engine = ctx->GetEngine();
|
||||
|
||||
// TODO: This should only be done once
|
||||
// TODO: This assumes that CScriptArray was already registered
|
||||
asITypeInfo *arrayType = engine->GetTypeInfoByDecl("array<string>");
|
||||
|
||||
// Create the array object
|
||||
CScriptArray *array = CScriptArray::Create(arrayType);
|
||||
|
||||
#if defined(_WIN32)
|
||||
// Windows uses UTF16 so it is necessary to convert the string
|
||||
wchar_t bufUTF16[10000];
|
||||
string searchPattern = currentPath + "/*";
|
||||
MultiByteToWideChar(CP_UTF8, 0, searchPattern.c_str(), -1, bufUTF16, 10000);
|
||||
|
||||
WIN32_FIND_DATAW ffd;
|
||||
HANDLE hFind = FindFirstFileW(bufUTF16, &ffd);
|
||||
if( INVALID_HANDLE_VALUE == hFind )
|
||||
return array;
|
||||
|
||||
do
|
||||
{
|
||||
// Skip files
|
||||
if( !(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
|
||||
continue;
|
||||
|
||||
// Convert the file name back to UTF8
|
||||
char bufUTF8[10000];
|
||||
WideCharToMultiByte(CP_UTF8, 0, ffd.cFileName, -1, bufUTF8, 10000, 0, 0);
|
||||
|
||||
if( strcmp(bufUTF8, ".") == 0 || strcmp(bufUTF8, "..") == 0 )
|
||||
continue;
|
||||
|
||||
// Add the dir to the array
|
||||
array->Resize(array->GetSize()+1);
|
||||
((string*)(array->At(array->GetSize()-1)))->assign(bufUTF8);
|
||||
}
|
||||
while( FindNextFileW(hFind, &ffd) != 0 );
|
||||
|
||||
FindClose(hFind);
|
||||
#else
|
||||
dirent *ent = 0;
|
||||
DIR *dir = opendir(currentPath.c_str());
|
||||
while( (ent = readdir(dir)) != NULL )
|
||||
{
|
||||
const string filename = ent->d_name;
|
||||
|
||||
// Skip . and ..
|
||||
if( filename[0] == '.' )
|
||||
continue;
|
||||
|
||||
// Skip files
|
||||
const string fullname = currentPath + "/" + filename;
|
||||
struct stat st;
|
||||
if( stat(fullname.c_str(), &st) == -1 )
|
||||
continue;
|
||||
if( (st.st_mode & S_IFDIR) == 0 )
|
||||
continue;
|
||||
|
||||
// Add the dir to the array
|
||||
array->Resize(array->GetSize()+1);
|
||||
((string*)(array->At(array->GetSize()-1)))->assign(filename);
|
||||
}
|
||||
closedir(dir);
|
||||
#endif
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
// Doesn't change anything if the new path is not valid
|
||||
bool CScriptFileSystem::ChangeCurrentPath(const string &path)
|
||||
{
|
||||
string newPath;
|
||||
if( path.find(":") != string::npos || path.find("/") == 0 || path.find("\\") == 0 )
|
||||
newPath = path;
|
||||
else
|
||||
newPath = currentPath + "/" + path;
|
||||
|
||||
// TODO: Resolve internal /./ and /../
|
||||
// TODO: Replace backslash with slash to keep a unified naming convention
|
||||
|
||||
// Remove trailing slashes from the path
|
||||
while(newPath.length() && (newPath[newPath.length()-1] == '/' || newPath[newPath.length()-1] == '\\') )
|
||||
newPath.resize(newPath.length()-1);
|
||||
|
||||
if (!IsDir(newPath))
|
||||
return false;
|
||||
|
||||
currentPath = newPath;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CScriptFileSystem::IsDir(const string &path) const
|
||||
{
|
||||
string search;
|
||||
if( path.find(":") != string::npos || path.find("/") == 0 || path.find("\\") == 0 )
|
||||
search = path;
|
||||
else
|
||||
search = currentPath + "/" + path;
|
||||
|
||||
#if defined(_WIN32)
|
||||
// Windows uses UTF16 so it is necessary to convert the string
|
||||
wchar_t bufUTF16[10000];
|
||||
MultiByteToWideChar(CP_UTF8, 0, search.c_str(), -1, bufUTF16, 10000);
|
||||
|
||||
// Check if the path exists and is a directory
|
||||
DWORD attrib = GetFileAttributesW(bufUTF16);
|
||||
if( attrib == INVALID_FILE_ATTRIBUTES ||
|
||||
!(attrib & FILE_ATTRIBUTE_DIRECTORY) )
|
||||
return false;
|
||||
#else
|
||||
// Check if the path exists and is a directory
|
||||
struct stat st;
|
||||
if( stat(search.c_str(), &st) == -1 )
|
||||
return false;
|
||||
if( (st.st_mode & S_IFDIR) == 0 )
|
||||
return false;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CScriptFileSystem::IsLink(const string &path) const
|
||||
{
|
||||
string search;
|
||||
if (path.find(":") != string::npos || path.find("/") == 0 || path.find("\\") == 0)
|
||||
search = path;
|
||||
else
|
||||
search = currentPath + "/" + path;
|
||||
|
||||
#if defined(_WIN32)
|
||||
// Windows uses UTF16 so it is necessary to convert the string
|
||||
wchar_t bufUTF16[10000];
|
||||
MultiByteToWideChar(CP_UTF8, 0, search.c_str(), -1, bufUTF16, 10000);
|
||||
|
||||
// Check if the path exists and is a link
|
||||
DWORD attrib = GetFileAttributesW(bufUTF16);
|
||||
if (attrib == INVALID_FILE_ATTRIBUTES ||
|
||||
!(attrib & FILE_ATTRIBUTE_REPARSE_POINT))
|
||||
return false;
|
||||
#else
|
||||
// Check if the path exists and is a link
|
||||
struct stat st;
|
||||
if (stat(search.c_str(), &st) == -1)
|
||||
return false;
|
||||
if ((st.st_mode & S_IFLNK) == 0)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
asINT64 CScriptFileSystem::GetSize(const string &path) const
|
||||
{
|
||||
string search;
|
||||
if (path.find(":") != string::npos || path.find("/") == 0 || path.find("\\") == 0)
|
||||
search = path;
|
||||
else
|
||||
search = currentPath + "/" + path;
|
||||
|
||||
#if defined(_WIN32)
|
||||
// Windows uses UTF16 so it is necessary to convert the string
|
||||
wchar_t bufUTF16[10000];
|
||||
MultiByteToWideChar(CP_UTF8, 0, search.c_str(), -1, bufUTF16, 10000);
|
||||
|
||||
// Get the size of the file
|
||||
LARGE_INTEGER largeInt;
|
||||
HANDLE file = CreateFileW(bufUTF16, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
BOOL success = GetFileSizeEx(file, &largeInt);
|
||||
CloseHandle(file);
|
||||
if( !success )
|
||||
return -1;
|
||||
return asINT64(largeInt.QuadPart);
|
||||
#else
|
||||
// Get the size of the file
|
||||
struct stat st;
|
||||
if (stat(search.c_str(), &st) == -1)
|
||||
return -1;
|
||||
return asINT64(st.st_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
// TODO: Should be able to return different codes for
|
||||
// - directory exists
|
||||
// - path not found
|
||||
// - access denied
|
||||
// TODO: Should be able to define the permissions for the directory
|
||||
int CScriptFileSystem::MakeDir(const string &path)
|
||||
{
|
||||
string search;
|
||||
if (path.find(":") != string::npos || path.find("/") == 0 || path.find("\\") == 0)
|
||||
search = path;
|
||||
else
|
||||
search = currentPath + "/" + path;
|
||||
|
||||
#if defined(_WIN32)
|
||||
// Windows uses UTF16 so it is necessary to convert the string
|
||||
wchar_t bufUTF16[10000];
|
||||
MultiByteToWideChar(CP_UTF8, 0, search.c_str(), -1, bufUTF16, 10000);
|
||||
|
||||
// Create the directory
|
||||
BOOL success = CreateDirectoryW(bufUTF16, 0);
|
||||
return success ? 0 : -1;
|
||||
#else
|
||||
// Create the directory
|
||||
int failure = mkdir(search.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
|
||||
return !failure ? 0 : -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
// TODO: Should be able to return different codes for
|
||||
// - directory doesn't exist
|
||||
// - directory is not empty
|
||||
// - access denied
|
||||
// TODO: Should have an option to remove the directory and all content recursively
|
||||
int CScriptFileSystem::RemoveDir(const string &path)
|
||||
{
|
||||
string search;
|
||||
if (path.find(":") != string::npos || path.find("/") == 0 || path.find("\\") == 0)
|
||||
search = path;
|
||||
else
|
||||
search = currentPath + "/" + path;
|
||||
|
||||
#if defined(_WIN32)
|
||||
// Windows uses UTF16 so it is necessary to convert the string
|
||||
wchar_t bufUTF16[10000];
|
||||
MultiByteToWideChar(CP_UTF8, 0, search.c_str(), -1, bufUTF16, 10000);
|
||||
|
||||
// Remove the directory
|
||||
BOOL success = RemoveDirectoryW(bufUTF16);
|
||||
return success ? 0 : -1;
|
||||
#else
|
||||
// Remove the directory
|
||||
int failure = rmdir(search.c_str());
|
||||
return !failure ? 0 : -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int CScriptFileSystem::DeleteFile(const string &path)
|
||||
{
|
||||
string search;
|
||||
if (path.find(":") != string::npos || path.find("/") == 0 || path.find("\\") == 0)
|
||||
search = path;
|
||||
else
|
||||
search = currentPath + "/" + path;
|
||||
|
||||
#if defined(_WIN32)
|
||||
// Windows uses UTF16 so it is necessary to convert the string
|
||||
wchar_t bufUTF16[10000];
|
||||
MultiByteToWideChar(CP_UTF8, 0, search.c_str(), -1, bufUTF16, 10000);
|
||||
|
||||
// Remove the file
|
||||
BOOL success = DeleteFileW(bufUTF16);
|
||||
return success ? 0 : -1;
|
||||
#else
|
||||
// Remove the file
|
||||
int failure = unlink(search.c_str());
|
||||
return !failure ? 0 : -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int CScriptFileSystem::CopyFile(const string &source, const string &target)
|
||||
{
|
||||
string search1;
|
||||
if (source.find(":") != string::npos || source.find("/") == 0 || source.find("\\") == 0)
|
||||
search1 = source;
|
||||
else
|
||||
search1 = currentPath + "/" + source;
|
||||
|
||||
string search2;
|
||||
if (target.find(":") != string::npos || target.find("/") == 0 || target.find("\\") == 0)
|
||||
search2 = target;
|
||||
else
|
||||
search2 = currentPath + "/" + target;
|
||||
|
||||
#if defined(_WIN32)
|
||||
// Windows uses UTF16 so it is necessary to convert the string
|
||||
wchar_t bufUTF16_1[10000];
|
||||
MultiByteToWideChar(CP_UTF8, 0, search1.c_str(), -1, bufUTF16_1, 10000);
|
||||
|
||||
wchar_t bufUTF16_2[10000];
|
||||
MultiByteToWideChar(CP_UTF8, 0, search2.c_str(), -1, bufUTF16_2, 10000);
|
||||
|
||||
// Copy the file
|
||||
BOOL success = CopyFileW(bufUTF16_1, bufUTF16_2, TRUE);
|
||||
return success ? 0 : -1;
|
||||
#else
|
||||
// Copy the file manually as there is no posix function for this
|
||||
bool failure = false;
|
||||
FILE *src = 0, *tgt = 0;
|
||||
src = fopen(search1.c_str(), "r");
|
||||
if (src == 0) failure = true;
|
||||
if( !failure ) tgt = fopen(search2.c_str(), "w");
|
||||
if (tgt == 0) failure = true;
|
||||
char buf[1024];
|
||||
size_t n;
|
||||
while (!failure && (n = fread(buf, sizeof(char), sizeof(buf), src)) > 0)
|
||||
{
|
||||
if (fwrite(buf, sizeof(char), n, tgt) != n)
|
||||
failure = true;
|
||||
}
|
||||
if (src) fclose(src);
|
||||
if (tgt) fclose(tgt);
|
||||
return !failure ? 0 : -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int CScriptFileSystem::Move(const string &source, const string &target)
|
||||
{
|
||||
string search1;
|
||||
if (source.find(":") != string::npos || source.find("/") == 0 || source.find("\\") == 0)
|
||||
search1 = source;
|
||||
else
|
||||
search1 = currentPath + "/" + source;
|
||||
|
||||
string search2;
|
||||
if (target.find(":") != string::npos || target.find("/") == 0 || target.find("\\") == 0)
|
||||
search2 = target;
|
||||
else
|
||||
search2 = currentPath + "/" + target;
|
||||
|
||||
#if defined(_WIN32)
|
||||
// Windows uses UTF16 so it is necessary to convert the string
|
||||
wchar_t bufUTF16_1[10000];
|
||||
MultiByteToWideChar(CP_UTF8, 0, search1.c_str(), -1, bufUTF16_1, 10000);
|
||||
|
||||
wchar_t bufUTF16_2[10000];
|
||||
MultiByteToWideChar(CP_UTF8, 0, search2.c_str(), -1, bufUTF16_2, 10000);
|
||||
|
||||
// Move the file or directory
|
||||
BOOL success = MoveFileW(bufUTF16_1, bufUTF16_2);
|
||||
return success ? 0 : -1;
|
||||
#else
|
||||
// Move the file or directory
|
||||
int failure = rename(search1.c_str(), search2.c_str());
|
||||
return !failure ? 0 : -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
string CScriptFileSystem::GetCurrentPath() const
|
||||
{
|
||||
return currentPath;
|
||||
}
|
||||
|
||||
CDateTime CScriptFileSystem::GetCreateDateTime(const string &path) const
|
||||
{
|
||||
string search;
|
||||
if (path.find(":") != string::npos || path.find("/") == 0 || path.find("\\") == 0)
|
||||
search = path;
|
||||
else
|
||||
search = currentPath + "/" + path;
|
||||
|
||||
#if defined(_WIN32)
|
||||
// Windows uses UTF16 so it is necessary to convert the string
|
||||
wchar_t bufUTF16[10000];
|
||||
MultiByteToWideChar(CP_UTF8, 0, search.c_str(), -1, bufUTF16, 10000);
|
||||
|
||||
// Get the create date/time of the file
|
||||
FILETIME createTm;
|
||||
HANDLE file = CreateFileW(bufUTF16, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
BOOL success = GetFileTime(file, &createTm, 0, 0);
|
||||
CloseHandle(file);
|
||||
if( !success )
|
||||
{
|
||||
asIScriptContext *ctx = asGetActiveContext();
|
||||
if( ctx )
|
||||
ctx->SetException("Failed to get file creation date/time");
|
||||
return CDateTime();
|
||||
}
|
||||
SYSTEMTIME tm;
|
||||
FileTimeToSystemTime(&createTm, &tm);
|
||||
return CDateTime(tm.wYear, tm.wMonth, tm.wDay, tm.wHour, tm.wMinute, tm.wSecond);
|
||||
#else
|
||||
// Get the create date/time of the file
|
||||
struct stat st;
|
||||
if (stat(search.c_str(), &st) == -1)
|
||||
{
|
||||
asIScriptContext *ctx = asGetActiveContext();
|
||||
if( ctx )
|
||||
ctx->SetException("Failed to get file creation date/time");
|
||||
return CDateTime();
|
||||
}
|
||||
tm *t = localtime(&st.st_ctime);
|
||||
return CDateTime(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
|
||||
#endif
|
||||
}
|
||||
|
||||
CDateTime CScriptFileSystem::GetModifyDateTime(const string &path) const
|
||||
{
|
||||
string search;
|
||||
if (path.find(":") != string::npos || path.find("/") == 0 || path.find("\\") == 0)
|
||||
search = path;
|
||||
else
|
||||
search = currentPath + "/" + path;
|
||||
|
||||
#if defined(_WIN32)
|
||||
// Windows uses UTF16 so it is necessary to convert the string
|
||||
wchar_t bufUTF16[10000];
|
||||
MultiByteToWideChar(CP_UTF8, 0, search.c_str(), -1, bufUTF16, 10000);
|
||||
|
||||
// Get the last modify date/time of the file
|
||||
FILETIME modifyTm;
|
||||
HANDLE file = CreateFileW(bufUTF16, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
BOOL success = GetFileTime(file, 0, 0, &modifyTm);
|
||||
CloseHandle(file);
|
||||
if( !success )
|
||||
{
|
||||
asIScriptContext *ctx = asGetActiveContext();
|
||||
if( ctx )
|
||||
ctx->SetException("Failed to get file modify date/time");
|
||||
return CDateTime();
|
||||
}
|
||||
SYSTEMTIME tm;
|
||||
FileTimeToSystemTime(&modifyTm, &tm);
|
||||
return CDateTime(tm.wYear, tm.wMonth, tm.wDay, tm.wHour, tm.wMinute, tm.wSecond);
|
||||
#else
|
||||
// Get the last modify date/time of the file
|
||||
struct stat st;
|
||||
if (stat(search.c_str(), &st) == -1)
|
||||
{
|
||||
asIScriptContext *ctx = asGetActiveContext();
|
||||
if( ctx )
|
||||
ctx->SetException("Failed to get file modify date/time");
|
||||
return CDateTime();
|
||||
}
|
||||
tm *t = localtime(&st.st_mtime);
|
||||
return CDateTime(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
|
||||
#endif
|
||||
}
|
||||
|
||||
END_AS_NAMESPACE
|
||||
78
add_on/scriptfile/scriptfilesystem.h
Normal file
78
add_on/scriptfile/scriptfilesystem.h
Normal file
@@ -0,0 +1,78 @@
|
||||
#ifndef AS_SCRIPTFILESYSTEM_H
|
||||
#define AS_SCRIPTFILESYSTEM_H
|
||||
|
||||
#ifndef ANGELSCRIPT_H
|
||||
// Avoid having to inform include path if header is already include before
|
||||
#include <angelscript.h>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../scriptarray/scriptarray.h"
|
||||
#include "../datetime/datetime.h"
|
||||
|
||||
BEGIN_AS_NAMESPACE
|
||||
|
||||
class CScriptFileSystem
|
||||
{
|
||||
public:
|
||||
CScriptFileSystem();
|
||||
|
||||
void AddRef() const;
|
||||
void Release() const;
|
||||
|
||||
// Sets the current path that should be used in other calls when using relative paths
|
||||
// It can use relative paths too, so moving up a directory is used by passing in ".."
|
||||
bool ChangeCurrentPath(const std::string &path);
|
||||
std::string GetCurrentPath() const;
|
||||
|
||||
// Returns true if the path is a directory. Input can be either a full path or a relative path.
|
||||
// This method does not return the dirs '.' and '..'
|
||||
bool IsDir(const std::string &path) const;
|
||||
|
||||
// Returns true if the path is a link. Input can be either a full path or a relative path
|
||||
bool IsLink(const std::string &path) const;
|
||||
|
||||
// Returns the size of file. Input can be either a full path or a relative path
|
||||
asINT64 GetSize(const std::string &path) const;
|
||||
|
||||
// Returns a list of the files in the current path
|
||||
CScriptArray *GetFiles() const;
|
||||
|
||||
// Returns a list of the directories in the current path
|
||||
CScriptArray *GetDirs() const;
|
||||
|
||||
// Creates a new directory. Returns 0 on success
|
||||
int MakeDir(const std::string &path);
|
||||
|
||||
// Removes a directory. Will only remove the directory if it is empty. Returns 0 on success
|
||||
int RemoveDir(const std::string &path);
|
||||
|
||||
// Deletes a file. Returns 0 on success
|
||||
int DeleteFile(const std::string &path);
|
||||
|
||||
// Copies a file. Returns 0 on success
|
||||
int CopyFile(const std::string &source, const std::string &target);
|
||||
|
||||
// Moves or renames a file or directory. Returns 0 on success
|
||||
int Move(const std::string &source, const std::string &target);
|
||||
|
||||
// Gets the date and time of the file/dir creation
|
||||
CDateTime GetCreateDateTime(const std::string &path) const;
|
||||
|
||||
// Gets the date and time of the file/dir modification
|
||||
CDateTime GetModifyDateTime(const std::string &path) const;
|
||||
|
||||
protected:
|
||||
~CScriptFileSystem();
|
||||
|
||||
mutable int refCount;
|
||||
std::string currentPath;
|
||||
};
|
||||
|
||||
void RegisterScriptFileSystem(asIScriptEngine *engine);
|
||||
|
||||
END_AS_NAMESPACE
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user