• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

orium

[C] Listas e xalloc

1 mensagem neste tópico

Aqui esta um header para criação de listas, feita inteiramente por macros (pela performance (sintam-se livres para as implementar como funções (inline, porque não? (vou parar com os parênteses, que parece que estou a escrever lisp)))).

Este header depende de xalloc.h, também escrito por mim, que implementa as funções de alocação dinâmica de memória com verificação implícita.

lalloc.h:

/*
*  GPL
*
*  Written by Diogo Sousa aka orium
*  Copyright (C) 2007 Diogo Sousa
*
*  This program 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
*  (at your option) any later version.
*
*  This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef LALLOC_H_
#define LALLOC_H_

#include <stdlib.h>
#include "xalloc.h"

/* Nota: As macros neste ficheiro devem assegurar apenas as ligações das listas.
*       So' aos membros next e prev devem ser atribuidos valores.
*
* *SO'* devera' ser feito free() se a função tiver explicitamente "free" no identificador
*/

/* Listas bidirecionais:
*      #define alloc_something(plst) _alloc_bi_node(plst)
*      #define alloc_something_with_last(plst,last_node) _alloc_bi_node_with_last(plst,last_node)
*      #define alloc_something_in_head(plst) _alloc_bi_node_in_head(plst)
*      #define rm_something(plst,torm) _rm_bi_node(plst,torm)
*      #define free_entire_something(plst,do_something_with_each_node) _free_entire_list(plst,do_something_with_each_node)
*
* Listas unidirecionais
*      #define alloc_something(plst) _alloc_uni_node(plst)
*      #define alloc_something_with_last(plst,last_node) _alloc_uni_node_with_last(plst,last_node)
*      #define alloc_something_in_head(plst) _alloc_uni_node_in_head(plst)
*      #define free_entire_something(plst,do_something_with_each_node) _free_entire_list(plst,do_something_with_each_node)
*/

/*Aloca nós de listas bidirecionais*/
#define _alloc_bi_node(_lst)                                                  \
        (                                                                     \
        {                                                                     \
                typeof(*_lst) _node;                                          \
                typeof(_lst) _plst=(_lst);                                    \
                                                                              \
                if (*_plst == NULL)                                           \
                {                                                             \
                        _node=*_plst=xmalloc(sizeof(**_plst));                \
                        _node->prev=NULL;                                     \
                }                                                             \
                else                                                          \
                {                                                             \
           for (_node=*_plst; _node != NULL; _node=_node->next)  \
                                if (_node->next == NULL)                      \
                                        break;                                \
                                         \
                        _node->next=xmalloc(sizeof(*_node->next));            \
                                                                              \
                        _node->next->prev=_node;                              \
                                                                              \
                        _node=_node->next;                                    \
                }                                                             \
                                                                              \
                _node->next=NULL;                                             \
                                                                              \
                _node;                                                        \
        }                                                                     \
        )

/*Aloca nós de listas bidirecionais, no inicio da lista*/
#define _alloc_bi_node_in_head(_lst)                                            \
        (                                                                       \
        {                                                                       \
                typeof(_lst) _plst=(_lst);                                      \
                typeof(*_lst) _next=*_plst;                                     \
                typeof(*_lst) _node;                                            \
                                                                                \
                _node=*_plst=xmalloc(sizeof(**_plst));                          \
                                                                                \
                _node->next=_next;                                              \
                _node->prev=NULL;                                               \
                                                                                \
                if (_node->next != NULL)                                        \
                        _node->next->prev=_node;                                \
                                                                                \
                _node;                                                          \
        }                                                                       \
        )

/*Aloca nós de listas bidirecionais sabendo o ultimo no', para melhorar a performance*/
#define _alloc_bi_node_with_last(_lst,_last_node)                                       \
        (                                                                               \
        {                                                                               \
                typeof(*_lst) _node;                                                    \
                typeof(_lst) _plst=(_lst);                                              \
                                                                                        \
                if (*_plst == NULL)                                                     \
                {                                                                       \
                        _node=*_plst=xmalloc(sizeof(**_plst));                          \
                        _node->prev=NULL;                                               \
                }                                                                       \
                else                                                                    \
                {                                                                       \
                                                                                        \
                        if ((_last_node) == NULL)                                       \
                        {                                                               \
                                for (_node=*_plst; _node != NULL; _node=_node->next)    \
                                        if (_node->next == NULL)                        \
                                                break;                                  \
                        }                                                               \
                        else                                                            \
                        {                                                               \
                                _node=(_last_node);                                     \
                                assert(_node->next == NULL);                            \
                        }                                                               \
                                                                                        \
                        _node->next=xmalloc(sizeof(*_node->next));                      \
                                                                                        \
                        _node->next->prev=_node;                                        \
                                                                                        \
                        _node=_node->next;                                              \
                }                                                                       \
                                                                                        \
                _node->next=NULL;                                                       \
                                                                                        \
                _node;                                                                  \
        }                                                                               \
        )

/*Retira nós de listas bidirecionais*/
#define _rm_bi_node(_lst,_torm)                                                 \
        (                                                                       \
        {                                                                       \
                typeof(_torm) _torm2=(_torm);                                   \
                typeof(_lst) _lst2=(_lst);                                      \
                                                                                \
                if (_torm2 != NULL && *_lst2 != NULL)                           \
                {                                                               \
                        if (_torm2->prev == NULL)                               \
                        {                                                       \
                                *_lst2=_torm2->next;                            \
                                                                                \
                                if (_torm2->next != NULL)                       \
                                        _torm2->next->prev=NULL;                \
                        }                                                       \
                        else                                                    \
                        {                                                       \
                                _torm2->prev->next=_torm2->next;                \
                                                                                \
                                if (_torm2->next != NULL)                       \
                                        _torm2->next->prev=_torm2->prev;        \
                        }                                                       \
                }                                                               \
        }                                                                       \
        )

