apfl/src/value.h
Laria Carolin Chabowski ebf3fc89ff Introduce allocator abstraction
We now no longer call malloc/free/... directly, but use an allocator object
that is passed around.

This was mainly done as a preparation for a garbage collector: The
collector will need to know, how much memory we're using, introducing the
collector abstraction will allow the GC to hook into the memory allocation
and observe the memory usage.

This has other potential applications:

- We could now be embedded into applications that can't use the libc
  allocator.
- There could be an allocator that limits the total amount of used memory,
  e.g. for sandboxing purposes.
- In our tests we could use this to simulate out of memory conditions
  (implement an allocator that fails at the n-th allocation, increase n by
  one and restart the test until there are no more faked OOM conditions).

The function signature of the allocator is basically exactly the same as
the one Lua uses.
2022-02-08 22:53:13 +01:00

99 lines
3.1 KiB
C

#ifndef APFL_VALUE_H
#define APFL_VALUE_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
#include <stdio.h>
#include "apfl.h"
enum apfl_value_type {
APFL_VALUE_NIL,
APFL_VALUE_BOOLEAN,
APFL_VALUE_NUMBER,
APFL_VALUE_STRING,
APFL_VALUE_LIST,
APFL_VALUE_DICT,
// TODO: functions/closures
};
struct apfl_list_data;
typedef struct apfl_list_data *apfl_list;
struct apfl_dict_data;
typedef struct apfl_dict_data *apfl_dict;
struct apfl_value {
enum apfl_value_type type;
union {
bool boolean;
apfl_number number;
apfl_refcounted_string string;
apfl_list list;
apfl_dict dict;
};
};
bool apfl_value_eq(const struct apfl_value, const struct apfl_value);
struct apfl_value apfl_value_move(struct apfl_value *src);
struct apfl_value apfl_value_incref(struct apfl_value);
void apfl_value_print(struct apfl_value, FILE *);
void apfl_value_deinit(struct apfl_allocator, struct apfl_value *);
enum apfl_value_get_item_result {
APFL_VALUE_GET_ITEM_OK,
APFL_VALUE_GET_ITEM_KEY_DOESNT_EXIST,
APFL_VALUE_GET_ITEM_NOT_A_CONTAINER,
APFL_VALUE_GET_ITEM_WRONG_KEY_TYPE,
};
enum apfl_value_get_item_result apfl_value_get_item(struct apfl_allocator allocator, struct apfl_value container, struct apfl_value key, struct apfl_value *out);
apfl_list apfl_list_incref(apfl_list);
size_t apfl_list_len(apfl_list);
bool apfl_list_get_item(struct apfl_allocator, apfl_list, size_t index, struct apfl_value *out);
void apfl_list_unref(struct apfl_allocator, apfl_list);
apfl_dict apfl_dict_incref(apfl_dict);
bool apfl_dict_get_item(struct apfl_allocator, apfl_dict, struct apfl_value key, struct apfl_value *out);
void apfl_dict_unref(struct apfl_allocator, apfl_dict);
struct apfl_editable_list_data;
typedef struct apfl_editable_list_data *apfl_editable_list;
apfl_editable_list apfl_editable_list_new(struct apfl_allocator);
bool apfl_editable_list_append(apfl_editable_list, struct apfl_value);
bool apfl_editable_list_append_list(apfl_editable_list, apfl_list);
void apfl_editable_list_destroy(apfl_editable_list);
/* Finalize the list and return a non-editable list.
* This also destroys the editable list object, so it's no longer safe to use it.
* Returns NULL on failure
*/
apfl_list apfl_editable_list_finalize(apfl_editable_list);
struct apfl_editable_dict_data;
typedef struct apfl_editable_dict_data *apfl_editable_dict;
apfl_editable_dict apfl_editable_dict_new(struct apfl_allocator);
apfl_editable_dict apfl_editable_dict_new_from_dict(struct apfl_allocator, apfl_dict);
bool apfl_editable_dict_get(apfl_editable_dict, struct apfl_value key, struct apfl_value *out);
bool apfl_editable_dict_set(apfl_editable_dict, struct apfl_value key, struct apfl_value value);
void apfl_editable_dict_delete(apfl_editable_dict, struct apfl_value key);
void apfl_editable_dict_destroy(apfl_editable_dict);
/* Finalize the dictionary and return a non-editable dictionary.
* This also destroys the editable dictionary object, so it's no longer safe to use it.
* Returns NULL on failure
*/
apfl_dict apfl_editable_dict_finalize(apfl_editable_dict);
#ifdef __cplusplus
}
#endif
#endif