jedi-academy/code/ff/ff_ConfigParser.cpp
2013-04-23 16:54:20 +10:00

483 lines
8.6 KiB
C++

#include "common_headers.h"
#ifdef _IMMERSION
//#include "ff_ConfigParser.h"
//#include "ifc.h"
//#include "ff_utils.h"
////--------------------
/// FFConfigParser::Init
//------------------------
// Reads the force feedback configuration file. Call this once after the device
// is initialized.
//
// Parameters:
// * filename
//
// Returns:
// * qtrue - the effects set directory has been set according to the initialized
// device. (See base/fffx/fffx.cfg)
// * qfalse - no effects set could be determined for this device.
//
qboolean FFConfigParser::Init( const char *filename )
{
Clear(); // Always cleanup
return qboolean( filename && Parse( LoadFile( filename ) ) );
}
////---------------------
/// FFConfigParser::Clear
//-------------------------
//
//
// Parameters:
//
// Returns:
//
void FFConfigParser::Clear( void )
{
mMap.clear();
mDefaultSet.clear();
}
////---------------------
/// FFConfigParser::Parse
//-------------------------
//
//
// Parameters:
//
// Returns:
//
qboolean FFConfigParser::Parse( void *file )
{
qboolean result = qboolean( file != NULL );
if ( file )
{
const char *token = 0, *pos = (const char*)file;
for
( token = COM_ParseExt( &pos, qtrue )
; token[ 0 ]
&& result // fail if any problem
; token = COM_ParseExt( &pos, qtrue )
){
if ( !Q_stricmp( token, "ffdefaults" ) )
{
result &= ParseDefaults( &pos );
}
else
if ( !Q_stricmp( token, "ffsets" ) )
{
result &= ParseSets( &pos );
}
else
{
// unexpected field
result = qfalse;
}
}
FS_FreeFile( file );
}
return result;
}
////---------------------------------
/// FFConfigParser::ParseDefaultBlock
//-------------------------------------
//
//
// Parameters:
//
// Returns:
//
qboolean FFConfigParser::ParseDefault( const char **pos, TDeviceType &defaultSet )
{
qboolean result = qboolean( pos != NULL );
if ( pos )
{
char *token = COM_ParseExt( pos, qtrue );
if ( token[ 0 ] == '{' )
{
for
( token = COM_ParseExt( pos, qtrue )
; token[ 0 ]
&& token[ 0 ] != '}'
&& result // fail if any problem
; token = COM_ParseExt( pos, qtrue )
){
int device = 0;
if ( sscanf( token, "%d", &device ) )
{
string &str = defaultSet[ device ];
if ( !str.size() )
{
str = COM_ParseExt( pos, qfalse );
result &= qboolean( str.size() > 0 );
}
else
{
result = qfalse;
#ifdef FF_PRINT
ConsoleParseError
( "Redefinition of DeviceType index"
, token
);
#endif
}
}
else
{
result = qfalse;
#ifdef FF_PRINT
ConsoleParseError
( "DeviceType field should begin with an integer"
, token
);
#endif
}
}
}
}
return result;
}
////----------------------------
/// FFConfigParser::ParseDefault
//--------------------------------
//
//
// Parameters:
//
// Returns:
//
qboolean FFConfigParser::ParseDefaults( const char **pos )
{
qboolean result = qboolean( pos != NULL );
if ( pos )
{
char *token = COM_ParseExt( pos, qtrue );
if ( token[ 0 ] == '{' )
{
for
( token = COM_ParseExt( pos, qtrue )
; token[ 0 ]
&& token[ 0 ] != '}'
&& result // fail if any problem
; token = COM_ParseExt( pos, qtrue )
){
int techType = 0;
if ( sscanf( token, "%d", &techType ) )
{
TDeviceType &deviceType = mDefaultSet[ techType ];
if ( !deviceType.size() )
{
result &= ParseDefault( pos, deviceType );
mDefaultPriority.push_back( techType );
}
else
{
result = qfalse;
#ifdef FF_PRINT
ConsoleParseError
( "Redefinition of TechType index"
, token
);
#endif
}
}
else
{
result = qfalse;
#ifdef FF_PRINT
ConsoleParseError
( "TechType fields should begin with integers"
, token
);
#endif
}
}
}
else
{
// expected '{'
result = qfalse;
}
}
return result;
}
////--------------------------
/// FFConfigParser::RightOfSet
//------------------------------
//
//
// Parameters:
//
// Returns:
//
const char* FFConfigParser::RightOfSet( const char *effectname )
{
const char *s = effectname;
// Check through all set names and test effectname against it
for
( TMap::iterator itMap = mMap.begin()
; itMap != mMap.end() && s == effectname
; itMap++
){
s = RightOf( effectname, (*itMap).first.c_str() );
}
return s ? s : effectname;
}
qboolean FFConfigParser::ParseSetDevices( const char **pos, TDevice &device )
{
qboolean result = qboolean( pos != NULL );
if ( pos )
{
char *token = COM_ParseExt( pos, qtrue );
if ( token[ 0 ] == '{' )
{
for
( token = COM_ParseExt( pos, qtrue )
; token[ 0 ]
&& token[ 0 ] != '}'
&& result // fail if any problem
; token = COM_ParseExt( pos, qtrue )
){
device.insert( token );
}
result = qboolean( token[ 0 ] != 0 );
}
else
{
// expected '{'
result = qfalse;
}
}
return result;
}
qboolean FFConfigParser::ParseSetIncludes( const char **pos, TInclude &include )
{
qboolean result = qboolean( pos != NULL );
if ( pos )
{
char *token = COM_ParseExt( pos, qtrue );
if ( token[ 0 ] == '{' )
{
for
( token = COM_ParseExt( pos, qtrue )
; token[ 0 ]
&& token[ 0 ] != '}'
&& result // fail if any problem
; token = COM_ParseExt( pos, qtrue )
){
include.push_back( token );
}
result = qboolean( token[ 0 ] != 0 );
}
else
{
// expected '{'
result = qfalse;
}
}
return result;
}
qboolean FFConfigParser::ParseSet( const char **pos, TData &data )
{
qboolean result = qboolean( pos != NULL );
if ( pos )
{
const char *oldpos = *pos; // allows set declarations with no attributes to have no "{}"
char *token = COM_ParseExt( pos, qtrue );
if ( token[ 0 ] == '{' )
{
for
( token = COM_ParseExt( pos, qtrue )
; token[ 0 ]
&& token[ 0 ] != '}'
&& result // fail if any problem
; token = COM_ParseExt( pos, qtrue )
){
if ( !Q_stricmp( token, "includes" ) )
{
result &= ParseSetIncludes( pos, data.include );
}
else
if ( !Q_stricmp( token, "devices" ) )
{
result &= ParseSetDevices( pos, data.device );
}
else
{
result = qfalse;
#ifdef FF_PRINT
ConsoleParseError
( "Invalid set parameter. Should be 'includes' or 'devices'"
, token
);
#endif
}
}
}
else
{
// expected '{' (no longer expected!)
//result = qfalse; (no longer an error!)
*pos = oldpos;
}
}
return result;
}
////-------------------------
/// FFConfigParser::ParseSets
//-----------------------------
//
//
// Parameters:
//
// Returns:
//
qboolean FFConfigParser::ParseSets( const char **pos )
{
qboolean result = qboolean( pos != NULL );
string groupName;
if ( pos )
{
char *token = COM_ParseExt( pos, qtrue );
if ( token[ 0 ] == '{' )
{
for
( token = COM_ParseExt( pos, qtrue )
; token[ 0 ]
&& token[ 0 ] != '}'
&& result // fail if any problem
; token = COM_ParseExt( pos, qtrue )
){
TData &data = mMap[ token ];
result &= ParseSet( pos, data );
}
}
else
{
// expected '{'
result = qfalse;
}
}
return result;
}
////---------------------------
/// FFConfigParser::GetIncludes
//-------------------------------
//
//
// Parameters:
//
// Returns:
//
FFConfigParser::TInclude& FFConfigParser::GetIncludes( const char *name )
{
TMap::iterator itMap = mMap.find( name );
if ( itMap != mMap.end() )
return (*itMap).second.include;
// No includes present
static TInclude emptyInclude;
return emptyInclude;
}
const char * FFConfigParser::GetFFSet( CImmDevice *Device )
{
char devName[ FF_MAX_PATH ];
const char *ffset = NULL;
//
// Check explicit name
//
devName[0] = 0;
Device->GetProductName( devName, FF_MAX_PATH - 1 );
for
( TMap::iterator itmap = mMap.begin()
; itmap != mMap.end()
; itmap++
){
TDevice::iterator itdev;
itdev = (*itmap).second.device.find( devName );
if ( itdev != (*itmap).second.device.end() )
ffset = (*itmap).first.c_str();
}
//
// Check device defaults
//
for
( int i = 0
; !ffset && i < mDefaultPriority.size()
; i++
){
int defaultTechType;
DWORD productType = Device->GetProductType();
WORD deviceType = HIWORD( productType );
WORD techType = LOWORD( productType );
defaultTechType = mDefaultPriority[ i ];
//
// Check for minimum required features
//
if ( (techType & defaultTechType) >= defaultTechType )
{
//
// Check that device exists in this technology section
//
TDeviceType::iterator itDeviceType = mDefaultSet[ defaultTechType ].find( deviceType );
if ( itDeviceType != mDefaultSet[ defaultTechType ].end() )
{
ffset = (*itDeviceType).second.c_str();
}
}
//
// If not, try next technology section
//
}
return ffset;
}
#endif // _IMMERSION