Skip to content
Extraits de code Groupes Projets

Add the query to the `update` command to filter karas to update

Fusionnées Kubat a demandé de fusionner dev-kubat vers master
1 file
+ 321
0
Comparer les modifications
  • Côte à côte
  • En ligne
+ 321
0
 
#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;
 
}
Chargement en cours