~linuxjedi/drizzle/trunk-bug-667053

« back to all changes in this revision

Viewing changes to strings/ctype-simple.c

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2002 MySQL AB
 
2
 
 
3
   This program is free software; you can redistribute it and/or modify
 
4
   it under the terms of the GNU General Public License as published by
 
5
   the Free Software Foundation; version 2 of the License.
 
6
 
 
7
   This program is distributed in the hope that it will be useful,
 
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
   GNU General Public License for more details.
 
11
 
 
12
   You should have received a copy of the GNU General Public License
 
13
   along with this program; if not, write to the Free Software
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
15
 
 
16
#include <my_global.h>
 
17
#include "m_string.h"
 
18
#include "m_ctype.h"
 
19
#include "my_sys.h"  /* Needed for MY_ERRNO_ERANGE */
 
20
#include <errno.h>
 
21
 
 
22
#include "stdarg.h"
 
23
 
 
24
/*
 
25
  Returns the number of bytes required for strnxfrm().
 
26
*/
 
27
 
 
28
size_t my_strnxfrmlen_simple(CHARSET_INFO *cs, size_t len)
 
29
{
 
30
  return len * (cs->strxfrm_multiply ? cs->strxfrm_multiply : 1);
 
31
}
 
32
 
 
33
 
 
34
/*
 
35
  Converts a string into its sort key.
 
36
  
 
37
  SYNOPSIS
 
38
     my_strnxfrm_xxx()
 
39
     
 
40
  IMPLEMENTATION
 
41
     
 
42
     The my_strxfrm_xxx() function transforms a string pointed to by
 
43
     'src' with length 'srclen' according to the charset+collation 
 
44
     pair 'cs' and copies the result key into 'dest'.
 
45
     
 
46
     Comparing two strings using memcmp() after my_strnxfrm_xxx()
 
47
     is equal to comparing two original strings with my_strnncollsp_xxx().
 
48
     
 
49
     Not more than 'dstlen' bytes are written into 'dst'.
 
50
     To garantee that the whole string is transformed, 'dstlen' must be
 
51
     at least srclen*cs->strnxfrm_multiply bytes long. Otherwise,
 
52
     consequent memcmp() may return a non-accurate result.
 
53
     
 
54
     If the source string is too short to fill whole 'dstlen' bytes,
 
55
     then the 'dest' string is padded up to 'dstlen', ensuring that:
 
56
     
 
57
       "a"  == "a "
 
58
       "a\0" < "a"
 
59
       "a\0" < "a "
 
60
     
 
61
     my_strnxfrm_simple() is implemented for 8bit charsets and
 
62
     simple collations with one-to-one string->key transformation.
 
63
     
 
64
     See also implementations for various charsets/collations in  
 
65
     other ctype-xxx.c files.
 
66
     
 
67
  RETURN
 
68
  
 
69
    Target len 'dstlen'.
 
70
  
 
71
*/
 
72
 
 
73
 
 
74
size_t my_strnxfrm_simple(CHARSET_INFO * cs,
 
75
                       uchar *dst, size_t dstlen, uint nweights,
 
76
                       const uchar *src, size_t srclen, uint flags)
 
77
{
 
78
  uchar *map= cs->sort_order;
 
79
  uchar *d0= dst;
 
80
  uint frmlen;
 
81
  if ((frmlen= min(dstlen, nweights)) > srclen)
 
82
    frmlen= srclen;
 
83
  if (dst != src)
 
84
  {
 
85
    const uchar *end;
 
86
    for (end= src + frmlen; src < end;)
 
87
      *dst++= map[*src++];
 
88
  }
 
89
  else
 
90
  {
 
91
    const uchar *end;
 
92
    for (end= dst + frmlen; dst < end; dst++)
 
93
      *dst= map[(uchar) *dst];
 
94
  }
 
95
  return my_strxfrm_pad_desc_and_reverse(cs, d0, dst, d0 + dstlen,
 
96
                                         nweights - frmlen, flags, 0);
 
97
}
 
98
 
 
99
 
 
100
int my_strnncoll_simple(CHARSET_INFO * cs, const uchar *s, size_t slen, 
 
101
                        const uchar *t, size_t tlen,
 
102
                        my_bool t_is_prefix)
 
103
{
 
104
  size_t len = ( slen > tlen ) ? tlen : slen;
 
105
  uchar *map= cs->sort_order;
 
106
  if (t_is_prefix && slen > tlen)
 
107
    slen=tlen;
 
108
  while (len--)
 
109
  {
 
110
    if (map[*s++] != map[*t++])
 
111
      return ((int) map[s[-1]] - (int) map[t[-1]]);
 
112
  }
 
113
  /*
 
114
    We can't use (slen - tlen) here as the result may be outside of the
 
115
    precision of a signed int
 
116
  */
 
117
  return slen > tlen ? 1 : slen < tlen ? -1 : 0 ;
 
118
}
 
119
 
 
120
 
 
121
/*
 
122
  Compare strings, discarding end space
 
123
 
 
124
  SYNOPSIS
 
125
    my_strnncollsp_simple()
 
126
    cs                  character set handler
 
127
    a                   First string to compare
 
128
    a_length            Length of 'a'
 
129
    b                   Second string to compare
 
130
    b_length            Length of 'b'
 
131
    diff_if_only_endspace_difference
 
132
                        Set to 1 if the strings should be regarded as different
 
133
                        if they only difference in end space
 
134
 
 
135
  IMPLEMENTATION
 
136
    If one string is shorter as the other, then we space extend the other
 
137
    so that the strings have equal length.
 
138
 
 
139
    This will ensure that the following things hold:
 
140
 
 
141
    "a"  == "a "
 
142
    "a\0" < "a"
 
143
    "a\0" < "a "
 
144
 
 
145
  RETURN
 
146
    < 0  a <  b
 
147
    = 0  a == b
 
148
    > 0  a > b
 
149
*/
 
150
 
 
151
int my_strnncollsp_simple(CHARSET_INFO * cs, const uchar *a, size_t a_length, 
 
152
                          const uchar *b, size_t b_length,
 
153
                          my_bool diff_if_only_endspace_difference)
 
154
{
 
155
  const uchar *map= cs->sort_order, *end;
 
156
  size_t length;
 
157
  int res;
 
158
 
 
159
#ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE
 
160
  diff_if_only_endspace_difference= 0;
 
161
#endif
 
162
 
 
163
  end= a + (length= min(a_length, b_length));
 
164
  while (a < end)
 
165
  {
 
166
    if (map[*a++] != map[*b++])
 
167
      return ((int) map[a[-1]] - (int) map[b[-1]]);
 
168
  }
 
169
  res= 0;
 
170
  if (a_length != b_length)
 
171
  {
 
172
    int swap= 1;
 
173
    if (diff_if_only_endspace_difference)
 
174
      res= 1;                                   /* Assume 'a' is bigger */
 
175
    /*
 
176
      Check the next not space character of the longer key. If it's < ' ',
 
177
      then it's smaller than the other key.
 
178
    */
 
179
    if (a_length < b_length)
 
180
    {
 
181
      /* put shorter key in s */
 
182
      a_length= b_length;
 
183
      a= b;
 
184
      swap= -1;                                 /* swap sign of result */
 
185
      res= -res;
 
186
    }
 
187
    for (end= a + a_length-length; a < end ; a++)
 
188
    {
 
189
      if (map[*a] != ' ')
 
190
        return (map[*a] < ' ') ? -swap : swap;
 
191
    }
 
192
  }
 
193
  return res;
 
194
}
 
195
 
 
196
 
 
197
size_t my_caseup_str_8bit(CHARSET_INFO * cs,char *str)
 
198
{
 
199
  register uchar *map= cs->to_upper;
 
200
  char *str_orig= str;
 
201
  while ((*str= (char) map[(uchar) *str]) != 0)
 
202
    str++;
 
203
  return (size_t) (str - str_orig);
 
204
}
 
205
 
 
206
 
 
207
size_t my_casedn_str_8bit(CHARSET_INFO * cs,char *str)
 
208
{
 
209
  register uchar *map= cs->to_lower;
 
210
  char *str_orig= str;
 
211
  while ((*str= (char) map[(uchar) *str]) != 0)
 
212
    str++;
 
213
  return (size_t) (str - str_orig);
 
214
}
 
215
 
 
216
 
 
217
size_t my_caseup_8bit(CHARSET_INFO * cs, char *src, size_t srclen,
 
218
                      char *dst __attribute__((unused)),
 
219
                      size_t dstlen __attribute__((unused)))
 
220
{
 
221
  char *end= src + srclen;
 
222
  register uchar *map= cs->to_upper;
 
223
  DBUG_ASSERT(src == dst && srclen == dstlen);
 
224
  for ( ; src != end ; src++)
 
225
    *src= (char) map[(uchar) *src];
 
226
  return srclen;
 
227
}
 
228
 
 
229
 
 
230
size_t my_casedn_8bit(CHARSET_INFO * cs, char *src, size_t srclen,
 
231
                      char *dst __attribute__((unused)),
 
232
                      size_t dstlen __attribute__((unused)))
 
