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 + -
显示快捷键?