~crm/cstring

22060bd2333f19c4dbd47606a9bedddcf4b2a9ab — Christos Margiolis 3 years ago e86d615
added debug mode and macros, still pending push_back/resize fix
5 files changed, 84 insertions(+), 15 deletions(-)

M Makefile
M cstring.3
M cstring.c
M cstring.h
M tests/test.c
M Makefile => Makefile +2 -2
@@ 12,7 12,7 @@ AR = ar
ARFLAGS = rs
CC = gcc
CPPFLAGS += -Iinclude -pedantic
CFLAGS += -Wall -std=c99 -O3
CFLAGS += -Wall -std=c99 -O3 -DCSTRING_DBG
LDFLAGS += -Llib
#LDLIBS += 



@@ 39,7 39,7 @@ install: all
	${CP} ${MAN3} ${DESTDIR}${MAN_DIR}
	chmod 644 ${DESTDIR}${MAN_DIR}/${MAN3}

uninstall: all
uninstall:
	sudo ${RM} ${DESTDIR}${HDR_DIR}/${LIB}.h
	sudo ${RM} ${DESTDIR}${LIB_DIR}/lib${LIB}.a
	sudo ${RM} ${DESTDIR}${MAN_DIR}/${MAN3}

M cstring.3 => cstring.3 +29 -0
@@ 125,11 125,40 @@ stream. Similar behavior to
Check if
.I pos
is out of bounds.
.TP
.BR CSTRING_MALLOC(ptr,\ size)
Allocate memory with error cheking.
.P
The following macros can only be used in debug mode:
.TP
.BR CSTRING_DBG_LOG(fmt,\ ...)
Prints a message in the format of "DEBUG: file:line:func(): msg".
.TP
.BR CSTRING_DBG_LOG_STR_INFO(cs)
Uses
.I CSTRING_DBG_LOG
to print all the contents of a
.I cstring
struct. The argument has to be a pointer.
.TP
.BR CSTRING_DBG_LOG_STR_INFO_NPTR(cs)
Uses
.I CSTRING_DBG_LOG
to print all the contents of a
.I cstring
struct. The argument has to be a non-pointer.
.SH CONSTANTS
.TP
.BR CSTRING_NPOS
This constant signifies that a pattern hasn't been found inside
the string. It's value is -1.
.SH OPTIONS
.TP
.BR CSTRING_DEBUG
Runs in debug mode if it is defined. In order to define it compile
the library with the
.I -DCSTRING_DEBUG
option.
.SH USAGE
You must
.B always

M cstring.c => cstring.c +28 -9
@@ 23,6 23,9 @@ cstring_create(const char *s)
    cs.len = strlen(s);
    cs.str = cstring_copy(s);
    cstring_resize(&cs, cs.len << 1);
#ifdef CSTRING_DBG
    CSTRING_DBG_LOG_STR_INFO_NPTR(cs);
#endif /* CSTRING_DBG */
    return cs;
}



@@ 44,6 47,9 @@ cstring_assign(cstring *cs, const char *s)
    if (!cstring_empty(cs)) free(cs->str);
    cs->str = cstring_copy(s);
    cs->len = newlen;
#ifdef CSTRING_DBG
    CSTRING_DBG_LOG_STR_INFO(cs);
#endif /* CSTRING_DBG */
}

void


@@ 52,16 58,20 @@ cstring_insert(cstring *cs, const char *s, size_t i)
    if (!CSTRING_OUT_OF_BOUNDS(cs, i) && s != NULL) {
        size_t slen = strlen(s);
        size_t newlen = cs->len + slen;
        char *tmp = (char *)malloc(newlen + 1);
        memcpy(tmp, cs->str, i);
        memcpy(tmp + i, s, slen);
        memcpy(tmp + slen + i, cs->str + i , newlen - slen - i);
        char *tmp;
        CSTRING_MALLOC(tmp, newlen + 1);
        if (CSTRING_EXCEEDS_CAPACITY(newlen, cs->capacity))
            cstring_resize(cs, newlen << 1);
        memcpy(tmp, cs->str, i);
        memcpy(tmp + i, s, slen);
        memcpy(tmp + slen + i, cs->str + i, newlen - slen - i);
        free(cs->str);
        cs->len = newlen;
        cs->str = tmp;
        cs->str[cs->len] = '\0';
#ifdef CSTRING_DBG
    CSTRING_DBG_LOG_STR_INFO(cs);
#endif /* CSTRING_DBG */
    }
}



