summaryrefslogtreecommitdiff
path: root/strings
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.org>2015-03-16 12:14:31 +0400
committerAlexander Barkov <bar@mariadb.org>2015-03-16 12:14:31 +0400
commitf48dc5ccc7246c5ca9ebad2acc2d1d56a3470f9d (patch)
treedad0c76c6303556b7a92431957b08dec4ff8c559 /strings
parentc4b268add0475c6633f35eaf8cf4c7fbcad298f6 (diff)
downloadmariadb-git-f48dc5ccc7246c5ca9ebad2acc2d1d56a3470f9d.tar.gz
Moving the conversion code from String::well_formed_copy()
to my_convert_fix() - a new function in /strings.
Diffstat (limited to 'strings')
-rw-r--r--strings/ctype.c73
1 files changed, 73 insertions, 0 deletions
diff --git a/strings/ctype.c b/strings/ctype.c
index 048fbe3d368..aa40e2b338c 100644
--- a/strings/ctype.c
+++ b/strings/ctype.c
@@ -1161,3 +1161,76 @@ my_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs,
DBUG_ASSERT(FALSE); // Should never get to here
return 0; // Make compiler happy
}
+
+
+size_t
+my_convert_fix(CHARSET_INFO *to_cs, char *to, size_t to_length,
+ CHARSET_INFO *from_cs, const char *from, size_t from_length,
+ size_t nchars, MY_STRCONV_STATUS *status)
+{
+ int cnvres;
+ my_wc_t wc;
+ my_charset_conv_mb_wc mb_wc= from_cs->cset->mb_wc;
+ my_charset_conv_wc_mb wc_mb= to_cs->cset->wc_mb;
+ const uchar *from_end= (const uchar*) from + from_length;
+ uchar *to_end= (uchar*) to + to_length;
+ char *to_start= to;
+
+ DBUG_ASSERT(to_cs != &my_charset_bin);
+ DBUG_ASSERT(from_cs != &my_charset_bin);
+
+ status->m_native_copy_status.m_well_formed_error_pos= NULL;
+ status->m_cannot_convert_error_pos= NULL;
+
+ for ( ; nchars; nchars--)
+ {
+ const char *from_prev= from;
+ if ((cnvres= (*mb_wc)(from_cs, &wc, (uchar*) from, from_end)) > 0)
+ from+= cnvres;
+ else if (cnvres == MY_CS_ILSEQ)
+ {
+ if (!status->m_native_copy_status.m_well_formed_error_pos)
+ status->m_native_copy_status.m_well_formed_error_pos= from;
+ from++;
+ wc= '?';
+ }
+ else if (cnvres > MY_CS_TOOSMALL)
+ {
+ /*
+ A correct multibyte sequence detected
+ But it doesn't have Unicode mapping.
+ */
+ if (!status->m_cannot_convert_error_pos)
+ status->m_cannot_convert_error_pos= from;
+ from+= (-cnvres);
+ wc= '?';
+ }
+ else
+ {
+ if ((uchar *) from >= from_end)
+ break; // End of line
+ // Incomplete byte sequence
+ if (!status->m_native_copy_status.m_well_formed_error_pos)
+ status->m_native_copy_status.m_well_formed_error_pos= from;
+ from++;
+ wc= '?';
+ }
+outp:
+ if ((cnvres= (*wc_mb)(to_cs, wc, (uchar*) to, to_end)) > 0)
+ to+= cnvres;
+ else if (cnvres == MY_CS_ILUNI && wc != '?')
+ {
+ if (!status->m_cannot_convert_error_pos)
+ status->m_cannot_convert_error_pos= from_prev;
+ wc= '?';
+ goto outp;
+ }
+ else
+ {
+ from= from_prev;
+ break;
+ }
+ }
+ status->m_native_copy_status.m_source_end_pos= from;
+ return to - to_start;
+}