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

MySQL数据库

开发平台:

Visual C++

  1.     else scans the next character and returns its first weight.
  2.     Each character can have number weights from 0 to 8.
  3.     
  4.     Some characters do not have weights at all, 0 weights. 
  5.     It means they are ignored during comparison.
  6.     
  7.     Examples:
  8.     1. 0x0001 START OF HEADING, has no weights, ignored, does
  9.        not produce any weights.
  10.     2. 0x0061 LATIN SMALL LETTER A, has one weight.
  11.        0x0E33 will be returned
  12.     3. 0x00DF LATIN SMALL LETTER SHARP S, aka SZ ligature,
  13.        has two weights. It will return 0x0FEA twice for two
  14.        consequent calls.
  15.     4. 0x247D PATENTHESIZED NUMBER TEN, has four weights,
  16.        this function will return these numbers in four 
  17.        consequent calls: 0x0288, 0x0E2A, 0x0E29, 0x0289
  18.     5. A string consisting of the above characters:
  19.        0x0001 0x0061 0x00DF 0x247D
  20.        will return the following weights, one weight per call:
  21.        0x0E33 0x0FEA 0x0FEA 0x0288, 0x0E2A, 0x0E29, 0x0289
  22.     
  23.   RETURN
  24.     Next weight, a number between 0x0000 and 0xFFFF
  25.     Or -1 on error (END-OF-STRING or ILLEGAL MULTIBYTE SEQUENCE)
  26. */
  27. static int my_uca_scanner_next_ucs2(my_uca_scanner *scanner)
  28. {
  29.   
  30.   /* 
  31.     Check if the weights for the previous character have been
  32.     already fully scanned. If yes, then get the next character and 
  33.     initialize wbeg and wlength to its weight string.
  34.   */
  35.   
  36.   if (scanner->wbeg[0])
  37.     return *scanner->wbeg++;
  38.   
  39.   do 
  40.   {
  41.     uint16 **ucaw= scanner->uca_weight;
  42.     uchar *ucal= scanner->uca_length;
  43.     
  44.     if (scanner->sbeg > scanner->send)
  45.       return -1;
  46.     
  47.     scanner->page= (unsigned char)scanner->sbeg[0];
  48.     scanner->code= (unsigned char)scanner->sbeg[1];
  49.     scanner->sbeg+= 2;
  50.     
  51.     if (scanner->contractions && (scanner->sbeg <= scanner->send))
  52.     {
  53.       int cweight;
  54.       
  55.       if (!scanner->page && !scanner->sbeg[0] &&
  56.           (scanner->sbeg[1] > 0x40) && (scanner->sbeg[1] < 0x80) &&
  57.           (scanner->code > 0x40) && (scanner->code < 0x80) &&
  58.           (cweight= scanner->contractions[(scanner->code-0x40)*0x40+scanner->sbeg[1]-0x40]))
  59.         {
  60.           scanner->implicit[0]= 0;
  61.           scanner->wbeg= scanner->implicit;
  62.           scanner->sbeg+=2;
  63.           return cweight;
  64.         }
  65.     }
  66.     
  67.     if (!ucaw[scanner->page])
  68.       goto implicit;
  69.     scanner->wbeg= ucaw[scanner->page] + scanner->code * ucal[scanner->page];
  70.   } while (!scanner->wbeg[0]);
  71.   
  72.   return *scanner->wbeg++;
  73.   
  74. implicit:
  75.   
  76.   scanner->code= (scanner->page << 8) + scanner->code;
  77.   scanner->implicit[0]= (scanner->code & 0x7FFF) | 0x8000;
  78.   scanner->implicit[1]= 0;
  79.   scanner->wbeg= scanner->implicit;
  80.   
  81.   scanner->page= scanner->page >> 7;
  82.   
  83.   if (scanner->code >= 0x3400 && scanner->code <= 0x4DB5)
  84.     scanner->page+= 0xFB80;
  85.   else if (scanner->code >= 0x4E00 && scanner->code <= 0x9FA5)
  86.     scanner->page+= 0xFB40;
  87.   else
  88.     scanner->page+= 0xFBC0;
  89.   
  90.   return scanner->page;
  91. }
  92. static my_uca_scanner_handler my_ucs2_uca_scanner_handler=
  93. {
  94.   my_uca_scanner_init_ucs2,
  95.   my_uca_scanner_next_ucs2
  96. };
  97. #endif
  98. /*
  99.   The same two functions for any character set
  100. */
  101. static void my_uca_scanner_init_any(my_uca_scanner *scanner,
  102.     CHARSET_INFO *cs __attribute__((unused)),
  103.     const uchar *str, uint length)
  104. {
  105.   /* Note, no needs to initialize scanner->wbeg */
  106.   scanner->sbeg= str;
  107.   scanner->send= str + length;
  108.   scanner->wbeg= nochar; 
  109.   scanner->uca_length= cs->sort_order;
  110.   scanner->uca_weight= cs->sort_order_big;
  111.   scanner->contractions= cs->contractions;
  112.   scanner->cs= cs;
  113. }
  114. static int my_uca_scanner_next_any(my_uca_scanner *scanner)
  115. {
  116.   
  117.   /* 
  118.     Check if the weights for the previous character have been
  119.     already fully scanned. If yes, then get the next character and 
  120.     initialize wbeg and wlength to its weight string.
  121.   */
  122.   
  123.   if (scanner->wbeg[0])
  124.     return *scanner->wbeg++;
  125.   
  126.   do 
  127.   {
  128.     uint16 **ucaw= scanner->uca_weight;
  129.     uchar *ucal= scanner->uca_length;
  130.     my_wc_t wc;
  131.     int mblen;
  132.     
  133.     if (((mblen= scanner->cs->cset->mb_wc(scanner->cs, &wc, 
  134.                                           scanner->sbeg,
  135.                                           scanner->send)) <= 0))
  136.       return -1;
  137.     
  138.     scanner->page= wc >> 8;
  139.     scanner->code= wc & 0xFF;
  140.     scanner->sbeg+= mblen;
  141.     
  142.     if (scanner->contractions && !scanner->page &&
  143.         (scanner->code > 0x40) && (scanner->code < 0x80))
  144.     {
  145.       uint page1, code1, cweight;
  146.       
  147.       if (((mblen= scanner->cs->cset->mb_wc(scanner->cs, &wc,
  148.                                             scanner->sbeg, 
  149.                                             scanner->send)) >=0) &&
  150.            (!(page1= (wc >> 8))) &&
  151.            ((code1= (wc & 0xFF)) > 0x40) &&
  152.            (code1 < 0x80) && 
  153.            (cweight= scanner->contractions[(scanner->code-0x40)*0x40 + code1-0x40]))
  154.       {
  155.         scanner->implicit[0]= 0;
  156.         scanner->wbeg= scanner->implicit;
  157.         scanner->sbeg+= mblen;
  158.         return cweight;
  159.       }
  160.     }
  161.     
  162.     if (!ucaw[scanner->page])
  163.       goto implicit;
  164.     scanner->wbeg= ucaw[scanner->page] + scanner->code * ucal[scanner->page];
  165.   } while (!scanner->wbeg[0]);
  166.   
  167.   return *scanner->wbeg++;
  168.   
  169. implicit:
  170.   
  171.   scanner->code= (scanner->page << 8) + scanner->code;
  172.   scanner->implicit[0]= (scanner->code & 0x7FFF) | 0x8000;
  173.   scanner->implicit[1]= 0;
  174.   scanner->wbeg= scanner->implicit;
  175.   
  176.   scanner->page= scanner->page >> 7;
  177.   
  178.   if (scanner->code >= 0x3400 && scanner->code <= 0x4DB5)
  179.     scanner->page+= 0xFB80;
  180.   else if (scanner->code >= 0x4E00 && scanner->code <= 0x9FA5)
  181.     scanner->page+= 0xFB40;
  182.   else
  183.     scanner->page+= 0xFBC0;
  184.   
  185.   return scanner->page;
  186. }
  187. static my_uca_scanner_handler my_any_uca_scanner_handler=
  188. {
  189.   my_uca_scanner_init_any,
  190.   my_uca_scanner_next_any
  191. };
  192. /*
  193.   Compares two strings according to the collation
  194.   SYNOPSIS:
  195.     my_strnncoll_uca()
  196.     cs Character set information
  197.     s First string
  198.     slen First string length
  199.     t Second string
  200.     tlen Seconf string length
  201.   
  202.   NOTES:
  203.     Initializes two weight scanners and gets weights
  204.     corresponding to two strings in a loop. If weights are not
  205.     the same at some step then returns their difference.
  206.     
  207.     In the while() comparison these situations are possible:
  208.     1. (s_res>0) and (t_res>0) and (s_res == t_res)
  209.        Weights are the same so far, continue comparison
  210.     2. (s_res>0) and (t_res>0) and (s_res!=t_res)
  211.        A difference has been found, return.
  212.     3. (s_res>0) and (t_res<0)
  213.        We have reached the end of the second string, or found
  214.        an illegal multibyte sequence in the second string.
  215.        Return a positive number, i.e. the first string is bigger.
  216.     4. (s_res<0) and (t_res>0)   
  217.        We have reached the end of the first string, or found
  218.        an illegal multibyte sequence in the first string.
  219.        Return a negative number, i.e. the second string is bigger.
  220.     5. (s_res<0) and (t_res<0)
  221.        Both scanners returned -1. It means we have riched
  222.        the end-of-string of illegal-sequence in both strings
  223.        at the same time. Return 0, strings are equal.
  224.     
  225.   RETURN
  226.     Difference between two strings, according to the collation:
  227.     0               - means strings are equal
  228.     negative number - means the first string is smaller
  229.     positive number - means the first string is bigger
  230. */
  231. static int my_strnncoll_uca(CHARSET_INFO *cs, 
  232.                             my_uca_scanner_handler *scanner_handler,
  233.     const uchar *s, uint slen,
  234.                             const uchar *t, uint tlen,
  235.                             my_bool t_is_prefix)
  236. {
  237.   my_uca_scanner sscanner;
  238.   my_uca_scanner tscanner;
  239.   int s_res;
  240.   int t_res;
  241.   
  242.   scanner_handler->init(&sscanner, cs, s, slen);
  243.   scanner_handler->init(&tscanner, cs, t, tlen);
  244.   
  245.   do
  246.   {
  247.     s_res= scanner_handler->next(&sscanner);
  248.     t_res= scanner_handler->next(&tscanner);
  249.   } while ( s_res == t_res && s_res >0);
  250.   
  251.   return  (t_is_prefix && t_res < 0) ? 0 : (s_res - t_res);
  252. }
  253. /*
  254.   Compares two strings according to the collation,
  255.   ignoring trailing spaces.
  256.   SYNOPSIS:
  257.     my_strnncollsp_uca()
  258.     cs Character set information
  259.     s First string
  260.     slen First string length
  261.     t Second string
  262.     tlen Seconf string length
  263.   
  264.   NOTES:
  265.     Works exactly the same with my_strnncoll_uca(),
  266.     but ignores trailing spaces.
  267.     In the while() comparison these situations are possible:
  268.     1. (s_res>0) and (t_res>0) and (s_res == t_res)
  269.        Weights are the same so far, continue comparison
  270.     2. (s_res>0) and (t_res>0) and (s_res!=t_res)
  271.        A difference has been found, return.
  272.     3. (s_res>0) and (t_res<0)
  273.        We have reached the end of the second string, or found
  274.        an illegal multibyte sequence in the second string.
  275.        Compare the first string to an infinite array of
  276.        space characters until difference is found, or until
  277.        the end of the first string.
  278.     4. (s_res<0) and (t_res>0)   
  279.        We have reached the end of the first string, or found
  280.        an illegal multibyte sequence in the first string.
  281.        Compare the second string to an infinite array of
  282.        space characters until difference is found or until
  283.        the end of the second steing.
  284.     5. (s_res<0) and (t_res<0)
  285.        Both scanners returned -1. It means we have riched
  286.        the end-of-string of illegal-sequence in both strings
  287.        at the same time. Return 0, strings are equal.
  288.   
  289.   RETURN
  290.     Difference between two strings, according to the collation:
  291.     0               - means strings are equal
  292.     negative number - means the first string is smaller
  293.     positive number - means the first string is bigger
  294. */
  295. static int my_strnncollsp_uca(CHARSET_INFO *cs, 
  296.                               my_uca_scanner_handler *scanner_handler,
  297.                               const uchar *s, uint slen,
  298.                               const uchar *t, uint tlen)
  299. {
  300.   my_uca_scanner sscanner;
  301.   my_uca_scanner tscanner;
  302.   int s_res;
  303.   int t_res;
  304.   
  305.   scanner_handler->init(&sscanner, cs, s, slen);
  306.   scanner_handler->init(&tscanner, cs, t, tlen);
  307.   
  308.   do
  309.   {
  310.     s_res= scanner_handler->next(&sscanner);
  311.     t_res= scanner_handler->next(&tscanner);
  312.   } while ( s_res == t_res && s_res >0);
  313.   if (s_res > 0 && t_res < 0)
  314.   { 
  315.     /* Calculate weight for SPACE character */
  316.     t_res= cs->sort_order_big[0][0x20 * cs->sort_order[0]];
  317.       
  318.     /* compare the first string to spaces */
  319.     do
  320.     {
  321.       if (s_res != t_res)
  322.         return (s_res - t_res);
  323.       s_res= scanner_handler->next(&sscanner);
  324.     } while (s_res > 0);
  325.     return 0;
  326.   }
  327.     
  328.   if (s_res < 0 && t_res > 0)
  329.   {
  330.     /* Calculate weight for SPACE character */
  331.     s_res= cs->sort_order_big[0][0x20 * cs->sort_order[0]];
  332.       
  333.     /* compare the second string to spaces */
  334.     do
  335.     {
  336.       if (s_res != t_res)
  337.         return (s_res - t_res);
  338.       t_res= scanner_handler->next(&tscanner);
  339.     } while (t_res > 0);
  340.     return 0;
  341.   }
  342.   
  343.   return ( s_res - t_res );
  344. }
  345. /*
  346.   Calculates hash value for the given string,
  347.   according to the collation, and ignoring trailing spaces.
  348.   
  349.   SYNOPSIS:
  350.     my_hash_sort_uca()
  351.     cs Character set information
  352.     s String
  353.     slen String's length
  354.     n1 First hash parameter
  355.     n2 Second hash parameter
  356.   
  357.   NOTES:
  358.     Scans consequently weights and updates
  359.     hash parameters n1 and n2. In a case insensitive collation,
  360.     upper and lower case of the same letter will return the same
  361.     weight sequence, and thus will produce the same hash values
  362.     in n1 and n2.
  363.   
  364.   RETURN
  365.     N/A
  366. */
  367. static void my_hash_sort_uca(CHARSET_INFO *cs,
  368.                              my_uca_scanner_handler *scanner_handler,
  369.      const uchar *s, uint slen,
  370.      ulong *n1, ulong *n2)
  371. {
  372.   int   s_res;
  373.   my_uca_scanner scanner;
  374.   
  375.   slen= cs->cset->lengthsp(cs, (char*) s, slen);
  376.   scanner_handler->init(&scanner, cs, s, slen);
  377.   
  378.   while ((s_res= scanner_handler->next(&scanner)) >0)
  379.   {
  380.     n1[0]^= (((n1[0] & 63)+n2[0])*(s_res >> 8))+ (n1[0] << 8);
  381.     n2[0]+=3;
  382.     n1[0]^= (((n1[0] & 63)+n2[0])*(s_res & 0xFF))+ (n1[0] << 8);
  383.     n2[0]+=3;
  384.   }
  385. }
  386. /*
  387.   For the given string creates its "binary image", suitable
  388.   to be used in binary comparison, i.e. in memcmp(). 
  389.   
  390.   SYNOPSIS:
  391.     my_strnxfrm_uca()
  392.     cs Character set information
  393.     dst Where to write the image
  394.     dstlen Space available for the image, in bytes
  395.     src The source string
  396.     srclen Length of the source string, in bytes
  397.   
  398.   NOTES:
  399.     In a loop, scans weights from the source string and writes
  400.     them into the binary image. In a case insensitive collation,
  401.     upper and lower cases of the same letter will produce the
  402.     same image subsequences. When we have reached the end-of-string
  403.     or found an illegal multibyte sequence, the loop stops.
  404.     It is impossible to restore the original string using its
  405.     binary image. 
  406.     
  407.     Binary images are used for bulk comparison purposes,
  408.     e.g. in ORDER BY, when it is more efficient to create
  409.     a binary image and use it instead of weight scanner
  410.     for the original strings for every comparison.
  411.   
  412.   RETURN
  413.     Number of bytes that have been written into the binary image.
  414. */
  415. static int my_strnxfrm_uca(CHARSET_INFO *cs, 
  416.                            my_uca_scanner_handler *scanner_handler,
  417.                            uchar *dst, uint dstlen,
  418.                            const uchar *src, uint srclen)
  419. {
  420.   uchar *de = dst + (dstlen & (uint) ~1); /* add even length for easier code */
  421.   int   s_res;
  422.   my_uca_scanner scanner;
  423.   scanner_handler->init(&scanner, cs, src, srclen);
  424.   
  425.   while (dst < de && (s_res= scanner_handler->next(&scanner)) >0)
  426.   {
  427.     dst[0]= s_res >> 8;
  428.     dst[1]= s_res & 0xFF;
  429.     dst+= 2;
  430.   }
  431.   s_res= cs->sort_order_big[0][0x20 * cs->sort_order[0]];
  432.   while (dst < de)
  433.   {
  434.     dst[0]= s_res >> 8;
  435.     dst[1]= s_res & 0xFF;
  436.     dst+= 2;
  437.   }
  438.   if (dstlen & 1) /* if odd number then fill the last char */
  439.     *dst= '';
  440.   
  441.   return dstlen;
  442. }
  443. /*
  444.   This function compares if two characters are the same.
  445.   The sign +1 or -1 does not matter. The only
  446.   important thing is that the result is 0 or not 0.
  447.   This fact allows us to use memcmp() safely, on both
  448.   little-endian and big-endian machines.
  449. */
  450. static int my_uca_charcmp(CHARSET_INFO *cs, my_wc_t wc1, my_wc_t wc2)
  451. {
  452.   size_t page1= wc1 >> MY_UCA_PSHIFT;
  453.   size_t page2= wc2 >> MY_UCA_PSHIFT;
  454.   uchar *ucal= cs->sort_order;
  455.   uint16 **ucaw= cs->sort_order_big;
  456.   size_t length1= ucal[page1];
  457.   size_t length2= ucal[page2];
  458.   uint16 *weight1= ucaw[page1] + (wc1 & MY_UCA_CMASK) * ucal[page1];
  459.   uint16 *weight2= ucaw[page2] + (wc2 & MY_UCA_CMASK) * ucal[page2];
  460.   
  461.   if (!weight1 || !weight2)
  462.     return wc1 != wc2;
  463.   
  464.   if (length1 > length2)
  465.     return memcmp((const void*)weight1, (const void*)weight2, length2*2) ?
  466.            1: weight1[length2];
  467.   
  468.   if (length1 < length2)
  469.     return memcmp((const void*)weight1, (const void*)weight2, length1*2) ?
  470.            1 : weight2[length1];
  471.   
  472.   return memcmp((const void*)weight1, (const void*)weight2, length1*2);
  473. }
  474. /*
  475. ** Compare string against string with wildcard
  476. ** 0 if matched
  477. ** -1 if not matched with wildcard
  478. **  1 if matched with wildcard
  479. */
  480. static
  481. int my_wildcmp_uca(CHARSET_INFO *cs,
  482.    const char *str,const char *str_end,
  483.    const char *wildstr,const char *wildend,
  484.    int escape, int w_one, int w_many)
  485. {
  486.   int result= -1; /* Not found, using wildcards */
  487.   my_wc_t s_wc, w_wc;
  488.   int scan;
  489.   int (*mb_wc)(struct charset_info_st *cs, my_wc_t *wc,
  490.                const unsigned char *s,const unsigned char *e);
  491.   mb_wc= cs->cset->mb_wc;
  492.   
  493.   while (wildstr != wildend)
  494.   {
  495.     while (1)
  496.     {
  497.       my_bool escaped= 0;
  498.       if ((scan= mb_wc(cs, &w_wc, (const uchar*)wildstr,
  499.        (const uchar*)wildend)) <= 0)
  500. return 1;
  501.       if (w_wc == (my_wc_t)w_many)
  502.       {
  503.         result= 1; /* Found an anchor char */
  504.         break;
  505.       }
  506.       wildstr+= scan;
  507.       if (w_wc ==  (my_wc_t)escape)
  508.       {
  509.         if ((scan= mb_wc(cs, &w_wc, (const uchar*)wildstr,
  510. (const uchar*)wildend)) <= 0)
  511.           return 1;
  512.         wildstr+= scan;
  513.         escaped= 1;
  514.       }
  515.       
  516.       if ((scan= mb_wc(cs, &s_wc, (const uchar*)str,
  517.               (const uchar*)str_end)) <= 0)
  518.         return 1;
  519.       str+= scan;
  520.       
  521.       if (!escaped && w_wc == (my_wc_t)w_one)
  522.       {
  523.         result= 1; /* Found an anchor char */
  524.       }
  525.       else
  526.       {
  527.         if (my_uca_charcmp(cs,s_wc,w_wc))
  528.           return 1;
  529.       }
  530.       if (wildstr == wildend)
  531. return (str != str_end); /* Match if both are at end */
  532.     }
  533.     
  534.     
  535.     if (w_wc == (my_wc_t)w_many)
  536.     { /* Found w_many */
  537.     
  538.       /* Remove any '%' and '_' from the wild search string */
  539.       for ( ; wildstr != wildend ; )
  540.       {
  541.         if ((scan= mb_wc(cs, &w_wc, (const uchar*)wildstr,
  542.  (const uchar*)wildend)) <= 0)
  543.           return 1;
  544.         
  545. if (w_wc == (my_wc_t)w_many)
  546. {
  547.   wildstr+= scan;
  548.   continue;
  549. if (w_wc == (my_wc_t)w_one)
  550. {
  551.   wildstr+= scan;
  552.   if ((scan= mb_wc(cs, &s_wc, (const uchar*)str,
  553.    (const uchar*)str_end)) <= 0)
  554.             return 1;
  555.           str+= scan;
  556.   continue;
  557. }
  558. break; /* Not a wild character */
  559.       }
  560.       
  561.       if (wildstr == wildend)
  562. return 0; /* Ok if w_many is last */
  563.       
  564.       if (str == str_end)
  565. return -1;
  566.       
  567.       if ((scan= mb_wc(cs, &w_wc, (const uchar*)wildstr,
  568.        (const uchar*)wildend)) <= 0)
  569.         return 1;
  570.       
  571.       if (w_wc ==  (my_wc_t)escape)
  572.       {
  573.         wildstr+= scan;
  574.         if ((scan= mb_wc(cs, &w_wc, (const uchar*)wildstr,
  575.  (const uchar*)wildend)) <= 0)
  576.           return 1;
  577.       }
  578.       
  579.       while (1)
  580.       {
  581.         /* Skip until the first character from wildstr is found */
  582.         while (str != str_end)
  583.         {
  584.           if ((scan= mb_wc(cs, &s_wc, (const uchar*)str,
  585.    (const uchar*)str_end)) <= 0)
  586.             return 1;
  587.           
  588.           if (!my_uca_charcmp(cs,s_wc,w_wc))
  589.             break;
  590.           str+= scan;
  591.         }
  592.         if (str == str_end)
  593.           return -1;
  594.         
  595.         result= my_wildcmp_uca(cs, str, str_end, wildstr, wildend,
  596.                 escape, w_one, w_many);
  597.         
  598.         if (result <= 0)
  599.           return result;
  600.         
  601.         str+= scan;
  602.       } 
  603.     }
  604.   }
  605.   return (str != str_end ? 1 : 0);
  606. }
  607. /*
  608.   Collation language is implemented according to
  609.   subset of ICU Collation Customization (tailorings):
  610.   http://oss.software.ibm.com/icu/userguide/Collate_Customization.html
  611.   
  612.   Collation language elements:
  613.   Delimiters:
  614.     space   - skipped
  615.   
  616.   <char> :=  A-Z | a-z | uXXXX
  617.   
  618.   Shift command:
  619.     <shift>  := &       - reset at this letter. 
  620.   
  621.   Diff command:
  622.     <d1> :=  <     - Identifies a primary difference.
  623.     <d2> :=  <<    - Identifies a secondary difference.
  624.     <d3> := <<<    - Idenfifies a tertiary difference.
  625.   
  626.   
  627.   Collation rules:
  628.     <ruleset> :=  <rule>  { <ruleset> }
  629.     
  630.     <rule> :=   <d1>    <string>
  631.               | <d2>    <string>
  632.               | <d3>    <string>
  633.               | <shift> <char>
  634.     
  635.     <string> := <char> [ <string> ]
  636.   An example, Polish collation:
  637.   
  638.     &A < u0105 <<< u0104
  639.     &C < u0107 <<< u0106
  640.     &E < u0119 <<< u0118
  641.     &L < u0142 <<< u0141
  642.     &N < u0144 <<< u0143
  643.     &O < u00F3 <<< u00D3
  644.     &S < u015B <<< u015A
  645.     &Z < u017A <<< u017B    
  646. */
  647. typedef enum my_coll_lexem_num_en
  648. {
  649.   MY_COLL_LEXEM_EOF = 0,
  650.   MY_COLL_LEXEM_DIFF = 1, 
  651.   MY_COLL_LEXEM_SHIFT = 4,
  652.   MY_COLL_LEXEM_CHAR = 5,
  653.   MY_COLL_LEXEM_ERROR = 6
  654. } my_coll_lexem_num;
  655. typedef struct my_coll_lexem_st
  656. {
  657.   const char *beg;
  658.   const char *end;
  659.   const char *prev;
  660.   int   diff;
  661.   int   code;
  662. } MY_COLL_LEXEM;
  663. /*
  664.   Initialize collation rule lexical anilizer
  665.   
  666.   SYNOPSIS
  667.     my_coll_lexem_init
  668.     lexem                Lex analizer to init
  669.     str                  Const string to parse
  670.     strend               End of the string
  671.   USAGE
  672.   
  673.   RETURN VALUES
  674.     N/A
  675. */
  676. static void my_coll_lexem_init(MY_COLL_LEXEM *lexem,
  677.                                const char *str, const char *strend)
  678. {
  679.   lexem->beg= str;
  680.   lexem->prev= str;
  681.   lexem->end= strend;
  682.   lexem->diff= 0;
  683.   lexem->code= 0;
  684. }
  685. /*
  686.   Print collation customization expression parse error, with context.
  687.   
  688.   SYNOPSIS
  689.     my_coll_lexem_print_error
  690.     lexem                Lex analizer to take context from
  691.     errstr               sting to write error to
  692.     errsize              errstr size
  693.     txt                  error message
  694.   USAGE
  695.   
  696.   RETURN VALUES
  697.     N/A
  698. */
  699. static void my_coll_lexem_print_error(MY_COLL_LEXEM *lexem,
  700.                                       char *errstr, size_t errsize,
  701.                                       const char *txt)
  702. {
  703.   char tail[30];
  704.   size_t len= lexem->end - lexem->prev;
  705.   strmake (tail, lexem->prev, min(len, sizeof(tail)-1));
  706.   errstr[errsize-1]= '';
  707.   my_snprintf(errstr,errsize-1,"%s at '%s'", txt, tail);
  708. }
  709. /*
  710.   Convert a hex digit into its numeric value
  711.   
  712.   SYNOPSIS
  713.     ch2x
  714.     ch                   hex digit to convert
  715.   USAGE
  716.   
  717.   RETURN VALUES
  718.     an integer value in the range 0..15
  719.     -1 on error
  720. */
  721. static int ch2x(int ch)
  722. {
  723.   if (ch >= '0' && ch <= '9')
  724.     return ch - '0';
  725.   
  726.   if (ch >= 'a' && ch <= 'f')
  727.     return 10 + ch - 'a';
  728.   
  729.   if (ch >= 'A' && ch <= 'F')
  730.     return 10 + ch - 'A';
  731.   
  732.   return -1;
  733. }
  734. /*
  735.   Collation language lexical parser:
  736.   Scans the next lexem.
  737.   
  738.   SYNOPSIS
  739.     my_coll_lexem_next
  740.     lexem                Lex analizer, previously initialized by 
  741.                          my_coll_lexem_init.
  742.   USAGE
  743.     Call this function in a loop
  744.     
  745.   RETURN VALUES
  746.     Lexem number: eof, diff, shift, char or error.
  747. */
  748. static my_coll_lexem_num my_coll_lexem_next(MY_COLL_LEXEM *lexem)
  749. {
  750.   const char *beg;
  751.   my_coll_lexem_num rc;
  752.   
  753.   for (beg= lexem->beg ; beg < lexem->end ; beg++)
  754.   {
  755.     if (*beg == ' ' || *beg == 't' || *beg == 'r' || *beg == 'n')
  756.       continue;
  757.     
  758.     if (*beg == '&')
  759.     {
  760.       beg++;
  761.       rc= MY_COLL_LEXEM_SHIFT;
  762.       goto ex;
  763.     }
  764.     
  765.     if (beg[0] == '<')
  766.     {
  767.       for (beg++, lexem->diff= 1;
  768.            (beg < lexem->end) && 
  769.            (*beg == '<') && (lexem->diff<3);
  770.            beg++, lexem->diff++);
  771.       rc= MY_COLL_LEXEM_DIFF;
  772.       goto ex;
  773.     }
  774.     
  775.     if ((*beg >= 'a' && *beg <= 'z') || (*beg >= 'A' && *beg <= 'Z'))
  776.     {
  777.       lexem->code= *beg++;
  778.       rc= MY_COLL_LEXEM_CHAR;
  779.       goto ex;
  780.     }
  781.     
  782.     if ((*beg == '\') && (beg+2 < lexem->end) && (beg[1] == 'u'))
  783.     {
  784.       int ch;
  785.       
  786.       beg+= 2;
  787.       lexem->code= 0;
  788.       while ((beg < lexem->end) && ((ch= ch2x(beg[0])) >= 0))
  789.       { 
  790.         lexem->code= (lexem->code << 4) + ch;
  791.         beg++;
  792.       }
  793.       rc= MY_COLL_LEXEM_CHAR;
  794.       goto ex;
  795.     }
  796.     
  797.     rc= MY_COLL_LEXEM_ERROR;
  798.     goto ex;
  799.   }
  800.   rc= MY_COLL_LEXEM_EOF;
  801.   
  802. ex:
  803.   lexem->prev= lexem->beg;
  804.   lexem->beg= beg;
  805.   return rc;  
  806. }
  807. /*
  808.   Collation rule item
  809. */
  810. typedef struct my_coll_rule_item_st
  811. {
  812.   uint base;     /* Base character                             */
  813.   uint curr[2];  /* Current character                          */
  814.   int diff[3];   /* Primary, Secondary and Tertiary difference */
  815. } MY_COLL_RULE;
  816. /*
  817.   Collation language syntax parser.
  818.   Uses lexical parser.
  819.   
  820.   SYNOPSIS
  821.     my_coll_rule_parse
  822.     rule                 Collation rule list to load to.
  823.     str                  A string containin collation language expression.
  824.     strend               End of the string.
  825.   USAGE
  826.     
  827.   RETURN VALUES
  828.     A positive number means the number of rules loaded.
  829.    -1 means ERROR, e.g. too many items, syntax error, etc.
  830. */
  831. static int my_coll_rule_parse(MY_COLL_RULE *rule, size_t mitems,
  832.                               const char *str, const char *strend,
  833.                               char *errstr, size_t errsize)
  834. {
  835.   MY_COLL_LEXEM lexem;
  836.   my_coll_lexem_num lexnum;
  837.   my_coll_lexem_num prevlexnum= MY_COLL_LEXEM_ERROR;
  838.   MY_COLL_RULE item; 
  839.   int state= 0;
  840.   size_t nitems= 0;
  841.   
  842.   /* Init all variables */
  843.   errstr[0]= '';
  844.   bzero(&item, sizeof(item));
  845.   my_coll_lexem_init(&lexem, str, strend);
  846.   
  847.   while ((lexnum= my_coll_lexem_next(&lexem)))
  848.   {
  849.     if (lexnum == MY_COLL_LEXEM_ERROR)
  850.     {
  851.       my_coll_lexem_print_error(&lexem,errstr,errsize-1,"Unknown character");
  852.       return -1;
  853.     }
  854.     
  855.     switch (state) {
  856.     case 0:
  857.       if (lexnum != MY_COLL_LEXEM_SHIFT)
  858.       {
  859.         my_coll_lexem_print_error(&lexem,errstr,errsize-1,"& expected");
  860.         return -1;
  861.       }
  862.       prevlexnum= lexnum;
  863.       state= 2;
  864.       continue;
  865.       
  866.     case 1:
  867.       if (lexnum != MY_COLL_LEXEM_SHIFT && lexnum != MY_COLL_LEXEM_DIFF)
  868.       {
  869.         my_coll_lexem_print_error(&lexem,errstr,errsize-1,"& or < expected");
  870.         return -1;
  871.       }
  872.       prevlexnum= lexnum;
  873.       state= 2;
  874.       continue;
  875.       
  876.     case 2:
  877.       if (lexnum != MY_COLL_LEXEM_CHAR)
  878.       {
  879.         my_coll_lexem_print_error(&lexem,errstr,errsize-1,"character expected");
  880.         return -1;
  881.       }
  882.       
  883.       if (prevlexnum == MY_COLL_LEXEM_SHIFT)
  884.       {
  885.         item.base= lexem.code;
  886.         item.diff[0]= 0;
  887.         item.diff[1]= 0;
  888.         item.diff[2]= 0;
  889.       }
  890.       else if (prevlexnum == MY_COLL_LEXEM_DIFF)
  891.       {
  892.         MY_COLL_LEXEM savlex;
  893.         savlex= lexem;
  894.         item.curr[0]= lexem.code;
  895.         if ((lexnum= my_coll_lexem_next(&lexem)) == MY_COLL_LEXEM_CHAR)
  896.         {
  897.           item.curr[1]= lexem.code;
  898.         }
  899.         else
  900.         {
  901.           item.curr[1]= 0;
  902.           lexem=savlex;   /* Restore previous parser state */
  903.         }
  904.         if (lexem.diff == 3)
  905.         {
  906.           item.diff[2]++;
  907.         }
  908.         else if (lexem.diff == 2)
  909.         {
  910.           item.diff[1]++;
  911.           item.diff[2]= 0;
  912.         }
  913.         else if (lexem.diff == 1)
  914.         {
  915.           item.diff[0]++;
  916.           item.diff[1]= 0;
  917.           item.diff[2]= 0;
  918.         }
  919.         if (nitems >= mitems)
  920.         {
  921.           my_coll_lexem_print_error(&lexem,errstr,errsize-1,"Too many rules");
  922.           return -1;
  923.         }
  924.         rule[nitems++]= item;
  925.       }
  926.       else
  927.       {
  928.         my_coll_lexem_print_error(&lexem,errstr,errsize-1,"Should never happen");
  929.         return -1;
  930.       }
  931.       state= 1;
  932.       continue;
  933.     }
  934.   }
  935.   return (size_t) nitems;
  936. }
  937. #define MY_MAX_COLL_RULE 128
  938. /*
  939.   This function copies an UCS2 collation from
  940.   the default Unicode Collation Algorithm (UCA)
  941.   weights applying tailorings, i.e. a set of
  942.   alternative weights for some characters. 
  943.   
  944.   The default UCA weights are stored in uca_weight/uca_length.
  945.   They consist of 256 pages, 256 character each.
  946.   
  947.   If a page is not overwritten by tailoring rules,
  948.   it is copies as is from UCA as is.
  949.   
  950.   If a page contains some overwritten characters, it is
  951.   allocated. Untouched characters are copied from the
  952.   default weights.
  953. */
  954. static my_bool create_tailoring(CHARSET_INFO *cs, void *(*alloc)(uint))
  955. {
  956.   MY_COLL_RULE rule[MY_MAX_COLL_RULE];
  957.   char errstr[128];
  958.   uchar   *newlengths;
  959.   uint16 **newweights;
  960.   const uchar *deflengths= uca_length;
  961.   uint16     **defweights= uca_weight;
  962.   int rc, i;
  963.   int ncontractions= 0;
  964.   
  965.   if (!cs->tailoring)
  966.     return 1;
  967.   
  968.   /* Parse ICU Collation Customization expression */
  969.   if ((rc= my_coll_rule_parse(rule, MY_MAX_COLL_RULE,
  970.                               cs->tailoring,
  971.                               cs->tailoring + strlen(cs->tailoring),
  972.                               errstr, sizeof(errstr))) < 0)
  973.   {
  974.     /* 
  975.       TODO: add error message reporting.
  976.       printf("Error: %d '%s'n", rc, errstr);
  977.     */
  978.     return 1;
  979.   }
  980.   
  981.   if (!(newweights= (uint16**) (*alloc)(256*sizeof(uint16*))))
  982.     return 1;
  983.   bzero(newweights, 256*sizeof(uint16*));
  984.   
  985.   if (!(newlengths= (uchar*) (*alloc)(256)))
  986.     return 1;
  987.   
  988.   memcpy(newlengths, deflengths, 256);
  989.   
  990.   /*
  991.     Calculate maximum lenghts for the pages
  992.     which will be overwritten.
  993.   */
  994.   for (i=0; i < rc; i++)
  995.   {
  996.     if (!rule[i].curr[1]) /* If not a contraction */
  997.     {
  998.       uint pageb= (rule[i].base >> 8) & 0xFF;
  999.       uint pagec= (rule[i].curr[0] >> 8) & 0xFF;
  1000.     
  1001.       if (newlengths[pagec] < deflengths[pageb])
  1002.         newlengths[pagec]= deflengths[pageb];
  1003.     }
  1004.     else
  1005.       ncontractions++;
  1006.   }
  1007.   
  1008.   for (i=0; i < rc;  i++)
  1009.   {
  1010.     uint pageb= (rule[i].base >> 8) & 0xFF;
  1011.     uint pagec= (rule[i].curr[0] >> 8) & 0xFF;
  1012.     uint chb, chc;
  1013.     
  1014.     if (rule[i].curr[1]) /* Skip contraction */
  1015.       continue;
  1016.     
  1017.     if (!newweights[pagec])
  1018.     {
  1019.       /* Alloc new page and copy the default UCA weights */
  1020.       uint size= 256*newlengths[pagec]*sizeof(uint16);
  1021.       
  1022.       if (!(newweights[pagec]= (uint16*) (*alloc)(size)))
  1023.         return 1;
  1024.       bzero((void*) newweights[pagec], size);
  1025.       
  1026.       for (chc=0 ; chc < 256; chc++)
  1027.       {
  1028.         memcpy(newweights[pagec] + chc*newlengths[pagec],
  1029.                defweights[pagec] + chc*deflengths[pagec],
  1030.                deflengths[pagec]*sizeof(uint16));
  1031.       }
  1032.     }
  1033.     
  1034.     /* 
  1035.       Aply the alternative rule:
  1036.       shift to the base character and primary difference.
  1037.     */
  1038.     chc= rule[i].curr[0] & 0xFF;
  1039.     chb= rule[i].base & 0xFF;
  1040.     memcpy(newweights[pagec] + chc*newlengths[pagec],
  1041.            defweights[pageb] + chb*deflengths[pageb],
  1042.            deflengths[pageb]*sizeof(uint16));
  1043.     /* Apply primary difference */
  1044.     newweights[pagec][chc*newlengths[pagec]]+= rule[i].diff[0];
  1045.   }
  1046.   
  1047.   /* Copy non-overwritten pages from the default UCA weights */
  1048.   for (i= 0; i < 256 ; i++)
  1049.   {
  1050.     if (!newweights[i])
  1051.       newweights[i]= defweights[i];
  1052.   }
  1053.   
  1054.   cs->sort_order= newlengths;
  1055.   cs->sort_order_big= newweights;
  1056.   cs->contractions= NULL;
  1057.   
  1058.   /* Now process contractions */
  1059.   if (ncontractions)
  1060.   {
  1061.     uint size= 0x40*0x40*sizeof(uint16); /* 8K, for basic latin letter only */
  1062.     if (!(cs->contractions= (uint16*) (*alloc)(size)))
  1063.         return 1;
  1064.     bzero((void*)cs->contractions, size);
  1065.     for (i=0; i < rc; i++)
  1066.     {
  1067.       if (rule[i].curr[1])
  1068.       {
  1069.         uint pageb= (rule[i].base >> 8) & 0xFF;
  1070.         uint chb= rule[i].base & 0xFF;
  1071.         uint16 *offsb= defweights[pageb] + chb*deflengths[pageb];
  1072.         uint offsc;
  1073.         
  1074.         if (offsb[1] || 
  1075.             rule[i].curr[0] < 0x40 || rule[i].curr[0] > 0x7f ||
  1076.             rule[i].curr[1] < 0x40 || rule[i].curr[1] > 0x7f)
  1077.         {
  1078.           /* 
  1079.            TODO: add error reporting;
  1080.            We support only basic latin letters contractions at this point.
  1081.            Also, We don't support contractions with weight longer than one.
  1082.            Otherwise, we'd need much more memory.
  1083.           */
  1084.           return 1;
  1085.         }
  1086.         offsc= (rule[i].curr[0]-0x40)*0x40+(rule[i].curr[1]-0x40);
  1087.         
  1088.         /* Copy base weight applying primary difference */
  1089.         cs->contractions[offsc]= offsb[0] + rule[i].diff[0];
  1090.       }
  1091.     }
  1092.   }
  1093.   return 0;
  1094. }
  1095. /*
  1096.   Universal CHARSET_INFO compatible wrappers
  1097.   for the above internal functions.
  1098.   Should work for any character set.
  1099. */
  1100. static my_bool my_coll_init_uca(CHARSET_INFO *cs, void *(*alloc)(uint))
  1101. {
  1102.   return create_tailoring(cs, alloc);
  1103. }
  1104. static int my_strnncoll_any_uca(CHARSET_INFO *cs,
  1105.                                 const uchar *s, uint slen,
  1106.                                 const uchar *t, uint tlen,
  1107.                                 my_bool t_is_prefix)
  1108. {
  1109.   return my_strnncoll_uca(cs, &my_any_uca_scanner_handler,
  1110.                           s, slen, t, tlen, t_is_prefix);
  1111. }
  1112. static int my_strnncollsp_any_uca(CHARSET_INFO *cs,
  1113.                               const uchar *s, uint slen,
  1114.                               const uchar *t, uint tlen)
  1115. {
  1116.   return my_strnncollsp_uca(cs, &my_any_uca_scanner_handler,
  1117.                             s, slen, t, tlen);
  1118. }   
  1119. static void my_hash_sort_any_uca(CHARSET_INFO *cs,
  1120.                                  const uchar *s, uint slen,
  1121.                                  ulong *n1, ulong *n2)
  1122. {
  1123.   my_hash_sort_uca(cs, &my_any_uca_scanner_handler, s, slen, n1, n2); 
  1124. }
  1125. static int my_strnxfrm_any_uca(CHARSET_INFO *cs, 
  1126.                                uchar *dst, uint dstlen,
  1127.                                const uchar *src, uint srclen)
  1128. {
  1129.   return my_strnxfrm_uca(cs, &my_any_uca_scanner_handler,
  1130.                          dst, dstlen, src, srclen);
  1131. }
  1132. #ifdef HAVE_CHARSET_ucs2
  1133. /*
  1134.   UCS2 optimized CHARSET_INFO compatible wrappers.
  1135. */
  1136. static int my_strnncoll_ucs2_uca(CHARSET_INFO *cs,
  1137.                                  const uchar *s, uint slen,
  1138.                                  const uchar *t, uint tlen,
  1139.                                  my_bool t_is_prefix)
  1140. {
  1141.   return my_strnncoll_uca(cs, &my_ucs2_uca_scanner_handler,
  1142.                           s, slen, t, tlen, t_is_prefix);
  1143. }
  1144. static int my_strnncollsp_ucs2_uca(CHARSET_INFO *cs,
  1145.                               const uchar *s, uint slen,
  1146.                               const uchar *t, uint tlen)
  1147. {
  1148.   return my_strnncollsp_uca(cs, &my_ucs2_uca_scanner_handler,
  1149.                             s, slen, t, tlen);
  1150. }   
  1151. static void my_hash_sort_ucs2_uca(CHARSET_INFO *cs,
  1152.                                   const uchar *s, uint slen,
  1153.                                   ulong *n1, ulong *n2)
  1154. {
  1155.   my_hash_sort_uca(cs, &my_ucs2_uca_scanner_handler, s, slen, n1, n2); 
  1156. }
  1157. static int my_strnxfrm_ucs2_uca(CHARSET_INFO *cs, 
  1158.                                 uchar *dst, uint dstlen,
  1159.                                 const uchar *src, uint srclen)
  1160. {
  1161.   return my_strnxfrm_uca(cs, &my_ucs2_uca_scanner_handler,
  1162.                          dst, dstlen, src, srclen);
  1163. }
  1164. MY_COLLATION_HANDLER my_collation_ucs2_uca_handler =
  1165. {
  1166.     my_coll_init_uca, /* init */
  1167.     my_strnncoll_ucs2_uca,
  1168.     my_strnncollsp_ucs2_uca,
  1169.     my_strnxfrm_ucs2_uca,
  1170.     my_like_range_ucs2,
  1171.     my_wildcmp_uca,
  1172.     NULL,
  1173.     my_instr_mb,
  1174.     my_hash_sort_ucs2_uca
  1175. };
  1176. CHARSET_INFO my_charset_ucs2_general_uca=
  1177. {
  1178.     128,0,0, /* number       */
  1179.     MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
  1180.     "ucs2", /* cs name    */
  1181.     "ucs2_unicode_ci", /* name         */
  1182.     "", /* comment      */
  1183.     "", /* tailoring    */
  1184.     NULL, /* ctype        */
  1185.     NULL, /* to_lower     */
  1186.     NULL, /* to_upper     */
  1187.     uca_length, /* sort_order   */
  1188.     NULL, /* contractions */
  1189.     uca_weight, /* sort_order_big*/
  1190.     NULL, /* tab_to_uni   */
  1191.     NULL, /* tab_from_uni */
  1192.     NULL, /* state_map    */
  1193.     NULL, /* ident_map    */
  1194.     8, /* strxfrm_multiply */
  1195.     2, /* mbminlen     */
  1196.     2, /* mbmaxlen     */
  1197.     9, /* min_sort_char */
  1198.     0xFFFF, /* max_sort_char */
  1199.     0,                  /* escape_with_backslash_is_dangerous */
  1200.     &my_charset_ucs2_handler,
  1201.     &my_collation_ucs2_uca_handler
  1202. };
  1203. CHARSET_INFO my_charset_ucs2_icelandic_uca_ci=
  1204. {
  1205.     129,0,0, /* number       */
  1206.     MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
  1207.     "ucs2", /* cs name    */
  1208.     "ucs2_icelandic_ci",/* name         */
  1209.     "", /* comment      */
  1210.     icelandic, /* tailoring    */
  1211.     NULL, /* ctype        */
  1212.     NULL, /* to_lower     */
  1213.     NULL, /* to_upper     */
  1214.     NULL, /* sort_order   */
  1215.     NULL, /* contractions */
  1216.     NULL, /* sort_order_big*/
  1217.     NULL, /* tab_to_uni   */
  1218.     NULL, /* tab_from_uni */
  1219.     NULL, /* state_map    */
  1220.     NULL, /* ident_map    */
  1221.     8, /* strxfrm_multiply */
  1222.     2, /* mbminlen     */
  1223.     2, /* mbmaxlen     */
  1224.     9, /* min_sort_char */
  1225.     0xFFFF, /* max_sort_char */
  1226.     0,                  /* escape_with_backslash_is_dangerous */
  1227.     &my_charset_ucs2_handler,
  1228.     &my_collation_ucs2_uca_handler
  1229. };
  1230. CHARSET_INFO my_charset_ucs2_latvian_uca_ci=
  1231. {
  1232.     130,0,0, /* number       */
  1233.     MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
  1234.     "ucs2", /* cs name    */
  1235.     "ucs2_latvian_ci", /* name         */
  1236.     "", /* comment      */
  1237.     latvian, /* tailoring    */
  1238.     NULL, /* ctype        */
  1239.     NULL, /* to_lower     */
  1240.     NULL, /* to_upper     */
  1241.     NULL, /* sort_order   */
  1242.     NULL, /* contractions */
  1243.     NULL, /* sort_order_big*/
  1244.     NULL, /* tab_to_uni   */
  1245.     NULL, /* tab_from_uni */
  1246.     NULL, /* state_map    */
  1247.     NULL, /* ident_map    */
  1248.     8, /* strxfrm_multiply */
  1249.     2, /* mbminlen     */
  1250.     2, /* mbmaxlen     */
  1251.     9, /* min_sort_char */
  1252.     0xFFFF, /* max_sort_char */
  1253.     0,                  /* escape_with_backslash_is_dangerous */
  1254.     &my_charset_ucs2_handler,
  1255.     &my_collation_ucs2_uca_handler
  1256. };
  1257. CHARSET_INFO my_charset_ucs2_romanian_uca_ci=
  1258. {
  1259.     131,0,0, /* number       */
  1260.     MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
  1261.     "ucs2", /* cs name    */
  1262.     "ucs2_romanian_ci", /* name         */
  1263.     "", /* comment      */
  1264.     romanian, /* tailoring    */
  1265.     NULL, /* ctype        */
  1266.     NULL, /* to_lower     */
  1267.     NULL, /* to_upper     */
  1268.     NULL, /* sort_order   */
  1269.     NULL, /* contractions */
  1270.     NULL, /* sort_order_big*/
  1271.     NULL, /* tab_to_uni   */
  1272.     NULL, /* tab_from_uni */
  1273.     NULL, /* state_map    */
  1274.     NULL, /* ident_map    */
  1275.     8, /* strxfrm_multiply */
  1276.     2, /* mbminlen     */
  1277.     2, /* mbmaxlen     */
  1278.     9, /* min_sort_char */
  1279.     0xFFFF, /* max_sort_char */
  1280.     0,                  /* escape_with_backslash_is_dangerous */
  1281.     &my_charset_ucs2_handler,
  1282.     &my_collation_ucs2_uca_handler
  1283. };
  1284. CHARSET_INFO my_charset_ucs2_slovenian_uca_ci=
  1285. {
  1286.     132,0,0, /* number       */
  1287.     MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
  1288.     "ucs2", /* cs name    */
  1289.     "ucs2_slovenian_ci",/* name         */
  1290.     "", /* comment      */
  1291.     slovenian, /* tailoring    */
  1292.     NULL, /* ctype        */
  1293.     NULL, /* to_lower     */
  1294.     NULL, /* to_upper     */
  1295.     NULL, /* sort_order   */
  1296.     NULL, /* contractions */
  1297.     NULL, /* sort_order_big*/
  1298.     NULL, /* tab_to_uni   */
  1299.     NULL, /* tab_from_uni */
  1300.     NULL, /* state_map    */
  1301.     NULL, /* ident_map    */
  1302.     8, /* strxfrm_multiply */
  1303.     2, /* mbminlen     */
  1304.     2, /* mbmaxlen     */
  1305.     9, /* min_sort_char */
  1306.     0xFFFF, /* max_sort_char */
  1307.     0,                  /* escape_with_backslash_is_dangerous */
  1308.     &my_charset_ucs2_handler,
  1309.     &my_collation_ucs2_uca_handler
  1310. };
  1311. CHARSET_INFO my_charset_ucs2_polish_uca_ci=
  1312. {
  1313.     133,0,0, /* number       */
  1314.     MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
  1315.     "ucs2", /* cs name    */
  1316.     "ucs2_polish_ci", /* name         */
  1317.     "", /* comment      */
  1318.     polish, /* tailoring    */
  1319.     NULL, /* ctype        */
  1320.     NULL, /* to_lower     */
  1321.     NULL, /* to_upper     */
  1322.     NULL, /* sort_order   */
  1323.     NULL, /* contractions */
  1324.     NULL, /* sort_order_big*/
  1325.     NULL, /* tab_to_uni   */
  1326.     NULL, /* tab_from_uni */
  1327.     NULL, /* state_map    */
  1328.     NULL, /* ident_map    */
  1329.     8, /* strxfrm_multiply */
  1330.     2, /* mbminlen     */
  1331.     2, /* mbmaxlen     */
  1332.     9, /* min_sort_char */
  1333.     0xFFFF, /* max_sort_char */
  1334.     0,                  /* escape_with_backslash_is_dangerous */
  1335.     &my_charset_ucs2_handler,
  1336.     &my_collation_ucs2_uca_handler
  1337. };
  1338. CHARSET_INFO my_charset_ucs2_estonian_uca_ci=
  1339. {
  1340.     134,0,0, /* number       */
  1341.     MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
  1342.     "ucs2", /* cs name    */
  1343.     "ucs2_estonian_ci", /* name         */
  1344.     "", /* comment      */
  1345.     estonian, /* tailoring    */
  1346.     NULL, /* ctype        */
  1347.     NULL, /* to_lower     */
  1348.     NULL, /* to_upper     */
  1349.     NULL, /* sort_order   */
  1350.     NULL, /* contractions */
  1351.     NULL, /* sort_order_big*/
  1352.     NULL, /* tab_to_uni   */
  1353.     NULL, /* tab_from_uni */
  1354.     NULL, /* state_map    */
  1355.     NULL, /* ident_map    */
  1356.     8, /* strxfrm_multiply */
  1357.     2, /* mbminlen     */
  1358.     2, /* mbmaxlen     */
  1359.     9, /* min_sort_char */
  1360.     0xFFFF, /* max_sort_char */
  1361.     0,                  /* escape_with_backslash_is_dangerous */
  1362.     &my_charset_ucs2_handler,
  1363.     &my_collation_ucs2_uca_handler
  1364. };
  1365. CHARSET_INFO my_charset_ucs2_spanish_uca_ci=
  1366. {
  1367.     135,0,0, /* number       */
  1368.     MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
  1369.     "ucs2", /* cs name    */
  1370.     "ucs2_spanish_ci", /* name         */
  1371.     "", /* comment      */
  1372.     spanish, /* tailoring    */
  1373.     NULL, /* ctype        */
  1374.     NULL, /* to_lower     */
  1375.     NULL, /* to_upper     */
  1376.     NULL, /* sort_order   */
  1377.     NULL, /* contractions */
  1378.     NULL, /* sort_order_big*/
  1379.     NULL, /* tab_to_uni   */
  1380.     NULL, /* tab_from_uni */
  1381.     NULL, /* state_map    */
  1382.     NULL, /* ident_map    */
  1383.     8, /* strxfrm_multiply */
  1384.     2, /* mbminlen     */
  1385.     2, /* mbmaxlen     */
  1386.     9, /* min_sort_char */
  1387.     0xFFFF, /* max_sort_char */
  1388.     0,                  /* escape_with_backslash_is_dangerous */
  1389.     &my_charset_ucs2_handler,
  1390.     &my_collation_ucs2_uca_handler
  1391. };
  1392. CHARSET_INFO my_charset_ucs2_swedish_uca_ci=
  1393. {
  1394.     136,0,0, /* number       */
  1395.     MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
  1396.     "ucs2", /* cs name    */
  1397.     "ucs2_swedish_ci", /* name         */
  1398.     "", /* comment      */
  1399.     swedish, /* tailoring    */
  1400.     NULL, /* ctype        */
  1401.     NULL, /* to_lower     */
  1402.     NULL, /* to_upper     */
  1403.     NULL, /* sort_order   */
  1404.     NULL, /* contractions */
  1405.     NULL, /* sort_order_big*/
  1406.     NULL, /* tab_to_uni   */
  1407.     NULL, /* tab_from_uni */
  1408.     NULL, /* state_map    */
  1409.     NULL, /* ident_map    */
  1410.     8, /* strxfrm_multiply */
  1411.     2, /* mbminlen     */
  1412.     2, /* mbmaxlen     */
  1413.     9, /* min_sort_char */
  1414.     0xFFFF, /* max_sort_char */
  1415.     0,                  /* escape_with_backslash_is_dangerous */
  1416.     &my_charset_ucs2_handler,
  1417.     &my_collation_ucs2_uca_handler
  1418. };
  1419. CHARSET_INFO my_charset_ucs2_turkish_uca_ci=
  1420. {
  1421.     137,0,0, /* number       */
  1422.     MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
  1423.     "ucs2", /* cs name    */
  1424.     "ucs2_turkish_ci", /* name         */
  1425.     "", /* comment      */
  1426.     turkish, /* tailoring    */
  1427.     NULL, /* ctype        */
  1428.     NULL, /* to_lower     */
  1429.     NULL, /* to_upper     */
  1430.     NULL, /* sort_order   */
  1431.     NULL, /* contractions */
  1432.     NULL, /* sort_order_big*/
  1433.     NULL, /* tab_to_uni   */
  1434.     NULL, /* tab_from_uni */
  1435.     NULL, /* state_map    */
  1436.     NULL, /* ident_map    */
  1437.     8, /* strxfrm_multiply */
  1438.     2, /* mbminlen     */
  1439.     2, /* mbmaxlen     */
  1440.     9, /* min_sort_char */
  1441.     0xFFFF, /* max_sort_char */
  1442.     0,                  /* escape_with_backslash_is_dangerous */
  1443.     &my_charset_ucs2_handler,
  1444.     &my_collation_ucs2_uca_handler
  1445. };
  1446. CHARSET_INFO my_charset_ucs2_czech_uca_ci=
  1447. {
  1448.     138,0,0, /* number       */
  1449.     MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
  1450.     "ucs2", /* cs name    */
  1451.     "ucs2_czech_ci", /* name         */
  1452.     "", /* comment      */
  1453.     czech, /* tailoring    */
  1454.     NULL, /* ctype        */
  1455.     NULL, /* to_lower     */
  1456.     NULL, /* to_upper     */
  1457.     NULL, /* sort_order   */
  1458.     NULL, /* contractions */
  1459.     NULL, /* sort_order_big*/
  1460.     NULL, /* tab_to_uni   */
  1461.     NULL, /* tab_from_uni */
  1462.     NULL, /* state_map    */
  1463.     NULL, /* ident_map    */
  1464.     8, /* strxfrm_multiply */
  1465.     2, /* mbminlen     */
  1466.     2, /* mbmaxlen     */
  1467.     9, /* min_sort_char */
  1468.     0xFFFF, /* max_sort_char */
  1469.     0,                  /* escape_with_backslash_is_dangerous */
  1470.     &my_charset_ucs2_handler,
  1471.     &my_collation_ucs2_uca_handler
  1472. };
  1473. CHARSET_INFO my_charset_ucs2_danish_uca_ci=
  1474. {
  1475.     139,0,0, /* number       */
  1476.     MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
  1477.     "ucs2", /* cs name    */
  1478.     "ucs2_danish_ci", /* name         */
  1479.     "", /* comment      */
  1480.     danish, /* tailoring    */
  1481.     NULL, /* ctype        */
  1482.     NULL, /* to_lower     */
  1483.     NULL, /* to_upper     */
  1484.     NULL, /* sort_order   */
  1485.     NULL, /* contractions */
  1486.     NULL, /* sort_order_big*/
  1487.     NULL, /* tab_to_uni   */
  1488.     NULL, /* tab_from_uni */
  1489.     NULL, /* state_map    */
  1490.     NULL, /* ident_map    */
  1491.     8, /* strxfrm_multiply */
  1492.     2, /* mbminlen     */
  1493.     2, /* mbmaxlen     */
  1494.     9, /* min_sort_char */
  1495.     0xFFFF, /* max_sort_char */
  1496.     0,                  /* escape_with_backslash_is_dangerous */
  1497.     &my_charset_ucs2_handler,
  1498.     &my_collation_ucs2_uca_handler
  1499. };
  1500. CHARSET_INFO my_charset_ucs2_lithuanian_uca_ci=
  1501. {
  1502.     140,0,0, /* number       */
  1503.     MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
  1504.     "ucs2", /* cs name    */
  1505.     "ucs2_lithuanian_ci",/* name         */
  1506.     "", /* comment      */
  1507.     lithuanian, /* tailoring    */
  1508.     NULL, /* ctype        */
  1509.     NULL, /* to_lower     */
  1510.     NULL, /* to_upper     */
  1511.     NULL, /* sort_order   */
  1512.     NULL, /* contractions */
  1513.     NULL, /* sort_order_big*/
  1514.     NULL, /* tab_to_uni   */
  1515.     NULL, /* tab_from_uni */
  1516.     NULL, /* state_map    */
  1517.     NULL, /* ident_map    */
  1518.     8, /* strxfrm_multiply */
  1519.     2, /* mbminlen     */
  1520.     2, /* mbmaxlen     */
  1521.     9, /* min_sort_char */
  1522.     0xFFFF, /* max_sort_char */
  1523.     0,                  /* escape_with_backslash_is_dangerous */
  1524.     &my_charset_ucs2_handler,
  1525.     &my_collation_ucs2_uca_handler
  1526. };
  1527. CHARSET_INFO my_charset_ucs2_slovak_uca_ci=
  1528. {
  1529.     141,0,0, /* number       */
  1530.     MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
  1531.     "ucs2", /* cs name    */
  1532.     "ucs2_slovak_ci", /* name         */
  1533.     "", /* comment      */
  1534.     slovak, /* tailoring    */
  1535.     NULL, /* ctype        */
  1536.     NULL, /* to_lower     */
  1537.     NULL, /* to_upper     */
  1538.     NULL, /* sort_order   */
  1539.     NULL, /* contractions */
  1540.     NULL, /* sort_order_big*/
  1541.     NULL, /* tab_to_uni   */
  1542.     NULL, /* tab_from_uni */
  1543.     NULL, /* state_map    */
  1544.     NULL, /* ident_map    */
  1545.     8, /* strxfrm_multiply */
  1546.     2, /* mbminlen     */
  1547.     2, /* mbmaxlen     */
  1548.     9, /* min_sort_char */
  1549.     0xFFFF, /* max_sort_char */
  1550.     0,                  /* escape_with_backslash_is_dangerous */
  1551.     &my_charset_ucs2_handler,
  1552.     &my_collation_ucs2_uca_handler
  1553. };
  1554. CHARSET_INFO my_charset_ucs2_spanish2_uca_ci=
  1555. {
  1556.     142,0,0, /* number       */
  1557.     MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
  1558.     "ucs2", /* cs name    */
  1559.     "ucs2_spanish2_ci", /* name         */
  1560.     "", /* comment      */
  1561.     spanish2, /* tailoring    */
  1562.     NULL, /* ctype        */
  1563.     NULL, /* to_lower     */
  1564.     NULL, /* to_upper     */
  1565.     NULL, /* sort_order   */
  1566.     NULL, /* contractions */
  1567.     NULL, /* sort_order_big*/
  1568.     NULL, /* tab_to_uni   */
  1569.     NULL, /* tab_from_uni */
  1570.     NULL, /* state_map    */
  1571.     NULL, /* ident_map    */
  1572.     8, /* strxfrm_multiply */
  1573.     2, /* mbminlen     */
  1574.     2, /* mbmaxlen     */
  1575.     9, /* min_sort_char */
  1576.     0xFFFF, /* max_sort_char */
  1577.     0,                  /* escape_with_backslash_is_dangerous */
  1578.     &my_charset_ucs2_handler,
  1579.     &my_collation_ucs2_uca_handler
  1580. };
  1581. CHARSET_INFO my_charset_ucs2_roman_uca_ci=
  1582. {
  1583.     143,0,0, /* number       */
  1584.     MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
  1585.     "ucs2", /* cs name    */
  1586.     "ucs2_roman_ci", /* name         */
  1587.     "", /* comment      */
  1588.     roman, /* tailoring    */
  1589.     NULL, /* ctype        */
  1590.     NULL, /* to_lower     */
  1591.     NULL, /* to_upper     */
  1592.     NULL, /* sort_order   */
  1593.     NULL, /* contractions */
  1594.     NULL, /* sort_order_big*/
  1595.     NULL, /* tab_to_uni   */
  1596.     NULL, /* tab_from_uni */
  1597.     NULL, /* state_map    */
  1598.     NULL, /* ident_map    */
  1599.     8, /* strxfrm_multiply */
  1600.     2, /* mbminlen     */
  1601.     2, /* mbmaxlen     */
  1602.     9, /* min_sort_char */
  1603.     0xFFFF, /* max_sort_char */
  1604.     0,                  /* escape_with_backslash_is_dangerous */
  1605.     &my_charset_ucs2_handler,
  1606.     &my_collation_ucs2_uca_handler
  1607. };
  1608. CHARSET_INFO my_charset_ucs2_persian_uca_ci=
  1609. {
  1610.     144,0,0, /* number       */
  1611.     MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
  1612.     "ucs2", /* cs name    */
  1613.     "ucs2_persian_ci", /* name         */
  1614.     "", /* comment      */
  1615.     persian, /* tailoring    */
  1616.     NULL, /* ctype        */
  1617.     NULL, /* to_lower     */
  1618.     NULL, /* to_upper     */
  1619.     NULL, /* sort_order   */
  1620.     NULL, /* contractions */
  1621.     NULL, /* sort_order_big*/
  1622.     NULL, /* tab_to_uni   */
  1623.     NULL, /* tab_from_uni */
  1624.     NULL, /* state_map    */
  1625.     NULL, /* ident_map    */
  1626.     8, /* strxfrm_multiply */
  1627.     2, /* mbminlen     */
  1628.     2, /* mbmaxlen     */
  1629.     9, /* min_sort_char */
  1630.     0xFFFF, /* max_sort_char */
  1631.     0,                  /* escape_with_backslash_is_dangerous */
  1632.     &my_charset_ucs2_handler,
  1633.     &my_collation_ucs2_uca_handler
  1634. };
  1635. #endif
  1636. #ifdef HAVE_CHARSET_utf8
  1637. MY_COLLATION_HANDLER my_collation_any_uca_handler =
  1638. {
  1639.     my_coll_init_uca, /* init */
  1640.     my_strnncoll_any_uca,
  1641.     my_strnncollsp_any_uca,
  1642.     my_strnxfrm_any_uca,
  1643.     my_like_range_mb,
  1644.     my_wildcmp_uca,
  1645.     NULL,
  1646.     my_instr_mb,
  1647.     my_hash_sort_any_uca
  1648. };
  1649. /* 
  1650.   We consider bytes with code more than 127 as a letter.
  1651.   This garantees that word boundaries work fine with regular
  1652.   expressions. Note, there is no need to mark byte 255  as a
  1653.   letter, it is illegal byte in UTF8.
  1654. */
  1655. static uchar ctype_utf8[] = {
  1656.     0,
  1657.    32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
  1658.    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
  1659.    72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
  1660.   132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16,
  1661.    16,129,129,129,129,129,129,  1,  1,  1,  1,  1,  1,  1,  1,  1,
  1662.     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 16, 16, 16, 16, 16,
  1663.    16,130,130,130,130,130,130,  2,  2,  2,  2,  2,  2,  2,  2,  2,
  1664.     2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 16, 16, 16, 16, 32,
  1665.     3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
  1666.     3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
  1667.     3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
  1668.     3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
  1669.     3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
  1670.     3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
  1671.     3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
  1672.     3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  0
  1673. };
  1674. extern MY_CHARSET_HANDLER my_charset_utf8_handler;
  1675. CHARSET_INFO my_charset_utf8_general_uca_ci=
  1676. {
  1677.     192,0,0, /* number       */
  1678.     MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
  1679.     "utf8", /* cs name    */
  1680.     "utf8_unicode_ci", /* name         */
  1681.     "", /* comment      */
  1682.     "", /* tailoring    */
  1683.     ctype_utf8, /* ctype        */
  1684.     NULL, /* to_lower     */
  1685.     NULL, /* to_upper     */
  1686.     uca_length, /* sort_order   */
  1687.     NULL, /* contractions */
  1688.     uca_weight, /* sort_order_big*/
  1689.     NULL, /* tab_to_uni   */
  1690.     NULL, /* tab_from_uni */
  1691.     NULL, /* state_map    */
  1692.     NULL, /* ident_map    */
  1693.     8, /* strxfrm_multiply */
  1694.     1, /* mbminlen     */
  1695.     3, /* mbmaxlen     */
  1696.     9, /* min_sort_char */
  1697.     0xFFFF, /* max_sort_char */
  1698.     0,                  /* escape_with_backslash_is_dangerous */
  1699.     &my_charset_utf8_handler,
  1700.     &my_collation_any_uca_handler
  1701. };
  1702. CHARSET_INFO my_charset_utf8_icelandic_uca_ci=
  1703. {
  1704.     193,0,0, /* number       */
  1705.     MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
  1706.     "utf8", /* cs name    */
  1707.     "utf8_icelandic_ci",/* name         */
  1708.     "", /* comment      */
  1709.     icelandic, /* tailoring    */
  1710.     ctype_utf8, /* ctype        */
  1711.     NULL, /* to_lower     */
  1712.     NULL, /* to_upper     */
  1713.     NULL, /* sort_order   */
  1714.     NULL, /* contractions */
  1715.     NULL, /* sort_order_big*/
  1716.     NULL, /* tab_to_uni   */
  1717.     NULL, /* tab_from_uni */
  1718.     NULL, /* state_map    */
  1719.     NULL, /* ident_map    */
  1720.     8, /* strxfrm_multiply */
  1721.     1, /* mbminlen     */
  1722.     3, /* mbmaxlen     */
  1723.     9, /* min_sort_char */
  1724.     0xFFFF, /* max_sort_char */
  1725.     0,                  /* escape_with_backslash_is_dangerous */
  1726.     &my_charset_utf8_handler,
  1727.     &my_collation_any_uca_handler
  1728. };
  1729. CHARSET_INFO my_charset_utf8_latvian_uca_ci=
  1730. {
  1731.     194,0,0, /* number       */
  1732.     MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
  1733.     "utf8", /* cs name    */
  1734.     "utf8_latvian_ci", /* name         */
  1735.     "", /* comment      */
  1736.     latvian, /* tailoring    */
  1737.     ctype_utf8, /* ctype        */
  1738.     NULL, /* to_lower     */
  1739.     NULL, /* to_upper     */
  1740.     NULL, /* sort_order   */
  1741.     NULL, /* contractions */
  1742.     NULL, /* sort_order_big*/
  1743.     NULL, /* tab_to_uni   */
  1744.     NULL, /* tab_from_uni */
  1745.     NULL, /* state_map    */
  1746.     NULL, /* ident_map    */
  1747.     8, /* strxfrm_multiply */
  1748.     1, /* mbminlen     */
  1749.     3, /* mbmaxlen     */
  1750.     9, /* min_sort_char */
  1751.     0xFFFF, /* max_sort_char */
  1752.     0,                  /* escape_with_backslash_is_dangerous */
  1753.     &my_charset_utf8_handler,
  1754.     &my_collation_any_uca_handler
  1755. };
  1756. CHARSET_INFO my_charset_utf8_romanian_uca_ci=
  1757. {
  1758.     195,0,0, /* number       */
  1759.     MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
  1760.     "utf8", /* cs name    */
  1761.     "utf8_romanian_ci", /* name         */
  1762.     "", /* comment      */
  1763.     romanian, /* tailoring    */
  1764.     ctype_utf8, /* ctype        */
  1765.     NULL, /* to_lower     */
  1766.     NULL, /* to_upper     */
  1767.     NULL, /* sort_order   */
  1768.     NULL, /* contractions */
  1769.     NULL, /* sort_order_big*/
  1770.     NULL, /* tab_to_uni   */
  1771.     NULL, /* tab_from_uni */
  1772.     NULL, /* state_map    */
  1773.     NULL, /* ident_map    */
  1774.     8, /* strxfrm_multiply */
  1775.     1, /* mbminlen     */
  1776.     3, /* mbmaxlen     */
  1777.     9, /* min_sort_char */
  1778.     0xFFFF, /* max_sort_char */
  1779.     0,                  /* escape_with_backslash_is_dangerous */
  1780.     &my_charset_utf8_handler,
  1781.     &my_collation_any_uca_handler
  1782. };
  1783. CHARSET_INFO my_charset_utf8_slovenian_uca_ci=
  1784. {
  1785.     196,0,0, /* number       */
  1786.     MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
  1787.     "utf8", /* cs name    */
  1788.     "utf8_slovenian_ci",/* name         */
  1789.     "", /* comment      */
  1790.     slovenian, /* tailoring    */
  1791.     ctype_utf8, /* ctype        */
  1792.     NULL, /* to_lower     */
  1793.     NULL, /* to_upper     */
  1794.     NULL, /* sort_order   */
  1795.     NULL, /* contractions */
  1796.     NULL, /* sort_order_big*/
  1797.     NULL, /* tab_to_uni   */
  1798.     NULL, /* tab_from_uni */
  1799.     NULL, /* state_map    */
  1800.     NULL, /* ident_map    */
  1801.     8, /* strxfrm_multiply */
  1802.     1, /* mbminlen     */
  1803.     3, /* mbmaxlen     */
  1804.     9, /* min_sort_char */
  1805.     0xFFFF, /* max_sort_char */
  1806.     0,                  /* escape_with_backslash_is_dangerous */
  1807.     &my_charset_utf8_handler,
  1808.     &my_collation_any_uca_handler
  1809. };
  1810. CHARSET_INFO my_charset_utf8_polish_uca_ci=
  1811. {
  1812.     197,0,0, /* number       */
  1813.     MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
  1814.     "utf8", /* cs name    */
  1815.     "utf8_polish_ci", /* name         */
  1816.     "", /* comment      */
  1817.     polish, /* tailoring    */
  1818.     ctype_utf8, /* ctype        */
  1819.     NULL, /* to_lower     */
  1820.     NULL, /* to_upper     */
  1821.     NULL, /* sort_order   */
  1822.     NULL, /* contractions */
  1823.     NULL, /* sort_order_big*/
  1824.     NULL, /* tab_to_uni   */
  1825.     NULL, /* tab_from_uni */
  1826.     NULL, /* state_map    */
  1827.     NULL, /* ident_map    */
  1828.     8, /* strxfrm_multiply */
  1829.     1, /* mbminlen     */
  1830.     3, /* mbmaxlen     */
  1831.     9, /* min_sort_char */
  1832.     0xFFFF, /* max_sort_char */
  1833.     0,                  /* escape_with_backslash_is_dangerous */
  1834.     &my_charset_utf8_handler,
  1835.     &my_collation_any_uca_handler
  1836. };
  1837. CHARSET_INFO my_charset_utf8_estonian_uca_ci=
  1838. {
  1839.     198,0,0, /* number       */
  1840.     MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
  1841.     "utf8", /* cs name    */
  1842.     "utf8_estonian_ci", /* name         */
  1843.     "", /* comment      */
  1844.     estonian, /* tailoring    */
  1845.     ctype_utf8, /* ctype        */
  1846.     NULL, /* to_lower     */
  1847.     NULL, /* to_upper     */
  1848.     NULL, /* sort_order   */
  1849.     NULL, /* contractions */
  1850.     NULL, /* sort_order_big*/
  1851.     NULL, /* tab_to_uni   */
  1852.     NULL, /* tab_from_uni */
  1853.     NULL, /* state_map    */
  1854.     NULL, /* ident_map    */
  1855.     8, /* strxfrm_multiply */
  1856.     1, /* mbminlen     */
  1857.     3, /* mbmaxlen     */
  1858.     9, /* min_sort_char */
  1859.     0xFFFF, /* max_sort_char */
  1860.     0,                  /* escape_with_backslash_is_dangerous */
  1861.     &my_charset_utf8_handler,
  1862.     &my_collation_any_uca_handler
  1863. };
  1864. CHARSET_INFO my_charset_utf8_spanish_uca_ci=
  1865. {
  1866.     199,0,0, /* number       */
  1867.     MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
  1868.     "utf8", /* cs name    */
  1869.     "utf8_spanish_ci", /* name         */
  1870.     "", /* comment      */
  1871.     spanish, /* tailoring    */
  1872.     ctype_utf8, /* ctype        */
  1873.     NULL, /* to_lower     */
  1874.     NULL, /* to_upper     */
  1875.     NULL, /* sort_order   */
  1876.     NULL, /* contractions */
  1877.     NULL, /* sort_order_big*/
  1878.     NULL, /* tab_to_uni   */
  1879.     NULL, /* tab_from_uni */
  1880.     NULL, /* state_map    */
  1881.     NULL, /* ident_map    */
  1882.     8, /* strxfrm_multiply */
  1883.     1, /* mbminlen     */
  1884.     3, /* mbmaxlen     */
  1885.     9, /* min_sort_char */
  1886.     0xFFFF, /* max_sort_char */
  1887.     0,                  /* escape_with_backslash_is_dangerous */
  1888.     &my_charset_utf8_handler,
  1889.     &my_collation_any_uca_handler
  1890. };
  1891. CHARSET_INFO my_charset_utf8_swedish_uca_ci=
  1892. {
  1893.     200,0,0, /* number       */
  1894.     MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
  1895.     "utf8", /* cs name    */
  1896.     "utf8_swedish_ci", /* name         */
  1897.     "", /* comment      */
  1898.     swedish, /* tailoring    */
  1899.     ctype_utf8, /* ctype        */
  1900.     NULL, /* to_lower     */
  1901.     NULL, /* to_upper     */
  1902.     NULL, /* sort_order   */
  1903.     NULL, /* contractions */
  1904.     NULL, /* sort_order_big*/
  1905.     NULL, /* tab_to_uni   */
  1906.     NULL, /* tab_from_uni */
  1907.     NULL, /* state_map    */
  1908.     NULL, /* ident_map    */
  1909.     8, /* strxfrm_multiply */
  1910.     1, /* mbminlen     */
  1911.     3, /* mbmaxlen     */
  1912.     9, /* min_sort_char */
  1913.     0xFFFF, /* max_sort_char */
  1914.     0,                  /* escape_with_backslash_is_dangerous */
  1915.     &my_charset_utf8_handler,
  1916.     &my_collation_any_uca_handler
  1917. };
  1918. CHARSET_INFO my_charset_utf8_turkish_uca_ci=
  1919. {
  1920.     201,0,0, /* number       */
  1921.     MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
  1922.     "utf8", /* cs name    */
  1923.     "utf8_turkish_ci", /* name         */
  1924.     "", /* comment      */
  1925.     turkish, /* tailoring    */
  1926.     ctype_utf8, /* ctype        */
  1927.     NULL, /* to_lower     */
  1928.     NULL, /* to_upper     */
  1929.     NULL, /* sort_order   */
  1930.     NULL, /* contractions */
  1931.     NULL, /* sort_order_big*/
  1932.     NULL, /* tab_to_uni   */
  1933.     NULL, /* tab_from_uni */
  1934.     NULL, /* state_map    */
  1935.     NULL, /* ident_map    */
  1936.     8, /* strxfrm_multiply */
  1937.     1, /* mbminlen     */
  1938.     3, /* mbmaxlen     */
  1939.     9, /* min_sort_char */
  1940.     0xFFFF, /* max_sort_char */
  1941.     0,                  /* escape_with_backslash_is_dangerous */
  1942.     &my_charset_utf8_handler,
  1943.     &my_collation_any_uca_handler
  1944. };
  1945. CHARSET_INFO my_charset_utf8_czech_uca_ci=
  1946. {
  1947.     202,0,0, /* number       */
  1948.     MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
  1949.     "utf8", /* cs name    */
  1950.     "utf8_czech_ci", /* name         */
  1951.     "", /* comment      */
  1952.     czech, /* tailoring    */
  1953.     ctype_utf8, /* ctype        */
  1954.     NULL, /* to_lower     */
  1955.     NULL, /* to_upper     */
  1956.     NULL, /* sort_order   */
  1957.     NULL, /* contractions */
  1958.     NULL, /* sort_order_big*/
  1959.     NULL, /* tab_to_uni   */
  1960.     NULL, /* tab_from_uni */
  1961.     NULL, /* state_map    */
  1962.     NULL, /* ident_map    */
  1963.     8, /* strxfrm_multiply */
  1964.     1, /* mbminlen     */
  1965.     3, /* mbmaxlen     */
  1966.     9, /* min_sort_char */
  1967.     0xFFFF, /* max_sort_char */
  1968.     0,                  /* escape_with_backslash_is_dangerous */
  1969.     &my_charset_utf8_handler,
  1970.     &my_collation_any_uca_handler
  1971. };
  1972. CHARSET_INFO my_charset_utf8_danish_uca_ci=
  1973. {
  1974.     203,0,0, /* number       */
  1975.     MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
  1976.     "utf8", /* cs name    */
  1977.     "utf8_danish_ci", /* name         */
  1978.     "", /* comment      */
  1979.     danish, /* tailoring    */
  1980.     ctype_utf8, /* ctype        */
  1981.     NULL, /* to_lower     */
  1982.     NULL, /* to_upper     */
  1983.     NULL, /* sort_order   */
  1984.     NULL, /* contractions */
  1985.     NULL, /* sort_order_big*/
  1986.     NULL, /* tab_to_uni   */
  1987.     NULL, /* tab_from_uni */
  1988.     NULL, /* state_map    */
  1989.     NULL, /* ident_map    */
  1990.     8, /* strxfrm_multiply */
  1991.     1, /* mbminlen     */
  1992.     3, /* mbmaxlen     */
  1993.     9, /* min_sort_char */
  1994.     0xFFFF, /* max_sort_char */
  1995.     0,                  /* escape_with_backslash_is_dangerous */
  1996.     &my_charset_utf8_handler,
  1997.     &my_collation_any_uca_handler
  1998. };
  1999. CHARSET_INFO my_charset_utf8_lithuanian_uca_ci=
  2000. {
  2001.     204,0,0, /* number       */
  2002.     MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
  2003.     "utf8", /* cs name    */
  2004.     "utf8_lithuanian_ci",/* name         */
  2005.     "", /* comment      */
  2006.     lithuanian, /* tailoring    */
  2007.     ctype_utf8, /* ctype        */
  2008.     NULL, /* to_lower     */
  2009.     NULL, /* to_upper     */
  2010.     NULL, /* sort_order   */
  2011.     NULL, /* contractions */
  2012.     NULL, /* sort_order_big*/
  2013.     NULL, /* tab_to_uni   */
  2014.     NULL, /* tab_from_uni */
  2015.     NULL, /* state_map    */
  2016.     NULL, /* ident_map    */
  2017.     8, /* strxfrm_multiply */
  2018.     1, /* mbminlen     */
  2019.     3, /* mbmaxlen     */
  2020.     9, /* min_sort_char */
  2021.     0xFFFF, /* max_sort_char */
  2022.     0,                  /* escape_with_backslash_is_dangerous */
  2023.     &my_charset_utf8_handler,
  2024.     &my_collation_any_uca_handler
  2025. };
  2026. CHARSET_INFO my_charset_utf8_slovak_uca_ci=
  2027. {
  2028.     205,0,0, /* number       */
  2029.     MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
  2030.     "utf8", /* cs name    */
  2031.     "utf8_slovak_ci", /* name         */
  2032.     "", /* comment      */
  2033.     slovak, /* tailoring    */
  2034.     ctype_utf8, /* ctype        */
  2035.     NULL, /* to_lower     */
  2036.     NULL, /* to_upper     */
  2037.     NULL, /* sort_order   */
  2038.     NULL, /* contractions */
  2039.     NULL, /* sort_order_big*/
  2040.     NULL, /* tab_to_uni   */
  2041.     NULL, /* tab_from_uni */
  2042.     NULL, /* state_map    */
  2043.     NULL, /* ident_map    */
  2044.     8, /* strxfrm_multiply */
  2045.     1, /* mbminlen     */
  2046.     3, /* mbmaxlen     */
  2047.     9, /* min_sort_char */
  2048.     0xFFFF, /* max_sort_char */
  2049.     0,                  /* escape_with_backslash_is_dangerous */
  2050.     &my_charset_utf8_handler,
  2051.     &my_collation_any_uca_handler
  2052. };
  2053. CHARSET_INFO my_charset_utf8_spanish2_uca_ci=
  2054. {
  2055.     206,0,0, /* number       */
  2056.     MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
  2057.     "utf8", /* cs name    */
  2058.     "utf8_spanish2_ci", /* name         */
  2059.     "", /* comment      */
  2060.     spanish2, /* tailoring    */
  2061.     ctype_utf8, /* ctype        */
  2062.     NULL, /* to_lower     */
  2063.     NULL, /* to_upper     */
  2064.     NULL, /* sort_order   */
  2065.     NULL, /* contractions */
  2066.     NULL, /* sort_order_big*/
  2067.     NULL, /* tab_to_uni   */
  2068.     NULL, /* tab_from_uni */
  2069.     NULL, /* state_map    */
  2070.     NULL, /* ident_map    */
  2071.     8, /* strxfrm_multiply */
  2072.     1, /* mbminlen     */
  2073.     3, /* mbmaxlen     */
  2074.     9, /* min_sort_char */
  2075.     0xFFFF, /* max_sort_char */
  2076.     0,                  /* escape_with_backslash_is_dangerous */
  2077.     &my_charset_utf8_handler,
  2078.     &my_collation_any_uca_handler
  2079. };
  2080. CHARSET_INFO my_charset_utf8_roman_uca_ci=
  2081. {
  2082.     207,0,0, /* number       */
  2083.     MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
  2084.     "utf8", /* cs name    */
  2085.     "utf8_roman_ci", /* name         */
  2086.     "", /* comment      */
  2087.     roman, /* tailoring    */
  2088.     ctype_utf8, /* ctype        */
  2089.     NULL, /* to_lower     */
  2090.     NULL, /* to_upper     */
  2091.     NULL, /* sort_order   */
  2092.     NULL, /* contractions */
  2093.     NULL, /* sort_order_big*/
  2094.     NULL, /* tab_to_uni   */
  2095.     NULL, /* tab_from_uni */
  2096.     NULL, /* state_map    */
  2097.     NULL, /* ident_map    */
  2098.     8, /* strxfrm_multiply */
  2099.     1, /* mbminlen     */
  2100.     3, /* mbmaxlen     */
  2101.     9, /* min_sort_char */
  2102.     0xFFFF, /* max_sort_char */
  2103.     0,                  /* escape_with_backslash_is_dangerous */
  2104.     &my_charset_utf8_handler,
  2105.     &my_collation_any_uca_handler
  2106. };
  2107. CHARSET_INFO my_charset_utf8_persian_uca_ci=
  2108. {
  2109.     208,0,0, /* number       */
  2110.     MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
  2111.     "utf8", /* cs name    */
  2112.     "utf8_persian_ci", /* name         */
  2113.     "", /* comment      */
  2114.     persian, /* tailoring    */
  2115.     ctype_utf8, /* ctype        */
  2116.     NULL, /* to_lower     */
  2117.     NULL, /* to_upper     */
  2118.     NULL, /* sort_order   */
  2119.     NULL, /* contractions */
  2120.     NULL, /* sort_order_big*/
  2121.     NULL, /* tab_to_uni   */
  2122.     NULL, /* tab_from_uni */
  2123.     NULL, /* state_map    */
  2124.     NULL, /* ident_map    */
  2125.     8, /* strxfrm_multiply */
  2126.     1, /* mbminlen     */
  2127.     3, /* mbmaxlen     */
  2128.     9, /* min_sort_char */
  2129.     0xFFFF, /* max_sort_char */
  2130.     0,                  /* escape_with_backslash_is_dangerous */
  2131.     &my_charset_utf8_handler,
  2132.     &my_collation_any_uca_handler
  2133. };
  2134. #endif /* HAVE_CHARSET_utf8 */
  2135. #endif /* HAVE_UCA_COLLATIONS */