~drizzle-pbxt/drizzle/drizzle-pbxt-4-pbxt

« back to all changes in this revision

Viewing changes to drizzled/ctype-simple.cc

  • Committer: Vladimir Kolesnikov
  • Date: 2010-03-10 13:00:36 UTC
  • mfrom: (1014.3.309 staging)
  • Revision ID: vladimir@primebase.org-20100310130036-gu5qlkwld3rn8g12
merge from upstream lp:drizzle rev.1323

Show diffs side-by-side

added added

removed removed

Lines of Context:
13
13
   along with this program; if not, write to the Free Software
14
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
 
#include "drizzled/global.h"
17
 
 
18
 
#include "m_string.h"
19
 
#include "m_ctype.h"
20
 
#include <errno.h>
21
 
#include <stdio.h>
22
 
#include <stdlib.h>
23
 
 
24
 
#include "stdarg.h"
 
16
#include "config.h"
 
17
 
 
18
#include "drizzled/internal/m_string.h"
 
19
#include "drizzled/charset_info.h"
 
20
#include <cerrno>
 
21
#include <cstdio>
 
22
#include <cstdlib>
 
23
 
 
24
#include <stdarg.h>
25
25
 
26
26
#include <algorithm>
27
27
 
28
28
using namespace std;
29
29
 
 
30
namespace drizzled
 
