summaryrefslogtreecommitdiff
path: root/strings
diff options
context:
space:
mode:
authorunknown <bar@mysql.com>2005-01-13 18:12:04 +0400
committerunknown <bar@mysql.com>2005-01-13 18:12:04 +0400
commit9842aca3ef48bf56a6c3ee5b9e1159e4249ce346 (patch)
tree89b4be1d3a807d6f2554dce92b0a5ecd0a9009ab /strings
parentbcb3783c7c88b06a8417a5734103ae856a2f7dbc (diff)
downloadmariadb-git-9842aca3ef48bf56a6c3ee5b9e1159e4249ce346.tar.gz
bug#7284: strnxfrm returns different results for equal strings
Diffstat (limited to 'strings')
-rw-r--r--strings/ctype-big5.c5
-rw-r--r--strings/ctype-bin.c26
-rw-r--r--strings/ctype-czech.c8
-rw-r--r--strings/ctype-gbk.c5
-rw-r--r--strings/ctype-latin1.c5
-rw-r--r--strings/ctype-mb.c11
-rw-r--r--strings/ctype-simple.c45
-rw-r--r--strings/ctype-sjis.c4
-rw-r--r--strings/ctype-tis620.c6
-rw-r--r--strings/ctype-uca.c16
-rw-r--r--strings/ctype-ucs2.c9
-rw-r--r--strings/ctype-utf8.c5
-rw-r--r--strings/ctype-win1250ch.c4
13 files changed, 117 insertions, 32 deletions
diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c
index 8345c53202c..997b8ce93d6 100644
--- a/strings/ctype-big5.c
+++ b/strings/ctype-big5.c
@@ -298,6 +298,7 @@ static int my_strnxfrm_big5(CHARSET_INFO *cs __attribute__((unused)),
const uchar * src, uint srclen)
{
uint16 e;
+ uint dstlen= len;
len = srclen;
while (len--)
@@ -312,7 +313,9 @@ static int my_strnxfrm_big5(CHARSET_INFO *cs __attribute__((unused)),
} else
*dest++ = sort_order_big5[(uchar) *src++];
}
- return srclen;
+ if (dstlen > srclen)
+ bfill(dest, dstlen - srclen, ' ');
+ return dstlen;
}
#if 0
diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c
index 7d17f62c8d0..95c52512243 100644
--- a/strings/ctype-bin.c
+++ b/strings/ctype-bin.c
@@ -341,13 +341,27 @@ static int my_wildcmp_bin(CHARSET_INFO *cs,
static int my_strnxfrm_bin(CHARSET_INFO *cs __attribute__((unused)),
- uchar * dest, uint len,
- const uchar *src,
- uint srclen __attribute__((unused)))
+ uchar * dest, uint dstlen,
+ const uchar *src, uint srclen)
{
if (dest != src)
- memcpy(dest,src,len= min(len,srclen));
- return len;
+ memcpy(dest, src, min(dstlen,srclen));
+ if (dstlen > srclen)
+ bfill(dest + srclen, dstlen - srclen, 0);
+ return dstlen;
+}
+
+
+static
+int my_strnxfrm_8bit_bin(CHARSET_INFO *cs __attribute__((unused)),
+ uchar * dest, uint dstlen,
+ const uchar *src, uint srclen)
+{
+ if (dest != src)
+ memcpy(dest, src, min(dstlen,srclen));
+ if (dstlen > srclen)
+ bfill(dest + srclen, dstlen - srclen, ' ');
+ return dstlen;
}
@@ -417,7 +431,7 @@ MY_COLLATION_HANDLER my_collation_8bit_bin_handler =
NULL, /* init */
my_strnncoll_8bit_bin,
my_strnncollsp_8bit_bin,
- my_strnxfrm_bin,
+ my_strnxfrm_8bit_bin,
my_like_range_simple,
my_wildcmp_bin,
my_strcasecmp_bin,
diff --git a/strings/ctype-czech.c b/strings/ctype-czech.c
index 2177a18504e..5725e81b15e 100644
--- a/strings/ctype-czech.c
+++ b/strings/ctype-czech.c
@@ -296,16 +296,18 @@ static int my_strnxfrm_czech(CHARSET_INFO *cs __attribute__((unused)),
int value;
const uchar * p, * store;
int pass = 0;
- int totlen = 0;
+ uint totlen = 0;
p = src; store = src;
do
{
NEXT_CMP_VALUE(src, p, store, pass, value, (int)srclen);
- ADD_TO_RESULT(dest, (int)len, totlen, value);
+ ADD_TO_RESULT(dest, len, totlen, value);
}
while (value);
- return totlen;
+ if (len > totlen)
+ bfill(dest + totlen, len - totlen, ' ');
+ return len;
}
#undef IS_END
diff --git a/strings/ctype-gbk.c b/strings/ctype-gbk.c
index 0be56e8d946..731ad58a2fb 100644
--- a/strings/ctype-gbk.c
+++ b/strings/ctype-gbk.c
@@ -2659,6 +2659,7 @@ static int my_strnxfrm_gbk(CHARSET_INFO *cs __attribute__((unused)),
const uchar * src, uint srclen)
{
uint16 e;
+ uint dstlen= len;
len = srclen;
while (len--)
@@ -2673,7 +2674,9 @@ static int my_strnxfrm_gbk(CHARSET_INFO *cs __attribute__((unused)),
} else
*dest++ = sort_order_gbk[(uchar) *src++];
}
- return srclen;
+ if (dstlen > srclen)
+ bfill(dest, dstlen - srclen, ' ');
+ return dstlen;
}
diff --git a/strings/ctype-latin1.c b/strings/ctype-latin1.c
index 5f1850b7772..32d9a227c2f 100644
--- a/strings/ctype-latin1.c
+++ b/strings/ctype-latin1.c
@@ -637,7 +637,6 @@ static int my_strnxfrm_latin1_de(CHARSET_INFO *cs __attribute__((unused)),
uchar * dest, uint len,
const uchar * src, uint srclen)
{
- const uchar *dest_orig = dest;
const uchar *de = dest + len;
const uchar *se = src + srclen;
for ( ; src < se && dest < de ; src++)
@@ -647,7 +646,9 @@ static int my_strnxfrm_latin1_de(CHARSET_INFO *cs __attribute__((unused)),
if ((chr=combo2map[*src]) && dest < de)
*dest++=chr;
}
- return (int) (dest - dest_orig);
+ if (dest < de)
+ bfill(dest, de - dest, ' ');
+ return (int) len;
}
diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c
index 3cdf7f460cd..bf69fe683ae 100644
--- a/strings/ctype-mb.c
+++ b/strings/ctype-mb.c
@@ -412,13 +412,14 @@ static int my_strnncollsp_mb_bin(CHARSET_INFO * cs __attribute__((unused)),
static int my_strnxfrm_mb_bin(CHARSET_INFO *cs __attribute__((unused)),
- uchar * dest, uint len,
- const uchar *src,
- uint srclen __attribute__((unused)))
+ uchar * dest, uint dstlen,
+ const uchar *src, uint srclen)
{
if (dest != src)
- memcpy(dest,src,len= min(len,srclen));
- return len;
+ memcpy(dest, src, min(dstlen, srclen));
+ if (dstlen > srclen)
+ bfill(dest + srclen, dstlen - srclen, ' ');
+ return dstlen;
}
diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c
index a019665a235..5bfa9e52595 100644
--- a/strings/ctype-simple.c
+++ b/strings/ctype-simple.c
@@ -21,27 +21,68 @@
#include "stdarg.h"
+/*
+ Converts a string into its sort key.
+
+ SYNOPSIS
+ my_strnxfrm_xxx()
+
+ IMPLEMENTATION
+
+ The my_strxfrm_xxx() function transforms a string pointed to by
+ 'src' with length 'srclen' according to the charset+collation
+ pair 'cs' and copies the result key into 'dest'.
+
+ Comparing two strings using memcmp() after my_strnxfrm_xxx()
+ is equal to comparing two original strings with my_strnncollsp_xxx().
+
+ Not more than 'dstlen' bytes are written into 'dst'.
+ To garantee that the whole string is transformed, 'dstlen' must be
+ at least srclen*cs->strnxfrm_multiply bytes long. Otherwise,
+ consequent memcmp() may return a non-accurate result.
+
+ If the source string is too short to fill whole 'dstlen' bytes,
+ then the 'dest' string is padded up to 'dstlen', ensuring that:
+
+ "a" == "a "
+ "a\0" < "a"
+ "a\0" < "a "
+
+ my_strnxfrm_simple() is implemented for 8bit charsets and
+ simple collations with one-to-one string->key transformation.
+
+ See also implementations for various charsets/collations in
+ other ctype-xxx.c files.
+
+ RETURN
+
+ Target len 'dstlen'.
+
+*/
+
int my_strnxfrm_simple(CHARSET_INFO * cs,
uchar *dest, uint len,
const uchar *src, uint srclen)
{
uchar *map= cs->sort_order;
+ uint dstlen= len;
set_if_smaller(len, srclen);
if (dest != src)
{
const uchar *end;
for ( end=src+len; src < end ; )
*dest++= map[*src++];
- return len;
}
else
{
const uchar *end;
for ( end=dest+len; dest < end ; dest++)
*dest= (char) map[(uchar) *dest];
- return len;
}
+ if (dstlen > len)
+ bfill(dest, dstlen - len, ' ');
+ return dstlen;
}
int my_strnncoll_simple(CHARSET_INFO * cs, const uchar *s, uint slen,
diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c
index a8b5394f8c5..c0b33a13cdd 100644
--- a/strings/ctype-sjis.c
+++ b/strings/ctype-sjis.c
@@ -291,7 +291,9 @@ static int my_strnxfrm_sjis(CHARSET_INFO *cs __attribute__((unused)),
else
*dest++ = sort_order_sjis[(uchar)*src++];
}
- return srclen;
+ if (len > srclen)
+ bfill(dest, len - srclen, ' ');
+ return len;
}
diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c
index 5d37aa965d9..3a43c556ac8 100644
--- a/strings/ctype-tis620.c
+++ b/strings/ctype-tis620.c
@@ -631,9 +631,13 @@ int my_strnxfrm_tis620(CHARSET_INFO *cs __attribute__((unused)),
uchar * dest, uint len,
const uchar * src, uint srclen)
{
+ uint dstlen= len;
len= (uint) (strmake((char*) dest, (char*) src, min(len, srclen)) -
(char*) dest);
- return (int) thai2sortable(dest, len);
+ len= thai2sortable(dest, len);
+ if (dstlen > len)
+ bfill(dest + len, dstlen - len, ' ');
+ return dstlen;
}
diff --git a/strings/ctype-uca.c b/strings/ctype-uca.c
index 89c876ad10c..4992ef2dcd1 100644
--- a/strings/ctype-uca.c
+++ b/strings/ctype-uca.c
@@ -7214,8 +7214,7 @@ static int my_strnxfrm_uca(CHARSET_INFO *cs,
uchar *dst, uint dstlen,
const uchar *src, uint srclen)
{
- uchar *de = dst + dstlen;
- const uchar *dst_orig = dst;
+ uchar *de = dst + (dstlen & (uint) ~1); // add even length for easier code
int s_res;
my_uca_scanner scanner;
scanner_handler->init(&scanner, cs, src, srclen);
@@ -7226,8 +7225,17 @@ static int my_strnxfrm_uca(CHARSET_INFO *cs,
dst[1]= s_res & 0xFF;
dst+= 2;
}
- for ( ; dst < de; *dst++='\0');
- return dst - dst_orig;
+ s_res= cs->sort_order_big[0][0x20 * cs->sort_order[0]];
+ while (dst < de)
+ {
+ dst[0]= s_res >> 8;
+ dst[1]= s_res & 0xFF;
+ dst+= 2;
+ }
+ if (dstlen & 1) // if odd number then fill the last char
+ *dst= '\0';
+
+ return dstlen;
}
diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c
index 403d31aa15b..936e2b6fdce 100644
--- a/strings/ctype-ucs2.c
+++ b/strings/ctype-ucs2.c
@@ -347,7 +347,6 @@ static int my_strnxfrm_ucs2(CHARSET_INFO *cs,
int plane;
uchar *de = dst + dstlen;
const uchar *se = src + srclen;
- const uchar *dst_orig = dst;
while( src < se && dst < de )
{
@@ -367,7 +366,9 @@ static int my_strnxfrm_ucs2(CHARSET_INFO *cs,
}
dst+=res;
}
- return dst - dst_orig;
+ if (dst < de)
+ cs->cset->fill(cs, dst, de - dst, ' ');
+ return dstlen;
}
@@ -1377,7 +1378,9 @@ int my_strnxfrm_ucs2_bin(CHARSET_INFO *cs __attribute__((unused)),
{
if (dst != src)
memcpy(dst,src,srclen= min(dstlen,srclen));
- return srclen;
+ if (dstlen > srclen)
+ cs->cset->fill(cs, dst + srclen, dstlen - srclen, ' ');
+ return dstlen;
}
diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c
index ce9346eb475..502d0ec285e 100644
--- a/strings/ctype-utf8.c
+++ b/strings/ctype-utf8.c
@@ -2228,7 +2228,6 @@ static int my_strnxfrm_utf8(CHARSET_INFO *cs,
int plane;
uchar *de = dst + dstlen;
const uchar *se = src + srclen;
- const uchar *dst_orig = dst;
while( src < se && dst < de )
{
@@ -2248,7 +2247,9 @@ static int my_strnxfrm_utf8(CHARSET_INFO *cs,
}
dst+=res;
}
- return dst - dst_orig;
+ if (dst < de)
+ bfill(dst, de - dst, ' ');
+ return dstlen;
}
static int my_ismbchar_utf8(CHARSET_INFO *cs,const char *b, const char *e)
diff --git a/strings/ctype-win1250ch.c b/strings/ctype-win1250ch.c
index 4ada3d47bf5..98389a9a5a4 100644
--- a/strings/ctype-win1250ch.c
+++ b/strings/ctype-win1250ch.c
@@ -503,7 +503,9 @@ static int my_strnxfrm_win1250ch(CHARSET_INFO * cs __attribute__((unused)),
dest[totlen] = value;
totlen++;
} while (value) ;
- return totlen;
+ if (len > totlen)
+ bfill(dest + totlen, len - totlen, ' ');
+ return len;
}
#undef IS_END