2
\$\begingroup\$

In order to learn macros in C I decided to make a generic data structures generator for other projects that I have in C.

The main macros are the following:

  1. CONTAINER_GENERATE(C, P, PFX, SNAME, FMOD, T) ....
  2. CONTAINER_GENERATE_SOURCE(C, P, PFX, SNAME, FMOD, T) ....
  3. CONTAINER_GENERATE_HEADER(C, P, PFX, SNAME, FMOD, T) ....

Where:

  • C - The container you want;
    • Currently available are LIST, STACK and QUEUE;
  • P - If you want your data structure's fields visible;
    • PRIVATE or PUBLIC. Hides the structure definition in the source file;
    • Only makes a difference in the macros 2 and 3;
  • PFX - Functions prefix, or namespace;
  • SNAME - Structure name (typedef SNAME##_s SNAME;);
  • FMOD - Functions modifier;
    • Currently I've been using static with macro 1;
  • T - Your data type to be worked with.

And here is the source file:

macro_containers.h

#ifndef MACRO_CONTAINERS
#define MACRO_CONTAINERS

#define CONCATH_(C, P) C##_GENERATE_HEADER##_##P
#define CONCATC_(C, P) C##_GENERATE_SOURCE##_##P

#define CONCATH(C, P) CONCATH_(C, P)
#define CONCATC(C, P) CONCATC_(C, P)

#define CONTAINER_GENERATE(C, P, PFX, SNAME, FMOD, T)    \
    CONTAINER_GENERATE_HEADER(C, P, PFX, SNAME, FMOD, T) \
    CONTAINER_GENERATE_SOURCE(C, P, PFX, SNAME, FMOD, T)

#define CONTAINER_GENERATE_HEADER(C, P, PFX, SNAME, FMOD, T) \
    CONCATH(C, P)                                            \
    (PFX, SNAME, FMOD, T)

#define CONTAINER_GENERATE_SOURCE(C, P, PFX, SNAME, FMOD, T) \
    CONCATC(C, P)                                            \
    (PFX, SNAME, FMOD, T)

/*****************************************************************************/
/********************************************************************** LIST */
/*****************************************************************************/

/* PRIVATE *******************************************************************/
#define LIST_GENERATE_HEADER_PRIVATE(PFX, SNAME, FMOD, T) \
    LIST_GENERATE_HEADER(PFX, SNAME, FMOD, T)
#define LIST_GENERATE_SOURCE_PRIVATE(PFX, SNAME, FMOD, T) \
    LIST_GENERATE_STRUCT(PFX, SNAME, FMOD, T)             \
    LIST_GENERATE_SOURCE(PFX, SNAME, FMOD, T)
/* PUBLIC ********************************************************************/
#define LIST_GENERATE_HEADER_PUBLIC(PFX, SNAME, FMOD, T) \
    LIST_GENERATE_STRUCT(PFX, SNAME, FMOD, T)            \
    LIST_GENERATE_HEADER(PFX, SNAME, FMOD, T)
#define LIST_GENERATE_SOURCE_PUBLIC(PFX, SNAME, FMOD, T) \
    LIST_GENERATE_SOURCE(PFX, SNAME, FMOD, T)
/* STRUCT ********************************************************************/
#define LIST_GENERATE_STRUCT(PFX, SNAME, FMOD, T) \
                                                \
    struct SNAME##_s                              \
    {                                             \
        T *buffer;                                \
        size_t capacity;                          \
        size_t count;                             \
    };
/* HEADER ********************************************************************/
#define LIST_GENERATE_HEADER(PFX, SNAME, FMOD, T)                                    \
                                                                                    \
    typedef struct SNAME##_s SNAME;                                                  \
                                                                                    \
    FMOD SNAME *PFX##_new(size_t size);                                              \
    FMOD void PFX##_free(SNAME *list);                                               \
    FMOD bool PFX##_push_front(SNAME *list, T element);                              \
    FMOD bool PFX##_push(SNAME *list, T element, size_t index);                      \
    FMOD bool PFX##_push_back(SNAME *list, T element);                               \
    FMOD bool PFX##_pop_front(SNAME *list);                                          \
    FMOD bool PFX##_pop(SNAME *list, size_t index);                                  \
    FMOD bool PFX##_pop_back(SNAME *list);                                           \
    FMOD bool PFX##_insert_if(SNAME *list, T element, size_t index, bool condition); \
    FMOD bool PFX##_remove_if(SNAME *list, size_t index, bool condition);            \
    FMOD T PFX##_back(SNAME *list);                                                  \
    FMOD T PFX##_get(SNAME *list, size_t index);                                     \
    FMOD T PFX##_front(SNAME *list);                                                 \
    FMOD bool PFX##_empty(SNAME *list);                                              \
    FMOD bool PFX##_full(SNAME *list);                                               \
    FMOD size_t PFX##_count(SNAME *list);                                            \
    FMOD size_t PFX##_capacity(SNAME *list);
/* SOURCE ********************************************************************/
#define LIST_GENERATE_SOURCE(PFX, SNAME, FMOD, T)                                   \
                                                                                    \
    FMOD bool PFX##_grow(SNAME *list);                                              \
                                                                                    \
    FMOD SNAME *PFX##_new(size_t size)                                              \
    {                                                                               \
        if (size < 1)                                                               \
            return NULL;                                                            \
                                                                                    \
        SNAME *list = malloc(sizeof(SNAME));                                        \
                                                                                    \
        if (!list)                                                                  \
            return NULL;                                                            \
                                                                                    \
        list->buffer = malloc(sizeof(T) * size);                                    \
                                                                                    \
        if (!list->buffer)                                                          \
        {                                                                           \
            free(list);                                                             \
            return NULL;                                                            \
        }                                                                           \
                                                                                    \
        for (size_t i = 0; i < size; i++)                                           \
        {                                                                           \
            list->buffer[i] = 0;                                                    \
        }                                                                           \
                                                                                    \
        list->capacity = size;                                                      \
        list->count = 0;                                                            \
                                                                                    \
        return list;                                                                \
    }                                                                               \
                                                                                    \
    FMOD void PFX##_free(SNAME *list)                                               \
    {                                                                               \
        free(list->buffer);                                                         \
        free(list);                                                                 \
    }                                                                               \
                                                                                    \
    FMOD bool PFX##_push_front(SNAME *list, T element)                              \
    {                                                                               \
        if (PFX##_full(list))                                                       \
        {                                                                           \
            if (!PFX##_grow(list))                                                  \
                return false;                                                       \
        }                                                                           \
                                                                                    \
        if (!PFX##_empty(list))                                                     \
        {                                                                           \
            for (size_t i = list->count; i > 0; i--)                                \
            {                                                                       \
                list->buffer[i] = list->buffer[i - 1];                              \
            }                                                                       \
        }                                                                           \
                                                                                    \
        list->buffer[0] = element;                                                  \
                                                                                    \
        list->count++;                                                              \
                                                                                    \
        return true;                                                                \
    }                                                                               \
                                                                                    \
    FMOD bool PFX##_push(SNAME *list, T element, size_t index)                      \
    {                                                                               \
        if (index > list->count)                                                    \
            return false;                                                           \
                                                                                    \
        if (index == 0)                                                             \
        {                                                                           \
            return PFX##_push_front(list, element);                                 \
        }                                                                           \
        else if (index == list->count)                                              \
        {                                                                           \
            return PFX##_push_back(list, element);                                  \
        }                                                                           \
                                                                                    \
        if (PFX##_full(list))                                                       \
        {                                                                           \
            if (!PFX##_grow(list))                                                  \
                return false;                                                       \
        }                                                                           \
                                                                                    \
        for (size_t i = list->count; i > index; i--)                                \
        {                                                                           \
            list->buffer[i] = list->buffer[i - 1];                                  \
        }                                                                           \
                                                                                    \
        list->buffer[index] = element;                                              \
                                                                                    \
        list->count++;                                                              \
                                                                                    \
        return true;                                                                \
    }                                                                               \
                                                                                    \
    FMOD bool PFX##_push_back(SNAME *list, T element)                               \
    {                                                                               \
        if (PFX##_full(list))                                                       \
        {                                                                           \
            if (!PFX##_grow(list))                                                  \
                return false;                                                       \
        }                                                                           \
                                                                                    \
        list->buffer[list->count++] = element;                                      \
                                                                                    \
        return true;                                                                \
    }                                                                               \
                                                                                    \
    FMOD bool PFX##_pop_front(SNAME *list)                                          \
    {                                                                               \
        if (PFX##_empty(list))                                                      \
            return false;                                                           \
                                                                                    \
        for (size_t i = 0; i < list->count; i++)                                    \
        {                                                                           \
            list->buffer[i] = list->buffer[i + 1];                                  \
        }                                                                           \
                                                                                    \
        list->buffer[--list->count] = 0;                                            \
                                                                                    \
        return true;                                                                \
    }                                                                               \
                                                                                    \
    FMOD bool PFX##_pop(SNAME *list, size_t index)                                  \
    {                                                                               \
        if (PFX##_empty(list))                                                      \
            return false;                                                           \
                                                                                    \
        if (index == 0)                                                             \
        {                                                                           \
            return PFX##_pop_front(list);                                           \
        }                                                                           \
        else if (index == list->count - 1)                                          \
        {                                                                           \
            return PFX##_pop_back(list);                                            \
        }                                                                           \
                                                                                    \
        for (size_t i = index; i < list->count - 1; i++)                            \
        {                                                                           \
            list->buffer[i] = list->buffer[i + 1];                                  \
        }                                                                           \
                                                                                    \
        list->buffer[--list->count] = 0;                                            \
                                                                                    \
        return true;                                                                \
    }                                                                               \
                                                                                    \
    FMOD bool PFX##_pop_back(SNAME *list)                                           \
    {                                                                               \
        if (PFX##_empty(list))                                                      \
            return false;                                                           \
                                                                                    \
        list->buffer[--list->count] = 0;                                            \
                                                                                    \
        return true;                                                                \
    }                                                                               \
                                                                                    \
    FMOD bool PFX##_insert_if(SNAME *list, T element, size_t index, bool condition) \
    {                                                                               \
        if (condition)                                                              \
            return PFX##_push(list, element, index);                                \
                                                                                    \
        return false;                                                               \
    }                                                                               \
                                                                                    \
    FMOD bool PFX##_remove_if(SNAME *list, size_t index, bool condition)            \
    {                                                                               \
        if (condition)                                                              \
            return PFX##_pop(list, index);                                          \
                                                                                    \
        return false;                                                               \
    }                                                                               \
                                                                                    \
    FMOD T PFX##_front(SNAME *list)                                                 \
    {                                                                               \
        if (PFX##_empty(list))                                                      \
            return 0;                                                               \
                                                                                    \
        return list->buffer[0];                                                     \
    }                                                                               \
                                                                                    \
    FMOD T PFX##_get(SNAME *list, size_t index)                                     \
    {                                                                               \
        if (index >= list->count)                                                   \
            return 0;                                                               \
                                                                                    \
        if (PFX##_empty(list))                                                      \
            return 0;                                                               \
                                                                                    \
        return list->buffer[index];                                                 \
    }                                                                               \
                                                                                    \
    FMOD T PFX##_back(SNAME *list)                                                  \
    {                                                                               \
        if (PFX##_empty(list))                                                      \
            return 0;                                                               \
                                                                                    \
        return list->buffer[list->count - 1];                                       \
    }                                                                               \
                                                                                    \
    FMOD bool PFX##_empty(SNAME *list)                                              \
    {                                                                               \
        return list->count == 0;                                                    \
    }                                                                               \
                                                                                    \
    FMOD bool PFX##_full(SNAME *list)                                               \
    {                                                                               \
        return list->count >= list->capacity;                                       \
    }                                                                               \
                                                                                    \
    FMOD size_t PFX##_count(SNAME *list)                                            \
    {                                                                               \
        return list->count;                                                         \
    }                                                                               \
                                                                                    \
    FMOD size_t PFX##_capacity(SNAME *list)                                         \
    {                                                                               \
        return list->capacity;                                                      \
    }                                                                               \
                                                                                    \
    FMOD bool PFX##_grow(SNAME *list)                                               \
    {                                                                               \
        size_t new_capacity = list->capacity * 2;                                   \
                                                                                    \
        T *new_buffer = realloc(list->buffer, sizeof(T) * new_capacity);            \
                                                                                    \
        if (!new_buffer)                                                            \
            return false;                                                           \
                                                                                    \
        list->buffer = new_buffer;                                                  \
        list->capacity = new_capacity;                                              \
                                                                                    \
        return true;                                                                \
    }

/*****************************************************************************/
/********************************************************************* STACK */
/*****************************************************************************/

/* PRIVATE *******************************************************************/
#define STACK_GENERATE_HEADER_PRIVATE(PFX, SNAME, FMOD, T) \
    STACK_GENERATE_HEADER(PFX, SNAME, FMOD, T)
#define STACK_GENERATE_SOURCE_PRIVATE(PFX, SNAME, FMOD, T) \
    STACK_GENERATE_STRUCT(PFX, SNAME, FMOD, T)             \
    STACK_GENERATE_SOURCE(PFX, SNAME, FMOD, T)
/* PUBLIC ********************************************************************/
#define STACK_GENERATE_HEADER_PUBLIC(PFX, SNAME, FMOD, T) \
    STACK_GENERATE_STRUCT(PFX, SNAME, FMOD, T)            \
    STACK_GENERATE_HEADER(PFX, SNAME, FMOD, T)
#define STACK_GENERATE_SOURCE_PUBLIC(PFX, SNAME, FMOD, T) \
    STACK_GENERATE_SOURCE(PFX, SNAME, FMOD, T)
/* STRUCT ********************************************************************/
#define STACK_GENERATE_STRUCT(PFX, SNAME, FMOD, T) \
                                                \
    struct SNAME##_s                               \
    {                                              \
        T *buffer;                                 \
        size_t capacity;                           \
        size_t count;                              \
    };                                             \
                                                \
/* HEADER ********************************************************************/
#define STACK_GENERATE_HEADER(PFX, SNAME, FMOD, T)                    \
                                                                    \
    typedef struct SNAME##_s SNAME;                                   \
                                                                    \
    FMOD SNAME *PFX##_new(size_t size);                               \
    FMOD void PFX##_free(SNAME *stack);                               \
    FMOD bool PFX##_push(SNAME *stack, T element);                    \
    FMOD bool PFX##_pop(SNAME *stack);                                \
    FMOD T PFX##_top(SNAME *stack);                                   \
    FMOD bool PFX##_push_if(SNAME *stack, T element, bool condition); \
    FMOD bool PFX##_pop_if(SNAME *stack, bool condition);             \
    FMOD bool PFX##_empty(SNAME *stack);                              \
    FMOD bool PFX##_full(SNAME *stack);                               \
    FMOD size_t PFX##_count(SNAME *stack);                            \
    FMOD size_t PFX##_capacity(SNAME *stack);

/* SOURCE ********************************************************************/
#define STACK_GENERATE_SOURCE(PFX, SNAME, FMOD, T)                        \
                                                                        \
    FMOD bool PFX##_grow(SNAME *stack);                                   \
                                                                        \
    FMOD SNAME *PFX##_new(size_t size)                                    \
    {                                                                     \
        if (size < 1)                                                     \
            return NULL;                                                  \
                                                                        \
        SNAME *stack = malloc(sizeof(SNAME));                             \
                                                                        \
        if (!stack)                                                       \
            return NULL;                                                  \
                                                                        \
        stack->buffer = malloc(sizeof(T) * size);                         \
                                                                        \
        if (!stack->buffer)                                               \
        {                                                                 \
            free(stack);                                                  \
            return NULL;                                                  \
        }                                                                 \
                                                                        \
        for (size_t i = 0; i < size; i++)                                 \
        {                                                                 \
            stack->buffer[i] = 0;                                         \
        }                                                                 \
                                                                        \
        stack->capacity = size;                                           \
        stack->count = 0;                                                 \
                                                                        \
        return stack;                                                     \
    }                                                                     \
                                                                        \
    FMOD void PFX##_free(SNAME *stack)                                    \
    {                                                                     \
        free(stack->buffer);                                              \
        free(stack);                                                      \
    }                                                                     \
                                                                        \
    FMOD bool PFX##_push(SNAME *stack, T element)                         \
    {                                                                     \
        if (PFX##_full(stack))                                            \
        {                                                                 \
            if (!PFX##_grow(stack))                                       \
                return false;                                             \
        }                                                                 \
                                                                        \
        stack->buffer[stack->count++] = element;                          \
                                                                        \
        return true;                                                      \
    }                                                                     \
                                                                        \
    FMOD bool PFX##_pop(SNAME *stack)                                     \
    {                                                                     \
        if (PFX##_empty(stack))                                           \
            return false;                                                 \
                                                                        \
        stack->buffer[--stack->count] = 0;                                \
                                                                        \
        return true;                                                      \
    }                                                                     \
                                                                        \
    FMOD T PFX##_top(SNAME *stack)                                        \
    {                                                                     \
        if (PFX##_empty(stack))                                           \
            return 0;                                                     \
                                                                        \
        return stack->buffer[stack->count - 1];                           \
    }                                                                     \
                                                                        \
    FMOD bool PFX##_push_if(SNAME *stack, T element, bool condition)      \
    {                                                                     \
        if (condition)                                                    \
            return PFX##_push(stack, element);                            \
                                                                        \
        return false;                                                     \
    }                                                                     \
                                                                        \
    FMOD bool PFX##_pop_if(SNAME *stack, bool condition)                  \
    {                                                                     \
        if (condition)                                                    \
            return PFX##_pop(stack);                                      \
                                                                        \
        return false;                                                     \
    }                                                                     \
                                                                        \
    FMOD bool PFX##_empty(SNAME *stack)                                   \
    {                                                                     \
        return stack->count == 0;                                         \
    }                                                                     \
                                                                        \
    FMOD bool PFX##_full(SNAME *stack)                                    \
    {                                                                     \
        return stack->count >= stack->capacity;                           \
    }                                                                     \
                                                                        \
    FMOD size_t PFX##_count(SNAME *stack)                                 \
    {                                                                     \
        return stack->count;                                              \
    }                                                                     \
                                                                        \
    FMOD size_t PFX##_capacity(SNAME *stack)                              \
    {                                                                     \
        return stack->capacity;                                           \
    }                                                                     \
                                                                        \
    FMOD bool PFX##_grow(SNAME *stack)                                    \
    {                                                                     \
        size_t new_capacity = stack->capacity * 2;                        \
                                                                        \
        T *new_buffer = realloc(stack->buffer, sizeof(T) * new_capacity); \
                                                                        \
        if (!new_buffer)                                                  \
            return false;                                                 \
                                                                        \
        stack->buffer = new_buffer;                                       \
        stack->capacity = new_capacity;                                   \
                                                                        \
        return true;                                                      \
    }

/*****************************************************************************/
/********************************************************************* QUEUE */
/*****************************************************************************/

/* PRIVATE *******************************************************************/
#define QUEUE_GENERATE_HEADER_PRIVATE(PFX, SNAME, FMOD, T) \
    QUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, T)
#define QUEUE_GENERATE_SOURCE_PRIVATE(PFX, SNAME, FMOD, T) \
    QUEUE_GENERATE_STRUCT(PFX, SNAME, FMOD, T)             \
    QUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, T)
/* PUBLIC ********************************************************************/
#define QUEUE_GENERATE_HEADER_PUBLIC(PFX, SNAME, FMOD, T) \
    QUEUE_GENERATE_STRUCT(PFX, SNAME, FMOD, T)            \
    QUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, T)
#define QUEUE_GENERATE_SOURCE_PUBLIC(PFX, SNAME, FMOD, T) \
    QUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, T)
/* STRUCT ********************************************************************/
#define QUEUE_GENERATE_STRUCT(PFX, SNAME, FMOD, T) \
                                                \
    struct SNAME##_s                               \
    {                                              \
        T *buffer;                                 \
        size_t capacity;                           \
        size_t count;                              \
        size_t front;                              \
        size_t rear;                               \
    };
/* HEADER ********************************************************************/
#define QUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, T)                       \
                                                                        \
    typedef struct SNAME##_s SNAME;                                      \
                                                                        \
    FMOD SNAME *PFX##_new(size_t size);                                  \
    FMOD void PFX##_free(SNAME *queue);                                  \
    FMOD bool PFX##_enqueue(SNAME *queue, T element);                    \
    FMOD bool PFX##_dequeue(SNAME *queue);                               \
    FMOD T PFX##_peek(SNAME *queue);                                     \
    FMOD bool PFX##_enqueue_if(SNAME *queue, T element, bool condition); \
    FMOD bool PFX##_dequeue_if(SNAME *queue, bool condition);            \
    FMOD bool PFX##_empty(SNAME *queue);                                 \
    FMOD bool PFX##_full(SNAME *queue);                                  \
    FMOD size_t PFX##_count(SNAME *queue);                               \
    FMOD size_t PFX##_capacity(SNAME *queue);
/* SOURCE ********************************************************************/
#define QUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, T)                                                 \
                                                                                                \
    FMOD bool PFX##_grow(SNAME *queue);                                                            \
                                                                                                \
    FMOD SNAME *PFX##_new(size_t size)                                                             \
    {                                                                                              \
        if (size < 1)                                                                              \
            return NULL;                                                                           \
                                                                                                \
        SNAME *queue = malloc(sizeof(SNAME));                                                      \
                                                                                                \
        if (!queue)                                                                                \
            return NULL;                                                                           \
                                                                                                \
        queue->buffer = malloc(sizeof(T) * size);                                                  \
                                                                                                \
        if (!queue->buffer)                                                                        \
        {                                                                                          \
            free(queue);                                                                           \
            return NULL;                                                                           \
        }                                                                                          \
                                                                                                \
        for (size_t i = 0; i < size; i++)                                                          \
        {                                                                                          \
            queue->buffer[i] = 0;                                                                  \
        }                                                                                          \
                                                                                                \
        queue->capacity = size;                                                                    \
        queue->count = 0;                                                                          \
        queue->front = 0;                                                                          \
        queue->rear = 0;                                                                           \
                                                                                                \
        return queue;                                                                              \
    }                                                                                              \
                                                                                                \
    FMOD void PFX##_free(SNAME *queue)                                                             \
    {                                                                                              \
        free(queue->buffer);                                                                       \
        free(queue);                                                                               \
    }                                                                                              \
                                                                                                \
    FMOD bool PFX##_enqueue(SNAME *queue, T element)                                               \
    {                                                                                              \
        if (PFX##_full(queue))                                                                     \
        {                                                                                          \
            if (!PFX##_grow(queue))                                                                \
                return false;                                                                      \
        }                                                                                          \
                                                                                                \
        queue->buffer[queue->rear] = element;                                                      \
                                                                                                \
        queue->rear = (queue->rear == queue->capacity - 1) ? 0 : queue->rear + 1;                  \
        queue->count++;                                                                            \
                                                                                                \
        return true;                                                                               \
    }                                                                                              \
                                                                                                \
    FMOD bool PFX##_dequeue(SNAME *queue)                                                          \
    {                                                                                              \
        if (PFX##_empty(queue))                                                                    \
            return false;                                                                          \
                                                                                                \
        queue->buffer[queue->front] = 0;                                                           \
                                                                                                \
        queue->front = (queue->front == queue->capacity - 1) ? 0 : queue->front + 1;               \
        queue->count--;                                                                            \
                                                                                                \
        return true;                                                                               \
    }                                                                                              \
                                                                                                \
    FMOD T PFX##_peek(SNAME *queue)                                                                \
    {                                                                                              \
        if (PFX##_empty(queue))                                                                    \
            return 0;                                                                              \
                                                                                                \
        return queue->buffer[queue->front];                                                        \
    }                                                                                              \
                                                                                                \
    FMOD bool PFX##_enqueue_if(SNAME *queue, T element, bool condition)                            \
    {                                                                                              \
        if (condition)                                                                             \
            return PFX##_enqueue(queue, element);                                                  \
                                                                                                \
        return false;                                                                              \
    }                                                                                              \
                                                                                                \
    FMOD bool PFX##_dequeue_if(SNAME *queue, bool condition)                                       \
    {                                                                                              \
        if (condition)                                                                             \
            return PFX##_dequeue(queue);                                                           \
                                                                                                \
        return false;                                                                              \
    }                                                                                              \
                                                                                                \
    FMOD bool PFX##_empty(SNAME *queue)                                                            \
    {                                                                                              \
        return queue->count == 0;                                                                  \
    }                                                                                              \
                                                                                                \
    FMOD bool PFX##_full(SNAME *queue)                                                             \
    {                                                                                              \
        return queue->count >= queue->capacity;                                                    \
    }                                                                                              \
                                                                                                \
    FMOD size_t PFX##_count(SNAME *queue)                                                          \
    {                                                                                              \
        return queue->count;                                                                       \
    }                                                                                              \
                                                                                                \
    FMOD size_t PFX##_capacity(SNAME *queue)                                                       \
    {                                                                                              \
        return queue->capacity;                                                                    \
    }                                                                                              \
                                                                                                \
    FMOD bool PFX##_grow(SNAME *queue)                                                             \
    {                                                                                              \
                                                                                                \
        size_t new_capacity = queue->capacity * 2;                                                 \
                                                                                                \
        T *new_buffer = malloc(sizeof(T) * new_capacity);                                          \
                                                                                                \
        if (!new_buffer)                                                                           \
            return false;                                                                          \
                                                                                                \
        for (size_t i = queue->front, j = 0; j < queue->count; i = (i + 1) % queue->capacity, j++) \
        {                                                                                          \
            new_buffer[j] = queue->buffer[i];                                                      \
        }                                                                                          \
                                                                                                \
        free(queue->buffer);                                                                       \
                                                                                                \
        queue->buffer = new_buffer;                                                                \
        queue->capacity = new_capacity;                                                            \
        queue->front = 0;                                                                          \
        queue->rear = queue->count;                                                                \
                                                                                                \
        return true;                                                                               \
    }

#endif /* MACRO_CONTAINERS */

Here are some examples:

  • I want a list of type double, and I want to use it only in this file
    • In source file: MACRO_GENERATE(LIST, PUBLIC, dl, dlist, static, double)
    • Note that PUBLIC or PRIVATE makes no difference, but you must specify one or the other
    • dlist *list = dl_new(100);
  • I want a queue called queue_line of type person_t with hidden struct fields
    • In source file: MACRO_GENERATE_SOURCE(QUEUE, PRIVATE, q, queue_line, , person_t)
    • In header file: MACRO_GENERATE_HEADER(QUEUE, PRIVATE, q, queue_line, , person_t)
    • Note here that you can (and should) omit static without a problem
    • queue_line *queue = q_new(120);
    • queue->count; // Error
    • size_t total_elements = q_count(queue); // OK
  • I want a stack of type const char * and I want access to its fields
    • In source file: MACRO_GENERATE_SOURCE(STACK, PUBLIC, stk, my_stack, , const char *)
    • In header file: MACRO_GENERATE_HEADER(STACK, PUBLIC, stk, my_stack, , const char *)
    • my_stack *stack = stk_new(80);
    • for (size_t i = 0; i < stack->count; i++) ... // OK
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.