233
{
 
234
  char *end= src + srclen;
 
235
  register uchar *map=cs->to_lower;
 
236
  DBUG_ASSERT(src == dst && srclen == dstlen);
 
237
  for ( ; src != end ; src++)
 
238
    *src= (char) map[(uchar) *src];
 
239
  return srclen;
 
240
}
 
241
 
 
242
int my_strcasecmp_8bit(CHARSET_INFO * cs,const char *s, const char *t)
 
243
{
 
244
  register uchar *map=cs->to_upper;
 
245
  while (map[(uchar) *s] == map[(uchar) *t++])
 
246
    if (!*s++) return 0;
 
247
  return ((int) map[(uchar) s[0]] - (int) map[(uchar) t[-1]]);
 
248
}
 
249
 
 
250
 
 
251
int my_mb_wc_8bit(CHARSET_INFO *cs,my_wc_t *wc,
 
252
                  const uchar *str,
 
253
                  const uchar *end __attribute__((unused)))
 
254
{
 
255
  if (str >= end)
 
256
    return MY_CS_TOOSMALL;
 
257
  
 
258
  *wc=cs->tab_to_uni[*str];
 
259
  return (!wc[0] && str[0]) ? -1 : 1;
 
260
}
 
261
 
 
262
int my_wc_mb_8bit(CHARSET_INFO *cs,my_wc_t wc,
 
263
                  uchar *str,
 
264
                  uchar *end)
 
265
{
 
266
  MY_UNI_IDX *idx;
 
267
 
 
268
  if (str >= end)
 
269
    return MY_CS_TOOSMALL;
 
270
  
 
271
  for (idx=cs->tab_from_uni; idx->tab ; idx++)
 
272
  {
 
273
    if (idx->from <= wc && idx->to >= wc)
 
274
    {
 
275
      str[0]= idx->tab[wc - idx->from];
 
276
      return (!str[0] && wc) ? MY_CS_ILUNI : 1;
 
277
    }
 
278
  }
 
279
  return MY_CS_ILUNI;
 
280
}
 
281
 
 
282
 
 
283
/* 
 
284
   We can't use vsprintf here as it's not guaranteed to return
 
285
   the length on all operating systems.
 
286
   This function is also not called in a safe environment, so the
 
287
   end buffer must be checked.
 
288
*/
 
289
 
 
290
size_t my_snprintf_8bit(CHARSET_INFO *cs  __attribute__((unused)),
 
291
                        char* to, size_t n  __attribute__((unused)),
 
292
                     const char* fmt, ...)
 
293
{
 
294
  va_list args;
 
295
  int result;
 
296
  va_start(args,fmt);
 
297
  result= my_vsnprintf(to, n, fmt, args);
 
298
  va_end(args);
 
299
  return result;
 
300
}
 
301
 
 
302
 
 
303
void my_hash_sort_simple(CHARSET_INFO *cs,
 
304
                         const uchar *key, size_t len,
 
305
                         ulong *nr1, ulong *nr2)
 
306
{
 
307
  register uchar *sort_order=cs->sort_order;
 
308
  const uchar *end;
 
309
  
 
310
  /*
 
311
    Remove end space. We have to do this to be able to compare
 
312
    'A ' and 'A' as identical
 
313
  */
 
314
  end= skip_trailing_space(key, len);
 
315
  
 
316
  for (; key < (uchar*) end ; key++)
 
317
  {
 
318
    nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) * 
 
319
             ((uint) sort_order[(uint) *key])) + (nr1[0] << 8);
 
320
    nr2[0]+=3;
 
321
  }
 
322
}
 
323
 
 
324
 
 
325
long my_strntol_8bit(CHARSET_INFO *cs,
 
326
                     const char *nptr, size_t l, int base,
 
327
                     char **endptr, int *err)
 
328
{
 
329
  int negative;
 
330
  register uint32 cutoff;
 
331
  register uint cutlim;
 
332
  register uint32 i;
 
333
  register const char *s;
 
334
  register uchar c;
 
335
  const char *save, *e;
 
336
  int overflow;
 
337
 
 
338
  *err= 0;                              /* Initialize error indicator */
 
339
#ifdef NOT_USED
 
340
  if (base < 0 || base == 1 || base > 36)
 
341
    base = 10;
 
342
#endif
 
343
 
 
344
  s = nptr;
 
345
  e = nptr+l;
 
346
  
 
347
  for ( ; s<e && my_isspace(cs, *s) ; s++);
 
348
  
 
349
  if (s == e)
 
350
  {
 
351
    goto noconv;
 
352
  }
 
353
  
 
354
  /* Check for a sign.  */
 
355
  if (*s == '-')
 
356
  {
 
357
    negative = 1;
 
358
    ++s;
 
359
  }
 
360
  else if (*s == '+')
 
361
  {
 
362
    negative = 0;
 
363
    ++s;
 
364
  }
 
365
  else
 
366
    negative = 0;
 
367
 
 
368
#ifdef NOT_USED
 
369
  if (base == 16 && s[0] == '0' && (s[1]=='X' || s[1]=='x'))
 
370
    s += 2;
 
371
#endif
 
372
 
 
373
#ifdef NOT_USED
 
374
  if (base == 0)
 
375
  {
 
376
    if (*s == '0')
 
377
    {
 
378
      if (s[1]=='X' || s[1]=='x')
 
379
      {
 
380
        s += 2;
 
381
        base = 16;
 
382
      }
 
383
      else
 
384
        base = 8;
 
385
    }
 
386
    else
 
387
      base = 10;
 
388
  }
 
389
#endif
 
390
 
 
391
  save = s;
 
392
  cutoff = ((uint32)~0L) / (uint32) base;
 
393
  cutlim = (uint) (((uint32)~0L) % (uint32) base);
 
394
 
 
395
  overflow = 0;
 
396
  i = 0;
 
397
  for (c = *s; s != e; c = *++s)
 
398
  {
 
399
    if (c>='0' && c<='9')
 
400
      c -= '0';
 
401
    else if (c>='A' && c<='Z')
 
402
      c = c - 'A' + 10;
 
403
    else if (c>='a' && c<='z')
 
404
      c = c - 'a' + 10;
 
405
    else
 
406
      break;
 
407
    if (c >= base)
 
408
      break;
 
409
    if (i > cutoff || (i == cutoff && c > cutlim))
 
410
      overflow = 1;
 
411
    else
 
412
    {
 
413
      i *= (uint32) base;
 
414
      i += c;
 
415
    }
 
416
  }
 
417
  
 
418
  if (s == save)
 
419
    goto noconv;
 
420
  
 
421
  if (endptr != NULL)
 
422
    *endptr = (char *) s;
 
423
  
 
424
  if (negative)
 
425
  {
 
426
    if (i  > (uint32) INT_MIN32)
 
427
      overflow = 1;
 
428
  }
 
429
  else if (i > INT_MAX32)
 
430
    overflow = 1;
 
431
  
 
432
  if (overflow)
 
433
  {
 
434
    err[0]= ERANGE;
 
435
    return negative ? INT_MIN32 : INT_MAX32;
 
436
  }
 
437
  
 
438
  return (negative ? -((long) i) : (long) i);
 
439
 
 
440
noconv:
 
441
  err[0]= EDOM;
 
442
  if (endptr != NULL)
 
443
    *endptr = (char *) nptr;
 
444
  return 0L;
 
445
}
 
446
 
 
447
 
 
448
ulong my_strntoul_8bit(CHARSET_INFO *cs,
 
449
                       const char *nptr, size_t l, int base,
 
450
                       char **endptr, int *err)
 
451
{
 
452
  int negative;
 
453
  register uint32 cutoff;
 
454
  register uint cutlim;
 
455
  register uint32 i;
 
456
  register const char *s;
 
457
  register uchar c;
 
458
  const char *save, *e;
 
459
  int overflow;
 
460
 
 
461
  *err= 0;                              /* Initialize error indicator */
 
462
#ifdef NOT_USED
 
463
  if (base < 0 || base == 1 || base > 36)
 
464
    base = 10;
 
465
#endif
 
466
 
 
467
  s = nptr;
 
468
  e = nptr+l;
 
469
  
 
470
  for( ; s<e && my_isspace(cs, *s); s++);
 
471
  
 
472
  if (s==e)
 
473
  {
 
474
    goto noconv;
 
475
  }
 
476
 
 
477
  if (*s == '-')
 
478
  {
 
479
    negative = 1;
 
480
    ++s;
 
481
  }
 
482
  else if (*s == '+')
 
483
  {
 
484
    negative = 0;
 
485
    ++s;
 
486
  }
 
487
  else
 
488
    negative = 0;
 
489
 
 
490
#ifdef NOT_USED
 
491
  if (base == 16 && s[0] == '0' && (s[1]=='X' || s[1]=='x'))
 
492
    s += 2;
 
493
#endif
 
494
 
 
495
#ifdef NOT_USED
 
496
  if (base == 0)
 
497
  {
 
498
    if (*s == '0')
 
499
    {
 
500
      if (s[1]=='X' || s[1]=='x')
 
501
      {
 
502
        s += 2;
 
503
        base = 16;
 
504
      }
 
505
      else
 
506
        base = 8;
 
507
    }
 
508
    else
 
509
      base = 10;
 
510
  }
 
511
#endif
 
512
 
 
513
  save = s;
 
514
  cutoff = ((uint32)~0L) / (uint32) base;
 
515
  cutlim = (uint) (((uint32)~0L) % (uint32) base);
 
516
  overflow = 0;
 
517
  i = 0;
 
518
  
 
519
  for (c = *s; s != e; c = *++s)
 
520
  {
 
521
    if (c>='0' && c<='9')
 
522
      c -= '0';
 
523
    else if (c>='A' && c<='Z')
 
524
      c = c - 'A' + 10;
 
525
    else if (c>='a' && c<='z')
 
526
      c = c - 'a' + 10;
 
527
    else
 
528
      break;
 
529
    if (c >= base)
 
530
      break;
 
531
    if (i > cutoff || (i == cutoff && c > cutlim))
 
532
      overflow = 1;
 
533
    else
 
534
    {
 
535
      i *= (uint32) base;
 
536
      i += c;
 
537
    }
 
538
  }
 
539
 
 
540
  if (s == save)
 
541
    goto noconv;
 
542
 
 
543
  if (endptr != NULL)
 
544
    *endptr = (char *) s;
 
545
 
 
546
  if (overflow)
 
547
  {
 
548
    err[0]= ERANGE;
 
549
    return (~(uint32) 0);
 
550
  }
 
551
  
 
552
  return (negative ? -((long) i) : (long) i);
 
553
  
 
554
noconv:
 
555
  err[0]= EDOM;
 
556
  if (endptr != NULL)
 
557
    *endptr = (char *) nptr;
 
558
  return 0L;
 
559
}
 
