Remove struct copy and document some more things

This commit is contained in:
Alex D. 2021-03-14 16:35:38 +00:00
parent 423f7bc021
commit 91f370fa58
Signed by: caskd
GPG Key ID: F92BA85F61F4C173
7 changed files with 95 additions and 169 deletions

View File

@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.16)
project(
uIRC
VERSION 0.3.0
VERSION 0.3.1
DESCRIPTION "Simple and lightweight IRC protocol helper"
LANGUAGES C
)
@ -81,6 +81,7 @@ if(BUILD_DOCS)
doxygen_add_docs(docgen
src/doc/main.doc
README.md
${UIRC_HEADERS}
ALL
)
endif()

View File

@ -38,10 +38,10 @@ ssize_t uirc_assembler_tag_list(char* buf, const llist_t* t, size_t len);
*
* This assembles a IRC_Message struct to a string representation of a most size len
* The return value is either the lenght of the string or any of the uirc_errors errors
* \param[out] buf String representation of message
* \param[in] m IRC_Message struct that contains at least a command
* \param[in] len Maximum lenght of string
* \param[out] buf String representation of message (if successful)
* \warning in and buf SHOULD NOT be NULL, this will trigger a ASSERT so it's required to check it where needed
* \warning in and buf SHOULD NOT be NULL
*/
ssize_t uirc_assembler_message(char* buf, const IRC_Message* m, size_t len);
#endif /* UIRC_GUARD_PUBLIC_ASSEMBLERS */

View File

@ -25,8 +25,7 @@
#ifndef UIRC_GUARD_PUBLIC_MEMORY
#define UIRC_GUARD_PUBLIC_MEMORY
void* uirc_struct_copy(const void* src, IRC_Struct_Type type);
void uirc_struct_free(void* obj, IRC_Struct_Type type);
void uirc_struct_free(void* obj, IRC_Struct_Type type);
#ifdef UIRC_FEATURE_IRCV3
IRC_Tag* uirc_struct_assm_tag(bool clientbound, const char* key, const char* value);

View File

@ -48,7 +48,7 @@ IRC_User* uirc_tokenizer_user(const char* str);
/*!
* \brief Tokenize a IRC message string.
*
* This function takes a IRC Message and attempts to tokenize/parse it, pointing every element found to it's respective struct element
* This function takes a IRC message and attempts to tokenize/parse it, pointing every element found to it's respective struct element
* \param[in] str String containing a IRC message without the ending '\\r\\n'
*/
IRC_Message* uirc_tokenizer_message(const char* str);

View File

