Switch values to having their data refcounted separately.
This allows for values to be "cast" and have a different type, while still referencing the same data.
This commit is contained in:
parent
3e8c814215
commit
cf3136a237
|
@ -80,7 +80,15 @@ libab_result libab_create_table(libab_ref* into, libab_ref* parent);
|
||||||
* @param type the type to give the value.
|
* @param type the type to give the value.
|
||||||
* @return the result of necessary allocations.
|
* @return the result of necessary allocations.
|
||||||
*/
|
*/
|
||||||
libab_result libab_create_value(libab_ref* into, void* data, libab_ref* type);
|
libab_result libab_create_value_ref(libab_ref* into, libab_ref* data, libab_ref* type);
|
||||||
|
/**
|
||||||
|
* Allocates a new reference counted value with the given type and data.
|
||||||
|
* @param into the reference to store the allocated data into.
|
||||||
|
* @param data the type-specific data this value holds.
|
||||||
|
* @param type the type to give the value.
|
||||||
|
* @return the result of necessary allocations.
|
||||||
|
*/
|
||||||
|
libab_result libab_create_value_raw(libab_ref* into, void* data, libab_ref* type);
|
||||||
/**
|
/**
|
||||||
* Creates a function list object, storing it in to the given reference.
|
* Creates a function list object, storing it in to the given reference.
|
||||||
* @param into the reference to store into.
|
* @param into the reference to store into.
|
||||||
|
|
|
@ -15,19 +15,28 @@ struct libab_value_s {
|
||||||
/**
|
/**
|
||||||
* The data that is specific to this value.
|
* The data that is specific to this value.
|
||||||
*/
|
*/
|
||||||
void* data;
|
libab_ref data;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct libab_value_s libab_value;
|
typedef struct libab_value_s libab_value;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a new value with the given allocated memory for the data,
|
* Initializes a new value with the given reference counted data
|
||||||
* and the given type.
|
* and the given type.
|
||||||
* @param data the data for this value. It is freed when the value is released
|
* @param value the value to initialize.
|
||||||
* according to the free function of the base type.
|
* @param data the data for this value. Its refcount is decreased when the value is freed.
|
||||||
* @param type the type of this value.
|
* @param type the type of this value.
|
||||||
*/
|
*/
|
||||||
void libab_value_init(libab_value* value, void* data, libab_ref* type);
|
void libab_value_init_ref(libab_value* value, libab_ref* data, libab_ref* type);
|
||||||
|
/**
|
||||||
|
* Initializes a new value with the given raw allocated data, and a type,
|
||||||
|
* whose basetype's free function is used to release the data when the value is freed.
|
||||||
|
* @param value the value to initialize.
|
||||||
|
* @param data the data this value holds.
|
||||||
|
* @param type the type of this value.
|
||||||
|
* @return the result of any necessary allocations.
|
||||||
|
*/
|
||||||
|
libab_result libab_value_init_raw(libab_value* value, void* data, libab_ref* type);
|
||||||
/**
|
/**
|
||||||
* Frees the given value.
|
* Frees the given value.
|
||||||
* @param value the value to free.
|
* @param value the value to free.
|
||||||
|
|
|
@ -25,7 +25,7 @@ libab_result _interpreter_create_num_val(struct interpreter_state* state,
|
||||||
libab_result result = LIBAB_SUCCESS;
|
libab_result result = LIBAB_SUCCESS;
|
||||||
|
|
||||||
if((data = state->ab->impl.parse_num(from))) {
|
if((data = state->ab->impl.parse_num(from))) {
|
||||||
result = libab_create_value(into, data, &state->ab->type_num);
|
result = libab_create_value_raw(into, data, &state->ab->type_num);
|
||||||
|
|
||||||
if(result != LIBAB_SUCCESS) {
|
if(result != LIBAB_SUCCESS) {
|
||||||
((libab_parsetype*) libab_ref_get(&state->ab->type_num))->data_u.base->free_function(data);
|
((libab_parsetype*) libab_ref_get(&state->ab->type_num))->data_u.base->free_function(data);
|
||||||
|
|
31
src/util.c
31
src/util.c
|
@ -155,11 +155,11 @@ void _free_value(void* value) {
|
||||||
free(value);
|
free(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
libab_result libab_create_value(libab_ref* into, void* data, libab_ref* type) {
|
libab_result libab_create_value_ref(libab_ref* into, libab_ref* data, libab_ref* type) {
|
||||||
libab_value* value;
|
libab_value* value;
|
||||||
libab_result result = LIBAB_SUCCESS;
|
libab_result result = LIBAB_SUCCESS;
|
||||||
if((value = malloc(sizeof(*value)))) {
|
if((value = malloc(sizeof(*value)))) {
|
||||||
libab_value_init(value, data, type);
|
libab_value_init_ref(value, data, type);
|
||||||
result = libab_ref_new(into, value, _free_value);
|
result = libab_ref_new(into, value, _free_value);
|
||||||
|
|
||||||
if(result != LIBAB_SUCCESS) {
|
if(result != LIBAB_SUCCESS) {
|
||||||
|
@ -175,6 +175,31 @@ libab_result libab_create_value(libab_ref* into, void* data, libab_ref* type) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
libab_result libab_create_value_raw(libab_ref* into, void* data, libab_ref* type) {
|
||||||
|
libab_value* value;
|
||||||
|
libab_result result = LIBAB_SUCCESS;
|
||||||
|
|
||||||
|
if((value = malloc(sizeof(*value)))) {
|
||||||
|
result = libab_value_init_raw(value, data, type);
|
||||||
|
} else {
|
||||||
|
result = LIBAB_MALLOC;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(result == LIBAB_SUCCESS) {
|
||||||
|
result = libab_ref_new(into, value, _free_value);
|
||||||
|
if(result != LIBAB_SUCCESS) {
|
||||||
|
libab_value_free(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(result != LIBAB_SUCCESS) {
|
||||||
|
libab_ref_null(into);
|
||||||
|
free(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
libab_result libab_create_function_list(libab_ref* into, libab_ref* type) {
|
libab_result libab_create_function_list(libab_ref* into, libab_ref* type) {
|
||||||
libab_function_list* list;
|
libab_function_list* list;
|
||||||
libab_result result = LIBAB_SUCCESS;
|
libab_result result = LIBAB_SUCCESS;
|
||||||
|
@ -186,7 +211,7 @@ libab_result libab_create_function_list(libab_ref* into, libab_ref* type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(result == LIBAB_SUCCESS) {
|
if(result == LIBAB_SUCCESS) {
|
||||||
result = libab_create_value(into, list, type);
|
result = libab_create_value_raw(into, list, type);
|
||||||
if(result != LIBAB_SUCCESS) {
|
if(result != LIBAB_SUCCESS) {
|
||||||
libab_function_list_free(list);
|
libab_function_list_free(list);
|
||||||
libab_ref_free(into);
|
libab_ref_free(into);
|
||||||
|
|
30
src/value.c
30
src/value.c
|
@ -1,17 +1,27 @@
|
||||||
#include "value.h"
|
#include "value.h"
|
||||||
#include "parsetype.h"
|
#include "parsetype.h"
|
||||||
|
|
||||||
void libab_value_init(libab_value* value, void* data, libab_ref* type) {
|
void libab_value_init_ref(libab_value* value, libab_ref* data, libab_ref* type) {
|
||||||
value->data = data;
|
libab_ref_copy(data, &value->data);
|
||||||
libab_ref_copy(type, &value->type);
|
libab_ref_copy(type, &value->type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void libab_value_free(libab_value* value) {
|
libab_result libab_value_init_raw(libab_value* value, void* data, libab_ref* type) {
|
||||||
void (*free_function)(void*);
|
libab_result result = LIBAB_SUCCESS;
|
||||||
libab_parsetype* value_type;
|
libab_ref tmp_ref;
|
||||||
value_type = libab_ref_get(&value->type);
|
|
||||||
free_function = value_type->data_u.base->free_function;
|
result = libab_ref_new(&tmp_ref, data,
|
||||||
libab_ref_free(&value->type);
|
((libab_parsetype*) libab_ref_get(type))->data_u.base->free_function);
|
||||||
if (free_function)
|
|
||||||
free_function(value->data);
|
if(result == LIBAB_SUCCESS) {
|
||||||
|
libab_value_init_ref(value, &tmp_ref, type);
|
||||||
|
libab_ref_free(&tmp_ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void libab_value_free(libab_value* value) {
|
||||||
|
libab_ref_free(&value->data);
|
||||||
|
libab_ref_free(&value->type);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user