/* Routines for string processing. *_ext_* functions are provided for foreign strings we're not in control of. */ #ifndef COM_STR_H #define COM_STR_H #include "def.h" #include #include #define COM_STR_GROWABLE (1 << 0) /* Data can grow and be reallocated. */ #define COM_STR_STACK (1 << 1) /* Stack residing. */ #define COM_STR_SUB (1 << 2) /* Substring of an existing one. */ #define COM_STR_NULL_TERMINATED (1 << 3) /* Whether there's NULL at last. */ /* Internal strings are assumed to have vectorizable alignment. */ /* Instead of growing strings on joining we implement ropes. */ typedef struct com_str { struct com_str *next; /* Actual size is +1, to fit NULL terminator. */ uint32_t len; uint32_t flags; char data[] __attribute__((aligned(COM_DEF_ALIGNMENT))); } com_str; /* NOTE: Have to be moved to static or global memory. */ #define com_str_lit(p_l) {NULL, sizeof(p_l) - 1, COM_STR_NULL_TERMINATED, (p_l)} static inline uint32_t com_str_ext_len(char const *s) { char const *p = s; for (; *p != 0; ++p) { } return p - s; } /* Returns index of a char or -1 if it's not found. */ static inline int32_t com_str_ext_find_char(char const *s, char ch) { for (char const *p = s; *p != 0; ++p) if (*p == ch) return p - s; return -1; } /* Returns true if string 'a' is prefixed by 'b'. */ static inline bool com_str_ext_prefixed(char const *__restrict a, struct com_str prefix) { uint32_t n = prefix.len; char *b = prefix.data; while (n && *a && (*a == *b)) { ++a; ++b; --n; } return n == 0; } #endif