Add a vector of reference counted values.
This commit is contained in:
parent
35fc0e7fd1
commit
e6801255fa
|
@ -8,7 +8,7 @@ project(libabacus)
|
||||||
|
|
||||||
add_compile_options(-pedantic -Wall)
|
add_compile_options(-pedantic -Wall)
|
||||||
|
|
||||||
add_library(abacus STATIC src/lexer.c src/util.c src/table.c src/parser.c src/libabacus.c src/tree.c src/debug.c src/parsetype.c src/reserved.c src/trie.c src/refcount.c src/type.c)
|
add_library(abacus STATIC src/lexer.c src/util.c src/table.c src/parser.c src/libabacus.c src/tree.c src/debug.c src/parsetype.c src/reserved.c src/trie.c src/refcount.c src/type.c src/ref_vec.c)
|
||||||
add_executable(libabacus src/main.c)
|
add_executable(libabacus src/main.c)
|
||||||
add_subdirectory(external/liblex)
|
add_subdirectory(external/liblex)
|
||||||
|
|
||||||
|
|
69
include/ref_vec.h
Normal file
69
include/ref_vec.h
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
#ifndef LIBABACUS_REF_VEC_H
|
||||||
|
#define LIBABACUS_REF_VEC_H
|
||||||
|
|
||||||
|
#include "result.h"
|
||||||
|
#include "refcount.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define LIBABACUS_REF_VEC_INITIAL_SIZE 4
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A vector of reference counter pointers.
|
||||||
|
*/
|
||||||
|
struct libab_ref_vec_s {
|
||||||
|
/*
|
||||||
|
* The capacity of the vector (how many elements
|
||||||
|
* can be stored inside).
|
||||||
|
*/
|
||||||
|
size_t capacity;
|
||||||
|
/**
|
||||||
|
* The number of elements inside the vector.
|
||||||
|
*/
|
||||||
|
size_t size;
|
||||||
|
/**
|
||||||
|
* The array of references.
|
||||||
|
*/
|
||||||
|
libab_ref* data;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct libab_ref_vec_s libab_ref_vec;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a new vector.
|
||||||
|
* @param vec the vector to initialize.
|
||||||
|
* @return the result of the initialization.
|
||||||
|
*/
|
||||||
|
libab_result libab_ref_vec_init(libab_ref_vec* vec);
|
||||||
|
/**
|
||||||
|
* Inserts an existing reference counted value into the vector.
|
||||||
|
* This bumps the reference's refcount, thereby preventing its
|
||||||
|
* deallocation.
|
||||||
|
* @param vec the vector to insert into.
|
||||||
|
* @param data the reference to insert.
|
||||||
|
* @return the result of the insertion.
|
||||||
|
*/
|
||||||
|
libab_result libab_ref_vec_insert(libab_ref_vec* vec, libab_ref* data);
|
||||||
|
/**
|
||||||
|
* Inserts an allocated value into the vector after wrapping it in a reference.
|
||||||
|
* @param vec the vector to insert into.
|
||||||
|
* @param data the value to convert to a refcounted pointer.
|
||||||
|
* @param free_func the function called to release the value (besides free)
|
||||||
|
* @return the result of the insertion.
|
||||||
|
*/
|
||||||
|
libab_result libab_ref_vec_insert_value(libab_ref_vec* vec, void* data, void (*free_func)(void*));
|
||||||
|
/**
|
||||||
|
* Returns the value at the given index in the vector, or null or the value doesn't
|
||||||
|
* exist.
|
||||||
|
* @param vec the vector to get a value from.
|
||||||
|
* @param index the index to look at.
|
||||||
|
* @return the reference stored at the given index.
|
||||||
|
*/
|
||||||
|
const libab_ref* libab_ref_vec_index(libab_ref_vec* vec, size_t index);
|
||||||
|
/**
|
||||||
|
* Releases the memory allocated by the vector.
|
||||||
|
* The references stored in the vector have their refcount decreased.
|
||||||
|
* @param vec the vector to free.
|
||||||
|
*/
|
||||||
|
void libab_ref_vec_free(libab_ref_vec* vec);
|
||||||
|
|
||||||
|
#endif
|
|
@ -70,10 +70,10 @@ void libab_ref_free(libab_ref* ref);
|
||||||
/**
|
/**
|
||||||
* Copies this reference, thereby increasing the reference count.
|
* Copies this reference, thereby increasing the reference count.
|
||||||
*/
|
*/
|
||||||
void libab_ref_copy(libab_ref* ref, libab_ref* into);
|
void libab_ref_copy(const libab_ref* ref, libab_ref* into);
|
||||||
/**
|
/**
|
||||||
* Gets the value of the reference.
|
* Gets the value of the reference.
|
||||||
*/
|
*/
|
||||||
void* libab_ref_get(libab_ref* ref);
|
void* libab_ref_get(const libab_ref* ref);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
66
src/ref_vec.c
Normal file
66
src/ref_vec.c
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
#include "ref_vec.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
libab_result libab_ref_vec_init(libab_ref_vec* vec) {
|
||||||
|
libab_result result = LIBAB_SUCCESS;
|
||||||
|
vec->capacity = LIBABACUS_REF_VEC_INITIAL_SIZE;
|
||||||
|
vec->size = 0;
|
||||||
|
vec->data =
|
||||||
|
malloc(sizeof(*vec->data) * LIBABACUS_REF_VEC_INITIAL_SIZE);
|
||||||
|
if(vec->data == NULL) {
|
||||||
|
result = LIBAB_MALLOC;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
libab_result _libab_ref_vec_try_resize(libab_ref_vec* vec) {
|
||||||
|
libab_result result = LIBAB_SUCCESS;
|
||||||
|
if(vec->size == vec->capacity) {
|
||||||
|
libab_ref* new_memory = realloc(vec->data, (vec->capacity *= 2) * sizeof(*vec->data));
|
||||||
|
if(new_memory == NULL) {
|
||||||
|
free(vec->data);
|
||||||
|
result = LIBAB_MALLOC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
libab_result libab_ref_vec_insert(libab_ref_vec* vec, libab_ref* data) {
|
||||||
|
libab_result result = _libab_ref_vec_try_resize(vec);
|
||||||
|
|
||||||
|
if(result == LIBAB_SUCCESS) {
|
||||||
|
libab_ref_copy(data, &vec->data[vec->size++]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
libab_result libab_ref_vec_insert_value(libab_ref_vec* vec, void* data, void (*free_func)(void*)) {
|
||||||
|
libab_result result = _libab_ref_vec_try_resize(vec);
|
||||||
|
|
||||||
|
if(result == LIBAB_SUCCESS) {
|
||||||
|
result = libab_ref_new(&vec->data[vec->size], data, free_func);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(result == LIBAB_SUCCESS) {
|
||||||
|
vec->size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const libab_ref* libab_ref_vec_index(libab_ref_vec* vec, size_t index) {
|
||||||
|
const libab_ref* to_return = NULL;
|
||||||
|
if(index < vec->size) {
|
||||||
|
to_return = &vec->data[index];
|
||||||
|
}
|
||||||
|
return to_return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void libab_ref_vec_free(libab_ref_vec* vec) {
|
||||||
|
size_t i = 0;
|
||||||
|
for(; i < vec->size; i++) {
|
||||||
|
libab_ref_free(&vec->data[i]);
|
||||||
|
}
|
||||||
|
free(vec->data);
|
||||||
|
}
|
|
@ -42,13 +42,13 @@ void libab_ref_free(libab_ref* ref) {
|
||||||
_libab_ref_changed(ref);
|
_libab_ref_changed(ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
void libab_ref_copy(libab_ref* ref, libab_ref* into) {
|
void libab_ref_copy(const libab_ref* ref, libab_ref* into) {
|
||||||
ref->count->strong++;
|
ref->count->strong++;
|
||||||
ref->count->weak++;
|
ref->count->weak++;
|
||||||
memcpy(into, ref, sizeof(*ref));
|
memcpy(into, ref, sizeof(*ref));
|
||||||
}
|
}
|
||||||
|
|
||||||
void* libab_ref_get(libab_ref* ref) {
|
void* libab_ref_get(const libab_ref* ref) {
|
||||||
void* to_return = NULL;
|
void* to_return = NULL;
|
||||||
if(ref->count->strong > 0) {
|
if(ref->count->strong > 0) {
|
||||||
to_return = ref->data;
|
to_return = ref->data;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user