// Ryzom - MMORPG Framework
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
#include "stdpch.h"
#include "cst_loader.h"
using namespace std;
using namespace NLMISC;
/****************************************************************\
buildTableFormat()
\****************************************************************/
void CSTLoader::buildTableFormat( string fileName, list >& tableFormat )
{
_File = new ifstream(fileName.c_str(), ios::in);
if( !_File->is_open() )
{
nlerror("can't open file : %s\n", fileName.c_str());
}
// read first line
//================
char readBuffer[4096];
char * token;
_File->getline(readBuffer, 4096);
// extract first token
//====================
token = strtok(readBuffer, _Seps.c_str());
// extract type from token
string stoken = string( token );
sint typeStart = stoken.find_last_of("<");
nlassert(typeStart != -1);
sint typeEnd = stoken.find_first_of(">",typeStart);
nlassert(typeEnd != -1);
string type_str = stoken.substr( typeStart+1, (typeEnd-typeStart-1) );
TDataType type_enum = convertType(type_str);
// extract column label from token
string toConvert(stoken.substr(0,typeStart));
string label = convertName( toConvert );
// string label = stoken.substr(0,typeStart);
// insert pair (label,type)
tableFormat.push_back( make_pair( label, type_enum ) );
// extract next tokens
//====================
while( token != NULL )
{
token = strtok(NULL, _Seps.c_str());
if(token != NULL)
{
stoken = string( token );
// extract type from token
typeStart = stoken.find_last_of("<");
nlassert(typeStart != -1);
typeEnd = stoken.find_first_of(">",typeStart);
nlassert(typeEnd != -1);
type_str = stoken.substr( typeStart+1, (typeEnd-typeStart-1) );
type_enum = convertType(type_str);
// extract column label from token
string toConvert(stoken.substr(0,typeStart));
label = convertName( toConvert );
// label = stoken.substr(0,typeStart);
// insert pair (label,type)
tableFormat.push_back( make_pair( label, type_enum ) );
}
}
}
/****************************************************************\
readData()
\****************************************************************/
void CSTLoader::readData( list >& data )
{
char readBuffer[4096];
char * token;
bool firstToken = true;
while( !_File->eof() )
{
// list of current object values
list lineData;
// read a line
_File->getline(readBuffer, 4096);
// check all tokens of the current line
do
{
if( firstToken )
{
// extract first token
token = strtok(readBuffer, _Seps.c_str());
firstToken = false;
}
else
{
// extract next token
token = strtok(NULL, _Seps.c_str());
}
if( token != NULL )
{
string stoken( token );
lineData.push_back( stoken );
}
}
while( token != NULL );
firstToken = true;
if( lineData.size() )
{
data.push_back( lineData );
}
}
}
/****************************************************************\
generateDerivedClasses()
\****************************************************************/
void CSTLoader::generateDerivedClasses(ofstream &file, std::list< std::pair > &format, std::list< std::list< std::string> > &data )
{
std::list< std::list< std::string> >::iterator it_dl = data.begin();
while ( it_dl != data.end() )
{
std::list< std::pair >::iterator it_def = format.begin();
std::list::iterator it_val = (*it_dl).begin();
// sint32 size = data.size();
// sint32 size2 = (*it_dl).size();
// std::string name = convertName( *it_val );
// std::string test = *it_val;
if ( (*it_dl).size() )
{
file << "From Item : Define " << convertName( *it_val ) << endl;
it_val++;
it_def++;
file << "{" << endl;
file << "\tComponent:" << endl;
}
std::list< std::pair >::iterator it_obj = format.begin();
it_obj++;
while ( it_obj != format.end() )
{
file << "\t\t";
switch ( (*it_obj).second )
{
case UINT8:
file << "uint8";
break;
case SINT8:
file << "sint8";
break;
case UINT16:
file << "uint16";
break;
case SINT16:
file << "sint16";
break;
case UINT32:
file << "uint32";
break;
case SINT32:
file << "sint32";
break;
case FLOAT:
file << "Float";
break;
case STRING:
file << "String";
break;
case BOOL:
file << "Bool";
break;
}
file << "<'" << (*it_obj).first << "', Static>;" << endl;
it_obj++;
}
file << "\tEnd" << endl << endl;
file << "\t StaticInit()" << endl;
while ( it_def != format.end() && it_val != (*it_dl).end() )
{
#ifdef NL_DEBUG
std::string test1 = *it_val;
std::string test2 = (*it_def).first;
#endif
file << "\t\t" << (*it_def).first << " = ";
switch ( (*it_def).second )
{
case UINT8:
file << "new uint8(" << convertName(*it_val);
break;
case SINT8:
file << "new sint8(" << convertName(*it_val);
break;
case UINT16:
file << "new uint16(" << convertName(*it_val);
break;
case SINT16:
file << "new sint16(" << convertName(*it_val);
break;
case UINT32:
file << "new uint32(" << convertName(*it_val);
break;
case SINT32:
file << "new sint32(" << convertName(*it_val);
break;
case FLOAT:
file << "new Float(" <& fileFormat)
{
_FileFormat = fileFormat;
_FileName = fileName;
_File = new ifstream(fileName.c_str(), ios::in);
if( !_File->is_open() )
{
nlerror("can't open file : %s\n", fileName.c_str());
}
// read first line
char readBuffer[4096];
char * token;
_File->getline(readBuffer, 4096);
// extract first token
token = strtok(readBuffer, _Seps.c_str());
_Columns.push_back( string(token) );
// extract next tokens
while( token != NULL )
{
token = strtok(NULL, _Seps.c_str());
if(token != NULL)
{
_Columns.push_back( string(token) );
}
}
}
/****************************************************************\
readLine()
\****************************************************************/
bool CSTLoader::readLine()
{
if( _File->eof() )
{
return false;
}
const uint nbColumn = _Columns.size();
char readBuffer[4096];
char * token;
bool firstToken = true;
uint j = 0;
string columnLabel;
map::iterator itf;
// erase all previous values
_Tokens.clear();
// read a line
_File->getline(readBuffer, 4096);
// if the line is empty we consider we are at end of file
if( strlen(readBuffer) == 0)
{
//nlinfo("CSTLoader: empty line in file '%s'", _FileName.c_str());
return false;
}
// check all tokens of the current line
do
{
if( firstToken )
{
// extract first token
token = strtok(readBuffer, _Seps.c_str());
firstToken = false;
}
else
{
// extract next token
token = strtok(NULL, _Seps.c_str());
}
if( token != NULL )
{
// label of token column
nlassert( j < nbColumn);
columnLabel = _Columns[j];
// look for column data type
itf = _FileFormat.find( columnLabel );
if( itf != _FileFormat.end() )
{
// check data type validity
switch( (*itf).second )
{
case UINT8 :
case SINT8 :
case UINT16 :
case SINT16 :
case UINT32 :
case SINT32 :
{
sint32 tmp;
fromString((const char*)token, tmp);
if( tmp == 0 )
{
if( token[0] != '0' )
{
nlerror("Data type error at column %s, at line %d : not an integer",columnLabel.c_str(),_LineCount);
}
}
}
break;
case FLOAT :
{
double tmp;
fromString((const char*)token, tmp);
if( tmp == 0.0 )
{
if( token[0] != '0' )
{
nlerror("Data type error at column %s, at line %d : not a float",columnLabel.c_str(),_LineCount);
}
}
}
break;
case BOOL :
if( strcmp(token,"0") && strcmp(token,"1") )
{
nlerror("Data type error at column %s, at line %d : not a bool",columnLabel.c_str(),_LineCount);
}
break;
default:
break;
}
// we keep the pair
_Tokens.erase(columnLabel); // do not forget to delete the old value (insert does not assure proper remplacement)
_Tokens.insert( make_pair(columnLabel,string(token)) );
}
// if this column is not expected by the user we go on to next token
else
{
nlinfo("%s : this colum is not in the file format",columnLabel.c_str());
}
}
++j;
}
while( token != NULL );
++_LineCount;
return true;
}