@ -29,62 +29,115 @@ typedef unsigned short IRC_Modes;
typedef uintmax_t IRC_Counter;
#ifdef UIRC_FEATURE_IRCV3
/*!
* \brief Capability status structure
*/
typedef struct {
char *key, *value;
bool clientbound;
char *key, /*!< Name of the tag */
*value; /*!< Value of the tag
* \warning may be NULL
*/
bool clientbound; /*!< true if the tag is sent by the client */
} IRC_Tag;
/*!
* \brief Capability status structure
*/
typedef struct {
char* name;
bool active;
char* name; /*!< Name of the capability */
bool active; /*!< Status of the capability */
} IRC_Capability;
#endif /* UIRC_FEATURE_IRCV3 */
/*!
* \brief User information structure
*/
typedef struct {
char * nick, *user, *host, *real;
IRC_Modes modes;
bool is_service;
char *nick, /*!< Nickname of the user */
*user, /*!< Username of the user */
*host, /*!< Hostname of the user */
*real; /*!< Real name of the user
* \note It is only used in USER registrations
*/
IRC_Modes modes; /*!< Modes that the user has active on the network */
bool is_service; /*!< Whether the user is a service or not */
} IRC_User;
/*!
* \brief The maximum amount of arguments in a message (including trailing)
*
* See *params* at \ref https://tools.ietf.org/html/rfc2812#section-2.3.1
* \warning This should remain as it is unless you deal with a special implementation that can handle more
*/
#define IRC_MAXARGS 15
/*!
* \brief Message information structure
*/
typedef struct {
IRC_User* source;
char* command;
char* args[IRC_MAXARGS]; /* 0-13 + trailing, ended early with a NULL */
bool trailing; /* Tells if the last argument is trailing */
IRC_User* source; /*!< Where the message originates from */
char* command; /*!< Command of the message */
char* args[IRC_MAXARGS]; /*!< Array of arguments up to \ref IRC_MAXARGS, ended early by a NULL */
bool trailing; /*!< Tells if the last argument is trailing */
#ifdef UIRC_FEATURE_IRCV3
llist_t* tag_list;
#endif /* UIRC_FEATURE_IRCV3 */
llist_t* tag_list; /*!< Linked list of \ref IRC_Tag for the message */
#endif /* UIRC_FEATURE_IRCV3 */
} IRC_Message;
typedef enum { IRC_DIRECT, IRC_CHANNEL, IRC_GLOBAL } IRC_Buffer_Type;
/*!
* \brief List of possible buffer types
*/
typedef enum {
IRC_DIRECT, /*!< Private buffer (direct messages) */
IRC_CHANNEL, /*!< Channel buffer (group of people) */
IRC_GLOBAL /*!< Anything else that doesn't fit in the other categories */
} IRC_Buffer_Type;
/*!
* \brief Buffer information structure
*
* This structure contains lists and information about a buffer
*/
typedef struct {
IRC_Buffer_Type type;
char * name, *topic, *key;
bool subscribed;
IRC_Modes modes;
llist_t * user_list, *message_list;
IRC_Buffer_Type type; /*!< Type of the buffer */
char * name, /*!< Name of the buffer, usually channel name or nickname */
*topic, /*!< Topic of the buffer (only applies to channels) */
*key; /*!< Password required to subscribe to the buffer (to be used with PASS) */
bool subscribed; /*!< Subscription status (eg. being part of a channel) */
IRC_Modes modes; /*!< Modes for the buffer (not to be confused to modes of a user) */
llist_t * user_list, /*!< Linked list of \ref IRC_User participating in a buffer (channel usually) */
*message_list; /*!< Linked list of \ref IRC_Message received on that buffer */
} IRC_Buffer;
/*!
* \brief Network information structure
*
* This structure contains all the information related to a network and inherits all the other structures directly or indirectly
*/
typedef struct {
char * addr, *svc, *pass;
IRC_User* user;
llist_t* buf_list;
char *addr, /*!< Address of the server (usually IP address for TCP) */
*svc, /*!< Service description (port for TCP) */
*pass; /*!< Password for the service */
IRC_User* user; /*!< User that registers on the network (self) */
llist_t* buf_list; /*!< Linked list of \ref IRC_Buffer open to this network */
#ifdef UIRC_FEATURE_IRCV3
llist_t* cap_list;
#endif /* UIRC_FEATURE_IRCV3 */
llist_t* cap_list; /*!< Linked list of \ref IRC_Capability for this network */
#endif /* UIRC_FEATURE_IRCV3 */
} IRC_Network;
/*!
* \brief List of structure types available
*
* This is used to signal what kind of structure was passed to a function which accepts multiple types or is a void pointer
*/
typedef enum {
#ifdef UIRC_FEATURE_IRCV3
IRC_STRUCT_TAG,
IRC_STRUCT_CAPABILITY,
#endif /* UIRC_FEATURE_IRCV3 */
IRC_STRUCT_USER,
IRC_STRUCT_MESSAGE,
IRC_STRUCT_BUFFER,
IRC_STRUCT_NETWORK
IRC_STRUCT_TAG, /*!< \ref IRC_Tag */
IRC_STRUCT_CAPABILITY, /*!< \ref IRC_Capability */
#endif /* UIRC_FEATURE_IRCV3 */
IRC_STRUCT_USER, /*!< \ref IRC_User */
IRC_STRUCT_MESSAGE, /*!< \ref IRC_Message */
IRC_STRUCT_BUFFER, /*!< \ref IRC_Buffer */
IRC_STRUCT_NETWORK /*!< \ref IRC_Network */
} IRC_Struct_Type;
#endif /* UIRC_GUARD_PUBLIC_TYPES */

View File

@ -1,30 +1,2 @@
/// ***************************************************************************
/// @mainpage MicroIRC library
///
/// @section Core
/// @subsection Assemblers
/// Assemblers are a quick way to convert structs to a string representation
///
/// - \ref Assm_mesg
/// - \ref Assm_user
///
/// @subsection Tokenizers
/// Tokenizers tokenize and point struct elements to the matching substrings in the string given
///
/// - \ref Tok_mesg
/// - \ref Tok_user
///
/// @section Additions
///
/// @subsection Validators
/// - \ref Val_mesg
///
/// @subsection IRCv3
/// @subsubsection Tags
/// - \ref Assm_tags
/// - \ref Tok_tags
///
/// @subsubsection Capabilities
///
///
/// ***************************************************************************

View File

