From 7bf819f5af888c2389310409bf8a953b5ee96164 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 21 Apr 2019 23:18:40 -0700 Subject: [PATCH] Use a superior strcasestr --- src/m_misc.c | 67 ----------------------------- src/strcasestr.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++ src/string.c | 3 ++ 3 files changed, 113 insertions(+), 67 deletions(-) create mode 100644 src/strcasestr.c diff --git a/src/m_misc.c b/src/m_misc.c index 701fba2db..f7d5cf961 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -1672,73 +1672,6 @@ void strcatbf(char *s1, const char *s2, const char *s3) strcat(s1, tmp); } -/** Locate a substring, case-insensitively. - * Know that I hate this style. -James - * - * \param s The string to search within. - * \param q The substring to find. - * \return a pointer to the located substring, or NULL if it could be found. -*/ -char *strcasestr(const char *s, const char *q) -{ - void **vpp;/* a hack! */ - - size_t qz; - - const char *up; - const char *lp; - - int uc; - int lc; - - qz = strlen(q); - - uc = toupper(*q); - lc = tolower(*q); - - up = s; - lp = s; - - do - { - if (uc > 0) - { - up = strchr(up, uc); - if (!up || ( lc == 0 && lp < up )) - uc = -1; - else - if (strnicmp(q, up, qz) == 0) - uc = 0; - else - up++; - } - if (lc > 0) - { - lp = strchr(lp, lc); - if (!lp || ( uc == 0 && up < lp )) - lc = -1; - else - if (strnicmp(q, lp, qz) == 0) - lc = 0; - else - lp++; - } - } - while (( uc > 0 ) || ( lc > 0 )) ; - - if (uc == 0) - vpp = (void **)&up; - else - vpp = (void **)&lp; - - /* - We can dereference a double void pointer and cast it to remove const. - This works because the original variable (the pointer) is writeable, - but its value is not. - */ - return (char *)*vpp; -} - /** Converts an ASCII Hex string into an integer. Thanks, Borland! * I don't know if this belongs here specifically, but it sure * doesn't belong in p_spec.c, that's for sure diff --git a/src/strcasestr.c b/src/strcasestr.c new file mode 100644 index 000000000..2077dc3ff --- /dev/null +++ b/src/strcasestr.c @@ -0,0 +1,110 @@ +/* +strcasestr -- case insensitive substring searching function. +*/ +/* +Copyright 2019 James R. +All rights reserved. + +Redistribution and use in source forms, with or without modification, is +permitted provided that the following condition is met: + +1. Redistributions of source code must retain the above copyright notice, this + condition and the following disclaimer. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS 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 COPYRIGHT OWNER OR 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. +*/ + +#define SWAP( a, b ) \ +(\ + (a) ^= (b),\ + (b) ^= (a),\ + (a) ^= (b)\ +) + +static inline int +trycmp (char **pp, char *cp, + const char *q, size_t qn) +{ + char *p; + p = (*pp); + if (strncasecmp(p, q, qn) == 0) + return 0; + (*pp) = strchr(&p[1], (*cp)); + return 1; +} + +static inline void +swapp (char ***ppap, char ***ppbp, char **cpap, char **cpbp) +{ + SWAP(*(intptr_t *)ppap, *(intptr_t *)ppbp); + SWAP(*(intptr_t *)cpap, *(intptr_t *)cpbp); +} + +char * +strcasestr (const char *s, const char *q) +{ + size_t qn; + + char uc; + char lc; + + char *up; + char *lp; + + char **ppa; + char **ppb; + + char *cpa; + char *cpb; + + uc = toupper(*q); + lc = tolower(*q); + + up = strchr(s, uc); + lp = strchr(s, lc); + + if (!( (intptr_t)up|(intptr_t)lp )) + return 0; + + if (!lp || up < lp) + { + ppa = &up; + ppb = &lp; + + cpa = &uc; + cpb = &lc; + } + else + { + ppa = &lp; + ppb = &up; + + cpa = &lc; + cpb = &uc; + } + + qn = strlen(q); + + for (;;) + { + if (trycmp(ppa, cpa, q, qn) == 0) + return (*ppa); + + if (!( (intptr_t)up|(intptr_t)lp )) + break; + + if (!(*ppa) || ( (*ppb) && (*ppb) < (*ppa) )) + swapp(&ppa, &ppb, &cpa, &cpb); + } + + return 0; +} diff --git a/src/string.c b/src/string.c index 2a03e8729..c415e5245 100644 --- a/src/string.c +++ b/src/string.c @@ -2,6 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 2006 by Graue. // Copyright (C) 2006-2018 by Sonic Team Junior. +// Copyright (C) 2019 by James R. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -50,3 +51,5 @@ size_t strlcpy(char *dst, const char *src, size_t siz) } #endif + +#include "strcasestr.c"