diff options
| -rw-r--r-- | src/common.c | 52 | ||||
| -rw-r--r-- | src/kike.c | 6 | 
2 files changed, 45 insertions, 13 deletions
| diff --git a/src/common.c b/src/common.c index fecaa92..eb69b80 100644 --- a/src/common.c +++ b/src/common.c @@ -578,10 +578,9 @@ struct str_map  	size_t len;                         ///< Number of entries in the table  	void (*free) (void *);              ///< Callback to destruct the payload -	/// Callback to compare keys for equivalence -	// FIXME: they may still end up on a different index, and actually should; -	//   delete this callback and put strxfrm() in its place -	int (*key_cmp) (const char *, const char *); +	/// Callback that transforms all key values for storage and comparison; +	/// has to behave exactly like strxfrm(). +	size_t (*key_xfrm) (char *dest, const char *src, size_t n);  };  // As long as you don't remove the current entry, you can modify the map. @@ -604,7 +603,7 @@ str_map_init (struct str_map *self)  	self->alloc = STR_MAP_MIN_ALLOC;  	self->len = 0;  	self->free = NULL; -	self->key_cmp = strcmp; +	self->key_xfrm = NULL;  	self->map = xcalloc (self->alloc, sizeof *self->map);  } @@ -698,13 +697,13 @@ str_map_resize (struct str_map *self, size_t new_size)  }  static void -str_map_set (struct str_map *self, const char *key, void *value) +str_map_set_real (struct str_map *self, const char *key, void *value)  {  	uint64_t pos = str_map_pos (self, key);  	struct str_map_link *iter = self->map[pos];  	for (; iter; iter = iter->next)  	{ -		if (self->key_cmp (key, iter->key)) +		if (strcmp (key, iter->key))  			continue;  		// Storing the same data doesn't destroy it @@ -748,16 +747,40 @@ str_map_set (struct str_map *self, const char *key, void *value)  	self->len++;  } +static void +str_map_set (struct str_map *self, const char *key, void *value) +{ +	if (!self->key_xfrm) +	{ +		str_map_set_real (self, key, value); +		return; +	} +	char tmp[self->key_xfrm (NULL, key, 0) + 1]; +	self->key_xfrm (tmp, key, sizeof tmp); +	str_map_set_real (self, tmp, value); +} +  static void * -str_map_find (struct str_map *self, const char *key) +str_map_find_real (struct str_map *self, const char *key)  {  	struct str_map_link *iter = self->map[str_map_pos (self, key)];  	for (; iter; iter = iter->next) -		if (!self->key_cmp (key, (const char *) iter + sizeof *iter)) +		if (!strcmp (key, (const char *) iter + sizeof *iter))  			return iter->data;  	return NULL;  } +static void * +str_map_find (struct str_map *self, const char *key) +{ +	if (!self->key_xfrm) +		return str_map_find_real (self, key); + +	char tmp[self->key_xfrm (NULL, key, 0) + 1]; +	self->key_xfrm (tmp, key, sizeof tmp); +	return str_map_find_real (self, tmp); +} +  // --- File descriptor utilities -----------------------------------------------  static void @@ -1727,7 +1750,7 @@ irc_process_buffer (struct str *buf,  }  static int -irc_tolower (char c) +irc_tolower (int c)  {  	if (c == '[')   return '{';  	if (c == ']')   return '}'; @@ -1736,6 +1759,15 @@ irc_tolower (char c)  	return c >= 'A' && c <= 'Z' ? c + ('a' - 'A') : c;  } +static size_t +irc_strxfrm (char *dest, const char *src, size_t n) +{ +	size_t len = strlen (src); +	while (n-- && (*dest++ = irc_tolower (*src++))) +		; +	return len; +} +  static int  irc_strcmp (const char *a, const char *b)  { @@ -378,12 +378,12 @@ server_context_init (struct server_context *self)  	self->server_name = NULL;  	str_map_init (&self->users); -	self->users.key_cmp = irc_strcmp; +	self->users.key_xfrm = irc_strxfrm;  	// TODO: set channel_free() as the free function?  	str_map_init (&self->channels); -	self->channels.key_cmp = irc_strcmp; +	self->channels.key_xfrm = irc_strxfrm;  	str_map_init (&self->handlers); -	self->handlers.key_cmp = irc_strcmp; +	self->handlers.key_xfrm = irc_strxfrm;  	poller_init (&self->poller);  	self->quitting = false; | 
