~crm/cstring

84348c13c16f391e9f9595d7c786e6de05ce8f08 — Christos Margiolis 3 years ago d2a6d68
added data function, added static inline declarations, still pending erase fix
4 files changed, 112 insertions(+), 67 deletions(-)

M cstring.3
M cstring.c
M cstring.h
M tests/test.c
M cstring.3 => cstring.3 +3 -0
@@ 154,6 154,9 @@ Check to see if string starts with
Check to see if string ends with
.I c
.TP
.BR void\ *cstring_data(const\ cstring\ *cs)
Get raw bytes of string's content.
.TP
.BR char\ *cstring_copy(const\ char\ *s)
Make a copy of a given
.I const\ char\ *

M cstring.c => cstring.c +51 -33
@@ 2,39 2,32 @@

#define CSTRING_EXCEEDS_CAPACITY(len, cap)  ((len) >= (cap))

#define CSTRING_FIND_OCCURENCE(cs, s, func) do {                          \
    char *_found;                                                         \
    if ((_found = func(cs->str, (s))) != NULL)                            \
        return (_found - cs->str);                                        \
#define CSTRING_FIND_OCCURENCE(cs, s, func) do {                            \
    char *_found;                                                           \
    if ((_found = func(cs->str, (s))) != NULL)                              \
        return (_found - cs->str);                                          \
} while (0)

#ifdef CSTRING_DBG
#define CSTRING_FREE(cs) do {                                             \
    CSTRING_DBG_LOG("Before CSTRING_FREE: %s\n", cs->str);                \
    if (!cstring_empty(cs))                                               \
        free(cs->str);                                                    \
#define CSTRING_FREE(cs) do {                                               \
    CSTRING_DBG_LOG("Before CSTRING_FREE: %s\n", cs->str);                  \
    if (!cstring_empty(cs))                                                 \
        free(cs->str);                                                      \
} while (0)

/* Might move above erase functions */
#define CSTRING_EXPECTED_ERASE_STR(cs, pos, len) do {                     \
    CSTRING_DBG_LOG("%s", "CSTRING_EXPECTED_ERASE_STR: ");                \
    size_t _i;                                                            \
    for (_i = 0; _i < (pos); _i++)                                        \
        printf("%c", cs->str[_i]);                                        \
    for (_i = (pos) + (len); _i < cs->len; _i++)                          \
        printf("%c", cs->str[_i]);                                        \
    printf("\n");                                                         \
} while (0)

#define CSTRING_EXPECTED_ERASE_LEN(cs, len)                               \
    CSTRING_DBG_LOG("CSTRING_EXPECTED_ERASE_LEN: %ld\n", cs->len - len)
#else
#define CSTRING_FREE(cs) do {                                             \
    if (!cstring_empty(cs))                                               \
        free(cs->str);                                                    \
#else /* !CSTRING_DBG */
#define CSTRING_FREE(cs) do {                                               \
    if (!cstring_empty(cs))                                                 \
        free(cs->str);                                                      \
} while (0)
#endif /* CSTRING_DBG */

/* statics */
static int cstring_is_one_of(char, const char *);
static inline int cstring_cmp_greater(const void *, const void *);
static inline int cstring_cmp_less(const void *, const void *);
static inline int cstring_cmp_char_greater(const void *, const void *);
static inline int cstring_cmp_char_less(const void *, const void *);

static int
cstring_is_one_of(char c, const char *s)
{


@@ 68,6 61,7 @@ cstring_cmp_char_less(const void *lhs, const void *rhs)
    return (*(char *)lhs < *(char *)rhs);
}

/* externs */
cstring
cstring_create(const char *s)
{


@@ 129,6 123,21 @@ cstring_insert(cstring *cs, const char *s, size_t i)
    }
}

#ifdef CSTRING_DBG
#define CSTRING_DBG_EXPECTED_ERASE_STR(cs, pos, len) do {                   \
    CSTRING_DBG_LOG("%s", "CSTRING_DBG_EXPECTED_ERASE_STR: ");              \
    size_t _i;                                                              \
    for (_i = 0; _i < (pos); _i++)                                          \
        printf("%c", cs->str[_i]);                                          \
    for (_i = (pos) + (len); _i < cs->len; _i++)                            \
        printf("%c", cs->str[_i]);                                          \
    printf("\n");                                                           \
} while (0)

