home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 January / Chip_2001-01_cd1.bin / tema / mysql / mysql-3.23.28g-win-source.exe / sql / sql_string.cpp < prev    next >
C/C++ Source or Header  |  2000-11-21  |  17KB  |  755 lines

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