You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

161 lines
3.2 KiB
C

/* See the end of this file for copyright and license terms. */
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include "neo/_error.h"
#include "neo/_nalloc.h"
#include "neo/_nref.h"
#include "neo/_stddef.h"
#include "neo/_types.h"
static void nbuf_destroy(struct _neo_nbuf *buf)
{
if (buf->_borrow != nil)
_neo_nput(buf->_borrow);
nfree(buf);
}
nbuf_t *nbuf_create(usize size, error *err)
{
if (size == 0) {
yeet(err, ERANGE, "Cannot create zero-size buffer");
return nil;
}
/*
* Just like with strings, we allocate 4 extra bytes.
* The buffer functions depend on this behavior, don't change.
*/
struct _neo_nbuf *buf = nalloc(sizeof(*buf) + size + 4, err);
catch(err) {
return nil;
}
byte *data = (byte *)buf + sizeof(*buf);
for (unsigned int i = 0; i < 4; i++)
data[size + i] = 0;
buf->_size = size;
buf->_data = data;
buf->_borrow = nil;
nref_init(buf, nbuf_destroy);
neat(err);
return buf;
}
nbuf_t *nbuf_from(const void *data, usize len, error *err)
{
if (data == nil) {
yeet(err, EFAULT, "Data is nil");
return nil;
}
struct _neo_nbuf *buf = nbuf_create(len, err);
catch(err) {
return nil;
}
byte *buf_data = (byte *)buf + sizeof(*buf);
memcpy(buf_data, data, len);
/* _data field already filled by nbuf_create */
return buf;
}
nbuf_t *nbuf_from_str(const char *s, error *err)
{
if (s == nil) {
yeet(err, EFAULT, "String is nil");
return nil;
}
usize size = strlen(s) + 1;
return nbuf_from(s, size, err);
}
nbuf_t *nbuf_from_nstr(nstr_t *s, error *err)
{
if (s == nil) {
yeet(err, EFAULT, "String is nil");
return nil;
}
nbuf_t *buf = nalloc(sizeof(*buf), err);
catch(err) {
return nil;
}
nget(s);
buf->_size = s->_size;
buf->_borrow = &s->__neo_nref;
buf->_data = (const byte *)s->_data;
nref_init(buf, nbuf_destroy);
return buf;
}
nbuf_t *nbuf_clone(nbuf_t *buf, error *err)
{
if (buf == nil) {
yeet(err, EFAULT, "Source buffer is nil");
return nil;
}
nbuf_t *clone = nalloc(sizeof(*clone), err);
catch(err) {
return nil;
}
nget(buf);
clone->_size = buf->_size;
clone->_borrow = &buf->__neo_nref;
clone->_data = buf->_data;
nref_init(clone, nbuf_destroy);
return clone;
}
int nbuf_cmp(const nbuf_t *buf1, const nbuf_t *buf2, error *err)
{
if (buf1 == nil) {
yeet(err, EFAULT, "First buffer is nil");
if (buf2 == nil)
return 0;
else
return -1;
}
if (buf2 == nil) {
yeet(err, EFAULT, "Second buffer is nil");
return 1;
}
neat(err);
if (buf1->_data == buf2->_data)
return 0;
/*
* Extra byte because the two buffers might be of different size
* (one of the reasons nbuf_create() allocates 4 bytes more than needed)
*/
usize maxbytes = nmin(nlen(buf1), nlen(buf2)) + 1;
return memcmp(&buf1->_data[0], &buf2->_data[0], maxbytes);
}
/*
* This file is part of libneo.
* Copyright (c) 2021 Fefie <owo@fef.moe>.
*
* libneo is non-violent software: you may only use, redistribute,
* and/or modify it under the terms of the CNPLv6+ as found in
* the LICENSE file in the source code root directory or at
* <https://git.pixie.town/thufie/CNPL>.
*
* libneo comes with ABSOLUTELY NO WARRANTY, to the extent
* permitted by applicable law. See the CNPLv6+ for details.
*/