#define CSTRING_DBG_EXPECTED_ERASE_LEN(cs, len)                             \
    CSTRING_DBG_LOG("CSTRING_DBG_EXPECTED_ERASE_LEN: %ld\n", cs->len - len)
#endif /* CSTRING_DBG */

void
cstring_erase(cstring *cs, size_t pos, size_t len)
{


@@ 138,8 147,8 @@ cstring_erase(cstring *cs, size_t pos, size_t len)
    {
#ifdef CSTRING_DBG
        CSTRING_DBG_LOG("STR: %s | INDEX: %ld | LEN: %ld\n", cs->str, pos, len);
        CSTRING_EXPECTED_ERASE_STR(cs, pos, len);
        CSTRING_EXPECTED_ERASE_LEN(cs, len);
        CSTRING_DBG_EXPECTED_ERASE_STR(cs, pos, len);
        CSTRING_DBG_EXPECTED_ERASE_LEN(cs, len);
#endif /* CSTRING_DBG */
        size_t newlen = cs->len - len;
        char *tmp;


@@ 182,6 191,11 @@ cstring_trim(cstring *cs, const char *s)
        cstring_erase(cs, i, 1);
}

#ifdef CSTRING_DBG
#undef CSTRING_DBG_EXPECTED_ERASE_STR
#undef CSTRING_DBG_EXPECTED_ERASE_LEN
#endif /* CSTRING_DBG */

void
cstring_push_back(cstring *cs, char c)
{


@@ 308,7 322,8 @@ cstring_rfind(const cstring *cs, const char *s)
                break;
            }
        }
        if (found) idx = i;
        if (found)
            idx = i;
    }
    return (idx == -1 ? CSTRING_NPOS : idx);
}


@@ 377,10 392,11 @@ cstring_resize(cstring *cs, size_t newcapacity)
            cs->capacity, newcapacity);
#endif /* CSTRING_DBG */
    char *tmp;
    CSTRING_MALLOC(tmp, newcapacity);
    memcpy(tmp, cs->str, cs->len + 1); /* copy \0 too */
    CSTRING_MALLOC(tmp, newcapacity + 1); /* no +1? */
    memcpy(tmp, cs->str, cs->len + 1);    /* copy \0 too */
    CSTRING_FREE(cs);
    cs->str = tmp;
    cs->str[cs->len] = '\0';
    cs->capacity = newcapacity;
#ifdef CSTRING_DBG
    CSTRING_DBG_LOG_CSTR_INFO(cs);


@@ 393,8 409,10 @@ cstring_getline(FILE *fd, cstring *cs, char delim)
    char c;
    cstring_clear(cs);
    while ((c = fgetc(fd)) != EOF && c != '\n') {
        if (c == delim) break;
        else cstring_push_back(cs, c);
        if (c == delim)
            break;
        else
            cstring_push_back(cs, c);
    }
    return (c == EOF) ? NULL : cs;
}

