Simple generic macro-generated containers
$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:
CONTAINER_GENERATE(C, P, PFX, SNAME, FMOD, T) ....CONTAINER_GENERATE_SOURCE(C, P, PFX, SNAME, FMOD, T) ....CONTAINER_GENERATE_HEADER(C, P, PFX, SNAME, FMOD, T) ....
Where:
C - The container you want;
- Currently available are
LIST,STACKandQUEUE;
- Currently available are
P - If you want your data structure's fields visible;
PRIVATEorPUBLIC. Hides the structure definition in the source file;- Only makes a difference in the macros
2and3;
PFX - Functions prefix, or namespace;
SNAME - Structure name (typedef SNAME##_s SNAME;);
FMOD - Functions modifier;
- Currently I've been using
staticwith macro1;
- Currently I've been using
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
PUBLICorPRIVATEmakes no difference, but you must specify one or the other dlist *list = dl_new(100);
- In source file:
- I want a queue called
queue_lineof typeperson_twith 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
staticwithout a problem queue_line *queue = q_new(120);queue->count; // Errorsize_t total_elements = q_count(queue); // OK
- In source file:
- 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
- In source file:
c collections macros
$endgroup$
add a comment |
$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:
CONTAINER_GENERATE(C, P, PFX, SNAME, FMOD, T) ....CONTAINER_GENERATE_SOURCE(C, P, PFX, SNAME, FMOD, T) ....CONTAINER_GENERATE_HEADER(C, P, PFX, SNAME, FMOD, T) ....
Where:
C - The container you want;
- Currently available are
LIST,STACKandQUEUE;
- Currently available are
P - If you want your data structure's fields visible;
PRIVATEorPUBLIC. Hides the structure definition in the source file;- Only makes a difference in the macros
2and3;
PFX - Functions prefix, or namespace;
SNAME - Structure name (typedef SNAME##_s SNAME;);
FMOD - Functions modifier;
- Currently I've been using
staticwith macro1;
- Currently I've been using
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
PUBLICorPRIVATEmakes no difference, but you must specify one or the other dlist *list = dl_new(100);
- In source file:
- I want a queue called
queue_lineof typeperson_twith 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
staticwithout a problem queue_line *queue = q_new(120);queue->count; // Errorsize_t total_elements = q_count(queue); // OK
- In source file:
- 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
- In source file:
c collections macros
$endgroup$
add a comment |
$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:
CONTAINER_GENERATE(C, P, PFX, SNAME, FMOD, T) ....CONTAINER_GENERATE_SOURCE(C, P, PFX, SNAME, FMOD, T) ....CONTAINER_GENERATE_HEADER(C, P, PFX, SNAME, FMOD, T) ....
Where:
C - The container you want;
- Currently available are
LIST,STACKandQUEUE;
- Currently available are
P - If you want your data structure's fields visible;
PRIVATEorPUBLIC. Hides the structure definition in the source file;- Only makes a difference in the macros
2and3;
PFX - Functions prefix, or namespace;
SNAME - Structure name (typedef SNAME##_s SNAME;);
FMOD - Functions modifier;
- Currently I've been using
staticwith macro1;
- Currently I've been using
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
PUBLICorPRIVATEmakes no difference, but you must specify one or the other dlist *list = dl_new(100);
- In source file:
- I want a queue called
queue_lineof typeperson_twith 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
staticwithout a problem queue_line *queue = q_new(120);queue->count; // Errorsize_t total_elements = q_count(queue); // OK
- In source file:
- 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
- In source file:
c collections macros
$endgroup$
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:
CONTAINER_GENERATE(C, P, PFX, SNAME, FMOD, T) ....CONTAINER_GENERATE_SOURCE(C, P, PFX, SNAME, FMOD, T) ....CONTAINER_GENERATE_HEADER(C, P, PFX, SNAME, FMOD, T) ....
Where:
C - The container you want;
- Currently available are
LIST,STACKandQUEUE;
- Currently available are
P - If you want your data structure's fields visible;
PRIVATEorPUBLIC. Hides the structure definition in the source file;- Only makes a difference in the macros
2and3;
PFX - Functions prefix, or namespace;
SNAME - Structure name (typedef SNAME##_s SNAME;);
FMOD - Functions modifier;
- Currently I've been using
staticwith macro1;
- Currently I've been using
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
PUBLICorPRIVATEmakes no difference, but you must specify one or the other dlist *list = dl_new(100);
- In source file:
- I want a queue called
queue_lineof typeperson_twith 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
staticwithout a problem queue_line *queue = q_new(120);queue->count; // Errorsize_t total_elements = q_count(queue); // OK
- In source file:
- 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
- In source file:
c collections macros
c collections macros
asked 9 mins ago
LeoVenLeoVen
62
62
add a comment |
add a comment |
0
active
oldest
votes
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f213553%2fsimple-generic-macro-generated-containers%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
0
active
oldest
votes
0
active
oldest
votes
active
oldest
votes
active
oldest
votes
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f213553%2fsimple-generic-macro-generated-containers%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown