commit 3db911364bcc348ddcb9f71077743d065cc0847f
parent fb54a79b85158d77c21d18220c33226aaa78f48d
Author: Christos Margiolis <christos@margiolis.net>
Date: Mon, 10 May 2021 03:18:59 +0300
removed CSTRING_DBG
Diffstat:
M | README | | | 9 | --------- |
M | cstring.3 | | | 99 | +++++++++++++++++++++++++++---------------------------------------------------- |
M | cstring.c | | | 129 | ++++++++++++++++++++++++++----------------------------------------------------- |
M | cstring.h | | | 121 | +++++++++++++++++++++++++++++++------------------------------------------------ |
M | tests/Makefile | | | 4 | ++-- |
5 files changed, 126 insertions(+), 236 deletions(-)
diff --git a/README b/README
@@ -24,8 +24,6 @@ If you want to uninstall the library do:
# sudo make uninstall
A file using `cstring` has to be linked using the `-lcstring` linker flag.
-In case you want to run your project in debug mode, compile the library using
-the `-DCSTRING_DBG` option.
Usage
-----
@@ -96,13 +94,6 @@ Macros
- `CSTRING_ARR_LEN`: Determine an array's length. The macro must be called in the same function the array is declared.
- `CSTRING_MALLOC`: Allocate memory with error checking.
-The following macros can only be used in debug mode:
-
-- `CSTIRNG_DBG_LOG`: Prints a message in the format of `DEBUG: file:line:func(): msg`.
-- `CSTRING_DBG_LOG_CSTR_INFO`: Prints all the contents of a `cstring` struct. The argument *has* to be a pointer.
-- `CSTRING_DBG_LOG_CSTR_INFO_NPTR`: Like `CSTRING_DBG_LOG_CSTR_INFO` but the argument has to be a non-pointer.
-- `CSTRING_DBG_LOG_STR_INFO`: Print contents of a normal string.
-
Constants
---------
- `CSTRING_NPOS`: Signifies that a pattern hasn't been found inside the string. Its value is -1.
diff --git a/cstring.3 b/cstring.3
@@ -4,6 +4,8 @@
.Nm cstring
.Nd A simple and lightweight string library for C inspired by C++'s
STL string class
+.Sh LIBRARY
+C String (-lcstring)
.Sh SYNOPSIS
#include <cstring.h>
.Sh DESCRIPTION
@@ -12,38 +14,42 @@ The
.Nm
library offers a lightweight and fast way to manage
strings with a wide range of useful functions.
-.Pp
-A program using
-.Nm
-has to be linked using the
-.Ar \-lcstring
-option.
-.Pp
-In case you want to run the program in debug mode, compile
-it with the
-.Ar \-DCSTRING_DBG
-option.
-.Sh STRUCTURES
+
.Bl -tag -width Ds
typedef struct _cstring {
- size_t len; /* string length */
- size_t capacity; /* string capacity */
- char *str; /* contents of string */
-
-CSTRING_SORT_ASCENDING 0x01 /* sort in ascending order */
-.br
-CSTRING_SORT_DESCENDING 0x02 /* sort in descending order */
-.br
-CSTRING_SORT_CALLBACK 0x04 /* sort using a callback function */
-.br
-CSTRING_SORT_REST 0x10 /* sort the rest of the array */
-.br
+ size_t len; /* string length */
+ size_t capacity; /* string capacity */
+ char *str; /* contents of string */
+CSTRING_SORT_ASCENDING 0x01 /* sort in ascending order */
+CSTRING_SORT_DESCENDING 0x02 /* sort in descending order */
+CSTRING_SORT_CALLBACK 0x04 /* sort using a callback function */
+CSTRING_SORT_REST 0x10 /* sort the rest of the array */
} cstring;
-.Sh TYPEDEFS
-.Bl -tag -width Ds
-Short typedef for the cstring structure.
+
.It typedef\ int\ (*cstring_sort_callback)(const void *, const void *);
Used in sort functions.
+
+.Sh USAGE
+You must
+.Ar always
+call the
+.Fn cstring_create
+and
+.Fn cstring_delete
+functions whenever you want to make a new instance of
+.Ar cstring
+and stop using it respectively, in order to not cause any memory
+leaks.
+.Pp
+The recommended way of initializing an empty string is by doing
+.Ar cstring foo = cstring_create(CSTRING_INIT_EMPTY)
+.Pp
+If a function requires a
+.Ar char *
+you can access the
+.Ar .str
+field and pass it to the function.
+
.Sh FUNCTIONS
.Bl -tag -width Ds
.It void Fn cstring_create "const char *s"
@@ -217,30 +223,13 @@ Check if
.Ar pos
is out of bounds (pos > len).
-.It Fn CSTRING_ARR_LEN "arr"
+.It Fn CSTRING_ARR_LEN "x"
Determine an array's length. The macro must be called in the same function
the array is declared.
.It Fn CSTRING_MALLOC "ptr" "size"
Allocate memory with error cheking.
-.Pp
-The following macros can only be used in debug mode:
-.It Fn CSTRING_DBG_LOG "fmt" "..."
-Prints a message in the format of "DEBUG: file:line:func(): msg".
-
-.It Fn CSTRING_DBG_LOG_CSTR_INFO "cs"
-Print all the contents of a
-.Ar cstring
-struct. The argument has to be a pointer.
-
-.It Fn CSTRING_DBG_LOG_CSTR_INFO_NPTR "cs"
-Like
-.Fn CSTRING_DBG_LOG_CSTR_INFO
-but the argument has to be a non-pointer.
-.It Fn CSTRING_DBG_LOG_STR_INFO "s" "len"
-Print contents of a normal string.
-
.Sh CONSTANTS
.Bl -tag -width Ds
.It CSTRING_NPOS
@@ -252,25 +241,5 @@ Used with
.Fn cstring_create
in case the string is to be initliazed as empty.
-.Sh USAGE
-You must
-.Ar always
-call the
-.Fn cstring_create
-and
-.Fn cstring_delete
-functions whenever you want to make a new instance of
-.Ar cstring
-and stop using it respectively, in order to not cause any memory
-leaks.
-.Pp
-The recommended way of initializing an empty string is by doing
-.Ar cstring foo = cstring_create(CSTRING_INIT_EMPTY)
-.Pp
-If a function requires a
-.Ar char *
-you can access the
-.Ar .str
-field and pass it to the function.
.Sh AUTHORS
.An Christos Margiolis Aq Mt christos@christosmarg.xyz
diff --git a/cstring.c b/cstring.c
@@ -2,28 +2,16 @@
#include "cstring.h"
#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); \
-} 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); \
-} while (0)
-#else /* !CSTRING_DBG */
-#define CSTRING_FREE(cs) do { \
- if (!cstring_empty(cs)) \
- free(cs->str); \
+#define FIND_OCC(cs, s, f) do { \
+ char *_found; \
+ if ((_found = f(cs->str, (s))) != NULL) \
+ return (_found - cs->str); \
} while (0)
-#endif /* CSTRING_DBG */
/* statics */
static int cstring_is_one_of(char, const char *);
+static void *emalloc(size_t);
+static void csfree(cstring *);
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 *);
@@ -38,6 +26,25 @@ cstring_is_one_of(char c, const char *s)
return 0;
}
+static void *
+emalloc(size_t nb)
+{
+ void *p;
+
+ if ((p= malloc(nb)) == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+ return p;
+}
+
+static void
+csfree(cstring *cs)
+{
+ if (!cstring_empty(cs))
+ free(cs->str);
+}
+
static inline int
cstring_cmp_greater(const void *lhs, const void *rhs)
{
@@ -70,17 +77,13 @@ 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(s, cs.len);
- CSTRING_DBG_LOG_CSTR_INFO_NPTR(cs);
-#endif /* CSTRING_DBG */
return cs;
}
void
cstring_delete(cstring *cs)
{
- CSTRING_FREE(cs);
+ csfree(cs);
cs->str = NULL;
cs->len = 0;
cs->capacity = 0;
@@ -89,15 +92,11 @@ cstring_delete(cstring *cs)
void
cstring_assign(cstring *cs, const char *s)
{
- CSTRING_FREE(cs);
+ csfree(cs);
cs->str = cstring_copy(s);
cs->len = strlen(s);
if (CSTRING_EXCEEDS_CAPACITY(cs->len, cs->capacity))
cstring_resize(cs, cs->len << 1);
-#ifdef CSTRING_DBG
- CSTRING_DBG_LOG_STR_INFO(s, cs->len);
- CSTRING_DBG_LOG_CSTR_INFO(cs);
-#endif /* CSTRING_DBG */
}
void
@@ -109,39 +108,19 @@ cstring_insert(cstring *cs, const char *s, size_t i)
if (!CSTRING_OUT_OF_BOUNDS(cs->len, i) && s != NULL) {
slen = strlen(s);
newlen = cs->len + slen;
- CSTRING_MALLOC(tmp, newlen + 1);
+ tmp = emalloc(newlen + 1);
memcpy(tmp, cs->str, i);
memcpy(tmp + i, s, slen);
memcpy(tmp + i + slen, cs->str + i, newlen - slen - i + 1);
- CSTRING_FREE(cs);
+ csfree(cs);
cs->len = newlen;
cs->str = tmp;
cs->str[cs->len] = '\0';
if (CSTRING_EXCEEDS_CAPACITY(newlen, cs->capacity))
cstring_resize(cs, newlen << 1);
-#ifdef CSTRING_DBG
- CSTRING_DBG_LOG_STR_INFO(s, slen);
- CSTRING_DBG_LOG_CSTR_INFO(cs);
-#endif /* CSTRING_DBG */
}
}
-#ifdef CSTRING_DBG
-// FIXME
-#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)
{
@@ -151,23 +130,14 @@ cstring_erase(cstring *cs, size_t pos, size_t len)
if (!cstring_empty(cs)
&& (!CSTRING_OUT_OF_BOUNDS(cs->len, pos)
|| !CSTRING_OUT_OF_BOUNDS(cs->len, len))) {
-#ifdef CSTRING_DBG
- CSTRING_DBG_LOG("STR: %s | INDEX: %ld | LEN: %ld\n",
- cs->str, pos, len);
- CSTRING_DBG_EXPECTED_ERASE_STR(cs, pos, len);
- CSTRING_DBG_EXPECTED_ERASE_LEN(cs, len);
-#endif /* CSTRING_DBG */
newlen = cs->len - len;
- CSTRING_MALLOC(tmp, newlen + 1);
+ tmp = emalloc(newlen + 1);
memcpy(tmp, cs->str, pos);
memcpy(tmp + pos, cs->str + pos + len, cs->len - pos - len);
- CSTRING_FREE(cs); /* Useless check but keep it for consistency */
+ csfree(cs); /* Useless check but keep it for consistency */
cs->len = newlen;
cs->str = tmp;
cs->str[cs->len] = '\0';
-#ifdef CSTRING_DBG
- CSTRING_DBG_LOG_CSTR_INFO(cs);
-#endif /* CSTRING_DBG */
}
}
@@ -201,11 +171,6 @@ 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)
{
@@ -213,9 +178,6 @@ 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_CSTR_INFO(cs);
-#endif /* CSTRING_DBG */
}
void
@@ -296,8 +258,8 @@ cstring_sort_chars_partial(cstring *cs, size_t pos, size_t len, int flags,
void
cstring_clear(cstring *cs)
{
- CSTRING_FREE(cs);
- CSTRING_MALLOC(cs->str, 1);
+ csfree(cs);
+ cs->str = emalloc(1);
cs->str[0] = '\0';
cs->len = 0;
cs->capacity = 0;
@@ -311,7 +273,7 @@ size_t
cstring_find(const cstring *cs, const char *s)
{
CSTRING_CHECK(cs, s);
- CSTRING_FIND_OCCURENCE(cs, s, strstr);
+ FIND_OCC(cs, s, strstr);
return CSTRING_NPOS;
}
@@ -344,7 +306,7 @@ cstring_find_first_of(const cstring *cs, const char *s)
{
CSTRING_CHECK(cs, s);
for (; *s; s++) {
- CSTRING_FIND_OCCURENCE(cs, *s, strchr);
+ FIND_OCC(cs, *s, strchr);
}
return CSTRING_NPOS;
}
@@ -369,7 +331,7 @@ cstring_find_last_of(const cstring *cs, const char *s)
CSTRING_CHECK(cs, s);
i = *(s + strlen(s));
for (; i >= 0; i--) {
- CSTRING_FIND_OCCURENCE(cs, s[i], strrchr);
+ FIND_OCC(cs, s[i], strrchr);
}
return CSTRING_NPOS;
}
@@ -391,7 +353,7 @@ cstring_find_last_not_of(const cstring *cs, const char *s)
int
cstring_ends_with_str(const cstring *cs, const char *s)
{
- /* avoid cstring_substr */
+ /* TODO: avoid cstring_substr */
cstring sub;
size_t slen;
int found;
@@ -410,9 +372,9 @@ cstring_copy(const char *s)
char *tmp;
len = strlen(s);
- CSTRING_MALLOC(tmp, len + 1);
+ tmp = emalloc(len + 1);
memcpy(tmp, s, len + 1);
- tmp[len] = '\0'; /* Add \0 in case s didn't have it */
+ tmp[len] = '\0'; /* Add \0 in case `s` didn't have it */
return tmp;
}
@@ -421,19 +383,12 @@ cstring_resize(cstring *cs, size_t newcapacity)
{
char *tmp;
-#ifdef CSTRING_DBG
- CSTRING_DBG_LOG("Old capacity: %ld | New capacity: %ld\n",
- cs->capacity, newcapacity);
-#endif /* CSTRING_DBG */
- CSTRING_MALLOC(tmp, newcapacity + 1); /* no +1? */
- memcpy(tmp, cs->str, cs->len + 1); /* copy \0 too */
- CSTRING_FREE(cs);
+ tmp = emalloc(newcapacity + 1);
+ memcpy(tmp, cs->str, cs->len + 1);
+ csfree(cs);
cs->str = tmp;
cs->str[cs->len] = '\0';
cs->capacity = newcapacity;
-#ifdef CSTRING_DBG
- CSTRING_DBG_LOG_CSTR_INFO(cs);
-#endif /* CSTRING_DBG */
}
cstring *
diff --git a/cstring.h b/cstring.h
@@ -1,6 +1,6 @@
/* See LICENSE file for copyright and license details. */
-#ifndef CSTRING_H
-#define CSTRING_H
+#ifndef _CSTRING_H_
+#define _CSTRING_H_
#include <stdio.h>
#include <stdlib.h>
@@ -13,30 +13,7 @@ extern "C" {
#define CSTRING_NPOS -1
#define CSTRING_INIT_EMPTY ""
#define CSTRING_OUT_OF_BOUNDS(len, pos) ((pos) > (len))
-#define CSTRING_ARR_LEN(arr) ((size_t)sizeof((arr)) / sizeof((arr)[0]))
-
-#define CSTRING_MALLOC(ptr, size) do { \
- ptr = 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_CSTR_INFO(cs) \
- CSTRING_DBG_LOG("STR: %s | LEN: %ld | CAP: %ld\n", \
- cs->str, cs->len, cs->capacity)
-
-#define CSTRING_DBG_LOG_CSTR_INFO_NPTR(cs) \
- CSTRING_DBG_LOG("STR: %s | LEN: %ld | CAP: %ld\n", \
- cs.str, cs.len, cs.capacity)
-
-#define CSTRING_DBG_LOG_STR_INFO(s, len) \
- CSTRING_DBG_LOG("S: %s | LEN: %ld\n", (s), (len))
-#endif /* CSTRING_DBG */
+#define CSTRING_ARR_LEN(x) (sizeof((x)) / sizeof((x)[0]))
typedef struct _cstring {
size_t len; /* strlen of str */
@@ -51,54 +28,52 @@ typedef struct _cstring {
typedef int (*cstring_sort_callback)(const void *, const void *);
-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_partial(cstring *, size_t, size_t, int,
- cstring_sort_callback);
-extern void cstring_sort_chars_partial(cstring *cs, size_t, size_t, int,
- cstring_sort_callback);
-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 int cstring_ends_with_str(const cstring *, const char *);
-extern char *cstring_copy(const char *);
-extern void cstring_resize(cstring *, size_t);
-extern cstring *cstring_getline(FILE *, cstring *, char);
+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_partial(cstring *, size_t, size_t, int, cstring_sort_callback);
+extern void cstring_sort_chars_partial(cstring *cs, size_t, size_t, int, cstring_sort_callback);
+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 int cstring_ends_with_str(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_sort(cstring *, size_t, int, cstring_sort_callback);
-static inline void cstring_sort_chars(cstring *, int, cstring_sort_callback);
-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_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 *, const char *);
+static inline void cstring_append(cstring *, const char *);
+static inline void cstring_sort(cstring *, size_t, int, cstring_sort_callback);
+static inline void cstring_sort_chars(cstring *, int, cstring_sort_callback);
+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_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)
@@ -205,4 +180,4 @@ cstring_less_or_equal(const cstring *lhs, const cstring *rhs)
}
#endif /* __cplusplus */
-#endif /* CSTRING_H */
+#endif /* _CSTRING_H_ */
diff --git a/tests/Makefile b/tests/Makefile
@@ -3,9 +3,9 @@
.POSIX:
BINS = test_basic test_insert
-CC = gcc
+CC = cc
CFLAGS = -Wall -std=c99 -pedantic -O3
-LDFLAGS = -Llib -lcstring
+LDFLAGS = -Llib -L/usr/local/lib -I/usr/local/include -lcstring
all: options ${BINS}