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.
89 lines
2.0 KiB
C
89 lines
2.0 KiB
C
#pragma once
|
|
|
|
#include <stdlib.h>
|
|
#include <stdbool.h>
|
|
#include <string.h>
|
|
|
|
#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;
|
|
|
|
len = strnlen(ptr, maxlen);
|
|
return sv_from_parts(ptr, len);
|
|
}
|
|
|
|
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;
|
|
}
|