summaryrefslogtreecommitdiff
path: root/source3/lib/util_str.c
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2003-09-09 04:07:32 +0000
committerGerald Carter <jerry@samba.org>2003-09-09 04:07:32 +0000
commit4093bf7ff8c8861cf7b941945ede53a8ec5bb6c8 (patch)
treedd0a9f32d9933e1f75d919b5083e007d7453f9c4 /source3/lib/util_str.c
parent3d7cb49747a9a7f5cdec0ee05c6270ec3604202f (diff)
downloadsamba-4093bf7ff8c8861cf7b941945ede53a8ec5bb6c8.tar.gz
samba-4093bf7ff8c8861cf7b941945ede53a8ec5bb6c8.tar.bz2
samba-4093bf7ff8c8861cf7b941945ede53a8ec5bb6c8.zip
sync 3.0 into HEAD for the last time
(This used to be commit c17a7dc9a190156a069da3e861c18fd3f81224ad)
Diffstat (limited to 'source3/lib/util_str.c')
-rw-r--r--source3/lib/util_str.c202
1 files changed, 182 insertions, 20 deletions
diff --git a/source3/lib/util_str.c b/source3/lib/util_str.c
index 7569a39e6a..82b312e241 100644
--- a/source3/lib/util_str.c
+++ b/source3/lib/util_str.c
@@ -37,7 +37,7 @@
**/
BOOL next_token(const char **ptr,char *buff, const char *sep, size_t bufsize)
{
- const char *s;
+ char *s;
char *pbuf;
BOOL quoted;
size_t len=1;
@@ -45,7 +45,7 @@ BOOL next_token(const char **ptr,char *buff, const char *sep, size_t bufsize)
if (!ptr)
return(False);
- s = *ptr;
+ s = (char *)*ptr;
/* default to simple separators */
if (!sep)
@@ -88,7 +88,7 @@ BOOL next_token_nr(const char **ptr,char *buff, const char *sep, size_t bufsize)
{
BOOL ret;
if (!ptr)
- ptr = (const char **)&last_ptr;
+ ptr = &last_ptr;
ret = next_token(ptr, buff, sep, bufsize);
last_ptr = *ptr;
@@ -109,7 +109,7 @@ void set_first_token(char *ptr)
char **toktocliplist(int *ctok, const char *sep)
{
- char *s=last_ptr;
+ char *s=(char *)last_ptr;
int ictok=0;
char **ret, **iret;
@@ -132,7 +132,7 @@ char **toktocliplist(int *ctok, const char *sep)
} while(*s);
*ctok=ictok;
- s=last_ptr;
+ s=(char *)last_ptr;
if (!(ret=iret=malloc(ictok*sizeof(char *))))
return NULL;
@@ -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.
**/
@@ -428,7 +499,9 @@ BOOL trim_string(char *s,const char *front,const char *back)
if (front_len) {
while (len && strncmp(s, front, front_len)==0) {
- memcpy(s, s+front_len, (len-front_len)+1);
+ /* Must use memmove here as src & dest can
+ * easily overlap. Found by valgrind. JRA. */
+ memmove(s, s+front_len, (len-front_len)+1);
len -= front_len;
ret=True;
}
@@ -501,7 +574,9 @@ char *safe_strcpy_fn(const char *fn, int line, char *dest,const char *src, size_
return NULL;
}
+#ifdef DEVELOPER
clobber_region(fn,line,dest, maxlength+1);
+#endif
if (!src) {
*dest = 0;
@@ -540,7 +615,9 @@ char *safe_strcat_fn(const char *fn, int line, char *dest, const char *src, size
src_len = strnlen(src, maxlength + 1);
dest_len = strnlen(dest, maxlength + 1);
+#ifdef DEVELOPER
clobber_region(fn, line, dest + dest_len, maxlength + 1 - dest_len);
+#endif
if (src_len + dest_len > maxlength) {
DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n",
@@ -567,7 +644,9 @@ char *alpha_strcpy_fn(const char *fn, int line, char *dest, const char *src, con
{
size_t len, i;
+#ifdef DEVELOPER
clobber_region(fn, line, dest, maxlength);
+#endif
if (!dest) {
DEBUG(0,("ERROR: NULL dest in alpha_strcpy\n"));
@@ -607,7 +686,9 @@ char *StrnCpy_fn(const char *fn, int line,char *dest,const char *src,size_t n)
{
char *d = dest;
+#ifdef DEVELOPER
clobber_region(fn, line, dest, n+1);
+#endif
if (!dest)
return(NULL);
@@ -637,8 +718,9 @@ static char *strncpyn(char *dest, const char *src, size_t n, char c)
char *p;
size_t str_len;
+#ifdef DEVELOPER
clobber_region(dest, n+1);
-
+#endif
p = strchr_m(src, c);
if (p == NULL) {
DEBUG(5, ("strncpyn: separator character (%c) not found\n", c));
@@ -910,6 +992,7 @@ char *realloc_string_sub(char *string, const char *pattern, const char *insert)
while ((p = strstr(s,pattern))) {
if (ld > 0) {
+ int offset = PTR_DIFF(s,string);
char *t = Realloc(string, ls + ld + 1);
if (!t) {
DEBUG(0, ("realloc_string_sub: out of memory!\n"));
@@ -917,7 +1000,7 @@ char *realloc_string_sub(char *string, const char *pattern, const char *insert)
return NULL;
}
string = t;
- p = t + (p - s);
+ p = t + offset + (p - s);
}
if (li != lp) {
memmove(p+li,p+lp,strlen(p+lp)+1);
@@ -1098,6 +1181,19 @@ char *strchr_m(const char *s, char c)
pstring s2;
smb_ucs2_t *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) */
+
+ while (*s && (((unsigned char)s[0]) & 0x80)) {
+ if (*s == c)
+ return s;
+ }
+
+ if (!*s)
+ return NULL;
+
push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
p = strchr_w(ws, UCS2_CHAR(c));
if (!p)
@@ -1109,17 +1205,53 @@ char *strchr_m(const char *s, char c)
char *strrchr_m(const char *s, char c)
{
- wpstring ws;
- pstring s2;
- smb_ucs2_t *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). Also, in Samba
+ we only search for ascii characters in 'c' and that
+ in all mb character sets with a compound character
+ containing c, if 'c' is not a match at position
+ p, then p[-1] > 0x7f. JRA. */
- push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
- p = strrchr_w(ws, UCS2_CHAR(c));
- if (!p)
- return NULL;
- *p = 0;
- pull_ucs2_pstring(s2, ws);
- return (char *)(s+strlen(s2));
+ {
+ size_t len = strlen(s);
+ const char *cp = s;
+ BOOL got_mb = False;
+
+ if (len == 0)
+ return NULL;
+ cp += (len - 1);
+ do {
+ if (c == *cp) {
+ /* Could be a match. Part of a multibyte ? */
+ if ((cp > s) && (((unsigned char)cp[-1]) & 0x80)) {
+ /* Yep - go slow :-( */
+ got_mb = True;
+ break;
+ }
+ /* No - we have a match ! */
+ return cp;
+ }
+ } while (cp-- != s);
+ if (!got_mb)
+ return NULL;
+ }
+
+ /* String contained a non-ascii char. Slow path. */
+ {
+ wpstring ws;
+ pstring s2;
+ smb_ucs2_t *p;
+
+ push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
+ p = strrchr_w(ws, UCS2_CHAR(c));
+ if (!p)
+ return NULL;
+ *p = 0;
+ pull_ucs2_pstring(s2, ws);
+ return (char *)(s+strlen(s2));
+ }
}
/***********************************************************************
@@ -1409,6 +1541,35 @@ void str_list_free(char ***list)
SAFE_FREE(*list);
}
+/******************************************************************************
+ version of standard_sub_basic() for string lists; uses alloc_sub_basic()
+ for the work
+ *****************************************************************************/
+
+BOOL str_list_sub_basic( char **list, const char *smb_name )
+{
+ char *s, *tmpstr;
+
+ while ( *list ) {
+ s = *list;
+ tmpstr = alloc_sub_basic(smb_name, s);
+ if ( !tmpstr ) {
+ DEBUG(0,("str_list_sub_basic: alloc_sub_basic() return NULL!\n"));
+ return False;
+ }
+
+ *list = tmpstr;
+
+ list++;
+ }
+
+ return True;
+}
+
+/******************************************************************************
+ substritute a specific pattern in a string list
+ *****************************************************************************/
+
BOOL str_list_substitute(char **list, const char *pattern, const char *insert)
{
char *p, *s, *t;
@@ -1464,6 +1625,7 @@ BOOL str_list_substitute(char **list, const char *pattern, const char *insert)
}
}
+
list++;
}