source-engine/common/info_key.cpp

304 lines
4.4 KiB
C++
Raw Normal View History

2020-04-22 16:56:21 +00:00
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "info_key.h"
#include <stdio.h>
#include <string.h>
#include "tier1/strtools.h"
#define MAX_KV_LEN 127
/*
===============
Info_ValueForKey
Searches the string for the given
key and returns the associated value, or an empty string.
===============
*/
const char *Info_ValueForKey ( const char *s, const char *key )
{
char pkey[512];
static char value[4][512]; // use two buffers so compares
// work without stomping on each other
static int valueindex;
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;
if (!stricmp(key, pkey) )
return value[valueindex];
if (!*s)
return "";
s++;
}
}
void Info_RemoveKey ( char *s, const char *key )
{
char *start;
char pkey[512];
char value[512];
char *o;
if (strstr (key, "\\"))
{
return;
}
while (1)
{
start = s;
if (*s == '\\')
s++;
o = pkey;
while (*s != '\\')
{
if (!*s)
return;
*o++ = *s++;
}
*o = 0;
s++;
o = value;
while (*s != '\\' && *s)
{
if (!*s)
return;
*o++ = *s++;
}
*o = 0;
if (!stricmp (key, pkey) )
{
// This is safe because we're copying within the same string
Q_strcpy (start, s); // remove this part
return;
}
if (!*s)
return;
}
}
void Info_RemovePrefixedKeys (char *start, char prefix)
{
char *s;
char pkey[512];
char value[512];
char *o;
s = start;
while (1)
{
if (*s == '\\')
s++;
o = pkey;
while (*s != '\\')
{
if (!*s)
return;
*o++ = *s++;
}
*o = 0;
s++;
o = value;
while (*s != '\\' && *s)
{
if (!*s)
return;
*o++ = *s++;
}
*o = 0;
if (pkey[0] == prefix)
{
Info_RemoveKey (start, pkey);
s = start;
}
if (!*s)
return;
}
}
bool Info_IsKeyImportant( const char *key )
{
if ( key[0] == '*' )
return true;
if ( !stricmp( key, "tracker" ) )
return true;
return false;
}
char *Info_FindLargestKey( char *s, int maxsize )
{
char key[256];
char value[256];
char *o;
int l;
static char largest_key[256];
int largest_size = 0;
*largest_key = 0;
if (*s == '\\')
s++;
while (*s)
{
int size = 0;
o = key;
while (*s && *s != '\\')
*o++ = *s++;
l = o - key;
*o = 0;
size = strlen( key );
if (!*s)
{
return largest_key;
}
o = value;
s++;
while (*s && *s != '\\')
*o++ = *s++;
*o = 0;
if (*s)
s++;
size += strlen( value );
if ( (size > largest_size) && !Info_IsKeyImportant(key) )
{
largest_size = size;
Q_strncpy( largest_key, key, sizeof( largest_key ) );
}
}
return largest_key;
}
void Info_SetValueForStarKey ( char *s, const char *key, const char *value, int maxsize )
{
char news[1024], *v;
int c;
if (strstr (key, "\\") || strstr (value, "\\") )
{
return;
}
if (strstr (key, "..") || strstr (value, "..") )
{
// Con_Printf ("Can't use keys or values with a ..\n");
return;
}
if (strstr (key, "\"") || strstr (value, "\"") )
{
return;
}
if (strlen(key) > MAX_KV_LEN || strlen(value) > MAX_KV_LEN)
{
return;
}
Info_RemoveKey (s, key);
if (!value || !strlen(value))
return;
Q_snprintf (news, sizeof( news ), "\\%s\\%s", key, value);
if ( (int)(strlen(news) + strlen(s)) >= maxsize)
{
// 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, maxsize );
Info_RemoveKey( s, largekey );
} while ( ((int)(strlen(news) + strlen(s)) >= maxsize) && *largekey != 0 );
if ( largekey[0] == 0 )
{
// no room to add setting
return;
}
}
else
{
// no room to add setting
return;
}
}
// only copy ascii values
s += strlen(s);
v = news;
while (*v)
{
c = (unsigned char)*v++;
// Strip out high ascii characters
c &= 127;
if (c > 13)
{
*s++ = c;
}
}
*s = 0;
}
void Info_SetValueForKey (char *s, const char *key, const char *value, int maxsize)
{
if (key[0] == '*')
{
return;
}
Info_SetValueForStarKey (s, key, value, maxsize);
}