Skip to content
Extraits de code Groupes Projets
Vérifiée Valider 7a01d701 rédigé par Kubat's avatar Kubat
Parcourir les fichiers

LIB: Add a simple string view implementation

parent abe5428e
Aucune branche associée trouvée
Aucune étiquette associée trouvée
1 requête de fusion!177Add the query to the `update` command to filter karas to update
#pragma once
struct strv {
int count;
const char *data;
};
#define STRV_STATIC(str) \
{ \
.count = sizeof(str) - 1, .data = (str), \
}
/* Create the NULL/empty string view */
#define STRV_NULL strv_from_slice(NULL, 0)
#define STRV_FMT "%.*s" /* Format string for a string view */
#define STRV_ARG(sv) ((sv).count), ((sv).data) /* Unpack the string view */
#define STRV_DEF __attribute__((unused)) static
/* Create a string view from a slice or a C string. */
STRV_DEF struct strv strv_from_slice(const char *data, int count);
STRV_DEF struct strv strv_from_str(const char *);
/* Copy a string view */
STRV_DEF struct strv strv_copy(const struct strv sv);
/* Copy back a string view to a C string */
STRV_DEF _Bool strv_as_str(const struct strv, char *data, int len);
/* Convert strv to an integet, in decimal notation */
STRV_DEF int strv_to_int(const struct strv);
/* Get the length of the string view */
STRV_DEF int strv_len(struct strv sv);
/* Different ways of trimming the strings */
STRV_DEF struct strv strv_trim_l(struct strv);
STRV_DEF struct strv strv_trim_r(struct strv);
STRV_DEF struct strv strv_trim(struct strv);
STRV_DEF struct strv strv_take_left_while(struct strv, _Bool (*)(char));
STRV_DEF struct strv strv_chop_by_delim(struct strv *, char);
STRV_DEF _Bool strv_try_chop_by_delim(struct strv *, char delim, struct strv *chunk);
STRV_DEF struct strv strv_chop_left(struct strv *, int);
STRV_DEF struct strv strv_chop_right(struct strv *, int);
STRV_DEF struct strv strv_chop_left_while(struct strv *, _Bool (*)(char));
/* Find substrings or characters in a string view. Returns 1 if found, 0
* otherwise. For the index_of function the index of the character is placed
* inside `index` if the pointer is not NULL. */
STRV_DEF _Bool strv_index_of(struct strv sv, char c, int *index);
STRV_DEF _Bool strv_starts_with(struct strv sv, struct strv prefix);
STRV_DEF _Bool strv_ends_with(struct strv sv, struct strv suffix);
/* Compare two string views */
STRV_DEF _Bool strv_equal(struct strv a, struct strv b);
STRV_DEF _Bool strv_equal_nocase(struct strv a, struct strv b);
/* Private implementation of some functions to not include some headers */
static inline char
strv_ctoupper(char s)
{
return (('a' <= s) && (s <= 'z')) ? 'A' + (s - 'a') : s;
}
static inline char
strv_ctolower(char s)
{
return (('A' <= s) && (s <= 'Z')) ? 'a' + (s - 'A') : s;
}
static inline _Bool
strv_memcmp(const void *ptr2, const void *ptr1, int count)
{
register const unsigned char *s1 = (const unsigned char *)ptr1;
register const unsigned char *s2 = (const unsigned char *)ptr2;
while (count-- > 0) {
if (*s1++ != *s2++)
return (_Bool)0;
}
return (_Bool)1;
}
static inline _Bool
strv_isspace(char x)
{
return x == ' ' || x == '\t' || x == '\n' || x == '\r' || x == '\v' || x == '\f';
}
static inline int
strv_strlen(const char *str)
{
int len = 0;
while (str[len]) {
len += 1;
/* Try to avoid overflows */
if (len == __INT_MAX__)
return 0;
}
return len;
}
/* Implementation of the functions */
static struct strv
strv_from_slice(const char *data, int count)
{
struct strv sv;
sv.count = count;
sv.data = data;
return sv;
}
static struct strv
strv_from_str(const char *cstr)
{
return strv_from_slice(cstr, strv_strlen(cstr));
}
static _Bool
strv_as_str(const struct strv sv, char *data, int len)
{
if (sv.count >= len)
return (_Bool)0;
for (int i = 0; i < sv.count; ++i)
data[i] = sv.data[i];
data[sv.count] = '\0';
return (_Bool)1;
}
static struct strv
strv_trim_l(struct strv sv)
{
int i = 0;
while ((i < sv.count) && strv_isspace(sv.data[i]))
i += 1;
return strv_from_slice(sv.data + i, sv.count - i);
}
static struct strv
strv_trim_r(struct strv sv)
{
int i = 0;
while ((i < sv.count) && strv_isspace(sv.data[sv.count - 1 - i]))
i += 1;
return strv_from_slice(sv.data, sv.count - i);
}
static struct strv
strv_trim(struct strv sv)
{
return strv_trim_r(strv_trim_l(sv));
}
static struct strv
strv_chop_left(struct strv *sv, int n)
{
if (n > sv->count)
n = sv->count;
struct strv result = strv_from_slice(sv->data, n);
sv->data += n;
sv->count -= n;
return result;
}
static struct strv
strv_chop_right(struct strv *sv, int n)
{
if (n > sv->count)
n = sv->count;
struct strv result = strv_from_slice(sv->data + sv->count - n, n);
sv->count -= n;
return result;
}
static _Bool
strv_index_of(struct strv sv, char c, int *index)
{
int i = 0;
while (i < sv.count && sv.data[i] != c)
i += 1;
if (i < sv.count) {
if (index)
*index = i;
return (_Bool)1;
}
else
return (_Bool)0;
}
static _Bool
strv_try_chop_by_delim(struct strv *sv, char delim, struct strv *chunk)
{
int i = 0;
while (i < sv->count && sv->data[i] != delim)
i += 1;
struct strv result = strv_from_slice(sv->data, i);
if (i < sv->count) {
i += 1;
sv->count -= i;
sv->data += i;
if (chunk)
*chunk = result;
return (_Bool)1;
}
return (_Bool)0;
}
static struct strv
strv_chop_by_delim(struct strv *sv, char delim)
{
int i = 0;
while (i < sv->count && sv->data[i] != delim)
i += 1;
const struct strv result = strv_from_slice(sv->data, i);
i += (i < sv->count);
sv->count -= i;
sv->data += i;
return result;
}
static _Bool
strv_starts_with(struct strv sv, struct strv expected_prefix)
{
if (expected_prefix.count <= sv.count) {
const struct strv actual_prefix = strv_from_slice(sv.data, expected_prefix.count);
return strv_equal(expected_prefix, actual_prefix);
}
return (_Bool)0;
}
static _Bool
strv_ends_with(struct strv sv, struct strv expected_suffix)
{
if (expected_suffix.count <= sv.count) {
const struct strv actual_suffix =
strv_from_slice(sv.data + sv.count - expected_suffix.count, expected_suffix.count);
return strv_equal(expected_suffix, actual_suffix);
}
return (_Bool)0;
}
static _Bool
strv_equal(struct strv a, struct strv b)
{
return (a.count != b.count) ? (_Bool)0 : strv_memcmp(a.data, b.data, a.count);
}
static _Bool
strv_equal_nocase(struct strv a, struct strv b)
{
if (a.count != b.count) return (_Bool)0;
for (int i = 0; i < a.count; ++i) {
if (strv_ctoupper(a.data[i]) != strv_ctoupper(b.data[i]))
return (_Bool)0;
}
return (_Bool)1;
}
static struct strv
strv_chop_left_while(struct strv *sv, _Bool (*cb)(char))
{
int i = 0;
while ((i < sv->count) && cb(sv->data[i]))
i += 1;
return strv_chop_left(sv, i);
}
static struct strv
strv_take_left_while(struct strv sv, _Bool (*cb)(char))
{
int i = 0;
while ((i < sv.count) && cb(sv.data[i]))
i += 1;
return strv_from_slice(sv.data, i);
}
static int
strv_len(struct strv sv)
{
return sv.count;
}
static struct strv
strv_copy(const struct strv sv)
{
return (struct strv) { .data = sv.data, .count = sv.count };
}
static int
strv_to_int(const struct strv sv_init)
{
if (strv_len(sv_init) == 0)
return 0;
int total = 0;
struct strv sv = strv_copy(sv_init);
const _Bool negative = strv_chop_left(&sv, 1).data[0] == '-';
for (int i = 0; i < sv.count; ++i)
total = (total * 10) + (sv.data[i] - '0');
return (negative) ? -1 * total : total;
}
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Veuillez vous inscrire ou vous pour commenter