colobot/src/CBot/ClassFILE.cpp

429 lines
11 KiB
C++
Raw Normal View History

2012-03-19 11:44:39 +00:00
// * This file is part of the COLOBOT source code
// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
// *
// * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
// * the Free Software Foundation, either version 3 of the License, or
// * (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have received a copy of the GNU General Public License
2012-08-02 22:50:25 +00:00
// * along with this program. If not, see http://www.gnu.org/licenses/.
// ClassFile.cpp
2012-03-19 11:44:39 +00:00
//
2012-08-02 22:50:25 +00:00
// definition of methods for class FILE
2012-08-02 22:50:25 +00:00
// Static variables
static CBotClass* m_pClassFILE;
static CBotProgram* m_pFuncFile;
static int m_CompteurFileOpen = 0;
2012-08-02 22:50:25 +00:00
// Prepares a file name.
void PrepareFilename(CBotString &filename) //DD!
{
int pos;
pos = filename.ReverseFind('\\');
if ( pos > 0 )
{
2012-08-02 22:50:25 +00:00
filename = filename.Mid(pos+1); // remove the records (files)??
}
pos = filename.ReverseFind('/');
if ( pos > 0 )
{
2012-08-02 22:50:25 +00:00
filename = filename.Mid(pos+1); // also those with /
}
pos = filename.ReverseFind(':');
if ( pos > 0 )
{
2012-08-02 22:50:25 +00:00
filename = filename.Mid(pos+1); // also removes the drive letter C:
}
filename = CBotString("files\\") + filename;
}
2012-08-02 22:50:25 +00:00
// constructor of the class
// gets the filename as a parameter
2012-08-02 22:50:25 +00:00
// execution
bool rfconstruct (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
{
CBotString mode;
2012-08-02 22:50:25 +00:00
// accepts no parameters
2012-08-08 00:01:06 +00:00
if ( pVar == NULL ) return true;
2012-08-02 22:50:25 +00:00
// must be a string
2012-08-08 00:01:06 +00:00
if ( pVar->GivType() != CBotTypString ) { Exception = CBotErrBadString; return false; }
CBotString filename = pVar->GivValString();
PrepareFilename(filename); //DR
2012-08-02 22:50:25 +00:00
// there may be a second parameter
pVar = pVar->GivNext();
if ( pVar != NULL )
{
2012-08-02 22:50:25 +00:00
// recovers the mode
mode = pVar->GivValString();
2012-08-08 00:01:06 +00:00
if ( mode != "r" && mode != "w" ) { Exception = CBotErrBadParam; return false; }
2012-08-02 22:50:25 +00:00
// no third parameter, only two or one possible
2012-08-08 00:01:06 +00:00
if ( pVar->GivNext() != NULL ) { Exception = CBotErrOverParam; return false; }
}
2012-08-02 22:50:25 +00:00
// save the file name
pVar = pThis->GivItem("filename");
pVar->SetValString(filename);
if ( ! mode.IsEmpty() )
{
2012-08-02 22:50:25 +00:00
// open the called file
FILE* pFile = fopen( filename, mode );
2012-08-08 00:01:06 +00:00
if ( pFile == NULL ) { Exception = CBotErrFileOpen; return false; }
m_CompteurFileOpen ++;
2012-08-02 22:50:25 +00:00
// save the handle of file
pVar = pThis->GivItem("handle");
pVar->SetValInt((long)pFile);
}
2012-08-08 00:01:06 +00:00
return true;
}
// compilation
CBotTypResult cfconstruct (CBotVar* pThis, CBotVar* &pVar)
{
2012-08-02 22:50:25 +00:00
// accepts no parameters
if ( pVar == NULL ) return CBotTypResult( 0 );
2012-08-02 22:50:25 +00:00
// must be a string
if ( pVar->GivType() != CBotTypString )
return CBotTypResult( CBotErrBadString );
2012-08-02 22:50:25 +00:00
// there may be a second parameter
pVar = pVar->GivNext();
if ( pVar != NULL )
{
2012-08-02 22:50:25 +00:00
// must be a string
if ( pVar->GivType() != CBotTypString )
return CBotTypResult( CBotErrBadString );
2012-08-02 22:50:25 +00:00
// no third parameter
if ( pVar->GivNext() != NULL ) return CBotTypResult( CBotErrOverParam );
}
2012-08-08 00:01:06 +00:00
// le r<>sultat est de type void (constructeur)
return CBotTypResult( 0 );
}
2012-08-02 22:50:25 +00:00
// destructor of the class
2012-08-02 22:50:25 +00:00
// execution
bool rfdestruct (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
{
2012-08-02 22:50:25 +00:00
// retrieves the element "handle"
pVar = pThis->GivItem("handle");
2012-08-02 22:50:25 +00:00
// not open? no problem
2012-08-08 00:01:06 +00:00
if ( pVar->GivInit() != IS_DEF) return true;
FILE* pFile= (FILE*)pVar->GivValInt();
fclose(pFile);
m_CompteurFileOpen --;
pVar->SetInit(IS_NAN);
2012-08-08 00:01:06 +00:00
return true;
}
2012-08-02 22:50:25 +00:00
// FILE :: open method
// get the r / w mode as a parameter
2012-08-02 22:50:25 +00:00
// execution
bool rfopen (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
{
2012-08-02 22:50:25 +00:00
// there must be a parameter
2012-08-08 00:01:06 +00:00
if ( pVar == NULL ) { Exception = CBotErrLowParam; return false; }
2012-08-02 22:50:25 +00:00
// must be a string
2012-08-08 00:01:06 +00:00
if ( pVar->GivType() != CBotTypString ) { Exception = CBotErrBadString; return false; }
2012-08-02 22:50:25 +00:00
// there may be a second parameter
if ( pVar->GivNext() != NULL )
{
2012-08-02 22:50:25 +00:00
// in this case the first parameter is the file name
CBotString filename = pVar->GivValString();
PrepareFilename(filename); //DR
2012-08-02 22:50:25 +00:00
// saves the file name
CBotVar* pVar2 = pThis->GivItem("filename");
pVar2->SetValString(filename);
2012-08-02 22:50:25 +00:00
// next parameter is the mode
pVar = pVar -> GivNext();
}
CBotString mode = pVar->GivValString();
2012-08-08 00:01:06 +00:00
if ( mode != "r" && mode != "w" ) { Exception = CBotErrBadParam; return false; }
2012-08-02 22:50:25 +00:00
// No third parameter
2012-08-08 00:01:06 +00:00
if ( pVar->GivNext() != NULL ) { Exception = CBotErrOverParam; return false; }
2012-08-02 22:50:25 +00:00
// retrieves the element "handle"
pVar = pThis->GivItem("handle");
2012-08-02 22:50:25 +00:00
// which must not be initialized
2012-08-08 00:01:06 +00:00
if ( pVar->GivInit() == IS_DEF) { Exception = CBotErrFileOpen; return false; }
2012-08-02 22:50:25 +00:00
// contains filename
pVar = pThis->GivItem("filename");
CBotString filename = pVar->GivValString();
2012-08-02 22:50:25 +00:00
PrepareFilename(filename); //DD! (if the name was assigned by h.filename = "...";
2012-08-02 22:50:25 +00:00
// open requsted file
FILE* pFile = fopen( filename, mode );
if ( pFile == NULL ) //DR
{
2012-08-08 00:01:06 +00:00
pResult->SetValInt(false); //DR
return true; //DR
}
m_CompteurFileOpen ++;
2012-08-02 22:50:25 +00:00
// saves the handle of file
pVar = pThis->GivItem("handle");
pVar->SetValInt((long)pFile);
2012-08-08 00:01:06 +00:00
pResult->SetValInt(true); //DR
return true;
}
// compilation
CBotTypResult cfopen (CBotVar* pThis, CBotVar* &pVar)
{
2012-08-02 22:50:25 +00:00
// there must be a parameter
if ( pVar == NULL ) return CBotTypResult( CBotErrLowParam );
2012-08-02 22:50:25 +00:00
// must be a string
if ( pVar->GivType() != CBotTypString )
return CBotTypResult( CBotErrBadString );
2012-08-02 22:50:25 +00:00
// there may be a second parameter
pVar = pVar->GivNext();
if ( pVar != NULL )
{
2012-08-02 22:50:25 +00:00
// must be a string
if ( pVar->GivType() != CBotTypString )
return CBotTypResult( CBotErrBadString );
2012-08-02 22:50:25 +00:00
// no third parameter
if ( pVar->GivNext() != NULL ) return CBotTypResult( CBotErrOverParam );
}
2012-08-02 22:50:25 +00:00
// the result is of type bool
return CBotTypResult(CBotTypBoolean); //DR
}
2012-08-02 22:50:25 +00:00
// FILE :: close method
2012-08-02 22:50:25 +00:00
// execution
bool rfclose (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
{
2012-08-02 22:50:25 +00:00
// it should not be any parameter
if ( pVar != NULL ) return CBotErrOverParam;
2012-08-02 22:50:25 +00:00
// retrieves the element "handle"
pVar = pThis->GivItem("handle");
2012-08-08 00:01:06 +00:00
if ( pVar->GivInit() != IS_DEF) { Exception = CBotErrNotOpen; return false; }
FILE* pFile= (FILE*)pVar->GivValInt();
fclose(pFile);
m_CompteurFileOpen --;
pVar->SetInit(IS_NAN);
2012-08-08 00:01:06 +00:00
return true;
}
// compilation
CBotTypResult cfclose (CBotVar* pThis, CBotVar* &pVar)
{
2012-08-02 22:50:25 +00:00
// it should not be any parameter
if ( pVar != NULL ) return CBotTypResult( CBotErrOverParam );
2012-08-02 22:50:25 +00:00
// function returns a result "void"
return CBotTypResult( 0 );
}
2012-08-02 22:50:25 +00:00
// FILE :: writeln method
2012-08-02 22:50:25 +00:00
// execution
bool rfwrite (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
{
2012-08-02 22:50:25 +00:00
// there must be a parameter
2012-08-08 00:01:06 +00:00
if ( pVar == NULL ) { Exception = CBotErrLowParam; return false; }
2012-08-02 22:50:25 +00:00
// must be a string
2012-08-08 00:01:06 +00:00
if ( pVar->GivType() != CBotTypString ) { Exception = CBotErrBadString; return false; }
CBotString param = pVar->GivValString();
2012-08-02 22:50:25 +00:00
//retrieves the element "handle"
pVar = pThis->GivItem("handle");
2012-08-08 00:01:06 +00:00
if ( pVar->GivInit() != IS_DEF) { Exception = CBotErrNotOpen; return false; }
FILE* pFile= (FILE*)pVar->GivValInt();
int res = fputs(param+CBotString("\n"), pFile);
2012-08-02 22:50:25 +00:00
// on error throws an exception
2012-08-08 00:01:06 +00:00
if ( res < 0 ) { Exception = CBotErrWrite; return false; }
2012-08-08 00:01:06 +00:00
return true;
}
// compilation
CBotTypResult cfwrite (CBotVar* pThis, CBotVar* &pVar)
{
2012-08-02 22:50:25 +00:00
// there must be a parameter
if ( pVar == NULL ) return CBotTypResult( CBotErrLowParam );
2012-08-02 22:50:25 +00:00
// must be a string
if ( pVar->GivType() != CBotTypString ) return CBotTypResult( CBotErrBadString );
2012-08-02 22:50:25 +00:00
// no other parameter
if ( pVar->GivNext() != NULL ) return CBotTypResult( CBotErrOverParam );
2012-08-02 22:50:25 +00:00
// function returns "void" result
return CBotTypResult( 0 );
}
2012-08-02 22:50:25 +00:00
// FILE :: readln method
2012-08-02 22:50:25 +00:00
// execution
bool rfread (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
{
2012-08-02 22:50:25 +00:00
// there shouldn't be any parameter
2012-08-08 00:01:06 +00:00
if ( pVar != NULL ) { Exception = CBotErrOverParam; return false; }
2012-08-02 22:50:25 +00:00
//retrieves the element "handle"
pVar = pThis->GivItem("handle");
2012-08-08 00:01:06 +00:00
if ( pVar->GivInit() != IS_DEF) { Exception = CBotErrNotOpen; return false; }
FILE* pFile= (FILE*)pVar->GivValInt();
char chaine[2000];
int i;
for ( i = 0 ; i < 2000 ; i++ ) chaine[i] = 0;
fgets(chaine, 1999, pFile);
for ( i = 0 ; i < 2000 ; i++ ) if (chaine[i] == '\n') chaine[i] = 0;
2012-08-02 22:50:25 +00:00
// on error throws an exception
2012-08-08 00:01:06 +00:00
if ( ferror(pFile) ) { Exception = CBotErrRead; return false; }
pResult->SetValString( chaine );
2012-08-08 00:01:06 +00:00
return true;
}
// compilation
CBotTypResult cfread (CBotVar* pThis, CBotVar* &pVar)
{
2012-08-02 22:50:25 +00:00
// there shouldn't be any parameter
if ( pVar != NULL ) return CBotTypResult( CBotErrOverParam );
2012-08-02 22:50:25 +00:00
// function return "string" result
return CBotTypResult( CBotTypString );
}
2012-08-02 22:50:25 +00:00
// FILE :: readln method
2012-08-02 22:50:25 +00:00
// execution
bool rfeof (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
{
2012-08-02 22:50:25 +00:00
// there shouldn't be any parameter
2012-08-08 00:01:06 +00:00
if ( pVar != NULL ) { Exception = CBotErrOverParam; return false; }
2012-08-02 22:50:25 +00:00
// retrieves the element "handle"
pVar = pThis->GivItem("handle");
2012-08-08 00:01:06 +00:00
if ( pVar->GivInit() != IS_DEF) { Exception = CBotErrNotOpen; return false; }
FILE* pFile= (FILE*)pVar->GivValInt();
pResult->SetValInt( feof( pFile ) );
2012-08-08 00:01:06 +00:00
return true;
}
// compilation
CBotTypResult cfeof (CBotVar* pThis, CBotVar* &pVar)
{
2012-08-02 22:50:25 +00:00
// there shouldn't be any parameter
if ( pVar != NULL ) return CBotTypResult( CBotErrOverParam );
2012-08-02 22:50:25 +00:00
// function return boolean result
return CBotTypResult( CBotTypBoolean );
}
void InitClassFILE()
{
2012-08-02 22:50:25 +00:00
// creates a class for file management
// the usage is as follows:
// file canal( "NomFichier.txt" )
2012-08-02 22:50:25 +00:00
// canal.open( "r" ); // open reading
// s = canal.readln( ); // reads a line
// canal.close(); // closes the file
2012-08-02 22:50:25 +00:00
// create class FILE
m_pClassFILE = new CBotClass("file", NULL);
2012-08-02 22:50:25 +00:00
// add the component ".filename"
m_pClassFILE->AddItem("filename", CBotTypString);
2012-08-02 22:50:25 +00:00
// add the component ".handle"
m_pClassFILE->AddItem("handle", CBotTypInt, PR_PRIVATE);
2012-08-02 22:50:25 +00:00
// define a constructor and destructor
m_pClassFILE->AddFunction("file", rfconstruct, cfconstruct );
m_pClassFILE->AddFunction("~file", rfdestruct, NULL );
2012-08-02 22:50:25 +00:00
// defined associated methods
m_pClassFILE->AddFunction("open", rfopen, cfopen );
m_pClassFILE->AddFunction("close", rfclose, cfclose );
m_pClassFILE->AddFunction("writeln", rfwrite, cfwrite );
m_pClassFILE->AddFunction("readln", rfread, cfread );
m_pClassFILE->AddFunction("eof", rfeof, cfeof );
m_pFuncFile = new CBotProgram( );
CBotStringArray ListFonctions;
m_pFuncFile->Compile( "public file openfile(string name, string mode) {return new file(name, mode);}", ListFonctions);
2012-08-02 22:50:25 +00:00
m_pFuncFile->SetIdent(-2); // restoreState as a special identifier for this function
}