Index: ossp-pkg/str/LICENSE RCS File: /v/ossp/cvs/ossp-pkg/str/LICENSE,v co -q -kk -p'1.2' '/v/ossp/cvs/ossp-pkg/str/LICENSE,v' | diff -u /dev/null - -L'ossp-pkg/str/LICENSE' 2>/dev/null --- ossp-pkg/str/LICENSE +++ - 2024-05-11 07:59:34.160085481 +0200 @@ -0,0 +1,22 @@ + + Str - String Library + Copyright (c) 1999-2001 Ralf S. Engelschall + + Permission to use, copy, modify, and distribute this software for + any purpose with or without fee is hereby granted, provided that + the above copyright notice and this permission notice appear in all + copies. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + Index: ossp-pkg/str/Makefile.in RCS File: /v/ossp/cvs/ossp-pkg/str/Makefile.in,v rcsdiff -q -kk '-r1.33' '-r1.34' -u '/v/ossp/cvs/ossp-pkg/str/Makefile.in,v' 2>/dev/null --- Makefile.in 2001/08/16 12:16:51 1.33 +++ Makefile.in 2001/08/16 13:21:22 1.34 @@ -1,6 +1,6 @@ ## ## Str - String Library -## Copyright (c) 1999-2000 Ralf S. Engelschall +## Copyright (c) 1999-2001 Ralf S. Engelschall ## ## This file is part of Str, a string handling and manipulation ## library which can be found at http://www.engelschall.com/sw/str/. Index: ossp-pkg/str/README RCS File: /v/ossp/cvs/ossp-pkg/str/README,v rcsdiff -q -kk '-r1.13' '-r1.14' -u '/v/ossp/cvs/ossp-pkg/str/README,v' 2>/dev/null --- README 2000/07/14 15:24:16 1.13 +++ README 2001/08/16 13:21:22 1.14 @@ -17,7 +17,7 @@ COPYRIGHT AND LICENSE - Copyright (c) 1999-2000 Ralf S. Engelschall + Copyright (c) 1999-2001 Ralf S. Engelschall This product includes software developed by the University of California, Berkeley and its contributors. This product includes Index: ossp-pkg/str/configure RCS File: /v/ossp/cvs/ossp-pkg/str/Attic/configure,v rcsdiff -q -kk '-r1.12' '-r1.13' -u '/v/ossp/cvs/ossp-pkg/str/Attic/configure,v' 2>/dev/null --- configure 2001/08/16 12:24:24 1.12 +++ configure 2001/08/16 13:21:22 1.13 @@ -24,7 +24,7 @@ # friendly header ;) echo "Configuring ${TB}Str${TN} (String Library), Version ${TB}${STR_VERSION_STR}${TN}" - echo "Copyright (c) 1999-2000 Ralf S. Engelschall " + echo "Copyright (c) 1999-2001 Ralf S. Engelschall " # additionally find out hex version STR_VERSION_HEX="`$ac_shtool version -l c -d hex $ac_srcdir/str_version.c`" Index: ossp-pkg/str/configure.ac RCS File: /v/ossp/cvs/ossp-pkg/str/configure.ac,v rcsdiff -q -kk '-r1.2' '-r1.3' -u '/v/ossp/cvs/ossp-pkg/str/configure.ac,v' 2>/dev/null --- configure.ac 2001/08/16 12:24:24 1.2 +++ configure.ac 2001/08/16 13:21:22 1.3 @@ -9,7 +9,7 @@ AC_HEADLINE(dnl Str, String Library, dnl STR_VERSION, str_version.c, dnl -[Copyright (c) 1999-2000 Ralf S. Engelschall ]) +[Copyright (c) 1999-2001 Ralf S. Engelschall ]) AC_CONFIG_HEADER(str_config.h) AC_PREFIX_DEFAULT(/usr/local) AC_PLATFORM(PLATFORM) Index: ossp-pkg/str/str-config.in RCS File: /v/ossp/cvs/ossp-pkg/str/str-config.in,v co -q -kk -p'1.3' '/v/ossp/cvs/ossp-pkg/str/str-config.in,v' | diff -u /dev/null - -L'ossp-pkg/str/str-config.in' 2>/dev/null --- ossp-pkg/str/str-config.in +++ - 2024-05-11 07:59:34.189472183 +0200 @@ -0,0 +1,143 @@ +#!/bin/sh +## +## Str - String Library +## Copyright (c) 1999-2001 Ralf S. Engelschall +## +## This file is part of Str, a string handling and manipulation +## library which can be found at http://www.engelschall.com/sw/str/. +## +## Permission to use, copy, modify, and distribute this software for +## any purpose with or without fee is hereby granted, provided that +## the above copyright notice and this permission notice appear in all +## copies. +## +## THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR +## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +## SUCH DAMAGE. +## +## str-config.in: Configuration Tool +## + +DIFS=' +' + +prefix="@prefix@" +exec_prefix="@exec_prefix@" + +str_prefix="$prefix" +str_exec_prefix="$exec_prefix" +str_bindir="@bindir@" +str_libdir="@libdir@" +str_includedir="@includedir@" +str_mandir="@mandir@" +str_datadir="@datadir@" +str_acdir="@datadir@/aclocal" +str_cflags="@CFLAGS@" +str_ldflags="@LDFLAGS@" +str_libs="@LIBS@" +str_version="@PTH_VERSION_STR@" + +help=no +version=no + +usage="str-config" +usage="$usage [--help] [--version] [--all]" +usage="$usage [--prefix] [--exec-prefix] [--bindir] [--libdir] [--includedir] [--mandir] [--datadir] [--acdir]" +usage="$usage [--cflags] [--ldflags] [--libs]" +if [ $# -eq 0 ]; then + echo "str-config:Error: Invalid option" 1>&2 + echo "str-config:Usage: $usage" 1>&2 + exit 1 +fi +output='' +output_extra='' +all=no +prev='' +OIFS="$IFS" IFS="$DIFS" +for option +do + if [ ".$prev" != . ]; then + eval "$prev=\$option" + prev='' + continue + fi + case "$option" in + -*=*) optarg=`echo "$option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg='' ;; + esac + case "$option" in + --help|-h) + echo "Usage: $usage" + exit 0 + ;; + --version|-v) + echo "Str $str_version" + exit 0 + ;; + --all) + all=yes + ;; + --prefix) + output="$output $str_prefix" + ;; + --exec-prefix) + output="$output $str_exec_prefix" + ;; + --bindir) + output="$output $str_bindir" + ;; + --libdir) + output="$output $str_libdir" + ;; + --includedir) + output="$output $str_includedir" + ;; + --mandir) + output="$output $str_mandir" + ;; + --datadir) + output="$output $str_datadir" + ;; + --acdir) + output="$output $str_acdir" + ;; + --cflags) + output="$output -I$str_includedir" + output_extra="$output_extra $str_cflags" + ;; + --ldflags) + output="$output -L$str_libdir" + output_extra="$output_extra $str_ldflags" + ;; + --libs) + output="$output -lstr" + output_extra="$output_extra $str_libs" + ;; + * ) + echo "str-config:Error: Invalid option" 1>&2 + echo "str-config:Usage: $usage" 1>&2 + exit 1; + ;; + esac +done +IFS="$OIFS" +if [ ".$prev" != . ]; then + echo "str-config:Error: missing argument to --`echo $prev | sed 's/_/-/g'`" 1>&2 + exit 1 +fi +if [ ".$output" != . ]; then + if [ ".$all" = .yes ]; then + output="$output $output_extra" + fi + echo $output +fi + Index: ossp-pkg/str/str-config.pod RCS File: /v/ossp/cvs/ossp-pkg/str/str-config.pod,v co -q -kk -p'1.3' '/v/ossp/cvs/ossp-pkg/str/str-config.pod,v' | diff -u /dev/null - -L'ossp-pkg/str/str-config.pod' 2>/dev/null --- ossp-pkg/str/str-config.pod +++ - 2024-05-11 07:59:34.192092404 +0200 @@ -0,0 +1,159 @@ +## +## Str - String Library +## Copyright (c) 1999-2001 Ralf S. Engelschall +## +## This file is part of Str, a string handling and manipulation +## library which can be found at http://www.engelschall.com/sw/str/. +## +## Permission to use, copy, modify, and distribute this software for +## any purpose with or without fee is hereby granted, provided that +## the above copyright notice and this permission notice appear in all +## copies. +## +## THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR +## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +## SUCH DAMAGE. +## +## str-config.pod: Unix manual page for str-config +## + +=pod + +=head1 NAME + +B - Str library build utility + +=head1 VERSION + +Str STR_VERSION_STR + +=head1 SYNOPSIS + +B +[B<--help>] +[B<--version>] +[B<--all>] +[B<--prefix>] +[B<--exec-prefix>] +[B<--bindir>] +[B<--libdir>] +[B<--includedir>] +[B<--mandir>] +[B<--datadir>] +[B<--acdir>] +[B<--cflags>] +[B<--ldflags>] +[B<--libs>] + +=head1 DESCRIPTION + +The B program is a little helper utility for easy configuring and +building applications based on the str(3) library. It can be used to query the +C compiler and linker flags which are required to correctly compile and link +the application against the str(3) library. + +=head1 OPTIONS + +B accepts the following options: + +=over 4 + +=item B<--help> + +Prints the short usage information. + +=item B<--version> + +Prints the version number and date of the installed str(3) library. + +=item B<--all> + +Forces the output of all flags, that is, including extra flags which are not +B specific. + +=item B<--prefix> + +Prints the installation prefix of architecture independent files + +=item B<--exec-prefix> + +Prints the installation prefix of architecture dependent files. + +=item B<--bindir> + +Prints the installation directory of binaries. + +=item B<--libdir> + +Prints the installation directory of libraries. + +=item B<--includedir> + +Prints the installation directory of include headers. + +=item B<--mandir> + +Prints the installation directory of manual pages. + +=item B<--datadir> + +Prints the installation directory of shared data. + +=item B<--acdir> + +Prints the installation directory of B data. + +=item B<--cflags> + +Prints the C compiler flags which are needed to compile the str(3)-based +application. The output is usually added to the C variable of the +applications C. + +=item B<--ldflags> + +Prints the linker flags (C<-L>) which are needed to link the application with +the str(3) library. The output is usually added to the C variable of +the applications C. + +=item B<--libs> + +Prints the library flags (C<-l>) which are needed to link the application with +the str(3) library. The output is usually added to the C variable of the +applications C. + +=back + +=head1 EXAMPLE + + CC = cc + CFLAGS = -O `str-config --cflags` + LDFLAGS = `str-config --ldflags` + LIBS = -lm `str-config --libs` + + all: foo + foo: foo.o + $(CC) $(LDFLAGS) -o foo foo.o $(LIBS) + foo.o: foo.c + $(CC) $(CFLAGS) -c foo.c + +=head1 SEE ALSO + +str(3). + +=head1 AUTHOR + + Ralf S. Engelschall + rse@engelschall.com + www.engelschall.com + +=cut + Index: ossp-pkg/str/str.h RCS File: /v/ossp/cvs/ossp-pkg/str/Attic/str.h,v co -q -kk -p'1.21' '/v/ossp/cvs/ossp-pkg/str/Attic/str.h,v' | diff -u /dev/null - -L'ossp-pkg/str/str.h' 2>/dev/null --- ossp-pkg/str/str.h +++ - 2024-05-11 07:59:34.194706880 +0200 @@ -0,0 +1,109 @@ +/* +** Str - String Library +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of Str, a string handling and manipulation +** library which can be found at http://www.engelschall.com/sw/str/. +** +** Permission to use, copy, modify, and distribute this software for +** any purpose with or without fee is hereby granted, provided that +** the above copyright notice and this permission notice appear in all +** copies. +** +** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR +** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. +** +** str.h: public API header +*/ + +#ifndef _STR_H_ +#define _STR_H_ + + /* C++ support */ +#ifdef __cplusplus +#define BEGIN_DECLARATION extern "C" { +#define END_DECLARATION } +#else +#define BEGIN_DECLARATION /*nop*/ +#define END_DECLARATION /*nop*/ +#endif + +#include +#include +#include +#include + +/* true and false boolean values and corresponding type */ +#undef TRUE +#undef FALSE +#undef BOOL +#ifdef __cplusplus +#define BOOL bool +#define TRUE true +#define FALSE false +#else +#define BOOL char +#define TRUE ((BOOL)(1 == 1)) +#define FALSE ((BOOL)(0 == 1)) +#endif + +/* null values for pointers and characters */ +#ifndef NULL +#define NULL ((void *)0) +#endif +#ifndef NUL +#define NUL '\0' +#endif + +BEGIN_DECLARATION + +typedef unsigned int str_size_t; + +#define STR_RIGHT (1 << 0) /* operate from right end */ +#define STR_COMPLEMENT (1 << 1) /* use complement */ +#define STR_NOCASE (1 << 2) /* no case sensitive operation */ +#define STR_STRIPQUOTES (1 << 3) /* strip quote characters */ +#define STR_BACKSLASHESC (1 << 4) /* enable ANSI C style (backslashed) escape sequences */ +#define STR_SKIPDELIMS (1 << 5) /* skip trailing delimiters before return */ +#define STR_TRIGRAPHS (1 << 6) /* enable ANSI C trigraph processing (implies STR_BACKSLASHESCAPE) */ + +#define STR_HASH_DJBX33 (1 << 0) /* Daniel J. Bernstein: Times 33 */ +#define STR_HASH_BJDDJ (1 << 1) /* Bob Jenkins: Dr. Dobbs Journal */ +#define STR_HASH_MACRC32 (1 << 2) /* Mark Adler: Cyclic Redudancy Check 32 */ + +#define STR_BASE64_ENCODE (1 << 0) /* encode: string -> base64 */ +#define STR_BASE64_DECODE (1 << 1) /* decode: base64 -> string */ +#define STR_BASE64_STRICT (1 << 2) /* strict encoding with no more than 72 chars/line */ + +extern str_size_t str_len (const char *); +extern char *str_copy (char *, const char *, str_size_t); +extern char *str_dup (const char *, str_size_t); +extern char *str_concat (char *, ...); +extern char *str_splice (char *, str_size_t, str_size_t, char *, str_size_t); +extern char *str_token (char **, const char *, const char *, const char *, int); +extern int str_parse (const char *, const char *, ...); +extern int str_compare (const char *, const char *, str_size_t, int); +extern char *str_span (const char *, str_size_t, const char *, int); +extern char *str_locate (const char *, str_size_t, const char *); +extern int str_format (char *, str_size_t, const char *, ...); +extern unsigned long str_hash (const char *, str_size_t, int); +extern int str_base64 (char *, str_size_t, unsigned char *, str_size_t, int); + +extern char *str_concat_va (char *, va_list); +extern int str_parse_va (const char *, const char *, va_list); +extern int str_format_va (char *, str_size_t, const char *, va_list); + +END_DECLARATION + +#endif /* _STR_H_ */ + Index: ossp-pkg/str/str.pod RCS File: /v/ossp/cvs/ossp-pkg/str/str.pod,v rcsdiff -q -kk '-r1.27' '-r1.28' -u '/v/ossp/cvs/ossp-pkg/str/str.pod,v' 2>/dev/null --- str.pod 2001/08/16 13:17:00 1.27 +++ str.pod 2001/08/16 13:21:22 1.28 @@ -1,6 +1,6 @@ ## ## Str - String Library -## Copyright (c) 1999-2000 Ralf S. Engelschall +## Copyright (c) 1999-2001 Ralf S. Engelschall ## ## This file is part of Str, a string handling and manipulation ## library which can be found at http://www.engelschall.com/sw/str/. Index: ossp-pkg/str/str_base64.c RCS File: /v/ossp/cvs/ossp-pkg/str/str_base64.c,v rcsdiff -q -kk '-r1.3' '-r1.4' -u '/v/ossp/cvs/ossp-pkg/str/str_base64.c,v' 2>/dev/null --- str_base64.c 2001/08/16 12:21:21 1.3 +++ str_base64.c 2001/08/16 13:21:22 1.4 @@ -1,6 +1,6 @@ /* ** Str - String Library -** Copyright (c) 1999-2000 Ralf S. Engelschall +** Copyright (c) 1999-2001 Ralf S. Engelschall ** ** This file is part of Str, a string handling and manipulation ** library which can be found at http://www.engelschall.com/sw/str/. Index: ossp-pkg/str/str_basic.c RCS File: /v/ossp/cvs/ossp-pkg/str/str_basic.c,v co -q -kk -p'1.8' '/v/ossp/cvs/ossp-pkg/str/str_basic.c,v' | diff -u /dev/null - -L'ossp-pkg/str/str_basic.c' 2>/dev/null --- ossp-pkg/str/str_basic.c +++ - 2024-05-11 07:59:34.207647600 +0200 @@ -0,0 +1,244 @@ +/* +** Str - String Library +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of Str, a string handling and manipulation +** library which can be found at http://www.engelschall.com/sw/str/. +** +** Permission to use, copy, modify, and distribute this software for +** any purpose with or without fee is hereby granted, provided that +** the above copyright notice and this permission notice appear in all +** copies. +** +** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR +** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. +** +** str_handle.c: handling and manipulation functions +*/ + +#include "str_p.h" + +/* + * str_len -- determine length of string. + * This is exactly equal to POSIX strlen(3). + */ +str_size_t str_len(const char *s) +{ + register const char *t; + + if (s == NULL) + return 0; + t = s; + while (*t++ != NUL) + /*nop*/; + return (t-s-1); +} + +/* + * str_copy -- copy a string. + * This is inspired by POSIX strncpy(3), but the source and target + * and overlap and the the target is always NUL-terminated. + */ +char *str_copy(char *as, const char *at, str_size_t n) +{ + register char *s; + register const char *t; + char *rv; + + if (as == NULL || at == NULL) + return NULL; + if (n == 0) + n = str_len(at); + t = at; + s = as; + rv = as; + if (s > t) { + /* must go high to low */ + t += n - 1; + s += n; + rv = s; + *s-- = NUL; + while (n-- > 0) + *s-- = *t--; + } + else if (s < t) { + /* must go low to high */ + while (n-- > 0) + *s++ = *t++; + *s = NUL; + rv = s; + } + return rv; +} + +/* + * str_dup -- duplicate a string. + * This is inspired by POSIX strdup(3), but provides + * the ability to specify a maximum length. + */ +char *str_dup(const char *s, str_size_t n) +{ + char *t; + char *rv; + + if (s == NULL) + return NULL; + if (n == 0) + n = str_len(s); + if ((rv = str_mem_alloc(n+1)) == NULL) + return NULL; + t = rv; + while (n-- > 0) + *t++ = *s++; + *t = NUL; + return rv; +} + +/* + * str_concat -- concatenate one or more strings. + * This function allows one to concatenate an arbitrary number of + * strings and is inspired by Apache's ap_pstrcat() function. + */ +char *str_concat(char *s, ...) +{ + va_list ap; + char *rv; + + va_start(ap, s); + rv = str_concat_va(s, ap); + va_end(ap); + return rv; +} + +char *str_concat_va(char *s, va_list ap) +{ + va_list ap_safe; + int n; + char *rv; + char *cp; + char *ds; + + if (s == NULL) + return NULL; + + /* determine required target string length */ + ap_safe = ap; + n = str_len(s); + while ((cp = va_arg(ap, char *)) != NULL) + n += str_len(cp); + ap = ap_safe; + + /* allocate target string */ + if ((rv = str_mem_alloc(n+1)) == NULL) + return NULL; + + /* concatenate the strings */ + ds = rv; + while ((*ds++ = *s++) != NUL) + /*nop*/; + while ((cp = va_arg(ap, char *)) != NULL) + while ((*ds++ = *cp++) != NUL) + /*nop*/; + *ds = NUL; + + /* return target string */ + return rv; +} + +/* + * str_splice -- splice one string into another. + * This is inspired by Perl's splice() function and can be used + * both for inplace movements, insert and cut-out operations. + */ +char *str_splice(char *s, str_size_t off, str_size_t n, char *t, str_size_t m) +{ + int sl; + + /* check for invalid arguments */ + if (s == NULL || t == NULL) + return NULL; + /* check for overlapping areas */ + if (!((t+m) <= s || (s+off+n) <= t)) + return NULL; + + sl = str_len(s); + if ((t+m) < s || (s+sl) < t) { + /* splice _external_ area into internal area */ + if (m != n) + str_mem_move(s+off+m, s+off+n, sl-off-n+1); + str_mem_move(s+off, t, m); + } + else { + /* splice _internal_ area into internal area */ + if (t > s) { + /* move t from larger to lower address of s */ + str_mem_rev(s+off, (t+m)-(s+off)); + str_mem_rev(s+off, m); + str_mem_rev(s+off+m, t-(s+n)); + str_mem_move(t+m-n, t+m, (s+sl)-(t+m)+1); + } + else { + /* move t from lower to higher address of s */ + str_mem_rev(t, (s+off)-t); + str_mem_rev(t, (s+off)-t-m); + str_mem_rev(s+off-m, m); + str_mem_move(s+off, s+off+n, sl-off-n+1); + } + } + return s; +} + +/* + * str_compare -- compare a two strings. + * This is inspired by POSIX str[n][case]cmp(3), but + * merges all functionality in a single function. + */ +int str_compare(const char *s1, const char *s2, str_size_t n, int mode) +{ + int rv; + int bWithLen; + + rv = 0; + if (n == 0) + bWithLen = FALSE; + else + bWithLen = TRUE; + if (mode & STR_NOCASE) { + /* compare case insensitive */ + do { + if (str_tolower(*s1) != str_tolower(*s2++)) { + rv = ((str_tolower(*s1) - + str_tolower(*(s2 - 1))) < 0 ? -1 : +1); + break; + } + if (bWithLen) + if (--n <= 0) + break; + } while (*s1++ != NUL); + } + else { + /* compare case sensitive */ + do { + if (*s1 != *s2++) { + rv = (((int)(*(const unsigned char *)s1) - + (int)(*(const unsigned char *)(s2 - 1))) < 0 ? -1 : +1); + break; + } + if (bWithLen) + if (--n <= 0) + break; + } while (*s1++ != NUL); + } + return rv; +} + Index: ossp-pkg/str/str_format.c RCS File: /v/ossp/cvs/ossp-pkg/str/str_format.c,v rcsdiff -q -kk '-r1.24' '-r1.25' -u '/v/ossp/cvs/ossp-pkg/str/str_format.c,v' 2>/dev/null --- str_format.c 2001/04/28 08:18:51 1.24 +++ str_format.c 2001/08/16 13:21:22 1.25 @@ -1,6 +1,6 @@ /* ** Str - String Library -** Copyright (c) 1999-2000 Ralf S. Engelschall +** Copyright (c) 1999-2001 Ralf S. Engelschall ** ** This file is part of Str, a string handling and manipulation ** library which can be found at http://www.engelschall.com/sw/str/. Index: ossp-pkg/str/str_hash.c RCS File: /v/ossp/cvs/ossp-pkg/str/str_hash.c,v co -q -kk -p'1.4' '/v/ossp/cvs/ossp-pkg/str/str_hash.c,v' | diff -u /dev/null - -L'ossp-pkg/str/str_hash.c' 2>/dev/null --- ossp-pkg/str/str_hash.c +++ - 2024-05-11 07:59:34.215618732 +0200 @@ -0,0 +1,281 @@ +/* +** Str - String Library +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of Str, a string handling and manipulation +** library which can be found at http://www.engelschall.com/sw/str/. +** +** Permission to use, copy, modify, and distribute this software for +** any purpose with or without fee is hereby granted, provided that +** the above copyright notice and this permission notice appear in all +** copies. +** +** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR +** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. +** +** str_hash.c: hashing functions +*/ + +#include "str_p.h" + +/* + * DJBX33A (Daniel J. Bernstein, Times 33 with Addition) + * + * This is Daniel J. Bernstein's popular `times 33' hash function as + * posted by him years ago on comp.lang.c. It basically uses a function + * like ``hash(i) = hash(i-1) * 33 + string[i]''. This is one of the + * best hashing functions for strings. Because it is both computed very + * fast and distributes very well. + * + * The magic of the number 33, i.e. why it works better than many other + * constants, prime or not, has never been adequately explained by + * anyone. So I try an own RSE-explanation: if one experimentally tests + * all multipliers between 1 and 256 (as I did it) one detects that + * even numbers are not useable at all. The remaining 128 odd numbers + * (except for the number 1) work more or less all equally well. They + * all distribute in an acceptable way and this way fill a hash table + * with an average percent of approx. 86%. + * + * If one compares the Chi/2 values resulting of the various + * multipliers, the 33 not even has the best value. But the 33 and a + * few other equally good values like 17, 31, 63, 127 and 129 have + * nevertheless a great advantage over the remaining values in the large + * set of possible multipliers: their multiply operation can be replaced + * by a faster operation based on just one bit-wise shift plus either a + * single addition or subtraction operation. And because a hash function + * has to both distribute good and has to be very fast to compute, those + * few values should be preferred and seems to be also the reason why + * Daniel J. Bernstein also preferred it. + */ +static unsigned long +hash_djbx33( + register unsigned char *key, + register str_size_t len) +{ + register unsigned long hash = 5381; + + /* the hash unrolled eight times */ + for (; len >= 8; len -= 8) { + hash = ((hash << 5) + hash) + *key++; + hash = ((hash << 5) + hash) + *key++; + hash = ((hash << 5) + hash) + *key++; + hash = ((hash << 5) + hash) + *key++; + hash = ((hash << 5) + hash) + *key++; + hash = ((hash << 5) + hash) + *key++; + hash = ((hash << 5) + hash) + *key++; + hash = ((hash << 5) + hash) + *key++; + } + switch (len) { + case 7: hash = ((hash << 5) + hash) + *key++; /* fallthrough... */ + case 6: hash = ((hash << 5) + hash) + *key++; /* fallthrough... */ + case 5: hash = ((hash << 5) + hash) + *key++; /* fallthrough... */ + case 4: hash = ((hash << 5) + hash) + *key++; /* fallthrough... */ + case 3: hash = ((hash << 5) + hash) + *key++; /* fallthrough... */ + case 2: hash = ((hash << 5) + hash) + *key++; /* fallthrough... */ + case 1: hash = ((hash << 5) + hash) + *key++; break; + default: /* case 0: */ break; + } + return hash; +} + +/* + * BJDDJ (Bob Jenkins, Dr. Dobbs Journal) + * + * This is a very complex but also very good hashing function, as + * proposed in the March'97 issue of Dr. Dobbs Journal (DDJ) by Bob + * Jenkins (see http://burtleburtle.net/bob/hash/doobs.html for online + * version). He showed in his texts, that his hash function has both + * very good distribution and performance and my own hash function + * comparison confirmed this, too. The only difference to the original + * function of B.J. here is that my version doesn't provide the `level' + * (= previous hash) argument for consistency reasons with the other + * hash functions (i.e. same function signature). It can be definitely + * recommended as a very good general purpose hashing function. + */ +static unsigned long +hash_bjddj( + register unsigned char *k, + register str_size_t length) +{ + register unsigned long a,b,c,len; + + /* some abbreviations */ +#define ub4 unsigned long +#define mix(a,b,c) { \ + a -= b; a -= c; a ^= (c>>13); \ + b -= c; b -= a; b ^= (a<< 8); \ + c -= a; c -= b; c ^= (b>>13); \ + a -= b; a -= c; a ^= (c>>12); \ + b -= c; b -= a; b ^= (a<<16); \ + c -= a; c -= b; c ^= (b>> 5); \ + a -= b; a -= c; a ^= (c>> 3); \ + b -= c; b -= a; b ^= (a<<10); \ + c -= a; c -= b; c ^= (b>>15); \ + } + + /* setup the internal state */ + len = length; + a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */ + c = 0; + + /* handle most of the key */ + while (len >= 12) { + a += (k[0] +((ub4)k[1]<<8) +((ub4)k[ 2]<<16) +((ub4)k[ 3]<<24)); + b += (k[4] +((ub4)k[5]<<8) +((ub4)k[ 6]<<16) +((ub4)k[ 7]<<24)); + c += (k[8] +((ub4)k[9]<<8) +((ub4)k[10]<<16) +((ub4)k[11]<<24)); + mix(a,b,c); + k += 12; len -= 12; + } + + /* handle the last 11 bytes */ + c += length; + switch(len) { + /* all the case statements fall through */ + case 11: c += ((ub4)k[10]<<24); + case 10: c += ((ub4)k[ 9]<<16); + case 9 : c += ((ub4)k[ 8]<< 8); + /* the first byte of c is reserved for the length */ + case 8 : b += ((ub4)k[ 7]<<24); + case 7 : b += ((ub4)k[ 6]<<16); + case 6 : b += ((ub4)k[ 5]<< 8); + case 5 : b += k[4]; + case 4 : a += ((ub4)k[ 3]<<24); + case 3 : a += ((ub4)k[ 2]<<16); + case 2 : a += ((ub4)k[ 1]<< 8); + case 1 : a += k[0]; + /* case 0: nothing left to add */ + } + mix(a,b,c); + + /* delete abbreviations */ +#undef ub4 +#undef mix + + /* report the result */ + return c; +} + +/* + * MACRC32 (Mark Adler, Cyclic Redundancy Check 32-Bit) + * + * This hash function is based on the good old CRC-32 (Cyclic Redundancy + * Check with 32 Bit) algorithm as invented by Mark Adler. It is one + * of the hash functions with medium performance but with very good + * distribution. So it can be considered as a rock solid general purpose + * hash function. It should be used if good distribution is more + * important than high performance. + */ +static unsigned long +hash_macrc32( + register unsigned char *key, + register str_size_t len) +{ + /* the CRC-32 table */ + static unsigned long tab[256] = { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, + 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, + 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, + 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, + 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, + 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, + 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, + 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, + 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, + 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, + 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, + 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, + 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, + 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, + 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, + 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, + 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, + 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, + 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, + 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, + 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, + 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, + 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, + 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, + 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, + 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, + 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, + 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, + 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, + 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, + 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, + 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, + 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, + 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, + 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, + 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, + 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, + 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, + 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, + 0x2d02ef8dL + }; + register unsigned long hash; + + /* compute hash with the help of the table */ + hash = 0xffffffff; + while (len-- > 0) + hash = tab[(hash ^ *key++) & 0xff] ^ (hash >> 8); + hash ^= 0xffffffff; + + /* return the calculated hash value */ + return hash; +} + +/* + * The API function. + */ +unsigned long +str_hash( + const char *s, + str_size_t n, + int mode) +{ + unsigned long hash; + + if (s == NULL) + return 0; + if (n == 0) + n = str_len(s); + switch (mode) { + case STR_HASH_DJBX33: + hash = hash_djbx33((unsigned char *)s, n); + break; + case STR_HASH_BJDDJ: + hash = hash_bjddj((unsigned char *)s, n); + break; + case STR_HASH_MACRC32: + hash = hash_macrc32((unsigned char *)s, n); + break; + default: + hash = 0; + break; + } + return hash; +} + Index: ossp-pkg/str/str_memory.c RCS File: /v/ossp/cvs/ossp-pkg/str/str_memory.c,v co -q -kk -p'1.5' '/v/ossp/cvs/ossp-pkg/str/str_memory.c,v' | diff -u /dev/null - -L'ossp-pkg/str/str_memory.c' 2>/dev/null --- ossp-pkg/str/str_memory.c +++ - 2024-05-11 07:59:34.218343146 +0200 @@ -0,0 +1,241 @@ +/* +** Str - String Library +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of Str, a string handling and manipulation +** library which can be found at http://www.engelschall.com/sw/str/. +** +** Permission to use, copy, modify, and distribute this software for +** any purpose with or without fee is hereby granted, provided that +** the above copyright notice and this permission notice appear in all +** copies. +** +** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR +** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. +** +** str_mem.c: raw memory functions +*/ + +#include "str_p.h" + +#define _str_mem_alloc malloc +#define _str_mem_realloc realloc +#define _str_mem_free free + +static void * +_str_mem_dup( + void *mem, + size_t bytes) +{ + void *dmem; + + if (mem == NULL) + return NULL; + if ((dmem = str_mem_alloc(bytes)) == NULL) + return NULL; + str_mem_move(dmem, mem, bytes); + return dmem; +} + +#ifdef HAVE_MEMSET +#define _str_mem_set memset +#else +static void * +_str_mem_set( + void *dst0, + int c0, + size_t bytes) +{ + register size_t t; + register unsigned int c; + register unsigned char *dst; + const int word_size = sizeof(unsigned int); + const int word_mask = (sizeof(unsigned int) - 1); + + dst = dst0; + + /* if not enough words for a reasonable speedup, just fill bytes */ + if (bytes < 3 * word_size) { + while (bytes != 0) { + *dst++ = c0; + --bytes; + } + return dst0; + } + + /* fill the whole stamping word */ + if ((c = (unsigned char)c0) != 0) { + c = c | (c << 8); +#if (SIZEOF_INT > 2) + c = c | (c << 16); +#endif +#if (SIZEOF_INT > 4) + c = c | (c << 32); +#endif + } + + /* align destination by filling in bytes */ + if ((t = (long)dst & word_mask) != 0) { + t = word_size - t; + bytes -= t; + do { + *dst++ = c0; + } while (--t != 0); + } + + /* now fill with words. length was >= 2*words so we know t >= 1 here */ + t = bytes / word_size; + do { + *(unsigned int *)dst = c; + dst += word_size; + } while (--t != 0); + + /* finish with trailing bytes, if there are bytes left */ + t = bytes & word_mask; + if (t != 0) { + do { + *dst++ = c0; + } while (--t != 0); + } + + return dst0; +} +#endif + +#ifdef HAVE_MEMMOVE +#define _str_mem_move memmove +#else +static void * +_str_mem_move( + void *dst, + const void *src, + size_t bytes) +{ + register unsigned char *dst_p; + register const unsigned char *src_p; + + if (src == NULL || dst == NULL) + return NULL; + src_p = src; + dst_p = dst; + if (dst > src) { + /* must go high to low */ + src_p += bytes; + dst_p += bytes; + while (bytes-- > 0) + *--dst_p = *--src_p; + } + else if (dst < src) { + /* must go low to high */ + while (bytes-- > 0) + *dst_p++ = *src_p++; + } + return dst; +} +#endif + +static void * +_str_mem_rev( + void *src, + size_t bytes) +{ + register unsigned char *p1; + register unsigned char *p2; + register unsigned char c; + + p1 = (unsigned char *)src; + p2 = (unsigned char *)src + bytes; + while (p1 < p2) + c = *p1, *p1++ = *p2, *p2-- = c; + return src; +} + +#ifdef HAVE_MEMCHR +#define _str_mem_char memchr +#else +static void * +_str_mem_char( + const void *src, + int c, + size_t bytes) +{ + register const unsigned char *cp; + + if (bytes != 0) { + cp = src; + do { + if (*cp++ == (unsigned char)c) + return ((void *)(cp - 1)); + } while (--bytes != 0); + } + return NULL; +} +#endif + +static void * +_str_mem_mem( + const void *haystack, size_t haystack_len, + const void *needle, size_t needle_len) +{ + register const char *begin; + register const char *last_possible; + + if (needle_len == 0) + /* The first occurrence of the empty string is deemed to occur at + the end of the string. */ + return (void *)&((const char *)haystack)[haystack_len - 1]; + last_possible = (const char *)haystack + haystack_len - needle_len; + for (begin = (const char *)haystack; begin <= last_possible; begin++) + if (*begin == *((const char *)needle) && + str_mem_cmp(&begin[1], (const char *)needle + 1, needle_len - 1) == 0) + + return (void *)begin; + return NULL; +} + +#ifdef HAVE_MEMCMP +#define _str_mem_cmp memcmp +#else +static int +_str_mem_cmp( + const void *src1, + const void *src2, + size_t bytes) +{ + register const unsigned char *cp1; + register const unsigned char *cp2; + + if (bytes != 0) { + cp1 = src1; + cp2 = src2; + do { + if (*cp1++ != *cp2++) + return (*--cp1 - *--cp2); + } while (--bytes != 0); + } + return 0; +} +#endif + +/* the API consists only of indirection pointers */ +void *(*str_mem_alloc)(size_t) = _str_mem_alloc; +void *(*str_mem_realloc)(void *, size_t) = _str_mem_realloc; +void (*str_mem_free)(void *) = _str_mem_free; +void *(*str_mem_dup)(void *, size_t) = _str_mem_dup; +void *(*str_mem_set)(void *, int, size_t) = _str_mem_set; +void *(*str_mem_move)(void *, const void *, size_t) = _str_mem_move; +void *(*str_mem_rev)(void *, size_t) = _str_mem_rev; +void *(*str_mem_char)(const void *, int, size_t) = _str_mem_char; +void *(*str_mem_mem)(const void *, size_t, const void *, size_t) = _str_mem_mem; +int (*str_mem_cmp)(const void *, const void *, size_t) = _str_mem_cmp; + Index: ossp-pkg/str/str_p.h RCS File: /v/ossp/cvs/ossp-pkg/str/str_p.h,v co -q -kk -p'1.16' '/v/ossp/cvs/ossp-pkg/str/str_p.h,v' | diff -u /dev/null - -L'ossp-pkg/str/str_p.h' 2>/dev/null --- ossp-pkg/str/str_p.h +++ - 2024-05-11 07:59:34.220981469 +0200 @@ -0,0 +1,86 @@ +/* +** Str - String Library +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of Str, a string handling and manipulation +** library which can be found at http://www.engelschall.com/sw/str/. +** +** Permission to use, copy, modify, and distribute this software for +** any purpose with or without fee is hereby granted, provided that +** the above copyright notice and this permission notice appear in all +** copies. +** +** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR +** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. +** +** str_p.h: private API header +*/ + +#ifndef _STR_P_H_ +#define _STR_P_H_ + +#include "str.h" +#include "str_config.h" + +#include /* for malloc, etc. */ +#include /* for modf(3) */ +#include /* ... */ + +#include "str_pcre.h" + +/* explicit support for unsigned char based ctype stuff */ +#define str_isalpha(c) (isalpha(((unsigned char)(c)))) +#define str_isdigit(c) (isdigit(((unsigned char)(c)))) +#define str_isxdigit(c) (isxdigit(((unsigned char)(c)))) +#define str_islower(c) (islower(((unsigned char)(c)))) +#define str_tolower(c) (tolower((unsigned char)(c))) + +extern void *(*str_mem_alloc)(size_t); +extern void *(*str_mem_realloc)(void *, size_t); +extern void (*str_mem_free)(void *); +extern void *(*str_mem_dup)(void *, size_t); +extern void *(*str_mem_set)(void *, int, size_t); +extern void *(*str_mem_move)(void *, const void *, size_t); +extern void *(*str_mem_rev)(void *, size_t); +extern void *(*str_mem_char)(const void *, int, size_t); +extern void *(*str_mem_mem)(const void *, size_t, const void *, size_t); +extern int (*str_mem_cmp)(const void *, const void *, size_t); + +typedef struct str_vformat_st str_vformat_t; +struct str_vformat_st { + char *curpos; + char *endpos; + union { + int i; long l; + double d; void *p; + } data[6]; + int (*flush)(struct str_vformat_st *); + char *(*format)( + struct str_vformat_st *, + char *, char *, int *, + char *, int, char *, int, va_list + ); +}; + +int str_vformat(str_vformat_t *, const char *, va_list); + +#define str_ilen(n,s) \ +do { \ + register const char *_s = (const char *)(s); \ + while (*_s++) \ + /*nop*/; \ + (n) = _s - (const char *)(s) - 1; \ +} while(0) + +#endif /* _STR_P_H_ */ + Index: ossp-pkg/str/str_parse.c RCS File: /v/ossp/cvs/ossp-pkg/str/str_parse.c,v co -q -kk -p'1.14' '/v/ossp/cvs/ossp-pkg/str/str_parse.c,v' | diff -u /dev/null - -L'ossp-pkg/str/str_parse.c' 2>/dev/null --- ossp-pkg/str/str_parse.c +++ - 2024-05-11 07:59:34.223537805 +0200 @@ -0,0 +1,596 @@ +/* +** Str - String Library +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of Str, a string handling and manipulation +** library which can be found at http://www.engelschall.com/sw/str/. +** +** Permission to use, copy, modify, and distribute this software for +** any purpose with or without fee is hereby granted, provided that +** the above copyright notice and this permission notice appear in all +** copies. +** +** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR +** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. +** +** str_parse.c: parsing functions +*/ + +#include "str_p.h" + +/* compile a regular expression pattern from string into internal format */ +static int +pattern_compile( + const char *ptr, + int len, + int opt, + pcre **p_pcre, + pcre_extra **p_pcre_extra) +{ + const char *err_str; + char buf[128]; + int err_pos; + char *cp; + + if (ptr[len] == NUL) { + /* plain string, so we can speed up processing... */ + *p_pcre = pcre_compile(ptr, opt, &err_str, &err_pos, NULL); + } + else { + /* ...else we have to create a temporary NUL-terminated string */ + if (len < sizeof(buf)) { + /* either we use a local buffer to avoid malloc/free ping-pong... */ + memcpy(buf, ptr, len); + buf[len] = NUL; + *p_pcre = pcre_compile(buf, opt, &err_str, &err_pos, NULL); + } + else { + /* ...or we have to actually allocate a memory chunk :-( */ + if ((cp = malloc(len+1)) == NULL) + return FALSE; + memcpy(cp, ptr, len); + cp[len] = NUL; + *p_pcre = pcre_compile(cp, opt, &err_str, &err_pos, NULL); + free(cp); + } + } + if (*p_pcre == NULL) + return FALSE; + + /* optionally study pattern */ + if (p_pcre_extra != NULL) { + *p_pcre_extra = pcre_study(*p_pcre, 0, &err_str); + if (err_str != NULL) { + free(p_pcre); + return FALSE; + } + } + return TRUE; + +} + +/* the hash table entry in the pattern cache */ +struct hash_entry { + struct hash_entry *next; + char *key; + int keylen; + pcre *p_pcre; + pcre_extra *p_pcre_extra; +}; + +/* size of the cache hash table; is prime */ +#define HASH_SIZE 101 + +/* the pattern cache hash table */ +static struct hash_entry *pattern_hash[HASH_SIZE]; + +/* initialization flag for hash table */ +static int hash_initialized = FALSE; + +/* initialize cache hash table */ +static void +hash_init(void) +{ + int i; + for (i = 0; i < HASH_SIZE; i++) + pattern_hash[i] = NULL; + return; +} + +/* destroy cache hash table */ +static void +hash_destroy(void) +{ + int i; + struct hash_entry *he, *ohe; + + for (i = 0; i < HASH_SIZE; i++) { + he = pattern_hash[i]; + pattern_hash[i] = NULL; + while (he != NULL) { + ohe = he; + he = he->next; + free(ohe); + } + } + return; +} + +/* the hashing function: a popular `times 33' hash */ +static unsigned int +hash_func( + const char *key, + int keylen) +{ + unsigned int h; + int i; + + h = 0xDEAD; + for (i = 0; key[i] != NUL; i++) + h = ((((h<<5)+h)+key[i]) % HASH_SIZE); + return h; +} + +/* cache a pattern */ +static void +pattern_cache( + const char *key, + int keylen, + pcre *p_pcre, + pcre_extra *p_pcre_extra) +{ + int h; + struct hash_entry *he, *che; + + if ((he = (struct hash_entry *)malloc(sizeof(struct hash_entry))) == NULL) + return; + if ((he->key = malloc(keylen)) == NULL) { + free(he); + return; + } + he->next = NULL; + memcpy(he->key, key, keylen); + he->keylen = keylen; + he->p_pcre = p_pcre; + he->p_pcre_extra = p_pcre_extra; + h = hash_func(key, keylen); + if (pattern_hash[h] == NULL) + pattern_hash[h] = he; + else { + che = pattern_hash[h]; + while (che->next != NULL) + che = che->next; + che->next = he; + } + return; +} + +/* lookup a pattern */ +static void +pattern_lookup( + const char *key, + int keylen, + pcre **p_pcre, + pcre_extra **p_pcre_extra) +{ + int h; + struct hash_entry *he; + + *p_pcre = NULL; + *p_pcre_extra = NULL; + + h = hash_func(key, keylen); + if ((he = pattern_hash[h]) == NULL) + return; + while (he->next != NULL) { + if (he->keylen == keylen) + if (memcmp(he->key, key, keylen)) + break; + he = he->next; + } + *p_pcre = he->p_pcre; + *p_pcre_extra = he->p_pcre_extra; + return; +} + +static int +str_parse_flush_nop( + str_vformat_t *sf) +{ + sf->data[2].i = sf->data[2].i + sf->data[1].i; + sf->curpos = (char *)sf->data[0].p; + return 0; +} + +static int +str_parse_flush_str( + str_vformat_t *sf) +{ + return -1; +} + +static char * +str_parse_format( + str_vformat_t *sf, + char *cpPrefix, + char *cpPad, + int *ipStrLen, + char *cpBuf, + int nBufLen, + char *cpExtinfo, + int cFmt, + va_list ap) +{ + char *pStr; + int n; + int *cap_vec; + int cap_num; + char *string; + + pStr = NULL; + if (cFmt == 'R') { + if (cpExtinfo != NULL && str_isdigit(cpExtinfo[0]) && cpExtinfo[1] == NUL) { + n = cpExtinfo[0] - '0'; + string = (char *)sf->data[3].p; + cap_vec = (int *)sf->data[4].p; + cap_num = sf->data[5].i; + if (n <= cap_num) { + if (cap_vec[(n*2)] != -1 && cap_vec[(n*2)+1] != -1) { + pStr = (char *)(string+cap_vec[(n*2)]); + *ipStrLen = (cap_vec[(n*2)+1] - cap_vec[(n*2)]); + } + } + } + } + return pStr; +} + +/* the API parsing function */ +int str_parse(const char *string, const char *pattern, ...) +{ + va_list ap; + int rv; + + va_start(ap, pattern); + rv = str_parse_va(string, pattern, ap); + va_end(ap); + return rv; +} +int str_parse_va(const char *string, const char *pattern, va_list ap) +{ + pcre *p_pcre; + pcre_extra *p_pcre_extra; + const char *match_ptr; + int match_len; + int match_opt; + int match_once; + int match_1resbuf; + const char *subst_ptr; + int subst_len; + int *cap_vec; + int cap_num; + int cap_len; + char *cp; + char *cp2; + char **cpp; + char cb[2]; + int n; + int i; + int k; + int l; + int ismop; + int issop; + char buf[128]; + char buf2[128]; + char *buf_ptr; + str_vformat_t sf; + + /* + * Caching support + */ + /* hash table initialization */ + if (!hash_initialized) { + hash_init(); + atexit(hash_destroy); + hash_initialized = TRUE; + } + /* hash table destruction */ + if (string == NULL && pattern == NULL) { + hash_destroy(); + return 0; + } + + /* + * Check input parameters + */ + if (string == NULL || pattern == NULL) + return -1; + + /* + * Parse pattern + */ + match_ptr = NULL; + match_len = 0; + match_opt = 0; + match_once = FALSE; + match_1resbuf = FALSE; + subst_ptr = NULL; + subst_len = 0; + ismop = FALSE; + issop = FALSE; + cp = NULL; /* compiler happyness only */ + cp2 = NULL; /* compiler happyness only */ + /* determine type of pattern and remember important positions */ + if (*pattern == 'm' && str_len(pattern) >= 3) + if ((cp = str_span(pattern, 0, "imsxob", STR_RIGHT)) > pattern+1) + if (*(pattern+1) == *cp) + ismop = TRUE; + if (!ismop) + if (*pattern == 's' && str_len(pattern) >= 4) + if ((cp = str_span(pattern, 0, "imsxo", STR_RIGHT)) > pattern+1) + if ((cb[0] = *cp, cb[1] = NUL, + cp2 = str_span(pattern, cp-pattern, cb, STR_RIGHT|STR_COMPLEMENT)) > pattern+1) + if (*(pattern+1) == *cp && *(pattern+1) == *cp2) + issop = TRUE; + /* finish parsing */ + if (ismop) { + /* pattern is a match operation */ + match_ptr = pattern + 2; + match_len = cp - match_ptr; + cp++; + for (i = 0; cp[i] != NUL; i++) { + switch (cp[i]) { + case 'i': match_opt |= PCRE_CASELESS; break; + case 'm': match_opt |= PCRE_MULTILINE; break; + case 's': match_opt |= PCRE_DOTALL; break; + case 'x': match_opt |= PCRE_EXTENDED; break; + case 'o': match_once = TRUE; break; + case 'b': match_1resbuf = TRUE; break; + default: + return -1; + } + } + } + else if (issop) { + /* pattern is a substitute operation */ + match_ptr = pattern + 2; + match_len = cp2 - match_ptr; + subst_ptr = cp2 + 1; + subst_len = cp - subst_ptr; + cp++; + for (i = 0; cp[i] != NUL; i++) { + switch (cp[i]) { + case 'i': match_opt |= PCRE_CASELESS; break; + case 'm': match_opt |= PCRE_MULTILINE; break; + case 's': match_opt |= PCRE_DOTALL; break; + case 'x': match_opt |= PCRE_EXTENDED; break; + case 'o': match_once = TRUE; break; + default: + return -1; + } + } + } + else { + /* fallback: treat pattern as a match operation */ + match_ptr = pattern; + match_len = str_len(pattern); + ismop = TRUE; + } + + /* + * Compile pattern into internal PCRE structure + */ + if (match_once) { + /* optimized processing: up to factor 15(!) for complex regular expressions */ + pattern_lookup(match_ptr, match_len, &p_pcre, &p_pcre_extra); + if (p_pcre == NULL) { + if (!pattern_compile(match_ptr, match_len, match_opt, &p_pcre, &p_pcre_extra)) + return -1; + pattern_cache(match_ptr, match_len, p_pcre, p_pcre_extra); + } + } + else { + /* unoptimized processing */ + p_pcre_extra = NULL; + if (!pattern_compile(match_ptr, match_len, match_opt, &p_pcre, NULL)) + return -1; + } + + /* + * Allocate storage for offset table of captured substrings + */ + cap_vec = NULL; + cap_len = 0; + cap_num = pcre_info(p_pcre, NULL, NULL); + if (cap_num > 0) { + cap_len = (cap_num+1)*3; + if ((cap_vec = (int *)malloc(cap_len*sizeof(int))) == NULL) { + if (!match_once) { + free(p_pcre); + free(p_pcre_extra); + } + return -1; + } + } + + /* + * Perform the matching operation + */ + n = pcre_exec(p_pcre, p_pcre_extra, string, str_len(string), 0, 0, cap_vec, cap_len); + if (n < 0) { + if (cap_vec != NULL) + free(cap_vec); + if (!match_once) { + free(p_pcre); + free(p_pcre_extra); + } + if (n == PCRE_ERROR_NOMATCH) + return 0; + return -1; + } + + /* + * Create either matching or substitution result + */ + if (ismop && cap_num > 0) { + /* + * extract captured substrings into caller provided pointer variables + */ + if (match_1resbuf) { + /* use a single result buffer */ + l = 0; + for (i = 1; i <= cap_num && i <= (n-1); i++) { + if (cap_vec[(i*2)] != -1 && cap_vec[(i*2)+1] != -1) { + k = (cap_vec[(i*2)+1] - cap_vec[(i*2)]); + if (k > 0) + l += k+1; + } + } + cpp = va_arg(ap, char **); + if (cpp == NULL) + cpp = &cp; + if ((*cpp = malloc(l)) != NULL) { + cp = *cpp; + for (i = 1; i <= cap_num; i++) { + cpp = va_arg(ap, char **); + if (cpp != NULL) { + if (i <= (n-1)) { + if (cap_vec[(i*2)] != -1 && cap_vec[(i*2)+1] != -1) { + k = (cap_vec[(i*2)+1] - cap_vec[(i*2)]); + if (k > 0) { + memcpy(cp, (char *)(string+cap_vec[(i*2)]), k); + cp += k; + *cp++ = NUL; + continue; + } + } + } + *cpp = cp; + *cp++ = NUL; + } + } + } + } + else { + /* use multiple result buffers */ + for (i = 1; i <= cap_num; i++) { + cpp = va_arg(ap, char **); + if (cpp != NULL) { + if (i <= (n-1)) { + if (cap_vec[(i*2)] != -1 && cap_vec[(i*2)+1] != -1) { + k = (cap_vec[(i*2)+1] - cap_vec[(i*2)]); + if (k > 0) { + if ((*cpp = malloc(k+1)) != NULL) { + memcpy(*cpp, (char *)(string+cap_vec[(i*2)]), k); + (*cpp)[k] = NUL; + continue; + } + } + } + } + *cpp = strdup(""); + } + } + } + } + else if (issop) { + /* + * create a substitutional string with optional expansions + */ + + /* determine required buffer len */ + l = 0; + for (cp = (char *)subst_ptr; cp < (subst_ptr+subst_len); cp++, l++) { + if (*cp == '$') { + if (!(cp > subst_ptr && *(cp-1) == '\\')) { + if (cp < (subst_ptr+subst_len-1) && str_isdigit(*(cp+1))) { + cp += 1; + l += 4; + } + } + } + } + l++; /* NUL char */ + + /* allocate temp buffer */ + if (l <= sizeof(buf)) + buf_ptr = buf; + else + buf_ptr = (char *)malloc(l); + + /* copy subst string into temp buffer and replace $N with %{N}R */ + for (cp = (char *)subst_ptr, cp2 = buf_ptr; cp < (subst_ptr+subst_len); ) { + if (*cp == '$') { + if (!(cp > subst_ptr && *(cp-1) == '\\')) { + if (cp < (subst_ptr+subst_len-1) && str_isdigit(*(cp+1))) { + *cp2++ = '%'; + *cp2++ = '{'; + *cp2++ = *(cp+1); + *cp2++ = '}'; + *cp2++ = 'R'; + cp += 2; + continue; + } + } + } + *cp2++ = *cp++; + } + *cp2 = NUL; + + /* remove output argument from varargs */ + cpp = va_arg(ap, char **); + + /* calculate output buffer requirement */ + sf.curpos = buf2; + sf.endpos = buf2 + sizeof(buf2) - 1; + sf.flush = str_parse_flush_nop; + sf.format = str_parse_format; + sf.data[0].p = buf2; + sf.data[1].i = sizeof(buf2); + sf.data[2].i = 0; + sf.data[3].p = (char *)string; + sf.data[4].p = cap_vec; + sf.data[5].i = cap_num; + l = str_vformat(&sf, buf_ptr, ap); + + /* allocate output buffer */ + if ((*cpp = (char *)malloc(l+1)) == NULL) + return -1; /* XXX */ + + /* finally expand the substitutions string into output buffer */ + sf.curpos = *cpp; + sf.endpos = *cpp + l; + sf.flush = str_parse_flush_str; + sf.format = str_parse_format; + sf.data[3].p = (char *)string; + sf.data[4].p = cap_vec; + sf.data[5].i = cap_num; + str_vformat(&sf, buf_ptr, ap); + *((*cpp)+l) = NUL; + + /* free temp buffer */ + if (buf_ptr != buf) + free(buf_ptr); + } + + /* cleanup */ + if (cap_vec != NULL) + free(cap_vec); + if (!match_once) { + free(p_pcre); + free(p_pcre_extra); + } + /* return success */ + return 1; +} + Index: ossp-pkg/str/str_search.c RCS File: /v/ossp/cvs/ossp-pkg/str/str_search.c,v rcsdiff -q -kk '-r1.15' '-r1.16' -u '/v/ossp/cvs/ossp-pkg/str/str_search.c,v' 2>/dev/null --- str_search.c 2000/11/20 19:48:39 1.15 +++ str_search.c 2001/08/16 13:21:23 1.16 @@ -1,6 +1,6 @@ /* ** Str - String Library -** Copyright (c) 1999-2000 Ralf S. Engelschall +** Copyright (c) 1999-2001 Ralf S. Engelschall ** ** This file is part of Str, a string handling and manipulation ** library which can be found at http://www.engelschall.com/sw/str/. Index: ossp-pkg/str/str_test.c RCS File: /v/ossp/cvs/ossp-pkg/str/str_test.c,v rcsdiff -q -kk '-r1.20' '-r1.21' -u '/v/ossp/cvs/ossp-pkg/str/str_test.c,v' 2>/dev/null --- str_test.c 2001/08/16 13:16:31 1.20 +++ str_test.c 2001/08/16 13:21:23 1.21 @@ -1,6 +1,6 @@ /* ** Str - String Library -** Copyright (c) 1999-2000 Ralf S. Engelschall +** Copyright (c) 1999-2001 Ralf S. Engelschall ** ** This file is part of Str, a string handling and manipulation ** library which can be found at http://www.engelschall.com/sw/str/. Index: ossp-pkg/str/str_token.c RCS File: /v/ossp/cvs/ossp-pkg/str/str_token.c,v co -q -kk -p'1.6' '/v/ossp/cvs/ossp-pkg/str/str_token.c,v' | diff -u /dev/null - -L'ossp-pkg/str/str_token.c' 2>/dev/null --- ossp-pkg/str/str_token.c +++ - 2024-05-11 07:59:34.235106840 +0200 @@ -0,0 +1,302 @@ +/* +** Str - String Library +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of Str, a string handling and manipulation +** library which can be found at http://www.engelschall.com/sw/str/. +** +** Permission to use, copy, modify, and distribute this software for +** any purpose with or without fee is hereby granted, provided that +** the above copyright notice and this permission notice appear in all +** copies. +** +** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR +** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. +** +** str_token.c: tokenizing functions +*/ + +#include "str_p.h" + +/* + * str_token -- tokenize a string. + * This is the implementation of our tokenization function str_token(3). + * It is partly derived from an achient strqtok(3) function, written + * 1991 by William Deich which itself was + * already a superset of POSIX strtok(3). The main differences between + * our str_token(3) and a plain POSIX strtok(3) is that our str_token(3) + * is reentrant to support multithreading environments, supports + * quoted tokens, can ignore trailing comments and is aware of ANSI-C + * backslashed escape sequences and trigraphs. This way it is a lot + * more powerful and useful in practice than a stock POSIX strtok(3) or + * similar functions. + */ + +/* + * isoneof -- check whether c is one of the chars in c + */ +static int +isoneof( + register char c, + register const char *s) +{ + for (; *s != NUL; s++) + if (*s == c) + return TRUE; + return FALSE; +} + +/* + * nextchar -- get next character from a string + */ +static char * +nextchar( + register char *s, /* string from which to collect character(s) */ + register char *c, /* return character here */ + int bTrigraphs, /* whether to interpret trigraphs according to ANSI rules */ + int *bBackslashed) /* return FALSE if character was started with a backslash */ +{ + register char ch; + + if ((*bBackslashed = (*s == '\\'))) { + /* + * ANSI C backslashed escape sequence ("\x") + */ + switch (*++s) { + case 'a': *c = '\a'; break; + case 'b': *c = '\b'; break; + case 'f': *c = '\f'; break; + case 'n': *c = '\n'; break; + case 'r': *c = '\r'; break; + case 't': *c = '\t'; break; + case 'v': *c = '\v'; break; + case '\\': *c = '\\'; break; + case '^': *c = '^'; break; + case '\'': *c = '\''; break; + case '"': *c = '"'; break; + case '?': *c = '?'; break; + case '0': case '1': case '2': + case '3': case '4': case '5': + case '6': case '7': + /* convert octal digits into number */ + ch = 0; + if (str_isdigit(*s) && *s != '8' && *s != '9') { + ch = *s++ - '0'; + if (str_isdigit(*s) && *s != '8' && *s != '9') { + ch <<= 3; + ch |= *s++ - '0'; + if (str_isdigit(*s) && *s != '8' && *s != '9') { + ch <<= 3; + ch |= *s++ - '0'; + } + } + } + s--; + *c = ch; + break; + case 'x': + /* convert hexadecimal digits into number */ + s++; + for (ch = 0; str_isxdigit(*s); s++) { + ch <<= 4; + ch |= str_isdigit(*s) ? *s - '0' : + str_islower(*s) ? *s + 10 - 'a' : *s + 10 - 'A'; + } + s--; + *c = ch; + break; + default: + *c = *s; + break; + } + } + else if (bTrigraphs && (*s == '?') && (*(s + 1) == '?')) { + /* + * ANSI C trigraph ("??x") + */ + switch (*(s + 2)) { + case '=': *c = '#'; s += 2; break; + case '(': *c = '['; s += 2; break; + case '/': *c = '\\'; s += 2; break; + case ')': *c = ']'; s += 2; break; + case '\'': *c = '^'; s += 2; break; + case '<': *c = '{'; s += 2; break; + case '!': *c = '|'; s += 2; break; + case '>': *c = '}'; s += 2; break; + case '-': *c = '~'; s += 2; break; + default: + /* not a trigraph sequence */ + *c = *s; + } + *c = *s; + } + else { + /* + * Ordinary Character + */ + *c = *s; + } + return (*s != NUL) ? s + 1 : NULL; +} + +/* + * str_token -- the API tokenization function + */ +char * +str_token( + char **s, + const char *cs_delim, + const char *cs_quote, + const char *cs_comment, + int mode) +{ + register char *p, *q; + int bBackslashed, bInQuote, bInToken, bWithTrigraphs; + char c, cLeftQuote; + char *cpToken; + + /* argument checking */ + if (s == NULL || *s == NULL) + return NULL; + if (cs_delim == NULL) + return NULL; + if (cs_quote == NULL) + cs_quote = ""; + if (cs_comment == NULL) + cs_comment = ""; + + /* skip leading delimiters */ + p = *s; + while (*p != NUL && isoneof(*p, cs_delim)) + p++; + + /* end of string, so stop parsing */ + if (*p == NUL) + return NULL; + + /* + * start of comment reached, so stop parsing but update the parsing + * cursor just in case the user wants to recover the comment + */ + if (isoneof(*p, cs_comment)) { + *s = p; + (*s)++; + return NULL; + } + + /* + * Set `cpToken' to point to returned string. + * Then use p and q to walk through the string: + * - p will follow the input characters; + * - q will overwrite string with output characters, + * (minus possibly-stripped quotes and including NULs after tokens) + */ + + cpToken = q = p; + bInQuote = FALSE; + bInToken = TRUE; + bWithTrigraphs = (mode & STR_TRIGRAPHS); + cLeftQuote = NUL; + + if ((mode & STR_BACKSLASHESC) || (mode & STR_TRIGRAPHS)) { + /* + * parse while recognizing backslash escapes + */ + while (bInToken && (p = nextchar(p, &c, bWithTrigraphs, &bBackslashed)) != NULL) { + if (bBackslashed) { + /* treat as plain character */ + *q++ = c; + } + else if (!bInQuote && *cs_delim != NUL && isoneof(c, cs_delim)) { + /* reached end of token */ + *q = NUL; + bInToken = FALSE; + } + else if (!bInQuote && *cs_comment != NUL && isoneof(c, cs_comment)) { + /* reached end of token */ + *q = NUL; + *p = NUL; + bInToken = FALSE; + } + else if (!bInQuote && *cs_quote != NUL && isoneof(c, cs_quote)) { + /* beginning a quoted segment */ + bInQuote = TRUE; + cLeftQuote = c; + if (!(mode & STR_STRIPQUOTES)) + *q++ = c; + } + else if (bInQuote && cLeftQuote == c) { + /* ending a quoted segment */ + bInQuote = FALSE; + if (!(mode & STR_STRIPQUOTES)) + *q++ = cLeftQuote; + } + else { + /* ordinary character */ + *q++ = c; + } + } + } + else { + /* + * parse while ignoring backslash escapes + */ + while (bInToken && *p != NUL) { + if (!bInQuote && *cs_delim != NUL && isoneof(*p, cs_delim)) { + /* reached end of token */ + *q = NUL; + p++; + bInToken = FALSE; + } + else if (!bInQuote && *cs_comment != NUL && isoneof(*p, cs_comment)) { + /* reached end of token */ + *q = NUL; + *p = NUL; + bInToken = FALSE; + } + else if (!bInQuote && *cs_quote != NUL && isoneof(*p, cs_quote)) { + /* beginning a quoted segment */ + bInQuote = TRUE; + cLeftQuote = *p++; + if (!(mode & STR_STRIPQUOTES)) + *q++ = cLeftQuote; + } + else if (bInQuote && cLeftQuote == *p) { + /* ending a quoted segment */ + bInQuote = FALSE; + p++; + if (!(mode & STR_STRIPQUOTES)) + *q++ = cLeftQuote; + } + else { + /* ordinary character */ + *q++ = *p++; + } + } + } + + /* terminate token and update parsing cursor */ + *q = NUL; + *s = p; + + /* skip trailing delimiters + (if requested only, else we do it on next round) */ + if ((mode & STR_SKIPDELIMS) && *s != NULL) { + while (*(*s) != NUL && isoneof(*(*s), cs_delim)) + (*s)++; + } + + /* return the resulting token */ + return cpToken; +} +