nstr: Make cloning zero-copy
This commit is contained in:
parent
d504786bc7
commit
cf4bd2ea5b
5 changed files with 42 additions and 18 deletions
|
@ -109,7 +109,7 @@ nstr_t *u2nstr(u64 u, int radix, error *err);
|
|||
* @param err: Error pointer
|
||||
* @returns The duplicated string, unless an error occurred
|
||||
*/
|
||||
nstr_t *nstrdup(const nstr_t *s, error *err);
|
||||
nstr_t *nstrdup(nstr_t *s, error *err);
|
||||
|
||||
/**
|
||||
* Repeat a string `n` times and return the new string.
|
||||
|
@ -123,7 +123,7 @@ nstr_t *nstrdup(const nstr_t *s, error *err);
|
|||
* @param err: Error pointer
|
||||
* @returns A new string with the repeated content, unless an error occurred
|
||||
*/
|
||||
nstr_t *nstrmul(const nstr_t *s, usize n, error *err);
|
||||
nstr_t *nstrmul(nstr_t *s, usize n, error *err);
|
||||
|
||||
/**
|
||||
* Create a string considting of `n` repetitions of `c`.
|
||||
|
@ -205,6 +205,9 @@ nstr_t *leftpad(const nstr_t *s, usize length, nchar fill, error *err);
|
|||
*__pos != '\0' && (err) != nil && (err)->_number + 1 < 2; \
|
||||
__pos += utf8_to_nchr(cursor, __pos, err))
|
||||
|
||||
/** Internal callback for nref */
|
||||
void _neo_nstr_destroy(nstr_t *s);
|
||||
|
||||
/*
|
||||
* This file is part of libneo.
|
||||
* Copyright (c) 2021 Fefie <owo@fef.moe>.
|
||||
|
|
|
@ -80,7 +80,12 @@ struct _neo_nstr {
|
|||
NREF_FIELD;
|
||||
/* physical size in bytes, including the four NUL terminators */
|
||||
usize _size;
|
||||
char *_data;
|
||||
/**
|
||||
* If this string was cloned or converted from a buffer, this points to
|
||||
* the original structure's refcounter. Otherwise, it is nil.
|
||||
*/
|
||||
nref_t *_borrow;
|
||||
const char *_data;
|
||||
};
|
||||
typedef struct _neo_nstr nstr_t;
|
||||
|
||||
|
|
|
@ -14,12 +14,14 @@
|
|||
#include "neo/_types.h"
|
||||
#include "neo/utf.h"
|
||||
|
||||
static void nstr_destroy(nstr_t *str)
|
||||
void _neo_nstr_destroy(nstr_t *str)
|
||||
{
|
||||
if (str->_borrow != nil)
|
||||
_neo_nput(str->_borrow);
|
||||
nfree(str);
|
||||
}
|
||||
|
||||
static nstr_t *nstr_unsafe(const char *restrict s, usize size_without_nul, error *err)
|
||||
static nstr_t *nstr_unsafe(const char *s, usize size_without_nul, error *err)
|
||||
{
|
||||
usize len = utf8_ncheck(s, size_without_nul, err);
|
||||
catch(err) {
|
||||
|
@ -49,16 +51,16 @@ static nstr_t *nstr_unsafe(const char *restrict s, usize size_without_nul, error
|
|||
* stored immediately after the string itself. This also saves us an
|
||||
* additional memory allocation.
|
||||
*/
|
||||
str->_data = (char *)str + sizeof(*str);
|
||||
str->_len = len;
|
||||
str->_size = size_without_nul + 4;
|
||||
nref_init(str, nstr_destroy);
|
||||
char *data = (char *)str + sizeof(*str);
|
||||
memcpy(data, s, size_without_nul);
|
||||
for (unsigned int i = 0; i < 4; i++)
|
||||
data[size_without_nul + i] = '\0';
|
||||
|
||||
memcpy(str->_data, s, size_without_nul);
|
||||
str->_data[size_without_nul] = '\0';
|
||||
str->_data[size_without_nul + 1] = '\0';
|
||||
str->_data[size_without_nul + 2] = '\0';
|
||||
str->_data[size_without_nul + 3] = '\0';
|
||||
str->_data = data;
|
||||
str->_len = len;
|
||||
str->_borrow = nil;
|
||||
str->_size = size_without_nul + 4;
|
||||
nref_init(str, _neo_nstr_destroy);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
@ -97,7 +99,7 @@ nchar nchrat(const nstr_t *s, usize index, error *err)
|
|||
return '\0';
|
||||
}
|
||||
|
||||
char *ptr = s->_data;
|
||||
const char *ptr = s->_data;
|
||||
while (index != 0)
|
||||
index -= (*ptr++ & 0xc0) != 0x80;
|
||||
ptr--;
|
||||
|
|
|
@ -3,17 +3,31 @@
|
|||
#include <errno.h>
|
||||
|
||||
#include "neo/_error.h"
|
||||
#include "neo/_nalloc.h"
|
||||
#include "neo/_nref.h"
|
||||
#include "neo/_nstr.h"
|
||||
#include "neo/_types.h"
|
||||
|
||||
nstr_t *nstrdup(const nstr_t *s, error *err)
|
||||
nstr_t *nstrdup(nstr_t *s, error *err)
|
||||
{
|
||||
if (s == nil) {
|
||||
yeet(err, EFAULT, "String is nil");
|
||||
return nil;
|
||||
}
|
||||
|
||||
return nstr(s->_data, err);
|
||||
nstr_t *copy = nalloc(sizeof(*copy), err);
|
||||
catch(err) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
nget(s);
|
||||
|
||||
copy->_len = s->_len;
|
||||
copy->_size = s->_size;
|
||||
copy->_borrow = &s->__neo_nref;
|
||||
copy->_data = s->_data;
|
||||
nref_init(copy, _neo_nstr_destroy);
|
||||
return copy;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#include "neo/_types.h"
|
||||
#include "neo/utf.h"
|
||||
|
||||
nstr_t *nstrmul(const nstr_t *s, usize n, error *err)
|
||||
nstr_t *nstrmul(nstr_t *s, usize n, error *err)
|
||||
{
|
||||
if (s == nil) {
|
||||
yeet(err, EFAULT, "String is nil");
|
||||
|
|
Loading…
Reference in a new issue