560
 
 
561
 
 
562
longlong my_strntoll_8bit(CHARSET_INFO *cs __attribute__((unused)),
 
563
                          const char *nptr, size_t l, int base,
 
564
                          char **endptr,int *err)
 
565
{
 
566
  int negative;
 
567
  register ulonglong cutoff;
 
568
  register uint cutlim;
 
569
  register ulonglong i;
 
570
  register const char *s, *e;
 
571
  const char *save;
 
572
  int overflow;
 
573
 
 
574
  *err= 0;                              /* Initialize error indicator */
 
575
#ifdef NOT_USED
 
576
  if (base < 0 || base == 1 || base > 36)
 
577
    base = 10;
 
578
#endif
 
579
 
 
580
  s = nptr;
 
581
  e = nptr+l;
 
582
 
 
583
  for(; s<e && my_isspace(cs,*s); s++);
 
584
 
 
585
  if (s == e)
 
586
  {
 
587
    goto noconv;
 
588
  }
 
589
 
 
590
  if (*s == '-')
 
591
  {
 
592
    negative = 1;
 
593
    ++s;
 
594
  }
 
595
  else if (*s == '+')
 
596
  {
 
597
    negative = 0;
 
598
    ++s;
 
599
  }
 
600
  else
 
601
    negative = 0;
 
602
 
 
603
#ifdef NOT_USED
 
604
  if (base == 16 && s[0] == '0' && (s[1]=='X'|| s[1]=='x'))
 
605
    s += 2;
 
606
#endif
 
607
 
 
608
#ifdef NOT_USED
 
609
  if (base == 0)
 
610
  {
 
611
    if (*s == '0')
 
612
    {
 
613
      if (s[1]=='X' || s[1]=='x')
 
614
      {
 
615
        s += 2;
 
616
        base = 16;
 
617
      }
 
618
      else
 
619
        base = 8;
 
620
    }
 
621
    else
 
622
      base = 10;
 
623
  }
 
624
#endif
 
625
 
 
626
  save = s;
 
627
 
 
628
  cutoff = (~(ulonglong) 0) / (unsigned long int) base;
 
629
  cutlim = (uint) ((~(ulonglong) 0) % (unsigned long int) base);
 
630
 
 
631
  overflow = 0;
 
632
  i = 0;
 
633
  for ( ; s != e; s++)
 
634
  {
 
635
    register uchar c= *s;
 
636
    if (c>='0' && c<='9')
 
637
      c -= '0';
 
638
    else if (c>='A' && c<='Z')
 
639
      c = c - 'A' + 10;
 
640
    else if (c>='a' && c<='z')
 
641
      c = c - 'a' + 10;
 
642
    else
 
643
      break;
 
644
    if (c >= base)
 
645
      break;
 
646
    if (i > cutoff || (i == cutoff && c > cutlim))
 
647
      overflow = 1;
 
648
    else
 
649
    {
 
650
      i *= (ulonglong) base;
 
651
      i += c;
 
652
    }
 
653
  }
 
654
 
 
655
  if (s == save)
 
656
    goto noconv;
 
657
 
 
658
  if (endptr != NULL)
 
659
    *endptr = (char *) s;
 
660
 
 
661
  if (negative)
 
662
  {
 
663
    if (i  > (ulonglong) LONGLONG_MIN)
 
664
      overflow = 1;
 
665
  }
 
666
  else if (i > (ulonglong) LONGLONG_MAX)
 
667
    overflow = 1;
 
668
 
 
669
  if (overflow)
 
670
  {
 
671
    err[0]= ERANGE;
 
672
    return negative ? LONGLONG_MIN : LONGLONG_MAX;
 
673
  }
 
674
 
 
675
  return (negative ? -((longlong) i) : (longlong) i);
 
676
 
 
677
noconv:
 
678
  err[0]= EDOM;
 
679
  if (endptr != NULL)
 
680
    *endptr = (char *) nptr;
 
681
  return 0L;
 
682
}
 
683
 
 
684
 
 
685
ulonglong my_strntoull_8bit(CHARSET_INFO *cs,
 
686
                           const char *nptr, size_t l, int base,
 
687
                           char **endptr, int *err)
 
688
{
 
689
  int negative;
 
690
  register ulonglong cutoff;
 
691
  register uint cutlim;
 
692
  register ulonglong i;
 
693
  register const char *s, *e;
 
694
  const char *save;
 
695
  int overflow;
 
696
 
 
697
  *err= 0;                              /* Initialize error indicator */
 
698
#ifdef NOT_USED
 
699
  if (base < 0 || base == 1 || base > 36)
 
700
    base = 10;
 
701
#endif
 
702
 
 
703
  s = nptr;
 
704
  e = nptr+l;
 
705
 
 
706
  for(; s<e && my_isspace(cs,*s); s++);
 
707
 
 
708
  if (s == e)
 
709
  {
 
710
    goto noconv;
 
711
  }
 
712
 
 
713
  if (*s == '-')
 
714
  {
 
715
    negative = 1;
 
716
    ++s;
 
717
  }
 
718
  else if (*s == '+')
 
719
  {
 
720
    negative = 0;
 
721
    ++s;
 
722
  }
 
723
  else
 
724
    negative = 0;
 
725
 
 
726
#ifdef NOT_USED
 
727
  if (base == 16 && s[0] == '0' && (s[1]=='X' || s[1]=='x'))
 
728
    s += 2;
 
729
#endif
 
730
 
 
731
#ifdef NOT_USED
 
732
  if (base == 0)
 
733
  {
 
734
    if (*s == '0')
 
735
    {
 
736
      if (s[1]=='X' || s[1]=='x')
 
737
      {
 
738
        s += 2;
 
739
        base = 16;
 
740
      }
 
741
      else
 
742
        base = 8;
 
743
    }
 
744
    else
 
745
      base = 10;
 
746
  }
 
747
#endif
 
748
 
 
749
  save = s;
 
750
 
 
751
  cutoff = (~(ulonglong) 0) / (unsigned long int) base;
 
752
  cutlim = (uint) ((~(ulonglong) 0) % (unsigned long int) base);
 
753
 
 
754
  overflow = 0;
 
755
  i = 0;
 
756
  for ( ; s != e; s++)
 
757
  {
 
758
    register uchar c= *s;
 
759
 
 
760
    if (c>='0' && c<='9')
 
761
      c -= '0';
 
762
    else if (c>='A' && c<='Z')
 
763
      c = c - 'A' + 10;
 
764
    else if (c>='a' && c<='z')
 
765
      c = c - 'a' + 10;
 
766
    else
 
767
      break;
 
768
    if (c >= base)
 
769
      break;
 
770
    if (i > cutoff || (i == cutoff && c > cutlim))
 
771
      overflow = 1;
 
772
    else
 
773
    {
 
774
      i *= (ulonglong) base;
 
775
      i += c;
 
776
    }
 
777
  }
 
778
 
 
779
  if (s == save)
 
780
    goto noconv;
 
781
 
 
782
  if (endptr != NULL)
 
783
    *endptr = (char *) s;
 
784
 
 
785
  if (overflow)
 
786
  {
 
787
    err[0]= ERANGE;
 
788
    return (~(ulonglong) 0);
 
789
  }
 
790
 
 
791
  return (negative ? -((longlong) i) : (longlong) i);
 
792
 
 
793
noconv:
 
794
  err[0]= EDOM;
 
795
  if (endptr != NULL)
 
796
    *endptr = (char *) nptr;
 
797
  return 0L;
 
798
}
 
