You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
303 lines
4.4 KiB
303 lines
4.4 KiB
//========= 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); |
|
} |
|
|
|
|
|
|
|
|