mbutils.c

来自「postgresql8.3.4源码,开源数据库」· C语言 代码 · 共 768 行 · 第 1/2 页

C
768
字号
	/*	 * build bytea data type structure.	 */	len = strlen((char *) result) + VARHDRSZ;	retval = palloc(len);	SET_VARSIZE(retval, len);	memcpy(VARDATA(retval), result, len - VARHDRSZ);	if (result != str)		pfree(result);	pfree(str);	/* free memory if allocated by the toaster */	PG_FREE_IF_COPY(string, 0);	PG_RETURN_BYTEA_P(retval);}/* * get the length of the string considered as text in the specified * encoding. Raises an error if the data is not valid in that * encoding. * * INT4 length (BYTEA string, NAME src_encoding_name) */Datumlength_in_encoding(PG_FUNCTION_ARGS){	bytea	   *string = PG_GETARG_BYTEA_P(0);	char	   *src_encoding_name = NameStr(*PG_GETARG_NAME(1));	int			src_encoding = pg_char_to_encoding(src_encoding_name);	int			len = VARSIZE(string) - VARHDRSZ;	int			retval;	if (src_encoding < 0)		ereport(ERROR,				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),				 errmsg("invalid encoding name \"%s\"",						src_encoding_name)));	retval = pg_verify_mbstr_len(src_encoding, VARDATA(string), len, false);	PG_RETURN_INT32(retval);}/* * convert client encoding to server encoding. */char *pg_client_to_server(const char *s, int len){	Assert(DatabaseEncoding);	Assert(ClientEncoding);	if (len <= 0)		return (char *) s;	if (ClientEncoding->encoding == DatabaseEncoding->encoding ||		ClientEncoding->encoding == PG_SQL_ASCII)	{		/*		 * No conversion is needed, but we must still validate the data.		 */		(void) pg_verify_mbstr(DatabaseEncoding->encoding, s, len, false);		return (char *) s;	}	if (DatabaseEncoding->encoding == PG_SQL_ASCII)	{		/*		 * No conversion is possible, but we must still validate the data,		 * because the client-side code might have done string escaping using		 * the selected client_encoding.  If the client encoding is ASCII-safe		 * then we just do a straight validation under that encoding.  For an		 * ASCII-unsafe encoding we have a problem: we dare not pass such data		 * to the parser but we have no way to convert it.	We compromise by		 * rejecting the data if it contains any non-ASCII characters.		 */		if (PG_VALID_BE_ENCODING(ClientEncoding->encoding))			(void) pg_verify_mbstr(ClientEncoding->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,							(unsigned char) s[i])));			}		}		return (char *) s;	}	return perform_default_encoding_conversion(s, len, true);}/* * convert server encoding to client encoding. */char *pg_server_to_client(const char *s, int len){	Assert(DatabaseEncoding);	Assert(ClientEncoding);	if (len <= 0)		return (char *) s;	if (ClientEncoding->encoding == DatabaseEncoding->encoding ||		ClientEncoding->encoding == PG_SQL_ASCII ||		DatabaseEncoding->encoding == PG_SQL_ASCII)		return (char *) s;		/* assume data is valid */	return perform_default_encoding_conversion(s, len, false);}/* *	Perform default encoding conversion using cached FmgrInfo. Since *	this function does not access database at all, it is safe to call *	outside transactions. Explicit setting client encoding required *	before calling this function. Otherwise no conversion is *	performed.*/static char *perform_default_encoding_conversion(const char *src, int len, bool is_client_to_server){	char	   *result;	int			src_encoding,				dest_encoding;	FmgrInfo   *flinfo;	if (is_client_to_server)	{		src_encoding = ClientEncoding->encoding;		dest_encoding = DatabaseEncoding->encoding;		flinfo = ToServerConvProc;	}	else	{		src_encoding = DatabaseEncoding->encoding;		dest_encoding = ClientEncoding->encoding;		flinfo = ToClientConvProc;	}	if (flinfo == NULL)		return (char *) src;	/*	 * Allocate space for conversion result, being wary of integer overflow	 */	if ((Size) len >= (MaxAllocSize / (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 = palloc(len * MAX_CONVERSION_GROWTH + 1);	FunctionCall5(flinfo,				  Int32GetDatum(src_encoding),				  Int32GetDatum(dest_encoding),				  CStringGetDatum(src),				  CStringGetDatum(result),				  Int32GetDatum(len));	return result;}/* convert a multibyte string to a wchar */intpg_mb2wchar(const char *from, pg_wchar *to){	return (*pg_wchar_table[DatabaseEncoding->encoding].mb2wchar_with_len) ((const unsigned char *) from, to, strlen(from));}/* convert a multibyte string to a wchar with a limited length */intpg_mb2wchar_with_len(const char *from, pg_wchar *to, int len){	return (*pg_wchar_table[DatabaseEncoding->encoding].mb2wchar_with_len) ((const unsigned char *) from, to, len);}/* same, with any encoding */intpg_encoding_mb2wchar_with_len(int encoding,							  const char *from, pg_wchar *to, int len){	return (*pg_wchar_table[encoding].mb2wchar_with_len) ((const unsigned char *) from, to, len);}/* returns the byte length of a multibyte word */intpg_mblen(const char *mbstr){	return ((*pg_wchar_table[DatabaseEncoding->encoding].mblen) ((const unsigned char *) mbstr));}/* returns the display length of a multibyte word */intpg_dsplen(const char *mbstr){	return ((*pg_wchar_table[DatabaseEncoding->encoding].dsplen) ((const unsigned char *) mbstr));}/* returns the length (counted in wchars) of a multibyte string */intpg_mbstrlen(const char *mbstr){	int			len = 0;	/* optimization for single byte encoding */	if (pg_database_encoding_max_length() == 1)		return strlen(mbstr);	while (*mbstr)	{		mbstr += pg_mblen(mbstr);		len++;	}	return len;}/* returns the length (counted in wchars) of a multibyte string * (not necessarily NULL terminated) */intpg_mbstrlen_with_len(const char *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(mbstr);		limit -= l;		mbstr += l;		len++;	}	return len;}/* * returns the byte length of a multibyte string * (not necessarily  NULL terminated) * that is no longer than limit. * this function does not break multibyte word boundary. */intpg_mbcliplen(const char *mbstr, int len, int limit){	int			clen = 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(mbstr);		if ((clen + l) > limit)			break;		clen += l;		if (clen == limit)			break;		len -= l;		mbstr += l;	}	return clen;}/* * Similar to pg_mbcliplen except the limit parameter specifies the * character length, not the byte length.  */intpg_mbcharcliplen(const char *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(mbstr);		nch++;		if (nch > limit)			break;		clen += l;		len -= l;		mbstr += l;	}	return clen;}voidSetDatabaseEncoding(int encoding){	if (!PG_VALID_BE_ENCODING(encoding))		elog(ERROR, "invalid database encoding: %d", encoding);	DatabaseEncoding = &pg_enc2name_tbl[encoding];	Assert(DatabaseEncoding->encoding == encoding);	/*	 * On Windows, we allow UTF-8 database encoding to be used with any	 * locale setting, because UTF-8 requires special handling anyway.	 * But this means that gettext() might be misled about what output	 * encoding it should use, so we have to tell it explicitly.	 *	 * In future we might want to call bind_textdomain_codeset	 * unconditionally, but that requires knowing how to spell the codeset	 * name properly for all encodings on all platforms, which might be	 * problematic.	 *	 * This is presently unnecessary, but harmless, on non-Windows platforms.	 */#ifdef ENABLE_NLS	if (encoding == PG_UTF8)		if (bind_textdomain_codeset("postgres", "UTF-8") == NULL)			elog(LOG, "bind_textdomain_codeset failed");#endif}voidSetDefaultClientEncoding(void){	ClientEncoding = &pg_enc2name_tbl[GetDatabaseEncoding()];}intGetDatabaseEncoding(void){	Assert(DatabaseEncoding);	return DatabaseEncoding->encoding;}const char *GetDatabaseEncodingName(void){	Assert(DatabaseEncoding);	return DatabaseEncoding->name;}Datumgetdatabaseencoding(PG_FUNCTION_ARGS){	Assert(DatabaseEncoding);	return DirectFunctionCall1(namein, CStringGetDatum(DatabaseEncoding->name));}Datumpg_client_encoding(PG_FUNCTION_ARGS){	Assert(ClientEncoding);	return DirectFunctionCall1(namein, CStringGetDatum(ClientEncoding->name));}static intcliplen(const char *str, int len, int limit){	int			l = 0;	const char *s;	for (s = str; *s; s++, l++)	{		if (l >= len || l >= limit)			return l;	}	return (s - str);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?