/*Aloca nós de listas unidirecionais*/
#define _alloc_uni_node(_lst)                                                   \
        (                                                                       \
        {                                                                       \
                typeof(*_lst) _node;                                            \
                typeof(_lst) _plst=(_lst);                                      \
                                                                                \
                if (*_plst == NULL)                                             \
                        _node=*_plst=xmalloc(sizeof(**_plst));                  \
                else                                                            \
                {                                                               \
                        for (_node=*_plst; _node != NULL; _node=_node->next)    \
                                if (_node->next == NULL)                        \
                                        break;                                  \
                                                                                \
                        _node->next=xmalloc(sizeof(*_node->next));              \
                        _node=_node->next;                                      \
                }                                                               \
                                                                                \
                _node->next=NULL;                                               \
                                                                                \
                _node;                                                          \
        }                                                                       \
        )

/*Aloca nós de listas unidirecionais no inicio da lista*/
#define _alloc_uni_node_in_head(_lst)                                           \
        (                                                                       \
        {                                                                       \
                typeof(_lst) _plst=(_lst);                                      \
                typeof(*_lst) _next=*_plst;                                     \
                typeof(*_lst) _node;                                            \
                                                                                \
                _node=*_plst=xmalloc(sizeof(**_plst));                          \
                                                                                \
                _node->next=_next;                                              \
                                                                                \
                _node;                                                          \
        }                                                                       \
        )

/*Aloca nós de listas unidirecionais sabendo o ultimo no', para melhorar a performance*/
#define _alloc_uni_node_with_last(_lst,_last_node)                                      \
        (                                                                               \
        {                                                                               \
                typeof(*_lst) _node;                                                    \
                typeof(_lst) _plst=(_lst);                                              \
                                                                                        \
                if (*_plst == NULL)                                                     \
                        _node=*_plst=xmalloc(sizeof(**_plst));                          \
                else                                                                    \
                {                                                                       \
                        if ((_last_node) == NULL)                                       \
                        {                                                               \
                                for (_node=*_plst; _node != NULL; _node=_node->next)    \
                                        if (_node->next == NULL)                        \
                                                break;                                  \
                        }                                                               \
                        else                                                            \
                        {                                                               \
                                _node=(_last_node);                                     \
                                assert(_node->next == NULL);                            \
                        }                                                               \
                                                                                        \
                        _node->next=xmalloc(sizeof(*_node->next));                      \
                        _node=_node->next;                                              \
                }                                                                       \
                                                                                        \
                _node->next=NULL;                                                       \
                                                                                        \
                _node;                                                                  \
        }                                                                               \
        )

/*Liberta listas unidirecionais/bidirecionais*/
#define _free_entire_list(_lst,do_something_with_each_node)               \
        (                                                                 \
        {                                                                 \
                typeof(*_lst) _node;                                      \
                typeof(*_lst) _next_node;                                 \
                typeof(_lst) _plst=(_lst);                                \
                                                                          \
                                                                          \
                for (_node=*_plst; _node != NULL; _node=_next_node)       \
                {                                                         \
                        _next_node=_node->next;                           \
                        if (do_something_with_each_node != NULL)          \
                                do_something_with_each_node(_node);       \
                        free(_node);                                      \
                }                                                         \
                                                                          \
                *_plst=NULL;                                              \
        }                                                                 \
        )
#endif /*alloc.h included*/

xalloc.c:

/*
*  GPL
*
*  Written by Diogo Sousa aka orium
*  Copyright (C) 2007 Diogo Sousa
*
*  This program 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
*  (at your option) any later version.
*
*  This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void xalloc_set_error_func(void (*f)(void));
void xmemerror(void);
void *xmalloc(size_t size);
void *xcalloc(size_t nmemb, size_t size);
void *xrealloc(void *ptr, size_t size);
char *xstrdup(const char *s);

static void (*mem_error_func)(void)=xmemerror;

void xalloc_set_error_func(void (*f)(void))
{
        mem_error_func=f;
}

void xmemerror(void)
{
        fprintf(stderr,"Erro na alocação de memória\n");
        exit(EXIT_FAILURE);
}

void *xmalloc(size_t size)
{
        void *r;

        r=malloc(size);

        if (r == NULL)
                mem_error_func();

        return r;
}

void *xcalloc(size_t nmemb, size_t size)
{
        void *r;

        r=calloc(nmemb,size);

        if (r == NULL)
                mem_error_func();

        return r;
}

void *xrealloc(void *ptr, size_t size)
{
        void *r;

        r=realloc(ptr,size);

        if (r == NULL)
                mem_error_func();

        return r;
}

char *xstrdup(const char *s)
{
        char *r;

        r=strdup(s);

        if (r == NULL)
                mem_error_func();

        return r;
}

xalloc.h:

/*
*  GPL
*
*  Written by Diogo Sousa aka orium
*  Copyright (C) 2007 Diogo Sousa
*
*  This program 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
*  (at your option) any later version.
*
*  This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XALLOC_H_
#define XALLOC_H_
#include <stdlib.h>

extern void xalloc_set_error_func(void (*)(void));
extern void xmemerror(void);
extern void *xmalloc(size_t);
extern void *xcalloc(size_t, size_t);
extern void *xrealloc(void *, size_t);
extern char *xstrdup(const char *);

#endif /*xalloc.h included*/

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora