From 1979f7aa77d4c51a3f8f396cf3a3180637d9afdc Mon Sep 17 00:00:00 2001 From: Alex Denes Date: Mon, 15 Feb 2021 15:57:29 +0000 Subject: [PATCH] Split tokenizers into tag and tag_list and fix a few memory leaks --- CMakeLists.txt | 4 +- src/memory/memory.c | 11 +---- src/memory/memory.h | 1 - src/tests/tokenizers/tag.c | 4 +- src/tokenizers/message.c | 14 +++--- src/tokenizers/{tags.c => tag.c} | 74 ++++++++++++++++++++------------ src/tokenizers/tokenizers.h | 3 +- src/tokenizers/user.c | 6 +-- 8 files changed, 64 insertions(+), 53 deletions(-) rename src/tokenizers/{tags.c => tag.c} (59%) diff --git a/CMakeLists.txt b/CMakeLists.txt index a7c22cc..31a867f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.16) project( uIRC - VERSION 0.1 + VERSION 0.2 DESCRIPTION "Simple and lightweight IRC protocol helper" LANGUAGES C ) @@ -50,7 +50,7 @@ if (BUILD_IRCV3) set(UIRC_SOURCE ${UIRC_SOURCE} src/assemblers/tag.c - src/tokenizers/tags.c + src/tokenizers/tag.c ) endif() if (BUILD_VALIDATORS) diff --git a/src/memory/memory.c b/src/memory/memory.c index bc1fe3f..aa5aa2a 100644 --- a/src/memory/memory.c +++ b/src/memory/memory.c @@ -40,16 +40,7 @@ uirc_malloc_user(const char* nick, const char* user, const char* real) return NULL; } -llist_t* -uirc_malloc_tag(llist_t* prev, const char* key, const char* value) -{ - llist_t* tmp = NULL; - if ((tmp = allocate_linked_list_elem(sizeof(IRC_Tag))) == NULL) return NULL; - if (prev != NULL) prev->next = tmp; - ((IRC_Tag*) tmp->content)->key = malloc_string(key, strlen(key)); - ((IRC_Tag*) tmp->content)->value = malloc_string(value, strlen(value)); - return tmp; -} +// TODO: uirc_malloc_tag_list uirc_malloc_tag void uirc_free_tag(IRC_Tag* t) diff --git a/src/memory/memory.h b/src/memory/memory.h index 3116755..3edd7d7 100644 --- a/src/memory/memory.h +++ b/src/memory/memory.h @@ -26,7 +26,6 @@ #define UIRC_GUARD_PUBLIC_MEMORY IRC_User* uirc_malloc_user(const char* nick, const char* user, const char* real); -llist_t* uirc_malloc_tag(llist_t* prev, const char* key, const char* value); void uirc_free_tag(IRC_Tag* t); void uirc_free_user(IRC_User* u); void uirc_free_message(IRC_Message* m); diff --git a/src/tests/tokenizers/tag.c b/src/tests/tokenizers/tag.c index f9efa93..53c73da 100644 --- a/src/tests/tokenizers/tag.c +++ b/src/tests/tokenizers/tag.c @@ -16,7 +16,7 @@ * along with uIRC. If not, see . */ -#include "../../tokenizers/tokenizers.h" // Tok_tags() +#include "../../tokenizers/tokenizers.h" // uirc_tokenizer_*() #include "../common.h" // expect() #include // assert() @@ -33,7 +33,7 @@ int main(void) { IRC_Tag* cur = NULL; - llist_t* tags = uirc_tokenizer_tags("+" key1 "=" val1 ";" key2 ";" key3 "=" val3); + llist_t* tags = uirc_tokenizer_tag_list("+" key1 "=" val1 ";" key2 ";" key3 "=" val3); ERRIFNULL(tags, "Tags weren't tokenized successfully.\n"); cur = tags->content; diff --git a/src/tokenizers/message.c b/src/tokenizers/message.c index 2fcc870..def984e 100644 --- a/src/tokenizers/message.c +++ b/src/tokenizers/message.c @@ -16,9 +16,9 @@ * along with uIRC. If not, see . */ -#include "../memory/memory.h" // Free_IRC_Message() +#include "../memory/memory.h" // uirc_memory_*() #include "../types.h" // IRC_Message -#include "tokenizers.h" // Tok_mesg() Tok_user() Tok_tags() +#include "tokenizers.h" // uirc_tokenizer_*() #include // assert() #include // malloc_string() strtok_mr() @@ -31,12 +31,12 @@ static void free_ctx(IRC_Message* msg, char* str); static void skip_spaces(char** addr); IRC_Message* -uirc_tokenizer_message(const char* s) +uirc_tokenizer_message(const char* str) { - assert(s != NULL); + assert(str != NULL); IRC_Message* m = malloc(sizeof(IRC_Message)); - char* const ws = malloc_string(s, strlen(s)); + char* const ws = malloc_string(str, strlen(str)); char* p = ws; if (ws == NULL || m == NULL) { free(ws); @@ -44,13 +44,13 @@ uirc_tokenizer_message(const char* s) return NULL; } memset(m, 0, sizeof(IRC_Message)); - strcpy(ws, s); + strcpy(ws, str); #ifdef UIRC_FEATURE_IRCV3 if (*p == '@') { p++; const char* tmp = NULL; - if ((tmp = strtok_mr(&p, " ")) == NULL || (m->tag_list = uirc_tokenizer_tags(tmp)) == NULL) { + if ((tmp = strtok_mr(&p, " ")) == NULL || (m->tag_list = uirc_tokenizer_tag_list(tmp)) == NULL) { free_ctx(m, ws); return NULL; } diff --git a/src/tokenizers/tags.c b/src/tokenizers/tag.c similarity index 59% rename from src/tokenizers/tags.c rename to src/tokenizers/tag.c index 05e6483..d225a05 100644 --- a/src/tokenizers/tags.c +++ b/src/tokenizers/tag.c @@ -27,42 +27,26 @@ #include // free() #include // strchr() -static void free_ctx(llist_t* list, char* s); - -// TODO: Only tokenizer IRC_Tag and put the looping logic in uirc_tokenizer_message() +static void free_ctx(llist_t* list, IRC_Tag* t, char* s); llist_t* -uirc_tokenizer_tags(const char* s) +uirc_tokenizer_tag_list(const char* str) { - assert(s != NULL); + assert(str != NULL); - char* const ws = malloc_string(s, strlen(s)); + char* const ws = malloc_string(str, strlen(str)); char * p = ws, *tmp; llist_t * pl = NULL, *l = NULL; + if (ws == NULL) return NULL; while ((tmp = strtok_mr(&p, ";")) != NULL) { llist_t* cl; - if ((cl = allocate_linked_list_elem(sizeof(IRC_Tag))) == NULL) { - free_ctx(l, ws); + if ((cl = allocate_linked_list_elem(0)) == NULL) { + free_ctx(l, NULL, ws); return NULL; } - IRC_Tag* tag = (IRC_Tag*) cl->content; - - char* ckey = tmp; - if (*tmp == '+') { - ckey++; - tag->clientbound = true; - } - char* cval = strchr(ckey, '='); - if (cval != NULL) { - *(cval++) = '\0'; - if ((tag->value = malloc_string(cval, strlen(cval))) == NULL) { - free_ctx(l, ws); - return NULL; - } - } - if ((tag->key = malloc_string(ckey, strlen(ckey))) == NULL) { - free_ctx(l, ws); + if ((cl->content = uirc_tokenizer_tag(tmp)) == NULL) { + free_ctx(l, NULL, ws); return NULL; } @@ -71,17 +55,53 @@ uirc_tokenizer_tags(const char* s) connect_linked_list_elem(pl, cl); pl = cl; } + free(ws); return l; } +IRC_Tag* +uirc_tokenizer_tag(const char* str) +{ + assert(str != NULL); + + char* const ws = malloc_string(str, strlen(str)); + IRC_Tag* t = malloc(sizeof(IRC_Tag)); + char* ckey = ws; + + if (t == NULL || ws == NULL) { + free_ctx(NULL, t, ws); + return NULL; + } + if (*ws == '+') { + ckey++; + t->clientbound = true; + } + char* cval = strchr(ckey, '='); + if (cval != NULL) { + *(cval++) = '\0'; + if ((t->value = malloc_string(cval, strlen(cval))) == NULL) { + free_ctx(NULL, t, ws); + return NULL; + } + } + if ((t->key = malloc_string(ckey, strlen(ckey))) == NULL) { + free_ctx(NULL, t, ws); + return NULL; + } + free(ws); + return t; +} + static void -free_ctx(llist_t* list, char* s) +free_ctx(llist_t* list, IRC_Tag* t, char* s) { for (llist_t* c = list; c != NULL;) { llist_t* l = c; c = c->next; - uirc_free_tag(l->content); + if (l->content != NULL) uirc_free_tag(l->content); remove_linked_list_elem(l); } + free(t); free(s); } + diff --git a/src/tokenizers/tokenizers.h b/src/tokenizers/tokenizers.h index 090950f..5d7b85a 100644 --- a/src/tokenizers/tokenizers.h +++ b/src/tokenizers/tokenizers.h @@ -33,7 +33,8 @@ * This function parses IRCv3 tags according to the specification at * \param[in] str String containing a IRC source with or without the ':' prefix */ -llist_t* uirc_tokenizer_tags(const char* str); +llist_t* uirc_tokenizer_tag_list(const char* str); +IRC_Tag* uirc_tokenizer_tag(const char* str); #endif /* UIRC_FEATURE_IRCV3 */ /*! diff --git a/src/tokenizers/user.c b/src/tokenizers/user.c index c2b61db..32ca306 100644 --- a/src/tokenizers/user.c +++ b/src/tokenizers/user.c @@ -16,9 +16,9 @@ * along with uIRC. If not, see . */ -#include "../memory/memory.h" // Free_IRC_User() -#include "../types.h" // IRC_User -#include "tokenizers.h" // Tok_user() +#include "../memory/memory.h" // uirc_memory_*() +#include "../types.h" // IRC_Message +#include "tokenizers.h" // uirc_tokenizer_*() #include // assert() #include // malloc_string()