@@ 73,7 83,8 @@ cstring_erase(cstring *cs, size_t pos, size_t len)
    &&  !CSTRING_OUT_OF_BOUNDS(cs, len))
    {
        size_t newlen = cs->len - len;
        char *tmp = (char *)malloc(newlen + 1);
        char *tmp;
        CSTRING_MALLOC(tmp, newlen + 1);
        memcpy(tmp, cs->str, pos); // pos + 1??
        memcpy(tmp + pos, cs->str + pos + len, newlen);
        free(cs->str);


@@ 116,13 127,17 @@ cstring_push_back(cstring *cs, char c)
        cstring_resize(cs, cs->len << 1);
    cs->str[cs->len] = c;
    cs->str[++cs->len] = '\0';
#ifdef CSTRING_DBG
    CSTRING_DBG_LOG_STR_INFO(cs);
#endif /* CSTRING_DBG */
}

void
cstring_pop_back(cstring *cs)
{
    if (cs->len > 0) {
        char *tmp = (char *)malloc(cs->len);
        char *tmp;
        CSTRING_MALLOC(tmp, cs->len);
        memcpy(tmp, cs->str, cs->len);
        free(cs->str);
        tmp[--cs->len] = '\0';


@@ 175,7 190,7 @@ void
cstring_clear(cstring *cs)
{
    if (!cstring_empty(cs)) free(cs->str);
    cs->str = (char *)malloc(1);
    CSTRING_MALLOC(cs->str, 1);
    cs->str[0] = '\0';
    cs->len = 0;
    cs->capacity = 0;


@@ 264,7 279,8 @@ char *
cstring_copy(const char *s)
{
    size_t len = strlen(s);
    char *tmp = (char *)malloc(len + 1);
    char *tmp;
    CSTRING_MALLOC(tmp, len + 1);
    memcpy(tmp, s, len + 1);
    tmp[len] = '\0';
    return tmp;


@@ 273,8 289,11 @@ cstring_copy(const char *s)
void
cstring_resize(cstring *cs, size_t newcapacity)
{
    cs->str = (char *)realloc(cs->str, newcapacity);
    cs->str = (char *)realloc(cs->str, newcapacity + 1);
    cs->capacity = newcapacity;
#ifdef CSTRING_DBG
    CSTRING_DBG_LOG_STR_INFO(cs);
#endif /* CSTRING_DBG */
}

cstring *

M cstring.h => cstring.h +20 -0
@@ 12,6 12,26 @@ extern "C" {
#define CSTRING_NPOS -1
#define CSTRING_OUT_OF_BOUNDS(cs, pos) ((pos) > cs->len)

#define CSTRING_MALLOC(ptr, size) do {                               \
    ptr = (char *)malloc((size));                                    \
    if (ptr == NULL)                                                 \
        fputs("CSTRING_MALLOC(): cannot allocate memory\n", stderr); \
} while (0)

#ifdef CSTRING_DBG
#define CSTRING_DBG_LOG(fmt, ...)                                    \
    fprintf(stderr, "DEBUG: %s:%d:%s(): " fmt,                       \
            __FILE__, __LINE__, __func__, __VA_ARGS__)

#define CSTRING_DBG_LOG_STR_INFO(cs)                                 \
    CSTRING_DBG_LOG("STR: %s | LEN: %ld | CAP: %ld\n",               \
            cs->str, cs->len, cs->capacity)

#define CSTRING_DBG_LOG_STR_INFO_NPTR(cs)                            \
    CSTRING_DBG_LOG("STR: %s | LEN: %ld | CAP: %ld\n",               \
            cs.str, cs.len, cs.capacity)
#endif /* CSTRING_DBG */

typedef struct cstring {
    char   *str;
    size_t  len;

M tests/test.c => tests/test.c +5 -4
@@ 17,6 17,10 @@ main(int argc, char **argv)
    cstring_prepend(&s, "OK");
    printf("cstring_prepend: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity);

    // BUG
    /*for (int i = 0; i < 50; i++)*/
        /*cstring_push_back(&s, 'c');*/

    cstring_push_back(&s, 'c');
    printf("cstring_push_back: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity);



@@ 50,11 54,8 @@ main(int argc, char **argv)
    cstring_trim(&s, " ");
    printf("cstring_trim: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity);

    cstring_insert(&s, "New text", 2);
    printf("cstring_insert: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity);

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

    return 0;
}