39 #include <freetds/tds.h>
40 #include <freetds/iconv.h>
41 #include <freetds/bool.h>
42 #include <freetds/bytes.h>
47 #define CHARSIZE(charset) ( ((charset)->min_bytes_per_char == (charset)->max_bytes_per_char )? \
48 (charset)->min_bytes_per_char : 0 )
65 #define TDS_ICONV_ENCODING_TABLES
84 { 6,
"Ao\xC3\x93\xC3\xA5" },
85 { 8,
"A\x00o\x000\xD3\x00\xE5\x00" },
86 { 8,
"\x00" "A\x00o\x000\xD3\x00\xE5" },
113 for (
i = 0; iconv_aliases[
i].alias; ++
i) {
116 if (iconv_aliases[
i].canonic !=
POS_ISO1)
118 for (j = 0; iconv_aliases[j].alias; ++j) {
119 if (iconv_aliases[j].canonic !=
POS_UTF8)
154 for (
i = 0; iconv_aliases[
i].alias; ++
i) {
155 if (
strncmp(canonic_charsets[iconv_aliases[
i].canonic].name,
"UCS-2", 5) != 0)
165 int byte_sequence = 0;
174 if (
tds_sys_iconv(cd, &pib, &il, &pob, &ol) != (
size_t) - 1) {
202 for (
i = 0;
i < 4; ++
i)
207 for (
i = 0;
i < 4 * 4; ++
i) {
208 const int from =
i / 4;
209 const int to =
i % 4;
258 name = canonic_charsets[charset].name;
267 for (
i = 0; iconv_aliases[
i].alias; ++
i) {
268 if (iconv_aliases[
i].canonic != charset)
271 name = iconv_aliases[
i].alias;
299 conv->to.charset.min_bytes_per_char = 1;
300 conv->to.charset.max_bytes_per_char = 1;
331 conn->char_convs[
i] = &char_conv[
i];
366 static const char UCS_2LE[] =
"UCS-2LE";
386 "try using GNU libiconv library\n");
419 client->max_bytes_per_char = 3;
428 if (canonic_env_charset >= 0) {
460 if (client_canonical < 0) {
465 if (server_canonical < 0) {
470 *
client = canonic_charsets[client_canonical];
471 *server = canonic_charsets[server_canonical];
474 if (client_canonical == server_canonical) {
475 char_conv->to.cd = (
iconv_t) -1;
481 char_conv->
flags = 0;
499 if (char_conv->to.cd == (
iconv_t) -1) {
521 if (*cd != invalid) {
539 for (
i = 0;
i <
conn->char_conv_count; ++
i)
543 #define CHUNK_ALLOC 4
550 if (!
conn->char_convs)
558 conn->char_conv_count = 0;
601 const char **
inbuf,
size_t * inbytesleft,
char **
outbuf,
size_t * outbytesleft)
609 char quest_mark[] =
"?";
613 size_t one_character;
614 bool eilseq_raised =
false;
626 if (*inbytesleft == 0)
646 size_t len = *inbytesleft < *outbytesleft ? *inbytesleft : *outbytesleft;
649 conv_errno = *inbytesleft > *outbytesleft ? E2BIG : 0;
651 *outbytesleft -=
len;
655 return conv_errno ? (size_t) -1 : 0;
666 if (irreversible != (
size_t) - 1) {
667 if (irreversible > 0) {
668 eilseq_raised =
true;
686 eilseq_raised =
true;
705 if (error_cd == invalid) {
707 if (error_cd == invalid) {
713 pquest_mark = quest_mark;
717 if (irreversible == (
size_t) - 1)
724 if (eilseq_raised && !suppress->
eilseq) {
727 if (irreversible == (
size_t) - 1) {
739 switch (conv_errno) {
757 if (error_cd != invalid) {
776 if (canonic_client ==
conn->char_convs[
i]->from.charset.canonic
777 && canonic_server ==
conn->char_convs[
i]->to.charset.canonic)
778 return conn->char_convs[
i];
793 conn->char_convs = p;
796 conn->char_convs[
i +
conn->char_conv_count] = &infos[
i];
807 --
conn->char_conv_count;
817 if (canonic_client_charset_num < 0) {
821 if (canonic_server_charset_num < 0) {
838 tdsdump_log(
TDS_DBG_FUNC,
"setting server single-byte charset to \"%s\"\n", canonic_charsets[canonic_charset_num].name);
840 if (canonic_charset_num == char_conv->to.charset.canonic)
879 unsigned charsize =
CHARSIZE(charset);
906 }
while ((c <<= 1) & 0x80);
925 if (il > *input_size)
928 memcpy(ib +
l, *
input, il);
950 il =
sizeof(ib) - ol;
966 if (charsize > *input_size)
969 *input_size -= charsize;
1000 return canonic_charsets[res].name;
1002 return charset_name;
1009 const int sql_collate = collate[4];
1026 switch (sql_collate) {
static const struct charset_alias * charset_lookup(register const char *str, register size_t len)
static CS_CONNECTION * conn
#define TDS_GET_UA2LE(ptr)
#define TDS_ENCODING_MEMCPY
@ initial_char_conv_count
#define TDS_VECTOR_SIZE(x)
#define tds_new0(type, n)
#define tds_mutex_lock(x)
#define tds_mutex_unlock(x)
int tds_iconv_alloc(TDSCONNECTION *conn)
Allocate iconv stuff.
int tds_canonical_charset(const char *charset_name)
Determine canonical iconv character set.
TDSICONV * tds_iconv_get_info(TDSCONNECTION *conn, int canonic_client, int canonic_server)
Get a iconv info structure, allocate and initialize if needed.
#define TDS_MUTEX_INITIALIZER
static const char * tds_set_iconv_name(int charset)
Get iconv name given canonic.
static const char * iconv_names[TDS_VECTOR_SIZE(canonic_charsets)]
static bool iconv_initialized
static void tds_iconv_reset(TDSICONV *conv)
static bool tds_iconv_init(void)
Initialize charset searching for UTF-8, UCS-2 and ISO8859-1.
static const char * ucs2name
static tds_mutex iconv_mtx
static const struct @1038 test_strings[4]
#define CHARSIZE(charset)
static size_t skip_one_input_sequence(iconv_t cd, const TDS_ENCODING *charset, const char **input, size_t *input_size)
Move the input sequence pointer to the next valid position.
static int tds_iconv_info_init(TDSICONV *char_conv, int client_canonic, int server_canonic)
Open iconv descriptors to convert between character sets (both directions).
static void tds_srv_charset_changed_num(TDSCONNECTION *conn, int canonic_charset_num)
static void _iconv_close(iconv_t *cd)
static void tds_iconv_info_close(TDSICONV *char_conv)
static void tds_iconv_err(TDSSOCKET *tds, int err)
TDSRET tds_iconv_open(TDSCONNECTION *conn, const char *charset, int use_utf16)
void tds_iconv_close(TDSCONNECTION *conn)
void tds_srv_charset_changed(TDSCONNECTION *conn, const char *charset)
const char * tds_canonical_charset_name(const char *charset_name)
Determine canonical iconv character set name.
size_t tds_sys_iconv(iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft)
size_t tds_iconv(TDSSOCKET *tds, TDSICONV *conv, TDS_ICONV_DIRECTION io, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft)
Wrapper around iconv(3).
static int collate2charset(TDSCONNECTION *conn, TDS_UCHAR collate[5])
iconv_t tds_sys_iconv_open(const char *tocode, const char *fromcode)
Inputs are FreeTDS canonical names, no other.
TDSICONV * tds_iconv_get(TDSCONNECTION *conn, const char *client_charset, const char *server_charset)
void tds7_srv_charset_changed(TDSCONNECTION *conn, int sql_collate, int lcid)
void tds_iconv_free(TDSCONNECTION *conn)
int tds_sys_iconv_close(iconv_t cd)
TDSICONV * tds_iconv_from_collate(TDSCONNECTION *conn, TDS_UCHAR collate[5])
Get iconv information from a LCID (to support different column encoding under MSSQL2K)
int strncmp(const char *str1, const char *str2, size_t count)
int strcmp(const char *str1, const char *str2)
static SLJIT_INLINE sljit_ins l(sljit_gpr r, sljit_s32 d, sljit_gpr x, sljit_gpr b)
static CNamedPipeClient * client
Information relevant to libiconv.
unsigned char max_bytes_per_char
const char * name
name of the encoding (ie UTF-8)
unsigned char min_bytes_per_char
unsigned char canonic
internal numeric index into array of all encodings
Information for a server connection.
struct tdsiconvdir to from
TDS_ERRNO_MESSAGE_FLAGS suppress
uchar outbuf[(1000000+1000000)]