~drizzle-trunk/drizzle/development

1 by brian
clean slate
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);
77.1.18 by Monty Taylor
Removed my_vsnprintf and my_snprintf.
297
  result= vsnprintf(to, n, fmt, args);
1 by brian
clean slate
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
};