summaryrefslogtreecommitdiff
path: root/sql/sql_string.cc
diff options
context:
space:
mode:
authorSergey Petrunya <psergey@askmonty.org>2009-09-08 00:50:10 +0400
committerSergey Petrunya <psergey@askmonty.org>2009-09-08 00:50:10 +0400
commit29f0dcb56337a3e352ad7a70dcff6b25bb605325 (patch)
tree84935c21dc958724ae7dcbeeca0c0f08986fc430 /sql/sql_string.cc
parent915a624cbcb58a10a2cfb2e2e4fd5029191fa86a (diff)
parent8a2454f8e9fce648272577fcf8006ae6e6806cf9 (diff)
downloadmariadb-git-29f0dcb56337a3e352ad7a70dcff6b25bb605325.tar.gz
Merge MySQL->MariaDB
* Finished Monty and Jani's merge * Some InnoDB tests still fail (because it's old xtradb code run against newer testsuite). They are expected to go after mergning with the latest xtradb.
Diffstat (limited to 'sql/sql_string.cc')
-rw-r--r--sql/sql_string.cc87
1 files changed, 86 insertions, 1 deletions
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 8b4294c5caf..e9927c8e85c 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -322,12 +322,24 @@ bool String::set_or_copy_aligned(const char *str,uint32 arg_length,
return copy_aligned(str, arg_length, offset, cs);
}
- /* Copy with charset conversion */
+
+/**
+ Copies the character data into this String, with optional character set
+ conversion.
+
+ @return
+ FALSE ok
+ TRUE Could not allocate result buffer
+
+*/
bool String::copy(const char *str, uint32 arg_length,
CHARSET_INFO *from_cs, CHARSET_INFO *to_cs, uint *errors)
{
uint32 offset;
+
+ DBUG_ASSERT(!str || str != Ptr);
+
if (!needs_conversion(arg_length, from_cs, to_cs, &offset))
{
*errors= 0;
@@ -1167,3 +1179,76 @@ void String::swap(String &s)
swap_variables(bool, alloced, s.alloced);
swap_variables(CHARSET_INFO*, str_charset, s.str_charset);
}
+
+
+/**
+ Convert string to printable ASCII string
+
+ @details This function converts input string "from" replacing non-ASCII bytes
+ with hexadecimal sequences ("\xXX") optionally appending "..." to the end of
+ the resulting string.
+ This function used in the ER_TRUNCATED_WRONG_VALUE_FOR_FIELD error messages,
+ e.g. when a string cannot be converted to a result charset.
+
+
+ @param to output buffer
+ @param to_len size of the output buffer (8 bytes or greater)
+ @param from input string
+ @param from_len size of the input string
+ @param from_cs input charset
+ @param nbytes maximal number of bytes to convert (from_len if 0)
+
+ @return number of bytes in the output string
+*/
+
+uint convert_to_printable(char *to, size_t to_len,
+ const char *from, size_t from_len,
+ CHARSET_INFO *from_cs, size_t nbytes /*= 0*/)
+{
+ /* needs at least 8 bytes for '\xXX...' and zero byte */
+ DBUG_ASSERT(to_len >= 8);
+
+ char *t= to;
+ char *t_end= to + to_len - 1; // '- 1' is for the '\0' at the end
+ const char *f= from;
+ const char *f_end= from + (nbytes ? min(from_len, nbytes) : from_len);
+ char *dots= to; // last safe place to append '...'
+
+ if (!f || t == t_end)
+ return 0;
+
+ for (; t < t_end && f < f_end; f++)
+ {
+ /*
+ If the source string is ASCII compatible (mbminlen==1)
+ and the source character is in ASCII printable range (0x20..0x7F),
+ then display the character as is.
+
+ Otherwise, if the source string is not ASCII compatible (e.g. UCS2),
+ or the source character is not in the printable range,
+ then print the character using HEX notation.
+ */
+ if (((unsigned char) *f) >= 0x20 &&
+ ((unsigned char) *f) <= 0x7F &&
+ from_cs->mbminlen == 1)
+ {
+ *t++= *f;
+ }
+ else
+ {
+ if (t_end - t < 4) // \xXX
+ break;
+ *t++= '\\';
+ *t++= 'x';
+ *t++= _dig_vec_upper[((unsigned char) *f) >> 4];
+ *t++= _dig_vec_upper[((unsigned char) *f) & 0x0F];
+ }
+ if (t_end - t >= 3) // '...'
+ dots= t;
+ }
+ if (f < from + from_len)
+ memcpy(dots, STRING_WITH_LEN("...\0"));
+ else
+ *t= '\0';
+ return t - to;
+}