diff options
author | Sergey Petrunya <psergey@askmonty.org> | 2009-09-08 00:50:10 +0400 |
---|---|---|
committer | Sergey Petrunya <psergey@askmonty.org> | 2009-09-08 00:50:10 +0400 |
commit | 29f0dcb56337a3e352ad7a70dcff6b25bb605325 (patch) | |
tree | 84935c21dc958724ae7dcbeeca0c0f08986fc430 /sql/sql_string.cc | |
parent | 915a624cbcb58a10a2cfb2e2e4fd5029191fa86a (diff) | |
parent | 8a2454f8e9fce648272577fcf8006ae6e6806cf9 (diff) | |
download | mariadb-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.cc | 87 |
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; +} |