2015-06-26 11:40:28 +02:00
|
|
|
/*
|
|
|
|
Copyright (c) 2015, MariaDB Foundation
|
2020-01-26 17:27:13 +01:00
|
|
|
Copyright (c) 2015, 2020, MariaDB Corporation.
|
2015-06-26 11:40:28 +02:00
|
|
|
|
|
|
|
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
|
|
|
|
the Free Software Foundation; version 2 of the License.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
2019-05-11 21:19:05 +02:00
|
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA
|
2015-06-26 11:40:28 +02:00
|
|
|
*/
|
|
|
|
|
2021-09-08 09:42:42 +02:00
|
|
|
#include "ctype-ascii.h"
|
|
|
|
|
2015-06-26 11:40:28 +02:00
|
|
|
#ifndef MY_FUNCTION_NAME
|
|
|
|
#error MY_FUNCTION_NAME is not defined
|
|
|
|
#endif
|
|
|
|
|
2018-10-19 12:20:31 +02:00
|
|
|
/*
|
|
|
|
Define strnncoll() and strnncollsp() by default,
|
|
|
|
unless "#define DEFINE_STRNNCOLL 0" is specified.
|
|
|
|
*/
|
|
|
|
#ifndef DEFINE_STRNNCOLL
|
|
|
|
#define DEFINE_STRNNCOLL 1
|
|
|
|
#endif
|
|
|
|
|
2015-06-26 11:40:28 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
The weight for automatically padded spaces when comparing strings with
|
|
|
|
the PAD SPACE property.
|
|
|
|
Should normally be equal to the weight of a regular space.
|
|
|
|
*/
|
|
|
|
#ifndef WEIGHT_PAD_SPACE
|
|
|
|
#define WEIGHT_PAD_SPACE (' ')
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2021-09-08 09:42:42 +02:00
|
|
|
/*
|
|
|
|
For binary collations:
|
|
|
|
- on 32bit platforms perform only 4 byte optimization
|
|
|
|
- on 64bit platforms perform both 4 byte and 8 byte optimization
|
|
|
|
*/
|
|
|
|
#if defined(STRCOLL_MB7_BIN)
|
|
|
|
#define MY_STRCOLL_MB7_4BYTES(a,b) my_strcoll_mb7_bin_4bytes((a),(b))
|
|
|
|
#if SIZEOF_VOIDP == 8
|
|
|
|
#define STRCOLL_MB7_8BYTES
|
|
|
|
#define MY_STRCOLL_MB7_8BYTES(a,b) my_strcoll_mb7_bin_8bytes((a),(b))
|
|
|
|
#endif /* Architecture test */
|
|
|
|
#endif /* STRCOLL_MB7_BIN */
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
For case insensitive collations with trivial mapping from [a-z] to [A-Z]
|
|
|
|
perform optimization only on 64 bit platforms.
|
|
|
|
There is no sense to perform my_ascii_to_upper_magic_uint64() based
|
|
|
|
optimization on 32bit platforms. The idea of this optimization
|
|
|
|
is that it handles 8bytes at a time, using 64bit CPU registers.
|
|
|
|
Enabling this optimization on 32bit platform may only slow things down.
|
|
|
|
*/
|
|
|
|
#if defined(STRCOLL_MB7_TOUPPER)
|
|
|
|
#if SIZEOF_VOIDP == 8
|
|
|
|
#define MY_STRCOLL_MB7_4BYTES(a,b) my_strcoll_ascii_toupper_4bytes((a),(b))
|
|
|
|
#define MY_STRCOLL_MB7_8BYTES(a,b) my_strcoll_ascii_toupper_8bytes((a),(b))
|
|
|
|
#endif /* Architecture test */
|
|
|
|
#endif /* STRCOLL_MB7_TOUPPER */
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
A helper macro to shift two pointers forward, to the given amount.
|
|
|
|
*/
|
|
|
|
#define MY_STRING_SHIFT_PTR_PTR(a,b,len) do { a+= len; b+= len; } while(0)
|
|
|
|
|
|
|
|
|
2015-06-26 11:40:28 +02:00
|
|
|
/*
|
|
|
|
Weight of an illegal byte, must follow these rules:
|
|
|
|
1. Must be greater than weight of any normal character in the collation.
|
|
|
|
2. Two different bad bytes must have different weights and must be
|
|
|
|
compared in their binary order.
|
|
|
|
|
|
|
|
Depends on mbmaxlen of the character set, as well as how the collation
|
|
|
|
sorts various single-byte and multi-byte character blocks.
|
|
|
|
|
|
|
|
The macro below is the default definition, it is suitable for mbmaxlen=2
|
|
|
|
character sets that sort all multi-byte characters after all single-byte
|
|
|
|
characters: big5, euckr, gb2312, gbk.
|
|
|
|
|
|
|
|
All mbmaxlen>2 character sets must provide their own definitions.
|
|
|
|
All collations that have a more complex order (than just MB1 followed by MB2)
|
|
|
|
must also provide their own definitions (see definitions for
|
|
|
|
cp932_japanese_ci and sjis_japanese_ci as examples of a more complex order).
|
|
|
|
*/
|
|
|
|
#ifndef WEIGHT_ILSEQ
|
|
|
|
#define WEIGHT_ILSEQ(x) (0xFF00 + (x))
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2023-04-26 13:27:01 +02:00
|
|
|
#if defined(WEIGHT_SIZE) && WEIGHT_SIZE == 3
|
|
|
|
#define PUT_WC_BE_HAVE_1BYTE(dst, de, wc) PUT_WC_BE3_HAVE_1BYTE((dst), (de), (wc))
|
|
|
|
#define PAD_NWEIGHTS_UNICODE_BE(str, end, n) my_strxfrm_pad_nweights_unicode_be3(str, end, n)
|
|
|
|
#define PAD_UNICODE_BE(str, end) my_strxfrm_pad_unicode_be3(str, end)
|
|
|
|
#else
|
2024-08-17 10:56:28 +02:00
|
|
|
#define WEIGHT_SIZE 2
|
2023-04-26 13:27:01 +02:00
|
|
|
#define PUT_WC_BE_HAVE_1BYTE(dst, de, wc) PUT_WC_BE2_HAVE_1BYTE((dst), (de), (wc))
|
|
|
|
#define PAD_NWEIGHTS_UNICODE_BE(str, end, n) my_strxfrm_pad_nweights_unicode_be2(str, end, n)
|
|
|
|
#define PAD_UNICODE_BE(str, end) my_strxfrm_pad_unicode_be2(str, end)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2018-10-19 12:20:31 +02:00
|
|
|
#if DEFINE_STRNNCOLL
|
|
|
|
|
2015-06-26 11:40:28 +02:00
|
|
|
/**
|
|
|
|
Scan a valid character, or a bad byte, or an auto-padded space
|
|
|
|
from a string and calculate the weight of the scanned sequence.
|
|
|
|
|
|
|
|
@param [OUT] weight - the weight is returned here
|
|
|
|
@param str - the string
|
|
|
|
@param end - the end of the string
|
|
|
|
@return - the number of bytes scanned
|
|
|
|
|
|
|
|
The including source file must define the following macros:
|
2015-07-06 13:50:56 +02:00
|
|
|
IS_MB1_CHAR(b0) - for character sets that have MB1 characters
|
|
|
|
IS_MB1_MB2HEAD_GAP(b0) - optional, for better performance
|
|
|
|
IS_MB2_CHAR(b0,b1) - for character sets that have MB2 characters
|
|
|
|
IS_MB3_CHAR(b0,b1,b2) - for character sets that have MB3 characters
|
|
|
|
IS_MB4_CHAR(b0,b1,b2,b3) - for character sets with have MB4 characters
|
2015-06-26 11:40:28 +02:00
|
|
|
WEIGHT_PAD_SPACE
|
2015-07-06 13:50:56 +02:00
|
|
|
WEIGHT_MB1(b0) - for character sets that have MB1 characters
|
|
|
|
WEIGHT_MB2(b0,b1) - for character sets that have MB2 characters
|
|
|
|
WEIGHT_MB3(b0,b1,b2) - for character sets that have MB3 characters
|
|
|
|
WEIGHT_MB4(b0,b1,b2,b3) - for character sets that have MB4 characters
|
2015-06-26 11:40:28 +02:00
|
|
|
WEIGHT_ILSEQ(x)
|
|
|
|
*/
|
|
|
|
static inline uint
|
|
|
|
MY_FUNCTION_NAME(scan_weight)(int *weight, const uchar *str, const uchar *end)
|
|
|
|
{
|
|
|
|
if (str >= end)
|
|
|
|
{
|
|
|
|
*weight= WEIGHT_PAD_SPACE;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-07-06 13:50:56 +02:00
|
|
|
#ifdef IS_MB1_CHAR
|
2015-06-26 11:40:28 +02:00
|
|
|
if (IS_MB1_CHAR(*str))
|
|
|
|
{
|
|
|
|
*weight= WEIGHT_MB1(*str); /* A valid single byte character*/
|
|
|
|
return 1;
|
|
|
|
}
|
2015-07-06 13:50:56 +02:00
|
|
|
#endif
|
2015-06-26 11:40:28 +02:00
|
|
|
|
2015-07-03 15:24:16 +02:00
|
|
|
#ifdef IS_MB1_MBHEAD_UNUSED_GAP
|
|
|
|
/*
|
|
|
|
Quickly filter out unused bytes that are neither MB1 nor MBHEAD.
|
2019-06-28 07:05:12 +02:00
|
|
|
E.g. [0x80..0xC1] in utf8mb(3|4). This allows using simplified conditions
|
2015-07-03 15:24:16 +02:00
|
|
|
in IS_MB2_CHAR(), IS_MB3_CHAR(), etc.
|
|
|
|
*/
|
|
|
|
if (IS_MB1_MBHEAD_UNUSED_GAP(*str))
|
|
|
|
goto bad;
|
|
|
|
#endif
|
|
|
|
|
2015-07-06 13:50:56 +02:00
|
|
|
#ifdef IS_MB2_CHAR
|
2015-06-26 11:40:28 +02:00
|
|
|
if (str + 2 > end) /* The string ended unexpectedly */
|
|
|
|
goto bad; /* Treat as a bad byte */
|
|
|
|
|
|
|
|
if (IS_MB2_CHAR(str[0], str[1]))
|
|
|
|
{
|
|
|
|
*weight= WEIGHT_MB2(str[0], str[1]);
|
|
|
|
return 2; /* A valid two-byte character */
|
|
|
|
}
|
2015-07-06 13:50:56 +02:00
|
|
|
#endif
|
2015-06-26 11:40:28 +02:00
|
|
|
|
2015-07-03 08:33:17 +02:00
|
|
|
#ifdef IS_MB3_CHAR
|
|
|
|
if (str + 3 > end) /* Incomplete three-byte character */
|
|
|
|
goto bad;
|
|
|
|
|
|
|
|
if (IS_MB3_CHAR(str[0], str[1], str[2]))
|
|
|
|
{
|
|
|
|
*weight= WEIGHT_MB3(str[0], str[1], str[2]);
|
|
|
|
return 3; /* A valid three-byte character */
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-07-06 08:47:39 +02:00
|
|
|
#ifdef IS_MB4_CHAR
|
|
|
|
if (str + 4 > end) /* Incomplete four-byte character */
|
|
|
|
goto bad;
|
|
|
|
|
|
|
|
if (IS_MB4_CHAR(str[0], str[1], str[2], str[3]))
|
|
|
|
{
|
|
|
|
*weight= WEIGHT_MB4(str[0], str[1], str[2], str[3]);
|
|
|
|
return 4; /* A valid four-byte character */
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2015-06-26 11:40:28 +02:00
|
|
|
bad:
|
|
|
|
*weight= WEIGHT_ILSEQ(str[0]); /* Bad byte */
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
Compare two strings according to the collation,
|
|
|
|
without handling the PAD SPACE property.
|
|
|
|
|
2020-01-26 17:27:13 +01:00
|
|
|
Note, strnncoll() is usually used to compare identifiers.
|
2015-06-26 11:40:28 +02:00
|
|
|
Perhaps we should eventually (in 10.2?) create a new collation
|
2019-06-28 07:05:12 +02:00
|
|
|
my_charset_utf8mb3_general_ci_no_pad and have only one comparison function
|
2015-06-26 11:40:28 +02:00
|
|
|
in MY_COLLATION_HANDLER.
|
|
|
|
|
|
|
|
@param cs - the character set and collation
|
|
|
|
@param a - the left string
|
|
|
|
@param a_length - the length of the left string
|
|
|
|
@param b - the right string
|
|
|
|
@param b_length - the length of the right string
|
|
|
|
@param b_is_prefix - if the caller wants to check if "b" is a prefix of "a"
|
|
|
|
@return - the comparison result
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
MY_FUNCTION_NAME(strnncoll)(CHARSET_INFO *cs __attribute__((unused)),
|
|
|
|
const uchar *a, size_t a_length,
|
|
|
|
const uchar *b, size_t b_length,
|
|
|
|
my_bool b_is_prefix)
|
|
|
|
{
|
|
|
|
const uchar *a_end= a + a_length;
|
|
|
|
const uchar *b_end= b + b_length;
|
|
|
|
for ( ; ; )
|
|
|
|
{
|
|
|
|
int a_weight, b_weight, res;
|
|
|
|
uint a_wlen= MY_FUNCTION_NAME(scan_weight)(&a_weight, a, a_end);
|
2021-09-08 09:42:42 +02:00
|
|
|
uint b_wlen;
|
|
|
|
|
|
|
|
#ifdef MY_STRCOLL_MB7_4BYTES
|
|
|
|
if (a_wlen == 1 && my_strcoll_ascii_4bytes_found(a, a_end, b, b_end))
|
|
|
|
{
|
|
|
|
int res;
|
|
|
|
#ifdef MY_STRCOLL_MB7_8BYTES
|
|
|
|
/*TODO: a a loop here >='a' <='z' here, for automatic vectorization*/
|
|
|
|
if (my_strcoll_ascii_4bytes_found(a + 4, a_end, b + 4, b_end))
|
|
|
|
{
|
|
|
|
if ((res= MY_STRCOLL_MB7_8BYTES(a, b)))
|
|
|
|
return res;
|
|
|
|
MY_STRING_SHIFT_PTR_PTR(a, b, 8);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if ((res= MY_STRCOLL_MB7_4BYTES(a, b)))
|
|
|
|
return res;
|
|
|
|
MY_STRING_SHIFT_PTR_PTR(a, b, 4);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
#endif /* MY_STRCOLL_MB7_4BYTES */
|
|
|
|
|
|
|
|
b_wlen= MY_FUNCTION_NAME(scan_weight)(&b_weight, b, b_end);
|
|
|
|
|
2015-06-26 11:40:28 +02:00
|
|
|
/*
|
|
|
|
a_wlen b_wlen Comment
|
|
|
|
------ ------ -------
|
|
|
|
0 0 Strings ended simultaneously, "a" and "b" are equal.
|
|
|
|
0 >0 "a" is a prefix of "b", so "a" is smaller.
|
|
|
|
>0 0 "b" is a prefix of "a", check b_is_prefix.
|
|
|
|
>0 >0 Two weights were scanned, check weight difference.
|
|
|
|
*/
|
|
|
|
if (!a_wlen)
|
2023-04-26 13:27:01 +02:00
|
|
|
return b_wlen ? -1 : 0;
|
2015-06-26 11:40:28 +02:00
|
|
|
|
|
|
|
if (!b_wlen)
|
2023-04-26 13:27:01 +02:00
|
|
|
return b_is_prefix ? 0 : +1;
|
2015-06-26 11:40:28 +02:00
|
|
|
|
|
|
|
if ((res= (a_weight - b_weight)))
|
|
|
|
return res;
|
|
|
|
/*
|
|
|
|
None of the strings has ended yet.
|
|
|
|
*/
|
|
|
|
DBUG_ASSERT(a < a_end);
|
|
|
|
DBUG_ASSERT(b < b_end);
|
|
|
|
a+= a_wlen;
|
|
|
|
b+= b_wlen;
|
|
|
|
}
|
|
|
|
DBUG_ASSERT(0);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-06 10:50:02 +02:00
|
|
|
#ifdef DEFINE_STRNNCOLLSP_NOPAD
|
|
|
|
|
2015-06-26 11:40:28 +02:00
|
|
|
/**
|
2016-09-06 10:50:02 +02:00
|
|
|
Compare two strings according to the collation, with NO PAD handling.
|
2015-06-26 11:40:28 +02:00
|
|
|
|
|
|
|
@param cs - the character set and collation
|
|
|
|
@param a - the left string
|
|
|
|
@param a_length - the length of the left string
|
|
|
|
@param b - the right string
|
|
|
|
@param b_length - the length of the right string
|
|
|
|
@return - the comparison result
|
|
|
|
*/
|
2016-09-06 10:50:02 +02:00
|
|
|
static int
|
|
|
|
MY_FUNCTION_NAME(strnncollsp)(CHARSET_INFO *cs __attribute__((unused)),
|
|
|
|
const uchar *a, size_t a_length,
|
|
|
|
const uchar *b, size_t b_length)
|
|
|
|
{
|
|
|
|
return MY_FUNCTION_NAME(strnncoll)(cs, a, a_length, b, b_length, FALSE);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
/**
|
|
|
|
Compare two strings according to the collation, with PAD SPACE handling.
|
2015-06-26 11:40:28 +02:00
|
|
|
|
2016-09-06 10:50:02 +02:00
|
|
|
@param cs - the character set and collation
|
|
|
|
@param a - the left string
|
|
|
|
@param a_length - the length of the left string
|
|
|
|
@param b - the right string
|
|
|
|
@param b_length - the length of the right string
|
|
|
|
@return - the comparison result
|
|
|
|
*/
|
2015-06-26 11:40:28 +02:00
|
|
|
static int
|
|
|
|
MY_FUNCTION_NAME(strnncollsp)(CHARSET_INFO *cs __attribute__((unused)),
|
|
|
|
const uchar *a, size_t a_length,
|
2016-03-31 09:04:48 +02:00
|
|
|
const uchar *b, size_t b_length)
|
2015-06-26 11:40:28 +02:00
|
|
|
{
|
|
|
|
const uchar *a_end= a + a_length;
|
|
|
|
const uchar *b_end= b + b_length;
|
|
|
|
for ( ; ; )
|
|
|
|
{
|
|
|
|
int a_weight, b_weight, res;
|
|
|
|
uint a_wlen= MY_FUNCTION_NAME(scan_weight)(&a_weight, a, a_end);
|
2021-09-08 09:42:42 +02:00
|
|
|
uint b_wlen;
|
|
|
|
|
|
|
|
#ifdef MY_STRCOLL_MB7_4BYTES
|
|
|
|
if (a_wlen == 1 && my_strcoll_ascii_4bytes_found(a, a_end, b, b_end))
|
|
|
|
{
|
|
|
|
int res;
|
|
|
|
#ifdef MY_STRCOLL_MB7_8BYTES
|
|
|
|
if (my_strcoll_ascii_4bytes_found(a + 4, a_end, b + 4, b_end))
|
|
|
|
{
|
|
|
|
if ((res= MY_STRCOLL_MB7_8BYTES(a, b)))
|
|
|
|
return res;
|
|
|
|
MY_STRING_SHIFT_PTR_PTR(a, b, 8);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if ((res= MY_STRCOLL_MB7_4BYTES(a, b)))
|
|
|
|
return res;
|
|
|
|
MY_STRING_SHIFT_PTR_PTR(a, b, 4);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
#endif /* MY_STRCOLL_MB7_4BYTES */
|
|
|
|
|
|
|
|
b_wlen= MY_FUNCTION_NAME(scan_weight)(&b_weight, b, b_end);
|
|
|
|
|
2015-06-26 11:40:28 +02:00
|
|
|
if ((res= (a_weight - b_weight)))
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
Got two different weights. Each weight can be generated by either of:
|
|
|
|
- a real character
|
|
|
|
- a bad byte sequence or an incomplete byte sequence
|
|
|
|
- an auto-generated trailing space (PAD SPACE)
|
|
|
|
It does not matter how exactly each weight was generated.
|
|
|
|
Just return the weight difference.
|
|
|
|
*/
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
if (!a_wlen && !b_wlen)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
Got two auto-generated trailing spaces, i.e.
|
|
|
|
both strings have now ended, so they are equal.
|
|
|
|
*/
|
|
|
|
DBUG_ASSERT(a == a_end);
|
|
|
|
DBUG_ASSERT(b == b_end);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
At least one of the strings has not ended yet, continue comparison.
|
|
|
|
*/
|
|
|
|
DBUG_ASSERT(a < a_end || b < b_end);
|
|
|
|
a+= a_wlen;
|
|
|
|
b+= b_wlen;
|
|
|
|
}
|
|
|
|
DBUG_ASSERT(0);
|
|
|
|
return 0;
|
|
|
|
}
|
2021-09-08 09:42:42 +02:00
|
|
|
#endif /* DEFINE_STRNNCOLLSP_NOPAD */
|
2015-06-26 11:40:28 +02:00
|
|
|
|
2021-09-29 13:13:57 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
Compare two strings according to the collation,
|
|
|
|
with trailing space padding or trimming, according to "nchars".
|
|
|
|
|
|
|
|
@param cs - the character set and collation
|
|
|
|
@param a - the left string
|
|
|
|
@param a_length - the length of the left string
|
|
|
|
@param b - the right string
|
|
|
|
@param b_length - the length of the right string
|
|
|
|
@param nchars - compare this amount of characters only
|
|
|
|
@return - the comparison result
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
MY_FUNCTION_NAME(strnncollsp_nchars)(CHARSET_INFO *cs __attribute__((unused)),
|
|
|
|
const uchar *a, size_t a_length,
|
|
|
|
const uchar *b, size_t b_length,
|
2023-03-31 15:20:03 +02:00
|
|
|
size_t nchars,
|
|
|
|
uint flags)
|
2021-09-29 13:13:57 +02:00
|
|
|
{
|
|
|
|
const uchar *a_end= a + a_length;
|
|
|
|
const uchar *b_end= b + b_length;
|
|
|
|
for ( ; nchars ; nchars--)
|
|
|
|
{
|
|
|
|
int a_weight, b_weight, res;
|
|
|
|
uint a_wlen= MY_FUNCTION_NAME(scan_weight)(&a_weight, a, a_end);
|
|
|
|
uint b_wlen= MY_FUNCTION_NAME(scan_weight)(&b_weight, b, b_end);
|
|
|
|
|
|
|
|
if ((res= (a_weight - b_weight)))
|
|
|
|
{
|
|
|
|
/* Got two different weights. See comments in strnncollsp above. */
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
if (!a_wlen && !b_wlen)
|
|
|
|
{
|
|
|
|
/* Got two auto-generated trailing spaces. */
|
|
|
|
DBUG_ASSERT(a == a_end);
|
|
|
|
DBUG_ASSERT(b == b_end);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
At least one of the strings has not ended yet, continue comparison.
|
|
|
|
*/
|
|
|
|
DBUG_ASSERT(a < a_end || b < b_end);
|
|
|
|
a+= a_wlen;
|
|
|
|
b+= b_wlen;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-10-19 12:20:31 +02:00
|
|
|
#endif /* DEFINE_STRNNCOLL */
|
|
|
|
|
2016-03-23 11:26:43 +01:00
|
|
|
|
|
|
|
#ifdef DEFINE_STRNXFRM
|
|
|
|
#ifndef WEIGHT_MB2_FRM
|
|
|
|
#define WEIGHT_MB2_FRM(x,y) WEIGHT_MB2(x,y)
|
|
|
|
#endif
|
|
|
|
|
2024-08-17 10:56:28 +02:00
|
|
|
static my_strnxfrm_ret_t
|
2016-03-23 11:26:43 +01:00
|
|
|
MY_FUNCTION_NAME(strnxfrm)(CHARSET_INFO *cs,
|
|
|
|
uchar *dst, size_t dstlen, uint nweights,
|
|
|
|
const uchar *src, size_t srclen, uint flags)
|
|
|
|
{
|
|
|
|
uchar *d0= dst;
|
|
|
|
uchar *de= dst + dstlen;
|
2024-08-17 10:56:28 +02:00
|
|
|
const uchar *src0= src;
|
2016-03-23 11:26:43 +01:00
|
|
|
const uchar *se= src + srclen;
|
|
|
|
const uchar *sort_order= cs->sort_order;
|
2024-08-17 10:56:28 +02:00
|
|
|
uint warnings= 0;
|
|
|
|
my_strnxfrm_ret_t rcpad;
|
2016-03-23 11:26:43 +01:00
|
|
|
|
|
|
|
for (; dst < de && src < se && nweights; nweights--)
|
|
|
|
{
|
2020-01-26 17:27:13 +01:00
|
|
|
if (my_ci_charlen(cs, src, se) > 1)
|
2016-03-23 11:26:43 +01:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
Note, it is safe not to check (src < se)
|
2020-01-26 17:27:13 +01:00
|
|
|
in the code below, because my_ci_charlen() would
|
2016-03-23 11:26:43 +01:00
|
|
|
not return 2 if src was too short
|
|
|
|
*/
|
|
|
|
uint16 e= WEIGHT_MB2_FRM(src[0], src[1]);
|
|
|
|
*dst++= (uchar) (e >> 8);
|
|
|
|
if (dst < de)
|
|
|
|
*dst++= (uchar) (e & 0xFF);
|
2024-08-17 10:56:28 +02:00
|
|
|
else
|
|
|
|
warnings|= MY_STRNXFRM_TRUNCATED_WEIGHT_REAL_CHAR;
|
2016-03-23 11:26:43 +01:00
|
|
|
src+= 2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
*dst++= sort_order ? sort_order[*src++] : *src++;
|
|
|
|
}
|
2024-08-17 10:56:28 +02:00
|
|
|
rcpad=
|
2016-09-06 10:50:02 +02:00
|
|
|
#ifdef DEFINE_STRNNCOLLSP_NOPAD
|
2024-08-17 10:56:28 +02:00
|
|
|
my_strxfrm_pad_desc_and_reverse_nopad(cs, d0, dst, de,
|
|
|
|
nweights, flags, 0);
|
2016-09-06 10:50:02 +02:00
|
|
|
#else
|
2024-08-17 10:56:28 +02:00
|
|
|
my_strxfrm_pad_desc_and_reverse(cs, d0, dst, de, nweights, flags, 0);
|
2016-09-06 10:50:02 +02:00
|
|
|
#endif
|
2024-08-17 10:56:28 +02:00
|
|
|
|
|
|
|
return my_strnxfrm_ret_construct(rcpad.m_result_length, src - src0,
|
|
|
|
rcpad.m_warnings | warnings |
|
|
|
|
(src < se ? MY_STRNXFRM_TRUNCATED_WEIGHT_REAL_CHAR : 0));
|
2016-03-23 11:26:43 +01:00
|
|
|
}
|
|
|
|
#endif /* DEFINE_STRNXFRM */
|
|
|
|
|
|
|
|
|
2018-10-19 12:20:31 +02:00
|
|
|
#if defined(DEFINE_STRNXFRM_UNICODE) || defined(DEFINE_STRNXFRM_UNICODE_NOPAD)
|
|
|
|
|
|
|
|
/*
|
|
|
|
Store sorting weights using 2 bytes per character.
|
|
|
|
|
|
|
|
This function is shared between
|
2019-06-28 07:05:12 +02:00
|
|
|
- utf8mb3_general_ci, utf8mb3_bin, ucs2_general_ci, ucs2_bin
|
2018-10-19 12:20:31 +02:00
|
|
|
which support BMP only (U+0000..U+FFFF).
|
|
|
|
- utf8mb4_general_ci, utf16_general_ci, utf32_general_ci,
|
|
|
|
which map all supplementary characters to weight 0xFFFD.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef MY_MB_WC
|
|
|
|
#error MY_MB_WC must be defined for DEFINE_STRNXFRM_UNICODE
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef OPTIMIZE_ASCII
|
|
|
|
#error OPTIMIZE_ASCII must be defined for DEFINE_STRNXFRM_UNICODE
|
|
|
|
#endif
|
|
|
|
|
2023-02-24 16:22:32 +01:00
|
|
|
#if OPTIMIZE_ASCII && !defined(WEIGHT_MB1)
|
|
|
|
#error WEIGHT_MB1 must be defined for DEFINE_STRNXFRM_UNICODE
|
2018-10-19 12:20:31 +02:00
|
|
|
#endif
|
|
|
|
|
2023-02-24 16:22:32 +01:00
|
|
|
#ifndef MY_WC_WEIGHT
|
|
|
|
#error MY_WC_WEIGHT must be defined for DEFINE_STRNXFRM_UNICODE
|
2018-10-19 12:20:31 +02:00
|
|
|
#endif
|
|
|
|
|
2024-08-17 10:56:28 +02:00
|
|
|
static my_strnxfrm_ret_t
|
2020-01-29 15:41:04 +01:00
|
|
|
MY_FUNCTION_NAME(strnxfrm_internal)(CHARSET_INFO *cs __attribute__((unused)),
|
2018-10-19 12:20:31 +02:00
|
|
|
uchar *dst, uchar *de,
|
|
|
|
uint *nweights,
|
|
|
|
const uchar *src, const uchar *se)
|
|
|
|
{
|
|
|
|
my_wc_t UNINIT_VAR(wc);
|
|
|
|
uchar *dst0= dst;
|
2024-08-17 10:56:28 +02:00
|
|
|
const uchar *src0= src;
|
|
|
|
uint warnings= 0;
|
2018-10-19 12:20:31 +02:00
|
|
|
|
|
|
|
DBUG_ASSERT(src || !se);
|
|
|
|
DBUG_ASSERT((cs->state & MY_CS_LOWER_SORT) == 0);
|
|
|
|
|
|
|
|
for (; dst < de && *nweights; (*nweights)--)
|
|
|
|
{
|
|
|
|
int res;
|
|
|
|
#if OPTIMIZE_ASCII
|
|
|
|
if (src >= se)
|
|
|
|
break;
|
|
|
|
if (src[0] <= 0x7F)
|
|
|
|
{
|
2023-02-24 16:22:32 +01:00
|
|
|
wc= WEIGHT_MB1(*src++);
|
2024-08-17 10:56:28 +02:00
|
|
|
warnings|= de - dst < WEIGHT_SIZE ?
|
|
|
|
MY_STRNXFRM_TRUNCATED_WEIGHT_REAL_CHAR : 0;
|
2023-04-26 13:27:01 +02:00
|
|
|
PUT_WC_BE_HAVE_1BYTE(dst, de, wc);
|
2018-10-19 12:20:31 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if ((res= MY_MB_WC(cs, &wc, src, se)) <= 0)
|
|
|
|
break;
|
|
|
|
src+= res;
|
2023-02-24 16:22:32 +01:00
|
|
|
wc= MY_WC_WEIGHT(wc);
|
2024-08-17 10:56:28 +02:00
|
|
|
warnings|= de - dst < WEIGHT_SIZE ?
|
|
|
|
MY_STRNXFRM_TRUNCATED_WEIGHT_REAL_CHAR : 0;
|
2023-04-26 13:27:01 +02:00
|
|
|
PUT_WC_BE_HAVE_1BYTE(dst, de, wc);
|
2018-10-19 12:20:31 +02:00
|
|
|
}
|
2024-08-17 10:56:28 +02:00
|
|
|
return my_strnxfrm_ret_construct(dst - dst0, src - src0,
|
|
|
|
warnings |
|
|
|
|
(src < se ? MY_STRNXFRM_TRUNCATED_WEIGHT_REAL_CHAR : 0));
|
2018-10-19 12:20:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-08-17 10:56:28 +02:00
|
|
|
static my_strnxfrm_ret_t
|
2018-10-19 12:20:31 +02:00
|
|
|
MY_FUNCTION_NAME(strnxfrm)(CHARSET_INFO *cs,
|
|
|
|
uchar *dst, size_t dstlen, uint nweights,
|
|
|
|
const uchar *src, size_t srclen, uint flags)
|
|
|
|
{
|
|
|
|
uchar *dst0= dst;
|
|
|
|
uchar *de= dst + dstlen;
|
2024-08-17 10:56:28 +02:00
|
|
|
my_strnxfrm_ret_t rc= MY_FUNCTION_NAME(strnxfrm_internal)(cs, dst, de,
|
|
|
|
&nweights,
|
|
|
|
src, src + srclen);
|
|
|
|
dst+= rc.m_result_length;
|
2018-10-19 12:20:31 +02:00
|
|
|
DBUG_ASSERT(dst <= de); /* Safety */
|
|
|
|
|
2024-08-17 10:56:28 +02:00
|
|
|
if (nweights && (flags & MY_STRXFRM_PAD_WITH_SPACE))
|
|
|
|
{
|
|
|
|
my_strnxfrm_pad_ret_t rcpad= PAD_NWEIGHTS_UNICODE_BE(dst, de, nweights);
|
|
|
|
rc.m_warnings|= rcpad.m_warnings;
|
|
|
|
dst+= rcpad.m_result_length;
|
|
|
|
}
|
2018-10-19 12:20:31 +02:00
|
|
|
|
|
|
|
my_strxfrm_desc_and_reverse(dst0, dst, flags, 0);
|
|
|
|
|
|
|
|
if ((flags & MY_STRXFRM_PAD_TO_MAXLEN) && dst < de)
|
2023-04-26 13:27:01 +02:00
|
|
|
dst+= PAD_UNICODE_BE(dst, de);
|
2024-08-17 10:56:28 +02:00
|
|
|
rc.m_result_length= dst - dst0;
|
|
|
|
return rc;
|
2018-10-19 12:20:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef DEFINE_STRNXFRM_UNICODE_NOPAD
|
2024-08-17 10:56:28 +02:00
|
|
|
static my_strnxfrm_ret_t
|
2018-10-19 12:20:31 +02:00
|
|
|
MY_FUNCTION_NAME(strnxfrm_nopad)(CHARSET_INFO *cs,
|
|
|
|
uchar *dst, size_t dstlen,
|
|
|
|
uint nweights,
|
|
|
|
const uchar *src, size_t srclen, uint flags)
|
|
|
|
{
|
|
|
|
uchar *dst0= dst;
|
|
|
|
uchar *de= dst + dstlen;
|
2024-08-17 10:56:28 +02:00
|
|
|
my_strnxfrm_ret_t rc= MY_FUNCTION_NAME(strnxfrm_internal)(cs,
|
|
|
|
dst, de, &nweights,
|
|
|
|
src, src + srclen);
|
|
|
|
dst+= rc.m_result_length;
|
2018-10-19 12:20:31 +02:00
|
|
|
DBUG_ASSERT(dst <= de); /* Safety */
|
|
|
|
|
2024-08-17 10:56:28 +02:00
|
|
|
if (nweights && (flags & MY_STRXFRM_PAD_WITH_SPACE))
|
2018-10-19 12:20:31 +02:00
|
|
|
{
|
|
|
|
size_t len= de - dst;
|
2024-08-17 10:56:28 +02:00
|
|
|
if (len < nweights * 2)
|
|
|
|
rc.m_warnings|= MY_STRNXFRM_TRUNCATED_WEIGHT_TRAILING_SPACE;
|
2018-10-19 12:20:31 +02:00
|
|
|
set_if_smaller(len, nweights * 2);
|
|
|
|
memset(dst, 0x00, len);
|
|
|
|
dst+= len;
|
|
|
|
}
|
|
|
|
|
|
|
|
my_strxfrm_desc_and_reverse(dst0, dst, flags, 0);
|
|
|
|
|
|
|
|
if ((flags & MY_STRXFRM_PAD_TO_MAXLEN) && dst < de)
|
|
|
|
{
|
|
|
|
memset(dst, 0x00, de - dst);
|
|
|
|
dst= de;
|
|
|
|
}
|
2024-08-17 10:56:28 +02:00
|
|
|
rc.m_result_length= dst - dst0;
|
|
|
|
return rc;
|
2018-10-19 12:20:31 +02:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif /* DEFINE_STRNXFRM_UNICODE || DEFINE_STRNXFRM_UNICODE_NOPAD */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef DEFINE_STRNXFRM_UNICODE_BIN2
|
|
|
|
|
|
|
|
/*
|
|
|
|
Store sorting weights using 2 bytes per character.
|
|
|
|
|
|
|
|
These functions are shared between
|
2019-06-28 07:05:12 +02:00
|
|
|
- utf8mb3_general_ci, utf8mb3_bin, ucs2_general_ci, ucs2_bin
|
2018-10-19 12:20:31 +02:00
|
|
|
which support BMP only (U+0000..U+FFFF).
|
|
|
|
- utf8mb4_general_ci, utf16_general_ci, utf32_general_ci,
|
|
|
|
which map all supplementary characters to weight 0xFFFD.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef MY_MB_WC
|
|
|
|
#error MY_MB_WC must be defined for DEFINE_STRNXFRM_UNICODE_BIN2
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef OPTIMIZE_ASCII
|
|
|
|
#error OPTIMIZE_ASCII must be defined for DEFINE_STRNXFRM_UNICODE_BIN2
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2024-08-17 10:56:28 +02:00
|
|
|
static my_strnxfrm_ret_t
|
2020-01-29 15:41:04 +01:00
|
|
|
MY_FUNCTION_NAME(strnxfrm_internal)(CHARSET_INFO *cs __attribute__((unused)),
|
2018-10-19 12:20:31 +02:00
|
|
|
uchar *dst, uchar *de,
|
|
|
|
uint *nweights,
|
|
|
|
const uchar *src,
|
|
|
|
const uchar *se)
|
|
|
|
{
|
|
|
|
my_wc_t UNINIT_VAR(wc);
|
2024-08-17 10:56:28 +02:00
|
|
|
const uchar *src0= src;
|
2018-10-19 12:20:31 +02:00
|
|
|
uchar *dst0= dst;
|
2024-08-17 10:56:28 +02:00
|
|
|
uint warnings= 0;
|
2018-10-19 12:20:31 +02:00
|
|
|
|
|
|
|
DBUG_ASSERT(src || !se);
|
|
|
|
|
|
|
|
for (; dst < de && *nweights; (*nweights)--)
|
|
|
|
{
|
|
|
|
int res;
|
|
|
|
#if OPTIMIZE_ASCII
|
|
|
|
if (src >= se)
|
|
|
|
break;
|
|
|
|
if (src[0] <= 0x7F)
|
|
|
|
{
|
|
|
|
wc= *src++;
|
2024-08-17 10:56:28 +02:00
|
|
|
warnings|= de - dst < WEIGHT_SIZE ?
|
|
|
|
MY_STRNXFRM_TRUNCATED_WEIGHT_REAL_CHAR : 0;
|
2018-10-19 12:20:31 +02:00
|
|
|
PUT_WC_BE2_HAVE_1BYTE(dst, de, wc);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if ((res= MY_MB_WC(cs, &wc, src, se)) <= 0)
|
|
|
|
break;
|
|
|
|
src+= res;
|
|
|
|
if (wc > 0xFFFF)
|
|
|
|
wc= MY_CS_REPLACEMENT_CHARACTER;
|
2024-08-17 10:56:28 +02:00
|
|
|
warnings|= de - dst < WEIGHT_SIZE ?
|
|
|
|
MY_STRNXFRM_TRUNCATED_WEIGHT_REAL_CHAR : 0;
|
2018-10-19 12:20:31 +02:00
|
|
|
PUT_WC_BE2_HAVE_1BYTE(dst, de, wc);
|
|
|
|
}
|
2024-08-17 10:56:28 +02:00
|
|
|
return my_strnxfrm_ret_construct(dst - dst0, src - src0,
|
|
|
|
warnings |
|
2023-09-04 08:15:06 +02:00
|
|
|
((src - se) ? MY_STRNXFRM_TRUNCATED_WEIGHT_REAL_CHAR : 0));
|
2018-10-19 12:20:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-08-17 10:56:28 +02:00
|
|
|
static my_strnxfrm_ret_t
|
2018-10-19 12:20:31 +02:00
|
|
|
MY_FUNCTION_NAME(strnxfrm)(CHARSET_INFO *cs,
|
|
|
|
uchar *dst, size_t dstlen, uint nweights,
|
|
|
|
const uchar *src, size_t srclen, uint flags)
|
|
|
|
{
|
|
|
|
uchar *dst0= dst;
|
|
|
|
uchar *de= dst + dstlen;
|
2024-08-17 10:56:28 +02:00
|
|
|
my_strnxfrm_ret_t rc= MY_FUNCTION_NAME(strnxfrm_internal)(cs, dst, de,
|
|
|
|
&nweights,
|
|
|
|
src, src + srclen);
|
|
|
|
dst+= rc.m_result_length;
|
2018-10-19 12:20:31 +02:00
|
|
|
DBUG_ASSERT(dst <= de); /* Safety */
|
|
|
|
|
2024-08-17 10:56:28 +02:00
|
|
|
if (nweights && (flags & MY_STRXFRM_PAD_WITH_SPACE))
|
|
|
|
{
|
|
|
|
my_strnxfrm_pad_ret_t rcpad= PAD_NWEIGHTS_UNICODE_BE(dst, de, nweights);
|
|
|
|
rc.m_warnings|= rcpad.m_warnings;
|
|
|
|
dst+= rcpad.m_result_length;
|
|
|
|
}
|
2018-10-19 12:20:31 +02:00
|
|
|
|
|
|
|
my_strxfrm_desc_and_reverse(dst0, dst, flags, 0);
|
|
|
|
|
|
|
|
if ((flags & MY_STRXFRM_PAD_TO_MAXLEN) && dst < de)
|
2023-04-26 13:27:01 +02:00
|
|
|
dst+= PAD_UNICODE_BE(dst, de);
|
2024-08-17 10:56:28 +02:00
|
|
|
rc.m_result_length= dst - dst0;
|
|
|
|
return rc;
|
2018-10-19 12:20:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-08-17 10:56:28 +02:00
|
|
|
static my_strnxfrm_ret_t
|
2018-10-19 12:20:31 +02:00
|
|
|
MY_FUNCTION_NAME(strnxfrm_nopad)(CHARSET_INFO *cs,
|
|
|
|
uchar *dst, size_t dstlen, uint nweights,
|
|
|
|
const uchar *src, size_t srclen, uint flags)
|
|
|
|
{
|
|
|
|
uchar *dst0= dst;
|
|
|
|
uchar *de= dst + dstlen;
|
2024-08-17 10:56:28 +02:00
|
|
|
my_strnxfrm_ret_t rc= MY_FUNCTION_NAME(strnxfrm_internal)(cs, dst, de,
|
|
|
|
&nweights,
|
|
|
|
src, src + srclen);
|
|
|
|
dst+= rc.m_result_length;
|
2018-10-19 12:20:31 +02:00
|
|
|
DBUG_ASSERT(dst <= de); /* Safety */
|
|
|
|
|
2024-08-17 10:56:28 +02:00
|
|
|
if (nweights && (flags & MY_STRXFRM_PAD_WITH_SPACE))
|
2018-10-19 12:20:31 +02:00
|
|
|
{
|
|
|
|
size_t len= de - dst;
|
2024-08-17 10:56:28 +02:00
|
|
|
if (len < nweights * 2)
|
|
|
|
rc.m_warnings|= MY_STRNXFRM_TRUNCATED_WEIGHT_TRAILING_SPACE;
|
2018-10-19 12:20:31 +02:00
|
|
|
set_if_smaller(len, nweights * 2);
|
|
|
|
memset(dst, 0x00, len);
|
|
|
|
dst+= len;
|
|
|
|
}
|
|
|
|
|
|
|
|
my_strxfrm_desc_and_reverse(dst0, dst, flags, 0);
|
|
|
|
|
|
|
|
if ((flags & MY_STRXFRM_PAD_TO_MAXLEN) && dst < de)
|
|
|
|
{
|
|
|
|
memset(dst, 0x00, de - dst);
|
|
|
|
dst= de;
|
|
|
|
}
|
2024-08-17 10:56:28 +02:00
|
|
|
rc.m_result_length= dst - dst0;
|
|
|
|
return rc;
|
2018-10-19 12:20:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* DEFINE_STRNXFRM_UNICODE_BIN2 */
|
|
|
|
|
|
|
|
|
2015-06-26 11:40:28 +02:00
|
|
|
/*
|
|
|
|
We usually include this file at least two times from the same source file,
|
|
|
|
for the _ci and the _bin collations. Prepare for the second inclusion.
|
|
|
|
*/
|
|
|
|
#undef MY_FUNCTION_NAME
|
2018-10-19 12:20:31 +02:00
|
|
|
#undef MY_MB_WC
|
|
|
|
#undef OPTIMIZE_ASCII
|
2023-02-24 16:22:32 +01:00
|
|
|
#undef MY_WC_WEIGHT
|
2015-06-26 11:40:28 +02:00
|
|
|
#undef WEIGHT_ILSEQ
|
|
|
|
#undef WEIGHT_MB1
|
|
|
|
#undef WEIGHT_MB2
|
2015-07-03 08:33:17 +02:00
|
|
|
#undef WEIGHT_MB3
|
2015-07-06 08:47:39 +02:00
|
|
|
#undef WEIGHT_MB4
|
2015-06-26 11:40:28 +02:00
|
|
|
#undef WEIGHT_PAD_SPACE
|
2016-03-23 11:26:43 +01:00
|
|
|
#undef WEIGHT_MB2_FRM
|
2023-04-26 13:27:01 +02:00
|
|
|
#undef WEIGHT_SIZE
|
2016-03-23 11:26:43 +01:00
|
|
|
#undef DEFINE_STRNXFRM
|
2018-10-19 12:20:31 +02:00
|
|
|
#undef DEFINE_STRNXFRM_UNICODE
|
|
|
|
#undef DEFINE_STRNXFRM_UNICODE_NOPAD
|
|
|
|
#undef DEFINE_STRNXFRM_UNICODE_BIN2
|
|
|
|
#undef DEFINE_STRNNCOLL
|
2016-09-06 10:50:02 +02:00
|
|
|
#undef DEFINE_STRNNCOLLSP_NOPAD
|
2021-09-08 09:42:42 +02:00
|
|
|
|
|
|
|
#undef STRCOLL_MB7_TOUPPER
|
|
|
|
#undef STRCOLL_MB7_BIN
|
|
|
|
#undef MY_STRCOLL_MB7_4BYTES
|
|
|
|
#undef MY_STRCOLL_MB7_8BYTES
|
2023-04-26 13:27:01 +02:00
|
|
|
#undef PUT_WC_BE_HAVE_1BYTE
|
|
|
|
#undef PAD_NWEIGHTS_UNICODE_BE
|
|
|
|
#undef PAD_UNICODE_BE
|