31
{
30
32
 
31
33
/*
32
34
  Returns the number of bytes required for strnxfrm().
39
41
 
40
42
 
41
43
/*
42
 
  Converts a string into its sort key.
43
 
 
44
 
  SYNOPSIS
45
 
     my_strnxfrm_xxx()
46
 
 
47
 
  IMPLEMENTATION
48
 
 
49
 
     The my_strxfrm_xxx() function transforms a string pointed to by
50
 
     'src' with length 'srclen' according to the charset+collation
51
 
     pair 'cs' and copies the result key into 'dest'.
52
 
 
53
 
     Comparing two strings using memcmp() after my_strnxfrm_xxx()
54
 
     is equal to comparing two original strings with my_strnncollsp_xxx().
55
 
 
56
 
     Not more than 'dstlen' bytes are written into 'dst'.
57
 
     To garantee that the whole string is transformed, 'dstlen' must be
58
 
     at least srclen*cs->strnxfrm_multiply bytes long. Otherwise,
59
 
     consequent memcmp() may return a non-accurate result.
60
 
 
61
 
     If the source string is too short to fill whole 'dstlen' bytes,
62
 
     then the 'dest' string is padded up to 'dstlen', ensuring that:
63
 
 
64
 
       "a"  == "a "
65
 
       "a\0" < "a"
66
 
       "a\0" < "a "
67
 
 
68
 
     my_strnxfrm_simple() is implemented for 8bit charsets and
69
 
     simple collations with one-to-one string->key transformation.
70
 
 
71
 
     See also implementations for various charsets/collations in
72
 
     other ctype-xxx.c files.
73
 
 
74
 
  RETURN
75
 
 
76
 
    Target len 'dstlen'.
77
 
 
78
 
*/
79
 
 
80
 
 
81
 
size_t my_strnxfrm_simple(const CHARSET_INFO * const  cs,
82
 
                       unsigned char *dst, size_t dstlen, uint32_t nweights,
83
 
                       const unsigned char *src, size_t srclen, uint32_t flags)
84
 
{
85
 
  unsigned char *map= cs->sort_order;
86
 
  unsigned char *d0= dst;
87
 
  uint32_t frmlen;
88
 
  if ((frmlen= min((uint32_t)dstlen, nweights)) > srclen)
89
 
    frmlen= srclen;
90
 
  if (dst != src)
91
 
  {
92
 
    const unsigned char *end;
93
 
    for (end= src + frmlen; src < end;)
94
 
      *dst++= map[*src++];
95
 
  }
96
 
  else
97
 
  {
98
 
    const unsigned char *end;
99
 
    for (end= dst + frmlen; dst < end; dst++)
100
 
      *dst= map[(unsigned char) *dst];
101
 
  }
102
 
  return my_strxfrm_pad_desc_and_reverse(cs, d0, dst, d0 + dstlen,
103
 
                                         nweights - frmlen, flags, 0);
104
 
}
105
 
 
106
 
 
107
 
int my_strnncoll_simple(const CHARSET_INFO * const  cs, const unsigned char *s, size_t slen,
108
 
                        const unsigned char *t, size_t tlen,
109
 
                        bool t_is_prefix)
110
 
{
111
 
  size_t len = ( slen > tlen ) ? tlen : slen;
112
 
  unsigned char *map= cs->sort_order;
113
 
  if (t_is_prefix && slen > tlen)
114
 
    slen=tlen;
115
 
  while (len--)
116
 
  {
117
 
    if (map[*s++] != map[*t++])
118
 
      return ((int) map[s[-1]] - (int) map[t[-1]]);
119
 
  }
120
 
  /*
121
 
    We can't use (slen - tlen) here as the result may be outside of the
122
 
    precision of a signed int
123
 
  */
124
 
  return slen > tlen ? 1 : slen < tlen ? -1 : 0 ;
125
 
}
126
 
 
127
 
 
128
 
/*
129
 
  Compare strings, discarding end space
130
 
 
131
 
  SYNOPSIS
132
 
    my_strnncollsp_simple()
133
 
    cs                  character set handler
134
 
    a                   First string to compare
135
 
    a_length            Length of 'a'
136
 
    b                   Second string to compare
137
 
    b_length            Length of 'b'
138
 
    diff_if_only_endspace_difference
139
 
                        Set to 1 if the strings should be regarded as different
140
 
                        if they only difference in end space
141
 
 
142
 
  IMPLEMENTATION
143
 
    If one string is shorter as the other, then we space extend the other
144
 
    so that the strings have equal length.
145
 
 
146
 
    This will ensure that the following things hold:
147
 
 
148
 
    "a"  == "a "
149
 
    "a\0" < "a"
150
 
    "a\0" < "a "
151
 
 
152
 
  RETURN
153
 
    < 0  a <  b
154
 
    = 0  a == b
155
 
    > 0  a > b
156
 
*/
157
 
 
158
 
int my_strnncollsp_simple(const CHARSET_INFO * const  cs, const unsigned char *a, size_t a_length,
159
 
                          const unsigned char *b, size_t b_length,
160
 
                          bool diff_if_only_endspace_difference)
161
 
{
162
 
  const unsigned char *map= cs->sort_order, *end;
163
 
  size_t length;
164
 
  int res;
165
 
 
166
 
#ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE
167
 
  diff_if_only_endspace_difference= 0;
168
 
#endif
169
 
 
170
 
  end= a + (length= min(a_length, b_length));
171
 
  while (a < end)
172
 
  {
173
 
    if (map[*a++] != map[*b++])
174
 
      return ((int) map[a[-1]] - (int) map[b[-1]]);
175
 
  }
176
 
  res= 0;
177
 
  if (a_length != b_length)
178
 
  {
179
 
    int swap= 1;
180
 
    if (diff_if_only_endspace_difference)
181
 
      res= 1;                                   /* Assume 'a' is bigger */
182
 
    /*
183
 
      Check the next not space character of the longer key. If it's < ' ',
184
 
      then it's smaller than the other key.
185
 
    */
186
 
    if (a_length < b_length)
187
 
    {
188
 
      /* put shorter key in s */
189
 
      a_length= b_length;
190
 
      a= b;
191
 
      swap= -1;                                 /* swap sign of result */
192
 
      res= -res;
193
 
    }
194
 
    for (end= a + a_length-length; a < end ; a++)
195
 
    {
196
 
      if (map[*a] != ' ')
197
 
        return (map[*a] < ' ') ? -swap : swap;
198
 
    }
199
 
  }
200
 
  return res;
201
 
}
202
 
 
203
 
 
204
 
size_t my_caseup_str_8bit(const CHARSET_INFO * const  cs,char *str)
205
 
{
206
 
  register unsigned char *map= cs->to_upper;
207
 
  char *str_orig= str;
208
 
  while ((*str= (char) map[(unsigned char) *str]) != 0)
209
 
    str++;
210
 
  return (size_t) (str - str_orig);
211
 
}
212
 
 
213
 
 
214
 
size_t my_casedn_str_8bit(const CHARSET_INFO * const  cs,char *str)
215
 
{
216
 
  register unsigned char *map= cs->to_lower;
217
 
  char *str_orig= str;
218
 
  while ((*str= (char) map[(unsigned char) *str]) != 0)
219
 
    str++;
220
 
  return (size_t) (str - str_orig);
221
 
}
222
 
 
223
 
 
224
 
size_t my_caseup_8bit(const CHARSET_INFO * const  cs, char *src, size_t srclen,
225
 
                      char *dst, size_t dstlen)
226
 
{
227
 
  assert(src == dst && srclen == dstlen);
228
 
  char *end= src + srclen;
229
 
  register unsigned char *map= cs->to_upper;
230
 
  for ( ; src != end ; src++)
231
 
    *src= (char) map[(unsigned char) *src];
232
 
  return srclen;
233
 
}
234
 
 
235
 
 
236
 
size_t my_casedn_8bit(const CHARSET_INFO * const  cs, char *src, size_t srclen,
237
 
                      char *dst, size_t dstlen)
238
 
{
239
 
  assert(src == dst && srclen == dstlen);
240
 
  char *end= src + srclen;
241
 
  register unsigned char *map=cs->to_lower;
242
 
  for ( ; src != end ; src++)
243
 
    *src= (char) map[(unsigned char) *src];
244
 
  return srclen;
245
 
}
246
 
 
247
 
int my_strcasecmp_8bit(const CHARSET_INFO * const  cs,const char *s, const char *t)
248
 
{
249
 
  register unsigned char *map=cs->to_upper;
250
 
  while (map[(unsigned char) *s] == map[(unsigned char) *t++])
251
 
    if (!*s++) return 0;
252
 
  return ((int) map[(unsigned char) s[0]] - (int) map[(unsigned char) t[-1]]);
253
 
}
254
 
 
255
 
 
256
 
int my_mb_wc_8bit(const CHARSET_INFO * const cs,my_wc_t *wc,
257
 
                  const unsigned char *str,
258
 
                  const unsigned char *end)
259
 
{
260
 
  if (str >= end)
261
 
    return MY_CS_TOOSMALL;
262
 
 
263
 
  *wc=cs->tab_to_uni[*str];
264
 
  return (!wc[0] && str[0]) ? -1 : 1;
265
 
}
266
 
 
267
 
int my_wc_mb_8bit(const CHARSET_INFO * const cs,my_wc_t wc,
268
 
                  unsigned char *str,
269
 
                  unsigned char *end)
270
 
{
271
 
  MY_UNI_IDX *idx;
272
 
 
273
 
  if (str >= end)
274
 
    return MY_CS_TOOSMALL;
275
 
 
276
 
  for (idx=cs->tab_from_uni; idx->tab ; idx++)
277
 
  {
278
 
    if (idx->from <= wc && idx->to >= wc)
279
 
    {
280
 
      str[0]= idx->tab[wc - idx->from];
281
 
      return (!str[0] && wc) ? MY_CS_ILUNI : 1;
282
 
    }
283
 
  }
284
 
  return MY_CS_ILUNI;
285
 
}
286
 
 
287
 
 
288
 
/*
289
44
   We can't use vsprintf here as it's not guaranteed to return
290
45
   the length on all operating systems.
291
46
   This function is also not called in a safe environment, so the
305
60
}
306
61
 
307
62
 
308
 
void my_hash_sort_simple(const CHARSET_INFO * const cs,
309
 
                         const unsigned char *key, size_t len,
310
 
                         uint32_t *nr1, uint32_t *nr2)
311
 
{
312
 
  register unsigned char *sort_order=cs->sort_order;
313
 
  const unsigned char *end;
314
 
 
315
 
  /*
316
 
    Remove end space. We have to do this to be able to compare
317
 
    'A ' and 'A' as identical
318
 
  */
319
 
  end= skip_trailing_space(key, len);
320
 
 
321
 
  for (; key < end ; key++)
322
 
  {
323
 
    nr1[0]^=(ulong) ((((uint32_t) nr1[0] & 63)+nr2[0]) *
324
 
             ((uint32_t) sort_order[(uint32_t) *key])) + (nr1[0] << 8);
325
 
    nr2[0]+=3;
326
 
  }
327
 
}
328
 
 
329
 
 
330
63
long my_strntol_8bit(const CHARSET_INFO * const cs,
331
64
                     const char *nptr, size_t l, int base,
332
65
                     char **endptr, int *err)