799
 
 
800
 
 
801
/*
 
802
  Read double from string
 
803
 
 
804
  SYNOPSIS:
 
805
    my_strntod_8bit()
 
806
    cs          Character set information
 
807
    str         String to convert to double
 
808
    length      Optional length for string.
 
809
    end         result pointer to end of converted string
 
810
    err         Error number if failed conversion
 
811
    
 
812
  NOTES:
 
813
    If length is not INT_MAX32 or str[length] != 0 then the given str must
 
814
    be writeable
 
815
    If length == INT_MAX32 the str must be \0 terminated.
 
816
 
 
817
    It's implemented this way to save a buffer allocation and a memory copy.
 
818
 
 
819
  RETURN
 
820
    Value of number in string
 
821
*/
 
822
 
 
823
 
 
824
double my_strntod_8bit(CHARSET_INFO *cs __attribute__((unused)),
 
825
                       char *str, size_t length,
 
826
                       char **end, int *err)
 
827
{
 
828
  if (length == INT_MAX32)
 
829
    length= 65535;                          /* Should be big enough */
 
830
  *end= str + length;
 
831
  return my_strtod(str, end, err);
 
832
}
 
833
 
 
834
 
 
835
/*
 
836
  This is a fast version optimized for the case of radix 10 / -10
 
837
 
 
838
  Assume len >= 1
 
839
*/
 
840
 
 
841
size_t my_long10_to_str_8bit(CHARSET_INFO *cs __attribute__((unused)),
 
842
                             char *dst, size_t len, int radix, long int val)
 
843
{
 
844
  char buffer[66];
 
845
  register char *p, *e;
 
846
  long int new_val;
 
847
  uint sign=0;
 
848
  unsigned long int uval = (unsigned long int) val;
 
849
 
 
850
  e = p = &buffer[sizeof(buffer)-1];
 
851
  *p= 0;
 
852
  
 
853
  if (radix < 0)
 
854
  {
 
855
    if (val < 0)
 
856
    {
 
857
      /* Avoid integer overflow in (-val) for LONGLONG_MIN (BUG#31799). */
 
858
      uval= (unsigned long int)0 - uval;
 
859
      *dst++= '-';
 
860
      len--;
 
861
      sign= 1;
 
862
    }
 
863
  }
 
864
  
 
865
  new_val = (long) (uval / 10);
 
866
  *--p    = '0'+ (char) (uval - (unsigned long) new_val * 10);
 
867
  val     = new_val;
 
868
  
 
869
  while (val != 0)
 
870
  {
 
871
    new_val=val/10;
 
872
    *--p = '0' + (char) (val-new_val*10);
 
873
    val= new_val;
 
874
  }
 
875
  
 
876
  len= min(len, (size_t) (e-p));
 
877
  memcpy(dst, p, len);
 
878
  return len+sign;
 
879
}
 
880
 
 
881
 
 
882
size_t my_longlong10_to_str_8bit(CHARSET_INFO *cs __attribute__((unused)),
 
883
                                 char *dst, size_t len, int radix,
 
884
                                 longlong val)
 
885
{
 
886
  char buffer[65];
 
887
  register char *p, *e;
 
888
  long long_val;
 
889
  uint sign= 0;
 
890
  ulonglong uval = (ulonglong)val;
 
891
  
 
892
  if (radix < 0)
 
893
  {
 
894
    if (val < 0)
 
895
    {
 
896
      /* Avoid integer overflow in (-val) for LONGLONG_MIN (BUG#31799). */
 
897
      uval = (ulonglong)0 - uval;
 
898
      *dst++= '-';
 
899
      len--;
 
900
      sign= 1;
 
901
    }
 
902
  }
 
903
  
 
904
  e = p = &buffer[sizeof(buffer)-1];
 
905
  *p= 0;
 
906
  
 
907
  if (uval == 0)
 
908
  {
 
909
    *--p= '0';
 
910
    len= 1;
 
911
    goto cnv;
 
912
  }
 
913
  
 
914
  while (uval > (ulonglong) LONG_MAX)
 
915
  {
 
916
    ulonglong quo= uval/(uint) 10;
 
917
    uint rem= (uint) (uval- quo* (uint) 10);
 
918
    *--p = '0' + rem;
 
919
    uval= quo;
 
920
  }
 
921
  
 
922
  long_val= (long) uval;
 
923
  while (long_val != 0)
 
924
  {
 
925
    long quo= long_val/10;
 
926
    *--p = (char) ('0' + (long_val - quo*10));
 
927
    long_val= quo;
 
928
  }
 
929
  
 
930
  len= min(len, (size_t) (e-p));
 
931
cnv:
 
932
  memcpy(dst, p, len);
 
933
  return len+sign;
 
934
}
 
935
 
 
936
 
 
937
/*
 
938
** Compare string against string with wildcard
 
939
**      0 if matched
 
940
**      -1 if not matched with wildcard
 
941
**       1 if matched with wildcard
 
942
*/
 
943
 
 
944
#ifdef LIKE_CMP_TOUPPER
 
945
#define likeconv(s,A) (uchar) my_toupper(s,A)
 
946
#else
 
947
#define likeconv(s,A) (uchar) (s)->sort_order[(uchar) (A)]
 
948
#endif
 
949
 
 
950
#define INC_PTR(cs,A,B) (A)++
 
951
 
 
952
 
 
953
int my_wildcmp_8bit(CHARSET_INFO *cs,
 
954
                    const char *str,const char *str_end,
 
955
                    const char *wildstr,const char *wildend,
 
956
                    int escape, int w_one, int w_many)
 
957
{
 
958
  int result= -1;                       /* Not found, using wildcards */
 
959
 
 
960
  while (wildstr != wildend)
 
961
  {
 
962
    while (*wildstr != w_many && *wildstr != w_one)
 
963
    {
 
964
      if (*wildstr == escape && wildstr+1 != wildend)
 
965
        wildstr++;
 
966
 
 
967
      if (str == str_end || likeconv(cs,*wildstr++) != likeconv(cs,*str++))
 
968
        return(1);                              /* No match */
 
969
      if (wildstr == wildend)
 
970
        return(str != str_end);         /* Match if both are at end */
 
971
      result=1;                                 /* Found an anchor char     */
 
972
    }
 
973
    if (*wildstr == w_one)
 
974
    {
 
975
      do
 
976
      {
 
977
        if (str == str_end)                     /* Skip one char if possible */
 
978
          return(result);
 
979
        INC_PTR(cs,str,str_end);
 
980
      } while (++wildstr < wildend && *wildstr == w_one);
 
981
      if (wildstr == wildend)
 
982
        break;
 
983
    }
 
984
    if (*wildstr == w_many)
 
985
    {                                           /* Found w_many */
 
986
      uchar cmp;
 
987
      
 
988
      wildstr++;
 
989
      /* Remove any '%' and '_' from the wild search string */
 
990
      for (; wildstr != wildend ; wildstr++)
 
991
      {
 
992
        if (*wildstr == w_many)
 
993
          continue;
 
994
        if (*wildstr == w_one)
 
995
        {
 
996
          if (str == str_end)
 
997
            return(-1);
 
998
          INC_PTR(cs,str,str_end);
 
999
          continue;
 
1000
        }
 
1001
        break;                                  /* Not a wild character */
 
1002
      }
 
1003
      if (wildstr == wildend)
 
1004
        return(0);                              /* Ok if w_many is last */
 
1005
      if (str == str_end)
 
1006
        return(-1);
 
1007
      
 
1008
      if ((cmp= *wildstr) == escape && wildstr+1 != wildend)
 
1009
        cmp= *++wildstr;
 
1010
 
 
1011
      INC_PTR(cs,wildstr,wildend);      /* This is compared trough cmp */
 
1012
      cmp=likeconv(cs,cmp);
 
1013
      do
 
1014
      {
 
1015
        while (str != str_end && (uchar) likeconv(cs,*str) != cmp)
 
1016
          str++;
 
1017
        if (str++ == str_end) return(-1);
 
1018
        {
 
1019
          int tmp=my_wildcmp_8bit(cs,str,str_end,wildstr,wildend,escape,w_one,
 
1020
                                  w_many);
 
1021
          if (tmp <= 0)
 
1022
            return(tmp);
 
1023
        }
 
1024
      } while (str != str_end && wildstr[0] != w_many);
 
1025
      return(-1);
 
1026
    }
 
1027
  }
 
1028
  return(str != str_end ? 1 : 0);
 
1029
}
 
1030
 
 
1031
 
 
1032
/*
 
1033
** Calculate min_str and max_str that ranges a LIKE string.
 
1034
** Arguments:
 
1035
** ptr          Pointer to LIKE string.
 
1036
** ptr_length   Length of LIKE string.
 
1037
** escape       Escape character in LIKE.  (Normally '\').
 
1038
**              All escape characters should be removed from min_str and max_str
 
1039
** res_length   Length of min_str and max_str.
 
1040
** min_str      Smallest case sensitive string that ranges LIKE.
 
1041
**              Should be space padded to res_length.
 
1042
** max_str      Largest case sensitive string that ranges LIKE.
 
1043
**              Normally padded with the biggest character sort value.
 
1044
**
 
1045
** The function should return 0 if ok and 1 if the LIKE string can't be
 
1046
** optimized !
 
1047
*/
 