M cstring.h => cstring.h +56 -33
@@ 36,9 36,9 @@ extern "C" {
#endif /* CSTRING_DBG */

typedef struct cstring {
    char   *str;
    size_t  len;
    size_t  capacity;
    char     *str;
    size_t    len;
    size_t    capacity;
} cstring;

enum cstring_flags {


@@ 47,36 47,53 @@ enum cstring_flags {
    CSTRING_CALLBACK
};

extern cstring  cstring_create(const char *);
extern void     cstring_delete(cstring *);
extern void     cstring_assign(cstring *, const char *);
extern void     cstring_insert(cstring *, const char *, size_t);
extern void     cstring_erase(cstring *, size_t, size_t);
extern void     cstring_erase_matching(cstring *, const char *);
extern void     cstring_erase_all_matching(cstring *, const char *);
extern void     cstring_trim(cstring *, const char *);
extern void     cstring_push_back(cstring *, char);
extern void     cstring_pop_back(cstring *);
extern void     cstring_replace_char(cstring *, size_t, char);
extern void     cstring_replace_str(cstring *, const char *, size_t, size_t);
extern cstring  cstring_substr(const cstring *, size_t, size_t);
extern void     cstring_swap(cstring *, cstring *);
extern void     cstring_sort(cstring **, size_t, enum cstring_flags,
                             int (*)(const void *, const void *));
extern void     cstring_sort_chars(cstring *cs, enum cstring_flags,
                                   int (*)(const void *, const void *));
extern void     cstring_clear(cstring *);
extern size_t   cstring_find(const cstring *, const char *);
extern size_t   cstring_rfind(const cstring *, const char *);
extern size_t   cstring_find_first_of(const cstring *, const char *);
extern size_t   cstring_find_first_not_of(const cstring *,const  char *);
extern size_t   cstring_find_last_of(const cstring *, const char *);
extern size_t   cstring_find_last_not_of(const cstring *, const char *);
extern char    *cstring_copy(const char *);
extern void     cstring_resize(cstring *, size_t);
extern cstring *cstring_getline(FILE *, cstring *, char);

/* inlines */
extern cstring    cstring_create(const char *);
extern void       cstring_delete(cstring *);
extern void       cstring_assign(cstring *, const char *);
extern void       cstring_insert(cstring *, const char *, size_t);
extern void       cstring_erase(cstring *, size_t, size_t);
extern void       cstring_erase_matching(cstring *, const char *);
extern void       cstring_erase_all_matching(cstring *, const char *);
extern void       cstring_trim(cstring *, const char *);
extern void       cstring_push_back(cstring *, char);
extern void       cstring_pop_back(cstring *);
extern void       cstring_replace_char(cstring *, size_t, char);
extern void       cstring_replace_str(cstring *, const char *, size_t, size_t);
extern cstring    cstring_substr(const cstring *, size_t, size_t);
extern void       cstring_swap(cstring *, cstring *);
extern void       cstring_sort(cstring **, size_t, enum cstring_flags,
                               int (*)(const void *, const void *));
extern void       cstring_sort_chars(cstring *cs, enum cstring_flags,
                                     int (*)(const void *, const void *));
extern void       cstring_clear(cstring *);
extern size_t     cstring_find(const cstring *, const char *);
extern size_t     cstring_rfind(const cstring *, const char *);
extern size_t     cstring_find_first_of(const cstring *, const char *);
extern size_t     cstring_find_first_not_of(const cstring *,const  char *);
extern size_t     cstring_find_last_of(const cstring *, const char *);
extern size_t     cstring_find_last_not_of(const cstring *, const char *);
extern char      *cstring_copy(const char *);
extern void       cstring_resize(cstring *, size_t);
extern cstring   *cstring_getline(FILE *, cstring *, char);

/* static inlines */
static inline void    cstring_prepend(cstring *, const char *);
static inline void    cstring_append(cstring *, const char *);
static inline void    cstring_shrink_to_fit(cstring *);
static inline int     cstring_empty(const cstring *);
static inline char    cstring_front(const cstring *);
static inline char    cstring_back(const cstring *);
static inline int     cstring_starts_with_str(const cstring *, const char *);
static inline int     cstring_ends_with_str(const cstring *, const char *);
static inline int     cstring_starts_with_char(const cstring *, char);
static inline int     cstring_ends_with_char(const cstring *, char);
static inline void   *cstring_data(const cstring *);
static inline int     cstring_equal(const cstring *, const cstring *);
static inline int     cstring_greater(const cstring *, const cstring *);
static inline int     cstring_greater_or_equal(const cstring *, const cstring *);
static inline int     cstring_less(const cstring *, const cstring *);
static inline int     cstring_less_or_equal(const cstring *, const cstring *);

static inline void
cstring_prepend(cstring *cs, const char *s)
{


@@ 137,6 154,12 @@ cstring_ends_with_char(const cstring *cs, char c)
    return (cs->str[cs->len] = c);
}

static inline void *
cstring_data(const cstring *cs)
{
    return (void *)cs->str;
}

static inline int
cstring_equal(const cstring *lhs, const cstring *rhs)
{

M tests/test.c => tests/test.c +2 -1
@@ 53,7 53,8 @@ main(int argc, char **argv)
    printf("cstring_trim: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity);

    cstring_delete(&s);
    if (cstring_empty(&s)) puts("cstring_delete: Deleted string.");
    if (cstring_empty(&s))
        puts("cstring_delete: Deleted string.");

    return 0;
}