mirror of
https://github.com/utkumaden/libmx.git
synced 2025-01-23 05:56:33 +01:00
Add a list.
This commit is contained in:
parent
9fed914164
commit
f92288a8a8
97
include/mx/list.h
Normal file
97
include/mx/list.h
Normal file
@ -0,0 +1,97 @@
|
||||
/**
|
||||
* @file list.h Array List
|
||||
* This is an array list implementation inspired by the stb data structures
|
||||
* single header library. The list itself works like any C pointer, except
|
||||
* the real base pointer is before the pointer you will see.
|
||||
*/
|
||||
#ifndef _MX_LIST_H_
|
||||
#define _MX_LIST_H_
|
||||
|
||||
#include "mx/base.h"
|
||||
#include "mx/assert.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct mx_list_self_t {
|
||||
int count;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Internal function for retreiving the list header.
|
||||
* @param list The list.
|
||||
* @returns The list header.
|
||||
*/
|
||||
#define mx_list_self(list) (((struct mx_list_self_t*)(list))-1)
|
||||
|
||||
/**
|
||||
* @brief The number of items in the list.
|
||||
* @param list The list.
|
||||
* @returns The number of items in the list.
|
||||
*/
|
||||
#define mx_list_count(list) (((list) == NULL) ? 0 : mx_list_self(list)->count)
|
||||
|
||||
#define mx_list_resize(list, count) do { \
|
||||
struct mx_list_self_t *self = (list == NULL) ? NULL : mx_list_self(list); \
|
||||
self = realloc(self, sizeof(*self) + sizeof(*(list)) * (count)); \
|
||||
if (self != NULL) { \
|
||||
self->count = (count); \
|
||||
(list) = (void*)(self+1); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @brief Insert an item into the list (with assignment)
|
||||
* @param list The list.
|
||||
* @param index The index to insert the item into.
|
||||
* @param item The item to insert.
|
||||
* @remarks This overload is for things that can be assigned, like base types. Useful for rvalues.
|
||||
*/
|
||||
#define mx_list_insert(list, index, item) do { \
|
||||
int idx = (index); \
|
||||
if (list == NULL) { \
|
||||
MX_ASSERT(idx == 0, "mx_list_insert() can only insert at 0 for an empty list."); \
|
||||
mx_list_resize(list, 1); \
|
||||
list[0] = item; \
|
||||
} else { \
|
||||
int count = mx_list_count(list) \
|
||||
MX_ASSERT(idx > 0 && idx <= count, "mx_list_insert() expected a range between 0 and mx_list_count()."); \
|
||||
mx_list_resize(list, count + 1); \
|
||||
memmove(&list[idx]+1, &list[idx], (count - idx) * sizeof(*list)); \
|
||||
list[idx] = item; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* @brief Insert an item into the list (with copy)
|
||||
* @param list The list.
|
||||
* @param index The index to insert the item into.
|
||||
* @param item The item to insert.
|
||||
* @remarks This overload is for things that can be copied, like structs. Item must be an addressable lvalue.
|
||||
*/
|
||||
#define mx_list_insert_copy(list, index, item) do { \
|
||||
int idx = (index); \
|
||||
if (list == NULL) { \
|
||||
MX_ASSERT(idx == 0, "mx_list_insert() can only insert at 0 for an empty list."); \
|
||||
mx_list_resize(list, 1); \
|
||||
memcpy(&list[0], &item, sizeof(*item)); \
|
||||
} else { \
|
||||
int count = mx_list_count(list) \
|
||||
MX_ASSERT(idx > 0 && idx <= count, "mx_list_insert() expected a range between 0 and mx_list_count()."); \
|
||||
mx_list_resize(list, count + 1); \
|
||||
memmove(&list[idx]+1, &list[idx], (count - idx) * sizeof(*list)); \
|
||||
memcpy(&list[idx], &item, sizeof(*item)); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* @brief Free the list, completely destroying any associated memory.
|
||||
* @param list The list to free.
|
||||
*/
|
||||
#define mx_list_free(list) do { \
|
||||
if (list != NULL) { \
|
||||
free(mx_list_self(list)); \
|
||||
list = NULL; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user