833
566
  if (length == INT32_MAX)
834
567
    length= 65535;                          /* Should be big enough */
835
568
  *end= str + length;
836
 
  return my_strtod(str, end, err);
 
569
  return internal::my_strtod(str, end, err);
837
570
}
838
571
 
839
572
 
1170
903
                        const char *ptr, size_t length)
1171
904
{
1172
905
  const char *end;
1173
 
  end= (const char *) skip_trailing_space((const unsigned char *)ptr, length);
 
906
  end= (const char *) internal::skip_trailing_space((const unsigned char *)ptr, length);
1174
907
  return (size_t) (end-ptr);
1175
908
}
1176
909
 
1372
1105
int64_t my_strtoll10_8bit(const CHARSET_INFO * const,
1373
1106
                          const char *nptr, char **endptr, int *error)
1374
1107
{
1375
 
  return my_strtoll10(nptr, endptr, error);
 
1108
  return internal::my_strtoll10(nptr, endptr, error);
1376
1109
}
1377
1110
 
1378
1111
 
1904
1637
  return frmend - str;
1905
1638
}
1906
1639
 
1907
 
 
1908
 
MY_CHARSET_HANDLER my_charset_8bit_handler=
1909
 
{
1910
 
    my_cset_init_8bit,
1911
 
    NULL,                       /* ismbchar      */
1912
 
    my_mbcharlen_8bit,          /* mbcharlen     */
1913
 
    my_numchars_8bit,
1914
 
    my_charpos_8bit,
1915
 
    my_well_formed_len_8bit,
1916
 
    my_lengthsp_8bit,
1917
 
    my_numcells_8bit,
1918
 
    my_mb_wc_8bit,
1919
 
    my_wc_mb_8bit,
1920
 
    my_mb_ctype_8bit,
1921
 
    my_caseup_str_8bit,
1922
 
    my_casedn_str_8bit,
1923
 
    my_caseup_8bit,
1924
 
    my_casedn_8bit,
1925
 
    my_snprintf_8bit,
1926
 
    my_long10_to_str_8bit,
1927
 
    my_int64_t10_to_str_8bit,
1928
 
    my_fill_8bit,
1929
 
    my_strntol_8bit,
1930
 
    my_strntoul_8bit,
1931
 
    my_strntoll_8bit,
1932
 
    my_strntoull_8bit,
1933
 
    my_strntod_8bit,
1934
 
    my_strtoll10_8bit,
1935
 
    my_strntoull10rnd_8bit,
1936
 
    my_scan_8bit
1937
 
};
1938
 
 
1939
 
MY_COLLATION_HANDLER my_collation_8bit_simple_ci_handler =
1940
 
{
1941
 
    my_coll_init_simple,        /* init */
1942
 
    my_strnncoll_simple,
1943
 
    my_strnncollsp_simple,
1944
 
    my_strnxfrm_simple,
1945
 
    my_strnxfrmlen_simple,
1946
 
    my_like_range_simple,
1947
 
    my_wildcmp_8bit,
1948
 
    my_strcasecmp_8bit,
1949
 
    my_instr_simple,
1950
 
    my_hash_sort_simple,
1951
 
    my_propagate_simple
1952
 
};
 
1640
} /* namespace drizzled */