/* * This file is part of uIRC. (https://git.redxen.eu/caskd/uIRC) * Copyright (c) 2019, 2020 Alex-David Denes * * uIRC is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * uIRC is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with uIRC. If not, see . */ #include "../memory/memory.h" // uirc_memory_*() #include "../types.h" // IRC_Message #include "tokenizers.h" // uirc_tokenizer_*() #include // assert() #include // malloc_string() strtok_mr() #include // isalnum() #include // NULL #include // malloc() #include // strlen() static void free_ctx(IRC_Message* msg, char* str); static void skip_spaces(char** addr); IRC_Message* uirc_tokenizer_message(const char* str) { assert(str != NULL); IRC_Message* m = malloc(sizeof(IRC_Message)); char* const ws = malloc_string(str, strlen(str)); char* p = ws; if (ws == NULL || m == NULL) { free(ws); free(m); return NULL; } memset(m, 0, sizeof(IRC_Message)); #ifdef UIRC_FEATURE_IRCV3 if (*p == '@') { p++; const char* tmp = NULL; if ((tmp = strtok_mr(&p, " ")) == NULL || (m->tag_list = uirc_tokenizer_tag_list(tmp)) == NULL) { free_ctx(m, ws); return NULL; } } skip_spaces(&p); #endif /* UIRC_FEATURE_IRCV3 */ if (*p == ':') { const char* tmp = NULL; p++; if ((tmp = strtok_mr(&p, " ")) == NULL || (m->source = uirc_tokenizer_user(tmp)) == NULL) { free_ctx(m, ws); return NULL; } skip_spaces(&p); } if (isalnum(*p)) { const char* tmp = NULL; if ((tmp = strtok_mr(&p, " ")) == NULL || (m->command = malloc_string(tmp, strlen(tmp))) == NULL) { free_ctx(m, ws); return NULL; } } else { free_ctx(m, ws); return NULL; } skip_spaces(&p); short i; for (i = 0; i < IRC_MAXARGS && *p;) { if (i == IRC_MAXARGS - 1 || *p == ':') { if (*p == ':') p++; if ((m->args[i++] = malloc_string(p, strlen(p))) == NULL) { free_ctx(m, ws); return NULL; } m->trailing = true; break; } else { const char* tmp = NULL; if ((tmp = strtok_mr(&p, " ")) == NULL || (m->args[i++] = malloc_string(tmp, strlen(tmp))) == NULL) { free_ctx(m, ws); return NULL; } skip_spaces(&p); } m->args[i] = NULL; } free(ws); return m; } static void free_ctx(IRC_Message* msg, char* str) { uirc_free_message(msg); free(msg); free(str); } static void skip_spaces(char** addr) { for (; **addr == ' '; (*addr)++) ; }