Copyright (C) Simo Sorce 2001
Copyright (C) Andrew Bartlett 2011
Copyright (C) Jeremy Allison 1992-2007
+ Copyright (C) Martin Pool 2003
+ Copyright (C) James Peach 2006
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#endif
/**
- Case insensitive string compararison
+ Case insensitive string compararison, handle specified for testing
**/
-_PUBLIC_ int strcasecmp_m(const char *s1, const char *s2)
+_PUBLIC_ int strcasecmp_m_handle(struct smb_iconv_handle *iconv_handle,
+ const char *s1, const char *s2)
{
codepoint_t c1=0, c2=0;
size_t size1, size2;
- struct smb_iconv_handle *iconv_handle = get_iconv_handle();
/* handle null ptr comparisons to simplify the use in qsort */
if (s1 == s2) return 0;
c1 = next_codepoint_handle(iconv_handle, s1, &size1);
c2 = next_codepoint_handle(iconv_handle, s2, &size2);
+ if (c1 == INVALID_CODEPOINT ||
+ c2 == INVALID_CODEPOINT) {
+ return strcasecmp(s1, s2);
+ }
+
s1 += size1;
s2 += size2;
continue;
}
- if (c1 == INVALID_CODEPOINT ||
- c2 == INVALID_CODEPOINT) {
- /* what else can we do?? */
- return strcasecmp(s1, s2);
- }
-
if (toupper_m(c1) != toupper_m(c2)) {
return c1 - c2;
}
}
/**
- Case insensitive string compararison, length limited
+ Case insensitive string compararison
**/
-_PUBLIC_ int strncasecmp_m(const char *s1, const char *s2, size_t n)
+_PUBLIC_ int strcasecmp_m(const char *s1, const char *s2)
+{
+ struct smb_iconv_handle *iconv_handle = get_iconv_handle();
+ return strcasecmp_m_handle(iconv_handle, s1, s2);
+}
+
+/**
+ Case insensitive string compararison, length limited, handle specified for testing
+**/
+_PUBLIC_ int strncasecmp_m_handle(struct smb_iconv_handle *iconv_handle,
+ const char *s1, const char *s2, size_t n)
{
codepoint_t c1=0, c2=0;
size_t size1, size2;
- struct smb_iconv_handle *iconv_handle = get_iconv_handle();
/* handle null ptr comparisons to simplify the use in qsort */
if (s1 == s2) return 0;
c1 = next_codepoint_handle(iconv_handle, s1, &size1);
c2 = next_codepoint_handle(iconv_handle, s2, &size2);
+ if (c1 == INVALID_CODEPOINT ||
+ c2 == INVALID_CODEPOINT) {
+ /*
+ * n was specified in characters,
+ * now we must convert it to bytes.
+ * As bytes are the smallest
+ * character unit, the following
+ * increment and strncasecmp is always
+ * safe.
+ *
+ * The source string was already known
+ * to be n characters long, so we are
+ * guaranteed to be able to look at the
+ * (n remaining + size1) bytes from the
+ * s1 position).
+ */
+ n += size1;
+ return strncasecmp(s1, s2, n);
+ }
+
s1 += size1;
s2 += size2;
continue;
}
- if (c1 == INVALID_CODEPOINT ||
- c2 == INVALID_CODEPOINT) {
- /* what else can we do?? */
- return strcasecmp(s1, s2);
- }
-
if (toupper_m(c1) != toupper_m(c2)) {
return c1 - c2;
}
return *s1 - *s2;
}
+/**
+ Case insensitive string compararison, length limited
+**/
+_PUBLIC_ int strncasecmp_m(const char *s1, const char *s2, size_t n)
+{
+ struct smb_iconv_handle *iconv_handle = get_iconv_handle();
+ return strncasecmp_m_handle(iconv_handle, s1, s2, n);
+}
+
/**
* Compare 2 strings.
*
* string which is expected to be in in src_charset encoding to the
* destination charset (which should be a unicode charset).
*/
-_PUBLIC_ size_t strlen_m_ext(const char *s, charset_t src_charset, charset_t dst_charset)
+_PUBLIC_ size_t strlen_m_ext_handle(struct smb_iconv_handle *ic,
+ const char *s, charset_t src_charset, charset_t dst_charset)
{
size_t count = 0;
- struct smb_iconv_handle *ic = get_iconv_handle();
+#ifdef DEVELOPER
+ switch (dst_charset) {
+ case CH_DOS:
+ case CH_UNIX:
+ smb_panic("cannot call strlen_m_ext() with a variable dest charset (must be UTF16* or UTF8)");
+ default:
+ break;
+ }
+
+ switch (src_charset) {
+ case CH_UTF16LE:
+ case CH_UTF16BE:
+ smb_panic("cannot call strlen_m_ext() with a UTF16 src charset (must be DOS, UNIX, DISPLAY or UTF8)");
+ default:
+ break;
+ }
+#endif
if (!s) {
return 0;
}
while (*s) {
size_t c_size;
- codepoint_t c = next_codepoint_handle_ext(ic, s, src_charset, &c_size);
+ codepoint_t c = next_codepoint_handle_ext(ic, s, strnlen(s, 5),
+ src_charset, &c_size);
s += c_size;
switch (dst_charset) {
count += 1;
} else if (c < 0x800) {
count += 2;
- } else if (c < 0x1000) {
+ } else if (c < 0x10000) {
count += 3;
} else {
count += 4;
return count;
}
+/**
+ * Calculate the number of units (8 or 16-bit, depending on the
+ * destination charset), that would be needed to convert the input
+ * string which is expected to be in in src_charset encoding to the
+ * destination charset (which should be a unicode charset).
+ */
+_PUBLIC_ size_t strlen_m_ext(const char *s, charset_t src_charset, charset_t dst_charset)
+{
+ struct smb_iconv_handle *ic = get_iconv_handle();
+ return strlen_m_ext_handle(ic, s, src_charset, dst_charset);
+}
+
_PUBLIC_ size_t strlen_m_ext_term(const char *s, const charset_t src_charset,
const charset_t dst_charset)
{
for (s = src; *s && !(((unsigned char)s[0]) & 0x80); s++) {
if (*s == c)
- return (char *)s;
+ return discard_const_p(char, s);
}
if (!*s)
break;
}
/* No - we have a match ! */
- return (char *)cp;
+ return discard_const_p(char , cp);
}
} while (cp-- != s);
if (!got_mb)
/**
return True if any (multi-byte) character is lower case
*/
-_PUBLIC_ bool strhaslower(const char *string)
+_PUBLIC_ bool strhaslower_handle(struct smb_iconv_handle *ic,
+ const char *string)
{
- struct smb_iconv_handle *ic = get_iconv_handle();
while (*string) {
size_t c_size;
codepoint_t s;
return false;
}
+_PUBLIC_ bool strhaslower(const char *string)
+{
+ struct smb_iconv_handle *ic = get_iconv_handle();
+ return strhaslower_handle(ic, string);
+}
+
/**
return True if any (multi-byte) character is upper case
*/
-_PUBLIC_ bool strhasupper(const char *string)
+_PUBLIC_ bool strhasupper_handle(struct smb_iconv_handle *ic,
+ const char *string)
{
- struct smb_iconv_handle *ic = get_iconv_handle();
while (*string) {
size_t c_size;
codepoint_t s;
return false;
}
+_PUBLIC_ bool strhasupper(const char *string)
+{
+ struct smb_iconv_handle *ic = get_iconv_handle();
+ return strhasupper_handle(ic, string);
+}
+
+/***********************************************************************
+ strstr_m - We convert via ucs2 for now.
+***********************************************************************/
+
+char *strstr_m(const char *src, const char *findstr)
+{
+ smb_ucs2_t *p;
+ smb_ucs2_t *src_w, *find_w;
+ const char *s;
+ char *s2;
+ char *retp;
+ size_t converted_size, findstr_len = 0;
+
+ TALLOC_CTX *frame; /* Only set up in the iconv case */
+
+ /* for correctness */
+ if (!findstr[0]) {
+ return discard_const_p(char, src);
+ }
+
+ /* Samba does single character findstr calls a *lot*. */
+ if (findstr[1] == '\0')
+ return strchr_m(src, *findstr);
+
+ /* 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 (s = src; *s && !(((unsigned char)s[0]) & 0x80); s++) {
+ if (*s == *findstr) {
+ if (!findstr_len)
+ findstr_len = strlen(findstr);
+
+ if (strncmp(s, findstr, findstr_len) == 0) {
+ return discard_const_p(char, s);
+ }
+ }
+ }
+
+ if (!*s)
+ return NULL;
+
+#if 1 /* def BROKEN_UNICODE_COMPOSE_CHARACTERS */
+ /* 'make check' fails unless we do this */
+
+ /* With compose characters we must restart from the beginning. JRA. */
+ s = src;
+#endif
+
+ frame = talloc_stackframe();
+
+ if (!push_ucs2_talloc(frame, &src_w, src, &converted_size)) {
+ DEBUG(0,("strstr_m: src malloc fail\n"));
+ TALLOC_FREE(frame);
+ return NULL;
+ }
+
+ if (!push_ucs2_talloc(frame, &find_w, findstr, &converted_size)) {
+ DEBUG(0,("strstr_m: find malloc fail\n"));
+ TALLOC_FREE(frame);
+ return NULL;
+ }
+
+ p = strstr_w(src_w, find_w);
+
+ if (!p) {
+ TALLOC_FREE(frame);
+ return NULL;
+ }
+
+ *p = 0;
+ if (!pull_ucs2_talloc(frame, &s2, src_w, &converted_size)) {
+ TALLOC_FREE(frame);
+ DEBUG(0,("strstr_m: dest malloc fail\n"));
+ return NULL;
+ }
+ retp = discard_const_p(char, (s+strlen(s2)));
+ TALLOC_FREE(frame);
+ return retp;
+}