cstring

Lightweight string library for C
git clone git://git.christosmarg.xyz/cstring.git
Log | Files | Refs | README | LICENSE

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:
Mcstring.3 | 60++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Mcstring.c | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
Mcstring.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);