Refactor array (#71)

The array container is now 3% faster.
This commit is contained in:
Bailey Thompson
2020-08-08 19:05:44 -04:00
committed by GitHub
parent 48b0751b6c
commit fdde32d981
4 changed files with 54 additions and 60 deletions

View File

@@ -303,19 +303,19 @@ unordered_multimap unordered_multimap_destroy(unordered_multimap me);
/** /**
* The array data structure, which is a static contiguous array. * The array data structure, which is a static contiguous array.
*/ */
typedef struct internal_array *array; typedef char *array;
/* Starting */ /* Starting */
array array_init(int element_count, size_t data_size); array array_init(size_t element_count, size_t data_size);
/* Utility */ /* Utility */
int array_size(array me); size_t array_size(array me);
void array_copy_to_array(void *arr, array me); void array_copy_to_array(void *arr, array me);
void *array_get_data(array me); void *array_get_data(array me);
/* Accessing */ /* Accessing */
int array_set(array me, int index, void *data); int array_set(array me, size_t index, void *data);
int array_get(void *data, array me, int index); int array_get(void *data, array me, size_t index);
/* Ending */ /* Ending */
array array_destroy(array me); array array_destroy(array me);

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017-2019 Bailey Thompson * Copyright (c) 2017-2020 Bailey Thompson
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@@ -24,14 +24,14 @@
#include <errno.h> #include <errno.h>
#include "include/array.h" #include "include/array.h"
struct internal_array { const size_t book_keeping_size = sizeof(size_t);
size_t bytes_per_item; const size_t arr_size_offset = 0;
int item_count; const size_t data_size_offset = sizeof(size_t);
void *data; const size_t data_ptr_offset = 2 * sizeof(size_t);
};
/** /**
* Initializes an array. * Initializes an array. If the multiplication of the element count and the
* data size overflows, it is undefined behavior.
* *
* @param element_count the number of elements in the array; must not be * @param element_count the number of elements in the array; must not be
* negative * negative
@@ -41,27 +41,19 @@ struct internal_array {
* initialized due to either invalid input arguments or memory * initialized due to either invalid input arguments or memory
* allocation error * allocation error
*/ */
array array_init(const int element_count, const size_t data_size) array array_init(const size_t element_count, const size_t data_size)
{ {
struct internal_array *init; char *init;
if (element_count < 0 || data_size == 0) { if (data_size == 0) {
return NULL; return NULL;
} }
init = malloc(sizeof(struct internal_array)); init = malloc(data_ptr_offset + element_count * data_size);
if (!init) { if (!init) {
return NULL; return NULL;
} }
init->bytes_per_item = data_size; memcpy(init + arr_size_offset, &element_count, book_keeping_size);
init->item_count = element_count; memcpy(init + data_size_offset, &data_size, book_keeping_size);
if (init->item_count == 0) { memset(init + data_ptr_offset, 0, element_count * data_size);
init->data = NULL;
return init;
}
init->data = calloc((size_t) element_count, data_size);
if (!init->data) {
free(init);
return NULL;
}
return init; return init;
} }
@@ -72,9 +64,11 @@ array array_init(const int element_count, const size_t data_size)
* *
* @return the size of the array * @return the size of the array
*/ */
int array_size(array me) size_t array_size(array me)
{ {
return me->item_count; size_t size;
memcpy(&size, me + arr_size_offset, book_keeping_size);
return size;
} }
/** /**
@@ -90,10 +84,11 @@ int array_size(array me)
*/ */
void array_copy_to_array(void *const arr, array me) void array_copy_to_array(void *const arr, array me)
{ {
if (me->item_count == 0) { size_t element_count;
return; size_t data_size;
} memcpy(&element_count, me + arr_size_offset, book_keeping_size);
memcpy(arr, me->data, me->item_count * me->bytes_per_item); memcpy(&data_size, me + data_size_offset, book_keeping_size);
memcpy(arr, me + data_ptr_offset, element_count * data_size);
} }
/** /**
@@ -113,15 +108,12 @@ void array_copy_to_array(void *const arr, array me)
*/ */
void *array_get_data(array me) void *array_get_data(array me)
{ {
return me->data; size_t element_count;
} memcpy(&element_count, me + arr_size_offset, book_keeping_size);
if (element_count == 0) {
/* return NULL;
* Determines if the input is illegal. }
*/ return me + data_ptr_offset;
static int array_is_illegal_input(array me, const int index)
{
return index < 0 || index >= me->item_count;
} }
/** /**
@@ -138,13 +130,16 @@ static int array_is_illegal_input(array me, const int index)
* @return 0 if no error * @return 0 if no error
* @return -EINVAL if invalid argument * @return -EINVAL if invalid argument
*/ */
int array_set(array me, const int index, void *const data) int array_set(array me, const size_t index, void *const data)
{ {
if (array_is_illegal_input(me, index)) { size_t element_count;
size_t data_size;
memcpy(&element_count, me + arr_size_offset, book_keeping_size);
if (index >= element_count) {
return -EINVAL; return -EINVAL;
} }
memcpy((char *) me->data + index * me->bytes_per_item, data, memcpy(&data_size, me + data_size_offset, book_keeping_size);
me->bytes_per_item); memcpy(me + data_ptr_offset + index * data_size, data, data_size);
return 0; return 0;
} }
@@ -163,13 +158,16 @@ int array_set(array me, const int index, void *const data)
* @return 0 if no error * @return 0 if no error
* @return -EINVAL if invalid argument * @return -EINVAL if invalid argument
*/ */
int array_get(void *const data, array me, const int index) int array_get(void *const data, array me, const size_t index)
{ {
if (array_is_illegal_input(me, index)) { size_t element_count;
size_t data_size;
memcpy(&element_count, me + arr_size_offset, book_keeping_size);
if (index >= element_count) {
return -EINVAL; return -EINVAL;
} }
memcpy(data, (char *) me->data + index * me->bytes_per_item, memcpy(&data_size, me + data_size_offset, book_keeping_size);
me->bytes_per_item); memcpy(data, me + data_ptr_offset + index * data_size, data_size);
return 0; return 0;
} }
@@ -183,7 +181,6 @@ int array_get(void *const data, array me, const int index)
*/ */
array array_destroy(array me) array array_destroy(array me)
{ {
free(me->data);
free(me); free(me);
return NULL; return NULL;
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017-2019 Bailey Thompson * Copyright (c) 2017-2020 Bailey Thompson
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@@ -28,19 +28,19 @@
/** /**
* The array data structure, which is a static contiguous array. * The array data structure, which is a static contiguous array.
*/ */
typedef struct internal_array *array; typedef char *array;
/* Starting */ /* Starting */
array array_init(int element_count, size_t data_size); array array_init(size_t element_count, size_t data_size);
/* Utility */ /* Utility */
int array_size(array me); size_t array_size(array me);
void array_copy_to_array(void *arr, array me); void array_copy_to_array(void *arr, array me);
void *array_get_data(array me); void *array_get_data(array me);
/* Accessing */ /* Accessing */
int array_set(array me, int index, void *data); int array_set(array me, size_t index, void *data);
int array_get(void *data, array me, int index); int array_get(void *data, array me, size_t index);
/* Ending */ /* Ending */
array array_destroy(array me); array array_destroy(array me);

View File

@@ -3,7 +3,6 @@
static void test_invalid_init(void) static void test_invalid_init(void)
{ {
assert(!array_init(-1, sizeof(int)));
assert(!array_init(1, 0)); assert(!array_init(1, 0));
} }
@@ -83,8 +82,6 @@ static void test_init_out_of_memory(void)
{ {
fail_malloc = 1; fail_malloc = 1;
assert(!array_init(10, sizeof(int))); assert(!array_init(10, sizeof(int)));
fail_calloc = 1;
assert(!array_init(10, sizeof(int)));
} }
#endif #endif