commit d2a6d689d0f34b7ccc60a1ac7515212a345a2a4a
parent 805f9acde435c5be62a70c4b69ccb1bec894d954
Author: Christos Margiolis <christos@margiolis.net>
Date: Fri, 9 Oct 2020 03:29:35 +0300
updated manpage, added sort functions, pending erase bug fixes
Diffstat:
M | cstring.3 | | | 60 | ++++++++++++++++++++++++++++++++++++++++++++++++++++-------- |
M | cstring.c | | | 71 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------- |
M | cstring.h | | | 13 | +++++++++++-- |
3 files changed, 124 insertions(+), 20 deletions(-)
diff --git a/cstring.3 b/cstring.3
@@ -1,7 +1,44 @@
.TH cstring 3
.SH NAME
-cstring \- A simple and lightweight string library for C inspired by C++'s
+.B cstring
+\- A simple and lightweight string library for C inspired by C++'s
STL string class
+.SH SYNOPSIS
+#include <cstring.h>
+.SH DESCRIPTION
+.P
+The
+.B cstring
+library offers a lightweight and fast way to manage
+strings with a wide range of useful functions.
+.P
+A program using
+.B cstring
+has to be linked using the
+.B \-lcstring
+option.
+.P
+In case you want to run the program in debug mode, compile
+it with the
+.B -DCSTRING_DEBUG
+option.
+.SH STRUCTURES AND ENUMS
+.TP
+.BR cstring
+typedef struct cstring {
+ char *str; /* contents of string */
+ size_t len; /* string length */
+ size_t capacity; /* string capacity */
+.br
+};
+.TP
+.BR cstring_flags
+enum cstring_flags {
+ CSTRING_ASCENDING, /* sort in ascending order */
+ CSTRING_DESCENDING, /* sort in descending order */
+ CSTRING_CALLBACK /* use your own sort function */
+.br
+};
.SH FUNCTIONS
.TP
.BR cstring\ cstring_create(const\ char\ *s)
@@ -54,6 +91,20 @@ Extract a substring from current string.
.BR void\ cstring_swap(cstring\ *lhs,\ cstring\ *rhs)
Swap contents of two strings.
.TP
+.BR void\ cstring_sort(cstring\ **cs,\ size_t\ len,\ enum\ cstring_flags\ flags,\ int\ (*callback)(const\ void\ *lhs,\ const\ void\ *rhs))
+Sort an array of cstrings. If you want to use the builtin comparison pass
+.I NULL
+in the last argument. In case you want to use your own callback use the
+.I CSTRING_CALLBACK
+flag and pass your own callback function in the last argument.
+.TP
+.BR void\ cstring_sort_chars(cstring\ *cs,\ enum\ cstring_flags\ flags,\ int\ (*callback)(const\ void\ *lhs,\ const\ void\ *rhs))
+Sort a cstring's contents. If you want to use the builtin comparison pass
+.I NULL
+in the last argument. In case you want to use your own callback use the
+.I CSTRING_CALLBACK
+flag and pass your own callback function in the last argument.
+.TP
.BR void\ cstring_shrink_to_fit(cstring\ *cs)
Reduce string's capacity to its size.
.TP
@@ -151,13 +202,6 @@ Print contents of a normal string.
.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
diff --git a/cstring.c b/cstring.c
@@ -2,6 +2,12 @@
#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); \
@@ -13,9 +19,9 @@
#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++) \
+ for (_i = 0; _i < (pos); _i++) \
printf("%c", cs->str[_i]); \
- for (_i = pos + len; _i < cs->len; _i++) \
+ for (_i = (pos) + (len); _i < cs->len; _i++) \
printf("%c", cs->str[_i]); \
printf("\n"); \
} while (0)
@@ -29,12 +35,6 @@
} while (0)
#endif /* CSTRING_DBG */
-#define CSTRING_FIND_OCCURENCE(cs, s, func) do { \
- char *_found; \
- if ((_found = func(cs->str, (s))) != NULL) \
- return (_found - cs->str); \
-} while (0)
-
static int
cstring_is_one_of(char c, const char *s)
{
@@ -44,6 +44,30 @@ cstring_is_one_of(char c, const char *s)
return 0;
}
+static inline int
+cstring_cmp_greater(const void *lhs, const void *rhs)
+{
+ return cstring_greater((cstring *)lhs, (cstring *)rhs);
+}
+
+static inline int
+cstring_cmp_less(const void *lhs, const void *rhs)
+{
+ return cstring_less((cstring *)lhs, (cstring *)rhs);
+}
+
+static inline int
+cstring_cmp_char_greater(const void *lhs, const void *rhs)
+{
+ return (*(char *)lhs > *(char *)rhs);
+}
+
+static inline int
+cstring_cmp_char_less(const void *lhs, const void *rhs)
+{
+ return (*(char *)lhs < *(char *)rhs);
+}
+
cstring
cstring_create(const char *s)
{
@@ -219,6 +243,33 @@ cstring_swap(cstring *lhs, cstring *rhs)
}
void
+cstring_sort(cstring **cs,
+ size_t len,
+ enum cstring_flags flags,
+ int (*callback)(const void *lhs, const void *rhs))
+{
+ if (flags == CSTRING_ASCENDING)
+ qsort(cs, len, sizeof(cstring *), cstring_cmp_greater);
+ else if (flags == CSTRING_DESCENDING)
+ qsort(cs, len, sizeof(cstring *), cstring_cmp_less);
+ else if (flags == CSTRING_CALLBACK)
+ qsort(cs, len, sizeof(cstring *), callback);
+}
+
+void
+cstring_sort_chars(cstring *cs,
+ enum cstring_flags flags,
+ int (*callback)(const void *lhs, const void *rhs))
+{
+ if (flags == CSTRING_ASCENDING)
+ qsort(cs->str, cs->len, sizeof(char), cstring_cmp_char_greater);
+ else if (flags == CSTRING_DESCENDING)
+ qsort(cs->str, cs->len, sizeof(char), cstring_cmp_char_less);
+ else if (flags == CSTRING_CALLBACK)
+ qsort(cs->str, cs->len, sizeof(char), callback);
+}
+
+void
cstring_clear(cstring *cs)
{
CSTRING_FREE(cs);
@@ -228,8 +279,8 @@ cstring_clear(cstring *cs)
cs->capacity = 0;
}
-#define CSTRING_CHECK(cs, s) \
- if (cstring_empty(cs) || !*s) \
+#define CSTRING_CHECK(cs, s) \
+ if (cstring_empty(cs) || !*(s)) \
return CSTRING_NPOS
size_t
diff --git a/cstring.h b/cstring.h
@@ -32,7 +32,7 @@ extern "C" {
cs.str, cs.len, cs.capacity)
#define CSTRING_DBG_LOG_STR_INFO(s, len) \
- CSTRING_DBG_LOG("S: %s | LEN: %ld\n", s, len)
+ CSTRING_DBG_LOG("S: %s | LEN: %ld\n", (s), (len))
#endif /* CSTRING_DBG */
typedef struct cstring {
@@ -41,6 +41,12 @@ typedef struct cstring {
size_t capacity;
} cstring;
+enum cstring_flags {
+ CSTRING_ASCENDING,
+ CSTRING_DESCENDING,
+ CSTRING_CALLBACK
+};
+
extern cstring cstring_create(const char *);
extern void cstring_delete(cstring *);
extern void cstring_assign(cstring *, const char *);
@@ -55,6 +61,10 @@ 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 *);
@@ -63,7 +73,6 @@ 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_move(cstring *cs, const char *);
extern void cstring_resize(cstring *, size_t);
extern cstring *cstring_getline(FILE *, cstring *, char);