1048
 
 
1049
my_bool my_like_range_simple(CHARSET_INFO *cs,
 
1050
                             const char *ptr, size_t ptr_length,
 
1051
                             pbool escape, pbool w_one, pbool w_many,
 
1052
                             size_t res_length,
 
1053
                             char *min_str,char *max_str,
 
1054
                             size_t *min_length, size_t *max_length)
 
1055
{
 
1056
  const char *end= ptr + ptr_length;
 
1057
  char *min_org=min_str;
 
1058
  char *min_end=min_str+res_length;
 
1059
  size_t charlen= res_length / cs->mbmaxlen;
 
1060
 
 
1061
  for (; ptr != end && min_str != min_end && charlen > 0 ; ptr++, charlen--)
 
1062
  {
 
1063
    if (*ptr == escape && ptr+1 != end)
 
1064
    {
 
1065
      ptr++;                                    /* Skip escape */
 
1066
      *min_str++= *max_str++ = *ptr;
 
1067
      continue;
 
1068
    }
 
1069
    if (*ptr == w_one)                          /* '_' in SQL */
 
1070
    {
 
1071
      *min_str++='\0';                          /* This should be min char */
 
1072
      *max_str++= (char) cs->max_sort_char;
 
1073
      continue;
 
1074
    }
 
1075
    if (*ptr == w_many)                         /* '%' in SQL */
 
1076
    {
 
1077
      /* Calculate length of keys */
 
1078
      *min_length= ((cs->state & MY_CS_BINSORT) ?
 
1079
                    (size_t) (min_str - min_org) :
 
1080
                    res_length);
 
1081
      *max_length= res_length;
 
1082
      do
 
1083
      {
 
1084
        *min_str++= 0;
 
1085
        *max_str++= (char) cs->max_sort_char;
 
1086
      } while (min_str != min_end);
 
1087
      return 0;
 
1088
    }
 
1089
    *min_str++= *max_str++ = *ptr;
 
1090
  }
 
1091
 
 
1092
 *min_length= *max_length = (size_t) (min_str - min_org);
 
1093
  while (min_str != min_end)
 
1094
    *min_str++= *max_str++ = ' ';      /* Because if key compression */
 
1095
  return 0;
 
1096
}
 
1097
 
 
1098
 
 
1099
size_t my_scan_8bit(CHARSET_INFO *cs, const char *str, const char *end, int sq)
 
1100
{
 
1101
  const char *str0= str;
 
1102
  switch (sq)
 
1103
  {
 
1104
  case MY_SEQ_INTTAIL:
 
1105
    if (*str == '.')
 
1106
    {
 
1107
      for(str++ ; str != end && *str == '0' ; str++);
 
1108
      return (size_t) (str - str0);
 
1109
    }
 
1110
    return 0;
 
1111
 
 
1112
  case MY_SEQ_SPACES:
 
1113
    for ( ; str < end ; str++)
 
1114
    {
 
1115
      if (!my_isspace(cs,*str))
 
1116
        break;
 
1117
    }
 
1118
    return (size_t) (str - str0);
 
1119
  default:
 
1120
    return 0;
 
1121
  }
 
1122
}
 
1123
 
 
1124
 
 
1125
void my_fill_8bit(CHARSET_INFO *cs __attribute__((unused)),
 
1126
                   char *s, size_t l, int fill)
 
1127
{
 
1128
  bfill((uchar*) s,l,fill);
 
1129
}
 
1130
 
 
1131
 
 
1132
size_t my_numchars_8bit(CHARSET_INFO *cs __attribute__((unused)),
 
1133
                      const char *b, const char *e)
 
1134
{
 
1135
  return (size_t) (e - b);
 
1136
}
 
1137
 
 
1138
 
 
1139
size_t my_numcells_8bit(CHARSET_INFO *cs __attribute__((unused)),
 
1140
                        const char *b, const char *e)
 
1141
{
 
1142
  return (size_t) (e - b);
 
1143
}
 
1144
 
 
1145
 
 
1146
size_t my_charpos_8bit(CHARSET_INFO *cs __attribute__((unused)),
 
1147
                       const char *b  __attribute__((unused)),
 
1148
                       const char *e  __attribute__((unused)),
 
1149
                       size_t pos)
 
1150
{
 
1151
  return pos;
 
1152
}
 
1153
 
 
1154
 
 
1155
size_t my_well_formed_len_8bit(CHARSET_INFO *cs __attribute__((unused)),
 
1156
                               const char *start, const char *end,
 
1157
                               size_t nchars, int *error)
 
1158
{
 
1159
  size_t nbytes= (size_t) (end-start);
 
1160
  *error= 0;
 
1161
  return min(nbytes, nchars);
 
1162
}
 
1163
 
 
1164
 
 
1165
size_t my_lengthsp_8bit(CHARSET_INFO *cs __attribute__((unused)),
 
1166
                        const char *ptr, size_t length)
 
1167
{
 
1168
  const char *end;
 
1169
  end= (const char *) skip_trailing_space((const uchar *)ptr, length);
 
1170
  return (size_t) (end-ptr);
 
1171
}
 
1172
 
 
1173
 
 
1174
uint my_instr_simple(CHARSET_INFO *cs,
 
1175
                     const char *b, size_t b_length, 
 
1176
                     const char *s, size_t s_length,
 
1177
                     my_match_t *match, uint nmatch)
 
1178
{
 
1179
  register const uchar *str, *search, *end, *search_end;
 
1180
  
 
1181
  if (s_length <= b_length)
 
1182
  {
 
1183
    if (!s_length)
 
1184
    {
 
1185
      if (nmatch)
 
1186
      {
 
1187
        match->beg= 0;
 
1188
        match->end= 0;
 
1189
        match->mb_len= 0;
 
1190
      }
 
1191
      return 1;         /* Empty string is always found */
 
1192
    }
 
1193
    
 
1194
    str= (const uchar*) b;
 
1195
    search= (const uchar*) s;
 
1196
    end= (const uchar*) b+b_length-s_length+1;
 
1197
    search_end= (const uchar*) s + s_length;
 
1198
    
 
1199
skip:
 
1200
    while (str != end)
 
1201
    {
 
1202
      if (cs->sort_order[*str++] == cs->sort_order[*search])
 
1203
      {
 
1204
        register const uchar *i,*j;
 
1205
        
 
1206
        i= str; 
 
1207
        j= search+1;
 
1208
        
 
1209
        while (j != search_end)
 
1210
          if (cs->sort_order[*i++] != cs->sort_order[*j++]) 
 
1211
            goto skip;
 
1212
        
 
1213
        if (nmatch > 0)
 
1214
        {
 
1215
          match[0].beg= 0;
 
1216
          match[0].end= (size_t) (str- (const uchar*)b-1);
 
1217
          match[0].mb_len= match[0].end;
 
1218
          
 
1219
          if (nmatch > 1)
 
1220
          {
 
1221
            match[1].beg= match[0].end;
 
1222
            match[1].end= match[0].end+s_length;
 
1223
            match[1].mb_len= match[1].end-match[1].beg;
 
1224
          }
 
1225
        }
 
1226
        return 2;
 
1227
      }
 
1228
    }
 
1229
  }
 
1230
  return 0;
 
1231
}
 
1232
 
 
1233
 
 
1234
typedef struct
 
1235
{
 
1236
  int           nchars;
 
1237
  MY_UNI_IDX    uidx;
 
1238
} uni_idx;
 
1239
 
 
1240
#define PLANE_SIZE      0x100
 
1241
#define PLANE_NUM       0x100
 
1242
#define PLANE_NUMBER(x) (((x)>>8) % PLANE_NUM)
 
1243
 
 
1244
static int pcmp(const void * f, const void * s)
 
1245
{
 
1246
  const uni_idx *F= (const uni_idx*) f;
 
1247
  const uni_idx *S= (const uni_idx*) s;
 
1248
  int res;
 
1249
 
 
1250
  if (!(res=((S->nchars)-(F->nchars))))
 
1251
    res=((F->uidx.from)-(S->uidx.to));
 
1252
  return res;
 
1253
}
 
1254
 
 
1255
static my_bool create_fromuni(CHARSET_INFO *cs, void *(*alloc)(size_t))
 
1256
{
 
1257
  uni_idx       idx[PLANE_NUM];
 
1258
  int           i,n;
 
1259
  
 
1260
  /*
 
1261
    Check that Unicode map is loaded.
 
1262
    It can be not loaded when the collation is
 
1263
    listed in Index.xml but not specified
 
1264
    in the character set specific XML file.
 
1265
  */
 
1266
  if (!cs->tab_to_uni)
 
1267
    return TRUE;
 
1268
  
 
1269
  /* Clear plane statistics */
 
1270
  bzero(idx,sizeof(idx));
 
1271
  
 
1272
  /* Count number of characters in each plane */
 
1273
  for (i=0; i< 0x100; i++)
 
1274
  {
 
1275
    uint16 wc=cs->tab_to_uni[i];
 
1276
    int pl= PLANE_NUMBER(wc);
 
1277
    
 
1278
    if (wc || !i)
 
1279
    {
 
1280
      if (!idx[pl].nchars)
 
1281
      {
 
1282
        idx[pl].uidx.from=wc;
 
1283
        idx[pl].uidx.to=wc;
 
1284
      }else
 
1285
      {
 
1286
        idx[pl].uidx.from=wc<idx[pl].uidx.from?wc:idx[pl].uidx.from;
 
1287
        idx[pl].uidx.to=wc>idx[pl].uidx.to?wc:idx[pl].uidx.to;
 
1288
      }
 
1289
      idx[pl].nchars++;
 
1290
    }
 
1291
  }
 
1292
  
 
1293
  /* Sort planes in descending order */
 
1294
  qsort(&idx,PLANE_NUM,sizeof(uni_idx),&pcmp);
 
1295
  
 
1296
  for (i=0; i < PLANE_NUM; i++)
 
1297
  {
 
1298
    int ch,numchars;
 
1299
    
 
1300
    /* Skip empty plane */
 
1301
    if (!idx[i].nchars)
 
1302
      break;
 
1303
    
 
1304
    numchars=idx[i].uidx.to-idx[i].uidx.from+1;
 
1305
    if (!(idx[i].uidx.tab=(uchar*) alloc(numchars * sizeof(*idx[i].uidx.tab))))
 
1306
      return TRUE;
 
1307
    
 
1308
    bzero(idx[i].uidx.tab,numchars*sizeof(*idx[i].uidx.tab));
 
1309
    
 
1310
    for (ch=1; ch < PLANE_SIZE; ch++)
 
1311
    {
 
1312
      uint16 wc=cs->tab_to_uni[ch];
 
1313
      if (wc >= idx[i].uidx.from && wc <= idx[i].uidx.to && wc)
 
1314
      {
 
1315
        int ofs= wc - idx[i].uidx.from;
 
1316
        idx[i].uidx.tab[ofs]= ch;
 
1317
      }
 
1318
    }
 
1319
  }
 
1320
  
 
1321
  /* Allocate and fill reverse table for each plane */
 
1322
  n=i;
 
1323
  if (!(cs->tab_from_uni= (MY_UNI_IDX*) alloc(sizeof(MY_UNI_IDX)*(n+1))))
 
1324
    return TRUE;
 
1325
 
 
1326
  for (i=0; i< n; i++)
 
1327
    cs->tab_from_uni[i]= idx[i].uidx;
 
1328
  
 
1329
  /* Set end-of-list marker */
 
1330
  bzero(&cs->tab_from_uni[i],sizeof(MY_UNI_IDX));
 
1331
  return FALSE;
 
1332
}
 
1333
 
 
1334
static my_bool my_cset_init_8bit(CHARSET_INFO *cs, void *(*alloc)(size_t))
 
1335
{
 
1336
  cs->caseup_multiply= 1;
 
1337
  cs->casedn_multiply= 1;
 
1338
  cs->pad_char= ' ';
 
1339
  return create_fromuni(cs, alloc);
 
1340
}
 
1341
 
 
1342
static void set_max_sort_char(CHARSET_INFO *cs)
 
1343
{
 
1344
  uchar max_char;
 
1345
  uint  i;
 
1346
  
 
1347
  if (!cs->sort_order)
 
1348
    return;
 
1349
  
 
1350
  max_char=cs->sort_order[(uchar) cs->max_sort_char];
 
1351
  for (i= 0; i < 256; i++)
 
1352
  {
 
1353
    if ((uchar) cs->sort_order[i] > max_char)
 
1354
    {
 
1355
      max_char=(uchar) cs->sort_order[i];
 
1356
      cs->max_sort_char= i;
 
1357
    }
 
1358
  }
 
1359
}
 
1360
 
 
1361
static my_bool my_coll_init_simple(CHARSET_INFO *cs,
 
1362
                                   void *(*alloc)(size_t) __attribute__((unused)))
 
1363
{
 
1364
  set_max_sort_char(cs);
 
1365
  return FALSE;
 
1366
}
 
1367
 
 
1368
 
 
1369
longlong my_strtoll10_8bit(CHARSET_INFO *cs __attribute__((unused)),
 
1370
                           const char *nptr, char **endptr, int *error)
 
1371
{
 
1372
  return my_strtoll10(nptr, endptr, error);
 
1373
}
 
1374
 
 
1375
 
 
1376
int my_mb_ctype_8bit(CHARSET_INFO *cs, int *ctype,
 
1377
                   const uchar *s, const uchar *e)
 
1378
{
 
1379
  if (s >= e)
 
1380
  {
 
1381
    *ctype= 0;
 
1382
    return MY_CS_TOOSMALL;
 
1383
  }
 
1384
  *ctype= cs->ctype[*s + 1];
 
1385
  return 1;
 
1386
}
 
1387
 
 
1388
 
 
1389
#undef  ULONGLONG_MAX
 
1390
/*
 
1391
  Needed under MetroWerks Compiler, since MetroWerks compiler does not
 
1392
  properly handle a constant expression containing a mod operator
 
1393
*/
 
1394
#if defined(__NETWARE__) && defined(__MWERKS__)
 
1395
static ulonglong ulonglong_max= ~(ulonglong) 0;
 
1396
#define ULONGLONG_MAX ulonglong_max
 
1397
#else
 
1398
#define ULONGLONG_MAX           (~(ulonglong) 0)
 
1399
#endif /* __NETWARE__ && __MWERKS__ */
 
1400
 
 
1401
    
 
1402
#define CUTOFF  (ULONGLONG_MAX / 10)
 
1403
#define CUTLIM  (ULONGLONG_MAX % 10)
 
1404
#define DIGITS_IN_ULONGLONG 20
 
1405
 
 
1406
static ulonglong d10[DIGITS_IN_ULONGLONG]=
 
1407
{
 
1408
  1,
 
1409
  10,
 
1410
  100,
 
1411
  1000,
 
1412
  10000,
 
1413
  100000,
 
1414
  1000000,
 
1415
  10000000,
 
1416
  100000000,
 
1417
  1000000000,
 
1418
  10000000000ULL,
 
1419
  100000000000ULL,
 
1420
  1000000000000ULL,
 
1421
  10000000000000ULL,
 
1422
  100000000000000ULL,
 
1423
  1000000000000000ULL,
 
1424
  10000000000000000ULL,
 
1425
  100000000000000000ULL,
 
1426
  1000000000000000000ULL,
 
1427
  10000000000000000000ULL
 
1428
};
 
1429
 
 
1430
 
 
1431
/*
 
1432
 
 
1433
  Convert a string to unsigned long long integer value
 
1434
  with rounding.
 
1435
  
 
1436
  SYNOPSYS
 
1437
    my_strntoull10_8bit()
 
1438
      cs              in      pointer to character set
 
1439
      str             in      pointer to the string to be converted
 
1440
      length          in      string length
 
1441
      unsigned_flag   in      whether the number is unsigned
 
1442
      endptr          out     pointer to the stop character
 
1443
      error           out     returned error code
 
1444
 
 
1445
  DESCRIPTION
 
1446
    This function takes the decimal representation of integer number
 
1447
    from string str and converts it to an signed or unsigned
 
1448
    long long integer value.
 
1449
    Space characters and tab are ignored.
 
1450
    A sign character might precede the digit characters.
 
1451
    The number may have any number of pre-zero digits.
 
1452
    The number may have decimal point and exponent.
 
1453
    Rounding is always done in "away from zero" style:
 
1454
      0.5  ->   1
 
1455
     -0.5  ->  -1
 
1456
 
 
1457
    The function stops reading the string str after "length" bytes
 
1458
    or at the first character that is not a part of correct number syntax:
 
1459
 
 
1460
    <signed numeric literal> ::=
 
1461
      [ <sign> ] <exact numeric literal> [ E [ <sign> ] <unsigned integer> ]
 
1462
 
 
1463
    <exact numeric literal> ::=
 
1464
                        <unsigned integer> [ <period> [ <unsigned integer> ] ]
 
1465
                      | <period> <unsigned integer>
 
1466
    <unsigned integer>   ::= <digit>...
 
1467
     
 
1468
  RETURN VALUES
 
1469
    Value of string as a signed/unsigned longlong integer
 
1470
 
 
1471
    endptr cannot be NULL. The function will store the end pointer
 
1472
    to the stop character here.
 
1473
 
 
1474
    The error parameter contains information how things went:
 
1475
    0        ok
 
1476
    ERANGE   If the the value of the converted number is out of range
 
1477
    In this case the return value is:
 
1478
    - ULONGLONG_MAX if unsigned_flag and the number was too big
 
1479
    - 0 if unsigned_flag and the number was negative
 
1480
    - LONGLONG_MAX if no unsigned_flag and the number is too big
 
1481
    - LONGLONG_MIN if no unsigned_flag and the number it too big negative
 
1482
    
 
1483
    EDOM If the string didn't contain any digits.
 
1484
    In this case the return value is 0.
 
1485
*/
 
1486
 
 
1487
ulonglong
 
1488
my_strntoull10rnd_8bit(CHARSET_INFO *cs __attribute__((unused)),
 
1489
                       const char *str, size_t length, int unsigned_flag,
 
1490
                       char **endptr, int *error)
 
