2021-12-10 20:22:16 +00:00
|
|
|
#include <stdbool.h>
|
|
|
|
|
#include <stddef.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
#include "apfl.h"
|
|
|
|
|
|
2022-01-02 16:55:05 +00:00
|
|
|
#include "internal.h"
|
2021-12-10 20:22:16 +00:00
|
|
|
#include "resizable.h"
|
|
|
|
|
|
2022-01-04 20:22:46 +00:00
|
|
|
struct apfl_refcounted_string_data {
|
|
|
|
|
unsigned refcount;
|
|
|
|
|
struct apfl_string string;
|
|
|
|
|
};
|
|
|
|
|
|
2021-12-10 20:22:16 +00:00
|
|
|
struct apfl_string_view
|
|
|
|
|
apfl_string_view_from_view(struct apfl_string_view view)
|
|
|
|
|
{
|
|
|
|
|
return view;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct apfl_string_view
|
|
|
|
|
apfl_string_view_from_cstr(char *cstr)
|
|
|
|
|
{
|
|
|
|
|
return (struct apfl_string_view) {
|
|
|
|
|
.bytes = cstr,
|
|
|
|
|
.len = strlen(cstr),
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct apfl_string_view
|
|
|
|
|
apfl_string_view_from_const_cstr(const char *cstr)
|
|
|
|
|
{
|
|
|
|
|
return (struct apfl_string_view) {
|
|
|
|
|
.bytes = cstr,
|
|
|
|
|
.len = strlen(cstr),
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct apfl_string_view
|
|
|
|
|
apfl_string_view_from_string(struct apfl_string string)
|
|
|
|
|
{
|
|
|
|
|
return (struct apfl_string_view) {
|
|
|
|
|
.bytes = string.bytes,
|
|
|
|
|
.len = string.len,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
apfl_string_view_cmp(struct apfl_string_view a, struct apfl_string_view b)
|
|
|
|
|
{
|
|
|
|
|
size_t n = a.len > b.len ? b.len : a.len;
|
|
|
|
|
int cmp = memcmp(a.bytes, b.bytes, n);
|
|
|
|
|
if (cmp != 0) {
|
|
|
|
|
return cmp;
|
|
|
|
|
}
|
|
|
|
|
if (a.len == b.len) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return a.len > b.len ? 1 : -1;
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-02 16:01:51 +00:00
|
|
|
struct apfl_string
|
|
|
|
|
apfl_string_blank(void)
|
|
|
|
|
{
|
|
|
|
|
return (struct apfl_string) {
|
|
|
|
|
.bytes = NULL,
|
|
|
|
|
.len = 0,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-10 20:22:16 +00:00
|
|
|
void
|
|
|
|
|
apfl_string_deinit(struct apfl_string *string)
|
|
|
|
|
{
|
|
|
|
|
free(string->bytes);
|
2022-01-02 16:01:51 +00:00
|
|
|
*string = apfl_string_blank();
|
2021-12-10 20:22:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
apfl_string_copy(struct apfl_string *dst, struct apfl_string_view src)
|
|
|
|
|
{
|
|
|
|
|
apfl_string_deinit(dst);
|
|
|
|
|
if ((dst->bytes = malloc(src.len)) == NULL) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memcpy(dst->bytes, src.bytes, src.len);
|
|
|
|
|
dst->len = src.len;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct apfl_string
|
|
|
|
|
apfl_string_move(struct apfl_string *src)
|
|
|
|
|
{
|
|
|
|
|
struct apfl_string out = *src;
|
2022-01-02 16:01:51 +00:00
|
|
|
*src = apfl_string_blank();
|
2021-12-10 20:22:16 +00:00
|
|
|
return out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
apfl_string_builder_init(struct apfl_string_builder *builder)
|
|
|
|
|
{
|
|
|
|
|
apfl_resizable_init((void **)&(builder->bytes), &(builder->len), &(builder->cap));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
apfl_string_builder_deinit(struct apfl_string_builder *builder)
|
|
|
|
|
{
|
|
|
|
|
free(builder->bytes);
|
|
|
|
|
apfl_string_builder_init(builder);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
append_bytes(struct apfl_string_builder *builder, const char *bytes, size_t len)
|
|
|
|
|
{
|
|
|
|
|
return apfl_resizable_append(
|
|
|
|
|
sizeof(char),
|
|
|
|
|
APFL_RESIZABLE_ARGS(*builder, bytes),
|
|
|
|
|
bytes,
|
|
|
|
|
len
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
apfl_string_builder_append(struct apfl_string_builder *builder, struct apfl_string_view view)
|
|
|
|
|
{
|
|
|
|
|
return append_bytes(builder, view.bytes, view.len);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
apfl_string_builder_append_byte(struct apfl_string_builder *builder, char byte)
|
|
|
|
|
{
|
|
|
|
|
return append_bytes(builder, &byte, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct apfl_string
|
|
|
|
|
apfl_string_builder_move_string(struct apfl_string_builder *builder)
|
|
|
|
|
{
|
|
|
|
|
struct apfl_string str;
|
|
|
|
|
|
|
|
|
|
str.bytes = builder->bytes;
|
|
|
|
|
str.len = builder->len;
|
|
|
|
|
|
|
|
|
|
apfl_string_builder_init(builder);
|
|
|
|
|
|
|
|
|
|
return str;
|
|
|
|
|
}
|
2022-01-02 16:55:05 +00:00
|
|
|
|
2022-01-04 20:22:46 +00:00
|
|
|
struct apfl_string_view
|
|
|
|
|
apfl_string_view_from_refcounted_string(apfl_refcounted_string rcstring)
|
2022-01-02 16:55:05 +00:00
|
|
|
{
|
2022-01-04 20:22:46 +00:00
|
|
|
if (rcstring == NULL) {
|
|
|
|
|
return apfl_string_view_from(apfl_string_blank());
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-02 16:55:05 +00:00
|
|
|
return apfl_string_view_from(rcstring->string);
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-04 20:22:46 +00:00
|
|
|
apfl_refcounted_string
|
2022-01-02 16:55:05 +00:00
|
|
|
apfl_string_move_into_new_refcounted(struct apfl_string *src)
|
|
|
|
|
{
|
2022-01-04 20:22:46 +00:00
|
|
|
apfl_refcounted_string dst = ALLOC(struct apfl_refcounted_string_data);
|
2022-01-02 16:55:05 +00:00
|
|
|
if (dst == NULL) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-04 20:22:46 +00:00
|
|
|
*dst = (struct apfl_refcounted_string_data) {
|
2022-01-02 16:55:05 +00:00
|
|
|
.refcount = 1,
|
|
|
|
|
.string = apfl_string_move(src),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return dst;
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-04 20:22:46 +00:00
|
|
|
apfl_refcounted_string
|
|
|
|
|
apfl_refcounted_string_incref(apfl_refcounted_string rcstring)
|
2022-01-02 16:55:05 +00:00
|
|
|
{
|
2022-01-04 20:22:46 +00:00
|
|
|
if (rcstring != NULL) {
|
|
|
|
|
rcstring->refcount++;
|
2022-01-02 16:55:05 +00:00
|
|
|
}
|
2022-01-04 20:22:46 +00:00
|
|
|
return rcstring;
|
2022-01-02 16:55:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2022-01-04 20:22:46 +00:00
|
|
|
apfl_refcounted_string_unref(apfl_refcounted_string rcstring)
|
2022-01-02 16:55:05 +00:00
|
|
|
{
|
2022-01-04 20:22:46 +00:00
|
|
|
if (rcstring != NULL && apfl_refcount_dec(&rcstring->refcount)) {
|
2022-01-02 16:55:05 +00:00
|
|
|
apfl_string_deinit(&rcstring->string);
|
2022-01-04 20:22:46 +00:00
|
|
|
free(rcstring);
|
2022-01-02 16:55:05 +00:00
|
|
|
}
|
|
|
|
|
}
|