various utils

main
pantonshire 2 months ago
parent 3851b60310
commit 45284910cc

@ -0,0 +1,6 @@
#pragma once
struct eventloop;
struct eventloop *eventloop_new(void);
void eventloop_free(struct eventloop *el);

@ -0,0 +1,21 @@
#pragma once
#include <unistd.h>
#include <sys/socket.h>
#include "scoped.h"
static inline void _close_if_nonnegative(int fd) {
if (fd >= 0)
close(fd);
}
DEF_SCOPED_TYPE(fd, int, -1, _close_if_nonnegative)
#define FD_SCOPED(VAL) SCOPED(fd, int, VAL)
#define FD_CLOSE(FD) _scoped_fd_cleanup(FD)
#define FD_RELEASE(FD) _scoped_fd_release(FD)
static inline int setsockopt_int(int fd, int level, int option, int val) {
return setsockopt(fd, level, option, &val, sizeof(val));
}

@ -0,0 +1,11 @@
#pragma once
#include <stdlib.h>
#include "scoped.h"
DEF_SCOPED_TYPE(mem, void *, NULL, free)
#define MEM_SCOPED(TYPE, VAL) SCOPED(mem, TYPE *, VAL)
#define MEM_FREE(TYPE, MEM) ({ CHECK_TYPE(TYPE **, MEM), (TYPE *)_scoped_mem_cleanup((void **)(MEM)); })
#define MEM_RELEASE(TYPE, MEM) ({ CHECK_TYPE(TYPE **, MEM), (TYPE *)_scoped_mem_release((void **)(MEM)); })

@ -0,0 +1,29 @@
#pragma once
#define CHECK_TYPE(TYPE, VAL) ({ \
typedef void (*_check_type_dummy_fn_t)(TYPE); \
_check_type_dummy_fn_t _check_type_dummy_fn = (_check_type_dummy_fn_t)NULL; \
if (0) \
_check_type_dummy_fn(VAL); \
1; \
})
#define DEF_SCOPED_TYPE(NAME, TYPE, UNOCCUPIED, CLEANUP_FN) \
static inline TYPE _scoped_##NAME##_unoccupied(void) { \
return (UNOCCUPIED); \
} \
static inline void _scoped_##NAME##_cleanup(TYPE *_val) { \
CLEANUP_FN(*_val); \
*_val = (UNOCCUPIED); \
} \
static inline void _scoped_##NAME##_cleanup_raw(void *_val) { \
_scoped_##NAME##_cleanup((TYPE *)_val); \
} \
static inline TYPE _scoped_##NAME##_release(TYPE *_val) { \
TYPE _released = *_val; \
*_val = (UNOCCUPIED); \
return _released; \
}
#define SCOPED(NAME, TYPE, VAL) \
TYPE VAL __attribute__((cleanup(_scoped_##NAME##_cleanup_raw))) = _scoped_##NAME##_unoccupied()

@ -1,22 +1,60 @@
#pragma once
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#define SV_LIT(S) (S "LITERAL_CHECK", (str_view_t) { S, sizeof(S) - 1 })
#define SV_LIT(S) ((void)(S "LITERAL_CHECK"), (str_view_t) { S, sizeof(S) - 1 })
#define SV_NULL ((str_view_t) { NULL, 0 })
#define SB_NULL ((str_buf_t) { NULL, 0 })
#define SB_SCOPED(NAME) str_buf_t NAME __attribute__((cleanup(sb_free))) = SB_NULL
#define SV_PRI "%.*s"
#define SV_PRI_ARGS(S) (int)((S).len), (S).ptr
// String which is:
// - Not owned
// - Not necessarily heap-allocated
// - Not necessarily nul-terminated
typedef struct {
const char *ptr;
size_t len;
} str_view_t;
// String which is:
// - Owned
// - Heap-allocated
// - Nul-terminated
// The length does not include the nul terminator.
typedef struct {
char *ptr;
size_t len;
} str_buf_t;
static inline bool sv_is_null(str_view_t s) {
return !s.ptr;
}
static inline bool sv_is_empty(str_view_t s) {
return !s.len;
}
static inline bool sb_is_null(str_buf_t buf) {
return !buf.ptr;
}
static inline bool sb_is_empty(str_buf_t buf) {
return !buf.len;
}
static inline str_view_t sv_from_parts(const char *ptr, size_t len) {
return (str_view_t) { ptr, len };
}
static inline str_view_t sv_from_cstr(const char *ptr, size_t maxlen) {
size_t len = strnlen(ptr, maxlen);
size_t len;
len = strnlen(ptr, maxlen);
return sv_from_parts(ptr, len);
}
@ -24,3 +62,27 @@ static inline str_view_t sv_from_cstr_unbounded(const char *ptr) {
size_t len = strlen(ptr);
return sv_from_parts(ptr, len);
}
static inline bool sv_eq(str_view_t s1, str_view_t s2) {
return (s1.len == s2.len) && ((!s1.ptr || !s2.ptr)
? (s1.ptr == s2.ptr)
: !memcmp(s1.ptr, s2.ptr, s1.len));
}
static inline str_view_t sv_substr(str_view_t s, size_t start, size_t end) {
if ((start > end) || (start > s.len) || (end > s.len))
return SV_NULL;
return sv_from_parts(s.ptr + start, end - start);
}
static inline str_view_t sb_view(str_buf_t buf) {
return sv_from_parts(buf.ptr, buf.len);
}
str_buf_t sb_from_sv(str_view_t s);
static inline void sb_free(str_buf_t *buf) {
free(buf->ptr);
buf->ptr = NULL;
buf->len = 0;
}

@ -8,6 +8,8 @@ sources = [
'src/main.c',
'src/server.c',
'src/client.c',
'src/str.c',
'src/eventloop.c',
]
includes = include_directories('include')

@ -0,0 +1,28 @@
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include "eventloop.h"
#include "mem.h"
struct eventloop {
int kqueue_fd;
};
struct eventloop *eventloop_new(void) {
MEM_SCOPED(struct eventloop, el);
if (!(el = malloc(sizeof(struct eventloop)))) {
errno = ENOMEM;
return NULL;
}
return MEM_RELEASE(struct eventloop, &el);
}
void eventloop_free(struct eventloop *el) {
if (!el)
return;
close(el->kqueue_fd);
free(el);
}

@ -0,0 +1,18 @@
#include <stdlib.h>
#include <string.h>
#include "str.h"
str_buf_t sb_from_sv(str_view_t s) {
char *buf;
if (sv_is_null(s) || sv_is_empty(s))
return SB_NULL;
if (!(buf = malloc(s.len + 1)))
return SB_NULL;
memcpy(buf, s.ptr, s.len);
buf[s.len] = 0;
return (str_buf_t) { buf, s.len };
}
Loading…
Cancel
Save