Skip to content

Instantly share code, notes, and snippets.

@Airbus5717
Last active June 3, 2023 13:55
Show Gist options
  • Save Airbus5717/ef44df6c4859aee24e1ed9b545d6f880 to your computer and use it in GitHub Desktop.
Save Airbus5717/ef44df6c4859aee24e1ed9b545d6f880 to your computer and use it in GitHub Desktop.
custom Vector impl (depends on libc only)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <limits.h>
typedef size_t usize;
typedef uint8_t u8;
#define RESET "\x1b[0m"
#define LRED "\x1b[91m"
void log_error(const char *str)
{
fprintf(stderr, "[%sERROR%s]: %s\n", LRED, RESET, str);
}
void exit_error(const char *str)
{
log_error(str);
exit(1);
}
#define ASSERT(expr, msg) \
if (!(expr)) \
{ \
fprintf(stderr, "%sAssert failure: %s\n@file: %s:%d%s\n", LRED, msg, __FILE__, __LINE__, \
RESET); \
exit(1); \
}
#define ASSERT_NULL(expr, msg) \
if ((expr) == NULL) \
{ \
fprintf(stderr, "%sAssert failure: %s\n@file: %s:%d%s\n", LRED, msg, __FILE__, __LINE__, \
RESET); \
exit(1); \
}
// C MACROS
// General sequence macros
#define seq_elem_type(seq) typeof(*(seq)->elements)
#define seq_start(seq) ((seq)->elements)
#define seq_end(seq) ((seq)->elements + (seq)->count)
#define seq_len(seq) ((seq)->count)
#define make_slice(T, start, count) ((slice(T)){start, count})
#define arr_slice(arr, low, high) \
{ \
(high) - (low), arr_start(arr) + (low) \
}
#define for_each(seq, iter) \
for (seq_elem_type(seq) *iter = seq_start(seq); iter < seq_end(seq); iter++)
// Slice type
#define slice(T) slice_##T
#define decl_slice(T) \
typedef struct \
{ \
size_t count; \
T *elements; \
} slice(T)
// arraylist type
#define ARRAY_GROWTH_FACTOR 2
#define arr(T) arraylist_##T
#define decl_arr(T) \
typedef struct T \
{ \
usize count; \
usize capacity; \
T elements[]; \
} * arr(T); \
decl_slice(T)
// arraylist implementation
#define arr_total_size(arr) \
(sizeof(_arraylist_header) + (arr)->capacity * sizeof(seq_elem_type(arr)))
typedef struct
{
usize count;
usize capacity;
} _arraylist_header;
static inline _arraylist_header *
_new_arr(_arraylist_header *header, usize initial_size)
{
header->count = 0;
header->capacity = initial_size;
return header;
}
#define make_arr(T, size) \
((arr(T))_new_arr(malloc(sizeof(_arraylist_header) + size * sizeof(T)), size))
#define arr_free(arr) free(arr)
#define arr_push(arr, ...) \
do \
{ \
if ((arr)->count + 1 > (arr)->capacity) \
{ \
(arr)->capacity <<= 1; \
(arr) = realloc(arr, arr_total_size(arr)); \
} \
(arr)->elements[(arr)->count++] = __VA_ARGS__; \
} while (0);
#define arr_start(arr) seq_start(arr)
#define arr_end(arr) seq_end(arr)
// WARN: no bounds checking
#define arr_at(arr, idx) (arr)->elements[(idx)]
#define arr_len(arr) seq_len(arr)
#define arr_foreach(arr, el) for_each(arr, el)
// C++ Version (not tested)
template <typename T>
class Vector
{
T *arr;
usize index = 0;
usize capacity = 0;
public:
// TODO: growth rate optimizer
static const usize growth_rate = 2;
Vector() : arr((T *)calloc(sizeof(T), 10)), index(0), capacity(10)
{
ASSERT_NULL(arr, "Vector init failure");
}
~Vector()
{
if (capacity > 0 && arr) free((void *)arr);
capacity = 0;
}
// void check()
// {
// if (!arr) log_error("Vector is null");
// if (index > capacity) log_error("out of bounds");
// }
usize size()
{
return index;
}
u8 push_back(T elem)
{
/*
* 9223372036854775807LL == (ULONG_LONG_MAX / 2) - 1;
*/
ASSERT(capacity < 9223372036854775807LL, "too large vector");
if (index + 1 == capacity)
{
arr = (T *)realloc(arr, growth_rate * capacity * sizeof(T));
if (arr == NULL) return EXIT_FAILURE;
capacity *= growth_rate;
}
arr[index++] = elem;
return EXIT_SUCCESS;
}
T operator[](usize i)
{
return arr[i];
}
T *getElements()
{
return arr;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment