sql_string.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:19k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. /* This file is originally from the mysql distribution. Coded by monty */
  14. #ifdef USE_PRAGMA_IMPLEMENTATION
  15. #pragma implementation // gcc: Class implementation
  16. #endif
  17. #include <my_global.h>
  18. #include <my_sys.h>
  19. #include <m_string.h>
  20. #include <m_ctype.h>
  21. #ifdef HAVE_FCONVERT
  22. #include <floatingpoint.h>
  23. #endif
  24. /*
  25.   The following extern declarations are ok as these are interface functions
  26.   required by the string function
  27. */
  28. extern gptr sql_alloc(unsigned size);
  29. extern void sql_element_free(void *ptr);
  30. #include "sql_string.h"
  31. /*****************************************************************************
  32. ** String functions
  33. *****************************************************************************/
  34. bool String::real_alloc(uint32 arg_length)
  35. {
  36.   arg_length=ALIGN_SIZE(arg_length+1);
  37.   str_length=0;
  38.   if (Alloced_length < arg_length)
  39.   {
  40.     free();
  41.     if (!(Ptr=(char*) my_malloc(arg_length,MYF(MY_WME))))
  42.       return TRUE;
  43.     Alloced_length=arg_length;
  44.     alloced=1;
  45.   }
  46.   Ptr[0]=0;
  47.   return FALSE;
  48. }
  49. /*
  50. ** Check that string is big enough. Set string[alloc_length] to 0
  51. ** (for C functions)
  52. */
  53. bool String::realloc(uint32 alloc_length)
  54. {
  55.   uint32 len=ALIGN_SIZE(alloc_length+1);
  56.   if (Alloced_length < len)
  57.   {
  58.     char *new_ptr;
  59.     if (alloced)
  60.     {
  61.       if ((new_ptr= (char*) my_realloc(Ptr,len,MYF(MY_WME))))
  62.       {
  63. Ptr=new_ptr;
  64. Alloced_length=len;
  65.       }
  66.       else
  67. return TRUE; // Signal error
  68.     }
  69.     else if ((new_ptr= (char*) my_malloc(len,MYF(MY_WME))))
  70.     {
  71.       if (str_length) // Avoid bugs in memcpy on AIX
  72. memcpy(new_ptr,Ptr,str_length);
  73.       new_ptr[str_length]=0;
  74.       Ptr=new_ptr;
  75.       Alloced_length=len;
  76.       alloced=1;
  77.     }
  78.     else
  79.       return TRUE; // Signal error
  80.   }
  81.   Ptr[alloc_length]=0; // This make other funcs shorter
  82.   return FALSE;
  83. }
  84. bool String::set(longlong num, CHARSET_INFO *cs)
  85. {
  86.   uint l=20*cs->mbmaxlen+1;
  87.   if (alloc(l))
  88.     return TRUE;
  89.   str_length=(uint32) (cs->cset->longlong10_to_str)(cs,Ptr,l,-10,num);
  90.   str_charset=cs;
  91.   return FALSE;
  92. }
  93. bool String::set(ulonglong num, CHARSET_INFO *cs)
  94. {
  95.   uint l=20*cs->mbmaxlen+1;
  96.   if (alloc(l))
  97.     return TRUE;
  98.   str_length=(uint32) (cs->cset->longlong10_to_str)(cs,Ptr,l,10,num);
  99.   str_charset=cs;
  100.   return FALSE;
  101. }
  102. bool String::set(double num,uint decimals, CHARSET_INFO *cs)
  103. {
  104.   char buff[331];
  105.   uint dummy_errors;
  106.   str_charset=cs;
  107.   if (decimals >= NOT_FIXED_DEC)
  108.   {
  109.     uint32 len= my_sprintf(buff,(buff, "%.14g",num));// Enough for a DATETIME
  110.     return copy(buff, len, &my_charset_latin1, cs, &dummy_errors);
  111.   }
  112. #ifdef HAVE_FCONVERT
  113.   int decpt,sign;
  114.   char *pos,*to;
  115.   VOID(fconvert(num,(int) decimals,&decpt,&sign,buff+1));
  116.   if (!my_isdigit(&my_charset_latin1, buff[1]))
  117.   { // Nan or Inf
  118.     pos=buff+1;
  119.     if (sign)
  120.     {
  121.       buff[0]='-';
  122.       pos=buff;
  123.     }
  124.     uint dummy_errors;
  125.     return copy(pos,(uint32) strlen(pos), &my_charset_latin1, cs, &dummy_errors);
  126.   }
  127.   if (alloc((uint32) ((uint32) decpt+3+decimals)))
  128.     return TRUE;
  129.   to=Ptr;
  130.   if (sign)
  131.     *to++='-';
  132.   pos=buff+1;
  133.   if (decpt < 0)
  134.   { /* value is < 0 */
  135.     *to++='0';
  136.     if (!decimals)
  137.       goto end;
  138.     *to++='.';
  139.     if ((uint32) -decpt > decimals)
  140.       decpt= - (int) decimals;
  141.     decimals=(uint32) ((int) decimals+decpt);
  142.     while (decpt++ < 0)
  143.       *to++='0';
  144.   }
  145.   else if (decpt == 0)
  146.   {
  147.     *to++= '0';
  148.     if (!decimals)
  149.       goto end;
  150.     *to++='.';
  151.   }
  152.   else
  153.   {
  154.     while (decpt-- > 0)
  155.       *to++= *pos++;
  156.     if (!decimals)
  157.       goto end;
  158.     *to++='.';
  159.   }
  160.   while (decimals--)
  161.     *to++= *pos++;
  162. end:
  163.   *to=0;
  164.   str_length=(uint32) (to-Ptr);
  165.   return FALSE;
  166. #else
  167. #ifdef HAVE_SNPRINTF
  168.   buff[sizeof(buff)-1]=0; // Safety
  169.   snprintf(buff,sizeof(buff)-1, "%.*f",(int) decimals,num);
  170. #else
  171.   sprintf(buff,"%.*f",(int) decimals,num);
  172. #endif
  173.   return copy(buff,(uint32) strlen(buff), &my_charset_latin1, cs,
  174.               &dummy_errors);
  175. #endif
  176. }
  177. bool String::copy()
  178. {
  179.   if (!alloced)
  180.   {
  181.     Alloced_length=0; // Force realloc
  182.     return realloc(str_length);
  183.   }
  184.   return FALSE;
  185. }
  186. bool String::copy(const String &str)
  187. {
  188.   if (alloc(str.str_length))
  189.     return TRUE;
  190.   str_length=str.str_length;
  191.   bmove(Ptr,str.Ptr,str_length); // May be overlapping
  192.   Ptr[str_length]=0;
  193.   str_charset=str.str_charset;
  194.   return FALSE;
  195. }
  196. bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *cs)
  197. {
  198.   if (alloc(arg_length))
  199.     return TRUE;
  200.   if ((str_length=arg_length))
  201.     memcpy(Ptr,str,arg_length);
  202.   Ptr[arg_length]=0;
  203.   str_charset=cs;
  204.   return FALSE;
  205. }
  206. /*
  207.   Checks that the source string can be just copied to the destination string
  208.   without conversion.
  209.   SYNPOSIS
  210.   needs_conversion()
  211.   arg_length Length of string to copy.
  212.   from_cs Character set to copy from
  213.   to_cs Character set to copy to
  214.   uint32 *offset Returns number of unaligned characters.
  215.   RETURN
  216.    0  No conversion needed
  217.    1  Either character set conversion or adding leading  zeros
  218.       (e.g. for UCS-2) must be done
  219. */
  220. bool String::needs_conversion(uint32 arg_length,
  221.       CHARSET_INFO *from_cs,
  222.       CHARSET_INFO *to_cs,
  223.       uint32 *offset)
  224. {
  225.   *offset= 0;
  226.   if ((to_cs == &my_charset_bin) || 
  227.       (to_cs == from_cs) ||
  228.       my_charset_same(from_cs, to_cs) ||
  229.       ((from_cs == &my_charset_bin) &&
  230.        (!(*offset=(arg_length % to_cs->mbminlen)))))
  231.     return FALSE;
  232.   return TRUE;
  233. }
  234. /*
  235.   Copy a multi-byte character sets with adding leading zeros.
  236.   SYNOPSIS
  237.   copy_aligned()
  238.   str String to copy
  239.   arg_length Length of string. This should NOT be dividable with
  240. cs->mbminlen.
  241.   offset arg_length % cs->mb_minlength
  242.   cs Character set for 'str'
  243.   NOTES
  244.     For real multi-byte, ascii incompatible charactser sets,
  245.     like UCS-2, add leading zeros if we have an incomplete character.
  246.     Thus, 
  247.       SELECT _ucs2 0xAA 
  248.     will automatically be converted into
  249.       SELECT _ucs2 0x00AA
  250.   RETURN
  251.     0  ok
  252.     1  error
  253. */
  254. bool String::copy_aligned(const char *str,uint32 arg_length, uint32 offset,
  255.   CHARSET_INFO *cs)
  256. {
  257.   /* How many bytes are in incomplete character */
  258.   offset= cs->mbmaxlen - offset; /* How many zeros we should prepend */
  259.   DBUG_ASSERT(offset && offset != cs->mbmaxlen);
  260.   uint32 aligned_length= arg_length + offset;
  261.   if (alloc(aligned_length))
  262.     return TRUE;
  263.   
  264.   /*
  265.     Note, this is only safe for little-endian UCS-2.
  266.     If we add big-endian UCS-2 sometimes, this code
  267.     will be more complicated. But it's OK for now.
  268.   */
  269.   bzero((char*) Ptr, offset);
  270.   memcpy(Ptr + offset, str, arg_length);
  271.   Ptr[aligned_length]=0;
  272.   /* str_length is always >= 0 as arg_length is != 0 */
  273.   str_length= aligned_length;
  274.   str_charset= cs;
  275.   return FALSE;
  276. }
  277. bool String::set_or_copy_aligned(const char *str,uint32 arg_length,
  278.  CHARSET_INFO *cs)
  279. {
  280.   /* How many bytes are in incomplete character */
  281.   uint32 offset= (arg_length % cs->mbminlen); 
  282.   
  283.   if (!offset) /* All characters are complete, just copy */
  284.   {
  285.     set(str, arg_length, cs);
  286.     return FALSE;
  287.   }
  288.   return copy_aligned(str, arg_length, offset, cs);
  289. }
  290. /* Copy with charset convertion */
  291. bool String::copy(const char *str, uint32 arg_length,
  292.   CHARSET_INFO *from_cs, CHARSET_INFO *to_cs, uint *errors)
  293. {
  294.   uint32 offset;
  295.   if (!needs_conversion(arg_length, from_cs, to_cs, &offset))
  296.   {
  297.     *errors= 0;
  298.     return copy(str, arg_length, to_cs);
  299.   }
  300.   if ((from_cs == &my_charset_bin) && offset)
  301.   {
  302.     *errors= 0;
  303.     return copy_aligned(str, arg_length, offset, to_cs);
  304.   }
  305.   uint32 new_length= to_cs->mbmaxlen*arg_length;
  306.   if (alloc(new_length))
  307.     return TRUE;
  308.   str_length=copy_and_convert((char*) Ptr, new_length, to_cs,
  309.                               str, arg_length, from_cs, errors);
  310.   str_charset=to_cs;
  311.   return FALSE;
  312. }
  313. /*
  314.   Set a string to the value of a latin1-string, keeping the original charset
  315.   
  316.   SYNOPSIS
  317.     copy_or_set()
  318.     str String of a simple charset (latin1)
  319.     arg_length Length of string
  320.   IMPLEMENTATION
  321.     If string object is of a simple character set, set it to point to the
  322.     given string.
  323.     If not, make a copy and convert it to the new character set.
  324.   RETURN
  325.     0 ok
  326.     1 Could not allocate result buffer
  327. */
  328. bool String::set_ascii(const char *str, uint32 arg_length)
  329. {
  330.   if (str_charset->mbminlen == 1)
  331.   {
  332.     set(str, arg_length, str_charset);
  333.     return 0;
  334.   }
  335.   uint dummy_errors;
  336.   return copy(str, arg_length, &my_charset_latin1, str_charset, &dummy_errors);
  337. }
  338. /* This is used by mysql.cc */
  339. bool String::fill(uint32 max_length,char fill_char)
  340. {
  341.   if (str_length > max_length)
  342.     Ptr[str_length=max_length]=0;
  343.   else
  344.   {
  345.     if (realloc(max_length))
  346.       return TRUE;
  347.     bfill(Ptr+str_length,max_length-str_length,fill_char);
  348.     str_length=max_length;
  349.   }
  350.   return FALSE;
  351. }
  352. void String::strip_sp()
  353. {
  354.    while (str_length && my_isspace(str_charset,Ptr[str_length-1]))
  355.     str_length--;
  356. }
  357. bool String::append(const String &s)
  358. {
  359.   if (s.length())
  360.   {
  361.     if (realloc(str_length+s.length()))
  362.       return TRUE;
  363.     memcpy(Ptr+str_length,s.ptr(),s.length());
  364.     str_length+=s.length();
  365.   }
  366.   return FALSE;
  367. }
  368. /*
  369.   Append an ASCII string to the a string of the current character set
  370. */
  371. bool String::append(const char *s,uint32 arg_length)
  372. {
  373.   if (!arg_length)
  374.     return FALSE;
  375.   /*
  376.     For an ASCII incompatible string, e.g. UCS-2, we need to convert
  377.   */
  378.   if (str_charset->mbminlen > 1)
  379.   {
  380.     uint32 add_length=arg_length * str_charset->mbmaxlen;
  381.     uint dummy_errors;
  382.     if (realloc(str_length+ add_length))
  383.       return TRUE;
  384.     str_length+= copy_and_convert(Ptr+str_length, add_length, str_charset,
  385.   s, arg_length, &my_charset_latin1,
  386.                                   &dummy_errors);
  387.     return FALSE;
  388.   }
  389.   /*
  390.     For an ASCII compatinble string we can just append.
  391.   */
  392.   if (realloc(str_length+arg_length))
  393.     return TRUE;
  394.   memcpy(Ptr+str_length,s,arg_length);
  395.   str_length+=arg_length;
  396.   return FALSE;
  397. }
  398. /*
  399.   Append a 0-terminated ASCII string
  400. */
  401. bool String::append(const char *s)
  402. {
  403.   return append(s, strlen(s));
  404. }
  405. /*
  406.   Append a string in the given charset to the string
  407.   with character set recoding
  408. */
  409. bool String::append(const char *s,uint32 arg_length, CHARSET_INFO *cs)
  410. {
  411.   uint32 dummy_offset;
  412.   
  413.   if (needs_conversion(arg_length, cs, str_charset, &dummy_offset))
  414.   {
  415.     uint32 add_length= arg_length / cs->mbminlen * str_charset->mbmaxlen;
  416.     uint dummy_errors;
  417.     if (realloc(str_length + add_length)) 
  418.       return TRUE;
  419.     str_length+= copy_and_convert(Ptr+str_length, add_length, str_charset,
  420.   s, arg_length, cs, &dummy_errors);
  421.   }
  422.   else
  423.   {
  424.     if (realloc(str_length + arg_length)) 
  425.       return TRUE;
  426.     memcpy(Ptr + str_length, s, arg_length);
  427.     str_length+= arg_length;
  428.   }
  429.   return FALSE;
  430. }
  431. #ifdef TO_BE_REMOVED
  432. bool String::append(FILE* file, uint32 arg_length, myf my_flags)
  433. {
  434.   if (realloc(str_length+arg_length))
  435.     return TRUE;
  436.   if (my_fread(file, (byte*) Ptr + str_length, arg_length, my_flags))
  437.   {
  438.     shrink(str_length);
  439.     return TRUE;
  440.   }
  441.   str_length+=arg_length;
  442.   return FALSE;
  443. }
  444. #endif
  445. bool String::append(IO_CACHE* file, uint32 arg_length)
  446. {
  447.   if (realloc(str_length+arg_length))
  448.     return TRUE;
  449.   if (my_b_read(file, (byte*) Ptr + str_length, arg_length))
  450.   {
  451.     shrink(str_length);
  452.     return TRUE;
  453.   }
  454.   str_length+=arg_length;
  455.   return FALSE;
  456. }
  457. bool String::append_with_prefill(const char *s,uint32 arg_length,
  458.  uint32 full_length, char fill_char)
  459. {
  460.   int t_length= arg_length > full_length ? arg_length : full_length;
  461.   if (realloc(str_length + t_length))
  462.     return TRUE;
  463.   t_length= full_length - arg_length;
  464.   if (t_length > 0)
  465.   {
  466.     bfill(Ptr+str_length, t_length, fill_char);
  467.     str_length=str_length + t_length;
  468.   }
  469.   append(s, arg_length);
  470.   return FALSE;
  471. }
  472. uint32 String::numchars()
  473. {
  474.   return str_charset->cset->numchars(str_charset, Ptr, Ptr+str_length);
  475. }
  476. int String::charpos(int i,uint32 offset)
  477. {
  478.   if (i <= 0)
  479.     return i;
  480.   return str_charset->cset->charpos(str_charset,Ptr+offset,Ptr+str_length,i);
  481. }
  482. int String::strstr(const String &s,uint32 offset)
  483. {
  484.   if (s.length()+offset <= str_length)
  485.   {
  486.     if (!s.length())
  487.       return ((int) offset); // Empty string is always found
  488.     register const char *str = Ptr+offset;
  489.     register const char *search=s.ptr();
  490.     const char *end=Ptr+str_length-s.length()+1;
  491.     const char *search_end=s.ptr()+s.length();
  492. skip:
  493.     while (str != end)
  494.     {
  495.       if (*str++ == *search)
  496.       {
  497. register char *i,*j;
  498. i=(char*) str; j=(char*) search+1;
  499. while (j != search_end)
  500.   if (*i++ != *j++) goto skip;
  501. return (int) (str-Ptr) -1;
  502.       }
  503.     }
  504.   }
  505.   return -1;
  506. }
  507. /*
  508. ** Search string from end. Offset is offset to the end of string
  509. */
  510. int String::strrstr(const String &s,uint32 offset)
  511. {
  512.   if (s.length() <= offset && offset <= str_length)
  513.   {
  514.     if (!s.length())
  515.       return offset; // Empty string is always found
  516.     register const char *str = Ptr+offset-1;
  517.     register const char *search=s.ptr()+s.length()-1;
  518.     const char *end=Ptr+s.length()-2;
  519.     const char *search_end=s.ptr()-1;
  520. skip:
  521.     while (str != end)
  522.     {
  523.       if (*str-- == *search)
  524.       {
  525. register char *i,*j;
  526. i=(char*) str; j=(char*) search-1;
  527. while (j != search_end)
  528.   if (*i-- != *j--) goto skip;
  529. return (int) (i-Ptr) +1;
  530.       }
  531.     }
  532.   }
  533.   return -1;
  534. }
  535. /*
  536. ** replace substring with string
  537. ** If wrong parameter or not enough memory, do nothing
  538. */
  539. bool String::replace(uint32 offset,uint32 arg_length,const String &to)
  540. {
  541.   return replace(offset,arg_length,to.ptr(),to.length());
  542. }
  543. bool String::replace(uint32 offset,uint32 arg_length,
  544.                      const char *to,uint32 length)
  545. {
  546.   long diff = (long) length-(long) arg_length;
  547.   if (offset+arg_length <= str_length)
  548.   {
  549.     if (diff < 0)
  550.     {
  551.       if (length)
  552. memcpy(Ptr+offset,to,length);
  553.       bmove(Ptr+offset+length,Ptr+offset+arg_length,
  554.     str_length-offset-arg_length);
  555.     }
  556.     else
  557.     {
  558.       if (diff)
  559.       {
  560. if (realloc(str_length+(uint32) diff))
  561.   return TRUE;
  562. bmove_upp(Ptr+str_length+diff,Ptr+str_length,
  563.   str_length-offset-arg_length);
  564.       }
  565.       if (length)
  566. memcpy(Ptr+offset,to,length);
  567.     }
  568.     str_length+=(uint32) diff;
  569.   }
  570.   return FALSE;
  571. }
  572. // added by Holyfoot for "geometry" needs
  573. int String::reserve(uint32 space_needed, uint32 grow_by)
  574. {
  575.   if (Alloced_length < str_length + space_needed)
  576.   {
  577.     if (realloc(Alloced_length + max(space_needed, grow_by) - 1))
  578.       return TRUE;
  579.   }
  580.   return FALSE;
  581. }
  582. void String::qs_append(const char *str, uint32 len)
  583. {
  584.   memcpy(Ptr + str_length, str, len + 1);
  585.   str_length += len;
  586. }
  587. void String::qs_append(double d)
  588. {
  589.   char *buff = Ptr + str_length;
  590.   str_length+= my_sprintf(buff, (buff, "%.14g", d));
  591. }
  592. void String::qs_append(double *d)
  593. {
  594.   double ld;
  595.   float8get(ld, (char*) d);
  596.   qs_append(ld);
  597. }
  598. /*
  599.   Compare strings according to collation, without end space.
  600.   SYNOPSIS
  601.     sortcmp()
  602.     s First string
  603.     t Second string
  604.     cs Collation
  605.   NOTE:
  606.     Normally this is case sensitive comparison
  607.   RETURN
  608.   < 0 s < t
  609.   0 s == t
  610.   > 0 s > t
  611. */
  612. int sortcmp(const String *s,const String *t, CHARSET_INFO *cs)
  613. {
  614.  return cs->coll->strnncollsp(cs,
  615.                              (unsigned char *) s->ptr(),s->length(),
  616.      (unsigned char *) t->ptr(),t->length());
  617. }
  618. /*
  619.   Compare strings byte by byte. End spaces are also compared.
  620.   SYNOPSIS
  621.     stringcmp()
  622.     s First string
  623.     t Second string
  624.   NOTE:
  625.     Strings are compared as a stream of unsigned chars
  626.   RETURN
  627.   < 0 s < t
  628.   0 s == t
  629.   > 0 s > t
  630. */
  631. int stringcmp(const String *s,const String *t)
  632. {
  633.   uint32 s_len=s->length(),t_len=t->length(),len=min(s_len,t_len);
  634.   int cmp= memcmp(s->ptr(), t->ptr(), len);
  635.   return (cmp) ? cmp : (int) (s_len - t_len);
  636. }
  637. String *copy_if_not_alloced(String *to,String *from,uint32 from_length)
  638. {
  639.   if (from->Alloced_length >= from_length)
  640.     return from;
  641.   if (from->alloced || !to || from == to)
  642.   {
  643.     (void) from->realloc(from_length);
  644.     return from;
  645.   }
  646.   if (to->realloc(from_length))
  647.     return from; // Actually an error
  648.   if ((to->str_length=min(from->str_length,from_length)))
  649.     memcpy(to->Ptr,from->Ptr,to->str_length);
  650.   to->str_charset=from->str_charset;
  651.   return to;
  652. }
  653. /****************************************************************************
  654.   Help functions
  655. ****************************************************************************/
  656. /*
  657.   copy a string from one character set to another
  658.   
  659.   SYNOPSIS
  660.     copy_and_convert()
  661.     to Store result here
  662.     to_cs Character set of result string
  663.     from Copy from here
  664.     from_length Length of from string
  665.     from_cs From character set
  666.   NOTES
  667.     'to' must be big enough as form_length * to_cs->mbmaxlen
  668.   RETURN
  669.     length of bytes copied to 'to'
  670. */
  671. uint32
  672. copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs, 
  673.                  const char *from, uint32 from_length, CHARSET_INFO *from_cs,
  674.                  uint *errors)
  675. {
  676.   int         cnvres;
  677.   my_wc_t     wc;
  678.   const uchar *from_end= (const uchar*) from+from_length;
  679.   char *to_start= to;
  680.   uchar *to_end= (uchar*) to+to_length;
  681.   int (*mb_wc)(struct charset_info_st *, my_wc_t *, const uchar *,
  682.        const uchar *) = from_cs->cset->mb_wc;
  683.   int (*wc_mb)(struct charset_info_st *, my_wc_t, uchar *s, uchar *e)=
  684.     to_cs->cset->wc_mb;
  685.   uint error_count= 0;
  686.   while (1)
  687.   {
  688.     if ((cnvres= (*mb_wc)(from_cs, &wc, (uchar*) from,
  689.       from_end)) > 0)
  690.       from+= cnvres;
  691.     else if (cnvres == MY_CS_ILSEQ)
  692.     {
  693.       error_count++;
  694.       from++;
  695.       wc= '?';
  696.     }
  697.     else
  698.       break; // Impossible char.
  699. outp:
  700.     if ((cnvres= (*wc_mb)(to_cs, wc, (uchar*) to, to_end)) > 0)
  701.       to+= cnvres;
  702.     else if (cnvres == MY_CS_ILUNI && wc != '?')
  703.     {
  704.       error_count++;
  705.       wc= '?';
  706.       goto outp;
  707.     }
  708.     else
  709.       break;
  710.   }
  711.   *errors= error_count;
  712.   return (uint32) (to - to_start);
  713. }
  714. void String::print(String *str)
  715. {
  716.   char *st= (char*)Ptr, *end= st+str_length;
  717.   for (; st < end; st++)
  718.   {
  719.     uchar c= *st;
  720.     switch (c)
  721.     {
  722.     case '\':
  723.       str->append("\\", 2);
  724.       break;
  725.     case '':
  726.       str->append("\0", 2);
  727.       break;
  728.     case ''':
  729.       str->append("\'", 2);
  730.       break;
  731.     case 'n':
  732.       str->append("\n", 2);
  733.       break;
  734.     case 'r':
  735.       str->append("\r", 2);
  736.       break;
  737.     case 26: //Ctrl-Z
  738.       str->append("\z", 2);
  739.       break;
  740.     default:
  741.       str->append(c);
  742.     }
  743.   }
  744. }
  745. /*
  746.   Exchange state of this object and argument.
  747.   SYNOPSIS
  748.     String::swap()
  749.   RETURN
  750.     Target string will contain state of this object and vice versa.
  751. */
  752. void String::swap(String &s)
  753. {
  754.   swap_variables(char *, Ptr, s.Ptr);
  755.   swap_variables(uint32, str_length, s.str_length);
  756.   swap_variables(uint32, Alloced_length, s.Alloced_length);
  757.   swap_variables(bool, alloced, s.alloced);
  758.   swap_variables(CHARSET_INFO*, str_charset, s.str_charset);
  759. }