colobot/src/CBot/ClassFILE.cpp

413 lines
10 KiB
C++
Raw Normal View History

// ClassFile.cpp
//
// d<>finition des m<>thodes pour la classe FILE
// Variables statiques
static CBotClass* m_pClassFILE;
static CBotProgram* m_pFuncFile;
static int m_CompteurFileOpen = 0;
// Pr<50>pare un nom de fichier.
void PrepareFilename(CBotString &filename) //DD!
{
int pos;
pos = filename.ReverseFind('\\');
if ( pos > 0 )
{
filename = filename.Mid(pos+1); // enl<6E>ve les dossiers
}
pos = filename.ReverseFind('/');
if ( pos > 0 )
{
filename = filename.Mid(pos+1); // aussi ceux avec /
}
pos = filename.ReverseFind(':');
if ( pos > 0 )
{
filename = filename.Mid(pos+1); // enl<6E>ve aussi la lettre d'unit<69> C:
}
filename = CBotString("files\\") + filename;
}
// constructeur de la classe
// re<72>ois le nom du fichier en param<61>tre
// ex<65>cution
BOOL rfconstruct (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
{
CBotString mode;
// accepte sans param<61>tre
if ( pVar == NULL ) return TRUE;
// qui doit <20>tre une cha<68>ne de caract<63>res
if ( pVar->GivType() != CBotTypString ) { Exception = CBotErrBadString; return FALSE; }
CBotString filename = pVar->GivValString();
PrepareFilename(filename); //DR
// il peut y avoir un second param<61>tre
pVar = pVar->GivNext();
if ( pVar != NULL )
{
// r<>cup<75>re le mode
mode = pVar->GivValString();
if ( mode != "r" && mode != "w" ) { Exception = CBotErrBadParam; return FALSE; }
// pas de 3e param<61>tre
if ( pVar->GivNext() != NULL ) { Exception = CBotErrOverParam; return FALSE; }
}
// enregistre le nom du fichier
pVar = pThis->GivItem("filename");
pVar->SetValString(filename);
if ( ! mode.IsEmpty() )
{
// ouvre le ficher demand<6E>
FILE* pFile = fopen( filename, mode );
if ( pFile == NULL ) { Exception = CBotErrFileOpen; return FALSE; }
m_CompteurFileOpen ++;
// enregiste le canal du fichier
pVar = pThis->GivItem("handle");
pVar->SetValInt((long)pFile);
}
return TRUE;
}
// compilation
CBotTypResult cfconstruct (CBotVar* pThis, CBotVar* &pVar)
{
// accepte sans param<61>tre
if ( pVar == NULL ) return CBotTypResult( 0 );
// qui doit <20>tre une chaine
if ( pVar->GivType() != CBotTypString )
return CBotTypResult( CBotErrBadString );
// il peut y avoir un second param<61>tre
pVar = pVar->GivNext();
if ( pVar != NULL )
{
// qui doit <20>tre une chaine
if ( pVar->GivType() != CBotTypString )
return CBotTypResult( CBotErrBadString );
// pas de 3e param<61>tre
if ( pVar->GivNext() != NULL ) return CBotTypResult( CBotErrOverParam );
}
// le r<>sultat est de type void (constructeur)
return CBotTypResult( 0 );
}
// destructeur de la classe
// ex<65>cution
BOOL rfdestruct (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
{
// r<>cup<75>re l'<27>l<EFBFBD>ment "handle"
pVar = pThis->GivItem("handle");
// pas ouvert ? pas de probl<62>me
if ( pVar->GivInit() != IS_DEF) return TRUE;
FILE* pFile= (FILE*)pVar->GivValInt();
fclose(pFile);
m_CompteurFileOpen --;
pVar->SetInit(IS_NAN);
return TRUE;
}
// m<>thode FILE :: open
// re<72>ois le mode r/w en param<61>tre
// ex<65>cution
BOOL rfopen (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
{
// il doit y avoir un param<61>tre
if ( pVar == NULL ) { Exception = CBotErrLowParam; return FALSE; }
// qui doit <20>tre une cha<68>ne de caract<63>res
if ( pVar->GivType() != CBotTypString ) { Exception = CBotErrBadString; return FALSE; }
// il peut y avoir un second param<61>tre
if ( pVar->GivNext() != NULL )
{
// dans ce cas le premier param<61>tre est le nom du fichier
CBotString filename = pVar->GivValString();
PrepareFilename(filename); //DR
// enregistre le nom du fichier
CBotVar* pVar2 = pThis->GivItem("filename");
pVar2->SetValString(filename);
// param<61>tre suivant est le mode
pVar = pVar -> GivNext();
}
CBotString mode = pVar->GivValString();
if ( mode != "r" && mode != "w" ) { Exception = CBotErrBadParam; return FALSE; }
// pas de 3e param<61>tre
if ( pVar->GivNext() != NULL ) { Exception = CBotErrOverParam; return FALSE; }
// r<>cup<75>re l'<27>l<EFBFBD>ment "handle"
pVar = pThis->GivItem("handle");
// qui doit pas <20>tre initialis<69>
if ( pVar->GivInit() == IS_DEF) { Exception = CBotErrFileOpen; return FALSE; }
// reprend le nom du fichier
pVar = pThis->GivItem("filename");
CBotString filename = pVar->GivValString();
PrepareFilename(filename); //DD! (si le nom a <20>t<EFBFBD> attribu<62> par h.filename = "...";
// ouvre le ficher demand<6E>
FILE* pFile = fopen( filename, mode );
if ( pFile == NULL ) //DR
{
pResult->SetValInt(FALSE); //DR
return TRUE; //DR
}
m_CompteurFileOpen ++;
// enregiste le canal du fichier
pVar = pThis->GivItem("handle");
pVar->SetValInt((long)pFile);
pResult->SetValInt(TRUE); //DR
return TRUE;
}
// compilation
CBotTypResult cfopen (CBotVar* pThis, CBotVar* &pVar)
{
// il doit y avoir un param<61>tre
if ( pVar == NULL ) return CBotTypResult( CBotErrLowParam );
// qui doit <20>tre une chaine
if ( pVar->GivType() != CBotTypString )
return CBotTypResult( CBotErrBadString );
// il peut y avoir un second param<61>tre
pVar = pVar->GivNext();
if ( pVar != NULL )
{
// qui doit <20>tre une chaine
if ( pVar->GivType() != CBotTypString )
return CBotTypResult( CBotErrBadString );
// pas de 3e param<61>tre
if ( pVar->GivNext() != NULL ) return CBotTypResult( CBotErrOverParam );
}
// le r<>sultat est de type bool
return CBotTypResult(CBotTypBoolean); //DR
}
// m<>thode FILE :: close
// ex<65>cution
BOOL rfclose (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
{
// il ne doit pas y avoir de param<61>tre
if ( pVar != NULL ) return CBotErrOverParam;
// r<>cup<75>re l'<27>l<EFBFBD>ment "handle"
pVar = pThis->GivItem("handle");
if ( pVar->GivInit() != IS_DEF) { Exception = CBotErrNotOpen; return FALSE; }
FILE* pFile= (FILE*)pVar->GivValInt();
fclose(pFile);
m_CompteurFileOpen --;
pVar->SetInit(IS_NAN);
return TRUE;
}
// compilation
CBotTypResult cfclose (CBotVar* pThis, CBotVar* &pVar)
{
// il ne doit pas y avoir de param<61>tre
if ( pVar != NULL ) return CBotTypResult( CBotErrOverParam );
// la fonction retourne un r<>sultat "void"
return CBotTypResult( 0 );
}
// m<>thode FILE :: writeln
// ex<65>cution
BOOL rfwrite (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
{
// il doit y avoir un param<61>tre
if ( pVar == NULL ) { Exception = CBotErrLowParam; return FALSE; }
// qui doit <20>tre une cha<68>ne de caract<63>res
if ( pVar->GivType() != CBotTypString ) { Exception = CBotErrBadString; return FALSE; }
CBotString param = pVar->GivValString();
// r<>cup<75>re l'<27>l<EFBFBD>ment "handle"
pVar = pThis->GivItem("handle");
if ( pVar->GivInit() != IS_DEF) { Exception = CBotErrNotOpen; return FALSE; }
FILE* pFile= (FILE*)pVar->GivValInt();
int res = fputs(param+"\n", pFile);
// en cas d'erreur g<>n<EFBFBD>re une exception
if ( res < 0 ) { Exception = CBotErrWrite; return FALSE; }
return TRUE;
}
// compilation
CBotTypResult cfwrite (CBotVar* pThis, CBotVar* &pVar)
{
// il doit y avoir un param<61>tre
if ( pVar == NULL ) return CBotTypResult( CBotErrLowParam );
// qui doit <20>tre une cha<68>ne de caract<63>res
if ( pVar->GivType() != CBotTypString ) return CBotTypResult( CBotErrBadString );
// pas d'autre param<61>tre
if ( pVar->GivNext() != NULL ) return CBotTypResult( CBotErrOverParam );
// la fonction retourne un r<>sultat void
return CBotTypResult( 0 );
}
// m<>thode FILE :: readln
// ex<65>cution
BOOL rfread (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
{
// il ne doit pas y avoir de param<61>tre
if ( pVar != NULL ) { Exception = CBotErrOverParam; return FALSE; }
// r<>cup<75>re l'<27>l<EFBFBD>ment "handle"
pVar = pThis->GivItem("handle");
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;
// en cas d'erreur g<>n<EFBFBD>re une exception
if ( ferror(pFile) ) { Exception = CBotErrRead; return FALSE; }
pResult->SetValString( chaine );
return TRUE;
}
// compilation
CBotTypResult cfread (CBotVar* pThis, CBotVar* &pVar)
{
// il ne doit pas y avoir de param<61>tre
if ( pVar != NULL ) return CBotTypResult( CBotErrOverParam );
// la fonction retourne un r<>sultat "string"
return CBotTypResult( CBotTypString );
}
// m<>thode FILE :: readln
// ex<65>cution
BOOL rfeof (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
{
// il ne doit pas y avoir de param<61>tre
if ( pVar != NULL ) { Exception = CBotErrOverParam; return FALSE; }
// r<>cup<75>re l'<27>l<EFBFBD>ment "handle"
pVar = pThis->GivItem("handle");
if ( pVar->GivInit() != IS_DEF) { Exception = CBotErrNotOpen; return FALSE; }
FILE* pFile= (FILE*)pVar->GivValInt();
pResult->SetValInt( feof( pFile ) );
return TRUE;
}
// compilation
CBotTypResult cfeof (CBotVar* pThis, CBotVar* &pVar)
{
// il ne doit pas y avoir de param<61>tre
if ( pVar != NULL ) return CBotTypResult( CBotErrOverParam );
// la fonction retourne un r<>sultat booleen
return CBotTypResult( CBotTypBoolean );
}
void InitClassFILE()
{
// cr<63>e une classe pour la gestion des fichiers
// l'utilisation en est la suivante:
// file canal( "NomFichier.txt" )
// canal.open( "r" ); // ouvre en lecture
// s = canal.readln( ); // lit une ligne
// canal.close(); // referme le fichier
// cr<63>e la classe FILE
m_pClassFILE = new CBotClass("file", NULL);
// ajoute le composant ".filename"
m_pClassFILE->AddItem("filename", CBotTypString);
// ajoute le composant ".handle"
m_pClassFILE->AddItem("handle", CBotTypInt, PR_PRIVATE);
// d<>fini un constructeur et un destructeur
m_pClassFILE->AddFunction("file", rfconstruct, cfconstruct );
m_pClassFILE->AddFunction("~file", rfdestruct, NULL );
// d<>fini les m<>thodes associ<63>es
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);
m_pFuncFile->SetIdent(-2); // identificateur sp<73>cial pour RestoreState dans cette fonction
}