ctype-mb.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:26k
源码类别:

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. #include <my_global.h>
  14. #include "m_ctype.h"
  15. #include "m_string.h"
  16. #ifdef USE_MB
  17. void my_caseup_str_mb(CHARSET_INFO * cs, char *str)
  18. {
  19.   register uint32 l;
  20.   register char *end=str+strlen(str); /* BAR TODO: remove strlen() call */
  21.   register uchar *map=cs->to_upper;
  22.   
  23.   while (*str)
  24.   {
  25.     if ((l=my_ismbchar(cs, str,end)))
  26.       str+=l;
  27.     else
  28.     { 
  29.       *str=(char) map[(uchar)*str];
  30.       str++;
  31.     }
  32.   }
  33. }
  34. void my_casedn_str_mb(CHARSET_INFO * cs, char *str)
  35. {
  36.   register uint32 l;
  37.   register char *end=str+strlen(str);
  38.   register uchar *map=cs->to_lower;
  39.   
  40.   while (*str)
  41.   {
  42.     if ((l=my_ismbchar(cs, str,end)))
  43.       str+=l;
  44.     else
  45.     {
  46.       *str=(char) map[(uchar)*str];
  47.       str++;
  48.     }
  49.   }
  50. }
  51. void my_caseup_mb(CHARSET_INFO * cs, char *str, uint length)
  52. {
  53.   register uint32 l;
  54.   register char *end=str+length;
  55.   register uchar *map=cs->to_upper;
  56.   
  57.   while (str<end)
  58.   {
  59.     if ((l=my_ismbchar(cs, str,end)))
  60.       str+=l;
  61.     else 
  62.     {
  63.       *str=(char) map[(uchar)*str];
  64.       str++;
  65.     }
  66.   }
  67. }
  68. void my_casedn_mb(CHARSET_INFO * cs, char *str, uint length)
  69. {
  70.   register uint32 l;
  71.   register char *end=str+length;
  72.   register uchar *map=cs->to_lower;
  73.   
  74.   while (str<end)
  75.   {
  76.     if ((l=my_ismbchar(cs, str,end)))
  77.       str+=l;
  78.     else
  79.     {
  80.       *str=(char) map[(uchar)*str];
  81.       str++;
  82.     }
  83.   }
  84. }
  85. int my_strcasecmp_mb(CHARSET_INFO * cs,const char *s, const char *t)
  86. {
  87.   register uint32 l;
  88.   register const char *end=s+strlen(s);
  89.   register uchar *map=cs->to_upper;
  90.   
  91.   while (s<end)
  92.   {
  93.     if ((l=my_ismbchar(cs, s,end)))
  94.     {
  95.       while (l--)
  96.         if (*s++ != *t++) 
  97.           return 1;
  98.     }
  99.     else if (my_mbcharlen(cs, *t) > 1)
  100.       return 1;
  101.     else if (map[(uchar) *s++] != map[(uchar) *t++])
  102.       return 1;
  103.   }
  104.   return *t;
  105. }
  106. /*
  107. ** Compare string against string with wildcard
  108. ** 0 if matched
  109. ** -1 if not matched with wildcard
  110. **  1 if matched with wildcard
  111. */
  112. #define INC_PTR(cs,A,B) A+=(my_ismbchar(cs,A,B) ? my_ismbchar(cs,A,B) : 1)
  113. #define likeconv(s,A) (uchar) (s)->sort_order[(uchar) (A)]
  114. int my_wildcmp_mb(CHARSET_INFO *cs,
  115.   const char *str,const char *str_end,
  116.   const char *wildstr,const char *wildend,
  117.   int escape, int w_one, int w_many)
  118. {
  119.   int result= -1; /* Not found, using wildcards */
  120.   while (wildstr != wildend)
  121.   {
  122.     while (*wildstr != w_many && *wildstr != w_one)
  123.     {
  124.       int l;
  125.       if (*wildstr == escape && wildstr+1 != wildend)
  126. wildstr++;
  127.       if ((l = my_ismbchar(cs, wildstr, wildend)))
  128.       {
  129.   if (str+l > str_end || memcmp(str, wildstr, l) != 0)
  130.       return 1;
  131.   str += l;
  132.   wildstr += l;
  133.       }
  134.       else
  135.       if (str == str_end || likeconv(cs,*wildstr++) != likeconv(cs,*str++))
  136. return(1); /* No match */
  137.       if (wildstr == wildend)
  138. return (str != str_end); /* Match if both are at end */
  139.       result=1; /* Found an anchor char */
  140.     }
  141.     if (*wildstr == w_one)
  142.     {
  143.       do
  144.       {
  145. if (str == str_end) /* Skip one char if possible */
  146.   return (result);
  147. INC_PTR(cs,str,str_end);
  148.       } while (++wildstr < wildend && *wildstr == w_one);
  149.       if (wildstr == wildend)
  150. break;
  151.     }
  152.     if (*wildstr == w_many)
  153.     { /* Found w_many */
  154.       uchar cmp;
  155.       const char* mb = wildstr;
  156.       int mblen=0;
  157.       
  158.       wildstr++;
  159.       /* Remove any '%' and '_' from the wild search string */
  160.       for (; wildstr != wildend ; wildstr++)
  161.       {
  162. if (*wildstr == w_many)
  163.   continue;
  164. if (*wildstr == w_one)
  165. {
  166.   if (str == str_end)
  167.     return (-1);
  168.   INC_PTR(cs,str,str_end);
  169.   continue;
  170. }
  171. break; /* Not a wild character */
  172.       }
  173.       if (wildstr == wildend)
  174. return(0); /* Ok if w_many is last */
  175.       if (str == str_end)
  176. return -1;
  177.       
  178.       if ((cmp= *wildstr) == escape && wildstr+1 != wildend)
  179. cmp= *++wildstr;
  180.       mb=wildstr;
  181.       mblen= my_ismbchar(cs, wildstr, wildend);
  182.       INC_PTR(cs,wildstr,wildend); /* This is compared trough cmp */
  183.       cmp=likeconv(cs,cmp);   
  184.       do
  185.       {
  186.         for (;;)
  187.         {
  188.           if (str >= str_end)
  189.             return -1;
  190.           if (mblen)
  191.           {
  192.             if (str+mblen <= str_end && memcmp(str, mb, mblen) == 0)
  193.             {
  194.               str += mblen;
  195.               break;
  196.             }
  197.           }
  198.           else if (!my_ismbchar(cs, str, str_end) &&
  199.                    likeconv(cs,*str) == cmp)
  200.           {
  201.             str++;
  202.             break;
  203.           }
  204.           INC_PTR(cs,str, str_end);
  205.         }
  206. {
  207.   int tmp=my_wildcmp_mb(cs,str,str_end,wildstr,wildend,escape,w_one,
  208.                                 w_many);
  209.   if (tmp <= 0)
  210.     return (tmp);
  211. }
  212.       } while (str != str_end && wildstr[0] != w_many);
  213.       return(-1);
  214.     }
  215.   }
  216.   return (str != str_end ? 1 : 0);
  217. }
  218. uint my_numchars_mb(CHARSET_INFO *cs __attribute__((unused)),
  219.       const char *pos, const char *end)
  220. {
  221.   register uint32 count=0;
  222.   while (pos < end) 
  223.   {
  224.     uint mblen;
  225.     pos+= (mblen= my_ismbchar(cs,pos,end)) ? mblen : 1;
  226.     count++;
  227.   }
  228.   return count;
  229. }
  230. uint my_charpos_mb(CHARSET_INFO *cs __attribute__((unused)),
  231.      const char *pos, const char *end, uint length)
  232. {
  233.   const char *start= pos;
  234.   
  235.   while (length && pos < end)
  236.   {
  237.     uint mblen;
  238.     pos+= (mblen= my_ismbchar(cs, pos, end)) ? mblen : 1;
  239.     length--;
  240.   }
  241.   return length ? (uint) (end + 2 - start) : (uint) (pos - start);
  242. }
  243. uint my_well_formed_len_mb(CHARSET_INFO *cs, const char *b, const char *e,
  244.                            uint pos, int *error)
  245. {
  246.   const char *b_start= b;
  247.   *error= 0;
  248.   while (pos)
  249.   {
  250.     my_wc_t wc;
  251.     int mblen;
  252.     if ((mblen= cs->cset->mb_wc(cs, &wc, (uchar*) b, (uchar*) e)) <= 0)
  253.     {
  254.       *error= b < e ? 1 : 0;
  255.       break;
  256.     }
  257.     b+= mblen;
  258.     pos--;
  259.   }
  260.   return (uint) (b - b_start);
  261. }
  262. uint my_instr_mb(CHARSET_INFO *cs,
  263.                  const char *b, uint b_length, 
  264.                  const char *s, uint s_length,
  265.                  my_match_t *match, uint nmatch)
  266. {
  267.   register const char *end, *b0;
  268.   int res= 0;
  269.   
  270.   if (s_length <= b_length)
  271.   {
  272.     if (!s_length)
  273.     {
  274.       if (nmatch)
  275.       {
  276.         match->beg= 0;
  277.         match->end= 0;
  278.         match->mblen= 0;
  279.       }
  280.       return 1; /* Empty string is always found */
  281.     }
  282.     
  283.     b0= b;
  284.     end= b+b_length-s_length+1;
  285.     
  286.     while (b < end)
  287.     {
  288.       int mblen;
  289.       
  290.       if (!cs->coll->strnncoll(cs, (unsigned char*) b,   s_length, 
  291.           (unsigned char*) s, s_length, 0))
  292.       {
  293.         if (nmatch)
  294.         {
  295.           match[0].beg= 0;
  296.           match[0].end= b-b0;
  297.           match[0].mblen= res;
  298.           if (nmatch > 1)
  299.           {
  300.             match[1].beg= match[0].end;
  301.             match[1].end= match[0].end+s_length;
  302.             match[1].mblen= 0; /* Not computed */
  303.           }
  304.         }
  305.         return 2;
  306.       }
  307.       mblen= (mblen= my_ismbchar(cs, b, end)) ? mblen : 1;
  308.       b+= mblen;
  309.       b_length-= mblen;
  310.       res++;
  311.     }
  312.   }
  313.   return 0;
  314. }
  315. /* BINARY collations handlers for MB charsets */
  316. static int my_strnncoll_mb_bin(CHARSET_INFO * cs __attribute__((unused)),
  317. const uchar *s, uint slen,
  318. const uchar *t, uint tlen,
  319.                                 my_bool t_is_prefix)
  320. {
  321.   uint len=min(slen,tlen);
  322.   int cmp= memcmp(s,t,len);
  323.   return cmp ? cmp : (int) ((t_is_prefix ? len : slen) - tlen);
  324. }
  325. /*
  326.   Compare two strings. 
  327.   
  328.   SYNOPSIS
  329.     my_strnncollsp_mb_bin()
  330.     cs Chararacter set
  331.     s String to compare
  332.     slen Length of 's'
  333.     t String to compare
  334.     tlen Length of 't'
  335.   NOTE
  336.    This function is used for character strings with binary collations.
  337.    The shorter string is extended with end space to be as long as the longer
  338.    one.
  339.   RETURN
  340.     A negative number if s < t
  341.     A positive number if s > t
  342.     0 if strings are equal
  343. */
  344. static int my_strnncollsp_mb_bin(CHARSET_INFO * cs __attribute__((unused)),
  345.                                  const uchar *a, uint a_length, 
  346.                                  const uchar *b, uint b_length)
  347. {
  348.   const uchar *end;
  349.   uint length;
  350.   
  351.   end= a + (length= min(a_length, b_length));
  352.   while (a < end)
  353.   {
  354.     if (*a++ != *b++)
  355.       return ((int) a[-1] - (int) b[-1]);
  356.   }
  357.   if (a_length != b_length)
  358.   {
  359.     int swap= 1;
  360.     /*
  361.       Check the next not space character of the longer key. If it's < ' ',
  362.       then it's smaller than the other key.
  363.     */
  364.     if (a_length < b_length)
  365.     {
  366.       /* put shorter key in s */
  367.       a_length= b_length;
  368.       a= b;
  369.       swap= -1; /* swap sign of result */
  370.     }
  371.     for (end= a + a_length-length; a < end ; a++)
  372.     {
  373.       if (*a != ' ')
  374. return (*a < ' ') ? -swap : swap;
  375.     }
  376.   }
  377.   return 0;
  378. }
  379. static int my_strnxfrm_mb_bin(CHARSET_INFO *cs __attribute__((unused)),
  380.                               uchar * dest, uint dstlen,
  381.                               const uchar *src, uint srclen)
  382. {
  383.   if (dest != src)
  384.     memcpy(dest, src, min(dstlen, srclen));
  385.   if (dstlen > srclen)
  386.     bfill(dest + srclen, dstlen - srclen, ' ');
  387.   return dstlen;
  388. }
  389. static int my_strcasecmp_mb_bin(CHARSET_INFO * cs __attribute__((unused)),
  390.       const char *s, const char *t)
  391. {
  392.   return strcmp(s,t);
  393. }
  394. static void my_hash_sort_mb_bin(CHARSET_INFO *cs __attribute__((unused)),
  395.       const uchar *key, uint len,ulong *nr1, ulong *nr2)
  396. {
  397.   const uchar *pos = key;
  398.   
  399.   key+= len;
  400.   
  401.   for (; pos < (uchar*) key ; pos++)
  402.   {
  403.     nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) * 
  404.      ((uint)*pos)) + (nr1[0] << 8);
  405.     nr2[0]+=3;
  406.   }
  407. }
  408. /* 
  409.   Write max key: create a buffer with multibyte
  410.   representation of the max_sort_char character,
  411.   and copy it into max_str in a loop. 
  412. */
  413. static void pad_max_char(CHARSET_INFO *cs, char *str, char *end)
  414. {
  415.   char buf[10];
  416.   char buflen= cs->cset->wc_mb(cs, cs->max_sort_char, (uchar*) buf,
  417.                                (uchar*) buf + sizeof(buf));
  418.   DBUG_ASSERT(buflen > 0);
  419.   do
  420.   {
  421.     if ((str + buflen) < end)
  422.     {
  423.       /* Enough space for the characer */
  424.       memcpy(str, buf, buflen);
  425.       str+= buflen;
  426.     }
  427.     else
  428.     {
  429.       /* 
  430.         There is no space for whole multibyte
  431.         character, then add trailing spaces.
  432.       */  
  433.       *str++= ' ';
  434.     }
  435.   } while (str < end);
  436. }
  437. /*
  438. ** Calculate min_str and max_str that ranges a LIKE string.
  439. ** Arguments:
  440. ** ptr Pointer to LIKE string.
  441. ** ptr_length Length of LIKE string.
  442. ** escape Escape character in LIKE.  (Normally '').
  443. ** All escape characters should be removed from min_str and max_str
  444. ** res_length Length of min_str and max_str.
  445. ** min_str Smallest case sensitive string that ranges LIKE.
  446. ** Should be space padded to res_length.
  447. ** max_str Largest case sensitive string that ranges LIKE.
  448. ** Normally padded with the biggest character sort value.
  449. **
  450. ** The function should return 0 if ok and 1 if the LIKE string can't be
  451. ** optimized !
  452. */
  453. my_bool my_like_range_mb(CHARSET_INFO *cs,
  454.  const char *ptr,uint ptr_length,
  455.  pbool escape, pbool w_one, pbool w_many,
  456.  uint res_length,
  457.  char *min_str,char *max_str,
  458.  uint *min_length,uint *max_length)
  459. {
  460.   const char *end= ptr + ptr_length;
  461.   char *min_org= min_str;
  462.   char *min_end= min_str + res_length;
  463.   char *max_end= max_str + res_length;
  464.   uint charlen= res_length / cs->mbmaxlen;
  465.   for (; ptr != end && min_str != min_end && charlen > 0 ; ptr++, charlen--)
  466.   {
  467.     if (*ptr == escape && ptr+1 != end)
  468.     {
  469.       ptr++; /* Skip escape */
  470.       *min_str++= *max_str++ = *ptr;
  471.       continue;
  472.     }
  473.     if (*ptr == w_one || *ptr == w_many) /* '_' and '%' in SQL */
  474.     {
  475.       /* Write min key  */
  476.       *min_length= (uint) (min_str - min_org);
  477.       do
  478.       {
  479. *min_str++= (char) cs->min_sort_char;
  480.       } while (min_str != min_end);
  481.       
  482.       /* 
  483.         Write max key: create a buffer with multibyte
  484.         representation of the max_sort_char character,
  485.         and copy it into max_str in a loop. 
  486.       */
  487.       *max_length= res_length;
  488.       pad_max_char(cs, max_str, max_end);
  489.       return 0;
  490.     }
  491.     *min_str++= *max_str++ = *ptr;
  492.   }
  493.   *min_length= *max_length = (uint) (min_str - min_org);
  494.   while (min_str != min_end)
  495.     *min_str++= ' '; /* Because if key compression */
  496.   pad_max_char(cs, max_str, max_end);
  497.   return 0;
  498. }
  499. static int my_wildcmp_mb_bin(CHARSET_INFO *cs,
  500.   const char *str,const char *str_end,
  501.   const char *wildstr,const char *wildend,
  502.   int escape, int w_one, int w_many)
  503. {
  504.   int result= -1; /* Not found, using wildcards */
  505.   while (wildstr != wildend)
  506.   {
  507.     while (*wildstr != w_many && *wildstr != w_one)
  508.     {
  509.       int l;
  510.       if (*wildstr == escape && wildstr+1 != wildend)
  511. wildstr++;
  512.       if ((l = my_ismbchar(cs, wildstr, wildend)))
  513.       {
  514.   if (str+l > str_end || memcmp(str, wildstr, l) != 0)
  515.       return 1;
  516.   str += l;
  517.   wildstr += l;
  518.       }
  519.       else
  520.       if (str == str_end || *wildstr++ != *str++)
  521. return(1); /* No match */
  522.       if (wildstr == wildend)
  523. return (str != str_end); /* Match if both are at end */
  524.       result=1; /* Found an anchor char */
  525.     }
  526.     if (*wildstr == w_one)
  527.     {
  528.       do
  529.       {
  530. if (str == str_end) /* Skip one char if possible */
  531.   return (result);
  532. INC_PTR(cs,str,str_end);
  533.       } while (++wildstr < wildend && *wildstr == w_one);
  534.       if (wildstr == wildend)
  535. break;
  536.     }
  537.     if (*wildstr == w_many)
  538.     { /* Found w_many */
  539.       uchar cmp;
  540.       const char* mb = wildstr;
  541.       int mblen=0;
  542.       
  543.       wildstr++;
  544.       /* Remove any '%' and '_' from the wild search string */
  545.       for (; wildstr != wildend ; wildstr++)
  546.       {
  547. if (*wildstr == w_many)
  548.   continue;
  549. if (*wildstr == w_one)
  550. {
  551.   if (str == str_end)
  552.     return (-1);
  553.   INC_PTR(cs,str,str_end);
  554.   continue;
  555. }
  556. break; /* Not a wild character */
  557.       }
  558.       if (wildstr == wildend)
  559. return(0); /* Ok if w_many is last */
  560.       if (str == str_end)
  561. return -1;
  562.       
  563.       if ((cmp= *wildstr) == escape && wildstr+1 != wildend)
  564. cmp= *++wildstr;
  565.       mb=wildstr;
  566.       mblen= my_ismbchar(cs, wildstr, wildend);
  567.       INC_PTR(cs,wildstr,wildend); /* This is compared trough cmp */
  568.       do
  569.       {
  570.         for (;;)
  571.         {
  572.           if (str >= str_end)
  573.             return -1;
  574.           if (mblen)
  575.           {
  576.             if (str+mblen <= str_end && memcmp(str, mb, mblen) == 0)
  577.             {
  578.               str += mblen;
  579.               break;
  580.             }
  581.           }
  582.           else if (!my_ismbchar(cs, str, str_end) && *str == cmp)
  583.           {
  584.             str++;
  585.             break;
  586.           }
  587.           INC_PTR(cs,str, str_end);
  588.         }
  589. {
  590.   int tmp=my_wildcmp_mb_bin(cs,str,str_end,wildstr,wildend,escape,w_one,w_many);
  591.   if (tmp <= 0)
  592.     return (tmp);
  593. }
  594.       } while (str != str_end && wildstr[0] != w_many);
  595.       return(-1);
  596.     }
  597.   }
  598.   return (str != str_end ? 1 : 0);
  599. }
  600. /*
  601.   Data was produced from EastAsianWidth.txt 
  602.   using utt11-dump utility.
  603. */
  604. static char pg11[256]=
  605. {
  606. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  607. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  608. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,
  609. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  610. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  611. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  612. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  613. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  614. };
  615. static char pg23[256]=
  616. {
  617. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  618. 0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  619. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  620. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  621. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  622. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  623. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  624. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  625. };
  626. static char pg2E[256]=
  627. {
  628. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  629. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  630. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  631. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  632. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,
  633. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  634. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  635. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0
  636. };
  637. static char pg2F[256]=
  638. {
  639. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  640. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  641. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  642. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  643. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  644. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  645. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,
  646. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0
  647. };
  648. static char pg30[256]=
  649. {
  650. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  651. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
  652. 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  653. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  654. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,
  655. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  656. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  657. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
  658. };
  659. static char pg31[256]=
  660. {
  661. 0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  662. 1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  663. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  664. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  665. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  666. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,
  667. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  668. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
  669. };
  670. static char pg32[256]=
  671. {
  672. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
  673. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  674. 1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  675. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,
  676. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  677. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  678. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  679. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0
  680. };
  681. static char pg4D[256]=
  682. {
  683. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  684. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  685. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  686. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  687. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  688. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,
  689. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  690. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  691. };
  692. static char pg9F[256]=
  693. {
  694. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  695. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  696. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  697. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  698. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  699. 1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  700. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  701. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  702. };
  703. static char pgA4[256]=
  704. {
  705. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  706. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  707. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  708. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  709. 1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  710. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  711. 1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  712. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  713. };
  714. static char pgD7[256]=
  715. {
  716. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  717. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  718. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  719. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  720. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  721. 1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  722. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  723. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  724. };
  725. static char pgFA[256]=
  726. {
  727. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  728. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  729. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  730. 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  731. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  732. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  733. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  734. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  735. };
  736. static char pgFE[256]=
  737. {
  738. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  739. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  740. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,
  741. 1,1,1,1,1,1,1,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  742. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  743. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  744. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  745. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  746. };
  747. static char pgFF[256]=
  748. {
  749. 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  750. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  751. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  752. 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  753. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  754. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  755. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  756. 1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  757. };
  758. static struct {int page; char *p;} utr11_data[256]=
  759. {
  760. {0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},
  761. {0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},
  762. {0,NULL},{0,pg11},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},
  763. {0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},
  764. {0,NULL},{0,NULL},{0,NULL},{0,pg23},{0,NULL},{0,NULL},{0,NULL},{0,NULL},
  765. {0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,pg2E},{0,pg2F},
  766. {0,pg30},{0,pg31},{0,pg32},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},
  767. {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},
  768. {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},
  769. {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{0,pg4D},{1,NULL},{1,NULL},
  770. {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},
  771. {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},
  772. {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},
  773. {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},
  774. {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},
  775. {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},
  776. {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},
  777. {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},
  778. {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},
  779. {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{0,pg9F},
  780. {1,NULL},{1,NULL},{1,NULL},{1,NULL},{0,pgA4},{0,NULL},{0,NULL},{0,NULL},
  781. {0,NULL},{0,NULL},{0,NULL},{0,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},
  782. {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},
  783. {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},
  784. {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},
  785. {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},
  786. {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{0,pgD7},
  787. {0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},
  788. {0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},
  789. {0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},
  790. {0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},
  791. {0,NULL},{1,NULL},{0,pgFA},{0,NULL},{0,NULL},{0,NULL},{0,pgFE},{0,pgFF}
  792. };
  793. uint my_numcells_mb(CHARSET_INFO *cs, const char *b, const char *e)
  794. {
  795.   my_wc_t wc;
  796.   int clen= 0;
  797.   
  798.   while (b < e)
  799.   {
  800.     int mblen;
  801.     uint pg;
  802.     if ((mblen= cs->cset->mb_wc(cs, &wc, (uchar*) b, (uchar*) e)) <= 0)
  803.     {
  804.       mblen= 1; /* Let's think a wrong sequence takes 1 dysplay cell */
  805.       b++;
  806.       continue;
  807.     }
  808.     b+= mblen;
  809.     pg= (wc >> 8) & 0xFF;
  810.     clen+= utr11_data[pg].p ? utr11_data[pg].p[wc & 0xFF] : utr11_data[pg].page;
  811.     clen++;
  812.   }
  813.   return clen;
  814. }
  815. MY_COLLATION_HANDLER my_collation_mb_bin_handler =
  816. {
  817.     NULL, /* init */
  818.     my_strnncoll_mb_bin,
  819.     my_strnncollsp_mb_bin,
  820.     my_strnxfrm_mb_bin,
  821.     my_like_range_simple,
  822.     my_wildcmp_mb_bin,
  823.     my_strcasecmp_mb_bin,
  824.     my_instr_mb,
  825.     my_hash_sort_mb_bin
  826. };
  827. #endif