mirror of
https://github.com/bkthomps/Containers.git
synced 2025-11-16 12:34:47 +00:00
Improve failed memory allocation recovery
This commit is contained in:
125
src/deque.c
125
src/deque.c
@@ -63,8 +63,9 @@ deque deque_init(const size_t data_size)
|
||||
free(init);
|
||||
return NULL;
|
||||
}
|
||||
init->block->data = malloc(BLOCK_SIZE * init->data_size);
|
||||
if (init->block->data == NULL) {
|
||||
struct node *const block = init->block;
|
||||
block->data = malloc(BLOCK_SIZE * init->data_size);
|
||||
if (block->data == NULL) {
|
||||
free(init->block);
|
||||
free(init);
|
||||
return NULL;
|
||||
@@ -111,21 +112,25 @@ int deque_trim(deque me)
|
||||
{
|
||||
const int start_block = me->start_index / BLOCK_SIZE;
|
||||
const int end_block = me->end_index / BLOCK_SIZE;
|
||||
for (int i = 0; i < start_block; i++) {
|
||||
free(me->block[i].data);
|
||||
}
|
||||
for (int i = end_block + 1; i < me->block_count; i++) {
|
||||
free(me->block[i].data);
|
||||
}
|
||||
me->block_count = end_block - start_block + 1;
|
||||
memmove(me->block,
|
||||
&me->block[start_block],
|
||||
me->block_count * sizeof(struct node));
|
||||
void *temp = realloc(me->block, me->block_count * sizeof(struct node));
|
||||
if (temp == NULL) {
|
||||
const int new_block_count = end_block - start_block + 1;
|
||||
void *const new_block = malloc(new_block_count * sizeof(struct node));
|
||||
if (new_block == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
me->block = temp;
|
||||
for (int i = 0; i < start_block; i++) {
|
||||
const struct node block_item = me->block[i];
|
||||
free(block_item.data);
|
||||
}
|
||||
for (int i = end_block + 1; i < me->block_count; i++) {
|
||||
const struct node block_item = me->block[i];
|
||||
free(block_item.data);
|
||||
}
|
||||
memmove(new_block,
|
||||
&me->block[start_block],
|
||||
new_block_count * sizeof(struct node));
|
||||
free(me->block);
|
||||
me->block = new_block;
|
||||
me->block_count = new_block_count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -162,14 +167,16 @@ int deque_push_front(deque me, void *const data)
|
||||
if (inner_index == BLOCK_SIZE - 1) {
|
||||
if (block_index == -1) {
|
||||
const int old_block_count = me->block_count;
|
||||
me->block_count = (int) ceil(RESIZE_RATIO * me->block_count);
|
||||
const int added_blocks = me->block_count - old_block_count;
|
||||
const int new_block_count =
|
||||
(int) ceil(RESIZE_RATIO * me->block_count);
|
||||
const int added_blocks = new_block_count - old_block_count;
|
||||
void *temp = realloc(me->block,
|
||||
me->block_count * sizeof(struct node));
|
||||
new_block_count * sizeof(struct node));
|
||||
if (temp == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
me->block = temp;
|
||||
me->block_count = new_block_count;
|
||||
memmove(&me->block[added_blocks],
|
||||
me->block,
|
||||
old_block_count * sizeof(struct node));
|
||||
@@ -177,19 +184,20 @@ int deque_push_front(deque me, void *const data)
|
||||
me->start_index += added_blocks * BLOCK_SIZE;
|
||||
me->end_index += added_blocks * BLOCK_SIZE;
|
||||
for (int i = 0; i < added_blocks; i++) {
|
||||
me->block[i].data = NULL;
|
||||
struct node *const block_item = &me->block[i];
|
||||
block_item->data = NULL;
|
||||
}
|
||||
}
|
||||
if (me->block[block_index].data == NULL) {
|
||||
me->block[block_index].data = malloc(BLOCK_SIZE * me->data_size);
|
||||
if (me->block[block_index].data == NULL) {
|
||||
struct node *const block_item = &me->block[block_index];
|
||||
if (block_item->data == NULL) {
|
||||
block_item->data = malloc(BLOCK_SIZE * me->data_size);
|
||||
if (block_item->data == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
}
|
||||
memcpy(me->block[block_index].data + inner_index * me->data_size,
|
||||
data,
|
||||
me->data_size);
|
||||
const struct node block_item = me->block[block_index];
|
||||
memcpy(block_item.data + inner_index * me->data_size, data, me->data_size);
|
||||
me->start_index--;
|
||||
return 0;
|
||||
}
|
||||
@@ -209,27 +217,30 @@ int deque_push_back(deque me, void *const data)
|
||||
const int inner_index = me->end_index % BLOCK_SIZE;
|
||||
if (inner_index == 0) {
|
||||
if (block_index == me->block_count) {
|
||||
me->block_count = (int) ceil(RESIZE_RATIO * me->block_count);
|
||||
const int new_block_count =
|
||||
(int) ceil(RESIZE_RATIO * me->block_count);
|
||||
void *temp = realloc(me->block,
|
||||
me->block_count * sizeof(struct node));
|
||||
new_block_count * sizeof(struct node));
|
||||
if (temp == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
me->block = temp;
|
||||
me->block_count = new_block_count;
|
||||
for (int i = block_index; i < me->block_count; i++) {
|
||||
me->block[i].data = NULL;
|
||||
struct node *const block_item = &me->block[i];
|
||||
block_item->data = NULL;
|
||||
}
|
||||
}
|
||||
if (me->block[block_index].data == NULL) {
|
||||
me->block[block_index].data = malloc(BLOCK_SIZE * me->data_size);
|
||||
if (me->block[block_index].data == NULL) {
|
||||
struct node *const block_item = &me->block[block_index];
|
||||
if (block_item->data == NULL) {
|
||||
block_item->data = malloc(BLOCK_SIZE * me->data_size);
|
||||
if (block_item->data == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
}
|
||||
memcpy(me->block[block_index].data + inner_index * me->data_size,
|
||||
data,
|
||||
me->data_size);
|
||||
const struct node block_item = me->block[block_index];
|
||||
memcpy(block_item.data + inner_index * me->data_size, data, me->data_size);
|
||||
me->end_index++;
|
||||
return 0;
|
||||
}
|
||||
@@ -251,9 +262,8 @@ int deque_pop_front(void *const data, deque me)
|
||||
me->start_index++;
|
||||
const int block_index = me->start_index / BLOCK_SIZE;
|
||||
const int inner_index = me->start_index % BLOCK_SIZE;
|
||||
memcpy(data,
|
||||
me->block[block_index].data + inner_index * me->data_size,
|
||||
me->data_size);
|
||||
const struct node block_item = me->block[block_index];
|
||||
memcpy(data, block_item.data + inner_index * me->data_size, me->data_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -274,9 +284,8 @@ int deque_pop_back(void *const data, deque me)
|
||||
me->end_index--;
|
||||
const int block_index = me->end_index / BLOCK_SIZE;
|
||||
const int inner_index = me->end_index % BLOCK_SIZE;
|
||||
memcpy(data,
|
||||
me->block[block_index].data + inner_index * me->data_size,
|
||||
me->data_size);
|
||||
const struct node block_item = me->block[block_index];
|
||||
memcpy(data, block_item.data + inner_index * me->data_size, me->data_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -312,9 +321,8 @@ int deque_set_at(deque me, int index, void *const data)
|
||||
index += me->start_index + 1;
|
||||
const int block_index = index / BLOCK_SIZE;
|
||||
const int inner_index = index % BLOCK_SIZE;
|
||||
memcpy(me->block[block_index].data + inner_index * me->data_size,
|
||||
data,
|
||||
me->data_size);
|
||||
const struct node block_item = me->block[block_index];
|
||||
memcpy(block_item.data + inner_index * me->data_size, data, me->data_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -364,9 +372,8 @@ int deque_get_at(void *const data, deque me, int index)
|
||||
index += me->start_index + 1;
|
||||
const int block_index = index / BLOCK_SIZE;
|
||||
const int inner_index = index % BLOCK_SIZE;
|
||||
memcpy(data,
|
||||
me->block[block_index].data + inner_index * me->data_size,
|
||||
me->data_size);
|
||||
const struct node block_item = me->block[block_index];
|
||||
memcpy(data, block_item.data + inner_index * me->data_size, me->data_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -394,21 +401,26 @@ int deque_get_last(void *const data, deque me)
|
||||
*/
|
||||
int deque_clear(deque me)
|
||||
{
|
||||
struct node *const temp_block = malloc(sizeof(struct node));
|
||||
if (temp_block == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
void *const temp_block_data = malloc(BLOCK_SIZE * me->data_size);
|
||||
if (temp_block_data == NULL) {
|
||||
free(temp_block);
|
||||
return -ENOMEM;
|
||||
}
|
||||
for (int i = 0; i < me->block_count; i++) {
|
||||
free(me->block[i].data);
|
||||
const struct node block_item = me->block[i];
|
||||
free(block_item.data);
|
||||
}
|
||||
free(me->block);
|
||||
me->start_index = BLOCK_SIZE / 2;
|
||||
me->end_index = me->start_index + 1;
|
||||
me->block_count = 1;
|
||||
me->block = malloc(sizeof(struct node));
|
||||
if (me->block == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
me->block->data = malloc(BLOCK_SIZE * me->data_size);
|
||||
if (me->block->data == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
me->block = temp_block;
|
||||
struct node *const block = me->block;
|
||||
block->data = temp_block_data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -422,7 +434,8 @@ int deque_clear(deque me)
|
||||
deque deque_destroy(deque me)
|
||||
{
|
||||
for (int i = 0; i < me->block_count; i++) {
|
||||
free(me->block[i].data);
|
||||
const struct node block_item = me->block[i];
|
||||
free(block_item.data);
|
||||
}
|
||||
free(me->block);
|
||||
free(me);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Bailey Thompson
|
||||
* Copyright (c) 2017-2018 Bailey Thompson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -258,6 +258,7 @@ static struct node *multiset_create_node(multiset me,
|
||||
memcpy(insert->key, data, me->key_size);
|
||||
insert->left = NULL;
|
||||
insert->right = NULL;
|
||||
me->size++;
|
||||
return insert;
|
||||
}
|
||||
|
||||
@@ -278,7 +279,6 @@ int multiset_put(multiset me, void *const key)
|
||||
return -ENOMEM;
|
||||
}
|
||||
me->root = insert;
|
||||
me->size++;
|
||||
return 0;
|
||||
}
|
||||
struct node *traverse = me->root;
|
||||
@@ -294,7 +294,6 @@ int multiset_put(multiset me, void *const key)
|
||||
}
|
||||
traverse->left = insert;
|
||||
multiset_insert_balance(me, insert);
|
||||
me->size++;
|
||||
return 0;
|
||||
}
|
||||
} else if (compare > 0) {
|
||||
@@ -307,7 +306,6 @@ int multiset_put(multiset me, void *const key)
|
||||
}
|
||||
traverse->right = insert;
|
||||
multiset_insert_balance(me, insert);
|
||||
me->size++;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Bailey Thompson
|
||||
* Copyright (c) 2017-2018 Bailey Thompson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -160,13 +160,14 @@ bool unordered_map_is_empty(unordered_map me)
|
||||
static int unordered_map_resize(unordered_map me)
|
||||
{
|
||||
const int old_capacity = me->capacity;
|
||||
me->capacity *= RESIZE_RATIO;
|
||||
const int new_capacity = (int) (me->capacity * RESIZE_RATIO);
|
||||
struct node **old_buckets = me->buckets;
|
||||
me->buckets = calloc((size_t) me->capacity, sizeof(struct node *));
|
||||
me->buckets = calloc((size_t) new_capacity, sizeof(struct node *));
|
||||
if (me->buckets == NULL) {
|
||||
me->buckets = old_buckets;
|
||||
return -ENOMEM;
|
||||
}
|
||||
me->capacity = new_capacity;
|
||||
for (int i = 0; i < old_capacity; i++) {
|
||||
struct node *traverse = old_buckets[i];
|
||||
while (traverse != NULL) {
|
||||
@@ -361,6 +362,11 @@ bool unordered_map_remove(unordered_map me, void *const key)
|
||||
*/
|
||||
int unordered_map_clear(unordered_map me)
|
||||
{
|
||||
struct node **temp =
|
||||
calloc((size_t) STARTING_BUCKETS, sizeof(struct node *));
|
||||
if (temp == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
for (int i = 0; i < me->capacity; i++) {
|
||||
struct node *traverse = me->buckets[i];
|
||||
while (traverse != NULL) {
|
||||
@@ -374,10 +380,6 @@ int unordered_map_clear(unordered_map me)
|
||||
}
|
||||
me->size = 0;
|
||||
me->capacity = STARTING_BUCKETS;
|
||||
struct node **temp = calloc((size_t) me->capacity, sizeof(struct node *));
|
||||
if (temp == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
free(me->buckets);
|
||||
me->buckets = temp;
|
||||
return 0;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Bailey Thompson
|
||||
* Copyright (c) 2017-2018 Bailey Thompson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -179,13 +179,14 @@ bool unordered_multimap_is_empty(unordered_multimap me)
|
||||
static int unordered_multimap_resize(unordered_multimap me)
|
||||
{
|
||||
const int old_capacity = me->capacity;
|
||||
me->capacity *= RESIZE_RATIO;
|
||||
const int new_capacity = (int) (me->capacity * RESIZE_RATIO);
|
||||
struct node **old_buckets = me->buckets;
|
||||
me->buckets = calloc((size_t) me->capacity, sizeof(struct node *));
|
||||
me->buckets = calloc((size_t) new_capacity, sizeof(struct node *));
|
||||
if (me->buckets == NULL) {
|
||||
me->buckets = old_buckets;
|
||||
return -ENOMEM;
|
||||
}
|
||||
me->capacity = new_capacity;
|
||||
for (int i = 0; i < old_capacity; i++) {
|
||||
struct node *traverse = old_buckets[i];
|
||||
while (traverse != NULL) {
|
||||
@@ -482,6 +483,11 @@ bool unordered_multimap_remove_all(unordered_multimap me, void *const key)
|
||||
*/
|
||||
int unordered_multimap_clear(unordered_multimap me)
|
||||
{
|
||||
struct node **temp =
|
||||
calloc((size_t) STARTING_BUCKETS, sizeof(struct node *));
|
||||
if (temp == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
for (int i = 0; i < me->capacity; i++) {
|
||||
struct node *traverse = me->buckets[i];
|
||||
while (traverse != NULL) {
|
||||
@@ -495,10 +501,6 @@ int unordered_multimap_clear(unordered_multimap me)
|
||||
}
|
||||
me->size = 0;
|
||||
me->capacity = STARTING_BUCKETS;
|
||||
struct node **temp = calloc((size_t) me->capacity, sizeof(struct node *));
|
||||
if (temp == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
free(me->buckets);
|
||||
me->buckets = temp;
|
||||
return 0;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Bailey Thompson
|
||||
* Copyright (c) 2017-2018 Bailey Thompson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -160,13 +160,14 @@ bool unordered_multiset_is_empty(unordered_multiset me)
|
||||
static int unordered_multiset_resize(unordered_multiset me)
|
||||
{
|
||||
const int old_capacity = me->capacity;
|
||||
me->capacity *= RESIZE_RATIO;
|
||||
const int new_capacity = (int) (me->capacity * RESIZE_RATIO);
|
||||
struct node **old_buckets = me->buckets;
|
||||
me->buckets = calloc((size_t) me->capacity, sizeof(struct node *));
|
||||
me->buckets = calloc((size_t) new_capacity, sizeof(struct node *));
|
||||
if (me->buckets == NULL) {
|
||||
me->buckets = old_buckets;
|
||||
return -ENOMEM;
|
||||
}
|
||||
me->capacity = new_capacity;
|
||||
for (int i = 0; i < old_capacity; i++) {
|
||||
struct node *traverse = old_buckets[i];
|
||||
while (traverse != NULL) {
|
||||
@@ -391,6 +392,11 @@ bool unordered_multiset_remove_all(unordered_multiset me, void *const key)
|
||||
*/
|
||||
int unordered_multiset_clear(unordered_multiset me)
|
||||
{
|
||||
struct node **temp =
|
||||
calloc((size_t) STARTING_BUCKETS, sizeof(struct node *));
|
||||
if (temp == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
for (int i = 0; i < me->capacity; i++) {
|
||||
struct node *traverse = me->buckets[i];
|
||||
while (traverse != NULL) {
|
||||
@@ -404,10 +410,6 @@ int unordered_multiset_clear(unordered_multiset me)
|
||||
me->size = 0;
|
||||
me->used = 0;
|
||||
me->capacity = STARTING_BUCKETS;
|
||||
struct node **temp = calloc((size_t) me->capacity, sizeof(struct node *));
|
||||
if (temp == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
free(me->buckets);
|
||||
me->buckets = temp;
|
||||
return 0;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Bailey Thompson
|
||||
* Copyright (c) 2017-2018 Bailey Thompson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -155,13 +155,14 @@ bool unordered_set_is_empty(unordered_set me)
|
||||
static int unordered_set_resize(unordered_set me)
|
||||
{
|
||||
const int old_capacity = me->capacity;
|
||||
me->capacity *= RESIZE_RATIO;
|
||||
const int new_capacity = (int) (me->capacity * RESIZE_RATIO);
|
||||
struct node **old_buckets = me->buckets;
|
||||
me->buckets = calloc((size_t) me->capacity, sizeof(struct node *));
|
||||
me->buckets = calloc((size_t) new_capacity, sizeof(struct node *));
|
||||
if (me->buckets == NULL) {
|
||||
me->buckets = old_buckets;
|
||||
return -ENOMEM;
|
||||
}
|
||||
me->capacity = new_capacity;
|
||||
for (int i = 0; i < old_capacity; i++) {
|
||||
struct node *traverse = old_buckets[i];
|
||||
while (traverse != NULL) {
|
||||
@@ -319,6 +320,11 @@ bool unordered_set_remove(unordered_set me, void *const key)
|
||||
*/
|
||||
int unordered_set_clear(unordered_set me)
|
||||
{
|
||||
struct node **temp =
|
||||
calloc((size_t) STARTING_BUCKETS, sizeof(struct node *));
|
||||
if (temp == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
for (int i = 0; i < me->capacity; i++) {
|
||||
struct node *traverse = me->buckets[i];
|
||||
while (traverse != NULL) {
|
||||
@@ -331,10 +337,6 @@ int unordered_set_clear(unordered_set me)
|
||||
}
|
||||
me->size = 0;
|
||||
me->capacity = STARTING_BUCKETS;
|
||||
struct node **temp = calloc((size_t) me->capacity, sizeof(struct node *));
|
||||
if (temp == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
free(me->buckets);
|
||||
me->buckets = temp;
|
||||
return 0;
|
||||
|
||||
15
src/vector.c
15
src/vector.c
@@ -88,15 +88,15 @@ bool vector_is_empty(vector me)
|
||||
*/
|
||||
static int vector_set_space(vector me, const int size)
|
||||
{
|
||||
me->space = size;
|
||||
if (me->space < me->offset) {
|
||||
me->offset = me->space;
|
||||
}
|
||||
void *const temp = realloc(me->storage, me->space * me->data_size);
|
||||
void *const temp = realloc(me->storage, size * me->data_size);
|
||||
if (temp == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
me->storage = temp;
|
||||
me->space = size;
|
||||
if (me->space < me->offset) {
|
||||
me->offset = me->space;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -188,12 +188,13 @@ int vector_add_at(vector me, const int index, void *const data)
|
||||
return -EINVAL;
|
||||
}
|
||||
if (me->offset + 1 >= me->space) {
|
||||
me->space *= RESIZE_RATIO;
|
||||
void *const temp = realloc(me->storage, me->space * me->data_size);
|
||||
const int new_space = (int) (me->space * RESIZE_RATIO);
|
||||
void *const temp = realloc(me->storage, new_space * me->data_size);
|
||||
if (temp == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
me->storage = temp;
|
||||
me->space = new_space;
|
||||
}
|
||||
if (index != me->offset) {
|
||||
memmove(me->storage + (index + 1) * me->data_size,
|
||||
|
||||
Reference in New Issue
Block a user