Fix refcounted strings
Increasing the refcount (confusingly called copy before, fixed that too) didn't work properly, as the object was copied and the refcount was only updated in one of the copies.
This commit is contained in:
parent
27eaefaaaa
commit
eaa6b723bc
5 changed files with 45 additions and 38 deletions
33
src/apfl.h
33
src/apfl.h
|
|
@ -30,10 +30,9 @@ struct apfl_string {
|
|||
size_t len;
|
||||
};
|
||||
|
||||
struct apfl_refcounted_string {
|
||||
unsigned refcount;
|
||||
struct apfl_string string;
|
||||
};
|
||||
struct apfl_refcounted_string_data;
|
||||
|
||||
typedef struct apfl_refcounted_string_data *apfl_refcounted_string;
|
||||
|
||||
#define APFL_STR_FMT "%.*s"
|
||||
#define APFL_STR_FMT_ARGS(s) (int)(s).len,(s).bytes
|
||||
|
|
@ -42,14 +41,14 @@ struct apfl_string_view apfl_string_view_from_view(struct apfl_string_view);
|
|||
struct apfl_string_view apfl_string_view_from_cstr(char *);
|
||||
struct apfl_string_view apfl_string_view_from_const_cstr(const char *);
|
||||
struct apfl_string_view apfl_string_view_from_string(struct apfl_string);
|
||||
struct apfl_string_view apfl_string_view_from_refcounted_string(struct apfl_refcounted_string *);
|
||||
struct apfl_string_view apfl_string_view_from_refcounted_string(apfl_refcounted_string);
|
||||
|
||||
#define apfl_string_view_from(s) _Generic((s), \
|
||||
struct apfl_string: apfl_string_view_from_string, \
|
||||
struct apfl_string_view: apfl_string_view_from_view, \
|
||||
struct apfl_refcounted_string *: apfl_string_view_from_refcounted_string, \
|
||||
char *: apfl_string_view_from_cstr, \
|
||||
const char *: apfl_string_view_from_const_cstr \
|
||||
#define apfl_string_view_from(s) _Generic((s), \
|
||||
struct apfl_string: apfl_string_view_from_string, \
|
||||
struct apfl_string_view: apfl_string_view_from_view, \
|
||||
apfl_refcounted_string: apfl_string_view_from_refcounted_string, \
|
||||
char *: apfl_string_view_from_cstr, \
|
||||
const char *: apfl_string_view_from_const_cstr \
|
||||
)(s)
|
||||
|
||||
int apfl_string_view_cmp(struct apfl_string_view, struct apfl_string_view);
|
||||
|
|
@ -82,13 +81,17 @@ struct apfl_string apfl_string_builder_move_string(struct apfl_string_builder *)
|
|||
|
||||
#define apfl_string_builder_append_cstr(builder, cstr) (apfl_string_builder_append((builder), apfl_string_view_from_cstr((cstr))))
|
||||
|
||||
struct apfl_refcounted_string *apfl_string_move_into_new_refcounted(struct apfl_string *);
|
||||
struct apfl_refcounted_string *apfl_refcounted_string_copy(struct apfl_refcounted_string *);
|
||||
apfl_refcounted_string apfl_string_move_into_new_refcounted(struct apfl_string *);
|
||||
|
||||
/* Increases the reference of the refcounted string.
|
||||
* Returns the same apfl_refcounted_string value.
|
||||
*/
|
||||
apfl_refcounted_string apfl_refcounted_string_incref(apfl_refcounted_string);
|
||||
|
||||
/* Unrefs the refcounted string. It is no longer allowed to use the pointer
|
||||
* after calling this function with it!
|
||||
*/
|
||||
void apfl_refcounted_string_unref(struct apfl_refcounted_string *);
|
||||
void apfl_refcounted_string_unref(apfl_refcounted_string );
|
||||
|
||||
// Tokens
|
||||
|
||||
|
|
@ -518,7 +521,7 @@ struct apfl_value {
|
|||
union {
|
||||
bool boolean;
|
||||
apfl_number number;
|
||||
struct apfl_refcounted_string *string;
|
||||
apfl_refcounted_string string;
|
||||
struct apfl_list *list;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ fatal(void)
|
|||
static struct apfl_result
|
||||
evaluate_constant(struct apfl_expr_const *constant)
|
||||
{
|
||||
struct apfl_refcounted_string *rcstring;
|
||||
apfl_refcounted_string rcstring;
|
||||
|
||||
switch (constant->type) {
|
||||
case APFL_EXPR_CONST_NIL:
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ apfl_print_indented(unsigned indent, FILE *f, const char* fmt, ...)
|
|||
bool
|
||||
apfl_refcount_dec(unsigned *rc)
|
||||
{
|
||||
if (rc == 0) {
|
||||
if (rc == NULL) {
|
||||
return false;
|
||||
}
|
||||
return --(*rc) == 0;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,11 @@
|
|||
#include "internal.h"
|
||||
#include "resizable.h"
|
||||
|
||||
struct apfl_refcounted_string_data {
|
||||
unsigned refcount;
|
||||
struct apfl_string string;
|
||||
};
|
||||
|
||||
struct apfl_string_view
|
||||
apfl_string_view_from_view(struct apfl_string_view view)
|
||||
{
|
||||
|
|
@ -142,21 +147,25 @@ apfl_string_builder_move_string(struct apfl_string_builder *builder)
|
|||
return str;
|
||||
}
|
||||
|
||||
struct
|
||||
apfl_string_view apfl_string_view_from_refcounted_string(struct apfl_refcounted_string *rcstring)
|
||||
struct apfl_string_view
|
||||
apfl_string_view_from_refcounted_string(apfl_refcounted_string rcstring)
|
||||
{
|
||||
if (rcstring == NULL) {
|
||||
return apfl_string_view_from(apfl_string_blank());
|
||||
}
|
||||
|
||||
return apfl_string_view_from(rcstring->string);
|
||||
}
|
||||
|
||||
struct apfl_refcounted_string *
|
||||
apfl_refcounted_string
|
||||
apfl_string_move_into_new_refcounted(struct apfl_string *src)
|
||||
{
|
||||
struct apfl_refcounted_string *dst = ALLOC(struct apfl_refcounted_string);
|
||||
apfl_refcounted_string dst = ALLOC(struct apfl_refcounted_string_data);
|
||||
if (dst == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*dst = (struct apfl_refcounted_string) {
|
||||
*dst = (struct apfl_refcounted_string_data) {
|
||||
.refcount = 1,
|
||||
.string = apfl_string_move(src),
|
||||
};
|
||||
|
|
@ -164,24 +173,20 @@ apfl_string_move_into_new_refcounted(struct apfl_string *src)
|
|||
return dst;
|
||||
}
|
||||
|
||||
struct apfl_refcounted_string *
|
||||
apfl_refcounted_string_copy(struct apfl_refcounted_string *src)
|
||||
apfl_refcounted_string
|
||||
apfl_refcounted_string_incref(apfl_refcounted_string rcstring)
|
||||
{
|
||||
struct apfl_refcounted_string *dst = ALLOC(struct apfl_refcounted_string);
|
||||
if (dst == NULL) {
|
||||
return NULL;
|
||||
if (rcstring != NULL) {
|
||||
rcstring->refcount++;
|
||||
}
|
||||
|
||||
*dst = *src;
|
||||
dst->refcount++;
|
||||
|
||||
return dst;
|
||||
return rcstring;
|
||||
}
|
||||
|
||||
void
|
||||
apfl_refcounted_string_unref(struct apfl_refcounted_string *rcstring)
|
||||
apfl_refcounted_string_unref(apfl_refcounted_string rcstring)
|
||||
{
|
||||
if (apfl_refcount_dec(&rcstring->refcount)) {
|
||||
if (rcstring != NULL && apfl_refcount_dec(&rcstring->refcount)) {
|
||||
apfl_string_deinit(&rcstring->string);
|
||||
free(rcstring);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,9 +50,7 @@ apfl_value_copy(struct apfl_value *dst, struct apfl_value src)
|
|||
// Nothing to do
|
||||
goto ok;
|
||||
case APFL_VALUE_STRING:
|
||||
if ((dst->string = apfl_refcounted_string_copy(src.string)) == NULL) {
|
||||
return false;
|
||||
}
|
||||
dst->string = apfl_refcounted_string_incref(src.string);
|
||||
goto ok;
|
||||
case APFL_VALUE_LIST:
|
||||
assert(src.list != NULL);
|
||||
|
|
@ -108,7 +106,8 @@ apfl_value_deinit(struct apfl_value *value)
|
|||
case APFL_VALUE_NUMBER:
|
||||
goto ok;
|
||||
case APFL_VALUE_STRING:
|
||||
DESTROY(value->string, apfl_refcounted_string_unref);
|
||||
apfl_refcounted_string_unref(value->string);
|
||||
value->string = NULL;
|
||||
goto ok;
|
||||
case APFL_VALUE_LIST:
|
||||
if (apfl_refcount_dec(&value->list->refcount)) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue