diff options
Diffstat (limited to 'sql/sql_string.cc')
-rw-r--r-- | sql/sql_string.cc | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 89f48607969..9534c5605fe 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -228,6 +228,52 @@ bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *cs) return FALSE; } +/* +** For real multi-byte, ascii incompatible charactser sets, +** like UCS-2, add leading zeros if we have an incomplete character. +** Thus, +** SELECT _ucs2 0xAA +** will automatically be converted into +** SELECT _ucs2 0x00AA +*/ + +bool String::set_or_copy_aligned(const char *str,uint32 arg_length, + CHARSET_INFO *cs) +{ + /* How many bytes are in incomplete character */ + uint32 offs= (arg_length % cs->mbminlen); + + if (!offs) /* All characters are complete, just copy */ + { + set(str, arg_length, cs); + return FALSE; + } + + offs= cs->mbmaxlen - offs; /* How many zeros we should prepend */ + uint32 aligned_length= arg_length + offs; + if (alloc(aligned_length)) + return TRUE; + + /* + Probably this condition is not really necessary + because if aligned_length is 0 then offs is 0 too + and we'll return after calling set(). + */ + if ((str_length= aligned_length)) + { + /* + Note, this is only safe for little-endian UCS-2. + If we add big-endian UCS-2 sometimes, this code + will be more complicated. But it's OK for now. + */ + bzero((char*)Ptr, offs); + memcpy(Ptr + offs, str, arg_length); + } + Ptr[aligned_length]=0; + str_charset=cs; + return FALSE; +} + /* Copy with charset convertion */ bool String::copy(const char *str, uint32 arg_length, |