Drizzled Public API Documentation

ctype-bin.cc
00001 /* Copyright (C) 2002 MySQL AB & tommy@valley.ne.jp.
00002 
00003    This library is free software; you can redistribute it and/or
00004    modify it under the terms of the GNU Library General Public
00005    License as published by the Free Software Foundation; version 2
00006    of the License.
00007 
00008    This library is distributed in the hope that it will be useful,
00009    but WITHOUT ANY WARRANTY; without even the implied warranty of
00010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011    Library General Public License for more details.
00012 
00013    You should have received a copy of the GNU Library General Public
00014    License along with this library; if not, write to the Free
00015    Software Foundation, Inc., 51 Franklin Place - Suite 330, Boston,
00016    MA 02110-1301, USA */
00017 
00018 /* This file is for binary pseudo charset, created by bar@mysql.com */
00019 
00020 
00021 #include <config.h>
00022 #include <drizzled/definitions.h>
00023 #include <drizzled/internal/m_string.h>
00024 #include <drizzled/charset.h>
00025 
00026 #include <algorithm>
00027 
00028 using namespace std;
00029 
00030 namespace drizzled {
00031 
00032 void my_hash_sort_bin(const charset_info_st * const,
00033                       const unsigned char *key, size_t len,
00034                       uint32_t *nr1, uint32_t *nr2);
00035 
00036 
00037 static unsigned char ctype_bin[]=
00038 {
00039   0,
00040   32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
00041   32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
00042   72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
00043   132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16,
00044   16,129,129,129,129,129,129,  1,  1,  1,  1,  1,  1,  1,  1,  1,
00045   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 16, 16, 16, 16, 16,
00046   16,130,130,130,130,130,130,  2,  2,  2,  2,  2,  2,  2,  2,  2,
00047   2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 16, 16, 16, 16, 32,
00048   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
00049   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
00050   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
00051   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
00052   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
00053   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
00054   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
00055   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
00056 };
00057 
00058 
00059 /* Dummy array for toupper / tolower / sortorder */
00060 
00061 static unsigned char bin_char_array[] =
00062 {
00063     0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
00064    16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
00065    32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
00066    48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
00067    64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
00068    80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
00069    96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
00070   112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
00071   128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
00072   144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
00073   160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
00074   176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
00075   192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
00076   208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
00077   224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
00078   240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
00079 };
00080 
00081 
00082 int my_strnncoll_binary(const charset_info_st * const,
00083                         const unsigned char *s, size_t slen,
00084                         const unsigned char *t, size_t tlen,
00085                         bool t_is_prefix)
00086 {
00087   size_t len= min(slen,tlen);
00088   int cmp= memcmp(s,t,len);
00089   return cmp ? cmp : static_cast<int>((t_is_prefix ? len : slen) - tlen);
00090 }
00091 
00092 
00093 size_t my_lengthsp_binary(const charset_info_st * const,
00094                           const char *, size_t length)
00095 {
00096   return length;
00097 }
00098 
00099 
00100 /*
00101   Compare two strings. Result is sign(first_argument - second_argument)
00102 
00103   SYNOPSIS
00104     my_strnncollsp_binary()
00105     cs      Chararacter set
00106     s     String to compare
00107     slen    Length of 's'
00108     t     String to compare
00109     tlen    Length of 't'
00110 
00111   NOTE
00112    This function is used for real binary strings, i.e. for
00113    BLOB, BINARY(N) and VARBINARY(N).
00114    It compares trailing spaces as spaces.
00115 
00116   RETURN
00117   < 0 s < t
00118   0 s == t
00119   > 0 s > t
00120 */
00121 
00122 int my_strnncollsp_binary(const charset_info_st * const cs,
00123                           const unsigned char *s, size_t slen,
00124                           const unsigned char *t, size_t tlen,
00125                           bool)
00126 {
00127   return my_strnncoll_binary(cs,s,slen,t,tlen,0);
00128 }
00129 
00130 
00131 int my_strnncoll_8bit_bin(const charset_info_st * const,
00132                           const unsigned char *s, size_t slen,
00133                           const unsigned char *t, size_t tlen,
00134                           bool t_is_prefix)
00135 {
00136   size_t len= min(slen,tlen);
00137   int cmp= memcmp(s,t,len);
00138   return cmp ? cmp : static_cast<int>((t_is_prefix ? len : slen) - tlen);
00139 }
00140 
00141 
00142 /*
00143   Compare two strings. Result is sign(first_argument - second_argument)
00144 
00145   SYNOPSIS
00146     my_strnncollsp_8bit_bin()
00147     cs      Chararacter set
00148     s     String to compare
00149     slen    Length of 's'
00150     t     String to compare
00151     tlen    Length of 't'
00152     diff_if_only_endspace_difference
00153             Set to 1 if the strings should be regarded as different
00154                         if they only difference in end space
00155 
00156   NOTE
00157    This function is used for character strings with binary collations.
00158    The shorter string is extended with end space to be as long as the longer
00159    one.
00160 
00161   RETURN
00162   < 0 s < t
00163   0 s == t
00164   > 0 s > t
00165 */
00166 
00167 int my_strnncollsp_8bit_bin(const charset_info_st * const,
00168                             const unsigned char *a, size_t a_length,
00169                             const unsigned char *b, size_t b_length,
00170                             bool diff_if_only_endspace_difference)
00171 {
00172   const unsigned char *end;
00173   size_t length;
00174   int res;
00175 
00176 #ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE
00177   diff_if_only_endspace_difference= 0;
00178 #endif
00179 
00180   end= a + (length= min(a_length, b_length));
00181   while (a < end)
00182   {
00183     if (*a++ != *b++)
00184       return a[-1] - b[-1];
00185   }
00186   res= 0;
00187   if (a_length != b_length)
00188   {
00189     int swap= 1;
00190     /*
00191       Check the next not space character of the longer key. If it's < ' ',
00192       then it's smaller than the other key.
00193     */
00194     if (diff_if_only_endspace_difference)
00195       res= 1;                                   /* Assume 'a' is bigger */
00196     if (a_length < b_length)
00197     {
00198       /* put shorter key in s */
00199       a_length= b_length;
00200       a= b;
00201       swap= -1;         /* swap sign of result */
00202       res= -res;
00203     }
00204     for (end= a + a_length-length; a < end ; a++)
00205     {
00206       if (*a != ' ')
00207   return (*a < ' ') ? -swap : swap;
00208     }
00209   }
00210   return res;
00211 }
00212 
00213 
00214 /* This function is used for all conversion functions */
00215 
00216 size_t my_case_str_bin(const charset_info_st * const, char *)
00217 {
00218   return 0;
00219 }
00220 
00221 
00222 size_t my_case_bin(const charset_info_st * const, char *,
00223                    size_t srclen, char *, size_t)
00224 {
00225   return srclen;
00226 }
00227 
00228 
00229 int my_strcasecmp_bin(const charset_info_st * const,
00230                       const char *s, const char *t)
00231 {
00232   return strcmp(s,t);
00233 }
00234 
00235 
00236 uint32_t my_mbcharlen_8bit(const charset_info_st * const, uint32_t)
00237 {
00238   return 1;
00239 }
00240 
00241 
00242 int my_mb_wc_bin(const charset_info_st * const,
00243                  my_wc_t *wc, const unsigned char *str,
00244                  const unsigned char *end)
00245 {
00246   if (str >= end)
00247     return MY_CS_TOOSMALL;
00248 
00249   *wc=str[0];
00250   return 1;
00251 }
00252 
00253 
00254 int my_wc_mb_bin(const charset_info_st * const, my_wc_t wc,
00255                  unsigned char *str, unsigned char *end)
00256 {
00257   if (str >= end)
00258     return MY_CS_TOOSMALL;
00259 
00260   if (wc < 256)
00261   {
00262     str[0]= wc;
00263     return 1;
00264   }
00265   return MY_CS_ILUNI;
00266 }
00267 
00268 
00269 void my_hash_sort_8bit_bin(const charset_info_st * const,
00270                            const unsigned char *key, size_t len,
00271                            uint32_t *nr1, uint32_t *nr2)
00272 {
00273   const unsigned char *pos = key;
00274 
00275   /*
00276      Remove trailing spaces. We have to do this to be able to compare
00277     'A ' and 'A' as identical
00278   */
00279   key= internal::skip_trailing_space(key, len);
00280 
00281   for (; pos < key ; pos++)
00282   {
00283     nr1[0]^= (((nr1[0] & 63) + nr2[0]) * *pos) + (nr1[0] << 8);
00284     nr2[0]+=3;
00285   }
00286 }
00287 
00288 
00289 void my_hash_sort_bin(const charset_info_st * const,
00290                       const unsigned char *key, size_t len,
00291                       uint32_t *nr1, uint32_t *nr2)
00292 {
00293   const unsigned char *pos = key;
00294 
00295   key+= len;
00296 
00297   for (; pos < key ; pos++)
00298   {
00299     nr1[0]^= (((nr1[0] & 63) + nr2[0]) * *pos) + (nr1[0] << 8);
00300     nr2[0]+=3;
00301   }
00302 }
00303 
00304 
00305 /*
00306   The following defines is here to keep the following code identical to
00307   the one in ctype-simple.c
00308 */
00309 
00310 #define likeconv(s,A) (A)
00311 #define INC_PTR(cs,A,B) (A)++
00312 
00313 
00314 int my_wildcmp_bin(const charset_info_st * const cs,
00315                    const char *str,const char *str_end,
00316                    const char *wildstr,const char *wildend,
00317                    int escape, int w_one, int w_many)
00318 {
00319   int result= -1;     /* Not found, using wildcards */
00320 
00321   while (wildstr != wildend)
00322   {
00323     while (*wildstr != w_many && *wildstr != w_one)
00324     {
00325       if (*wildstr == escape && wildstr+1 != wildend)
00326   wildstr++;
00327       if (str == str_end || likeconv(cs,*wildstr++) != likeconv(cs,*str++))
00328   return 1;     /* No match */
00329       if (wildstr == wildend)
00330   return(str != str_end);   /* Match if both are at end */
00331       result=1;       /* Found an anchor char */
00332     }
00333     if (*wildstr == w_one)
00334     {
00335       do
00336       {
00337   if (str == str_end)   /* Skip one char if possible */
00338     return(result);
00339   INC_PTR(cs,str,str_end);
00340       } while (++wildstr < wildend && *wildstr == w_one);
00341       if (wildstr == wildend)
00342   break;
00343     }
00344     if (*wildstr == w_many)
00345     {         /* Found w_many */
00346       unsigned char cmp;
00347       wildstr++;
00348       /* Remove any '%' and '_' from the wild search string */
00349       for (; wildstr != wildend ; wildstr++)
00350       {
00351   if (*wildstr == w_many)
00352     continue;
00353   if (*wildstr == w_one)
00354   {
00355     if (str == str_end)
00356       return(-1);
00357     INC_PTR(cs,str,str_end);
00358     continue;
00359   }
00360   break;        /* Not a wild character */
00361       }
00362       if (wildstr == wildend)
00363   return 0;     /* match if w_many is last */
00364       if (str == str_end)
00365   return(-1);
00366 
00367       if ((cmp= *wildstr) == escape && wildstr+1 != wildend)
00368   cmp= *++wildstr;
00369 
00370       INC_PTR(cs,wildstr,wildend);  /* This is compared through cmp */
00371       cmp=likeconv(cs,cmp);
00372       do
00373       {
00374   while (str != str_end && (unsigned char) likeconv(cs,*str) != cmp)
00375     str++;
00376   if (str++ == str_end)
00377     return(-1);
00378   {
00379     int tmp=my_wildcmp_bin(cs,str,str_end,wildstr,wildend,escape,w_one,
00380          w_many);
00381     if (tmp <= 0)
00382       return(tmp);
00383   }
00384       } while (str != str_end && wildstr[0] != w_many);
00385       return(-1);
00386     }
00387   }
00388   return(str != str_end ? 1 : 0);
00389 }
00390 
00391 
00392 size_t
00393 my_strnxfrm_8bit_bin(const charset_info_st * const cs,
00394                      unsigned char * dst, size_t dstlen, uint32_t nweights,
00395                      const unsigned char *src, size_t srclen, uint32_t flags)
00396 {
00397   set_if_smaller(srclen, dstlen);
00398   set_if_smaller(srclen, (size_t) nweights);
00399   if (dst != src)
00400     memcpy(dst, src, srclen);
00401   return my_strxfrm_pad_desc_and_reverse(cs, dst, dst + srclen, dst + dstlen,
00402                                          nweights - srclen, flags, 0);
00403 }
00404 
00405 
00406 uint32_t my_instr_bin(const charset_info_st * const,
00407                       const char *b, size_t b_length,
00408                       const char *s, size_t s_length,
00409                       my_match_t *match, uint32_t nmatch)
00410 {
00411   const unsigned char *str, *search, *end, *search_end;
00412 
00413   if (s_length <= b_length)
00414   {
00415     if (!s_length)
00416     {
00417       if (nmatch)
00418       {
00419         match->beg= 0;
00420         match->end= 0;
00421         match->mb_len= 0;
00422       }
00423       return 1;   /* Empty string is always found */
00424     }
00425 
00426     str= (const unsigned char*) b;
00427     search= (const unsigned char*) s;
00428     end= (const unsigned char*) b+b_length-s_length+1;
00429     search_end= (const unsigned char*) s + s_length;
00430 
00431 skip:
00432     while (str != end)
00433     {
00434       if ( (*str++) == (*search))
00435       {
00436   const unsigned char *i,*j;
00437 
00438   i= str;
00439   j= search+1;
00440 
00441   while (j != search_end)
00442     if ((*i++) != (*j++))
00443             goto skip;
00444 
00445         if (nmatch > 0)
00446   {
00447     match[0].beg= 0;
00448     match[0].end= (size_t) (str- (const unsigned char*)b-1);
00449     match[0].mb_len= match[0].end;
00450 
00451     if (nmatch > 1)
00452     {
00453       match[1].beg= match[0].end;
00454       match[1].end= match[0].end+s_length;
00455       match[1].mb_len= match[1].end-match[1].beg;
00456     }
00457   }
00458   return 2;
00459       }
00460     }
00461   }
00462   return 0;
00463 }
00464 
00465 
00466 static MY_COLLATION_HANDLER my_collation_binary_handler =
00467 {
00468   NULL,     /* init */
00469   my_strnncoll_binary,
00470   my_strnncollsp_binary,
00471   my_strnxfrm_8bit_bin,
00472   my_strnxfrmlen_simple,
00473   my_like_range_simple,
00474   my_wildcmp_bin,
00475   my_strcasecmp_bin,
00476   my_instr_bin,
00477   my_hash_sort_bin,
00478   my_propagate_simple
00479 };
00480 
00481 
00482 static MY_CHARSET_HANDLER my_charset_handler=
00483 {
00484   NULL,     /* ismbchar      */
00485   my_mbcharlen_8bit,  /* mbcharlen     */
00486   my_numchars_8bit,
00487   my_charpos_8bit,
00488   my_well_formed_len_8bit,
00489   my_lengthsp_binary,
00490   my_numcells_8bit,
00491   my_mb_wc_bin,
00492   my_wc_mb_bin,
00493   my_mb_ctype_8bit,
00494   my_case_str_bin,
00495   my_case_str_bin,
00496   my_case_bin,
00497   my_case_bin,
00498   my_snprintf_8bit,
00499   my_long10_to_str_8bit,
00500   my_int64_t10_to_str_8bit,
00501   my_fill_8bit,
00502   my_strntol_8bit,
00503   my_strntoul_8bit,
00504   my_strntoll_8bit,
00505   my_strntoull_8bit,
00506   my_strntod_8bit,
00507   my_strtoll10_8bit,
00508   my_strntoull10rnd_8bit,
00509   my_scan_8bit
00510 };
00511 
00512 
00513 DRIZZLED_API charset_info_st my_charset_bin =
00514 {
00515     63,0,0,     /* number        */
00516     MY_CS_COMPILED|MY_CS_BINSORT|MY_CS_PRIMARY,/* state */
00517     "binary",     /* cs name    */
00518     "binary",     /* name          */
00519     "",       /* comment       */
00520     NULL,     /* tailoring     */
00521     ctype_bin,      /* ctype         */
00522     bin_char_array,   /* to_lower      */
00523     bin_char_array,   /* to_upper      */
00524     NULL,     /* sort_order    */
00525     NULL,     /* contractions */
00526     NULL,     /* sort_order_big*/
00527     NULL,     /* tab_to_uni    */
00528     NULL,     /* tab_from_uni  */
00529     my_unicase_default,         /* caseinfo     */
00530     NULL,     /* state_map    */
00531     NULL,     /* ident_map    */
00532     1,        /* strxfrm_multiply */
00533     1,                          /* caseup_multiply  */
00534     1,                          /* casedn_multiply  */
00535     1,        /* mbminlen      */
00536     1,        /* mbmaxlen      */
00537     0,        /* min_sort_char */
00538     255,      /* max_sort_char */
00539     0,                          /* pad char      */
00540     1,                          /* levels_for_compare */
00541     1,                          /* levels_for_order   */
00542     &my_charset_handler,
00543     &my_collation_binary_handler
00544 };
00545 
00546 } /* namespace drizzled */