diff options
author | Jeremy Allison <jra@samba.org> | 2003-09-05 19:59:55 +0000 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2003-09-05 19:59:55 +0000 |
commit | 94f59f54921174fc156fade575ca114d331b1bd8 (patch) | |
tree | 06c2548e853c68c2bb24cce2ce3ba75eb3c8497e /source3/lib/util_str.c | |
parent | 7544b0c77382e300da0e2daf2b325527a23e6ddc (diff) | |
download | samba-94f59f54921174fc156fade575ca114d331b1bd8.tar.gz samba-94f59f54921174fc156fade575ca114d331b1bd8.tar.bz2 samba-94f59f54921174fc156fade575ca114d331b1bd8.zip |
More tuning from cachegrind. Change most trim_string() calls to trim_char(0,
as that's what they do. Fix string_replace() to fast-path ascii.
Jeremy.
(This used to be commit f35e9a8b909d3c74be47083ccc4a4e91a14938db)
Diffstat (limited to 'source3/lib/util_str.c')
-rw-r--r-- | source3/lib/util_str.c | 75 |
1 files changed, 73 insertions, 2 deletions
diff --git a/source3/lib/util_str.c b/source3/lib/util_str.c index 70567f88af..82b312e241 100644 --- a/source3/lib/util_str.c +++ b/source3/lib/util_str.c @@ -364,9 +364,27 @@ BOOL strisnormal(const char *s) void string_replace(pstring s,char oldc,char newc) { - push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE); + unsigned char *p; + + /* this is quite a common operation, so we want it to be + fast. We optimise for the ascii case, knowing that all our + supported multi-byte character sets are ascii-compatible + (ie. they match for the first 128 chars) */ + + for (p = (unsigned char *)s; *p; p++) { + if (*p & 0x80) /* mb string - slow path. */ + break; + if (*p == oldc) + *p = newc; + } + + if (!*p) + return; + + /* Slow (mb) path. */ + push_ucs2(NULL, tmpbuf, p, sizeof(tmpbuf), STR_TERMINATE); string_replace_w(tmpbuf, UCS2_CHAR(oldc), UCS2_CHAR(newc)); - pull_ucs2(NULL, s, tmpbuf, -1, sizeof(tmpbuf), STR_TERMINATE); + pull_ucs2(NULL, p, tmpbuf, -1, sizeof(tmpbuf), STR_TERMINATE); } /** @@ -406,6 +424,59 @@ size_t str_ascii_charnum(const char *s) return strlen(tmpbuf2); } +BOOL trim_char(char *s,char cfront,char cback) +{ + BOOL ret = False; + char *ep; + char *fp = s; + + /* Ignore null or empty strings. */ + if (!s || (s[0] == '\0')) + return False; + + if (cfront) { + while (*fp && *fp == cfront) + fp++; + if (!*fp) { + /* We ate the string. */ + s[0] = '\0'; + return True; + } + if (fp != s) + ret = True; + } + + ep = fp + strlen(fp) - 1; + if (cback) { + /* Attempt ascii only. Bail for mb strings. */ + while ((ep >= fp) && (*ep == cback)) { + ret = True; + if ((ep > fp) && (((unsigned char)ep[-1]) & 0x80)) { + /* Could be mb... bail back to tim_string. */ + char fs[2], bs[2]; + if (cfront) { + fs[0] = cfront; + fs[1] = '\0'; + } + bs[0] = cback; + bs[1] = '\0'; + return trim_string(s, cfront ? fs : NULL, bs); + } else { + ep--; + } + } + if (ep < fp) { + /* We ate the string. */ + s[0] = '\0'; + return True; + } + } + + ep[1] = '\0'; + memmove(s, fp, ep-fp+2); + return ret; +} + /** Trim the specified elements off the front and back of a string. **/ |