Created
September 2, 2019 08:10
-
-
Save basp1/0851a5ebea97cbf090ac1b1135412509 to your computer and use it in GitHub Desktop.
array
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "array.h" | |
#include <assert.h> | |
#include <memory.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#define HEADER(P) ((array_header_t*)((char*)P - sizeof(array_header_t))) | |
void* array_new(int length, int value_size) | |
{ | |
array_header_t* header = (array_header_t*)malloc(sizeof(array_header_t) + value_size * length); | |
if (NULL == header) | |
{ | |
return NULL; | |
} | |
header->length = length; | |
header->capacity = length; | |
header->value_size = value_size; | |
return header->values; | |
} | |
char* array_new_string(const char* str) | |
{ | |
char* array = array_new(0, sizeof(char)); | |
while (*str) | |
{ | |
array_push(&array, str++); | |
} | |
return array; | |
} | |
void array_delete(void* array) | |
{ | |
if (NULL == array) | |
{ | |
return; | |
} | |
array_header_t* header = HEADER(array); | |
header->capacity = 0; | |
header->length = 0; | |
free(header); | |
} | |
void array_clear(void* array) | |
{ | |
assert(NULL != array); | |
HEADER(array)->length = 0; | |
} | |
void array_setcap(void** array, int cap) | |
{ | |
assert(NULL != array); | |
array_header_t* header = HEADER(*array); | |
assert(cap >= header->capacity); | |
if (cap == header->capacity) | |
{ | |
return; | |
} | |
header = xrealloc(header, sizeof(array_header_t) + header->value_size * cap); | |
header->capacity = cap; | |
*array = header->values; | |
} | |
int array_cap(void* array) | |
{ | |
assert(NULL != array); | |
return HEADER(array)->capacity; | |
} | |
int array_len(void* array) | |
{ | |
assert(NULL != array); | |
return HEADER(array)->length; | |
} | |
void array_init(void* array, void* value) | |
{ | |
assert(NULL != array); | |
int len = HEADER(array)->length; | |
for (int i = 0; i < len; i++) | |
{ | |
array_set(array, i, value); | |
} | |
} | |
void* array_get(void* array, int index) | |
{ | |
assert(NULL != array); | |
return (char*)array + (HEADER(array)->value_size * index); | |
} | |
void array_set(void* array, int index, void* value) | |
{ | |
assert(NULL != array); | |
array_header_t* header = HEADER(array); | |
assert(index < header->length); | |
memcpy((char*)array + header->value_size * index, value, header->value_size); | |
} | |
void array_push(void** array, void* value) | |
{ | |
assert(NULL != array); | |
array_header_t* header = HEADER(*array); | |
if (header->length == header->capacity) | |
{ | |
int newcap; | |
if (0 == header->capacity) | |
{ | |
newcap = 1; | |
} | |
else | |
{ | |
newcap = 2 * header->capacity; | |
} | |
array_setcap(array, newcap); | |
} | |
header = HEADER(*array); | |
header->length += 1; | |
array_set(*array, header->length - 1, value); | |
} | |
bool array_pop(void* array, void* p) | |
{ | |
assert(NULL != array); | |
assert(NULL != p); | |
array_header_t* header = HEADER(array); | |
if (0 == header->length) | |
{ | |
return false; | |
} | |
void* last = array_get(array, header->length - 1); | |
memcpy(p, last, header->value_size); | |
header->length -= 1; | |
return true; | |
} | |
void* array_first(void* array) | |
{ | |
assert(NULL != array); | |
assert(array_len(array) > 0); | |
return array_get(array, 0); | |
} | |
void* array_last(void* array) | |
{ | |
assert(NULL != array); | |
assert(array_len(array) > 0); | |
return array_get(array, array_len(array) - 1); | |
} | |
void array_remove(void* array, int index) | |
{ | |
assert(NULL != array); | |
array_header_t* header = HEADER(array); | |
assert(index < header->length); | |
if (index < (header->length - 1)) | |
{ | |
memmove | |
( | |
(char*)array + header->value_size * index, | |
(char*)array + header->value_size * (index + 1), | |
header->value_size * (header->length - index - 1) | |
); | |
} | |
header->length -= 1; | |
} | |
void* array_copy(void* array) | |
{ | |
assert(NULL != array); | |
array_header_t* header = HEADER(array); | |
void* copy = array_new(header->length, header->value_size); | |
memcpy(copy, array, header->value_size * header->length); | |
return copy; | |
} | |
bool array_contains(void* array, void* value) | |
{ | |
assert(NULL != array); | |
array_header_t* header = HEADER(array); | |
for (int i = 0; i < header->length; i++) | |
{ | |
if (!memcmp(value, (char*)array + header->value_size * i, header->value_size)) | |
{ | |
return true; | |
} | |
} | |
return false; | |
} | |
bool array_equals(void* array1, void* array2) | |
{ | |
assert(NULL != array1); | |
assert(NULL != array2); | |
array_header_t* header1 = HEADER(array1); | |
array_header_t* header2 = HEADER(array2); | |
if (header1->length != header2->length) | |
{ | |
return false; | |
} | |
if (header1->value_size != header2->value_size) | |
{ | |
return false; | |
} | |
return !memcmp(array1, array2, header1->value_size * header1->length); | |
} | |
#undef HEADER |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <stdbool.h> | |
#ifdef __cplusplus | |
extern "C" { | |
#endif | |
typedef struct array_header_t { | |
int capacity; | |
int length; | |
int value_size; | |
char values[0]; | |
} array_header_t; | |
void* array_new(int length, int value_size); | |
char* array_new_string(const char*); | |
void array_delete(void* array); | |
void array_clear(void* array); | |
void array_setcap(void** array, int); | |
int array_cap(void* array); | |
int array_len(void* array); | |
void array_init(void* array, void*); | |
void* array_get(void* array, int); | |
void array_set(void* array, int, void*); | |
void array_push(void** array, void*); | |
bool array_pop(void* array, void* p); | |
void* array_first(void* array); | |
void* array_last(void* array); | |
void array_remove(void* array, int); | |
void* array_copy(void* array); | |
bool array_contains(void* array, void*); | |
bool array_equals(void*, void*); | |
#ifdef __cplusplus | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment