This repository has been archived on 2022-06-27. You can view files and clone it, but cannot push or open issues or pull requests.
Xash3DArchive/engine/common/infostring.c

495 lines
8.7 KiB
C
Raw Normal View History

2011-05-09 22:00:00 +02:00
/*
infostring.c - network info strings
Copyright (C) 2008 Uncle Mike
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.
*/
2008-08-03 22:00:00 +02:00
#include "common.h"
2017-02-12 22:00:00 +01:00
#define MAX_KV_SIZE 128
2008-08-03 22:00:00 +02:00
/*
=======================================================================
INFOSTRING STUFF
=======================================================================
*/
/*
===============
Info_Print
printing current key-value pair
===============
*/
2009-11-23 22:00:00 +01:00
void Info_Print( const char *s )
2008-08-03 22:00:00 +02:00
{
2017-02-12 22:00:00 +01:00
char key[MAX_KV_SIZE];
char value[MAX_KV_SIZE];
int l, count;
2008-08-03 22:00:00 +02:00
char *o;
2009-11-23 22:00:00 +01:00
if( *s == '\\' ) s++;
2008-08-03 22:00:00 +02:00
2009-11-23 22:00:00 +01:00
while( *s )
2008-08-03 22:00:00 +02:00
{
2017-02-12 22:00:00 +01:00
count = 0;
2008-08-03 22:00:00 +02:00
o = key;
2017-02-12 22:00:00 +01:00
while( count < (MAX_KV_SIZE - 1) && *s && *s != '\\' )
{
2009-11-23 22:00:00 +01:00
*o++ = *s++;
2017-02-12 22:00:00 +01:00
count++;
}
2008-08-03 22:00:00 +02:00
l = o - key;
2009-11-23 22:00:00 +01:00
if( l < 20 )
2008-08-03 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
memset( o, ' ', 20 - l );
2008-08-03 22:00:00 +02:00
key[20] = 0;
}
else *o = 0;
2017-02-12 22:00:00 +01:00
2018-03-03 22:00:00 +01:00
Con_Printf( "%s", key );
2008-08-03 22:00:00 +02:00
2009-11-23 22:00:00 +01:00
if( !*s )
2008-08-03 22:00:00 +02:00
{
2018-03-03 22:00:00 +01:00
Con_Printf( "(null)\n" );
2008-08-03 22:00:00 +02:00
return;
}
2017-02-12 22:00:00 +01:00
count = 0;
2008-08-03 22:00:00 +02:00
o = value;
s++;
2017-02-12 22:00:00 +01:00
while( count < (MAX_KV_SIZE - 1) && *s && *s != '\\' )
{
2009-11-23 22:00:00 +01:00
*o++ = *s++;
2017-02-12 22:00:00 +01:00
count++;
}
2008-08-03 22:00:00 +02:00
*o = 0;
2009-11-23 22:00:00 +01:00
if( *s ) s++;
2018-03-03 22:00:00 +01:00
Con_Printf( "%s\n", value );
2008-08-03 22:00:00 +02:00
}
}
2017-02-12 22:00:00 +01:00
/*
==============
Info_IsValid
check infostring for potential problems
==============
*/
qboolean Info_IsValid( const char *s )
{
char key[MAX_KV_SIZE];
char value[MAX_KV_SIZE];
int count;
char *o;
if( *s == '\\' ) s++;
while( *s )
{
count = 0;
o = key;
while( count < (MAX_KV_SIZE - 1) && *s && *s != '\\' )
{
*o++ = *s++;
count++;
}
*o = 0;
if( !*s ) return false;
count = 0;
o = value;
s++;
while( count < (MAX_KV_SIZE - 1) && *s && *s != '\\' )
{
*o++ = *s++;
count++;
}
*o = 0;
if( !Q_strlen( value ))
return false;
if( *s ) s++;
}
return true;
}
/*
==============
Info_WriteVars
==============
*/
void Info_WriteVars( file_t *f )
{
char *s = CL_Userinfo();
char pkey[MAX_SERVERINFO_STRING];
static char value[4][MAX_SERVERINFO_STRING]; // use two buffers so compares work without stomping on each other
static int valueindex;
convar_t *pcvar;
char *o;
valueindex = (valueindex + 1) % 4;
if( *s == '\\' ) s++;
while( 1 )
{
o = pkey;
while( *s != '\\' )
{
if( !*s ) return;
*o++ = *s++;
}
*o = 0;
s++;
o = value[valueindex];
while( *s != '\\' && *s )
{
if( !*s ) return;
*o++ = *s++;
}
*o = 0;
pcvar = Cvar_FindVar( pkey );
if( !pcvar && pkey[0] != '*' ) // don't store out star keys
FS_Printf( f, "setinfo \"%s\" \"%s\"\n", pkey, value[valueindex] );
if( !*s ) return;
s++;
}
}
2008-08-03 22:00:00 +02:00
/*
===============
Info_ValueForKey
Searches the string for the given
key and returns the associated value, or an empty string.
===============
*/
2009-11-10 22:00:00 +01:00
char *Info_ValueForKey( const char *s, const char *key )
2008-08-03 22:00:00 +02:00
{
2017-02-12 22:00:00 +01:00
char pkey[MAX_KV_SIZE];
static char value[4][MAX_KV_SIZE]; // use two buffers so compares work without stomping on each other
2008-08-03 22:00:00 +02:00
static int valueindex;
2017-02-12 22:00:00 +01:00
int count;
2008-08-03 22:00:00 +02:00
char *o;
2017-02-12 22:00:00 +01:00
valueindex = (valueindex + 1) % 4;
2008-08-03 22:00:00 +02:00
if( *s == '\\' ) s++;
2012-12-21 21:00:00 +01:00
2008-08-03 22:00:00 +02:00
while( 1 )
{
2017-02-12 22:00:00 +01:00
count = 0;
2008-08-03 22:00:00 +02:00
o = pkey;
2017-02-12 22:00:00 +01:00
while( count < (MAX_KV_SIZE - 1) && *s != '\\' )
2008-08-03 22:00:00 +02:00
{
2017-02-13 22:00:00 +01:00
if( !*s ) return "";
2008-08-03 22:00:00 +02:00
*o++ = *s++;
2017-02-12 22:00:00 +01:00
count++;
2008-08-03 22:00:00 +02:00
}
2009-11-23 22:00:00 +01:00
2008-08-03 22:00:00 +02:00
*o = 0;
s++;
o = value[valueindex];
2017-02-12 22:00:00 +01:00
count = 0;
2008-08-03 22:00:00 +02:00
2017-02-12 22:00:00 +01:00
while( count < (MAX_KV_SIZE - 1) && *s && *s != '\\' )
2008-08-03 22:00:00 +02:00
{
2009-11-23 22:00:00 +01:00
if( !*s ) return "";
2008-08-03 22:00:00 +02:00
*o++ = *s++;
2017-02-12 22:00:00 +01:00
count++;
2008-08-03 22:00:00 +02:00
}
*o = 0;
2011-03-09 22:00:00 +01:00
if( !Q_strcmp( key, pkey ))
2009-11-23 22:00:00 +01:00
return value[valueindex];
if( !*s ) return "";
2008-08-03 22:00:00 +02:00
s++;
}
}
2010-10-26 22:00:00 +02:00
qboolean Info_RemoveKey( char *s, const char *key )
2008-08-03 22:00:00 +02:00
{
char *start;
2017-02-12 22:00:00 +01:00
char pkey[MAX_KV_SIZE];
char value[MAX_KV_SIZE];
int cmpsize = Q_strlen( key );
int count;
2008-08-03 22:00:00 +02:00
char *o;
2017-02-12 22:00:00 +01:00
if( cmpsize > ( MAX_KV_SIZE - 1 ))
cmpsize = MAX_KV_SIZE - 1;
2011-03-09 22:00:00 +01:00
if( Q_strstr( key, "\\" ))
2009-11-23 22:00:00 +01:00
return false;
2008-08-03 22:00:00 +02:00
2009-11-23 22:00:00 +01:00
while( 1 )
2008-08-03 22:00:00 +02:00
{
start = s;
2009-11-23 22:00:00 +01:00
if( *s == '\\' ) s++;
2017-02-12 22:00:00 +01:00
count = 0;
2008-08-03 22:00:00 +02:00
o = pkey;
2009-11-23 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
while( count < (MAX_KV_SIZE - 1) && *s != '\\' )
2008-08-03 22:00:00 +02:00
{
2009-11-23 22:00:00 +01:00
if( !*s ) return false;
2008-08-03 22:00:00 +02:00
*o++ = *s++;
2017-02-12 22:00:00 +01:00
count++;
2008-08-03 22:00:00 +02:00
}
*o = 0;
s++;
2017-02-12 22:00:00 +01:00
count = 0;
2008-08-03 22:00:00 +02:00
o = value;
2017-02-12 22:00:00 +01:00
while( count < (MAX_KV_SIZE - 1) && *s != '\\' && *s )
2008-08-03 22:00:00 +02:00
{
2009-11-23 22:00:00 +01:00
if( !*s ) return false;
2008-08-03 22:00:00 +02:00
*o++ = *s++;
2017-02-12 22:00:00 +01:00
count++;
2008-08-03 22:00:00 +02:00
}
*o = 0;
2017-02-12 22:00:00 +01:00
if( !Q_strncmp( key, pkey, cmpsize ))
2008-08-03 22:00:00 +02:00
{
2011-03-09 22:00:00 +01:00
Q_strcpy( start, s ); // remove this part
2009-11-23 22:00:00 +01:00
return true;
2008-08-03 22:00:00 +02:00
}
2017-02-12 22:00:00 +01:00
2009-11-23 22:00:00 +01:00
if( !*s ) return false;
2008-08-03 22:00:00 +02:00
}
}
2009-12-04 22:00:00 +01:00
void Info_RemovePrefixedKeys( char *start, char prefix )
{
char *s, *o;
2017-02-12 22:00:00 +01:00
char pkey[MAX_KV_SIZE];
char value[MAX_KV_SIZE];
int count;
2009-12-04 22:00:00 +01:00
s = start;
while( 1 )
{
2017-02-12 22:00:00 +01:00
if( *s == '\\' ) s++;
count = 0;
2009-12-04 22:00:00 +01:00
o = pkey;
2017-02-12 22:00:00 +01:00
while( count < (MAX_KV_SIZE - 1) && *s != '\\' )
2009-12-04 22:00:00 +01:00
{
if( !*s ) return;
*o++ = *s++;
2017-02-12 22:00:00 +01:00
count++;
2009-12-04 22:00:00 +01:00
}
*o = 0;
s++;
2017-02-12 22:00:00 +01:00
count = 0;
2009-12-04 22:00:00 +01:00
o = value;
2017-02-12 22:00:00 +01:00
while( count < (MAX_KV_SIZE - 1) && *s && *s != '\\' )
2009-12-04 22:00:00 +01:00
{
if( !*s ) return;
*o++ = *s++;
2017-02-12 22:00:00 +01:00
count++;
2009-12-04 22:00:00 +01:00
}
*o = 0;
if( pkey[0] == prefix )
{
Info_RemoveKey( start, pkey );
s = start;
}
if( !*s ) return;
}
}
2017-02-12 22:00:00 +01:00
qboolean Info_IsKeyImportant( const char *key )
{
if( key[0] == '*' )
return true;
if( !Q_strcmp( key, "name" ))
return true;
if( !Q_strcmp( key, "model" ))
return true;
if( !Q_strcmp( key, "rate" ))
return true;
if( !Q_strcmp( key, "topcolor" ))
return true;
if( !Q_strcmp( key, "bottomcolor" ))
return true;
if( !Q_strcmp( key, "cl_updaterate" ))
return true;
if( !Q_strcmp( key, "cl_lw" ))
return true;
if( !Q_strcmp( key, "cl_lc" ))
return true;
if( !Q_strcmp( key, "cl_nopred" ))
return true;
return false;
}
2008-08-03 22:00:00 +02:00
2017-02-12 22:00:00 +01:00
char *Info_FindLargestKey( char *s )
2008-08-03 22:00:00 +02:00
{
2017-02-12 22:00:00 +01:00
char key[MAX_KV_SIZE];
char value[MAX_KV_SIZE];
static char largest_key[128];
int largest_size = 0;
int l, count;
char *o;
*largest_key = 0;
if( *s == '\\' ) s++;
while( *s )
{
int size = 0;
count = 0;
o = key;
while( count < (MAX_KV_SIZE - 1) && *s && *s != '\\' )
{
*o++ = *s++;
count++;
}
l = o - key;
*o = 0;
size = Q_strlen( key );
if( !*s ) return largest_key;
count = 0;
o = value;
s++;
while( count < (MAX_KV_SIZE - 1) && *s && *s != '\\' )
{
*o++ = *s++;
count++;
}
*o = 0;
if( *s ) s++;
size += Q_strlen( value );
if(( size > largest_size ) && !Info_IsKeyImportant( key ))
{
Q_strncpy( largest_key, key, sizeof( largest_key ));
largest_size = size;
}
}
return largest_key;
2008-08-03 22:00:00 +02:00
}
2011-10-09 22:00:00 +02:00
qboolean Info_SetValueForStarKey( char *s, const char *key, const char *value, int maxsize )
2008-08-03 22:00:00 +02:00
{
2011-10-09 22:00:00 +02:00
char new[1024], *v;
2017-02-21 22:00:00 +01:00
int c, team;
2008-08-03 22:00:00 +02:00
2011-03-09 22:00:00 +01:00
if( Q_strstr( key, "\\" ) || Q_strstr( value, "\\" ))
2008-08-03 22:00:00 +02:00
{
2018-09-28 23:00:00 +02:00
Con_Printf( S_ERROR "SetValueForKey: can't use keys or values with a \\\n" );
2009-11-23 22:00:00 +01:00
return false;
2008-08-03 22:00:00 +02:00
}
2017-02-12 22:00:00 +01:00
if( Q_strstr( key, ".." ) || Q_strstr( value, ".." ))
2009-11-23 22:00:00 +01:00
return false;
2011-03-09 22:00:00 +01:00
if( Q_strstr( key, "\"" ) || Q_strstr( value, "\"" ))
2008-08-03 22:00:00 +02:00
{
2018-09-28 23:00:00 +02:00
Con_Printf( S_ERROR "SetValueForKey: can't use keys or values with a \"\n" );
2009-11-23 22:00:00 +01:00
return false;
2008-08-03 22:00:00 +02:00
}
2009-11-23 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
if( Q_strlen( key ) > ( MAX_KV_SIZE - 1 ) || Q_strlen( value ) > ( MAX_KV_SIZE - 1 ))
2009-11-23 22:00:00 +01:00
return false;
2008-08-03 22:00:00 +02:00
2009-11-23 22:00:00 +01:00
Info_RemoveKey( s, key );
2011-10-09 22:00:00 +02:00
2011-03-09 22:00:00 +01:00
if( !value || !Q_strlen( value ))
2011-10-09 22:00:00 +02:00
return true; // just clear variable
2008-08-03 22:00:00 +02:00
2017-02-12 22:00:00 +01:00
Q_snprintf( new, sizeof( new ), "\\%s\\%s", key, value );
2011-10-09 22:00:00 +02:00
if( Q_strlen( new ) + Q_strlen( s ) > maxsize )
2008-08-03 22:00:00 +02:00
{
2017-02-12 22:00:00 +01:00
// no more room in buffer to add key/value
if( Info_IsKeyImportant( key ))
{
// keep removing the largest key/values until we have room
char *largekey;
do
{
largekey = Info_FindLargestKey( s );
Info_RemoveKey( s, largekey );
} while((( Q_strlen( new ) + Q_strlen( s )) >= maxsize ) && *largekey != 0 );
if( largekey[0] == 0 )
{
// no room to add setting
return true; // info changed, new value can't saved
}
}
else
{
// no room to add setting
return true; // info changed, new value can't saved
}
2008-08-03 22:00:00 +02:00
}
// only copy ascii values
2011-03-09 22:00:00 +01:00
s += Q_strlen( s );
2011-10-09 22:00:00 +02:00
v = new;
2009-11-23 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
team = ( Q_stricmp( key, "team" ) == 0 ) ? true : false;
2009-11-23 22:00:00 +01:00
while( *v )
2008-08-03 22:00:00 +02:00
{
2017-02-12 22:00:00 +01:00
c = (byte)*v++;
2017-02-21 22:00:00 +01:00
if( team ) c = Q_tolower( c );
2017-02-12 22:00:00 +01:00
if( c > 13 ) *s++ = c;
2008-08-03 22:00:00 +02:00
}
*s = 0;
2009-11-23 22:00:00 +01:00
// all done
return true;
2008-08-03 22:00:00 +02:00
}
2017-02-12 22:00:00 +01:00
qboolean Info_SetValueForKey( char *s, const char *key, const char *value, int maxsize )
2011-10-09 22:00:00 +02:00
{
if( key[0] == '*' )
{
2018-09-28 23:00:00 +02:00
Con_Printf( S_ERROR "Can't set *keys\n" );
2011-10-09 22:00:00 +02:00
return false;
}
2017-02-12 22:00:00 +01:00
return Info_SetValueForStarKey( s, key, value, maxsize );
2008-08-03 22:00:00 +02:00
}