sql_string.cc
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:17k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.    
  3.    This program file is free software; you can redistribute it and/or
  4.    modify it under the terms of the GNU Library General Public
  5.    License as published by the Free Software Foundation; either
  6.    version 2 of the License, or (at your option) any later version.
  7.    
  8.    This library is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11.    Library General Public License for more details.
  12.    
  13.    You should have received a copy of the GNU Library General Public
  14.    License along with this library; if not, write to the Free
  15.    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  16.    MA 02111-1307, USA */
  17. /* This file is originally from the mysql distribution. Coded by monty */
  18. #ifdef __GNUC__
  19. #pragma implementation // gcc: Class implementation
  20. #endif
  21. #include <global.h>
  22. #include <my_sys.h>
  23. #include <m_string.h>
  24. #include <m_ctype.h>
  25. #ifdef HAVE_FCONVERT
  26. #include <floatingpoint.h>
  27. #endif
  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.   if (Alloced_length < arg_length)
  38.   {
  39.     free();
  40.     if (!(Ptr=(char*) my_malloc(arg_length,MYF(MY_WME))))
  41.     {
  42.       str_length=0;
  43.       return TRUE;
  44.     }
  45.     Alloced_length=arg_length;
  46.     alloced=1;
  47.   }
  48.   Ptr[0]=0;
  49.   str_length=0;
  50.   return FALSE;
  51. }
  52. /*
  53. ** Check that string is big enough. Set string[alloc_length] to 0
  54. ** (for C functions)
  55. */
  56. bool String::realloc(uint32 alloc_length)
  57. {
  58.   uint32 len=ALIGN_SIZE(alloc_length+1);
  59.   if (Alloced_length < len)
  60.   {
  61.     char *new_ptr;
  62.     if (alloced)
  63.     {
  64.       if ((new_ptr= (char*) my_realloc(Ptr,len,MYF(MY_WME))))
  65.       {
  66. Ptr=new_ptr;
  67. Alloced_length=len;
  68.       }
  69.       else
  70. return TRUE; // Signal error
  71.     }
  72.     else if ((new_ptr= (char*) my_malloc(len,MYF(MY_WME))))
  73.     {
  74.       if (str_length) // Avoid bugs in memcpy on AIX
  75. memcpy(new_ptr,Ptr,str_length);
  76.       new_ptr[str_length]=0;
  77.       Ptr=new_ptr;
  78.       Alloced_length=len;
  79.       alloced=1;
  80.     }
  81.     else
  82.       return TRUE; // Signal error
  83.   }
  84.   Ptr[alloc_length]=0; // This make other funcs shorter
  85.   return FALSE;
  86. }
  87. bool String::set(longlong num)
  88. {
  89.   if (alloc(21))
  90.     return TRUE;
  91.   str_length=(uint32) (longlong10_to_str(num,Ptr,-10)-Ptr);
  92.   return FALSE;
  93. }
  94. bool String::set(ulonglong num)
  95. {
  96.   if (alloc(21))
  97.     return TRUE;
  98.   str_length=(uint32) (longlong10_to_str(num,Ptr,10)-Ptr);
  99.   return FALSE;
  100. }
  101. bool String::set(double num,uint decimals)
  102. {
  103.   char buff[331];
  104.   if (decimals >= NOT_FIXED_DEC)
  105.   {
  106.     sprintf(buff,"%.14g",num); // Enough for a DATETIME
  107.     return copy(buff, (uint32) strlen(buff));
  108.   }
  109. #ifdef HAVE_FCONVERT
  110.   int decpt,sign;
  111.   char *pos,*to;
  112.   VOID(fconvert(num,(int) decimals,&decpt,&sign,buff+1));
  113.   if (!isdigit(buff[1]))
  114.   { // Nan or Inf
  115.     pos=buff+1;
  116.     if (sign)
  117.     {
  118.       buff[0]='-';
  119.       pos=buff;
  120.     }
  121.     return copy(pos,(uint32) strlen(pos));
  122.   }
  123.   if (alloc((uint32) ((uint32) decpt+3+decimals)))
  124.     return TRUE;
  125.   to=Ptr;
  126.   if (sign)
  127.     *to++='-';
  128.   pos=buff+1;
  129.   if (decpt < 0)
  130.   { /* value is < 0 */
  131.     *to++='0';
  132.     if (!decimals)
  133.       goto end;
  134.     *to++='.';
  135.     if ((uint32) -decpt > decimals)
  136.       decpt= - (int) decimals;
  137.     decimals=(uint32) ((int) decimals+decpt);
  138.     while (decpt++ < 0)
  139.       *to++='0';
  140.   }
  141.   else if (decpt == 0)
  142.   {
  143.     *to++= '0';
  144.     if (!decimals)
  145.       goto end;
  146.     *to++='.';
  147.   }
  148.   else
  149.   {
  150.     while (decpt-- > 0)
  151.       *to++= *pos++;
  152.     if (!decimals)
  153.       goto end;
  154.     *to++='.';
  155.   }
  156.   while (decimals--)
  157.     *to++= *pos++;
  158. end:
  159.   *to=0;
  160.   str_length=(uint32) (to-Ptr);
  161.   return FALSE;
  162. #else
  163. #ifdef HAVE_SNPRINTF
  164.   buff[sizeof(buff)-1]=0; // Safety
  165.   snprintf(buff,sizeof(buff)-1, "%.*f",(int) decimals,num);
  166. #else
  167.   sprintf(buff,"%.*f",(int) decimals,num);
  168. #endif
  169.   return copy(buff,(uint32) strlen(buff));
  170. #endif
  171. }
  172. bool String::copy()
  173. {
  174.   if (!alloced)
  175.   {
  176.     Alloced_length=0; // Force realloc
  177.     return realloc(str_length);
  178.   }
  179.   return FALSE;
  180. }
  181. bool String::copy(const String &str)
  182. {
  183.   if (alloc(str.str_length))
  184.     return TRUE;
  185.   str_length=str.str_length;
  186.   bmove(Ptr,str.Ptr,str_length); // May be overlapping
  187.   Ptr[str_length]=0;
  188.   return FALSE;
  189. }
  190. bool String::copy(const char *str,uint32 arg_length)
  191. {
  192.   if (alloc(arg_length))
  193.     return TRUE;
  194.   if ((str_length=arg_length))
  195.     memcpy(Ptr,str,arg_length);
  196.   Ptr[arg_length]=0;
  197.   return FALSE;
  198. }
  199. /* This is used by mysql.cc */
  200. bool String::fill(uint32 max_length,char fill_char)
  201. {
  202.   if (str_length > max_length)
  203.     Ptr[str_length=max_length]=0;
  204.   else
  205.   {
  206.     if (realloc(max_length))
  207.       return TRUE;
  208.     bfill(Ptr+str_length,max_length-str_length,fill_char);
  209.     str_length=max_length;
  210.   }
  211.   return FALSE;
  212. }
  213. void String::strip_sp()
  214. {
  215.    while (str_length && isspace(Ptr[str_length-1]))
  216.     str_length--;
  217. }
  218. bool String::append(const String &s)
  219. {
  220.   if (s.length())
  221.   {
  222.     if (realloc(str_length+s.length()))
  223.       return TRUE;
  224.     memcpy(Ptr+str_length,s.ptr(),s.length());
  225.     str_length+=s.length();
  226.   }
  227.   return FALSE;
  228. }
  229. bool String::append(const char *s,uint32 arg_length)
  230. {
  231.   if (!arg_length) // Default argument
  232.     if (!(arg_length= (uint32) strlen(s)))
  233.       return FALSE;
  234.   if (realloc(str_length+arg_length))
  235.     return TRUE;
  236.   memcpy(Ptr+str_length,s,arg_length);
  237.   str_length+=arg_length;
  238.   return FALSE;
  239. }
  240. #ifdef TO_BE_REMOVED
  241. bool String::append(FILE* file, uint32 arg_length, myf my_flags)
  242. {
  243.   if (realloc(str_length+arg_length))
  244.     return TRUE;
  245.   if (my_fread(file, (byte*) Ptr + str_length, arg_length, my_flags))
  246.   {
  247.     shrink(str_length);
  248.     return TRUE;
  249.   }
  250.   str_length+=arg_length;
  251.   return FALSE;
  252. }
  253. #endif
  254. bool String::append(IO_CACHE* file, uint32 arg_length)
  255. {
  256.   if (realloc(str_length+arg_length))
  257.     return TRUE;
  258.   if (my_b_read(file, (byte*) Ptr + str_length, arg_length))
  259.   {
  260.     shrink(str_length);
  261.     return TRUE;
  262.   }
  263.   str_length+=arg_length;
  264.   return FALSE;
  265. }
  266. uint32 String::numchars()
  267. {
  268. #ifdef USE_MB
  269.   register uint32 n=0,mblen;
  270.   register const char *mbstr=Ptr;
  271.   register const char *end=mbstr+str_length;
  272.   if (use_mb(default_charset_info))
  273.   {
  274.     while (mbstr < end) {
  275.         if ((mblen=my_ismbchar(default_charset_info, mbstr,end))) mbstr+=mblen;
  276.         else ++mbstr;
  277.         ++n;
  278.     }
  279.     return n;
  280.   }
  281.   else
  282. #endif
  283.     return str_length;
  284. }
  285. int String::charpos(int i,uint32 offset)
  286. {
  287. #ifdef USE_MB
  288.   register uint32 mblen;
  289.   register const char *mbstr=Ptr+offset;
  290.   register const char *end=Ptr+str_length;
  291.   if (use_mb(default_charset_info))
  292.   {
  293.     if (i<=0) return i;
  294.     while (i && mbstr < end) {
  295.        if ((mblen=my_ismbchar(default_charset_info, mbstr,end))) mbstr+=mblen;
  296.        else ++mbstr;
  297.        --i;
  298.     }
  299.     if ( INT_MAX32-i <= (int) (mbstr-Ptr-offset)) 
  300.       return INT_MAX32;
  301.     else 
  302.       return (int) ((mbstr-Ptr-offset)+i);
  303.   }
  304.   else
  305. #endif
  306.     return i;
  307. }
  308. int String::strstr(const String &s,uint32 offset)
  309. {
  310.   if (s.length()+offset <= str_length)
  311.   {
  312.     if (!s.length())
  313.       return ((int) offset); // Empty string is always found
  314.     register const char *str = Ptr+offset;
  315.     register const char *search=s.ptr();
  316.     const char *end=Ptr+str_length-s.length()+1;
  317.     const char *search_end=s.ptr()+s.length();
  318. skipp:
  319.     while (str != end)
  320.     {
  321.       if (*str++ == *search)
  322.       {
  323. register char *i,*j;
  324. i=(char*) str; j=(char*) search+1;
  325. while (j != search_end)
  326.   if (*i++ != *j++) goto skipp;
  327. return (int) (str-Ptr) -1;
  328.       }
  329.     }
  330.   }
  331.   return -1;
  332. }
  333. /*
  334. ** Search string from end. Offset is offset to the end of string
  335. */
  336. int String::strrstr(const String &s,uint32 offset)
  337. {
  338.   if (s.length() <= offset && offset <= str_length)
  339.   {
  340.     if (!s.length())
  341.       return offset; // Empty string is always found
  342.     register const char *str = Ptr+offset-1;
  343.     register const char *search=s.ptr()+s.length()-1;
  344.     const char *end=Ptr+s.length()-2;
  345.     const char *search_end=s.ptr()-1;
  346. skipp:
  347.     while (str != end)
  348.     {
  349.       if (*str-- == *search)
  350.       {
  351. register char *i,*j;
  352. i=(char*) str; j=(char*) search-1;
  353. while (j != search_end)
  354.   if (*i-- != *j--) goto skipp;
  355. return (int) (i-Ptr) +1;
  356.       }
  357.     }
  358.   }
  359.   return -1;
  360. }
  361. /*
  362. ** replace substring with string
  363. ** If wrong parameter or not enough memory, do nothing
  364. */
  365. bool String::replace(uint32 offset,uint32 arg_length,const String &to)
  366. {
  367.   long diff = (long) to.length()-(long) arg_length;
  368.   if (offset+arg_length <= str_length)
  369.   {
  370.     if (diff < 0)
  371.     {
  372.       if (to.length())
  373. memcpy(Ptr+offset,to.ptr(),to.length());
  374.       bmove(Ptr+offset+to.length(),Ptr+offset+arg_length,
  375.     str_length-offset-arg_length);
  376.     }
  377.     else
  378.     {
  379.       if (diff)
  380.       {
  381. if (realloc(str_length+(uint32) diff))
  382.   return TRUE;
  383. bmove_upp(Ptr+str_length+diff,Ptr+str_length,
  384.   str_length-offset-arg_length);
  385.       }
  386.       if (to.length())
  387. memcpy(Ptr+offset,to.ptr(),to.length());
  388.     }
  389.     str_length+=(uint32) diff;
  390.   }
  391.   return FALSE;
  392. }
  393. int sortcmp(const String *x,const String *y)
  394. {
  395.   const char *s= x->ptr();
  396.   const char *t= y->ptr();
  397.   uint32 x_len=x->length(),y_len=y->length(),len=min(x_len,y_len);
  398. #ifdef USE_STRCOLL
  399.   if (use_strcoll(default_charset_info))
  400.   {
  401. #ifndef CMP_ENDSPACE
  402.     while (x_len && isspace(s[x_len-1]))
  403.       x_len--;
  404.     while (y_len && isspace(t[y_len-1]))
  405.       y_len--;
  406. #endif
  407.     return my_strnncoll(default_charset_info,
  408.                         (unsigned char *)s,x_len,(unsigned char *)t,y_len);
  409.   }
  410.   else
  411.   {
  412. #endif /* USE_STRCOLL */
  413.     x_len-=len; // For easy end space test
  414.     y_len-=len;
  415.     while (len--)
  416.     {
  417.       if (my_sort_order[(uchar) *s++] != my_sort_order[(uchar) *t++])
  418.         return ((int) my_sort_order[(uchar) s[-1]] -
  419.                 (int) my_sort_order[(uchar) t[-1]]);
  420.     }
  421. #ifndef CMP_ENDSPACE
  422.     /* Don't compare end space in strings */
  423.     {
  424.       if (y_len)
  425.       {
  426.         const char *end=t+y_len;
  427.         for (; t != end ; t++)
  428.           if (!isspace(*t))
  429.             return -1;
  430.       }
  431.       else
  432.       {
  433.         const char *end=s+x_len;
  434.         for (; s != end ; s++)
  435.           if (!isspace(*s))
  436.             return 1;
  437.       }
  438.       return 0;
  439.     }
  440. #else
  441.     return (int) (x_len-y_len);
  442. #endif /* CMP_ENDSPACE */
  443. #ifdef USE_STRCOLL
  444.   }
  445. #endif
  446. }
  447. int stringcmp(const String *x,const String *y)
  448. {
  449.   const char *s= x->ptr();
  450.   const char *t= y->ptr();
  451.   uint32 x_len=x->length(),y_len=y->length(),len=min(x_len,y_len);
  452.   while (len--)
  453.   {
  454.     if (*s++ != *t++)
  455.       return ((int) (uchar) s[-1] - (int) (uchar) t[-1]);
  456.   }
  457.   return (int) (x_len-y_len);
  458. }
  459. String *copy_if_not_alloced(String *to,String *from,uint32 from_length)
  460. {
  461.   if (from->Alloced_length >= from_length)
  462.     return from;
  463.   if (from->alloced || !to || from == to)
  464.   {
  465.     (void) from->realloc(from_length);
  466.     return from;
  467.   }
  468.   if (to->realloc(from_length))
  469.     return from; // Actually an error
  470.   if ((to->str_length=min(from->str_length,from_length)))
  471.     memcpy(to->Ptr,from->Ptr,to->str_length);
  472.   return to;
  473. }
  474. /* Make it easier to handle different charactersets */
  475. #ifdef USE_MB
  476. #define INC_PTR(A,B) A+=((use_mb_flag && 
  477.                           my_ismbchar(default_charset_info,A,B)) ? 
  478.                           my_ismbchar(default_charset_info,A,B) : 1)
  479. #else
  480. #define INC_PTR(A,B) A++
  481. #endif
  482. /*
  483. ** Compare string against string with wildcard
  484. ** 0 if matched
  485. ** -1 if not matched with wildcard
  486. **  1 if matched with wildcard
  487. */
  488. #ifdef LIKE_CMP_TOUPPER
  489. #define likeconv(A) (uchar) toupper(A)
  490. #else
  491. #define likeconv(A) (uchar) my_sort_order[(uchar) (A)]
  492. #endif
  493. static int wild_case_compare(const char *str,const char *str_end,
  494.      const char *wildstr,const char *wildend,
  495.      char escape)
  496. {
  497.   int result= -1; // Not found, using wildcards
  498. #ifdef USE_MB
  499.   bool use_mb_flag=use_mb(default_charset_info);
  500. #endif
  501.   while (wildstr != wildend)
  502.   {
  503.     while (*wildstr != wild_many && *wildstr != wild_one)
  504.     {
  505.       if (*wildstr == escape && wildstr+1 != wildend)
  506. wildstr++;
  507. #ifdef USE_MB
  508.       int l;
  509.       if (use_mb_flag &&
  510.           (l = my_ismbchar(default_charset_info, wildstr, wildend)))
  511.       {
  512.   if (str+l > str_end || memcmp(str, wildstr, l) != 0)
  513.       return 1;
  514.   str += l;
  515.   wildstr += l;
  516.       }
  517.       else
  518. #endif
  519.       if (str == str_end || likeconv(*wildstr++) != likeconv(*str++))
  520. return(1); // No match
  521.       if (wildstr == wildend)
  522. return (str != str_end); // Match if both are at end
  523.       result=1; // Found an anchor char
  524.     }
  525.     if (*wildstr == wild_one)
  526.     {
  527.       do
  528.       {
  529. if (str == str_end) // Skipp one char if possible
  530.   return (result);
  531. INC_PTR(str,str_end);
  532.       } while (++wildstr < wildend && *wildstr == wild_one);
  533.       if (wildstr == wildend)
  534. break;
  535.     }
  536.     if (*wildstr == wild_many)
  537.     { // Found wild_many
  538.       wildstr++;
  539.       /* Remove any '%' and '_' from the wild search string */
  540.       for ( ; wildstr != wildend ; wildstr++)
  541.       {
  542. if (*wildstr == wild_many)
  543.   continue;
  544. if (*wildstr == wild_one)
  545. {
  546.   if (str == str_end)
  547.     return (-1);
  548.   INC_PTR(str,str_end);
  549.   continue;
  550. }
  551. break; // Not a wild character
  552.       }
  553.       if (wildstr == wildend)
  554. return(0); // Ok if wild_many is last
  555.       if (str == str_end)
  556. return -1;
  557.       uchar cmp;
  558.       if ((cmp= *wildstr) == escape && wildstr+1 != wildend)
  559. cmp= *++wildstr;
  560. #ifdef USE_MB
  561.       const char* mb = wildstr;
  562.       int mblen;
  563.       LINT_INIT(mblen);
  564.       if (use_mb_flag)
  565.         mblen = my_ismbchar(default_charset_info, wildstr, wildend);
  566. #endif
  567.       INC_PTR(wildstr,wildend); // This is compared trough cmp
  568.       cmp=likeconv(cmp);   
  569.       do
  570.       {
  571. #ifdef USE_MB
  572.         if (use_mb_flag)
  573. {
  574.           for (;;)
  575.           {
  576.             if (str >= str_end)
  577.               return -1;
  578.             if (mblen)
  579.             {
  580.               if (str+mblen <= str_end && memcmp(str, mb, mblen) == 0)
  581.               {
  582.                 str += mblen;
  583.                 break;
  584.               }
  585.             }
  586.             else if (!my_ismbchar(default_charset_info, str, str_end) &&
  587.                      likeconv(*str) == cmp)
  588.             {
  589.               str++;
  590.               break;
  591.             }
  592.             INC_PTR(str, str_end);
  593.           }
  594. }
  595.         else
  596.         {
  597. #endif /* USE_MB */
  598.           while (str != str_end && likeconv(*str) != cmp)
  599.             str++;
  600.           if (str++ == str_end) return (-1);
  601. #ifdef USE_MB
  602.         }
  603. #endif
  604. {
  605.   int tmp=wild_case_compare(str,str_end,wildstr,wildend,escape);
  606.   if (tmp <= 0)
  607.     return (tmp);
  608. }
  609.       } while (str != str_end && wildstr[0] != wild_many);
  610.       return(-1);
  611.     }
  612.   }
  613.   return (str != str_end ? 1 : 0);
  614. }
  615. int wild_case_compare(String &match,String &wild, char escape)
  616. {
  617.   return wild_case_compare(match.ptr(),match.ptr()+match.length(),
  618.    wild.ptr(), wild.ptr()+wild.length(),escape);
  619. }
  620. /*
  621. ** The following is used when using LIKE on binary strings
  622. */
  623. static int wild_compare(const char *str,const char *str_end,
  624. const char *wildstr,const char *wildend,char escape)
  625. {
  626.   int result= -1; // Not found, using wildcards
  627.   while (wildstr != wildend)
  628.   {
  629.     while (*wildstr != wild_many && *wildstr != wild_one)
  630.     {
  631.       if (*wildstr == escape && wildstr+1 != wildend)
  632. wildstr++;
  633.       if (str == str_end || *wildstr++ != *str++)
  634. return(1);
  635.       if (wildstr == wildend)
  636. return (str != str_end); // Match if both are at end
  637.       result=1; // Found an anchor char
  638.     }
  639.     if (*wildstr == wild_one)
  640.     {
  641.       do
  642.       {
  643. if (str == str_end) // Skipp one char if possible
  644.   return (result);
  645. str++;
  646.       } while (*++wildstr == wild_one && wildstr != wildend);
  647.       if (wildstr == wildend)
  648. break;
  649.     }
  650.     if (*wildstr == wild_many)
  651.     { // Found wild_many
  652.       wildstr++;
  653.       /* Remove any '%' and '_' from the wild search string */
  654.       for ( ; wildstr != wildend ; wildstr++)
  655.       {
  656. if (*wildstr == wild_many)
  657.   continue;
  658. if (*wildstr == wild_one)
  659. {
  660.   if (str == str_end)
  661.     return (-1);
  662.   str++;
  663.   continue;
  664. }
  665. break; // Not a wild character
  666.       }
  667.       if (wildstr == wildend)
  668. return(0); // Ok if wild_many is last
  669.       if (str == str_end)
  670. return -1;
  671.       char cmp;
  672.       if ((cmp= *wildstr) == escape && wildstr+1 != wildend)
  673. cmp= *++wildstr;
  674.       wildstr++; // This is compared trough cmp
  675.       do
  676.       {
  677. while (str != str_end && *str != cmp)
  678.   str++;
  679. if (str++ == str_end) return (-1);
  680. {
  681.   int tmp=wild_compare(str,str_end,wildstr,wildend,escape);
  682.   if (tmp <= 0)
  683.     return (tmp);
  684. }
  685.       } while (str != str_end && wildstr[0] != wild_many);
  686.       return(-1);
  687.     }
  688.   }
  689.   return (str != str_end ? 1 : 0);
  690. }
  691. int wild_compare(String &match,String &wild, char escape)
  692. {
  693.   return wild_compare(match.ptr(),match.ptr()+match.length(),
  694.       wild.ptr(), wild.ptr()+wild.length(),escape);
  695. }