libslack(str) - string module
#include <slack/std.h> #include <slack/str.h>
typedef struct String String; typedef struct StringTR StringTR;
enum StringAlignment { ALIGN_LEFT = '<', ALIGN_RIGHT = '>', ALIGN_CENTRE = '|', ALIGN_CENTER = '|', ALIGN_FULL = '=' };
enum StringTROption { TR_COMPLEMENT = 1, TR_DELETE = 2, TR_SQUASH = 4 };
typedef enum StringAlignment StringAlignment; typedef enum StringTROption StringTROption;
String *str_create(const char *format, ...); String *str_create_with_locker(Locker *locker, const char *format, ...); String *str_vcreate(const char *format, va_list args); String *str_vcreate_with_locker(Locker *locker, const char *format, va_list args); String *str_create_sized(size_t size, const char *format, ...); String *str_create_with_locker_sized(Locker *locker, size_t size, const char *format, ...); String *str_vcreate_sized(size_t size, const char *format, va_list args); String *str_vcreate_with_locker_sized(Locker *locker, size_t size, const char *format, va_list args); String *str_copy(const String *str); String *str_copy_unlocked(const String *str); String *str_copy_with_locker(Locker *locker, const String *str); String *str_copy_with_locker_unlocked(Locker *locker, const String *str); String *str_fgetline(FILE *stream); String *str_fgetline_with_locker(Locker *locker, FILE *stream); void str_release(String *str); void *str_destroy(String **str); int str_rdlock(const String *str); int str_wrlock(const String *str); int str_unlock(const String *str); int str_empty(const String *str); int str_empty_unlocked(const String *str); ssize_t str_length(const String *str); ssize_t str_length_unlocked(const String *str); char *cstr(const String *str); ssize_t str_set_length(String *str, size_t length); ssize_t str_set_length_unlocked(String *str, size_t length); ssize_t str_recalc_length(String *str); ssize_t str_recalc_length_unlocked(String *str); String *str_clear(String *str); String *str_clear_unlocked(String *str); String *str_remove(String *str, ssize_t index); String *str_remove_unlocked(String *str, ssize_t index); String *str_remove_range(String *str, ssize_t index, ssize_t range); String *str_remove_range_unlocked(String *str, ssize_t index, ssize_t range); String *str_insert(String *str, ssize_t index, const char *format, ...); String *str_insert_unlocked(String *str, ssize_t index, const char *format, ...); String *str_vinsert(String *str, ssize_t index, const char *format, va_list args); String *str_vinsert_unlocked(String *str, ssize_t index, const char *format, va_list args); String *str_insert_str(String *str, ssize_t index, const String *src); String *str_insert_str_unlocked(String *str, ssize_t index, const String *src); String *str_append(String *str, const char *format, ...); String *str_append_unlocked(String *str, const char *format, ...); String *str_vappend(String *str, const char *format, va_list args); String *str_vappend_unlocked(String *str, const char *format, va_list args); String *str_append_str(String *str, const String *src); String *str_append_str_unlocked(String *str, const String *src); String *str_prepend(String *str, const char *format, ...); String *str_prepend_unlocked(String *str, const char *format, ...); String *str_vprepend(String *str, const char *format, va_list args); String *str_vprepend_unlocked(String *str, const char *format, va_list args); String *str_prepend_str(String *str, const String *src); String *str_prepend_str_unlocked(String *str, const String *src); String *str_replace(String *str, ssize_t index, ssize_t range, const char *format, ...); String *str_replace_unlocked(String *str, ssize_t index, ssize_t range, const char *format, ...); String *str_vreplace(String *str, ssize_t index, ssize_t range, const char *format, va_list args); String *str_vreplace_unlocked(String *str, ssize_t index, ssize_t range, const char *format, va_list args); String *str_replace_str(String *str, ssize_t index, ssize_t range, const String *src); String *str_replace_str_unlocked(String *str, ssize_t index, ssize_t range, const String *src); String *str_substr(const String *str, ssize_t index, ssize_t range); String *str_substr_unlocked(const String *str, ssize_t index, ssize_t range); String *str_substr_with_locker(Locker *locker, const String *str, ssize_t index, ssize_t range); String *str_substr_with_locker_unlocked(Locker *locker, const String *str, ssize_t index, ssize_t range); String *substr(const char *str, ssize_t index, ssize_t range); String *substr_with_locker(Locker *locker, const char *str, ssize_t index, ssize_t range); String *str_splice(String *str, ssize_t index, ssize_t range); String *str_splice_unlocked(String *str, ssize_t index, ssize_t range); String *str_splice_with_locker(Locker *locker, String *str, ssize_t index, ssize_t range); String *str_splice_with_locker_unlocked(Locker *locker, String *str, ssize_t index, ssize_t range); String *str_repeat(size_t count, const char *format, ...); String *str_repeat_with_locker(Locker *locker, size_t count, const char *format, ...); String *str_vrepeat(size_t count, const char *format, va_list args); String *str_vrepeat_with_locker(Locker *locker, size_t count, const char *format, va_list args); int str_tr(String *str, const char *from, const char *to, int option); int str_tr_unlocked(String *str, const char *from, const char *to, int option); int str_tr_str(String *str, const String *from, const String *to, int option); int str_tr_str_unlocked(String *str, const String *from, const String *to, int option); int tr(char *str, const char *from, const char *to, int option); StringTR *tr_compile(const char *from, const char *to, int option); StringTR *tr_compile_with_locker(Locker *locker, const char *from, const char *to, int option); StringTR *str_tr_compile(const String *from, const String *to, int option); StringTR *str_tr_compile_unlocked(const String *from, const String *to, int option); StringTR *str_tr_compile_with_locker(Locker *locker, const String *from, const String *to, int option); StringTR *str_tr_compile_with_locker_unlocked(Locker *locker, const String *from, const String *to, int option); void tr_release(StringTR *table); void *tr_destroy(StringTR **table); int str_tr_compiled(String *str, StringTR *table); int str_tr_compiled_unlocked(String *str, StringTR *table); int tr_compiled(char *str, StringTR *table); List *str_regexpr(const char *pattern, const String *text, int cflags, int eflags); List *str_regexpr_unlocked(const char *pattern, const String *text, int cflags, int eflags); List *str_regexpr_with_locker(Locker *locker, const char *pattern, const String *text, int cflags, int eflags); List *str_regexpr_with_locker_unlocked(Locker *locker, const char *pattern, const String *text, int cflags, int eflags); List *regexpr(const char *pattern, const char *text, int cflags, int eflags); List *regexpr_with_locker(Locker *locker, const char *pattern, const char *text, int cflags, int eflags); int regexpr_compile(regex_t *compiled, const char *pattern, int cflags); void regexpr_release(regex_t *compiled); List *str_regexpr_compiled(const regex_t *compiled, const String *text, int eflags); List *str_regexpr_compiled_unlocked(const regex_t *compiled, const String *text, int eflags); List *str_regexpr_compiled_with_locker(Locker *locker, const regex_t *compiled, const String *text, int eflags); List *str_regexpr_compiled_with_locker_unlocked(Locker *locker, const regex_t *compiled, const String *text, int eflags); List *regexpr_compiled(const regex_t *compiled, const char *text, int eflags); List *regexpr_compiled_with_locker(Locker *locker, const regex_t *compiled, const char *text, int eflags); String *str_regsub(const char *pattern, const char *replacement, String *text, int cflags, int eflags, int all); String *str_regsub_unlocked(const char *pattern, const char *replacement, String *text, int cflags, int eflags, int all); String *str_regsub_compiled(const regex_t *compiled, const char *replacement, String *text, int eflags, int all); String *str_regsub_compiled_unlocked(const regex_t *compiled, const char *replacement, String *text, int eflags, int all); List *str_fmt(const String *str, size_t line_width, StringAlignment alignment); List *str_fmt_unlocked(const String *str, size_t line_width, StringAlignment alignment); List *str_fmt_with_locker(Locker *locker, const String *str, size_t line_width, StringAlignment alignment); List *str_fmt_with_locker_unlocked(Locker *locker, const String *str, size_t line_width, StringAlignment alignment); List *fmt(const char *str, size_t line_width, StringAlignment alignment); List *fmt_with_locker(Locker *locker, const char *str, size_t line_width, StringAlignment alignment); List *str_split(const String *str, const char *delim); List *str_split_unlocked(const String *str, const char *delim); List *str_split_with_locker(Locker *locker, const String *str, const char *delim); List *str_split_with_locker_unlocked(Locker *locker, const String *str, const char *delim); List *split(const char *str, const char *delim); List *split_with_locker(Locker *locker, const char *str, const char *delim); List *str_regexpr_split(const String *str, const char *delim, int cflags, int eflags); List *str_regexpr_split_unlocked(const String *str, const char *delim, int cflags, int eflags); List *str_regexpr_split_with_locker(Locker *locker, const String *str, const char *delim, int cflags, int eflags); List *str_regexpr_split_with_locker_unlocked(Locker *locker, const String *str, const char *delim, int cflags, int eflags); List *regexpr_split(const char *str, const char *delim, int cflags, int eflags); List *regexpr_split_with_locker(Locker *locker, const char *str, const char *delim, int cflags, int eflags); String *str_join(const List *list, const char *delim); String *str_join_unlocked(const List *list, const char *delim); String *str_join_with_locker(Locker *locker, const List *list, const char *delim); String *str_join_with_locker_unlocked(Locker *locker, const List *list, const char *delim); String *join(const List *list, const char *delim); String *join_with_locker(Locker *locker, const List *list, const char *delim); int str_soundex(const String *str); int str_soundex_unlocked(const String *str); int soundex(const char *str); String *str_trim(String *str); String *str_trim_unlocked(String *str); char *trim(char *str); String *str_trim_left(String *str); String *str_trim_left_unlocked(String *str); char *trim_left(char *str); String *str_trim_right(String *str); String *str_trim_right_unlocked(String *str); char *trim_right(char *str); String *str_squeeze(String *str); String *str_squeeze_unlocked(String *str); char *squeeze(char *str); String *str_quote(const String *str, const char *quotable, char quote_char); String *str_quote_unlocked(const String *str, const char *quotable, char quote_char); String *str_quote_with_locker(Locker *locker, const String *str, const char *quotable, char quote_char); String *str_quote_with_locker_unlocked(Locker *locker, const String *str, const char *quotable, char quote_char); String *quote(const char *str, const char *quotable, char quote_char); String *quote_with_locker(Locker *locker, const char *str, const char *quotable, char quote_char); String *str_unquote(const String *str, const char *quotable, char quote_char); String *str_unquote_unlocked(const String *str, const char *quotable, char quote_char); String *str_unquote_with_locker(Locker *locker, const String *str, const char *quotable, char quote_char); String *str_unquote_with_locker_unlocked(Locker *locker, const String *str, const char *quotable, char quote_char); String *unquote(const char *str, const char *quotable, char quote_char); String *unquote_with_locker(Locker *locker, const char *str, const char *quotable, char quote_char); String *str_encode(const String *str, const char *uncoded, const char *coded, char quote_char, int printable); String *str_encode_unlocked(const String *str, const char *uncoded, const char *coded, char quote_char, int printable); String *str_encode_with_locker(Locker *locker, const String *str, const char *uncoded, const char *coded, char quote_char, int printable); String *str_encode_with_locker_unlocked(Locker *locker, const String *str, const char *uncoded, const char *coded, char quote_char, int printable); String *str_decode(const String *str, const char *uncoded, const char *coded, char quote_char, int printable); String *str_decode_unlocked(const String *str, const char *uncoded, const char *coded, char quote_char, int printable); String *str_decode_with_locker(Locker *locker, const String *str, const char *uncoded, const char *coded, char quote_char, int printable); String *str_decode_with_locker_unlocked(Locker *locker, const String *str, const char *uncoded, const char *coded, char quote_char, int printable); String *encode(const char *str, const char *uncoded, const char *coded, char quote_char, int printable); String *encode_with_locker(Locker *locker, const char *str, const char *uncoded, const char *coded, char quote_char, int printable); String *decode(const char *str, const char *uncoded, const char *coded, char quote_char, int printable); String *decode_with_locker(Locker *locker, const char *str, const char *uncoded, const char *coded, char quote_char, int printable); String *str_lc(String *str); String *str_lc_unlocked(String *str); char *lc(char *str); String *str_lcfirst(String *str); String *str_lcfirst_unlocked(String *str); char *lcfirst(char *str); String *str_uc(String *str); String *str_uc_unlocked(String *str); char *uc(char *str); String *str_ucfirst(String *str); String *str_ucfirst_unlocked(String *str); char *ucfirst(char *str); int str_chop(String *str); int str_chop_unlocked(String *str); int chop(char *str); int str_chomp(String *str); int str_chomp_unlocked(String *str); int chomp(char *str); int str_bin(const String *str); int str_bin_unlocked(const String *str); int bin(const char *str); int str_hex(const String *str); int str_hex_unlocked(const String *str); int hex(const char *str); int str_oct(const String *str); int str_oct_unlocked(const String *str); int oct(const char *str); int strcasecmp(const char *s1, const char *s2); int strncasecmp(const char *s1, const char *s2, size_t n); size_t strlcpy(char *dst, const char *src, size_t size); size_t strlcat(char *dst, const char *src, size_t size); char *cstrcpy(char *dst, const char *src); char *cstrcat(char *dst, const char *src); char *cstrchr(const char *str, int c); char *cstrpbrk(const char *str, const char *brk); char *cstrrchr(const char *str, int c); char *cstrstr(const char *str, const char *srch); int asprintf(char **str, const char *format, ...); int vasprintf(char **str, const char *format, va_list args);
This module provides text strings that grow and shrink automatically and functions for manipulating them. Some of the functions were modelled on the list(3) module. Others were modelled on the string functions and operators in perlfunc(1) and perlop(1). Others came from OpenBSD.
String *str_create(const char *format, ...)
format
and the following arguments as in
sprintf(3). On success, returns the new string. It is the caller's
responsibility to deallocate the new string with str_release(3) or
str_destroy(3). On error, returns null
with errno
set
appropriately.
Warning: Do not under any circumstances ever pass a non-literal string as the format argument unless you know exactly how many conversions will take place. Being careless with this is a very good way to build potential security holes into your programs. The same is true for all functions that take a printf()-like format string as an argument.
String *str = str_create(buf); // EVIL String *str = str_create("%s", buf); // GOOD
String *str_create_with_locker(Locker *locker, const char *format, ...)
locker
.
String *str_vcreate(const char *format, va_list args)
String *str_vcreate_with_locker(Locker *locker, const char *format, va_list args)
locker
.
String *str_create_sized(size_t size, const char *format, ...)
format
and the following arguments as in
sprintf(3). The initial allocation for the string data is at least
size
bytes. On success, returns the new string. It is the caller's
responsibility to deallocate the new string with str_release(3) or
str_destroy(3). On error, returns null
with errno
set
appropriately.
String *str_create_with_locker_sized(Locker *locker, size_t size, const char *format, ...)
locker
.
String *str_vcreate_sized(size_t size, const char *format, va_list args)
String *str_vcreate_with_locker_sized(Locker *locker, size_t size, const char *format, va_list args)
locker
.
String *str_copy(const String *str)
str
. On success, returns the copy. It is the caller's
responsibility to deallocate the new string with str_release(3) or
str_destroy(3). On error, returns null
with errno
set
appropriately.
String *str_copy_unlocked(const String *str)
str
is not read locked.
String *str_copy_with_locker(Locker *locker, const String *str)
locker
.
String *str_copy_with_locker_unlocked(Locker *locker, const String *str)
str
is not read
locked.
String *str_fgetline(FILE *stream)
EOF
or the end of the line. A newline is placed in
the string. A nul
is placed after the last character in the buffer. On
success, returns a new String. It is the caller's responsibility to
deallocate the new string with str_release(3) or str_destroy(3). On
error, or when the end of file occurs while no characters have been read,
returns null
. Calls to this function can be mixed with calls to other
input functions from the stdio library on the same input stream.
String *str_fgetline_with_locker(Locker *locker, FILE *stream)
locker
.
void str_release(String *str)
str
.
void *str_destroy(String **str)
null
) *str
. Returns null
.
Note: strings shared by multiple threads must not be destroyed until
after all threads have finished with it.
int str_rdlock(const String *str)
str
(if str
was created with a Locker).
Clients must call this before calling cstr(3) (for the purpose of reading
the raw string data) on a string that was created with a Locker. It is
the client's responsibility to call str_unlock(3) when finished with the
raw string data. It is also needed when multiple read only str(3)
module functions need to be called atomically. It is the caller's
responsbility to call str_unlock(3) after the atomic operation. The only
functions that may be called on str
between calls to str_rdlock(3) and
str_unlock(3) are cstr(3) and any read only str(3) module
functions whose name ends with _unlocked
. On success, returns 0
. On
error, returns an error code.
int str_wrlock(const String *str)
str
(if str
was created with a Locker).
Clients need to call this before calling cstr(3) (for the purpose of
modifying the raw string data) on a string that was created with a
Locker. It is the client's responsibility to call str_unlock(3) when
finished with the raw string data. It is also needed when multiple
read/write str(3) module functions need to be called atomically.
It is the caller's responsbility to call str_unlock(3) after the atomic
operation. The only functions that may be called on str
between calls to
str_wrlock(3) and str_unlock(3) are cstr(3) and any
str(3) module functions whose name ends with _unlocked
. On
success, returns 0
. On error, returns an error code.
int str_unlock(const String *str)
str
obtained with str_rdlock(3) or
str_wrlock(3) (if str
was created with a Locker). On success,
returns 0
. On error, returns an error code.
int str_empty(const String *str)
str
is the empty string. On error, returns -1
with errno
set appropriately.
int str_empty_unlocked(const String *str)
str
is not read locked.
ssize_t str_length(const String *str)
str
. On error, returns -1
with errno
set
appropriately.
ssize_t str_length_unlocked(const String *str)
str
is not read locked.
char *cstr(const String *str)
str
. Do not use this pointer to extend the
length of the string. It's ok to use it to reduce the length of the string
provided you call str_set_length_unlocked(3) or
str_recalc_length_unlocked(3) immediately afterwards. When used on a
string that is shared by multiple threads, cstr(3) must appear between
calls to str_rdlock(3) or str_wrlock(3) and str_unlock(3).
ssize_t str_set_length(String *str, size_t length)
str
to length
. Only needed after the raw C string
returned by cstr(3) has been used to shorten a string. On success,
returns the length of str
. On error, returns -1
with errno
set
appropriately.
ssize_t str_set_length_unlocked(String *str, size_t length)
str
is not write locked.
ssize_t str_recalc_length(String *str)
str
. Only needed after the raw C
string returned by cstr(3) has been used to shorten a string. Note:
Treats str
as a nul
-terminated string and should be avoided. Use
str_set_length(3) instead. On success, returns the length of str
. On
error, returns -1
with errno
set appropriately.
ssize_t str_recalc_length_unlocked(String *str)
str
is not write
locked.
String *str_clear(String *str)
str
the empty string. On success, returns str
. On error, returns
null
with errno
set appropriately.
String *str_clear_unlocked(String *str)
str
is not write locked.
String *str_remove(String *str, ssize_t index)
index
'th character from str
. If index
is negative, it
refers to a character position relative to the end of the string (-1
is
the position after the last character, -2
is the position of the last
character and so on). On success, returns str
. On error, returns null
with errno
set appropriately.
String *str_remove_unlocked(String *str, ssize_t index)
str
is not write locked.
String *str_remove_range(String *str, ssize_t index, ssize_t range)
range
characters from str
starting at index
. If index
or
range
are negative, they refer to character positions relative to the end
of the string (-1
is the position after the last character, -2
is the
position of the last character and so on). On success, returns str
. On
error, returns null
with errno
set appropriately.
String *str_remove_range_unlocked(String *str, ssize_t index, ssize_t range)
str
is not write locked.
String *str_insert(String *str, ssize_t index, const char *format, ...)
format
to str
at position index
. If
index
is negative, it refers to a character position relative to the end
of the string (-1
is the position after the last character, -2
is the
position of the last character and so on). On success, returns str
. On
error, returns null
with errno
set appropriately.
String *str_insert_unlocked(String *str, ssize_t index, const char *format, ...)
str
is not write locked.
String *str_vinsert(String *str, ssize_t index, const char *format, va_list args)
String *str_vinsert_unlocked(String *str, ssize_t index, const char *format, va_list args)
str
is not write locked.
String *str_insert_str(String *str, ssize_t index, const String *src)
src
into str
, starting at position index
. If index
is
negative, it refers to a character position relative to the end of the
string (-1
is the position after the last character, -2
is the
position of the last character and so on). On success, returns str
. On
error, returns null
with errno
set appropriately.
String *str_insert_str_unlocked(String *str, ssize_t index, const String *src)
str
is not write locked
and src
is not read locked. Note: If src
needs to be read locked, it
is the caller's responsibility to lock and unlock it explicitly with
str_rdlock(3) and str_unlock(3).
String *str_append(String *str, const char *format, ...)
format
to str
. On success, returns
str
. On error, returns null
with errno
set appropriately.
String *str_append_unlocked(String *str, const char *format, ...)
str
is not write locked.
String *str_vappend(String *str, const char *format, va_list args)
String *str_vappend_unlocked(String *str, const char *format, va_list args)
str
is not write locked.
String *str_append_str(String *str, const String *src)
src
to str
. On success, returns str
. On error, returns
null
with errno
set appropriately.
String *str_append_str_unlocked(String *str, const String *src)
str
is not write locked
and src
is not read locked. Note: If src
needs to be read locked, it
is the caller's responsibility to lock and unlock it explicitly with
str_rdlock(3) and str_unlock(3).
String *str_prepend(String *str, const char *format, ...)
format
to str
. On success, returns
str
. On error, returns null
with errno
set appropriately.
String *str_prepend_unlocked(String *str, const char *format, ...)
str
is not write locked.
String *str_vprepend(String *str, const char *format, va_list args)
String *str_vprepend_unlocked(String *str, const char *format, va_list args)
str
is not write locked.
String *str_prepend_str(String *str, const String *src)
src
to str
. On success, returns str
. On error, returns
null
with errno
set appropriately.
String *str_prepend_str_unlocked(String *str, const String *src)
str
is not write locked
and src
is not read locked. Note: If src
needs to be read locked, it
is the caller's responsibility to lock and unlock it explicitly with
str_rdlock(3) and str_unlock(3).
String *str_replace(String *str, ssize_t index, ssize_t range, const char *format, ...)
range
characters in str
, starting at index
, with the
string specified by format
. If index
or range
are negative, they
refer to character positions relative to the end of the string (-1
is the
position after the last character, -2
is the position of the last
character and so on). On success, returns str
. On error, returns null
with errno
set appropriately.
String *str_replace_unlocked(String *str, ssize_t index, ssize_t range, const char *format, ...)
str
is not write locked.
String *str_vreplace(String *str, ssize_t index, ssize_t range, const char *format, va_list args)
String *str_vreplace_unlocked(String *str, ssize_t index, ssize_t range, const char *format, va_list args)
str
is not write locked.
String *str_replace_str(String *str, ssize_t index, ssize_t range, const String *src)
range
characters in str
, starting at index
, with src
.
If index
or range
are negative, they refer to character positions
relative to the end of the string (-1
is the position after the last
character, -2
is the position of the last character and so on). On
success, return str
. On error, returns null
with errno
set
appropriately.
String *str_replace_str_unlocked(String *str, ssize_t index, ssize_t range, const String *src)
str
is not write locked
and src
is not read locked. Note: If src
needs to be read locked, it
is the caller's responsibility to lock and unlock it explicitly with
str_rdlock(3) and str_unlock(3).
String *str_substr(const String *str, ssize_t index, ssize_t range)
range
characters from
str
, starting at index
. If index
or range
are negative, they
refer to character positions relative to the end of the string (-1
is the
position after the last character, -2
is the position of the last
character and so on). On success, returns the new string. It is the caller's
responsibility to deallocate the new string with str_release(3) or
str_destroy(3). On error, returns null
with errno
set
appropriately.
String *str_substr_unlocked(const String *str, ssize_t index, ssize_t range)
str
is not read locked.
String *str_substr_with_locker(Locker *locker, const String *str, ssize_t index, ssize_t range)
locker
.
String *str_substr_with_locker_unlocked(Locker *locker, const String *str, ssize_t index, ssize_t range)
str
is not read
locked.
String *substr(const char *str, ssize_t index, ssize_t range)
String *substr_with_locker(Locker *locker, const char *str, ssize_t index, ssize_t range)
locker
. Note that no locking is
performed on str
as it is a raw C string.
String *str_splice(String *str, ssize_t index, ssize_t range)
str
starting at index
of length range
characters. If index
or range
are negative, they refer to character
positions relative to the end of the string (-1
is the position after the
last character, -2
is the position of the last character and so on). On
success, returns the substring. It is the caller's responsibility to
deallocate the new substring with str_release(3) or str_destroy(3). On
error, returns null
with errno
set appropriately.
String *str_splice_unlocked(String *str, ssize_t index, ssize_t range)
str
is not write locked.
String *str_splice_with_locker(Locker *locker, String *str, ssize_t index, ssize_t range)
locker
.
String *str_splice_with_locker_unlocked(Locker *locker, String *str, ssize_t index, ssize_t range)
str
is not write
locked.
String *str_repeat(size_t count, const char *format, ...)
format
repeated count
times. On success, return the new string. It is the
caller's responsibility to deallocate the new string with str_release(3)
or str_destroy(3). On error, returns null
with errno
set
appropriately.
String *str_repeat_with_locker(Locker *locker, size_t count, const char *format, ...)
locker
.
String *str_vrepeat(size_t count, const char *format, va_list args)
String *str_vrepeat_with_locker(Locker *locker, size_t count, const char *format, va_list args)
locker
.
int str_tr(String *str, const char *from, const char *to, int option)
Transliterates all occurrences of the characters in from
with the
corresponding character in to
. On success, returns the number of
characters replaced or deleted. On error, returns -1
with errno
set
appropriately.
A character range may be specified with a hyphen, so str_tr(str, "A-J",
"0-9")
does the same replacement as str_tr(str, "ACEGIBDFHJ",
"0246813579")
.
Note also that the whole range idea is rather unportable between character sets - and even within character sets they may cause results you probably didn't expect. A sound principle is to use only ranges that begin from and end at either alphabets of equal case (a-e, A-E), or digits (0-4). Anything else is unsafe. If in doubt, spell out the character sets in full.
Options:
TR_COMPLEMENT Complement from. TR_DELETE Delete found but unreplaced characters. TR_SQUASH Squash duplicate replaced characters.
If TR_COMPLEMENT is specified, from
is complemented. If TR_DELETE is
specified, any characters specified by from
not found in to
are
deleted. (Note that this is slightly more flexible than the behavior of some
tr programs, which delete anything they find in from
.) If TR_SQUASH is
specified, sequences of characters that were transliterated to the same
character are squashed down to a single instance of the character.
If TR_DELETE is used, to
is always interpreted exactly as specified.
Otherwise, if to
is shorter than from
, the final character is
replicated till it is long enough. If to
is empty or null
, from
is
replicated. This latter is useful for counting characters in a class or for
squashing character sequences in a class.
Examples:
str_tr(s, "A-Z", "a-z", 0); // canonicalize to lower case str_tr(s, "a-z", "A-Z", 0); // canonicalize to upper case str_tr(s, "a-zA-Z", "A-Za-z", 0); // swap upper and lower case str_tr(s, "*", "*", 0); // count the stars in str str_tr(s, "0-9", "", 0); // count the digits in $_ str_tr(s, "a-zA-Z", "", TR_SQUASH); // bookkeeper -> bokeper str_tr(s, "a-zA-Z", " ", TR_COMPLEMENT | TR_SQUASH); // change non-alphas to single space str_tr(c, "a-zA-Z", "n-za-mN-ZA-M", 0); // Rot13
from = str_create("\200-\377"); to = str_create("%c-\177", '\000'); str_tr_str(s, from, to, 0); // clear 8th bit
If multiple transliterations are given for a character, only the first one is used:
str_tr(str, "AAA", "XYZ", 0);
will transliterate any A to X.
int str_tr_unlocked(String *str, const char *from, const char *to, int option)
str
is not write locked.
int str_tr_str(String *str, const String *from, const String *to, int option)
from
and to
are String
objects. This is needed when from
or to
need to contain nul
characters.
int str_tr_str_unlocked(String *str, const String *from, const String *to, int option)
str
is not write locked and
from
and to
are not read locked. Note: If to
and from
need to be
read locked, it is the caller's responsibility to lock and unlock them
explicitly with str_rdlock(3) and str_unlock(3).
int tr(char *str, const char *from, const char *to, int option)
StringTR *tr_compile(const char *from, const char *to, int option)
from
, to
and option
into a translation table to be passed
to str_tr_compiled(3) or tr_compiled(3). On success, returns the new
translation table. It is the caller's responsibility to deallocate the
translation table with tr_release(3) or tr_destroy(3). On error,
returns null
with errno
set appropriately.
StringTR *tr_compile_with_locker(Locker *locker, const char *from, const char *to, int option)
locker
.
StringTR *str_tr_compile(const String *from, const String *to, int option)
from
and to
are String
objects. This is needed when from
or to
need to contain nul
characters.
StringTR *str_tr_compile_unlocked(const String *from, const String *to, int option)
from
and to
are not
read locked.
StringTR *str_tr_compile_with_locker(Locker *locker, const String *from, const String *to, int option)
locker
.
StringTR *str_tr_compile_with_locker_unlocked(Locker *locker, const String *from, const String *to, int option)
from
and to
are not read locked. Note: If to
and from
need to be read locked, it
is the caller's responsibility to lock and unlock them explicitly with
str_rdlock(3) and str_unlock(3).
void tr_release(StringTR *table)
table
.
void *tr_destroy(StringTR **table)
null
) *table
. Returns null
.
Note: translation tables shared by multiple threads must not be destroyed
until after all threads have finished with it.
int str_tr_compiled(String *str, StringTR *table)
table
(as created by
tr_compile(3) or equivalent) on str
. Use this whenever the same
translation will be performed multiple times. On success, returns the number
of characters replaced or deleted. On error, returns -1
with errno
set
appropriately.
int str_tr_compiled_unlocked(String *str, StringTR *table)
str
is not write locked.
int tr_compiled(char *str, StringTR *table)
List *str_regexpr(const char *pattern, const String *text, int cflags, int eflags)
pattern
is a regular expression. text
is the
string to be searched for matches. cflags
is passed to regcomp(3)
along with REG_EXTENDED
. eflags
is passed to regexec(3). On
success, returns a List of (at most 33) Strings containing the
matching substring followed by the matching substrings of any parenthesised
subexpressions. It is the caller's responsibility to deallocate the list
with list_release(3) or list_destroy(3). On error (including no
match), returns null
with errno
set appropriately. Only use this
function when the regular expression will be used only once. Otherwise, use
regexpr_compile(3) or regcomp(3) and str_regexpr_compiled(3) or
regexpr_compiled(3) or regexec(3).
Note: If you require perl pattern matching, you could use Philip Hazel's
PCRE package, ftp://ftp.cus.cam.ac.uk/pub/software/programs/pcre/
or
link against the perl library itself.
List *str_regexpr_unlocked(const char *pattern, const String *text, int cflags, int eflags)
text
is not read locked.
List *str_regexpr_with_locker(Locker *locker, const char *pattern, const String *text, int cflags, int eflags)
locker
.
List *str_regexpr_with_locker_unlocked(Locker *locker, const char *pattern, const String *text, int cflags, int eflags)
text
is not read
locked.
List *regexpr(const char *pattern, const char *text, int cflags, int eflags)
List *regexpr_with_locker(Locker *locker, const char *pattern, const char *text, int cflags, int eflags)
locker
.
int regexpr_compile(regex_t *compiled, const char *pattern, int cflags)
compiled
is the
location in which to compile the expression. pattern
is the regular
expression. cflags
is passed to regcomp(3) along with REG_EXTENDED
.
Call this, followed by re_compiled(3) when the regular expression will be
used multiple times. On success, returns 0
. On error, returns an error
code.
void regexpr_release(regex_t *compiled)
List *str_regexpr_compiled(const regex_t *compiled, const String *text, int eflags)
compiled
is the compiled regular
expression prepared by regexpr_compile(3) or regcomp(3). text
is
the string to be searched for a match. eflags
is passed to regexec(3).
On success, returns a List of (at most 33) Strings containing the
matching substring followed by the matching substrings of any parenthesised
subexpressions. It is the caller's responsibility to deallocate the list
with list_release(3) or list_destroy(3). On error (including no
match), returns null
with errno
set appropriately.
List *str_regexpr_compiled_unlocked(const regex_t *compiled, const String *text, int eflags)
text
is not write
locked.
List *str_regexpr_compiled_with_locker(Locker *locker, const regex_t *compiled, const String *text, int eflags)
locker
.
List *str_regexpr_compiled_with_locker_unlocked(Locker *locker, const regex_t *compiled, const String *text, int eflags)
text
is
not read locked.
List *regexpr_compiled(const regex_t *compiled, const char *text, int eflags)
List *regexpr_compiled_with_locker(Locker *locker, const regex_t *compiled, const char *text, int eflags)
locker
.
String *str_regsub(const char *pattern, const char *replacement, String *text, int cflags, int eflags, int all)
pattern
is a regular expression.
text
is the string to be searched for matches. cflags
is passed to
regcomp(3) along with REG_EXTENDED
. eflags
is passed to
regexec(3). all
specifies whether to substitute the first match (if
zero) or all matches (if non-zero). replacement
specifies the string that
replaces each match. If replacement
contains "$#"
or "${##}"
(where
"#"
is a decimal digit), the substring that matches the corresponding
subexpression is interpolated in its place. Up to 32 subexpressions are
supported. If replacement
contains "$$"
, then "$"
is interpolated
in its place. The following perl(1) quote escape sequences are also
understood:
\l lowercase next character \u uppercase next character \L lowercase until matching \E \U uppercase until matching \E \Q backslash non-alphanumeric characters until matching \E \E end case/quotemeta modification
Note that these sequences don't behave exactly like in perl(1). Namely,
an \l
appearing between a \U
and an \E
does lowercase the next
character and a \E
sequence without a matching \L
, \U
or \Q
is
an error. Also note that only 32 levels of nesting are supported.
On success, returns text
. On error (including no match), returns null
with errno
set appropriately. Only use this function when the regular
expression will be used only once. Otherwise, use regexpr_compile(3) or
regcomp(3) and str_regsub_compiled(3).
String *str_regsub_unlocked(const char *pattern, const char *replacement, String *text, int cflags, int eflags, int all)
text
is not write locked.
String *str_regsub_compiled(const regex_t *compiled, const char *replacement, String *text, int eflags, int all)
compiled
.
String *str_regsub_compiled_unlocked(const regex_t *compiled, const char *replacement, String *text, int eflags, int all)
text
is not write
locked.
List *str_fmt(const String *str, size_t line_width, StringAlignment alignment)
str
into a List of String objects with length no greater
than line_width
(unless there are individual words longer than
line_width
) with the alignment specified by alignment
:
ALIGN_LEFT
('<'
)ALIGN_RIGHT
('>')ALIGN_CENTRE
or ALIGN_CENTER
('|'
)str
will be split into lines at each newline character ('\n'
). The
lines will then be centred (with one space between words) padded with spaces
to the left.
ALIGN_FULL
('='
)On success, returns a new List of String objects. It is the caller's
responsibility to deallocate the list with list_release(3) or
list_destroy(3). On error, returns null
with errno
set
appropriately. Note that str
is interpreted as a nul
-terminated
string.
Note: str_fmt(3) provides straightforward formatting completely lacking in any aesthetic sensibilities. If you need awesome paragraph formatting, pipe text through par(1) instead (available from http://www.cs.berkeley.edu/~amc/Par/|http://www.cs.berkeley.edu/~amc/Par/).
List *str_fmt_unlocked(const String *str, size_t line_width, StringAlignment alignment)
str
is not read locked.
List *str_fmt_with_locker(Locker *locker, const String *str, size_t line_width, StringAlignment alignment)
locker
.
List *str_fmt_with_locker_unlocked(Locker *locker, const String *str, size_t line_width, StringAlignment alignment)
str
is not read
locked.
List *fmt(const char *str, size_t line_width, StringAlignment alignment)
List *fmt_with_locker(Locker *locker, const char *str, size_t line_width, StringAlignment alignment)
locker
.
List *str_split(const String *str, const char *delim)
str
into tokens separated by sequences of characters occurring in
delim
. On success, returns a new List of String objects. It is the
caller's responsibility to deallocate the list with list_release(3) or
list_destroy(3). On error, returns null
with errno
set
appropriately.
List *str_split_unlocked(const String *str, const char *delim)
str
is not read locked.
List *str_split_with_locker(Locker *locker, const String *str, const char *delim)
locker
.
List *str_split_with_locker_unlocked(Locker *locker, const String *str, const char *delim)
str
is not read
locked.
List *split(const char *str, const char *delim)
List *split_with_locker(Locker *locker, const char *str, const char *delim)
locker
.
List *str_regexpr_split(const String *str, const char *delim, int cflags, int eflags)
str
into tokens separated by occurrences of the regular
expression, delim
. str
is interpreted as a nul
-terminated C string.
cflags
is passed to regcomp(3) aling with REG_EXTENDED
and
eflags
is passed to regexec(3). On success, returns a new List of
String objects. It is the caller's responsibility to deallocate the list
with list_release(3) or list_destroy(3). On error, returns null
with errno
set appropriately.
List *str_regexpr_split_unlocked(const String *str, const char *delim, int cflags, int eflags)
str
is not read locked.
List *str_regexpr_split_with_locker(Locker *locker, const String *str, const char *delim, int cflags, int eflags)
locker
.
List *str_regexpr_split_with_locker_unlocked(Locker *locker, const String *str, const char *delim, int cflags, int eflags)
str
is not
read locked.
List *regexpr_split(const char *str, const char *delim, int cflags, int eflags)
List *regexpr_split_with_locker(Locker *locker, const char *str, const char *delim, int cflags, int eflags)
locker
.
String *str_join(const List *list, const char *delim)
list
with delim
inserted between each
one. On success, returns the resulting String. It is the caller's
responsibility to deallocate the string with str_release(3) or
str_destroy(3). On error, returns null
with errno
set
appropriately.
String *str_join_unlocked(const List *list, const char *delim)
list
is not read locked.
String *str_join_with_locker(Locker *locker, const List *list, const char *delim)
locker
.
String *str_join_with_locker_unlocked(Locker *locker, const List *list, const char *delim)
list
is not read
locked.
String *join(const List *list, const char *delim)
String *join_with_locker(Locker *locker, const List *list, const char *delim)
locker
.
int str_soundex(const String *str)
str
as an integer. On error, returns -1
with errno
set appropriately.
int str_soundex_unlocked(const String *str)
str
is not read locked.
int soundex(const char *str)
String *str_trim(String *str)
str
. On success, returns
str
. On error, returns null
with errno
set appropriately.
String *str_trim_unlocked(String *str)
str
is not write locked.
char *trim(char *str)
String *str_trim_left(String *str)
str
. On success, returns str
. On error,
returns null
with errno
set appropriately.
String *str_trim_left_unlocked(String *str)
str
is not write locked.
char *trim_left(char *str)
String *str_trim_right(String *str)
str
. On success, returns str
. On error,
returns null
with errno
set appropriately.
String *str_trim_right_unlocked(String *str)
str
is not write locked.
char *trim_right(char *str)
String *str_squeeze(String *str)
str
and replaces all other
sequences of whitespace with a single space. On success, returns str
. On
error, returns null
with errno
set appropriately.
String *str_squeeze_unlocked(String *str)
str
is not write locked.
char *squeeze(char *str)
String *str_quote(const String *str, const char *quotable, char quote_char)
str
with every occurrence of any
character in quotable
preceeded by quote_char
. On success, returns the
new string. It is the caller's responsibility to deallocate the new string
with str_release(3) or str_destroy(3). On error, returns null
with
errno
set appropriately.
String *str_quote_unlocked(const String *str, const char *quotable, char quote_char)
str
is not read locked.
String *str_quote_with_locker(Locker *locker, const String *str, const char *quotable, char quote_char)
locker
.
String *str_quote_with_locker_unlocked(Locker *locker, const String *str, const char *quotable, char quote_char)
str
is not read locked.
String *quote(const char *str, const char *quotable, char quote_char)
String *quote_with_locker(Locker *locker, const char *str, const char *quotable, char quote_char)
locker
.
String *str_unquote(const String *str, const char *quotable, char quote_char)
str
with every occurrence of
quote_char
that is followed by any character in quotable
removed. On
success, returns the new String. It is the caller's responsibility to
deallocate the new string with str_release(3) or str_destroy(3). On
error, returns null
with errno
set appropriately.
String *str_unquote_unlocked(const String *str, const char *quotable, char quote_char)
str
is not read locked.
String *str_unquote_with_locker(Locker *locker, const String *str, const char *quotable, char quote_char)
locker
.
String *str_unquote_with_locker_unlocked(Locker *locker, const String *str, const char *quotable, char quote_char)
str
is not read
locked.
String *unquote(const char *str, const char *quotable, char quote_char)
String *unquote_with_locker(Locker *locker, const char *str, const char *quotable, char quote_char)
locker
.
String *str_encode(const String *str, const char *uncoded, const char *coded, char quote_char, int printable)
str
with every occurrence in str
of characters in
uncoded
replaced with quote_char
followed by the corresponding (by
position) character in coded
. If printable
is non-zero, other
non-printable characters are replaced with their ASCII codes in hexadecimal.
It is the caller's responsibility to deallocate the new string with
str_release(3) or str_destroy(3). On error, returns null
with
errno
set appropriately.
Example:
// Encode a string into a C string literal str_encode(str, "\a\b\t\n\v\f\r\\", "abtnvfr\\", '\\', 1);
// Decode a C string literal str_decode(str, "\a\b\t\n\v\f\r\\", "abtnvfr\\", '\\', 1);
String *str_encode_unlocked(const String *str, const char *uncoded, const char *coded, char quote_char, int printable)
str
is not read locked.
String *str_encode_with_locker(Locker *locker, const String *str, const char *uncoded, const char *coded, char quote_char, int printable)
locker
.
String *str_encode_with_locker_unlocked(Locker *locker, const String *str, const char *uncoded, const char *coded, char quote_char, int printable)
str
is not read
locked.
String *str_decode(const String *str, const char *uncoded, const char *coded, char quote_char, int printable)
str
with every occurrence in str
of quote_char
followed by a character in coded
replaced with the corresponding (by
position) character in uncoded
. If printable
is non-zero, every
occurrence in str
of an ASCII code in octal or hexadecimal (i.e. ``\ooo''
or ``\xhh'') is replaced with the corresponding ASCII character. It is the
caller's responsibility to deallocate the new string with str_release(3)
or str_destroy(3). On error, returns null
with errno
set
appropriately.
String *str_decode_unlocked(const String *str, const char *uncoded, const char *coded, char quote_char, int printable)
str
is not read locked.
String *str_decode_with_locker(Locker *locker, const String *str, const char *uncoded, const char *coded, char quote_char, int printable)
locker
.
String *str_decode_with_locker_unlocked(Locker *locker, const String *str, const char *uncoded, const char *coded, char quote_char, int printable)
str
is not read
locked.
String *encode(const char *str, const char *uncoded, const char *coded, char quote_char, int printable)
String *encode_with_locker(Locker *locker, const char *str, const char *uncoded, const char *coded, char quote_char, int printable)
locker
.
String *decode(const char *str, const char *uncoded, const char *coded, char quote_char, int printable)
String *decode_with_locker(Locker *locker, const char *str, const char *uncoded, const char *coded, char quote_char, int printable)
locker
.
String *str_lc(String *str)
str
into lower case. On success, returns str
. On error,
returns null
with errno
set appropriately.
String *str_lc_unlocked(String *str)
str
is not write locked.
char *lc(char *str)
str
into lower case. On success, returns str
. On error,
returns null
with errno
set appropriately.
String *str_lcfirst(String *str)
str
into lower case. On success, returns
str
. On error, returns null
with errno
set appropriately.
String *str_lcfirst_unlocked(String *str)
str
is not write locked.
char *lcfirst(char *str)
str
into lower case. On success, returns
str
. On error, returns null
with errno
set appropriately.
String *str_uc(String *str)
str
into upper case. On success, returns str
. On error,
returns null
with errno
set appropriately.
String *str_uc_unlocked(String *str)
str
is not write locked.
char *uc(char *str)
str
into upper case. On success, returns str
. On error,
returns null
with errno
set appropriately.
String *str_ucfirst(String *str)
str
into upper case. On success, returns
str
. On error, returns null
with errno
set appropriately.
String *str_ucfirst_unlocked(String *str)
str
is not write locked.
char *ucfirst(char *str)
str
into upper case. On success, returns
str
. On error, returns null
with errno
set appropriately.
int str_chop(String *str)
str
. On success, returns the character
chopped. On error, returns -1
with errno
set appropriately.
int str_chop_unlocked(String *str)
str
is not write locked.
int chop(char *str)
str
. On success, returns the character
chopped. On error, returns -1
with errno
set appropriately.
int str_chomp(String *str)
str
. On success, returns the number of
characters chomped. On error, returns -1
with errno
set appropriately.
int str_chomp_unlocked(String *str)
str
is not write locked.
int chomp(char *str)
str
. On success, returns the number of
characters chomped. On error, returns -1
with errno
set appropriately.
int str_bin(const String *str)
str
. str
may
either be a string of [0-1]
or "0b"
followed by a string of [0-1]
.
On error, returns -1
with errno
set appropriately.
int str_bin_unlocked(const String *str)
str
is not read locked.
int bin(const char *str)
str
. str
may
either be a string of [0-1]
or "0b"
followed by a string of [0-1]
.
On error, returns -1
with errno
set appropriately.
int str_hex(const String *str)
str
. str
may
either be a string of [0-9a-fA-F]
or "0x"
followed by a string of
[0-9a-fA-f]
. On error, returns -1
with errno
set appropriately.
int str_hex_unlocked(const String *str)
str
is not read locked.
int hex(const char *str)
str
. str
may
either be a string of [0-9a-fA-F]
or "0x"
followed by a string of
[0-9a-fA-f]
. On error, returns -1
with errno
set appropriately.
int str_oct(const String *str)
str
. str
may either be "0x"
followed by a string of [0-9a-fA-F]
(hexadecimal), "0b"
followed by a string of [0-1]
(binary) or "0"
followed by a a string of [0-7]
(octal). On error, returns -1
with
errno
set appropriately.
int str_oct_unlocked(const String *str)
str
is not read locked.
int oct(const char *str)
str
. str
may either be "0x"
followed by a string of [0-9a-fA-F]
(hexadecimal), "0b"
followed by a string of [0-1]
(binary) or "0"
followed by a a string of [0-7]
(octal). On error, returns -1
with
errno
set appropriately.
s1
and s2
, ignoring the case of the characters.
It returns an integer less than, equal to, or greater than zero if s1
is
found to be less than, equal to, or greater than s2
, respectively.
n
characters.
src
into dst
(which is size
bytes long). The result, dst
,
will be no longer than size - 1
bytes and will be nul
terminated
(unless size
is zero). This is similar to strncpy(3) except that it
always terminates the string with a nul
byte (so it's safer) and it
doesn't fill the remainder of the buffer with nul
bytes (so it's faster).
Returns the length of src
(If this is >= size
, truncation occurred).
Use this rather than strcpy(3) or strncpy(3).
src
to dst
(which is size
bytes long). The result, dst
,
will be no longer than size - 1
bytes and will be nul
terminated
(unless size
is zero). This is similar to strncat(3) except that the
last argument is the size of the buffer, not the amount of space available.
(so it's more intuitive and hence safer). Returns the sum of the lengths of
src
and dst
(If this is >= size
, truncation occurred). Use this
rather than strcat(3) or strncat(3).
char *cstrcpy(char *dst, const char *src)
src
(including the terminating nul
character) to the array pointed to by dst
. The memory areas may not
overlap. The array dst
must be large enough to store the copy - unless
you know that this is the case, use strlcpy() instead. This is just like
strcpy(3) except that instead of returning dst
(which you already
know), this function returns the address of the terminating nul
character
(dst + strlen(src)
).
char *cstrcat(char *dst, const char *src)
src
to the string dst
The strings may not overlap.
The string dst
must be large enough to store the appended copy of
src
- unless you know that this is the case, use strlcat() instead. This
is just like strcat(3) except that instead of returning dst
(which you
already know), this function returns the address of the terminating nul
character (dst + strlen(dst) + strlen(src)
).
char *cstrchr(const char *str, int c)
str
looking for the character c
. Returns a pointer to
the first occurrence of the character c
in the string str
. This is
just like strchr(3) except that instead of returning null
when c
does not appear in str
, this function returns the address of the
terminating nul
character (str + strlen(str)
).
char *cstrpbrk(const char *str, const char *brk)
str
looking for any of the characters in brk
. Returns
a pointer to the first occurrence of any character in brk
in the string
str
. This is just like strpbrk(3) except that instead of returning
null
when no match is found in str
, this function returns the address
of the terminating nul
character (str + strlen(str)
).
char *cstrrchr(const char *str, int c)
str
looking for the character c
. Returns a pointer to
the last occurrence of the character c
in the string str
. This is just
like strrchr(3) except that instead of returning null
when c
does
not appear in str
, this function returns the address of the terminating
nul
character (str + strlen(str)
).
char *cstrstr(const char *str, const char *srch)
str
looking for the string srch
. Returns a pointer to
the first occurrence of the string srch
in the string str
. This is
just like strstr(3) except that instead of returning null
when srch
does not appear in str
, this function returns the address of the
terminating nul
character (str + strlen(str)
).
format
and
subsequent arguments into a buffer supplied by the caller, they are
formatted into a buffer that is internally allocated and stored in *str
.
On success, returns the number of bytes stored in *str
excluding the
terminating nul
character. On error, returns -1
and stores null
in
*str
.
On error, errno
is set either by an underlying function, or as follows:
MT-Disciplined
By default, Strings are not MT-Safe because most programs are single threaded and synchronisation doesn't come for free. Even in multi threaded programs, not all Strings are necessarily shared between multiple threads.
When a String is shared between multiple threads which need to be synchronised, the method of synchronisation must be carefully selected by the client code. There are tradeoffs between concurrency and overhead. The greater the concurrency, the greater the overhead. More locks give greater concurrency but have greater overhead. Readers/Writer locks can give greater concurrency than Mutex locks but have greater overhead. One lock for each String may be required, or one lock for all (or a set of) Strings may be more appropriate.
Generally, the best synchronisation strategy for a given application can only be determined by testing/benchmarking the written application. It is important to be able to experiment with the synchronisation strategy at this stage of development without pain.
To facilitate this, Strings can be created with string_create_with_locker(3) which takes a Locker argument. The Locker specifies a lock and a set of functions for manipulating the lock. Each String can have it's own lock by creating a separate Locker for each String. Multiple Strings can share the same lock by sharing the same Locker. Only the application developer can determine what is appropriate for each application on a string by string basis.
MT-Disciplined means that the application developer has a mechanism for specifying the synchronisation requirements to be applied to library code.
MT-Safe - str_fgetline(3)
Mac OS X doesn't have flockfile(3), funlockfile(3) or getc_unlocked(3). fgetline(3) is not MT-Safe on such platforms. You must guard all stdio calls with explicit synchronisation variables.
Doesn't support multibyte/widechar strings, UTF8, UNICODE or ISO 10646 but support can probably be layered over the top of String.
The delim
parameter to the split(3) and join(3) functions is an
ordinary C string so it can't contain nul
characters.
The quotable
parameter to the quote(3) and unquote(3) functions is
an ordinary C string so it can't contain nul
characters.
The uncoded
and coded
parameters to the str_encode(3) and
str_decode(3) functions are ordinary C strings so they can't contain
nul
characters.
Uses malloc(3). The type of memory used and the allocation strategy need to be decoupled from this code.
libslack(3), locker(3), string(3), regcomp(3), regexec(3), regerror(3), regfree(3), perlfunc(1), perlop(1)
20020916 raf <raf@raf.org>