📄 mbutils.c
字号:
/* make sure that source string is null terminated */ len = VARSIZE(string) - VARHDRSZ; str = palloc(len + 1); memcpy(str, VARDATA(string), len); *(str + len) = '\0'; result = pg_do_encoding_conversion(str, len, src_encoding, dest_encoding); if (result == NULL) elog(ERROR, "encoding conversion failed"); /* * build text data type structure. we cannot use textin() here, since * textin assumes that input string encoding is same as database encoding. */ len = strlen((char *) result) + VARHDRSZ; retval = palloc(len); VARATT_SIZEP(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_TEXT_P(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; result = palloc(len * 4 + 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);}/* 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"); DatabaseEncoding = &pg_enc2name_tbl[encoding]; Assert(DatabaseEncoding->encoding == encoding);}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 + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -