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

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. extern gptr sql_alloc(unsigned size);
  25. extern void sql_element_free(void *ptr);
  26. #include "sql_string.h"
  27. /*****************************************************************************
  28. ** String functions
  29. *****************************************************************************/
  30. bool String::real_alloc(uint32 arg_length)
  31. {
  32.   arg_length=ALIGN_SIZE(arg_length+1);
  33.   str_length=0;
  34.   if (Alloced_length < arg_length)
  35.   {
  36.     free();
  37.     if (!(Ptr=(char*) my_malloc(arg_length,MYF(MY_WME))))
  38.       return TRUE;
  39.     Alloced_length=arg_length;
  40.     alloced=1;
  41.   }
  42.   Ptr[0]=0;
  43.   return FALSE;
  44. }
  45. /*
  46. ** Check that string is big enough. Set string[alloc_length] to 0
  47. ** (for C functions)
  48. */
  49. bool String::realloc(uint32 alloc_length)
  50. {
  51.   uint32 len=ALIGN_SIZE(alloc_length+1);
  52.   if (Alloced_length < len)
  53.   {
  54.     char *new_ptr;
  55.     if (alloced)
  56.     {
  57.       if ((new_ptr= (char*) my_realloc(Ptr,len,MYF(MY_WME))))
  58.       {
  59. Ptr=new_ptr;
  60. Alloced_length=len;
  61.       }
  62.       else
  63. return TRUE; // Signal error
  64.     }
  65.     else if ((new_ptr= (char*) my_malloc(len,MYF(MY_WME))))
  66.     {
  67.       if (str_length) // Avoid bugs in memcpy on AIX
  68. memcpy(new_ptr,Ptr,str_length);
  69.       new_ptr[str_length]=0;
  70.       Ptr=new_ptr;
  71.       Alloced_length=len;
  72.       alloced=1;
  73.     }
  74.     else
  75.       return TRUE; // Signal error
  76.   }
  77.   Ptr[alloc_length]=0; // This make other funcs shorter
  78.   return FALSE;
  79. }
  80. bool String::set(longlong num, CHARSET_INFO *cs)
  81. {
  82.   uint l=20*cs->mbmaxlen+1;
  83.   if (alloc(l))
  84.     return TRUE;
  85.   if (cs->cset->snprintf == my_snprintf_8bit)
  86.   {
  87.     str_length=(uint32) (longlong10_to_str(num,Ptr,-10)-Ptr);
  88.   }
  89.   else
  90.   {
  91.     str_length=cs->cset->snprintf(cs,Ptr,l,"%d",num);
  92.   }
  93.   str_charset=cs;
  94.   return FALSE;
  95. }
  96. bool String::set(ulonglong num, CHARSET_INFO *cs)
  97. {
  98.   uint l=20*cs->mbmaxlen+1;
  99.   if (alloc(l))
  100.     return TRUE;
  101.   if (cs->cset->snprintf == my_snprintf_8bit)
  102.   {
  103.     str_length=(uint32) (longlong10_to_str(num,Ptr,10)-Ptr);
  104.   }
  105.   else
  106.   {
  107.     str_length=cs->cset->snprintf(cs,Ptr,l,"%d",num);
  108.   }
  109.   str_charset=cs;
  110.   return FALSE;
  111. }
  112. bool String::set(double num,uint decimals, CHARSET_INFO *cs)
  113. {
  114.   char buff[331];
  115.   str_charset=cs;
  116.   if (decimals >= NOT_FIXED_DEC)
  117.   {
  118.     sprintf(buff,"%.14g",num); // Enough for a DATETIME
  119.     return copy(buff, (uint32) strlen(buff), &my_charset_latin1, cs);
  120.   }
  121. #ifdef HAVE_FCONVERT
  122.   int decpt,sign;
  123.   char *pos,*to;
  124.   VOID(fconvert(num,(int) decimals,&decpt,&sign,buff+1));
  125.   if (!my_isdigit(&my_charset_latin1, buff[1]))
  126.   { // Nan or Inf
  127.     pos=buff+1;
  128.     if (sign)
  129.     {
  130.       buff[0]='-';
  131.       pos=buff;
  132.     }
  133.     return copy(pos,(uint32) strlen(pos), &my_charset_latin1, cs);
  134.   }
  135.   if (alloc((uint32) ((uint32) decpt+3+decimals)))
  136.     return TRUE;
  137.   to=Ptr;
  138.   if (sign)
  139.     *to++='-';
  140.   pos=buff+1;
  141.   if (decpt < 0)
  142.   { /* value is < 0 */
  143.     *to++='0';
  144.     if (!decimals)
  145.       goto end;
  146.     *to++='.';
  147.     if ((uint32) -decpt > decimals)
  148.       decpt= - (int) decimals;
  149.     decimals=(uint32) ((int) decimals+decpt);
  150.     while (decpt++ < 0)
  151.       *to++='0';
  152.   }
  153.   else if (decpt == 0)
  154.   {
  155.     *to++= '0';
  156.     if (!decimals)
  157.       goto end;
  158.     *to++='.';
  159.   }
  160.   else
  161.   {
  162.     while (decpt-- > 0)
  163.       *to++= *pos++;
  164.     if (!decimals)
  165.       goto end;
  166.     *to++='.';
  167.   }
  168.   while (decimals--)
  169.     *to++= *pos++;
  170. end:
  171.   *to=0;
  172.   str_length=(uint32) (to-Ptr);
  173.   return FALSE;
  174. #else
  175. #ifdef HAVE_SNPRINTF
  176.   buff[sizeof(buff)-1]=0; // Safety
  177.   snprintf(buff,sizeof(buff)-1, "%.*f",(int) decimals,num);
  178. #else
  179.   sprintf(buff,"%.*f",(int) decimals,num);
  180. #endif
  181.   return copy(buff,(uint32) strlen(buff), &my_charset_latin1, cs);
  182. #endif
  183. }
  184. bool String::copy()
  185. {
  186.   if (!alloced)
  187.   {
  188.     Alloced_length=0; // Force realloc
  189.     return realloc(str_length);
  190.   }
  191.   return FALSE;
  192. }
  193. bool String::copy(const String &str)
  194. {
  195.   if (alloc(str.str_length))
  196.     return TRUE;
  197.   str_length=str.str_length;
  198.   bmove(Ptr,str.Ptr,str_length); // May be overlapping
  199.   Ptr[str_length]=0;
  200.   str_charset=str.str_charset;
  201.   return FALSE;
  202. }
  203. bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *cs)
  204. {
  205.   if (alloc(arg_length))
  206.     return TRUE;
  207.   if ((str_length=arg_length))
  208.     memcpy(Ptr,str,arg_length);
  209.   Ptr[arg_length]=0;
  210.   str_charset=cs;
  211.   return FALSE;
  212. }
  213. /* Copy with charset convertion */
  214. bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *from, CHARSET_INFO *to)
  215. {
  216.   uint32      new_length=to->mbmaxlen*arg_length;
  217.   int         cnvres;
  218.   my_wc_t     wc;
  219.   const uchar *s=(const uchar *)str;
  220.   const uchar *se=s+arg_length;
  221.   uchar       *d, *de;
  222.   if (alloc(new_length))
  223.     return TRUE;
  224.   d=(uchar *)Ptr;
  225.   de=d+new_length;
  226.   
  227.   for (str_length=new_length ; s < se && d < de ; )
  228.   {
  229.     if ((cnvres=from->cset->mb_wc(from,&wc,s,se)) > 0 )
  230.     {
  231.       s+=cnvres;
  232.     }
  233.     else if (cnvres==MY_CS_ILSEQ)
  234.     {
  235.       s++;
  236.       wc='?';
  237.     }
  238.     else
  239.       break;
  240. outp:
  241.     if((cnvres=to->cset->wc_mb(to,wc,d,de)) >0 )
  242.     {
  243.       d+=cnvres;
  244.     }
  245.     else if (cnvres==MY_CS_ILUNI && wc!='?')
  246.     {
  247.       wc='?';
  248.       goto outp;
  249.     }
  250.     else
  251.       break;
  252.   }
  253.   Ptr[new_length]=0;
  254.   length((uint32) (d-(uchar *)Ptr));
  255.   str_charset=to;
  256.   return FALSE;
  257. }
  258. /* This is used by mysql.cc */
  259. bool String::fill(uint32 max_length,char fill_char)
  260. {
  261.   if (str_length > max_length)
  262.     Ptr[str_length=max_length]=0;
  263.   else
  264.   {
  265.     if (realloc(max_length))
  266.       return TRUE;
  267.     bfill(Ptr+str_length,max_length-str_length,fill_char);
  268.     str_length=max_length;
  269.   }
  270.   return FALSE;
  271. }
  272. void String::strip_sp()
  273. {
  274.    while (str_length && my_isspace(str_charset,Ptr[str_length-1]))
  275.     str_length--;
  276. }
  277. bool String::append(const String &s)
  278. {
  279.   if (s.length())
  280.   {
  281.     if (realloc(str_length+s.length()))
  282.       return TRUE;
  283.     memcpy(Ptr+str_length,s.ptr(),s.length());
  284.     str_length+=s.length();
  285.   }
  286.   return FALSE;
  287. }
  288. bool String::append(const char *s,uint32 arg_length)
  289. {
  290.   if (!arg_length) // Default argument
  291.     if (!(arg_length= (uint32) strlen(s)))
  292.       return FALSE;
  293.   if (realloc(str_length+arg_length))
  294.     return TRUE;
  295.   memcpy(Ptr+str_length,s,arg_length);
  296.   str_length+=arg_length;
  297.   return FALSE;
  298. }
  299. #ifdef TO_BE_REMOVED
  300. bool String::append(FILE* file, uint32 arg_length, myf my_flags)
  301. {
  302.   if (realloc(str_length+arg_length))
  303.     return TRUE;
  304.   if (my_fread(file, (byte*) Ptr + str_length, arg_length, my_flags))
  305.   {
  306.     shrink(str_length);
  307.     return TRUE;
  308.   }
  309.   str_length+=arg_length;
  310.   return FALSE;
  311. }
  312. #endif
  313. bool String::append(IO_CACHE* file, uint32 arg_length)
  314. {
  315.   if (realloc(str_length+arg_length))
  316.     return TRUE;
  317.   if (my_b_read(file, (byte*) Ptr + str_length, arg_length))
  318.   {
  319.     shrink(str_length);
  320.     return TRUE;
  321.   }
  322.   str_length+=arg_length;
  323.   return FALSE;
  324. }
  325. uint32 String::numchars()
  326. {
  327. #ifdef USE_MB
  328.   register uint32 n=0,mblen;
  329.   register const char *mbstr=Ptr;
  330.   register const char *end=mbstr+str_length;
  331.   if (use_mb(str_charset))
  332.   {
  333.     while (mbstr < end) {
  334.         if ((mblen=my_ismbchar(str_charset, mbstr,end))) mbstr+=mblen;
  335.         else ++mbstr;
  336.         ++n;
  337.     }
  338.     return n;
  339.   }
  340.   else
  341. #endif
  342.     return str_length;
  343. }
  344. int String::charpos(int i,uint32 offset)
  345. {
  346. #ifdef USE_MB
  347.   register uint32 mblen;
  348.   register const char *mbstr=Ptr+offset;
  349.   register const char *end=Ptr+str_length;
  350.   if (use_mb(str_charset))
  351.   {
  352.     if (i<=0) return i;
  353.     while (i && mbstr < end) {
  354.        if ((mblen=my_ismbchar(str_charset, mbstr,end))) mbstr+=mblen;
  355.        else ++mbstr;
  356.        --i;
  357.     }
  358.     if ( INT_MAX32-i <= (int) (mbstr-Ptr-offset)) 
  359.       return INT_MAX32;
  360.     else 
  361.       return (int) ((mbstr-Ptr-offset)+i);
  362.   }
  363.   else
  364. #endif
  365.     return i;
  366. }
  367. int String::strstr(const String &s,uint32 offset)
  368. {
  369.   if (s.length()+offset <= str_length)
  370.   {
  371.     if (!s.length())
  372.       return ((int) offset); // Empty string is always found
  373.     register const char *str = Ptr+offset;
  374.     register const char *search=s.ptr();
  375.     const char *end=Ptr+str_length-s.length()+1;
  376.     const char *search_end=s.ptr()+s.length();
  377. skip:
  378.     while (str != end)
  379.     {
  380.       if (*str++ == *search)
  381.       {
  382. register char *i,*j;
  383. i=(char*) str; j=(char*) search+1;
  384. while (j != search_end)
  385.   if (*i++ != *j++) goto skip;
  386. return (int) (str-Ptr) -1;
  387.       }
  388.     }
  389.   }
  390.   return -1;
  391. }
  392. /*
  393.   Search after a string without regarding to case
  394.   This needs to be replaced when we have character sets per string
  395. */
  396. int String::strstr_case(const String &s,uint32 offset)
  397. {
  398.   if (s.length()+offset <= str_length)
  399.   {
  400.     if (!s.length())
  401.       return ((int) offset); // Empty string is always found
  402.     register const char *str = Ptr+offset;
  403.     register const char *search=s.ptr();
  404.     const char *end=Ptr+str_length-s.length()+1;
  405.     const char *search_end=s.ptr()+s.length();
  406. skip:
  407.     while (str != end)
  408.     {
  409.       if (str_charset->sort_order[*str++] == str_charset->sort_order[*search])
  410.       {
  411. register char *i,*j;
  412. i=(char*) str; j=(char*) search+1;
  413. while (j != search_end)
  414.   if (str_charset->sort_order[*i++] != 
  415.               str_charset->sort_order[*j++]) 
  416.             goto skip;
  417. return (int) (str-Ptr) -1;
  418.       }
  419.     }
  420.   }
  421.   return -1;
  422. }
  423. /*
  424. ** Search string from end. Offset is offset to the end of string
  425. */
  426. int String::strrstr(const String &s,uint32 offset)
  427. {
  428.   if (s.length() <= offset && offset <= str_length)
  429.   {
  430.     if (!s.length())
  431.       return offset; // Empty string is always found
  432.     register const char *str = Ptr+offset-1;
  433.     register const char *search=s.ptr()+s.length()-1;
  434.     const char *end=Ptr+s.length()-2;
  435.     const char *search_end=s.ptr()-1;
  436. skip:
  437.     while (str != end)
  438.     {
  439.       if (*str-- == *search)
  440.       {
  441. register char *i,*j;
  442. i=(char*) str; j=(char*) search-1;
  443. while (j != search_end)
  444.   if (*i-- != *j--) goto skip;
  445. return (int) (i-Ptr) +1;
  446.       }
  447.     }
  448.   }
  449.   return -1;
  450. }
  451. /*
  452. ** replace substring with string
  453. ** If wrong parameter or not enough memory, do nothing
  454. */
  455. bool String::replace(uint32 offset,uint32 arg_length,const String &to)
  456. {
  457.   long diff = (long) to.length()-(long) arg_length;
  458.   if (offset+arg_length <= str_length)
  459.   {
  460.     if (diff < 0)
  461.     {
  462.       if (to.length())
  463. memcpy(Ptr+offset,to.ptr(),to.length());
  464.       bmove(Ptr+offset+to.length(),Ptr+offset+arg_length,
  465.     str_length-offset-arg_length);
  466.     }
  467.     else
  468.     {
  469.       if (diff)
  470.       {
  471. if (realloc(str_length+(uint32) diff))
  472.   return TRUE;
  473. bmove_upp(Ptr+str_length+diff,Ptr+str_length,
  474.   str_length-offset-arg_length);
  475.       }
  476.       if (to.length())
  477. memcpy(Ptr+offset,to.ptr(),to.length());
  478.     }
  479.     str_length+=(uint32) diff;
  480.   }
  481.   return FALSE;
  482. }
  483. // added by Holyfoot for "geometry" needs
  484. int String::reserve(uint32 space_needed, uint32 grow_by)
  485. {
  486.   if (Alloced_length < str_length + space_needed)
  487.   {
  488.     if (realloc(Alloced_length + max(space_needed, grow_by) - 1))
  489.       return TRUE;
  490.   }
  491.   return FALSE;
  492. }
  493. void String::qs_append(const char *str)
  494. {
  495.   int len = (int)strlen(str);
  496.   memcpy(Ptr + str_length, str, len + 1);
  497.   str_length += len;
  498. }
  499. void String::qs_append(double d)
  500. {
  501.   char *buff = Ptr + str_length;
  502.   sprintf(buff,"%.14g", d);
  503.   str_length += (int)strlen(buff);
  504. }
  505. void String::qs_append(double *d)
  506. {
  507.   double ld;
  508.   float8get(ld, (char*) d);
  509.   qs_append(ld);
  510. }
  511. void String::qs_append(const char &c)
  512. {
  513.   Ptr[str_length] = c;
  514.   str_length += sizeof(c);
  515. }
  516. int sortcmp(const String *x,const String *y)
  517. {
  518.   const char *s= x->ptr();
  519.   const char *t= y->ptr();
  520.   uint32 x_len=x->length(),y_len=y->length(),len=min(x_len,y_len);
  521.   if (use_strnxfrm(x->str_charset))
  522.   {
  523. #ifndef CMP_ENDSPACE
  524.     while (x_len && my_isspace(x->str_charset,s[x_len-1]))
  525.       x_len--;
  526.     while (y_len && my_isspace(x->str_charset,t[y_len-1]))
  527.       y_len--;
  528. #endif
  529.     return my_strnncoll(x->str_charset,
  530.                         (unsigned char *)s,x_len,(unsigned char *)t,y_len);
  531.   }
  532.   else
  533.   {
  534.     x_len-=len; // For easy end space test
  535.     y_len-=len;
  536.     if (x->str_charset->sort_order)
  537.     {
  538.       while (len--)
  539.       {
  540.         if (x->str_charset->sort_order[(uchar) *s++] != 
  541.           x->str_charset->sort_order[(uchar) *t++])
  542.             return ((int) x->str_charset->sort_order[(uchar) s[-1]] -
  543.                   (int) x->str_charset->sort_order[(uchar) t[-1]]);
  544.       }
  545.     }
  546.     else
  547.     {
  548.       while (len--)
  549.       {
  550.         if (*s++ != *t++)
  551.             return ((int) s[-1] - (int) t[-1]);
  552.       }
  553.     }
  554. #ifndef CMP_ENDSPACE
  555.     /* Don't compare end space in strings */
  556.     {
  557.       if (y_len)
  558.       {
  559.         const char *end=t+y_len;
  560.         for (; t != end ; t++)
  561.           if (!my_isspace(x->str_charset,*t))
  562.             return -1;
  563.       }
  564.       else
  565.       {
  566.         const char *end=s+x_len;
  567.         for (; s != end ; s++)
  568.           if (!my_isspace(x->str_charset,*s))
  569.             return 1;
  570.       }
  571.       return 0;
  572.     }
  573. #else
  574.     return (int) (x_len-y_len);
  575. #endif /* CMP_ENDSPACE */
  576.   }
  577. }
  578. int stringcmp(const String *x,const String *y)
  579. {
  580.   const char *s= x->ptr();
  581.   const char *t= y->ptr();
  582.   uint32 x_len=x->length(),y_len=y->length(),len=min(x_len,y_len);
  583.   while (len--)
  584.   {
  585.     if (*s++ != *t++)
  586.       return ((int) (uchar) s[-1] - (int) (uchar) t[-1]);
  587.   }
  588.   return (int) (x_len-y_len);
  589. }
  590. String *copy_if_not_alloced(String *to,String *from,uint32 from_length)
  591. {
  592.   if (from->Alloced_length >= from_length)
  593.     return from;
  594.   if (from->alloced || !to || from == to)
  595.   {
  596.     (void) from->realloc(from_length);
  597.     return from;
  598.   }
  599.   if (to->realloc(from_length))
  600.     return from; // Actually an error
  601.   if ((to->str_length=min(from->str_length,from_length)))
  602.     memcpy(to->Ptr,from->Ptr,to->str_length);
  603.   to->str_charset=from->str_charset;
  604.   return to;
  605. }