|
|
|
@ -1803,30 +1803,37 @@ get_collation_actual_version(char collprovider, const char *collcollate) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* pg_strncoll_libc_win32_utf8 |
|
|
|
* strncoll_libc_win32_utf8 |
|
|
|
* |
|
|
|
* |
|
|
|
* Win32 does not have UTF-8. Convert UTF8 arguments to wide characters and |
|
|
|
* Win32 does not have UTF-8. Convert UTF8 arguments to wide characters and |
|
|
|
* invoke wcscoll_l(). |
|
|
|
* invoke wcscoll_l(). |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* An input string length of -1 means that it's NUL-terminated. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
#ifdef WIN32 |
|
|
|
#ifdef WIN32 |
|
|
|
static int |
|
|
|
static int |
|
|
|
pg_strncoll_libc_win32_utf8(const char *arg1, size_t len1, const char *arg2, |
|
|
|
strncoll_libc_win32_utf8(const char *arg1, ssize_t len1, const char *arg2, |
|
|
|
size_t len2, pg_locale_t locale) |
|
|
|
ssize_t len2, pg_locale_t locale) |
|
|
|
{ |
|
|
|
{ |
|
|
|
char sbuf[TEXTBUFLEN]; |
|
|
|
char sbuf[TEXTBUFLEN]; |
|
|
|
char *buf = sbuf; |
|
|
|
char *buf = sbuf; |
|
|
|
char *a1p, |
|
|
|
char *a1p, |
|
|
|
*a2p; |
|
|
|
*a2p; |
|
|
|
int a1len = len1 * 2 + 2; |
|
|
|
int a1len; |
|
|
|
int a2len = len2 * 2 + 2; |
|
|
|
int a2len; |
|
|
|
int r; |
|
|
|
int r; |
|
|
|
int result; |
|
|
|
int result; |
|
|
|
|
|
|
|
|
|
|
|
Assert(locale->provider == COLLPROVIDER_LIBC); |
|
|
|
Assert(locale->provider == COLLPROVIDER_LIBC); |
|
|
|
Assert(GetDatabaseEncoding() == PG_UTF8); |
|
|
|
Assert(GetDatabaseEncoding() == PG_UTF8); |
|
|
|
#ifndef WIN32 |
|
|
|
|
|
|
|
Assert(false); |
|
|
|
if (len1 == -1) |
|
|
|
#endif |
|
|
|
len1 = strlen(arg1); |
|
|
|
|
|
|
|
if (len2 == -1) |
|
|
|
|
|
|
|
len2 = strlen(arg2); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
a1len = len1 * 2 + 2; |
|
|
|
|
|
|
|
a2len = len2 * 2 + 2; |
|
|
|
|
|
|
|
|
|
|
|
if (a1len + a2len > TEXTBUFLEN) |
|
|
|
if (a1len + a2len > TEXTBUFLEN) |
|
|
|
buf = palloc(a1len + a2len); |
|
|
|
buf = palloc(a1len + a2len); |
|
|
|
@ -1875,50 +1882,22 @@ pg_strncoll_libc_win32_utf8(const char *arg1, size_t len1, const char *arg2, |
|
|
|
#endif /* WIN32 */ |
|
|
|
#endif /* WIN32 */ |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* pg_strcoll_libc |
|
|
|
* strncoll_libc |
|
|
|
* |
|
|
|
|
|
|
|
* Call strcoll_l() or wcscoll_l() as appropriate for the given locale, |
|
|
|
|
|
|
|
* platform, and database encoding. If the locale is NULL, use the database |
|
|
|
|
|
|
|
* collation. |
|
|
|
|
|
|
|
* |
|
|
|
* |
|
|
|
* Arguments must be encoded in the database encoding and nul-terminated. |
|
|
|
* NUL-terminate arguments, if necessary, and pass to strcoll_l(). |
|
|
|
*/ |
|
|
|
|
|
|
|
static int |
|
|
|
|
|
|
|
pg_strcoll_libc(const char *arg1, const char *arg2, pg_locale_t locale) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int result; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Assert(locale->provider == COLLPROVIDER_LIBC); |
|
|
|
|
|
|
|
#ifdef WIN32 |
|
|
|
|
|
|
|
if (GetDatabaseEncoding() == PG_UTF8) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
size_t len1 = strlen(arg1); |
|
|
|
|
|
|
|
size_t len2 = strlen(arg2); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result = pg_strncoll_libc_win32_utf8(arg1, len1, arg2, len2, locale); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
#endif /* WIN32 */ |
|
|
|
|
|
|
|
result = strcoll_l(arg1, arg2, locale->info.lt); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return result; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* pg_strncoll_libc |
|
|
|
|
|
|
|
* |
|
|
|
* |
|
|
|
* Nul-terminate the arguments and call pg_strcoll_libc(). |
|
|
|
* An input string length of -1 means that it's already NUL-terminated. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
static int |
|
|
|
static int |
|
|
|
pg_strncoll_libc(const char *arg1, size_t len1, const char *arg2, size_t len2, |
|
|
|
strncoll_libc(const char *arg1, ssize_t len1, const char *arg2, ssize_t len2, |
|
|
|
pg_locale_t locale) |
|
|
|
pg_locale_t locale) |
|
|
|
{ |
|
|
|
{ |
|
|
|
char sbuf[TEXTBUFLEN]; |
|
|
|
char sbuf[TEXTBUFLEN]; |
|
|
|
char *buf = sbuf; |
|
|
|
char *buf = sbuf; |
|
|
|
size_t bufsize1 = len1 + 1; |
|
|
|
size_t bufsize1 = (len1 == -1) ? 0 : len1 + 1; |
|
|
|
size_t bufsize2 = len2 + 1; |
|
|
|
size_t bufsize2 = (len2 == -1) ? 0 : len2 + 1; |
|
|
|
char *arg1n; |
|
|
|
const char *arg1n; |
|
|
|
char *arg2n; |
|
|
|
const char *arg2n; |
|
|
|
int result; |
|
|
|
int result; |
|
|
|
|
|
|
|
|
|
|
|
Assert(locale->provider == COLLPROVIDER_LIBC); |
|
|
|
Assert(locale->provider == COLLPROVIDER_LIBC); |
|
|
|
@ -1926,22 +1905,40 @@ pg_strncoll_libc(const char *arg1, size_t len1, const char *arg2, size_t len2, |
|
|
|
#ifdef WIN32 |
|
|
|
#ifdef WIN32 |
|
|
|
/* check for this case before doing the work for nul-termination */ |
|
|
|
/* check for this case before doing the work for nul-termination */ |
|
|
|
if (GetDatabaseEncoding() == PG_UTF8) |
|
|
|
if (GetDatabaseEncoding() == PG_UTF8) |
|
|
|
return pg_strncoll_libc_win32_utf8(arg1, len1, arg2, len2, locale); |
|
|
|
return strncoll_libc_win32_utf8(arg1, len1, arg2, len2, locale); |
|
|
|
#endif /* WIN32 */ |
|
|
|
#endif /* WIN32 */ |
|
|
|
|
|
|
|
|
|
|
|
if (bufsize1 + bufsize2 > TEXTBUFLEN) |
|
|
|
if (bufsize1 + bufsize2 > TEXTBUFLEN) |
|
|
|
buf = palloc(bufsize1 + bufsize2); |
|
|
|
buf = palloc(bufsize1 + bufsize2); |
|
|
|
|
|
|
|
|
|
|
|
arg1n = buf; |
|
|
|
/* nul-terminate arguments if necessary */ |
|
|
|
arg2n = buf + bufsize1; |
|
|
|
if (len1 == -1) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
arg1n = arg1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
char *buf1 = buf; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
memcpy(buf1, arg1, len1); |
|
|
|
|
|
|
|
buf1[len1] = '\0'; |
|
|
|
|
|
|
|
arg1n = buf1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* nul-terminate arguments */ |
|
|
|
if (len2 == -1) |
|
|
|
memcpy(arg1n, arg1, len1); |
|
|
|
{ |
|
|
|
arg1n[len1] = '\0'; |
|
|
|
arg2n = arg2; |
|
|
|
memcpy(arg2n, arg2, len2); |
|
|
|
} |
|
|
|
arg2n[len2] = '\0'; |
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
char *buf2 = buf + bufsize1; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
memcpy(buf2, arg2, len2); |
|
|
|
|
|
|
|
buf2[len2] = '\0'; |
|
|
|
|
|
|
|
arg2n = buf2; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
result = pg_strcoll_libc(arg1n, arg2n, locale); |
|
|
|
result = strcoll_l(arg1n, arg2n, locale->info.lt); |
|
|
|
|
|
|
|
|
|
|
|
if (buf != sbuf) |
|
|
|
if (buf != sbuf) |
|
|
|
pfree(buf); |
|
|
|
pfree(buf); |
|
|
|
@ -1952,7 +1949,7 @@ pg_strncoll_libc(const char *arg1, size_t len1, const char *arg2, size_t len2, |
|
|
|
#ifdef USE_ICU |
|
|
|
#ifdef USE_ICU |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* pg_strncoll_icu_no_utf8 |
|
|
|
* strncoll_icu_no_utf8 |
|
|
|
* |
|
|
|
* |
|
|
|
* Convert the arguments from the database encoding to UChar strings, then |
|
|
|
* Convert the arguments from the database encoding to UChar strings, then |
|
|
|
* call ucol_strcoll(). An argument length of -1 means that the string is |
|
|
|
* call ucol_strcoll(). An argument length of -1 means that the string is |
|
|
|
@ -1962,8 +1959,8 @@ pg_strncoll_libc(const char *arg1, size_t len1, const char *arg2, size_t len2, |
|
|
|
* caller should call that instead. |
|
|
|
* caller should call that instead. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
static int |
|
|
|
static int |
|
|
|
pg_strncoll_icu_no_utf8(const char *arg1, int32_t len1, |
|
|
|
strncoll_icu_no_utf8(const char *arg1, ssize_t len1, |
|
|
|
const char *arg2, int32_t len2, pg_locale_t locale) |
|
|
|
const char *arg2, ssize_t len2, pg_locale_t locale) |
|
|
|
{ |
|
|
|
{ |
|
|
|
char sbuf[TEXTBUFLEN]; |
|
|
|
char sbuf[TEXTBUFLEN]; |
|
|
|
char *buf = sbuf; |
|
|
|
char *buf = sbuf; |
|
|
|
@ -2008,16 +2005,14 @@ pg_strncoll_icu_no_utf8(const char *arg1, int32_t len1, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* pg_strncoll_icu |
|
|
|
* strncoll_icu |
|
|
|
* |
|
|
|
* |
|
|
|
* Call ucol_strcollUTF8() or ucol_strcoll() as appropriate for the given |
|
|
|
* Call ucol_strcollUTF8() or ucol_strcoll() as appropriate for the given |
|
|
|
* database encoding. An argument length of -1 means the string is |
|
|
|
* database encoding. An argument length of -1 means the string is |
|
|
|
* NUL-terminated. |
|
|
|
* NUL-terminated. |
|
|
|
* |
|
|
|
|
|
|
|
* Arguments must be encoded in the database encoding. |
|
|
|
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
static int |
|
|
|
static int |
|
|
|
pg_strncoll_icu(const char *arg1, int32_t len1, const char *arg2, int32_t len2, |
|
|
|
strncoll_icu(const char *arg1, ssize_t len1, const char *arg2, ssize_t len2, |
|
|
|
pg_locale_t locale) |
|
|
|
pg_locale_t locale) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int result; |
|
|
|
int result; |
|
|
|
@ -2041,7 +2036,7 @@ pg_strncoll_icu(const char *arg1, int32_t len1, const char *arg2, int32_t len2, |
|
|
|
else |
|
|
|
else |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
{ |
|
|
|
{ |
|
|
|
result = pg_strncoll_icu_no_utf8(arg1, len1, arg2, len2, locale); |
|
|
|
result = strncoll_icu_no_utf8(arg1, len1, arg2, len2, locale); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return result; |
|
|
|
return result; |
|
|
|
@ -2052,15 +2047,7 @@ pg_strncoll_icu(const char *arg1, int32_t len1, const char *arg2, int32_t len2, |
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* pg_strcoll |
|
|
|
* pg_strcoll |
|
|
|
* |
|
|
|
* |
|
|
|
* Call ucol_strcollUTF8(), ucol_strcoll(), strcoll_l() or wcscoll_l() as |
|
|
|
* Like pg_strncoll for NUL-terminated input strings. |
|
|
|
* appropriate for the given locale, platform, and database encoding. If the |
|
|
|
|
|
|
|
* locale is not specified, use the database collation. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* Arguments must be encoded in the database encoding and nul-terminated. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* The caller is responsible for breaking ties if the collation is |
|
|
|
|
|
|
|
* deterministic; this maintains consistency with pg_strxfrm(), which cannot |
|
|
|
|
|
|
|
* easily account for deterministic collations. |
|
|
|
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
int |
|
|
|
int |
|
|
|
pg_strcoll(const char *arg1, const char *arg2, pg_locale_t locale) |
|
|
|
pg_strcoll(const char *arg1, const char *arg2, pg_locale_t locale) |
|
|
|
@ -2068,10 +2055,10 @@ pg_strcoll(const char *arg1, const char *arg2, pg_locale_t locale) |
|
|
|
int result; |
|
|
|
int result; |
|
|
|
|
|
|
|
|
|
|
|
if (locale->provider == COLLPROVIDER_LIBC) |
|
|
|
if (locale->provider == COLLPROVIDER_LIBC) |
|
|
|
result = pg_strcoll_libc(arg1, arg2, locale); |
|
|
|
result = strncoll_libc(arg1, -1, arg2, -1, locale); |
|
|
|
#ifdef USE_ICU |
|
|
|
#ifdef USE_ICU |
|
|
|
else if (locale->provider == COLLPROVIDER_ICU) |
|
|
|
else if (locale->provider == COLLPROVIDER_ICU) |
|
|
|
result = pg_strncoll_icu(arg1, -1, arg2, -1, locale); |
|
|
|
result = strncoll_icu(arg1, -1, arg2, -1, locale); |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
else |
|
|
|
else |
|
|
|
/* shouldn't happen */ |
|
|
|
/* shouldn't happen */ |
|
|
|
@ -2087,27 +2074,24 @@ pg_strcoll(const char *arg1, const char *arg2, pg_locale_t locale) |
|
|
|
* appropriate for the given locale, platform, and database encoding. If the |
|
|
|
* appropriate for the given locale, platform, and database encoding. If the |
|
|
|
* locale is not specified, use the database collation. |
|
|
|
* locale is not specified, use the database collation. |
|
|
|
* |
|
|
|
* |
|
|
|
* Arguments must be encoded in the database encoding. |
|
|
|
* The input strings must be encoded in the database encoding. If an input |
|
|
|
* |
|
|
|
* string is NUL-terminated, its length may be specified as -1. |
|
|
|
* This function may need to nul-terminate the arguments for libc functions; |
|
|
|
|
|
|
|
* so if the caller already has nul-terminated strings, it should call |
|
|
|
|
|
|
|
* pg_strcoll() instead. |
|
|
|
|
|
|
|
* |
|
|
|
* |
|
|
|
* The caller is responsible for breaking ties if the collation is |
|
|
|
* The caller is responsible for breaking ties if the collation is |
|
|
|
* deterministic; this maintains consistency with pg_strnxfrm(), which cannot |
|
|
|
* deterministic; this maintains consistency with pg_strnxfrm(), which cannot |
|
|
|
* easily account for deterministic collations. |
|
|
|
* easily account for deterministic collations. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
int |
|
|
|
int |
|
|
|
pg_strncoll(const char *arg1, size_t len1, const char *arg2, size_t len2, |
|
|
|
pg_strncoll(const char *arg1, ssize_t len1, const char *arg2, ssize_t len2, |
|
|
|
pg_locale_t locale) |
|
|
|
pg_locale_t locale) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int result; |
|
|
|
int result; |
|
|
|
|
|
|
|
|
|
|
|
if (locale->provider == COLLPROVIDER_LIBC) |
|
|
|
if (locale->provider == COLLPROVIDER_LIBC) |
|
|
|
result = pg_strncoll_libc(arg1, len1, arg2, len2, locale); |
|
|
|
result = strncoll_libc(arg1, len1, arg2, len2, locale); |
|
|
|
#ifdef USE_ICU |
|
|
|
#ifdef USE_ICU |
|
|
|
else if (locale->provider == COLLPROVIDER_ICU) |
|
|
|
else if (locale->provider == COLLPROVIDER_ICU) |
|
|
|
result = pg_strncoll_icu(arg1, len1, arg2, len2, locale); |
|
|
|
result = strncoll_icu(arg1, len1, arg2, len2, locale); |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
else |
|
|
|
else |
|
|
|
/* shouldn't happen */ |
|
|
|
/* shouldn't happen */ |
|
|
|
@ -2116,17 +2100,15 @@ pg_strncoll(const char *arg1, size_t len1, const char *arg2, size_t len2, |
|
|
|
return result; |
|
|
|
return result; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
static size_t |
|
|
|
* strnxfrm_libc |
|
|
|
pg_strxfrm_libc(char *dest, const char *src, size_t destsize, |
|
|
|
* |
|
|
|
pg_locale_t locale) |
|
|
|
* NUL-terminate src, if necessary, and pass to strxfrm_l(). |
|
|
|
{ |
|
|
|
* |
|
|
|
Assert(locale->provider == COLLPROVIDER_LIBC); |
|
|
|
* A source length of -1 means that it's already NUL-terminated. |
|
|
|
return strxfrm_l(dest, src, destsize, locale->info.lt); |
|
|
|
*/ |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static size_t |
|
|
|
static size_t |
|
|
|
pg_strnxfrm_libc(char *dest, const char *src, size_t srclen, size_t destsize, |
|
|
|
strnxfrm_libc(char *dest, size_t destsize, const char *src, ssize_t srclen, |
|
|
|
pg_locale_t locale) |
|
|
|
pg_locale_t locale) |
|
|
|
{ |
|
|
|
{ |
|
|
|
char sbuf[TEXTBUFLEN]; |
|
|
|
char sbuf[TEXTBUFLEN]; |
|
|
|
@ -2136,14 +2118,17 @@ pg_strnxfrm_libc(char *dest, const char *src, size_t srclen, size_t destsize, |
|
|
|
|
|
|
|
|
|
|
|
Assert(locale->provider == COLLPROVIDER_LIBC); |
|
|
|
Assert(locale->provider == COLLPROVIDER_LIBC); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (srclen == -1) |
|
|
|
|
|
|
|
return strxfrm_l(dest, src, destsize, locale->info.lt); |
|
|
|
|
|
|
|
|
|
|
|
if (bufsize > TEXTBUFLEN) |
|
|
|
if (bufsize > TEXTBUFLEN) |
|
|
|
buf = palloc(bufsize); |
|
|
|
buf = palloc(bufsize); |
|
|
|
|
|
|
|
|
|
|
|
/* nul-terminate arguments */ |
|
|
|
/* nul-terminate argument */ |
|
|
|
memcpy(buf, src, srclen); |
|
|
|
memcpy(buf, src, srclen); |
|
|
|
buf[srclen] = '\0'; |
|
|
|
buf[srclen] = '\0'; |
|
|
|
|
|
|
|
|
|
|
|
result = pg_strxfrm_libc(dest, buf, destsize, locale); |
|
|
|
result = strxfrm_l(dest, buf, destsize, locale->info.lt); |
|
|
|
|
|
|
|
|
|
|
|
if (buf != sbuf) |
|
|
|
if (buf != sbuf) |
|
|
|
pfree(buf); |
|
|
|
pfree(buf); |
|
|
|
@ -2158,7 +2143,7 @@ pg_strnxfrm_libc(char *dest, const char *src, size_t srclen, size_t destsize, |
|
|
|
|
|
|
|
|
|
|
|
/* 'srclen' of -1 means the strings are NUL-terminated */ |
|
|
|
/* 'srclen' of -1 means the strings are NUL-terminated */ |
|
|
|
static size_t |
|
|
|
static size_t |
|
|
|
pg_strnxfrm_icu(char *dest, const char *src, int32_t srclen, int32_t destsize, |
|
|
|
strnxfrm_icu(char *dest, size_t destsize, const char *src, ssize_t srclen, |
|
|
|
pg_locale_t locale) |
|
|
|
pg_locale_t locale) |
|
|
|
{ |
|
|
|
{ |
|
|
|
char sbuf[TEXTBUFLEN]; |
|
|
|
char sbuf[TEXTBUFLEN]; |
|
|
|
@ -2205,8 +2190,9 @@ pg_strnxfrm_icu(char *dest, const char *src, int32_t srclen, int32_t destsize, |
|
|
|
|
|
|
|
|
|
|
|
/* 'srclen' of -1 means the strings are NUL-terminated */ |
|
|
|
/* 'srclen' of -1 means the strings are NUL-terminated */ |
|
|
|
static size_t |
|
|
|
static size_t |
|
|
|
pg_strnxfrm_prefix_icu_no_utf8(char *dest, const char *src, int32_t srclen, |
|
|
|
strnxfrm_prefix_icu_no_utf8(char *dest, size_t destsize, |
|
|
|
int32_t destsize, pg_locale_t locale) |
|
|
|
const char *src, ssize_t srclen, |
|
|
|
|
|
|
|
pg_locale_t locale) |
|
|
|
{ |
|
|
|
{ |
|
|
|
char sbuf[TEXTBUFLEN]; |
|
|
|
char sbuf[TEXTBUFLEN]; |
|
|
|
char *buf = sbuf; |
|
|
|
char *buf = sbuf; |
|
|
|
@ -2253,8 +2239,9 @@ pg_strnxfrm_prefix_icu_no_utf8(char *dest, const char *src, int32_t srclen, |
|
|
|
|
|
|
|
|
|
|
|
/* 'srclen' of -1 means the strings are NUL-terminated */ |
|
|
|
/* 'srclen' of -1 means the strings are NUL-terminated */ |
|
|
|
static size_t |
|
|
|
static size_t |
|
|
|
pg_strnxfrm_prefix_icu(char *dest, const char *src, int32_t srclen, |
|
|
|
strnxfrm_prefix_icu(char *dest, size_t destsize, |
|
|
|
int32_t destsize, pg_locale_t locale) |
|
|
|
const char *src, ssize_t srclen, |
|
|
|
|
|
|
|
pg_locale_t locale) |
|
|
|
{ |
|
|
|
{ |
|
|
|
size_t result; |
|
|
|
size_t result; |
|
|
|
|
|
|
|
|
|
|
|
@ -2281,7 +2268,7 @@ pg_strnxfrm_prefix_icu(char *dest, const char *src, int32_t srclen, |
|
|
|
u_errorName(status)))); |
|
|
|
u_errorName(status)))); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
result = pg_strnxfrm_prefix_icu_no_utf8(dest, src, srclen, destsize, |
|
|
|
result = strnxfrm_prefix_icu_no_utf8(dest, destsize, src, srclen, |
|
|
|
locale); |
|
|
|
locale); |
|
|
|
|
|
|
|
|
|
|
|
return result; |
|
|
|
return result; |
|
|
|
@ -2324,20 +2311,7 @@ pg_strxfrm_enabled(pg_locale_t locale) |
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* pg_strxfrm |
|
|
|
* pg_strxfrm |
|
|
|
* |
|
|
|
* |
|
|
|
* Transforms 'src' to a nul-terminated string stored in 'dest' such that |
|
|
|
* Like pg_strnxfrm for a NUL-terminated input string. |
|
|
|
* ordinary strcmp() on transformed strings is equivalent to pg_strcoll() on |
|
|
|
|
|
|
|
* untransformed strings. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* The provided 'src' must be nul-terminated. If 'destsize' is zero, 'dest' |
|
|
|
|
|
|
|
* may be NULL. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* Not all providers support pg_strxfrm() safely. The caller should check |
|
|
|
|
|
|
|
* pg_strxfrm_enabled() first, otherwise this function may return wrong |
|
|
|
|
|
|
|
* results or an error. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* Returns the number of bytes needed (or more) to store the transformed |
|
|
|
|
|
|
|
* string, excluding the terminating nul byte. If the value returned is |
|
|
|
|
|
|
|
* 'destsize' or greater, the resulting contents of 'dest' are undefined. |
|
|
|
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
size_t |
|
|
|
size_t |
|
|
|
pg_strxfrm(char *dest, const char *src, size_t destsize, pg_locale_t locale) |
|
|
|
pg_strxfrm(char *dest, const char *src, size_t destsize, pg_locale_t locale) |
|
|
|
@ -2345,10 +2319,10 @@ pg_strxfrm(char *dest, const char *src, size_t destsize, pg_locale_t locale) |
|
|
|
size_t result = 0; /* keep compiler quiet */ |
|
|
|
size_t result = 0; /* keep compiler quiet */ |
|
|
|
|
|
|
|
|
|
|
|
if (locale->provider == COLLPROVIDER_LIBC) |
|
|
|
if (locale->provider == COLLPROVIDER_LIBC) |
|
|
|
result = pg_strxfrm_libc(dest, src, destsize, locale); |
|
|
|
result = strnxfrm_libc(dest, destsize, src, -1, locale); |
|
|
|
#ifdef USE_ICU |
|
|
|
#ifdef USE_ICU |
|
|
|
else if (locale->provider == COLLPROVIDER_ICU) |
|
|
|
else if (locale->provider == COLLPROVIDER_ICU) |
|
|
|
result = pg_strnxfrm_icu(dest, src, -1, destsize, locale); |
|
|
|
result = strnxfrm_icu(dest, destsize, src, -1, locale); |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
else |
|
|
|
else |
|
|
|
/* shouldn't happen */ |
|
|
|
/* shouldn't happen */ |
|
|
|
@ -2364,8 +2338,9 @@ pg_strxfrm(char *dest, const char *src, size_t destsize, pg_locale_t locale) |
|
|
|
* ordinary strcmp() on transformed strings is equivalent to pg_strcoll() on |
|
|
|
* ordinary strcmp() on transformed strings is equivalent to pg_strcoll() on |
|
|
|
* untransformed strings. |
|
|
|
* untransformed strings. |
|
|
|
* |
|
|
|
* |
|
|
|
* 'src' does not need to be nul-terminated. If 'destsize' is zero, 'dest' may |
|
|
|
* The input string must be encoded in the database encoding. If the input |
|
|
|
* be NULL. |
|
|
|
* string is NUL-terminated, its length may be specified as -1. If 'destsize' |
|
|
|
|
|
|
|
* is zero, 'dest' may be NULL. |
|
|
|
* |
|
|
|
* |
|
|
|
* Not all providers support pg_strnxfrm() safely. The caller should check |
|
|
|
* Not all providers support pg_strnxfrm() safely. The caller should check |
|
|
|
* pg_strxfrm_enabled() first, otherwise this function may return wrong |
|
|
|
* pg_strxfrm_enabled() first, otherwise this function may return wrong |
|
|
|
@ -2374,22 +2349,18 @@ pg_strxfrm(char *dest, const char *src, size_t destsize, pg_locale_t locale) |
|
|
|
* Returns the number of bytes needed (or more) to store the transformed |
|
|
|
* Returns the number of bytes needed (or more) to store the transformed |
|
|
|
* string, excluding the terminating nul byte. If the value returned is |
|
|
|
* string, excluding the terminating nul byte. If the value returned is |
|
|
|
* 'destsize' or greater, the resulting contents of 'dest' are undefined. |
|
|
|
* 'destsize' or greater, the resulting contents of 'dest' are undefined. |
|
|
|
* |
|
|
|
|
|
|
|
* This function may need to nul-terminate the argument for libc functions; |
|
|
|
|
|
|
|
* so if the caller already has a nul-terminated string, it should call |
|
|
|
|
|
|
|
* pg_strxfrm() instead. |
|
|
|
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
size_t |
|
|
|
size_t |
|
|
|
pg_strnxfrm(char *dest, size_t destsize, const char *src, size_t srclen, |
|
|
|
pg_strnxfrm(char *dest, size_t destsize, const char *src, ssize_t srclen, |
|
|
|
pg_locale_t locale) |
|
|
|
pg_locale_t locale) |
|
|
|
{ |
|
|
|
{ |
|
|
|
size_t result = 0; /* keep compiler quiet */ |
|
|
|
size_t result = 0; /* keep compiler quiet */ |
|
|
|
|
|
|
|
|
|
|
|
if (locale->provider == COLLPROVIDER_LIBC) |
|
|
|
if (locale->provider == COLLPROVIDER_LIBC) |
|
|
|
result = pg_strnxfrm_libc(dest, src, srclen, destsize, locale); |
|
|
|
result = strnxfrm_libc(dest, destsize, src, srclen, locale); |
|
|
|
#ifdef USE_ICU |
|
|
|
#ifdef USE_ICU |
|
|
|
else if (locale->provider == COLLPROVIDER_ICU) |
|
|
|
else if (locale->provider == COLLPROVIDER_ICU) |
|
|
|
result = pg_strnxfrm_icu(dest, src, srclen, destsize, locale); |
|
|
|
result = strnxfrm_icu(dest, destsize, src, srclen, locale); |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
else |
|
|
|
else |
|
|
|
/* shouldn't happen */ |
|
|
|
/* shouldn't happen */ |
|
|
|
@ -2419,44 +2390,24 @@ pg_strxfrm_prefix_enabled(pg_locale_t locale) |
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* pg_strxfrm_prefix |
|
|
|
* pg_strxfrm_prefix |
|
|
|
* |
|
|
|
* |
|
|
|
* Transforms 'src' to a byte sequence stored in 'dest' such that ordinary |
|
|
|
* Like pg_strnxfrm_prefix for a NUL-terminated input string. |
|
|
|
* memcmp() on the byte sequence is equivalent to pg_strcoll() on |
|
|
|
|
|
|
|
* untransformed strings. The result is not nul-terminated. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* The provided 'src' must be nul-terminated. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* Not all providers support pg_strxfrm_prefix() safely. The caller should |
|
|
|
|
|
|
|
* check pg_strxfrm_prefix_enabled() first, otherwise this function may return |
|
|
|
|
|
|
|
* wrong results or an error. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* If destsize is not large enough to hold the resulting byte sequence, stores |
|
|
|
|
|
|
|
* only the first destsize bytes in 'dest'. Returns the number of bytes |
|
|
|
|
|
|
|
* actually copied to 'dest'. |
|
|
|
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
size_t |
|
|
|
size_t |
|
|
|
pg_strxfrm_prefix(char *dest, const char *src, size_t destsize, |
|
|
|
pg_strxfrm_prefix(char *dest, const char *src, size_t destsize, |
|
|
|
pg_locale_t locale) |
|
|
|
pg_locale_t locale) |
|
|
|
{ |
|
|
|
{ |
|
|
|
size_t result = 0; /* keep compiler quiet */ |
|
|
|
return pg_strnxfrm_prefix(dest, destsize, src, -1, locale); |
|
|
|
|
|
|
|
|
|
|
|
#ifdef USE_ICU |
|
|
|
|
|
|
|
if (locale->provider == COLLPROVIDER_ICU) |
|
|
|
|
|
|
|
result = pg_strnxfrm_prefix_icu(dest, src, -1, destsize, locale); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
PGLOCALE_SUPPORT_ERROR(locale->provider); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return result; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* pg_strnxfrm_prefix |
|
|
|
* pg_strnxfrm_prefix |
|
|
|
* |
|
|
|
* |
|
|
|
* Transforms 'src' to a byte sequence stored in 'dest' such that ordinary |
|
|
|
* Transforms 'src' to a byte sequence stored in 'dest' such that ordinary |
|
|
|
* memcmp() on the byte sequence is equivalent to pg_strcoll() on |
|
|
|
* memcmp() on the byte sequence is equivalent to pg_strncoll() on |
|
|
|
* untransformed strings. The result is not nul-terminated. |
|
|
|
* untransformed strings. The result is not nul-terminated. |
|
|
|
* |
|
|
|
* |
|
|
|
* The provided 'src' must be nul-terminated. |
|
|
|
* The input string must be encoded in the database encoding. If the input |
|
|
|
|
|
|
|
* string is NUL-terminated, its length may be specified as -1. |
|
|
|
* |
|
|
|
* |
|
|
|
* Not all providers support pg_strnxfrm_prefix() safely. The caller should |
|
|
|
* Not all providers support pg_strnxfrm_prefix() safely. The caller should |
|
|
|
* check pg_strxfrm_prefix_enabled() first, otherwise this function may return |
|
|
|
* check pg_strxfrm_prefix_enabled() first, otherwise this function may return |
|
|
|
@ -2465,20 +2416,16 @@ pg_strxfrm_prefix(char *dest, const char *src, size_t destsize, |
|
|
|
* If destsize is not large enough to hold the resulting byte sequence, stores |
|
|
|
* If destsize is not large enough to hold the resulting byte sequence, stores |
|
|
|
* only the first destsize bytes in 'dest'. Returns the number of bytes |
|
|
|
* only the first destsize bytes in 'dest'. Returns the number of bytes |
|
|
|
* actually copied to 'dest'. |
|
|
|
* actually copied to 'dest'. |
|
|
|
* |
|
|
|
|
|
|
|
* This function may need to nul-terminate the argument for libc functions; |
|
|
|
|
|
|
|
* so if the caller already has a nul-terminated string, it should call |
|
|
|
|
|
|
|
* pg_strxfrm_prefix() instead. |
|
|
|
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
size_t |
|
|
|
size_t |
|
|
|
pg_strnxfrm_prefix(char *dest, size_t destsize, const char *src, |
|
|
|
pg_strnxfrm_prefix(char *dest, size_t destsize, const char *src, |
|
|
|
size_t srclen, pg_locale_t locale) |
|
|
|
ssize_t srclen, pg_locale_t locale) |
|
|
|
{ |
|
|
|
{ |
|
|
|
size_t result = 0; /* keep compiler quiet */ |
|
|
|
size_t result = 0; /* keep compiler quiet */ |
|
|
|
|
|
|
|
|
|
|
|
#ifdef USE_ICU |
|
|
|
#ifdef USE_ICU |
|
|
|
if (locale->provider == COLLPROVIDER_ICU) |
|
|
|
if (locale->provider == COLLPROVIDER_ICU) |
|
|
|
result = pg_strnxfrm_prefix_icu(dest, src, -1, destsize, locale); |
|
|
|
result = strnxfrm_prefix_icu(dest, destsize, src, -1, locale); |
|
|
|
else |
|
|
|
else |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
PGLOCALE_SUPPORT_ERROR(locale->provider); |
|
|
|
PGLOCALE_SUPPORT_ERROR(locale->provider); |
|
|
|
@ -2661,6 +2608,8 @@ init_icu_converter(void) |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* Find length, in UChars, of given string if converted to UChar string. |
|
|
|
* Find length, in UChars, of given string if converted to UChar string. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* A length of -1 indicates that the input string is NUL-terminated. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
static size_t |
|
|
|
static size_t |
|
|
|
uchar_length(UConverter *converter, const char *str, int32_t len) |
|
|
|
uchar_length(UConverter *converter, const char *str, int32_t len) |
|
|
|
@ -2678,6 +2627,8 @@ uchar_length(UConverter *converter, const char *str, int32_t len) |
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* Convert the given source string into a UChar string, stored in dest, and |
|
|
|
* Convert the given source string into a UChar string, stored in dest, and |
|
|
|
* return the length (in UChars). |
|
|
|
* return the length (in UChars). |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* A srclen of -1 indicates that the input string is NUL-terminated. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
static int32_t |
|
|
|
static int32_t |
|
|
|
uchar_convert(UConverter *converter, UChar *dest, int32_t destlen, |
|
|
|
uchar_convert(UConverter *converter, UChar *dest, int32_t destlen, |
|
|
|
|