khanat-opennel-code/code/ryzom/common/src/game_share/cst_loader.h
2010-05-06 02:08:41 +02:00

337 lines
8.1 KiB
C++

// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// 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 <http://www.gnu.org/licenses/>.
#ifndef CST_LOADER_H
#define CST_LOADER_H
#include "nel/misc/types_nl.h"
#include "nel/misc/debug.h"
#include <map>
#include <vector>
#include <string>
#include <fstream>
/**
* CSTLoader
* \author Stephane Coutelas
* \author Nevrax France
* \date 2001
*/
class CSTLoader
{
public:
/// data type
enum TDataType
{
UINT8,
SINT8,
UINT16,
SINT16,
UINT32,
SINT32,
FLOAT,
STRING,
BOOL
};
private:
/// cst file
std::ifstream * _File;
/// name of the cst file (used for debug information)
std::string _FileName;
/// separators
std::string _Seps;
/// current line in the file
uint _LineCount;
/// columns label of the actually readen data file
std::vector<std::string> _Columns;
/// file format expected
std::map<std::string,TDataType> _FileFormat;
/// tokens for each expected columns
std::map<std::string, std::string> _Tokens;
public:
/// constructor
CSTLoader()
{
_Seps = "\t;";
_LineCount = 0;
}
/**
* Set the separators to extract tokens
* \param seps all characters than can be a separator
*/
void setSeparators( std::string seps )
{
_Seps = seps;
}
/**
* (For files respecting the dynamical column label format : name<type>)
* Open a file, and init the file format. Each column has a label and a data type
*
* \param fileName the name of the file
* \param fileFormat the name of the columns and their data type
*/
void buildTableFormat( std::string fileName, std::list<std::pair< std::string,TDataType> >& tableFormat );
/**
* (For files respecting the dynamical column label format : name<type>)
* Read all the data of the file. For each object it fills a list of value(string)
*
* \param data the list of the name of the columns and their data type
*/
void readData( std::list<std::list<std::string> >& data );
/**
* Open a file, and init the file format
* \param fileName the name of the file
* \param fileFormat the name of the columns and their data type
*/
void init( std::string fileName, const std::map<std::string,TDataType>& fileFormat);
/**
* read a line in the file and check validity of token data type
* \return false if the ned of file has been reached, true else.
*/
bool readLine();
/**
* return the value corresponding to the given column in the current file line
* \param value a value in the table
*/
template<class T> void getValue( const std::string& columnLabel, T& value )
{
std::map<std::string,std::string>::const_iterator itt = _Tokens.find( columnLabel );
if( itt == _Tokens.end() )
{
nlerror("The value for the column %s has not been read in the line",columnLabel.c_str());
}
std::map<std::string,TDataType>::const_iterator itf = _FileFormat.find( columnLabel );
if( itf == _FileFormat.end() )
{
nlerror("The column %s is not in the file format",columnLabel.c_str());
}
nlassert( (*itf).second != STRING && (*itf).second != BOOL );
switch( (*itf).second )
{
case UINT8 :
case SINT8 :
case UINT16 :
case SINT16 :
case UINT32 :
case SINT32 :
case FLOAT :
fromString((*itt).second, value);
break;
}
}
/**
* return the string value corresponding to the given column in the current file line
* \param value a string value in the table
*/
void getStringValue( const std::string& columnLabel, std::string& value )
{
std::map<std::string,std::string>::const_iterator itt = _Tokens.find( columnLabel );
if( itt == _Tokens.end() )
{
nlerror("The value for the column %s has not been read in the line",columnLabel.c_str());
}
std::map<std::string,TDataType>::const_iterator itf = _FileFormat.find( columnLabel );
if( itf == _FileFormat.end() )
{
nlerror("The column %s is not in the file format",columnLabel.c_str());
}
nlassert( (*itf).second == STRING );
value = (*itt).second;
}
/**
* return the bool value corresponding to the given column in the current file line
* \param value a bool value in the table
*/
void getBoolValue( const std::string& columnLabel, bool& value )
{
std::map<std::string,std::string>::const_iterator itt = _Tokens.find( columnLabel );
if( itt == _Tokens.end() )
{
nlerror("The value for the column %s has not been read in the line",columnLabel.c_str());
}
std::map<std::string,TDataType>::const_iterator itf = _FileFormat.find( columnLabel );
if( itf == _FileFormat.end() )
{
nlerror("The column %s is not in the file format",columnLabel.c_str());
}
nlassert( (*itf).second == BOOL );
NLMISC::fromString((*itt).second, value);
}
/// close file
void close()
{
_File->close();
delete _File;
}
void Load(std::string fileName,std::ofstream &script_file)
{
// Generates the base class
std::list< std::pair<std::string,TDataType> > format;
buildTableFormat( fileName, format );
generateBaseClass( script_file, format);
// Generates a derived class for each type of object
std::list< std::list<std::string> > data;
readData( data );
generateDerivedClasses( script_file, format, data );
}
void generateBaseClass(std::ofstream &file, std::list< std::pair<std::string,TDataType> > &/* format */)
{
file << "From Agent : Define Item" << std::endl;
file << "{" << std::endl;
/* file << "\tComponent:" << std::endl;
std::list< std::pair<std::string,TDataType> >::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>;" << std::endl;
it_obj++;
}
file << "\tEnd" << std::endl;*/
file << "}" << std::endl;
file << std::endl;
}
void generateDerivedClasses(std::ofstream &, std::list< std::pair<std::string, TDataType> > &, std::list< std::list< std::string> > &);
TDataType convertType(std::string type_str)
{
if ( type_str == "UINT8")
return UINT8;
if ( type_str == "SINT8")
return SINT8;
if ( type_str == "UINT16")
return UINT16;
if ( type_str == "SINT16")
return SINT16;
if ( type_str == "UINT32")
return UINT32;
if ( type_str == "SINT32")
return SINT32;
if ( type_str == "FLOAT")
return FLOAT;
if ( type_str == "STRING")
return STRING;
if ( type_str == "BOOL")
return BOOL;
return (TDataType)0;
}
std::string convertName(std::string &name)
{
int i = 0;
char buffer[1024];
std::string::iterator it_c = name.begin();
while ( it_c != name.end() )
{
char c = *it_c;
switch ( c )
{
case ' ':
case '.':
buffer[i] = '_';
break;
case ',':
buffer[i] = '.';
break;
default:
buffer[i] = *it_c;
}
i++;
it_c++;
}
buffer[i] = 0;
return std::string( buffer );
}
};
#endif // CST_LOADER_H