Esempio n. 1
0
/*
* CL_ResolveMasterAddress
*/
static void CL_ResolveMasterAddress( const char *master, netadr_t *adr )
{
	trie_error_t err;
	masteradrcache_t *cache;

	// check memory cache
	err = Trie_Find( serverlist_masters_trie, master, TRIE_EXACT_MATCH, (void **)&cache );
	if( err == TRIE_OK )
	{
		if( adr )
			*adr = cache->adr;
		return;
	}

	// send a unicast packet
	cache = Mem_ZoneMalloc( sizeof( *cache ) );
	NET_StringToAddress( master, &cache->adr );

	if( adr )
		*adr = cache->adr;
	cache->next = serverlist_masters_head;
	serverlist_masters_head = cache;

	Trie_Insert( serverlist_masters_trie, master, (void *)cache );
}
Esempio n. 2
0
/*
* ML_AddMap
* Handles assigning memory for map and adding it to the list
* in alphabetical order
*/
static void ML_AddMap( const char *filename, const char *fullname )
{
	mapinfo_t *map;
	char *buffer;
	char fullname_[MAX_CONFIGSTRING_CHARS];

	if( !ML_ValidateFilename( filename ) )
		return;

	if( !strcmp(filename, "ui") )
		return;

	if( !fullname )
	{
		ML_GetFullnameFromMap( filename, fullname_, sizeof( fullname_ ) );
		fullname = fullname_;
	}

	if( !ML_ValidateFullname( fullname ) && *fullname )	// allow empty fullnames
		return;

	if( !strcmp(fullname, "ui") )
		return;

	ml_flush = true;	// tell everyone that maplist has changed
	buffer = ( char* )Mem_ZoneMalloc( sizeof( mapinfo_t ) + strlen( filename ) + 1 + strlen( fullname ) + 1 );

	map = ( mapinfo_t * )buffer;
	buffer += sizeof( mapinfo_t );

	map->filename = buffer;
	strcpy( map->filename, filename );
	COM_StripExtension( map->filename );
	buffer += strlen( filename ) + 1;

	map->fullname = buffer;
	strcpy( map->fullname, fullname );
	COM_RemoveColorTokens( map->fullname );
	Q_strlwr( map->fullname );

	Trie_Insert( mlist_filenames_trie, map->filename, map );
	Trie_Insert( mlist_fullnames_trie, map->fullname, map );

	map->next = maplist;
	maplist = map;
}
Esempio n. 3
0
/*
## FT.SUGGADD key string score [INCR] [PAYLOAD {payload}]

Add a suggestion string to an auto-complete suggestion dictionary. This is
disconnected from the
index definitions, and leaves creating and updating suggestino dictionaries to
the user.

### Parameters:

   - key: the suggestion dictionary key.

   - string: the suggestion string we index

   - score: a floating point number of the suggestion string's weight

   -INCR: if set, we increment the existing entry of the suggestion by the
given
score, instead
of
    replacing the score. This is useful for updating the dictionary based on
user queries in
real
    time

   - PAYLOAD: Add a payload to the suggestion string that will be used as additional information.

### Returns:

Integer reply: the current size of the suggestion dictionary.
*/
int RSSuggestAddCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
  if (argc < 4 || argc > 7) {
    return RedisModule_WrongArity(ctx);
  }

  int incr = 0, rv = AC_OK;
  RSPayload payload = {0};
  ArgsCursor ac = {0};
  ArgsCursor_InitRString(&ac, argv + 4, argc - 4);
  while (!AC_IsAtEnd(&ac)) {
    const char *s = AC_GetStringNC(&ac, NULL);
    if (!strcasecmp(s, "INCR")) {
      incr = 1;
    } else if (!strcasecmp(s, "PAYLOAD")) {
      if ((rv = AC_GetString(&ac, (const char **)&payload.data, &payload.len, 0)) != AC_OK) {
        return RMUtil_ReplyWithErrorFmt(ctx, "Invalid payload: %s", AC_Strerror(rv));
      }
    } else {
      return RMUtil_ReplyWithErrorFmt(ctx, "Unknown argument `%s`", s);
    }
  }

  RedisModule_AutoMemory(ctx); /* Use automatic memory management. */
  RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_READ | REDISMODULE_WRITE);
  int type = RedisModule_KeyType(key);
  if (type != REDISMODULE_KEYTYPE_EMPTY && RedisModule_ModuleTypeGetType(key) != TrieType) {
    return RedisModule_ReplyWithError(ctx, REDISMODULE_ERRORMSG_WRONGTYPE);
  }

  RedisModuleString *val = argv[2];
  double score;
  if ((RedisModule_StringToDouble(argv[3], &score) != REDISMODULE_OK)) {
    return RedisModule_ReplyWithError(ctx, "ERR invalid score");
  }

  /* Create an empty value object if the key is currently empty. */
  Trie *tree;
  if (type == REDISMODULE_KEYTYPE_EMPTY) {
    tree = NewTrie();
    RedisModule_ModuleTypeSetValue(key, TrieType, tree);
  } else {
    tree = RedisModule_ModuleTypeGetValue(key);
  }

  /* Insert the new element. */
  Trie_Insert(tree, val, score, incr, &payload);

  RedisModule_ReplyWithLongLong(ctx, tree->size);
  RedisModule_ReplicateVerbatim(ctx);
  return REDISMODULE_OK;
}
Esempio n. 4
0
/*
* CL_ResolveMasterAddress
*/
static void CL_ResolveMasterAddress( const char *master )
{
	netadr_t adr, *padr;

	if( master && *master ) {
		NET_StringToAddress( master, &adr );

		QMutex_Lock( resolveLock );

		padr = ( netadr_t * )malloc( sizeof( adr ) );
		*padr = adr;

		Trie_Insert( serverlist_masters_trie, master, padr );

		QMutex_Unlock( resolveLock );
	}
}
Esempio n. 5
0
dynvar_t *Dynvar_Create(
        const char *name,
        qboolean console,
        dynvar_getter_f getter,
        dynvar_setter_f setter
)
{
	assert( dynvar_trie );
	if( name && getter && setter )
	{
		dynvar_t *dynvar = Dynvar_NewDynvar( name, console, getter, setter );
		if( Trie_Insert( dynvar_trie, name, dynvar ) == TRIE_OK )
			return dynvar;
		else
			Dynvar_FreeDynvar( dynvar );
	}
	return NULL;
}
Esempio n. 6
0
/*
* Cvar_Get
* Creates the variable if it doesn't exist.
* If the variable already exists, the value will not be set
* The flags will be or'ed and default value overwritten in if the variable exists.
*/
cvar_t *Cvar_Get( const char *var_name, const char *var_value, cvar_flag_t flags )
{
	cvar_t *var;

	if( !var_name || !var_name[0] )
		return NULL;

	if( Cvar_FlagIsSet( flags, CVAR_USERINFO ) || Cvar_FlagIsSet( flags, CVAR_SERVERINFO ) )
	{
		if( !Cvar_InfoValidate( var_name, qtrue ) )
		{
			Com_Printf( "invalid info cvar name\n" );
			return NULL;
		}
	}

	assert( cvar_trie );
	Trie_Find( cvar_trie, var_name, TRIE_EXACT_MATCH, (void **)&var );

	if( var )
	{
		assert( var_value );
		if( !var->dvalue || strcmp( var->dvalue, var_value ) )
		{
			if( var->dvalue )
				Mem_ZoneFree( var->dvalue ); // free the old default value string
			var->dvalue = ZoneCopyString( (char *) var_value );
		}
#ifdef PUBLIC_BUILD
		if( Cvar_FlagIsSet( flags, CVAR_READONLY ) || Cvar_FlagIsSet( flags, CVAR_DEVELOPER ) )
		{
#else
		if( Cvar_FlagIsSet( flags, CVAR_READONLY ) )
		{
#endif
			if( !var->string || strcmp( var->string, var_value ) )
			{
				if( var->string )
					Mem_ZoneFree( var->string );
				var->string = ZoneCopyString( (char *) var_value );
				var->value = atof( var->string );
				var->integer = Q_rint( var->value );
			}
			var->flags = flags;
		}

		if( Cvar_FlagIsSet( flags, CVAR_USERINFO ) && !Cvar_FlagIsSet( var->flags, CVAR_USERINFO ) )
			userinfo_modified = qtrue; // transmit at next oportunity

		Cvar_FlagSet( &var->flags, flags );
		return var;
	}

	if( !var_value )
		return NULL;

	if( Cvar_FlagIsSet( flags, CVAR_USERINFO ) || Cvar_FlagIsSet( flags, CVAR_SERVERINFO ) )
	{
		if( !Cvar_InfoValidate( var_value, qfalse ) )
		{
			Com_Printf( "invalid info cvar value\n" );
			return NULL;
		}
	}

	var = Mem_ZoneMalloc( (int)( sizeof( *var ) + strlen( var_name ) + 1 ) );
	var->name = (char *)( (qbyte *)var + sizeof( *var ) );
	strcpy( var->name, var_name );
	var->dvalue = ZoneCopyString( (char *) var_value );
	var->string = ZoneCopyString( (char *) var_value );
	Cvar_SetModified( var );
	var->value = atof( var->string );
	var->integer = Q_rint( var->value );
	var->flags = flags;

	Trie_Insert( cvar_trie, var_name, var );

	return var;
}

/*
* Cvar_Set2
*/
static cvar_t *Cvar_Set2( const char *var_name, const char *value, qboolean force )
{
	cvar_t *var = Cvar_Find( var_name );

	if( !var )
	{
		// create it
		return Cvar_Get( var_name, value, 0 );
	}

	if( Cvar_FlagIsSet( var->flags, CVAR_USERINFO ) || Cvar_FlagIsSet( var->flags, CVAR_SERVERINFO ) )
	{
		if( !Cvar_InfoValidate( value, qfalse ) )
		{
			Com_Printf( "invalid info cvar value\n" );
			return var;
		}
	}

	if( !force )
	{
#ifdef PUBLIC_BUILD
		if( Cvar_FlagIsSet( var->flags, CVAR_NOSET ) || Cvar_FlagIsSet( var->flags, CVAR_READONLY ) || Cvar_FlagIsSet( var->flags, CVAR_DEVELOPER ) )
		{
#else
		if( Cvar_FlagIsSet( var->flags, CVAR_NOSET ) || Cvar_FlagIsSet( var->flags, CVAR_READONLY ) )
		{
#endif
			Com_Printf( "%s is write protected.\n", var_name );
			return var;
		}

		if( Cvar_FlagIsSet( var->flags, CVAR_CHEAT ) && strcmp( value, var->dvalue ) )
		{
			if( !Cvar_CheatsAllowed() )
			{
				Com_Printf( "%s is cheat protected.\n", var_name );
				return var;
			}
		}

		if( Cvar_FlagIsSet( var->flags, CVAR_LATCH ) || Cvar_FlagIsSet( var->flags, CVAR_LATCH_VIDEO ) ||
			Cvar_FlagIsSet( var->flags, CVAR_LATCH_SOUND ) )
		{
			if( var->latched_string )
			{
				if( !strcmp( value, var->latched_string ) )
					return var;
				Mem_ZoneFree( var->latched_string );
			}
			else
			{
				if( !strcmp( value, var->string ) )
					return var;
			}

			if( Com_ServerState() )
			{
				Com_Printf( "%s will be changed upon restarting.\n", var->name );
				var->latched_string = ZoneCopyString( (char *) value );
			}
			else
			{
				if( Cvar_FlagIsSet( var->flags, CVAR_LATCH_VIDEO ) )
				{
					Com_Printf( "%s will be changed upon restarting video.\n", var->name );
					var->latched_string = ZoneCopyString( (char *) value );
				}
				else if( Cvar_FlagIsSet( var->flags, CVAR_LATCH_SOUND ) )
				{
					Com_Printf( "%s will be changed upon restarting sound.\n", var->name );
					var->latched_string = ZoneCopyString( (char *) value );
				}
				else
				{
					if( !strcmp( var->name, "fs_game" ) )
					{
						FS_SetGameDirectory( value, qfalse );
						return var;
					}
					Mem_ZoneFree( var->string ); // free the old value string
					var->string = ZoneCopyString( value );
					var->value = atof( var->string );
					var->integer = Q_rint( var->value );
					Cvar_SetModified( var );
				}
			}
			return var;
		}
	}
	else
	{
		if( var->latched_string )
		{
			Mem_ZoneFree( var->latched_string );
			var->latched_string = NULL;
		}
	}

	if( !strcmp( value, var->string ) )
		return var; // not changed

	Cvar_SetModified( var );

	if( Cvar_FlagIsSet( var->flags, CVAR_USERINFO ) )
		userinfo_modified = qtrue; // transmit at next oportunity

	Mem_ZoneFree( var->string ); // free the old value string

	var->string = ZoneCopyString( (char *) value );
	var->value = atof( var->string );
	var->integer = Q_rint( var->value );

	return var;
}

/*
* Cvar_ForceSet
* Set the variable even if NOSET or LATCH
*/
cvar_t *Cvar_ForceSet( const char *var_name, const char *value )
{
	return Cvar_Set2( var_name, value, qtrue );
}

/*
* Cvar_Set
* Create the variable if it doesn't exist
*/
cvar_t *Cvar_Set( const char *var_name, const char *value )
{
	return Cvar_Set2( var_name, value, qfalse );
}

/*
* Cvar_FullSet
*/
cvar_t *Cvar_FullSet( const char *var_name, const char *value, cvar_flag_t flags, qboolean overwrite_flags )
{
	cvar_t *var;

	var = Cvar_Find( var_name );
	if( !var )
		return Cvar_Get( var_name, value, flags );

	if( overwrite_flags )
	{
		var->flags = flags;
	}
	else
	{
		Cvar_FlagSet( &var->flags, flags );
	}

	// if we overwrite the flags, we will also force the value
	return Cvar_Set2( var_name, value, overwrite_flags );
}
Esempio n. 7
0
/*
* L10n_ParsePOFile
*
* Doesn't allocate memory, writes to input buffer, which
* should NOT be freed after calling this function.
*/
static trie_t *L10n_ParsePOFile( const char *filepath, char *buffer, int length )
{
	int linenum = 0;
	char *start = buffer, *end = buffer + length;
	char *cur, *eol;
	qboolean have_msgid, have_msgstr, error;
	char *msgid, *msgstr, *instr, *outstr;
	size_t str_length;
	trie_t *dict;
	trie_error_t tr_err;

	tr_err = Trie_Create( TRIE_CASE_SENSITIVE, &dict );
	if( tr_err != TRIE_OK ) {
		return NULL;
	}

	have_msgid = have_msgstr = qfalse;
	instr = outstr = buffer;
	msgid = msgstr = buffer;
	eol = end;

	for( cur = start; cur >= start && cur < end; cur = eol + 1 ) {
		if( !*cur ) {
			break;
		}

		linenum++;

		// skip whitespaces
		while( *cur == ' ' || *cur == '\t' ) {
			cur++;
		}

		// find the end of line
		eol = strchr( cur, '\n' );
		if( eol ) {
			char *prev = eol - 1;
			*eol = '\0';
			if( *prev == '\r' ) {
				*prev = '\0';
			}
		}

		if( *cur == '#' ) {
			continue;
		}

		if( !*cur ) {
			// empty line
			continue;
		}

parse_cmd:
		// search for msgid "id"
		if( !strncmp( cur, "msgid ", 6 ) ) {
			if( have_msgstr ) {
				Trie_Insert( dict, msgid, ( void * )msgstr );
				have_msgid = have_msgstr = qfalse;
			}
			have_msgid = qtrue;
			instr = cur + 6;
			outstr = cur + 5;
			msgid = outstr;
			*msgid = '\0';
		}
		else if( have_msgid && !strncmp( cur, "msgstr ", 7 ) ) {
			have_msgstr = qtrue;
			instr = cur + 7;
			outstr = cur + 6;
			msgstr = outstr;
			*msgstr = '\0';
		}
		else {
			// multiline?
			if( have_msgid || have_msgstr ) {
				if( *cur != '"' || !strrchr( cur+1, '"') ) {
					if( have_msgstr ) {
						Trie_Insert( dict, msgid, ( void * )msgstr );
					}
					// no
					have_msgid = have_msgstr = qfalse;
					goto parse_cmd;
				}
				// yes
				instr = cur;
			} else {
				continue;
			}
		}

		// parse single line of C-style string
		str_length = L10n_ParsePOString( instr, outstr, &error );
		if( !str_length ) {
			have_msgid = have_msgstr = qfalse;
			if( error ) {
				Com_Printf( S_COLOR_YELLOW "Error parsing line %i of %s: syntax error near '%s'\n", 
					linenum, filepath, instr );
			}
		}
		else {
			// shift the output buffer so that in case multiline string
			// is ecountered it'll be properly appended
			outstr += str_length;
		}
	}

	if( have_msgstr ) {
		Trie_Insert( dict, msgid, ( void * )msgstr );
	}

	return dict;
}