@ -21,109 +21,9 @@
#include <assert.h> // assert()
#include <corelibs/stringext.h> // stringext_strmalloc()
#include <stdarg.h>
#include <stdlib.h> // free()
#include <string.h> // strlen()
void*
uirc_struct_copy(const void* src, IRC_Struct_Type type)
{
assert(src != NULL);
void* ret = NULL;
size_t structsize = 0;
switch (type) {
#ifdef UIRC_FEATURE_IRCV3
case IRC_STRUCT_TAG: structsize = sizeof(IRC_Tag); break;
case IRC_STRUCT_CAPABILITY: structsize = sizeof(IRC_Capability); break;
#endif /* UIRC_FEATURE_IRCV3 */
case IRC_STRUCT_USER: structsize = sizeof(IRC_User); break;
case IRC_STRUCT_MESSAGE: structsize = sizeof(IRC_Message); break;
case IRC_STRUCT_BUFFER: structsize = sizeof(IRC_Buffer); break;
case IRC_STRUCT_NETWORK: structsize = sizeof(IRC_Network); break;
}
if ((ret = malloc(structsize)) == NULL) return NULL;
memset(ret, 0, structsize);
switch (type) {
#ifdef UIRC_FEATURE_IRCV3
case IRC_STRUCT_TAG: {
IRC_Tag* c_ret = ret;
const IRC_Tag* c_src = src;
c_ret->clientbound = c_src->clientbound;
if (((c_ret->key = stringext_strmalloc(c_src->key, strlen(c_src->key))) == NULL)
|| (c_src->value != NULL && (c_ret->value = stringext_strmalloc(c_src->value, strlen(c_src->value))) == NULL))
break;
return ret;
}
case IRC_STRUCT_CAPABILITY: {
IRC_Capability* c_ret = ret;
const IRC_Capability* c_src = src;
c_ret->active = c_src->active;
if ((c_ret->name = stringext_strmalloc(c_src->name, strlen(c_src->name))) == NULL) break;
return ret;
}
#endif /* UIRC_FEATURE_IRCV3 */
case IRC_STRUCT_USER: {
IRC_User* c_ret = ret;
const IRC_User* c_src = src;
c_ret->modes = c_src->modes;
c_ret->is_service = c_src->is_service;
if ((c_src->nick != NULL && (c_ret->nick = stringext_strmalloc(c_src->nick, strlen(c_src->nick))) == NULL)
|| (c_src->user != NULL && (c_ret->user = stringext_strmalloc(c_src->user, strlen(c_src->user))) == NULL)
|| (c_src->real != NULL && (c_ret->real = stringext_strmalloc(c_src->real, strlen(c_src->real))) == NULL)
|| (c_src->host != NULL && (c_ret->host = stringext_strmalloc(c_src->host, strlen(c_src->host))) == NULL))
break;
return ret;
}
case IRC_STRUCT_MESSAGE: {
IRC_Message* c_ret = ret;
const IRC_Message* c_src = src;
c_ret->trailing = c_src->trailing;
if ((c_ret->command = stringext_strmalloc(c_src->command, strlen(c_src->command))) == NULL) break;
for (unsigned short i = 0; i < IRC_MAXARGS && c_src->args[i] != NULL; i++)
if ((c_ret->args[i] = stringext_strmalloc(c_src->args[i], strlen(c_src->args[i]))) == NULL) break;
return ret;
}
case IRC_STRUCT_BUFFER: {
IRC_Buffer* c_ret = ret;
const IRC_Buffer* c_src = src;
c_ret->modes = c_src->modes;
c_ret->subscribed = c_src->subscribed;
if ((c_ret->name = stringext_strmalloc(c_src->name, strlen(c_src->name))) == NULL
|| (c_src->topic != NULL && (c_ret->topic = stringext_strmalloc(c_src->topic, strlen(c_src->topic))) == NULL)
|| (c_src->key != NULL && (c_ret->key = stringext_strmalloc(c_src->key, strlen(c_src->key))) == NULL))
break;
return ret;
}
case IRC_STRUCT_NETWORK: {
IRC_Network* c_ret = ret;
const IRC_Network* c_src = src;
if ((c_ret->addr = stringext_strmalloc(c_src->addr, strlen(c_src->addr))) == NULL
|| (c_src->svc != NULL && (c_ret->svc = stringext_strmalloc(c_src->svc, strlen(c_src->svc))) == NULL)
|| (c_src->pass != NULL && (c_ret->pass = stringext_strmalloc(c_src->pass, strlen(c_src->pass))) == NULL))
break;
return ret;
}
}
uirc_struct_free(ret, type);
free(ret);
return NULL;
}
#include <stdarg.h> // va_*
#include <stdlib.h> // free()
#include <string.h> // strlen()
void
uirc_struct_free(void* obj, IRC_Struct_Type type)
@ -200,7 +100,8 @@ uirc_struct_assm_tag(bool clientbound, const char* key, const char* value)
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)) {
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;