1491
{
 
1492
  const char *dot, *end9, *beg, *end= str + length;
 
1493
  ulonglong ull;
 
1494
  ulong ul;
 
1495
  uchar ch;
 
1496
  int shift= 0, digits= 0, negative, addon;
 
1497
 
 
1498
  /* Skip leading spaces and tabs */
 
1499
  for ( ; str < end && (*str == ' ' || *str == '\t') ; str++);
 
1500
 
 
1501
  if (str >= end)
 
1502
    goto ret_edom;
 
1503
 
 
1504
  if ((negative= (*str == '-')) || *str=='+') /* optional sign */
 
1505
  {
 
1506
    if (++str == end)
 
1507
      goto ret_edom;
 
1508
  }
 
1509
 
 
1510
  beg= str;
 
1511
  end9= (str + 9) > end ? end : (str + 9);
 
1512
  /* Accumulate small number into ulong, for performance purposes */
 
1513
  for (ul= 0 ; str < end9 && (ch= (uchar) (*str - '0')) < 10; str++)
 
1514
  {
 
1515
    ul= ul * 10 + ch;
 
1516
  }
 
1517
  
 
1518
  if (str >= end) /* Small number without dots and expanents */
 
1519
  {
 
1520
    *endptr= (char*) str;
 
1521
    if (negative)
 
1522
    {
 
1523
      if (unsigned_flag)
 
1524
      {
 
1525
        *error= ul ? MY_ERRNO_ERANGE : 0;
 
1526
        return 0;
 
1527
      }
 
1528
      else
 
1529
      {
 
1530
        *error= 0;
 
1531
        return (ulonglong) (longlong) -(long) ul;
 
1532
      }
 
1533
    }
 
1534
    else
 
1535
    {
 
1536
      *error=0;
 
1537
      return (ulonglong) ul;
 
1538
    }
 
1539
  }
 
1540
  
 
1541
  digits= str - beg;
 
1542
 
 
1543
  /* Continue to accumulate into ulonglong */
 
1544
  for (dot= NULL, ull= ul; str < end; str++)
 
1545
  {
 
1546
    if ((ch= (uchar) (*str - '0')) < 10)
 
1547
    {
 
1548
      if (ull < CUTOFF || (ull == CUTOFF && ch <= CUTLIM))
 
1549
      {
 
1550
        ull= ull * 10 + ch;
 
1551
        digits++;
 
1552
        continue;
 
1553
      }
 
1554
      /*
 
1555
        Adding the next digit would overflow.
 
1556
        Remember the next digit in "addon", for rounding.
 
1557
        Scan all digits with an optional single dot.
 
1558
      */
 
1559
      if (ull == CUTOFF)
 
1560
      {
 
1561
        ull= ULONGLONG_MAX;
 
1562
        addon= 1;
 
1563
        str++;
 
1564
      }
 
1565
      else
 
1566
        addon= (*str >= '5');
 
1567
      if (!dot)
 
1568
      {
 
1569
        for ( ; str < end && (ch= (uchar) (*str - '0')) < 10; shift++, str++);
 
1570
        if (str < end && *str == '.')
 
1571
        {
 
1572
          str++;
 
1573
          for ( ; str < end && (ch= (uchar) (*str - '0')) < 10; str++);
 
1574
        }
 
1575
      }
 
1576
      else
 
1577
      {
 
1578
        shift= dot - str;
 
1579
        for ( ; str < end && (ch= (uchar) (*str - '0')) < 10; str++);
 
1580
      }
 
1581
      goto exp;
 
1582
    }
 
1583
    
 
1584
    if (*str == '.')
 
1585
    {
 
1586
      if (dot)
 
1587
      {
 
1588
        /* The second dot character */
 
1589
        addon= 0;
 
1590
        goto exp;
 
1591
      }
 
1592
      else
 
1593
      {
 
1594
        dot= str + 1;
 
1595
      }
 
1596
      continue;
 
1597
    }
 
1598
    
 
1599
    /* Unknown character, exit the loop */
 
1600
    break; 
 
1601
  }
 
1602
  shift= dot ? dot - str : 0; /* Right shift */
 
1603
  addon= 0;
 
1604
 
 
1605
exp:    /* [ E [ <sign> ] <unsigned integer> ] */
 
1606
 
 
1607
  if (!digits)
 
1608
  {
 
1609
    str= beg;
 
1610
    goto ret_edom;
 
1611
  }
 
1612
  
 
1613
  if (str < end && (*str == 'e' || *str == 'E'))
 
1614
  {
 
1615
    str++;
 
1616
    if (str < end)
 
1617
    {
 
1618
      int negative_exp, exponent;
 
1619
      if ((negative_exp= (*str == '-')) || *str=='+')
 
1620
      {
 
1621
        if (++str == end)
 
1622
          goto ret_sign;
 
1623
      }
 
1624
      for (exponent= 0 ;
 
1625
           str < end && (ch= (uchar) (*str - '0')) < 10;
 
1626
           str++)
 
1627
      {
 
1628
        exponent= exponent * 10 + ch;
 
1629
      }
 
1630
      shift+= negative_exp ? -exponent : exponent;
 
1631
    }
 
1632
  }
 
1633
  
 
1634
  if (shift == 0) /* No shift, check addon digit */
 
1635
  {
 
1636
    if (addon)
 
1637
    {
 
1638
      if (ull == ULONGLONG_MAX)
 
1639
        goto ret_too_big;
 
1640
      ull++;
 
1641
    }
 
1642
    goto ret_sign;
 
1643
  }
 
1644
 
 
1645
  if (shift < 0) /* Right shift */
 
1646
  {
 
1647
    ulonglong d, r;
 
1648
    
 
1649
    if (-shift >= DIGITS_IN_ULONGLONG)
 
1650
      goto ret_zero; /* Exponent is a big negative number, return 0 */
 
1651
    
 
1652
    d= d10[-shift];
 
1653
    r= (ull % d) * 2;
 
1654
    ull /= d;
 
1655
    if (r >= d)
 
1656
      ull++;
 
1657
    goto ret_sign;
 
1658
  }
 
1659
 
 
1660
  if (shift > DIGITS_IN_ULONGLONG) /* Huge left shift */
 
1661
  {
 
1662
    if (!ull)
 
1663
      goto ret_sign;
 
1664
    goto ret_too_big;
 
1665
  }
 
1666
 
 
1667
  for ( ; shift > 0; shift--, ull*= 10) /* Left shift */
 
1668
  {
 
1669
    if (ull > CUTOFF)
 
1670
      goto ret_too_big; /* Overflow, number too big */
 
1671
  }
 
1672
 
 
1673
ret_sign:
 
1674
  *endptr= (char*) str;
 
1675
 
 
1676
  if (!unsigned_flag)
 
1677
  {
 
1678
    if (negative)
 
1679
    {
 
1680
      if (ull > (ulonglong) LONGLONG_MIN)
 
1681
      {
 
1682
        *error= MY_ERRNO_ERANGE;
 
1683
        return (ulonglong) LONGLONG_MIN;
 
1684
      }
 
1685
      *error= 0;
 
1686
      return (ulonglong) -(longlong) ull;
 
1687
    }
 
1688
    else
 
1689
    {
 
1690
      if (ull > (ulonglong) LONGLONG_MAX)
 
1691
      {
 
1692
        *error= MY_ERRNO_ERANGE;
 
1693
        return (ulonglong) LONGLONG_MAX;
 
1694
      }
 
1695
      *error= 0;
 
1696
      return ull;
 
1697
    }
 
1698
  }
 
1699
 
 
1700
  /* Unsigned number */
 
1701
  if (negative && ull)
 
1702
  {
 
1703
    *error= MY_ERRNO_ERANGE;
 
1704
    return 0;
 
1705
  }
 
1706
  *error= 0;
 
1707
  return ull;
 
1708
 
 
1709
ret_zero:
 
1710
  *endptr= (char*) str;
 
1711
  *error= 0;
 
1712
  return 0;
 
1713
 
 
1714
ret_edom:
 
1715
  *endptr= (char*) str;
 
1716
  *error= MY_ERRNO_EDOM;
 
1717
  return 0;
 
1718
  
 
1719
ret_too_big:
 
1720
  *endptr= (char*) str;
 
1721
  *error= MY_ERRNO_ERANGE;
 
1722
  return unsigned_flag ?
 
1723
         ULONGLONG_MAX :
 
1724
         negative ? (ulonglong) LONGLONG_MIN : (ulonglong) LONGLONG_MAX;
 
1725
}
 
1726
 
 
1727
 
 
1728
/*
 
1729
  Check if a constant can be propagated
 
1730
 
 
1731
  SYNOPSIS:
 
1732
    my_propagate_simple()
 
1733
    cs          Character set information
 
1734
    str         String to convert to double
 
1735
    length      Optional length for string.
 
1736
    
 
1737
  NOTES:
 
1738
   Takes the string in the given charset and check
 
1739
   if it can be safely propagated in the optimizer.
 
1740
   
 
1741
   create table t1 (
 
1742
     s char(5) character set latin1 collate latin1_german2_ci);
 
1743
   insert into t1 values (0xf6); -- o-umlaut
 
1744
   select * from t1 where length(s)=1 and s='oe';
 
1745
 
 
1746
   The above query should return one row.
 
1747
   We cannot convert this query into:
 
1748
   select * from t1 where length('oe')=1 and s='oe';
 
1749
   
 
1750
   Currently we don't check the constant itself,
 
1751
   and decide not to propagate a constant
 
1752
   just if the collation itself allows tricky things
 
1753
   like expansions and contractions. In the future
 
1754
   we can write a more sophisticated functions to
 
1755
   check the constants. For example, 'oa' can always
 
1756
   be safety propagated in German2 because unlike 
 
1757
   'oe' it does not have any special meaning.
 
1758
 
 
1759
  RETURN
 
1760
    1 if constant can be safely propagated
 
1761
    0 if it is not safe to propagate the constant
 
1762
*/
 
