Add errors and refactor some code
This commit is contained in:
parent
c5d5f06063
commit
4abc4f35f7
|
@ -1,7 +1,7 @@
|
|||
cmake_minimum_required(VERSION 3.16)
|
||||
project(
|
||||
uIRC
|
||||
VERSION 0.3.2
|
||||
VERSION 0.4.0
|
||||
DESCRIPTION "Simple and lightweight IRC protocol helper"
|
||||
LANGUAGES C
|
||||
)
|
||||
|
@ -21,6 +21,7 @@ OPTION(CODE_COVERAGE "Build with coverage tools" OFF)
|
|||
set(UIRC_SOURCE
|
||||
src/assemblers/message.c
|
||||
src/assemblers/user.c
|
||||
src/error/error.c
|
||||
src/memory/list.c
|
||||
src/memory/struct.c
|
||||
src/tokenizers/message.c
|
||||
|
@ -31,6 +32,7 @@ set(UIRC_HEADERS
|
|||
include/assemblers.h
|
||||
include/commands.h
|
||||
include/ctcp.h
|
||||
include/errors.h
|
||||
include/memory.h
|
||||
include/misc.h
|
||||
include/modes.h
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* This file is part of uIRC. (https://git.redxen.eu/caskd/uIRC)
|
||||
* Copyright (c) 2019-2021 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
||||
#ifndef UIRC_GUARD_PUBLIC_ERRORS
|
||||
#define UIRC_GUARD_PUBLIC_ERRORS
|
||||
|
||||
typedef enum {
|
||||
UIRC_ERR_NERROR = 0,
|
||||
UIRC_ERR_SYSERR,
|
||||
UIRC_ERR_BUFSIZ,
|
||||
UIRC_ERR_INVFMT,
|
||||
} uirc_errno_t;
|
||||
|
||||
extern uirc_errno_t uirc_errno;
|
||||
const char* uirc_strerror(uirc_errno_t errno);
|
||||
|
||||
#endif /* UIRC_GUARD_PUBLIC_ERRORS */
|
||||
|
|
@ -19,6 +19,7 @@
|
|||
#include "assemblers.h"
|
||||
#include "commands.h"
|
||||
#include "ctcp.h"
|
||||
#include "errors.h"
|
||||
#include "memory.h"
|
||||
#include "misc.h"
|
||||
#include "modes.h"
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
*/
|
||||
|
||||
#include "assemblers.h" // uirc_assembler_*
|
||||
#include "errors.h" // uirc_errno
|
||||
#include "types.h" // IRC_Message IRC_Tag IRC_User
|
||||
|
||||
#include <assert.h> // assert()
|
||||
|
@ -33,12 +34,13 @@ uirc_assembler_message(char* buf, const IRC_Message* m, size_t len)
|
|||
|
||||
#ifdef UIRC_FEATURE_IRCV3
|
||||
if (m->tag_list != NULL) {
|
||||
|
||||
if (len > 1) {
|
||||
*(buf++) = '@';
|
||||
len--;
|
||||
} else
|
||||
} else {
|
||||
uirc_errno = UIRC_ERR_BUFSIZ;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t ret;
|
||||
if ((ret = uirc_assembler_tag_list(buf, m->tag_list, len)) >= 0) {
|
||||
|
@ -50,8 +52,10 @@ uirc_assembler_message(char* buf, const IRC_Message* m, size_t len)
|
|||
if (len > 1) {
|
||||
*(buf++) = ' ';
|
||||
len--;
|
||||
} else
|
||||
} else {
|
||||
uirc_errno = UIRC_ERR_BUFSIZ;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
assert(sv <= buf);
|
||||
#endif /* UIRC_FEATURE_IRCV3 */
|
||||
|
@ -59,8 +63,10 @@ uirc_assembler_message(char* buf, const IRC_Message* m, size_t len)
|
|||
if (len > 1) {
|
||||
*(buf++) = ':';
|
||||
len--;
|
||||
} else
|
||||
} else {
|
||||
uirc_errno = UIRC_ERR_BUFSIZ;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t ret;
|
||||
if ((ret = uirc_assembler_user(buf, m->source, len)) >= 0) {
|
||||
|
@ -72,31 +78,37 @@ uirc_assembler_message(char* buf, const IRC_Message* m, size_t len)
|
|||
if (len > 1) {
|
||||
*(buf++) = ' ';
|
||||
len--;
|
||||
} else
|
||||
} else {
|
||||
uirc_errno = UIRC_ERR_BUFSIZ;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
assert(sv <= buf);
|
||||
|
||||
if (m->command != NULL) {
|
||||
if (len < 2) return -1;
|
||||
int ret;
|
||||
if ((ret = snprintf(buf, len, "%s", m->command)) >= 0) {
|
||||
buf += (size_t) ret;
|
||||
len -= (size_t) ret;
|
||||
} else
|
||||
} else {
|
||||
uirc_errno = UIRC_ERR_BUFSIZ;
|
||||
return -1;
|
||||
} else
|
||||
}
|
||||
} else {
|
||||
uirc_errno = UIRC_ERR_INVFMT;
|
||||
return -1;
|
||||
}
|
||||
assert(sv <= buf);
|
||||
|
||||
for (unsigned int i = 0; i < IRC_MAXARGS && m->args[i] != NULL; i++) {
|
||||
if (len < 2) return -1;
|
||||
int ret;
|
||||
if ((ret = snprintf(buf, len, (m->args[i + 1] == NULL && m->trailing) ? " :%s" : " %s", m->args[i])) >= 0) {
|
||||
buf += (size_t) ret;
|
||||
len -= (size_t) ret;
|
||||
} else
|
||||
} else {
|
||||
uirc_errno = UIRC_ERR_BUFSIZ;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
assert(sv <= buf);
|
||||
|
||||
|
@ -104,8 +116,10 @@ uirc_assembler_message(char* buf, const IRC_Message* m, size_t len)
|
|||
if ((ret = snprintf(buf, len, "\r\n")) >= 0) {
|
||||
buf += (size_t) ret;
|
||||
len -= (size_t) ret;
|
||||
} else
|
||||
} else {
|
||||
uirc_errno = UIRC_ERR_BUFSIZ;
|
||||
return -1;
|
||||
}
|
||||
assert(sv <= buf);
|
||||
|
||||
return (ssize_t)(buf - sv);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
*/
|
||||
|
||||
#include "assemblers.h" // uirc_assembler_tag_*
|
||||
#include "errors.h" // uirc_errno
|
||||
#include "types.h" // IRC_Tag
|
||||
|
||||
#include <assert.h> // assert()
|
||||
|
@ -38,24 +39,28 @@ uirc_assembler_tag(char* buf, const IRC_Tag* t, size_t len)
|
|||
if (len > 1) {
|
||||
*(buf++) = '+';
|
||||
len--;
|
||||
} else
|
||||
} else {
|
||||
uirc_errno = UIRC_ERR_BUFSIZ;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (len < 1) return -1;
|
||||
if ((res = snprintf(buf, len, "%s", t->key)) >= 0) {
|
||||
buf += (size_t) res;
|
||||
len -= (size_t) res;
|
||||
} else
|
||||
} else {
|
||||
uirc_errno = UIRC_ERR_BUFSIZ;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (t->value != NULL) {
|
||||
if (len < 1) return -1;
|
||||
if ((res = snprintf(buf, len, "=%s", t->value)) >= 0) {
|
||||
buf += (size_t) res;
|
||||
len -= (size_t) res;
|
||||
} else
|
||||
} else {
|
||||
uirc_errno = UIRC_ERR_BUFSIZ;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return buf - sv;
|
||||
|
@ -73,16 +78,20 @@ uirc_assembler_tag_list(char* buf, const llist_t* tl, size_t len)
|
|||
if (len > 1) {
|
||||
*(buf++) = ';';
|
||||
len--;
|
||||
} else
|
||||
} else {
|
||||
uirc_errno = UIRC_ERR_BUFSIZ;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t ret;
|
||||
if ((ret = uirc_assembler_tag(buf, tl->content, len)) >= 0) {
|
||||
buf += (size_t) ret;
|
||||
len -= (size_t) ret;
|
||||
} else
|
||||
} else {
|
||||
uirc_errno = UIRC_ERR_BUFSIZ;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return buf - sv;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
*/
|
||||
|
||||
#include "assemblers.h" // Assm_user()
|
||||
#include "errors.h" // uirc_errno
|
||||
#include "types.h" // IRC_User
|
||||
|
||||
#include <assert.h> // assert()
|
||||
|
@ -33,31 +34,34 @@ uirc_assembler_user(char* buf, const IRC_User* u, size_t len)
|
|||
char* const sv = buf;
|
||||
|
||||
if (u->nick != NULL) {
|
||||
if (len < 1) return -1;
|
||||
int res;
|
||||
if ((res = snprintf(buf, len, "%s", u->nick)) >= 0) {
|
||||
buf += (size_t) res;
|
||||
len -= (size_t) res;
|
||||
} else
|
||||
} else {
|
||||
uirc_errno = UIRC_ERR_BUFSIZ;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (u->user != NULL) {
|
||||
if (len < 1) return -1;
|
||||
int res;
|
||||
if ((res = snprintf(buf, len, "!%s", u->user)) >= 0) {
|
||||
buf += (size_t) res;
|
||||
len -= (size_t) res;
|
||||
} else
|
||||
} else {
|
||||
uirc_errno = UIRC_ERR_BUFSIZ;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (u->host != NULL) {
|
||||
if (len < 1) return -1;
|
||||
int res;
|
||||
if ((res = snprintf(buf, len, (u->nick != NULL || u->user != NULL) ? "@%s" : "%s", u->host)) >= 0) {
|
||||
buf += (size_t) res;
|
||||
len -= (size_t) res;
|
||||
} else
|
||||
} else {
|
||||
uirc_errno = UIRC_ERR_BUFSIZ;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return buf - sv;
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* This file is part of uIRC. (https://git.redxen.eu/caskd/uIRC)
|
||||
* Copyright (c) 2019-2021 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "errors.h"
|
||||
|
||||
uirc_errno_t uirc_errno = UIRC_ERR_NERROR;
|
||||
|
||||
static const char* const uirc_errno_str[] = {
|
||||
[UIRC_ERR_NERROR] = "No error",
|
||||
[UIRC_ERR_SYSERR] = "System error",
|
||||
[UIRC_ERR_BUFSIZ] = "Buffer space full",
|
||||
[UIRC_ERR_INVFMT] = "Invalid format",
|
||||
};
|
||||
|
||||
const char*
|
||||
uirc_strerror(uirc_errno_t errno)
|
||||
{
|
||||
return uirc_errno_str[errno];
|
||||
}
|
|
@ -42,7 +42,7 @@ uirc_list_free(llist_t* list, IRC_Struct_Type type)
|
|||
for (; list != NULL; cnt++) {
|
||||
llist_t* const save = list;
|
||||
list = list->next;
|
||||
uirc_struct_free(save->content, type);
|
||||
if (save->content != NULL) uirc_struct_free(save->content, type);
|
||||
llist_elem_rm(save);
|
||||
}
|
||||
return cnt;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
* along with uIRC. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "errors.h" // uirc_errno
|
||||
#include "memory.h"
|
||||
#include "types.h" // IRC_*
|
||||
|
||||
|
@ -96,40 +97,61 @@ IRC_Tag*
|
|||
uirc_struct_assm_tag(bool clientbound, const char* key, const char* value)
|
||||
{
|
||||
assert(key != NULL);
|
||||
IRC_Tag* t = malloc(sizeof(*t));
|
||||
IRC_Tag* t = NULL;
|
||||
|
||||
if ((t = malloc(sizeof(*t))) == NULL) {
|
||||
uirc_errno = UIRC_ERR_SYSERR;
|
||||
goto cleanup;
|
||||
}
|
||||
memset(t, 0, sizeof(*t));
|
||||
|
||||
t->clientbound = clientbound;
|
||||
if ((t->key = stringext_strmalloc(key, strlen(key))) == NULL
|
||||
|| (value != NULL && (t->value = stringext_strmalloc(value, strlen(value))) == NULL)) {
|
||||
uirc_struct_free(t, IRC_STRUCT_TAG);
|
||||
free(t);
|
||||
return NULL;
|
||||
uirc_errno = UIRC_ERR_SYSERR;
|
||||
goto cleanup;
|
||||
}
|
||||
return t;
|
||||
cleanup:
|
||||
if (t != NULL) uirc_struct_free(t, IRC_STRUCT_TAG);
|
||||
free(t);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IRC_Capability*
|
||||
uirc_struct_assm_capability(bool active, const char* name)
|
||||
{
|
||||
assert(name != NULL);
|
||||
IRC_Capability* c = malloc(sizeof(*c));
|
||||
IRC_Capability* c = NULL;
|
||||
|
||||
if ((c = malloc(sizeof(*c))) == NULL) {
|
||||
uirc_errno = UIRC_ERR_SYSERR;
|
||||
goto cleanup;
|
||||
}
|
||||
memset(c, 0, sizeof(*c));
|
||||
|
||||
c->active = active;
|
||||
if ((c->name = stringext_strmalloc(name, strlen(name))) == NULL) {
|
||||
uirc_struct_free(c, IRC_STRUCT_CAPABILITY);
|
||||
free(c);
|
||||
return NULL;
|
||||
uirc_errno = UIRC_ERR_SYSERR;
|
||||
goto cleanup;
|
||||
}
|
||||
return c;
|
||||
cleanup:
|
||||
if (c != NULL) uirc_struct_free(c, IRC_STRUCT_CAPABILITY);
|
||||
free(c);
|
||||
return NULL;
|
||||
}
|
||||
#endif /* UIRC_FEATURE_IRCV3 */
|
||||
|
||||
IRC_User*
|
||||
uirc_struct_assm_user(bool service, IRC_Modes modes, const char* nick, const char* user, const char* real, const char* host)
|
||||
{
|
||||
IRC_User* u = malloc(sizeof(*u));
|
||||
IRC_User* u = NULL;
|
||||
|
||||
if ((u = malloc(sizeof(*u))) == NULL) {
|
||||
uirc_errno = UIRC_ERR_SYSERR;
|
||||
goto cleanup;
|
||||
}
|
||||
memset(u, 0, sizeof(*u));
|
||||
|
||||
u->is_service = service;
|
||||
|
@ -138,45 +160,60 @@ uirc_struct_assm_user(bool service, IRC_Modes modes, const char* nick, const cha
|
|||
|| (user != NULL && (u->user = stringext_strmalloc(user, strlen(user))) == NULL)
|
||||
|| (real != NULL && (u->real = stringext_strmalloc(real, strlen(real))) == NULL)
|
||||
|| (host != NULL && (u->host = stringext_strmalloc(host, strlen(host))) == NULL)) {
|
||||
uirc_struct_free(u, IRC_STRUCT_USER);
|
||||
free(u);
|
||||
return NULL;
|
||||
uirc_errno = UIRC_ERR_SYSERR;
|
||||
goto cleanup;
|
||||
}
|
||||
return u;
|
||||
cleanup:
|
||||
if (u != NULL) uirc_struct_free(u, IRC_STRUCT_USER);
|
||||
free(u);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IRC_Message*
|
||||
uirc_struct_assm_message(const char* cmd, bool trailing, unsigned int argc, ...)
|
||||
{
|
||||
assert(cmd != NULL);
|
||||
IRC_Message* m = malloc(sizeof(*m));
|
||||
IRC_Message* m = NULL;
|
||||
|
||||
if ((m = malloc(sizeof(*m))) == NULL) {
|
||||
uirc_errno = UIRC_ERR_SYSERR;
|
||||
goto cleanup;
|
||||
}
|
||||
memset(m, 0, sizeof(*m));
|
||||
|
||||
m->trailing = trailing;
|
||||
if (cmd != NULL && (m->command = stringext_strmalloc(cmd, strlen(cmd))) == NULL) {
|
||||
uirc_struct_free(m, IRC_STRUCT_MESSAGE);
|
||||
free(m);
|
||||
return NULL;
|
||||
if ((m->command = stringext_strmalloc(cmd, strlen(cmd))) == NULL) {
|
||||
uirc_errno = UIRC_ERR_SYSERR;
|
||||
goto cleanup;
|
||||
}
|
||||
va_list ap;
|
||||
va_start(ap, argc);
|
||||
for (unsigned short i = 0; i < IRC_MAXARGS && i < argc; i++) {
|
||||
const char* carg = va_arg(ap, const char*);
|
||||
if ((m->args[i] = stringext_strmalloc(carg, strlen(carg))) == NULL) {
|
||||
uirc_struct_free(m, IRC_STRUCT_MESSAGE);
|
||||
free(m);
|
||||
return NULL;
|
||||
uirc_errno = UIRC_ERR_SYSERR;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
va_end(ap);
|
||||
return m;
|
||||
cleanup:
|
||||
if (m != NULL) uirc_struct_free(m, IRC_STRUCT_MESSAGE);
|
||||
free(m);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IRC_Buffer*
|
||||
uirc_struct_assm_buffer(IRC_Buffer_Type type, IRC_Modes modes, bool subscribed, const char* name, const char* key, const char* topic)
|
||||
{
|
||||
assert(name != NULL);
|
||||
IRC_Buffer* b = malloc(sizeof(*b));
|
||||
IRC_Buffer* b = NULL;
|
||||
|
||||
if ((b = malloc(sizeof(*b))) == NULL) {
|
||||
uirc_errno = UIRC_ERR_SYSERR;
|
||||
goto cleanup;
|
||||
}
|
||||
memset(b, 0, sizeof(*b));
|
||||
|
||||
b->subscribed = subscribed;
|
||||
|
@ -184,25 +221,36 @@ uirc_struct_assm_buffer(IRC_Buffer_Type type, IRC_Modes modes, bool subscribed,
|
|||
b->type = type;
|
||||
if ((b->name = stringext_strmalloc(name, strlen(name))) == NULL || (key != NULL && (b->name = stringext_strmalloc(key, strlen(key))) == NULL)
|
||||
|| (topic != NULL && (b->topic = stringext_strmalloc(topic, strlen(topic))) == NULL)) {
|
||||
uirc_struct_free(b, IRC_STRUCT_BUFFER);
|
||||
free(b);
|
||||
return NULL;
|
||||
uirc_errno = UIRC_ERR_SYSERR;
|
||||
goto cleanup;
|
||||
}
|
||||
return b;
|
||||
cleanup:
|
||||
if (b != NULL) uirc_struct_free(b, IRC_STRUCT_BUFFER);
|
||||
free(b);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IRC_Network*
|
||||
uirc_struct_assm_network(const char* addr, const char* svc, const char* pass)
|
||||
{
|
||||
IRC_Network* n = malloc(sizeof(*n));
|
||||
IRC_Network* n = NULL;
|
||||
|
||||
if ((n = malloc(sizeof(*n))) == NULL) {
|
||||
uirc_errno = UIRC_ERR_SYSERR;
|
||||
goto cleanup;
|
||||
}
|
||||
memset(n, 0, sizeof(*n));
|
||||
|
||||
if ((addr != NULL && (n->addr = stringext_strmalloc(addr, strlen(addr))) == NULL)
|
||||
|| (svc != NULL && (n->svc = stringext_strmalloc(svc, strlen(svc))) == NULL)
|
||||
|| (pass != NULL && (n->pass = stringext_strmalloc(pass, strlen(pass))) == NULL)) {
|
||||
uirc_struct_free(n, IRC_STRUCT_NETWORK);
|
||||
free(n);
|
||||
return NULL;
|
||||
uirc_errno = UIRC_ERR_SYSERR;
|
||||
goto cleanup;
|
||||
}
|
||||
return n;
|
||||
cleanup:
|
||||
uirc_struct_free(n, IRC_STRUCT_NETWORK);
|
||||
free(n);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
* along with uIRC. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "errors.h" // uirc_errno
|
||||
#include "memory.h" // uirc_memory_*()
|
||||
#include "tokenizers.h" // uirc_tokenizer_*()
|
||||
#include "types.h" // IRC_Message
|
||||
|
@ -27,7 +28,6 @@
|
|||
#include <stdlib.h> // malloc()
|
||||
#include <string.h> // strlen()
|
||||
|
||||
static void free_ctx(IRC_Message* msg, char* str);
|
||||
static void skip_spaces(char** addr);
|
||||
|
||||
IRC_Message*
|
||||
|
@ -35,7 +35,14 @@ uirc_tokenizer_message(const char* str)
|
|||
{
|
||||
assert(str != NULL);
|
||||
|
||||
IRC_Message* const m = malloc(sizeof(IRC_Message));
|
||||
IRC_Message* m = NULL;
|
||||
char* ws = NULL;
|
||||
|
||||
if ((m = malloc(sizeof(*m))) == NULL) {
|
||||
uirc_errno = UIRC_ERR_SYSERR;
|
||||
goto cleanup;
|
||||
}
|
||||
memset(m, 0, sizeof(*m));
|
||||
|
||||
size_t len = strlen(str);
|
||||
// Ignore CRLF at the end, irrelevant for parsing
|
||||
|
@ -43,28 +50,22 @@ uirc_tokenizer_message(const char* str)
|
|||
len--;
|
||||
if (str[len - 1] == '\r') len--;
|
||||
}
|
||||
char* const ws = stringext_strmalloc(str, len); // NOTE: Some compilers might warn you about modifying contents of p because it points to ws which
|
||||
// is "immutable". This is safe to ignore as the purpose of it is to not use ws for tokenizing and
|
||||
// to save the original pointer which can be freed
|
||||
|
||||
char* p = ws;
|
||||
|
||||
if (ws == NULL || m == NULL) {
|
||||
free(ws);
|
||||
free(m);
|
||||
return NULL;
|
||||
if ((ws = stringext_strmalloc(str, len)) == NULL) {
|
||||
uirc_errno = UIRC_ERR_SYSERR;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
memset(m, 0, sizeof(IRC_Message));
|
||||
|
||||
char* p = ws;
|
||||
#ifdef UIRC_FEATURE_IRCV3
|
||||
if (*p == '@') {
|
||||
p++;
|
||||
const char* tmp = NULL;
|
||||
if ((tmp = stringext_strtok_mr(&p, " ")) == NULL || (m->tag_list = uirc_tokenizer_tag_list(tmp)) == NULL) {
|
||||
free_ctx(m, ws);
|
||||
return NULL;
|
||||
if ((tmp = stringext_strtok_mr(&p, " ")) == NULL) {
|
||||
uirc_errno = UIRC_ERR_INVFMT;
|
||||
goto cleanup;
|
||||
}
|
||||
if ((m->tag_list = uirc_tokenizer_tag_list(tmp)) == NULL) goto cleanup;
|
||||
}
|
||||
skip_spaces(&p);
|
||||
#endif /* UIRC_FEATURE_IRCV3 */
|
||||
|
@ -72,22 +73,27 @@ uirc_tokenizer_message(const char* str)
|
|||
if (*p == ':') {
|
||||
const char* tmp = NULL;
|
||||
p++;
|
||||
if ((tmp = stringext_strtok_mr(&p, " ")) == NULL || (m->source = uirc_tokenizer_user(tmp)) == NULL) {
|
||||
free_ctx(m, ws);
|
||||
return NULL;
|
||||
if ((tmp = stringext_strtok_mr(&p, " ")) == NULL) {
|
||||
uirc_errno = UIRC_ERR_INVFMT;
|
||||
goto cleanup;
|
||||
}
|
||||
if ((m->source = uirc_tokenizer_user(tmp)) == NULL) goto cleanup;
|
||||
skip_spaces(&p);
|
||||
}
|
||||
|
||||
if (isalnum(*p)) {
|
||||
const char* tmp = NULL;
|
||||
if ((tmp = stringext_strtok_mr(&p, " ")) == NULL || (m->command = stringext_strmalloc(tmp, strlen(tmp))) == NULL) {
|
||||
free_ctx(m, ws);
|
||||
return NULL;
|
||||
if ((tmp = stringext_strtok_mr(&p, " ")) == NULL) {
|
||||
uirc_errno = UIRC_ERR_INVFMT;
|
||||
goto cleanup;
|
||||
}
|
||||
if ((m->command = stringext_strmalloc(tmp, strlen(tmp))) == NULL) {
|
||||
uirc_errno = UIRC_ERR_SYSERR;
|
||||
goto cleanup;
|
||||
}
|
||||
} else {
|
||||
free_ctx(m, ws);
|
||||
return NULL;
|
||||
uirc_errno = UIRC_ERR_INVFMT;
|
||||
goto cleanup;
|
||||
}
|
||||
skip_spaces(&p);
|
||||
|
||||
|
@ -96,35 +102,36 @@ uirc_tokenizer_message(const char* str)
|
|||
if (i == IRC_MAXARGS - 1 || *p == ':') {
|
||||
if (*p == ':') {
|
||||
p++;
|
||||
// trailing is supposed to represent a early ending of spaced arguments, not if there's any arguments at all
|
||||
// trailing is supposed to represent a early ending of spaced arguments, not if there's any trailing arguments at all
|
||||
m->trailing = true;
|
||||
}
|
||||
if ((m->args[i++] = stringext_strmalloc(p, strlen(p))) == NULL) {
|
||||
free_ctx(m, ws);
|
||||
return NULL;
|
||||
uirc_errno = UIRC_ERR_SYSERR;
|
||||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
const char* tmp = NULL;
|
||||
if ((tmp = stringext_strtok_mr(&p, " ")) == NULL || (m->args[i++] = stringext_strmalloc(tmp, strlen(tmp))) == NULL) {
|
||||
free_ctx(m, ws);
|
||||
return NULL;
|
||||
if ((tmp = stringext_strtok_mr(&p, " ")) == NULL) {
|
||||
uirc_errno = UIRC_ERR_INVFMT;
|
||||
goto cleanup;
|
||||
}
|
||||
if ((m->args[i++] = stringext_strmalloc(tmp, strlen(tmp))) == NULL) {
|
||||
uirc_errno = UIRC_ERR_SYSERR;
|
||||
goto cleanup;
|
||||
}
|
||||
skip_spaces(&p);
|
||||
}
|
||||
m->args[i] = NULL;
|
||||
if (i < IRC_MAXARGS) m->args[i] = NULL;
|
||||
}
|
||||
|
||||
free(ws);
|
||||
return m;
|
||||
}
|
||||
|
||||
static void
|
||||
free_ctx(IRC_Message* msg, char* str)
|
||||
{
|
||||
uirc_struct_free(msg, IRC_STRUCT_MESSAGE);
|
||||
free(msg);
|
||||
free(str);
|
||||
cleanup:
|
||||
if (m != NULL) uirc_struct_free(m, IRC_STRUCT_MESSAGE);
|
||||
free(m);
|
||||
free(ws);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
* along with uIRC. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "errors.h" // uirc_errno
|
||||
#include "memory.h" // Free_IRC_Tag()
|
||||
#include "tokenizers.h" // uirc_tokenizer_tags()
|
||||
#include "types.h" // IRC_Tag
|
||||
|
@ -27,28 +28,28 @@
|
|||
#include <stdlib.h> // free()
|
||||
#include <string.h> // strchr()
|
||||
|
||||
static void free_ctx(llist_t* list, IRC_Tag* t, char* s);
|
||||
|
||||
llist_t*
|
||||
uirc_tokenizer_tag_list(const char* str)
|
||||
{
|
||||
assert(str != NULL);
|
||||
|
||||
char* const ws = stringext_strmalloc(str, strlen(str));
|
||||
char * p = ws, *tmp;
|
||||
llist_t * pl = NULL, *l = NULL;
|
||||
if (ws == NULL) return NULL;
|
||||
llist_t* l = NULL;
|
||||
char* ws = NULL;
|
||||
|
||||
if ((ws = stringext_strmalloc(str, strlen(str))) == NULL) {
|
||||
uirc_errno = UIRC_ERR_SYSERR;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
char * p = ws, *tmp;
|
||||
llist_t* pl = NULL;
|
||||
while ((tmp = stringext_strtok_mr(&p, ";")) != NULL) {
|
||||
llist_t* cl;
|
||||
if ((cl = llist_elem_alloc(0)) == NULL) {
|
||||
free_ctx(l, NULL, ws);
|
||||
return NULL;
|
||||
}
|
||||
if ((cl->content = uirc_tokenizer_tag(tmp)) == NULL) {
|
||||
free_ctx(l, NULL, ws);
|
||||
return NULL;
|
||||
uirc_errno = UIRC_ERR_SYSERR;
|
||||
goto cleanup;
|
||||
}
|
||||
if ((cl->content = uirc_tokenizer_tag(tmp)) == NULL) goto cleanup;
|
||||
|
||||
if (l == NULL) l = cl;
|
||||
else
|
||||
|
@ -58,6 +59,9 @@ uirc_tokenizer_tag_list(const char* str)
|
|||
|
||||
free(ws);
|
||||
return l;
|
||||
cleanup:
|
||||
if (l != NULL) uirc_list_free(l, IRC_STRUCT_TAG);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IRC_Tag*
|
||||
|
@ -65,18 +69,21 @@ uirc_tokenizer_tag(const char* str)
|
|||
{
|
||||
assert(str != NULL);
|
||||
|
||||
char* const ws = stringext_strmalloc(str, strlen(str));
|
||||
IRC_Tag* t = malloc(sizeof(IRC_Tag));
|
||||
char* ckey = ws;
|
||||
char* ws = NULL;
|
||||
IRC_Tag* t = NULL;
|
||||
|
||||
if (t == NULL || ws == NULL) {
|
||||
free(t);
|
||||
free(ws);
|
||||
return NULL;
|
||||
if ((ws = stringext_strmalloc(str, strlen(str))) == NULL) {
|
||||
uirc_errno = UIRC_ERR_SYSERR;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
memset(t, 0, sizeof(IRC_Tag));
|
||||
if ((t = malloc(sizeof(*t))) == NULL) {
|
||||
uirc_errno = UIRC_ERR_SYSERR;
|
||||
goto cleanup;
|
||||
}
|
||||
memset(t, 0, sizeof(*t));
|
||||
|
||||
char* ckey = ws;
|
||||
if (*ws == '+') {
|
||||
ckey++;
|
||||
t->clientbound = true;
|
||||
|
@ -85,30 +92,20 @@ uirc_tokenizer_tag(const char* str)
|
|||
if (cval != NULL) {
|
||||
*(cval++) = '\0';
|
||||
if ((t->value = stringext_strmalloc(cval, strlen(cval))) == NULL) {
|
||||
free_ctx(NULL, t, ws);
|
||||
return NULL;
|
||||
uirc_errno = UIRC_ERR_SYSERR;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
if ((t->key = stringext_strmalloc(ckey, strlen(ckey))) == NULL) {
|
||||
free_ctx(NULL, t, ws);
|
||||
return NULL;
|
||||
uirc_errno = UIRC_ERR_SYSERR;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
free(ws);
|
||||
return t;
|
||||
}
|
||||
|
||||
static void
|
||||
free_ctx(llist_t* list, IRC_Tag* t, char* s)
|
||||
{
|
||||
for (llist_t* c = list; c != NULL;) {
|
||||
llist_t* l = c;
|
||||
c = c->next;
|
||||
if (l->content != NULL) uirc_struct_free(l->content, IRC_STRUCT_TAG);
|
||||
llist_elem_rm(l);
|
||||
}
|
||||
uirc_struct_free(t, IRC_STRUCT_TAG);
|
||||
cleanup:
|
||||
if (t != NULL) uirc_struct_free(t, IRC_STRUCT_TAG);
|
||||
free(t);
|
||||
free(s);
|
||||
free(ws);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
* along with uIRC. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "errors.h" // uirc_errno
|
||||
#include "memory.h" // uirc_memory_*()
|
||||
#include "tokenizers.h" // uirc_tokenizer_*()
|
||||
#include "types.h" // IRC_Message
|
||||
|
@ -26,52 +27,50 @@
|
|||
#include <stdlib.h> // malloc()
|
||||
#include <string.h> // strchr()
|
||||
|
||||
static void free_ctx(IRC_User* u, char* s);
|
||||
|
||||
IRC_User*
|
||||
uirc_tokenizer_user(const char* str)
|
||||
{
|
||||
assert(str != NULL);
|
||||
|
||||
IRC_User* u = malloc(sizeof(IRC_User));
|
||||
char* const ws = stringext_strmalloc(str, strlen(str));
|
||||
char* tmp;
|
||||
IRC_User* u = NULL;
|
||||
char* ws = NULL;
|
||||
|
||||
if (u == NULL || ws == NULL) {
|
||||
free(u);
|
||||
free(ws);
|
||||
return NULL;
|
||||
if ((u = malloc(sizeof(*u))) == NULL) {
|
||||
uirc_errno = UIRC_ERR_SYSERR;
|
||||
goto cleanup;
|
||||
}
|
||||
memset(u, 0, sizeof(*u));
|
||||
|
||||
if ((ws = stringext_strmalloc(str, strlen(str))) == NULL) {
|
||||
uirc_errno = UIRC_ERR_SYSERR;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
memset(u, 0, sizeof(IRC_User));
|
||||
|
||||
char* tmp;
|
||||
if ((tmp = strchr(ws, '@')) != NULL) {
|
||||
*(tmp++) = '\0';
|
||||
if ((u->host = stringext_strmalloc(tmp, strlen(tmp))) == NULL) {
|
||||
free_ctx(u, ws);
|
||||
return NULL;
|
||||
uirc_errno = UIRC_ERR_SYSERR;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
if ((tmp = strchr(ws, '!')) != NULL) {
|
||||
*(tmp++) = '\0';
|
||||
if ((u->user = stringext_strmalloc(tmp, strlen(tmp))) == NULL) {
|
||||
free_ctx(u, ws);
|
||||
return NULL;
|
||||
uirc_errno = UIRC_ERR_SYSERR;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
if ((u->nick = stringext_strmalloc(ws, strlen(ws))) == NULL) {
|
||||
free_ctx(u, ws);
|
||||
return NULL;
|
||||
uirc_errno = UIRC_ERR_SYSERR;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
free(ws);
|
||||
return u;
|
||||
}
|
||||
|
||||
static void
|
||||
free_ctx(IRC_User* u, char* s)
|
||||
{
|
||||
uirc_struct_free(u, IRC_STRUCT_USER);
|
||||
cleanup:
|
||||
if (u != NULL) uirc_struct_free(u, IRC_STRUCT_USER);
|
||||
free(u);
|
||||
free(s);
|
||||
free(ws);
|
||||
return NULL;
|
||||
}
|
||||
|
|
Reference in New Issue