/* Attach new info to head of list */
oldcontext = MemoryContextSwitchTo(TopMemoryContext);
ConvProcList = lcons(convinfo, ConvProcList);
MemoryContextSwitchTo(oldcontext);
if (PrepareClientEncoding(pending_client_encoding) < 0 ||
SetClientEncoding(pending_client_encoding) < 0)
{ /* *Oops,therequestedconversionisnotavailable.Wecouldn'tfail *before,butwecannow.
*/
ereport(FATAL,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("conversion between %s and %s is not supported",
pg_enc2name_tbl[pending_client_encoding].name,
GetDatabaseEncodingName())));
}
/* *AlsolookuptheUTF8-to-serverconversionfunctionifneeded.Since *theserverencodingisfixedwithinanyonebackendprocess,wedon't *havetodothismorethanonce.
*/
current_server_encoding = GetDatabaseEncoding(); if (current_server_encoding != PG_UTF8 &&
current_server_encoding != PG_SQL_ASCII)
{
Oid utf8_to_server_proc;
AssertCouldGetRelation();
utf8_to_server_proc =
FindDefaultConversionProc(PG_UTF8,
current_server_encoding); /* If there's no such conversion, just leave the pointer as NULL */ if (OidIsValid(utf8_to_server_proc))
{
FmgrInfo *finfo;
finfo = (FmgrInfo *) MemoryContextAlloc(TopMemoryContext, sizeof(FmgrInfo));
fmgr_info_cxt(utf8_to_server_proc, finfo,
TopMemoryContext); /* Set Utf8ToServerConvProc only after data is fully valid */
Utf8ToServerConvProc = finfo;
}
}
}
/* *returnsthecurrentclientencoding
*/ int
pg_get_client_encoding(void)
{ return ClientEncoding->encoding;
}
/* *Convertsrcstringtoanotherencoding(generalcase). * *Seethenotesaboutstringconversionfunctionsatthetopofthisfile.
*/ unsignedchar *
pg_do_encoding_conversion(unsignedchar *src, int len, int src_encoding, int dest_encoding)
{ unsignedchar *result;
Oid proc;
if (len <= 0) return src; /* empty string is always valid */
if (src_encoding == dest_encoding) return src; /* no conversion required, assume valid */
if (dest_encoding == PG_SQL_ASCII) return src; /* any string is valid in SQL_ASCII */
if (src_encoding == PG_SQL_ASCII)
{ /* No conversion is possible, but we must validate the result */
(void) pg_verify_mbstr(dest_encoding, (constchar *) src, len, false); return src;
}
if (!IsTransactionState()) /* shouldn't happen */
elog(ERROR, "cannot perform encoding conversion outside a transaction");
proc = FindDefaultConversionProc(src_encoding, dest_encoding); if (!OidIsValid(proc))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("default conversion function for encoding \"%s\" to \"%s\" does not exist",
pg_encoding_to_char(src_encoding),
pg_encoding_to_char(dest_encoding))));
/* *Allocatespaceforconversionresult,beingwaryofintegeroverflow. * *len*MAX_CONVERSION_GROWTHistypicallyavastoverestimateofthe *requiredspace,soitmightexceedMaxAllocSizeeventhoughtheresult *wouldactuallyfit.Wedonotwanttohandbackaresultstringthat *exceedsMaxAllocSize,becausecallersmightnotcopegracefully---but *ifwejustallocatemorethanthat,anddon'tuseit,that'sfine.
*/ if ((Size) len >= (MaxAllocHugeSize / (Size) MAX_CONVERSION_GROWTH))
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("out of memory"),
errdetail("String of %d bytes is too long for encoding conversion.",
len)));
result = (unsignedchar *)
MemoryContextAllocHuge(CurrentMemoryContext,
(Size) len * MAX_CONVERSION_GROWTH + 1);
if (resultlen >= MaxAllocSize)
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("out of memory"),
errdetail("String of %d bytes is too long for encoding conversion.",
len)));
result = (unsignedchar *) repalloc(result, resultlen + 1);
}
return result;
}
/* *Convertsrcstringtoanotherencoding. * *ThisfunctionhasadifferentAPIthantheotherconversionfunctions. *Thecallershould'velookeduptheconversionfunctionusing *FindDefaultConversionProc().Unliketheotherfunctions,theconverted *resultisnotpalloc'd.Itiswrittentothecaller-suppliedbuffer *instead. * *src_encoding-encodingtoconvertfrom *dest_encoding-encodingtoconvertto *src,srclen-inputbufferanditslengthinbytes *dest,destlen-destinationbufferanditssizeinbytes * *Theoutputisnull-terminated. * *Ifdestlen<srclen*MAX_CONVERSION_INPUT_LENGTH+1,theconvertedoutput *wouldn'tnecessarilyfitintheoutputbuffer,andthefunctionwillnot *convertthewholeinput. * *TODO:Theconversionfunctioninterfaceisnotgreat.Firstly,it *wouldbenicetopassthroughthedestinationbuffersizetothe *conversionfunction,sothatifyoupassashorterdestinationbuffer,it *couldstillcontinuetofillupthewholebuffer.Currently,wehaveto *assumeworstcaseexpansionandstoptheconversionshort,evenifthere *isinfactspaceleftinthedestinationbuffer.Secondly,itwouldbe *nicetoreturnthenumberofbyteswrittentothecaller,toavoidacall *tostrlen().
*/ int
pg_do_encoding_conversion_buf(Oid proc, int src_encoding, int dest_encoding, unsignedchar *src, int srclen, unsignedchar *dest, int destlen, bool noError)
{
Datum result;
/* *Convertstringtoencodingencoding_name.Thesource *encodingistheDBencoding. *
* BYTEA convert_to(TEXT string, NAME encoding_name) */
Datum
pg_convert_to(PG_FUNCTION_ARGS)
{
Datum string = PG_GETARG_DATUM(0);
Datum dest_encoding_name = PG_GETARG_DATUM(1);
Datum src_encoding_name = DirectFunctionCall1(namein,
CStringGetDatum(DatabaseEncoding->name));
Datum result;
/* *Convertstringfromencodingencoding_name.Thedestination *encodingistheDBencoding. *
* TEXT convert_from(BYTEA string, NAME encoding_name) */
Datum
pg_convert_from(PG_FUNCTION_ARGS)
{
Datum string = PG_GETARG_DATUM(0);
Datum src_encoding_name = PG_GETARG_DATUM(1);
Datum dest_encoding_name = DirectFunctionCall1(namein,
CStringGetDatum(DatabaseEncoding->name));
Datum result;
result = DirectFunctionCall3(pg_convert, string,
src_encoding_name, dest_encoding_name);
/* *Convertstringbetweentwoarbitraryencodings. * *BYTEAconvert(BYTEAstring,NAMEsrc_encoding_name,NAMEdest_encoding_name)
*/
Datum
pg_convert(PG_FUNCTION_ARGS)
{
bytea *string = PG_GETARG_BYTEA_PP(0); char *src_encoding_name = NameStr(*PG_GETARG_NAME(1)); int src_encoding = pg_char_to_encoding(src_encoding_name); char *dest_encoding_name = NameStr(*PG_GETARG_NAME(2)); int dest_encoding = pg_char_to_encoding(dest_encoding_name); constchar *src_str; char *dest_str;
bytea *retval; int len;
if (src_encoding < 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("invalid source encoding name \"%s\"",
src_encoding_name))); if (dest_encoding < 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("invalid destination encoding name \"%s\"",
dest_encoding_name)));
/* make sure that source string is valid */
len = VARSIZE_ANY_EXHDR(string);
src_str = VARDATA_ANY(string);
(void) pg_verify_mbstr(src_encoding, src_str, len, false);
if (DatabaseEncoding->encoding == PG_SQL_ASCII)
{ /* *Noconversionispossible,butwemuststillvalidatethedata, *becausetheclient-sidecodemighthavedonestringescapingusing *theselectedclient_encoding.IftheclientencodingisASCII-safe *thenwejustdoastraightvalidationunderthatencoding.Foran *ASCII-unsafeencodingwehaveaproblem:wedarenotpasssuchdata *totheparserbutwehavenowaytoconvertit.Wecompromiseby *rejectingthedataifitcontainsanynon-ASCIIcharacters.
*/ if (PG_VALID_BE_ENCODING(encoding))
(void) pg_verify_mbstr(encoding, s, len, false); else
{ int i;
for (i = 0; i < len; i++)
{ if (s[i] == '\0' || IS_HIGHBIT_SET(s[i]))
ereport(ERROR,
(errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
errmsg("invalid byte value for encoding \"%s\": 0x%02x",
pg_enc2name_tbl[PG_SQL_ASCII].name,
(unsignedchar) s[i])));
}
} return unconstify(char *, s);
}
/* Fast path if we can use cached conversion function */ if (encoding == ClientEncoding->encoding) return perform_default_encoding_conversion(s, len, true);
/* General case ... will not work outside transactions */ return (char *) pg_do_encoding_conversion((unsignedchar *) unconstify(char *, s),
len,
encoding,
DatabaseEncoding->encoding);
}
/* *Convertserverencodingtoanyencoding. * *Seethenotesaboutstringconversionfunctionsatthetopofthisfile.
*/ char *
pg_server_to_any(constchar *s, int len, int encoding)
{ if (len <= 0) return unconstify(char *, s); /* empty string is always valid */
if (encoding == DatabaseEncoding->encoding ||
encoding == PG_SQL_ASCII) return unconstify(char *, s); /* assume data is valid */
if (DatabaseEncoding->encoding == PG_SQL_ASCII)
{ /* No conversion is possible, but we must validate the result */
(void) pg_verify_mbstr(encoding, s, len, false); return unconstify(char *, s);
}
/* Fast path if we can use cached conversion function */ if (encoding == ClientEncoding->encoding) return perform_default_encoding_conversion(s, len, false);
/* General case ... will not work outside transactions */ return (char *) pg_do_encoding_conversion((unsignedchar *) unconstify(char *, s),
len,
DatabaseEncoding->encoding,
encoding);
}
if (flinfo == NULL) return unconstify(char *, src);
/* *Allocatespaceforconversionresult,beingwaryofintegeroverflow. *Seecommentsinpg_do_encoding_conversion.
*/ if ((Size) len >= (MaxAllocHugeSize / (Size) MAX_CONVERSION_GROWTH))
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("out of memory"),
errdetail("String of %d bytes is too long for encoding conversion.",
len)));
result = (char *)
MemoryContextAllocHuge(CurrentMemoryContext,
(Size) len * MAX_CONVERSION_GROWTH + 1);
if (resultlen >= MaxAllocSize)
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("out of memory"),
errdetail("String of %d bytes is too long for encoding conversion.",
len)));
result = (char *) repalloc(result, resultlen + 1);
}
/* Otherwise, if it's in ASCII range, conversion is trivial */ if (c <= 0x7F)
{
s[0] = (unsignedchar) c;
s[1] = '\0'; return;
}
/* If the server encoding is UTF-8, we just need to reformat the code */
server_encoding = GetDatabaseEncoding(); if (server_encoding == PG_UTF8)
{
unicode_to_utf8(c, s);
s[pg_utf_mblen(s)] = '\0'; return;
}
/* For all other cases, we must have a conversion function available */ if (Utf8ToServerConvProc == NULL)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("conversion between %s and %s is not supported",
pg_enc2name_tbl[PG_UTF8].name,
GetDatabaseEncodingName())));
/* Convert, or throw error if we can't */
FunctionCall6(Utf8ToServerConvProc,
Int32GetDatum(PG_UTF8),
Int32GetDatum(server_encoding),
CStringGetDatum((char *) c_as_utf8),
CStringGetDatum((char *) s),
Int32GetDatum(c_as_utf8_len),
BoolGetDatum(false));
}
/* *ConvertasingleUnicodecodepointintoastringintheserverencoding. * *Sameaspg_unicode_to_server(),exceptthatwedon'tthrowerrors, *butsimplyreturnfalseonconversionfailure.
*/ bool
pg_unicode_to_server_noerror(pg_wchar c, unsignedchar *s)
{ unsignedchar c_as_utf8[MAX_MULTIBYTE_CHAR_LEN + 1]; int c_as_utf8_len; int converted_len; int server_encoding;
/* Fail if invalid Unicode code point */ if (!is_valid_unicode_codepoint(c)) returnfalse;
/* Otherwise, if it's in ASCII range, conversion is trivial */ if (c <= 0x7F)
{
s[0] = (unsignedchar) c;
s[1] = '\0'; returntrue;
}
/* If the server encoding is UTF-8, we just need to reformat the code */
server_encoding = GetDatabaseEncoding(); if (server_encoding == PG_UTF8)
{
unicode_to_utf8(c, s);
s[pg_utf_mblen(s)] = '\0'; returntrue;
}
/* For all other cases, we must have a conversion function available */ if (Utf8ToServerConvProc == NULL) returnfalse;
/* Convert, but without throwing error if we can't */
converted_len = DatumGetInt32(FunctionCall6(Utf8ToServerConvProc,
Int32GetDatum(PG_UTF8),
Int32GetDatum(server_encoding),
CStringGetDatum((char *) c_as_utf8),
CStringGetDatum((char *) s),
Int32GetDatum(c_as_utf8_len),
BoolGetDatum(true)));
/* Conversion was successful iff it consumed the whole input */ return (converted_len == c_as_utf8_len);
}
/* convert a multibyte string to a wchar */ int
pg_mb2wchar(constchar *from, pg_wchar *to)
{ return pg_wchar_table[DatabaseEncoding->encoding].mb2wchar_with_len((constunsignedchar *) from, to, strlen(from));
}
/* convert a multibyte string to a wchar with a limited length */ int
pg_mb2wchar_with_len(constchar *from, pg_wchar *to, int len)
{ return pg_wchar_table[DatabaseEncoding->encoding].mb2wchar_with_len((constunsignedchar *) from, to, len);
}
/* same, with any encoding */ int
pg_encoding_mb2wchar_with_len(int encoding, constchar *from, pg_wchar *to, int len)
{ return pg_wchar_table[encoding].mb2wchar_with_len((constunsignedchar *) from, to, len);
}
/* convert a wchar string to a multibyte */ int
pg_wchar2mb(const pg_wchar *from, char *to)
{ return pg_wchar_table[DatabaseEncoding->encoding].wchar2mb_with_len(from, (unsignedchar *) to, pg_wchar_strlen(from));
}
/* convert a wchar string to a multibyte with a limited length */ int
pg_wchar2mb_with_len(const pg_wchar *from, char *to, int len)
{ return pg_wchar_table[DatabaseEncoding->encoding].wchar2mb_with_len(from, (unsignedchar *) to, len);
}
/* same, with any encoding */ int
pg_encoding_wchar2mb_with_len(int encoding, const pg_wchar *from, char *to, int len)
{ return pg_wchar_table[encoding].wchar2mb_with_len(from, (unsignedchar *) to, len);
}
/* returns the display length of a multibyte character */ int
pg_dsplen(constchar *mbstr)
{ return pg_wchar_table[DatabaseEncoding->encoding].dsplen((constunsignedchar *) mbstr);
}
/* returns the length (counted in wchars) of a multibyte string */ int
pg_mbstrlen(constchar *mbstr)
{ int len = 0;
/* optimization for single byte encoding */ if (pg_database_encoding_max_length() == 1) return strlen(mbstr);
/* returns the length (counted in wchars) of a multibyte string *(stopsatthefirstof"limit"oraNUL)
*/ int
pg_mbstrlen_with_len(constchar *mbstr, int limit)
{ int len = 0;
/* optimization for single byte encoding */ if (pg_database_encoding_max_length() == 1) return limit;
while (limit > 0 && *mbstr)
{ int l = pg_mblen_with_len(mbstr, limit);
limit -= l;
mbstr += l;
len++;
} return len;
}
/* *returnsthebytelengthofamultibytestring *(notnecessarilyNULLterminated) *thatisnolongerthanlimit. *thisfunctiondoesnotbreakmultibytecharacterboundary.
*/ int
pg_mbcliplen(constchar *mbstr, int len, int limit)
{ return pg_encoding_mbcliplen(DatabaseEncoding->encoding, mbstr,
len, limit);
}
/* *pg_mbcliplenwithspecifiedencoding;stringmustbevalidinencoding
*/ int
pg_encoding_mbcliplen(int encoding, constchar *mbstr, int len, int limit)
{
mblen_converter mblen_fn; int clen = 0; int l;
/* optimization for single byte encoding */ if (pg_encoding_max_length(encoding) == 1) return cliplen(mbstr, len, limit);
mblen_fn = pg_wchar_table[encoding].mblen;
while (len > 0 && *mbstr)
{
l = (*mblen_fn) ((constunsignedchar *) mbstr); if ((clen + l) > limit) break;
clen += l; if (clen == limit) break;
len -= l;
mbstr += l;
} return clen;
}
/* *Similartopg_mbcliplenexceptthelimitparameterspecifiesthe *characterlength,notthebytelength.
*/ int
pg_mbcharcliplen(constchar *mbstr, int len, int limit)
{ int clen = 0; int nch = 0; int l;
/* optimization for single byte encoding */ if (pg_database_encoding_max_length() == 1) return cliplen(mbstr, len, limit);
while (len > 0 && *mbstr)
{
l = pg_mblen_with_len(mbstr, len);
nch++; if (nch > limit) break;
clen += l;
len -= l;
mbstr += l;
} return clen;
}
/* mbcliplen for any single-byte encoding */ staticint
cliplen(constchar *str, int len, int limit)
{ int l = 0;
len = Min(len, limit); while (l < len && str[l])
l++; return l;
}
#ifdef WIN32 if (!raw_pg_bind_textdomain_codeset(domainname, new_msgenc)) /* On failure, the old message encoding remains valid. */ return GetMessageEncoding(); #endif
switch (length)
{ default: /* reject lengths 5 and 6 for now */ returnfalse; case4:
a = charptr[3]; if (a < 0xBF)
{
charptr[3]++; break;
} /* FALL THRU */ case3:
a = charptr[2]; if (a < 0xBF)
{
charptr[2]++; break;
} /* FALL THRU */ case2:
a = charptr[1]; switch (*charptr)
{ case0xED:
limit = 0x9F; break; case0xF4:
limit = 0x8F; break; default:
limit = 0xBF; break;
} if (a < limit)
{
charptr[1]++; break;
} /* FALL THRU */ case1:
a = *charptr; if (a == 0x7F || a == 0xDF || a == 0xEF || a == 0xF4) returnfalse;
charptr[0]++; break;
}
for (j = 0; j < jlimit; j++)
{
p += sprintf(p, "0x%02x", (unsignedchar) mbstr[j]); if (j < jlimit - 1)
p += sprintf(p, " ");
}
ereport(ERROR,
(errcode(ERRCODE_UNTRANSLATABLE_CHARACTER),
errmsg("character with byte sequence %s in encoding \"%s\" has no equivalent in encoding \"%s\"",
buf,
pg_enc2name_tbl[src_encoding].name,
pg_enc2name_tbl[dest_encoding].name)));
}
#ifdef WIN32 /* *ConvertfromMessageEncodingtoapalloc'ed,null-terminatedutf16 *string.Thecharacterlengthisalsopassedtoutf16lenifnot *null.ReturnsNULLifffailed.BeforeMessageEncodinginitialization,"str" *shouldbeASCII-only;thiswillfunctionasthoughMessageEncodingisUTF8.
*/
WCHAR *
pgwin32_message_to_UTF16(constchar *str, int len, int *utf16len)
{ int msgenc = GetMessageEncoding();
WCHAR *utf16; int dstlen;
UINT codepage;
if (msgenc == PG_SQL_ASCII) /* No conversion is possible, and SQL_ASCII is never utf16. */ return NULL;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.