1763
 
 
1764
 
 
1765
 
 
1766
my_bool my_propagate_simple(CHARSET_INFO *cs __attribute__((unused)),
 
1767
                            const uchar *str __attribute__((unused)),
 
1768
                            size_t length __attribute__((unused)))
 
1769
{
 
1770
  return 1;
 
1771
}
 
1772
 
 
1773
 
 
1774
my_bool my_propagate_complex(CHARSET_INFO *cs __attribute__((unused)),
 
1775
                             const uchar *str __attribute__((unused)),
 
1776
                             size_t length __attribute__((unused)))
 
1777
{
 
1778
  return 0;
 
1779
}
 
1780
 
 
1781
 
 
1782
 
 
1783
/*
 
1784
  Normalize strxfrm flags
 
1785
 
 
1786
  SYNOPSIS:
 
1787
    my_strxfrm_flag_normalize()
 
1788
    flags    - non-normalized flags
 
1789
    nlevels  - number of levels
 
1790
    
 
1791
  NOTES:
 
1792
    If levels are omitted, then 1-maximum is assumed.
 
1793
    If any level number is greater than the maximum,
 
1794
    it is treated as the maximum.
 
1795
 
 
1796
  RETURN
 
1797
    normalized flags
 
1798
*/
 
1799
 
 
1800
uint my_strxfrm_flag_normalize(uint flags, uint maximum)
 
1801
{
 
1802
  DBUG_ASSERT(maximum >= 1 && maximum <= MY_STRXFRM_NLEVELS);
 
1803
  
 
1804
  /* If levels are omitted, then 1-maximum is assumed*/
 
1805
  if (!(flags & MY_STRXFRM_LEVEL_ALL))
 
1806
  {
 
1807
    static uint def_level_flags[]= {0, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F };
 
1808
    uint flag_pad= flags & MY_STRXFRM_PAD_WITH_SPACE;
 
1809
    flags= def_level_flags[maximum] | flag_pad;
 
1810
  }
 
1811
  else
 
1812
  {
 
1813
    uint i;
 
1814
    uint flag_lev= flags & MY_STRXFRM_LEVEL_ALL;
 
1815
    uint flag_dsc= (flags >> MY_STRXFRM_DESC_SHIFT) & MY_STRXFRM_LEVEL_ALL;
 
1816
    uint flag_rev= (flags >> MY_STRXFRM_REVERSE_SHIFT) & MY_STRXFRM_LEVEL_ALL;
 
1817
    uint flag_pad= flags & MY_STRXFRM_PAD_WITH_SPACE;
 
1818
 
 
1819
    /*
 
1820
      If any level number is greater than the maximum,
 
1821
      it is treated as the maximum.
 
1822
    */
 
1823
    for (maximum--, flags= 0, i= 0; i < MY_STRXFRM_NLEVELS; i++)
 
1824
    {
 
1825
      uint src_bit= 1 << i;
 
1826
      uint dst_bit= 1 << min(i, maximum);
 
1827
      if (flag_lev & src_bit)
 
1828
      {
 
1829
        flags|= dst_bit;
 
1830
        flags|= (flag_dsc & dst_bit) << MY_STRXFRM_DESC_SHIFT;
 
1831
        flags|= (flag_rev & dst_bit) << MY_STRXFRM_REVERSE_SHIFT;
 
1832
      }
 
1833
      else
 
1834
      {
 
1835
        /* Check that there are no DESC or REVERSE flag for skipped level */
 
1836
        DBUG_ASSERT(!(flag_dsc & src_bit) && !(flag_rev & src_bit));
 
1837
      }
 
1838
    }
 
1839
    flags|= flag_pad;
 
1840
  }
 
1841
  
 
1842
  return flags;
 
1843
}
 
1844
 
 
1845
/*
 
1846
  Apply DESC and REVERSE collation rules.
 
1847
 
 
1848
  SYNOPSIS:
 
1849
    my_strxfrm_desc_and_reverse()
 
1850
    str      - pointer to string
 
1851
    strend   - end of string
 
1852
    flags    - flags
 
1853
    level    - which level, starting from 0.
 
1854
    
 
1855
  NOTES:
 
1856
    Apply DESC or REVERSE or both flags.
 
1857
    
 
1858
    If DESC flag is given, then the weights
 
1859
    come out NOTed or negated for that level.
 
1860
    
 
1861
    If REVERSE flags is given, then the weights come out in
 
1862
    reverse order for that level, that is, starting with
 
1863
    the last character and ending with the first character.
 
1864
    
 
1865
    If nether DESC nor REVERSE flags are give,
 
1866
    the string is not changed.
 
1867
    
 
1868
*/
 
1869
void my_strxfrm_desc_and_reverse(uchar *str, uchar *strend,
 
1870
                                 uint flags, uint level)
 
1871
{
 
1872
  if (flags & (MY_STRXFRM_DESC_LEVEL1 << level))
 
1873
  {
 
1874
    if (flags & (MY_STRXFRM_REVERSE_LEVEL1 << level))
 
1875
    {
 
1876
      for (strend--; str <= strend;)
 
1877
      {
 
1878
        uchar tmp= *str;
 
1879
        *str++= ~*strend;
 
1880
        *strend--= ~tmp;
 
1881
      }
 
1882
    }
 
1883
    else
 
1884
    {
 
1885
      for (; str < strend; str++)
 
1886
        *str= ~*str;
 
1887
    }
 
1888
  }
 
1889
  else if (flags & (MY_STRXFRM_REVERSE_LEVEL1 << level))
 
1890
  {
 
1891
    for (strend--; str < strend;)
 
1892
    {
 
1893
      uchar tmp= *str;
 
1894
      *str++= *strend;
 
1895
      *strend--= tmp;
 
1896
    }
 
1897
  }
 
1898
}
 
1899
 
 
1900
 
 
1901
size_t
 
1902
my_strxfrm_pad_desc_and_reverse(CHARSET_INFO *cs,
 
1903
                                uchar *str, uchar *frmend, uchar *strend,
 
1904
                                uint nweights, uint flags, uint level)
 
1905
{
 
1906
  if (nweights && frmend < strend && (flags & MY_STRXFRM_PAD_WITH_SPACE))
 
1907
  {
 
1908
    uint fill_length= min((uint) (strend - frmend), nweights * cs->mbminlen);
 
1909
    cs->cset->fill(cs, (char*) frmend, fill_length, cs->pad_char);
 
1910
    frmend+= fill_length;
 
1911
  }
 
1912
  my_strxfrm_desc_and_reverse(str, frmend, flags, level);
 
1913
  return frmend - str;
 
1914
}
 
1915
 
 
1916
 
 
1917
MY_CHARSET_HANDLER my_charset_8bit_handler=
 
1918
{
 
1919
    my_cset_init_8bit,
 
1920
    NULL,                       /* ismbchar      */
 
1921
    my_mbcharlen_8bit,          /* mbcharlen     */
 
1922
    my_numchars_8bit,
 
1923
    my_charpos_8bit,
 
1924
    my_well_formed_len_8bit,
 
1925
    my_lengthsp_8bit,
 
1926
    my_numcells_8bit,
 
1927
    my_mb_wc_8bit,
 
1928
    my_wc_mb_8bit,
 
1929
    my_mb_ctype_8bit,
 
1930
    my_caseup_str_8bit,
 
1931
    my_casedn_str_8bit,
 
1932
    my_caseup_8bit,
 
1933
    my_casedn_8bit,
 
1934
    my_snprintf_8bit,
 
1935
    my_long10_to_str_8bit,
 
1936
    my_longlong10_to_str_8bit,
 
1937
    my_fill_8bit,
 
1938
    my_strntol_8bit,
 
1939
    my_strntoul_8bit,
 
1940
    my_strntoll_8bit,
 
1941
    my_strntoull_8bit,
 
1942
    my_strntod_8bit,
 
1943
    my_strtoll10_8bit,
 
1944
    my_strntoull10rnd_8bit,
 
1945
    my_scan_8bit
 
1946
};
 
1947
 
 
1948
MY_COLLATION_HANDLER my_collation_8bit_simple_ci_handler =
 
1949
{
 
1950
    my_coll_init_simple,        /* init */
 
1951
    my_strnncoll_simple,
 
1952
    my_strnncollsp_simple,
 
1953
    my_strnxfrm_simple,
 
1954
    my_strnxfrmlen_simple,
 
1955
    my_like_range_simple,
 
1956
    my_wildcmp_8bit,
 
1957
    my_strcasecmp_8bit,
 
1958
    my_instr_simple,
 
1959
    my_hash_sort_simple,
 
1960
    my_propagate_simple
 
1961
};