~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to strings/ctype-simple.c

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

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 *dest, size_t len,
 
76
                          const uchar *src, size_t srclen)
 
77
{
 
78
  uchar *map= cs->sort_order;
 
79
  size_t dstlen= len;
 
80
  set_if_smaller(len, srclen);
 
81
  if (dest != src)
 
82
  {
 
83
    const uchar *end;
 
84
    for ( end=src+len; src < end ;  )
 
85
      *dest++= map[*src++];
 
86
  }
 
87
  else
 
88
  {
 
89
    const uchar *end;
 
90
    for ( end=dest+len; dest < end ; dest++)
 
91
      *dest= (char) map[(uchar) *dest];
 
92
  }
 
93
  if (dstlen > len)
 
94
    bfill(dest, dstlen - len, ' ');
 
95
  return dstlen;
 
96
}
 
97
 
 
98
 
 
99
int my_strnncoll_simple(CHARSET_INFO * cs, const uchar *s, size_t slen, 
 
100
                        const uchar *t, size_t tlen,
 
101
                        my_bool t_is_prefix)
 
102
{
 
103
  size_t len = ( slen > tlen ) ? tlen : slen;
 
104
  uchar *map= cs->sort_order;
 
105
  if (t_is_prefix && slen > tlen)
 
106
    slen=tlen;
 
107
  while (len--)
 
108
  {
 
109
    if (map[*s++] != map[*t++])
 
110
      return ((int) map[s[-1]] - (int) map[t[-1]]);
 
111
  }
 
112
  /*
 
113
    We can't use (slen - tlen) here as the result may be outside of the
 
114
    precision of a signed int
 
115
  */
 
116
  return slen > tlen ? 1 : slen < tlen ? -1 : 0 ;
 
117
}
 
118
 
 
119
 
 
120
/*
 
121
  Compare strings, discarding end space
 
122
 
 
123
  SYNOPSIS
 
124
    my_strnncollsp_simple()
 
125
    cs                  character set handler
 
126
    a                   First string to compare
 
127
    a_length            Length of 'a'
 
128
    b                   Second string to compare
 
129
    b_length            Length of 'b'
 
130
    diff_if_only_endspace_difference
 
131
                        Set to 1 if the strings should be regarded as different
 
132
                        if they only difference in end space
 
133
 
 
134
  IMPLEMENTATION
 
135
    If one string is shorter as the other, then we space extend the other
 
136
    so that the strings have equal length.
 
137
 
 
138
    This will ensure that the following things hold:
 
139
 
 
140
    "a"  == "a "
 
141
    "a\0" < "a"
 
142
    "a\0" < "a "
 
143
 
 
144
  RETURN
 
145
    < 0  a <  b
 
146
    = 0  a == b
 
147
    > 0  a > b
 
148
*/
 
149
 
 
150
int my_strnncollsp_simple(CHARSET_INFO * cs, const uchar *a, size_t a_length, 
 
151
                          const uchar *b, size_t b_length,
 
152
                          my_bool diff_if_only_endspace_difference)
 
153
{
 
154
  const uchar *map= cs->sort_order, *end;
 
155
  size_t length;
 
156
  int res;
 
157
 
 
158
#ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE
 
159
  diff_if_only_endspace_difference= 0;
 
160
#endif
 
161
 
 
162
  end= a + (length= min(a_length, b_length));
 
163
  while (a < end)
 
164
  {
 
165
    if (map[*a++] != map[*b++])
 
166
      return ((int) map[a[-1]] - (int) map[b[-1]]);
 
167
  }
 
168
  res= 0;
 
169
  if (a_length != b_length)
 
170
  {
 
171
    int swap= 1;
 
172
    if (diff_if_only_endspace_difference)
 
173
      res= 1;                                   /* Assume 'a' is bigger */
 
174
    /*
 
175
      Check the next not space character of the longer key. If it's < ' ',
 
176
      then it's smaller than the other key.
 
177
    */
 
178
    if (a_length < b_length)
 
179
    {
 
180
      /* put shorter key in s */
 
181
      a_length= b_length;
 
182
      a= b;
 
183
      swap= -1;                                 /* swap sign of result */
 
184
      res= -res;
 
185
    }
 
186
    for (end= a + a_length-length; a < end ; a++)
 
187
    {
 
188
      if (map[*a] != map[' '])
 
189
        return (map[*a] < map[' ']) ? -swap : swap;
 
190
    }
 
191
  }
 
192
  return res;
 
193
}
 
194
 
 
195
 
 
196
size_t my_caseup_str_8bit(CHARSET_INFO * cs,char *str)
 
197
{
 
198
  register uchar *map= cs->to_upper;
 
199
  char *str_orig= str;
 
200
  while ((*str= (char) map[(uchar) *str]) != 0)
 
201
    str++;
 
202
  return (size_t) (str - str_orig);
 
203
}
 
204
 
 
205
 
 
206
size_t my_casedn_str_8bit(CHARSET_INFO * cs,char *str)
 
207
{
 
208
  register uchar *map= cs->to_lower;
 
209
  char *str_orig= str;
 
210
  while ((*str= (char) map[(uchar) *str]) != 0)
 
211
    str++;
 
212
  return (size_t) (str - str_orig);
 
213
}
 
214
 
 
215
 
 
216
size_t my_caseup_8bit(CHARSET_INFO * cs, char *src, size_t srclen,
 
217
                      char *dst __attribute__((unused)),
 
218
                      size_t dstlen __attribute__((unused)))
 
219
{
 
220
  char *end= src + srclen;
 
221
  register uchar *map= cs->to_upper;
 
222
  DBUG_ASSERT(src == dst && srclen == dstlen);
 
223
  for ( ; src != end ; src++)
 
224
    *src= (char) map[(uchar) *src];
 
225
  return srclen;
 
226
}
 
227
 
 
228
 
 
229
size_t my_casedn_8bit(CHARSET_INFO * cs, char *src, size_t srclen,
 
230
                      char *dst __attribute__((unused)),
 
231
                      size_t dstlen __attribute__((unused)))
 
232
{
 
233
  char *end= src + srclen;
 
234
  register uchar *map=cs->to_lower;
 
235
  DBUG_ASSERT(src == dst && srclen == dstlen);
 
236
  for ( ; src != end ; src++)
 
237
    *src= (char) map[(uchar) *src];
 
238
  return srclen;
 
239
}
 
240
 
 
241
int my_strcasecmp_8bit(CHARSET_INFO * cs,const char *s, const char *t)
 
242
{
 
243
  register uchar *map=cs->to_upper;
 
244
  while (map[(uchar) *s] == map[(uchar) *t++])
 
245
    if (!*s++) return 0;
 
246
  return ((int) map[(uchar) s[0]] - (int) map[(uchar) t[-1]]);
 
247
}
 
248
 
 
249
 
 
250
int my_mb_wc_8bit(CHARSET_INFO *cs,my_wc_t *wc,
 
251
                  const uchar *str,
 
252
                  const uchar *end __attribute__((unused)))
 
253
{
 
254
  if (str >= end)
 
255
    return MY_CS_TOOSMALL;
 
256
  
 
257
  *wc=cs->tab_to_uni[*str];
 
258
  return (!wc[0] && str[0]) ? -1 : 1;
 
259
}
 
260
 
 
261
int my_wc_mb_8bit(CHARSET_INFO *cs,my_wc_t wc,
 
262
                  uchar *str,
 
263
                  uchar *end)
 
264
{
 
265
  MY_UNI_IDX *idx;
 
266
 
 
267
  if (str >= end)
 
268
    return MY_CS_TOOSMALL;
 
269
  
 
270
  for (idx=cs->tab_from_uni; idx->tab ; idx++)
 
271
  {
 
272
    if (idx->from <= wc && idx->to >= wc)
 
273
    {
 
274
      str[0]= idx->tab[wc - idx->from];
 
275
      return (!str[0] && wc) ? MY_CS_ILUNI : 1;
 
276
    }
 
277
  }
 
278
  return MY_CS_ILUNI;
 
279
}
 
280
 
 
281
 
 
282
/* 
 
283
   We can't use vsprintf here as it's not guaranteed to return
 
284
   the length on all operating systems.
 
285
   This function is also not called in a safe environment, so the
 
286
   end buffer must be checked.
 
287
*/
 
288
 
 
289
size_t my_snprintf_8bit(CHARSET_INFO *cs  __attribute__((unused)),
 
290
                        char* to, size_t n  __attribute__((unused)),
 
291
                     const char* fmt, ...)
 
292
{
 
293
  va_list args;
 
294
  int result;
 
295
  va_start(args,fmt);
 
296
  result= my_vsnprintf(to, n, fmt, args);
 
297
  va_end(args);
 
298
  return result;
 
299
}
 
300
 
 
301
 
 
302
void my_hash_sort_simple(CHARSET_INFO *cs,
 
303
                         const uchar *key, size_t len,
 
304
                         ulong *nr1, ulong *nr2)
 
305
{
 
306
  register uchar *sort_order=cs->sort_order;
 
307
  const uchar *end= key + len;
 
308
  
 
309
  /*
 
310
    Remove end space. We have to do this to be able to compare
 
311
    'A ' and 'A' as identical
 
312
  */
 
313
  while (end > key && end[-1] == ' ')
 
314
    end--;
 
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= ptr+length;
 
1169
  while (end > ptr && end[-1] == ' ')
 
1170
    end--;
 
1171
  return (size_t) (end-ptr);
 
1172
}
 
1173
 
 
1174
 
 
1175
uint my_instr_simple(CHARSET_INFO *cs,
 
1176
                     const char *b, size_t b_length, 
 
1177
                     const char *s, size_t s_length,
 
1178
                     my_match_t *match, uint nmatch)
 
1179
{
 
1180
  register const uchar *str, *search, *end, *search_end;
 
1181
  
 
1182
  if (s_length <= b_length)
 
1183
  {
 
1184
    if (!s_length)
 
1185
    {
 
1186
      if (nmatch)
 
1187
      {
 
1188
        match->beg= 0;
 
1189
        match->end= 0;
 
1190
        match->mb_len= 0;
 
1191
      }
 
1192
      return 1;         /* Empty string is always found */
 
1193
    }
 
1194
    
 
1195
    str= (const uchar*) b;
 
1196
    search= (const uchar*) s;
 
1197
    end= (const uchar*) b+b_length-s_length+1;
 
1198
    search_end= (const uchar*) s + s_length;
 
1199
    
 
1200
skip:
 
1201
    while (str != end)
 
1202
    {
 
1203
      if (cs->sort_order[*str++] == cs->sort_order[*search])
 
1204
      {
 
1205
        register const uchar *i,*j;
 
1206
        
 
1207
        i= str; 
 
1208
        j= search+1;
 
1209
        
 
1210
        while (j != search_end)
 
1211
          if (cs->sort_order[*i++] != cs->sort_order[*j++]) 
 
1212
            goto skip;
 
1213
        
 
1214
        if (nmatch > 0)
 
1215
        {
 
1216
          match[0].beg= 0;
 
1217
          match[0].end= (size_t) (str- (const uchar*)b-1);
 
1218
          match[0].mb_len= match[0].end;
 
1219
          
 
1220
          if (nmatch > 1)
 
1221
          {
 
1222
            match[1].beg= match[0].end;
 
1223
            match[1].end= match[0].end+s_length;
 
1224
            match[1].mb_len= match[1].end-match[1].beg;
 
1225
          }
 
1226
        }
 
1227
        return 2;
 
1228
      }
 
1229
    }
 
1230
  }
 
1231
  return 0;
 
1232
}
 
1233
 
 
1234
 
 
1235
typedef struct
 
1236
{
 
1237
  int           nchars;
 
1238
  MY_UNI_IDX    uidx;
 
1239
} uni_idx;
 
1240
 
 
1241
#define PLANE_SIZE      0x100
 
1242
#define PLANE_NUM       0x100
 
1243
#define PLANE_NUMBER(x) (((x)>>8) % PLANE_NUM)
 
1244
 
 
1245
static int pcmp(const void * f, const void * s)
 
1246
{
 
1247
  const uni_idx *F= (const uni_idx*) f;
 
1248
  const uni_idx *S= (const uni_idx*) s;
 
1249
  int res;
 
1250
 
 
1251
  if (!(res=((S->nchars)-(F->nchars))))
 
1252
    res=((F->uidx.from)-(S->uidx.to));
 
1253
  return res;
 
1254
}
 
1255
 
 
1256
static my_bool create_fromuni(CHARSET_INFO *cs, void *(*alloc)(size_t))
 
1257
{
 
1258
  uni_idx       idx[PLANE_NUM];
 
1259
  int           i,n;
 
1260
  
 
1261
  /*
 
1262
    Check that Unicode map is loaded.
 
1263
    It can be not loaded when the collation is
 
1264
    listed in Index.xml but not specified
 
1265
    in the character set specific XML file.
 
1266
  */
 
1267
  if (!cs->tab_to_uni)
 
1268
    return TRUE;
 
1269
  
 
1270
  /* Clear plane statistics */
 
1271
  bzero(idx,sizeof(idx));
 
1272
  
 
1273
  /* Count number of characters in each plane */
 
1274
  for (i=0; i< 0x100; i++)
 
1275
  {
 
1276
    uint16 wc=cs->tab_to_uni[i];
 
1277
    int pl= PLANE_NUMBER(wc);
 
1278
    
 
1279
    if (wc || !i)
 
1280
    {
 
1281
      if (!idx[pl].nchars)
 
1282
      {
 
1283
        idx[pl].uidx.from=wc;
 
1284
        idx[pl].uidx.to=wc;
 
1285
      }else
 
1286
      {
 
1287
        idx[pl].uidx.from=wc<idx[pl].uidx.from?wc:idx[pl].uidx.from;
 
1288
        idx[pl].uidx.to=wc>idx[pl].uidx.to?wc:idx[pl].uidx.to;
 
1289
      }
 
1290
      idx[pl].nchars++;
 
1291
    }
 
1292
  }
 
1293
  
 
1294
  /* Sort planes in descending order */
 
1295
  qsort(&idx,PLANE_NUM,sizeof(uni_idx),&pcmp);
 
1296
  
 
1297
  for (i=0; i < PLANE_NUM; i++)
 
1298
  {
 
1299
    int ch,numchars;
 
1300
    
 
1301
    /* Skip empty plane */
 
1302
    if (!idx[i].nchars)
 
1303
      break;
 
1304
    
 
1305
    numchars=idx[i].uidx.to-idx[i].uidx.from+1;
 
1306
    if (!(idx[i].uidx.tab=(uchar*) alloc(numchars * sizeof(*idx[i].uidx.tab))))
 
1307
      return TRUE;
 
1308
    
 
1309
    bzero(idx[i].uidx.tab,numchars*sizeof(*idx[i].uidx.tab));
 
1310
    
 
1311
    for (ch=1; ch < PLANE_SIZE; ch++)
 
1312
    {
 
1313
      uint16 wc=cs->tab_to_uni[ch];
 
1314
      if (wc >= idx[i].uidx.from && wc <= idx[i].uidx.to && wc)
 
1315
      {
 
1316
        int ofs= wc - idx[i].uidx.from;
 
1317
        idx[i].uidx.tab[ofs]= ch;
 
1318
      }
 
1319
    }
 
1320
  }
 
1321
  
 
1322
  /* Allocate and fill reverse table for each plane */
 
1323
  n=i;
 
1324
  if (!(cs->tab_from_uni= (MY_UNI_IDX*) alloc(sizeof(MY_UNI_IDX)*(n+1))))
 
1325
    return TRUE;
 
1326
 
 
1327
  for (i=0; i< n; i++)
 
1328
    cs->tab_from_uni[i]= idx[i].uidx;
 
1329
  
 
1330
  /* Set end-of-list marker */
 
1331
  bzero(&cs->tab_from_uni[i],sizeof(MY_UNI_IDX));
 
1332
  return FALSE;
 
1333
}
 
1334
 
 
1335
static my_bool my_cset_init_8bit(CHARSET_INFO *cs, void *(*alloc)(size_t))
 
1336
{
 
1337
  cs->caseup_multiply= 1;
 
1338
  cs->casedn_multiply= 1;
 
1339
  cs->pad_char= ' ';
 
1340
  return create_fromuni(cs, alloc);
 
1341
}
 
1342
 
 
1343
static void set_max_sort_char(CHARSET_INFO *cs)
 
1344
{
 
1345
  uchar max_char;
 
1346
  uint  i;
 
1347
  
 
1348
  if (!cs->sort_order)
 
1349
    return;
 
1350
  
 
1351
  max_char=cs->sort_order[(uchar) cs->max_sort_char];
 
1352
  for (i= 0; i < 256; i++)
 
1353
  {
 
1354
    if ((uchar) cs->sort_order[i] > max_char)
 
1355
    {
 
1356
      max_char=(uchar) cs->sort_order[i];
 
1357
      cs->max_sort_char= i;
 
1358
    }
 
1359
  }
 
1360
}
 
1361
 
 
1362
static my_bool my_coll_init_simple(CHARSET_INFO *cs,
 
1363
                                   void *(*alloc)(size_t) __attribute__((unused)))
 
1364
{
 
1365
  set_max_sort_char(cs);
 
1366
  return FALSE;
 
1367
}
 
1368
 
 
1369
 
 
1370
longlong my_strtoll10_8bit(CHARSET_INFO *cs __attribute__((unused)),
 
1371
                           const char *nptr, char **endptr, int *error)
 
1372
{
 
1373
  return my_strtoll10(nptr, endptr, error);
 
1374
}
 
1375
 
 
1376
 
 
1377
int my_mb_ctype_8bit(CHARSET_INFO *cs, int *ctype,
 
1378
                   const uchar *s, const uchar *e)
 
1379
{
 
1380
  if (s >= e)
 
1381
  {
 
1382
    *ctype= 0;
 
1383
    return MY_CS_TOOSMALL;
 
1384
  }
 
1385
  *ctype= cs->ctype[*s + 1];
 
1386
  return 1;
 
1387
}
 
1388
 
 
1389
 
 
1390
#undef  ULONGLONG_MAX
 
1391
/*
 
1392
  Needed under MetroWerks Compiler, since MetroWerks compiler does not
 
1393
  properly handle a constant expression containing a mod operator
 
1394
*/
 
1395
#if defined(__NETWARE__) && defined(__MWERKS__)
 
1396
static ulonglong ulonglong_max= ~(ulonglong) 0;
 
1397
#define ULONGLONG_MAX ulonglong_max
 
1398
#else
 
1399
#define ULONGLONG_MAX           (~(ulonglong) 0)
 
1400
#endif /* __NETWARE__ && __MWERKS__ */
 
1401
 
 
1402
    
 
1403
#define CUTOFF  (ULONGLONG_MAX / 10)
 
1404
#define CUTLIM  (ULONGLONG_MAX % 10)
 
1405
#define DIGITS_IN_ULONGLONG 20
 
1406
 
 
1407
static ulonglong d10[DIGITS_IN_ULONGLONG]=
 
1408
{
 
1409
  1,
 
1410
  10,
 
1411
  100,
 
1412
  1000,
 
1413
  10000,
 
1414
  100000,
 
1415
  1000000,
 
1416
  10000000,
 
1417
  100000000,
 
1418
  1000000000,
 
1419
  10000000000ULL,
 
1420
  100000000000ULL,
 
1421
  1000000000000ULL,
 
1422
  10000000000000ULL,
 
1423
  100000000000000ULL,
 
1424
  1000000000000000ULL,
 
1425
  10000000000000000ULL,
 
1426
  100000000000000000ULL,
 
1427
  1000000000000000000ULL,
 
1428
  10000000000000000000ULL
 
1429
};
 
1430
 
 
1431
 
 
1432
/*
 
1433
 
 
1434
  Convert a string to unsigned long long integer value
 
1435
  with rounding.
 
1436
  
 
1437
  SYNOPSYS
 
1438
    my_strntoull10_8bit()
 
1439
      cs              in      pointer to character set
 
1440
      str             in      pointer to the string to be converted
 
1441
      length          in      string length
 
1442
      unsigned_flag   in      whether the number is unsigned
 
1443
      endptr          out     pointer to the stop character
 
1444
      error           out     returned error code
 
1445
 
 
1446
  DESCRIPTION
 
1447
    This function takes the decimal representation of integer number
 
1448
    from string str and converts it to an signed or unsigned
 
1449
    long long integer value.
 
1450
    Space characters and tab are ignored.
 
1451
    A sign character might precede the digit characters.
 
1452
    The number may have any number of pre-zero digits.
 
1453
    The number may have decimal point and exponent.
 
1454
    Rounding is always done in "away from zero" style:
 
1455
      0.5  ->   1
 
1456
     -0.5  ->  -1
 
1457
 
 
1458
    The function stops reading the string str after "length" bytes
 
1459
    or at the first character that is not a part of correct number syntax:
 
1460
 
 
1461
    <signed numeric literal> ::=
 
1462
      [ <sign> ] <exact numeric literal> [ E [ <sign> ] <unsigned integer> ]
 
1463
 
 
1464
    <exact numeric literal> ::=
 
1465
                        <unsigned integer> [ <period> [ <unsigned integer> ] ]
 
1466
                      | <period> <unsigned integer>
 
1467
    <unsigned integer>   ::= <digit>...
 
1468
     
 
1469
  RETURN VALUES
 
1470
    Value of string as a signed/unsigned longlong integer
 
1471
 
 
1472
    endptr cannot be NULL. The function will store the end pointer
 
1473
    to the stop character here.
 
1474
 
 
1475
    The error parameter contains information how things went:
 
1476
    0        ok
 
1477
    ERANGE   If the the value of the converted number is out of range
 
1478
    In this case the return value is:
 
1479
    - ULONGLONG_MAX if unsigned_flag and the number was too big
 
1480
    - 0 if unsigned_flag and the number was negative
 
1481
    - LONGLONG_MAX if no unsigned_flag and the number is too big
 
1482
    - LONGLONG_MIN if no unsigned_flag and the number it too big negative
 
1483
    
 
1484
    EDOM If the string didn't contain any digits.
 
1485
    In this case the return value is 0.
 
1486
*/
 
1487
 
 
1488
ulonglong
 
1489
my_strntoull10rnd_8bit(CHARSET_INFO *cs __attribute__((unused)),
 
1490
                       const char *str, size_t length, int unsigned_flag,
 
1491
                       char **endptr, int *error)
 
1492
{
 
1493
  const char *dot, *end9, *beg, *end= str + length;
 
1494
  ulonglong ull;
 
1495
  ulong ul;
 
1496
  uchar ch;
 
1497
  int shift= 0, digits= 0, negative, addon;
 
1498
 
 
1499
  /* Skip leading spaces and tabs */
 
1500
  for ( ; str < end && (*str == ' ' || *str == '\t') ; str++);
 
1501
 
 
1502
  if (str >= end)
 
1503
    goto ret_edom;
 
1504
 
 
1505
  if ((negative= (*str == '-')) || *str=='+') /* optional sign */
 
1506
  {
 
1507
    if (++str == end)
 
1508
      goto ret_edom;
 
1509
  }
 
1510
 
 
1511
  beg= str;
 
1512
  end9= (str + 9) > end ? end : (str + 9);
 
1513
  /* Accumulate small number into ulong, for performance purposes */
 
1514
  for (ul= 0 ; str < end9 && (ch= (uchar) (*str - '0')) < 10; str++)
 
1515
  {
 
1516
    ul= ul * 10 + ch;
 
1517
  }
 
1518
  
 
1519
  if (str >= end) /* Small number without dots and expanents */
 
1520
  {
 
1521
    *endptr= (char*) str;
 
1522
    if (negative)
 
1523
    {
 
1524
      if (unsigned_flag)
 
1525
      {
 
1526
        *error= ul ? MY_ERRNO_ERANGE : 0;
 
1527
        return 0;
 
1528
      }
 
1529
      else
 
1530
      {
 
1531
        *error= 0;
 
1532
        return (ulonglong) (longlong) -(long) ul;
 
1533
      }
 
1534
    }
 
1535
    else
 
1536
    {
 
1537
      *error=0;
 
1538
      return (ulonglong) ul;
 
1539
    }
 
1540
  }
 
1541
  
 
1542
  digits= str - beg;
 
1543
 
 
1544
  /* Continue to accumulate into ulonglong */
 
1545
  for (dot= NULL, ull= ul; str < end; str++)
 
1546
  {
 
1547
    if ((ch= (uchar) (*str - '0')) < 10)
 
1548
    {
 
1549
      if (ull < CUTOFF || (ull == CUTOFF && ch <= CUTLIM))
 
1550
      {
 
1551
        ull= ull * 10 + ch;
 
1552
        digits++;
 
1553
        continue;
 
1554
      }
 
1555
      /*
 
1556
        Adding the next digit would overflow.
 
1557
        Remember the next digit in "addon", for rounding.
 
1558
        Scan all digits with an optional single dot.
 
1559
      */
 
1560
      if (ull == CUTOFF)
 
1561
      {
 
1562
        ull= ULONGLONG_MAX;
 
1563
        addon= 1;
 
1564
        str++;
 
1565
      }
 
1566
      else
 
1567
        addon= (*str >= '5');
 
1568
      if (!dot)
 
1569
      {
 
1570
        for ( ; str < end && (ch= (uchar) (*str - '0')) < 10; shift++, str++);
 
1571
        if (str < end && *str == '.')
 
1572
        {
 
1573
          str++;
 
1574
          for ( ; str < end && (ch= (uchar) (*str - '0')) < 10; str++);
 
1575
        }
 
1576
      }
 
1577
      else
 
1578
      {
 
1579
        shift= dot - str;
 
1580
        for ( ; str < end && (ch= (uchar) (*str - '0')) < 10; str++);
 
1581
      }
 
1582
      goto exp;
 
1583
    }
 
1584
    
 
1585
    if (*str == '.')
 
1586
    {
 
1587
      if (dot)
 
1588
      {
 
1589
        /* The second dot character */
 
1590
        addon= 0;
 
1591
        goto exp;
 
1592
      }
 
1593
      else
 
1594
      {
 
1595
        dot= str + 1;
 
1596
      }
 
1597
      continue;
 
1598
    }
 
1599
    
 
1600
    /* Unknown character, exit the loop */
 
1601
    break; 
 
1602
  }
 
1603
  shift= dot ? dot - str : 0; /* Right shift */
 
1604
  addon= 0;
 
1605
 
 
1606
exp:    /* [ E [ <sign> ] <unsigned integer> ] */
 
1607
 
 
1608
  if (!digits)
 
1609
  {
 
1610
    str= beg;
 
1611
    goto ret_edom;
 
1612
  }
 
1613
  
 
1614
  if (str < end && (*str == 'e' || *str == 'E'))
 
1615
  {
 
1616
    str++;
 
1617
    if (str < end)
 
1618
    {
 
1619
      int negative_exp, exponent;
 
1620
      if ((negative_exp= (*str == '-')) || *str=='+')
 
1621
      {
 
1622
        if (++str == end)
 
1623
          goto ret_sign;
 
1624
      }
 
1625
      for (exponent= 0 ;
 
1626
           str < end && (ch= (uchar) (*str - '0')) < 10;
 
1627
           str++)
 
1628
      {
 
1629
        exponent= exponent * 10 + ch;
 
1630
      }
 
1631
      shift+= negative_exp ? -exponent : exponent;
 
1632
    }
 
1633
  }
 
1634
  
 
1635
  if (shift == 0) /* No shift, check addon digit */
 
1636
  {
 
1637
    if (addon)
 
1638
    {
 
1639
      if (ull == ULONGLONG_MAX)
 
1640
        goto ret_too_big;
 
1641
      ull++;
 
1642
    }
 
1643
    goto ret_sign;
 
1644
  }
 
1645
 
 
1646
  if (shift < 0) /* Right shift */
 
1647
  {
 
1648
    ulonglong d, r;
 
1649
    
 
1650
    if (-shift >= DIGITS_IN_ULONGLONG)
 
1651
      goto ret_zero; /* Exponent is a big negative number, return 0 */
 
1652
    
 
1653
    d= d10[-shift];
 
1654
    r= (ull % d) * 2;
 
1655
    ull /= d;
 
1656
    if (r >= d)
 
1657
      ull++;
 
1658
    goto ret_sign;
 
1659
  }
 
1660
 
 
1661
  if (shift > DIGITS_IN_ULONGLONG) /* Huge left shift */
 
1662
  {
 
1663
    if (!ull)
 
1664
      goto ret_sign;
 
1665
    goto ret_too_big;
 
1666
  }
 
1667
 
 
1668
  for ( ; shift > 0; shift--, ull*= 10) /* Left shift */
 
1669
  {
 
1670
    if (ull > CUTOFF)
 
1671
      goto ret_too_big; /* Overflow, number too big */
 
1672
  }
 
1673
 
 
1674
ret_sign:
 
1675
  *endptr= (char*) str;
 
1676
 
 
1677
  if (!unsigned_flag)
 
1678
  {
 
1679
    if (negative)
 
1680
    {
 
1681
      if (ull > (ulonglong) LONGLONG_MIN)
 
1682
      {
 
1683
        *error= MY_ERRNO_ERANGE;
 
1684
        return (ulonglong) LONGLONG_MIN;
 
1685
      }
 
1686
      *error= 0;
 
1687
      return (ulonglong) -(longlong) ull;
 
1688
    }
 
1689
    else
 
1690
    {
 
1691
      if (ull > (ulonglong) LONGLONG_MAX)
 
1692
      {
 
1693
        *error= MY_ERRNO_ERANGE;
 
1694
        return (ulonglong) LONGLONG_MAX;
 
1695
      }
 
1696
      *error= 0;
 
1697
      return ull;
 
1698
    }
 
1699
  }
 
1700
 
 
1701
  /* Unsigned number */
 
1702
  if (negative && ull)
 
1703
  {
 
1704
    *error= MY_ERRNO_ERANGE;
 
1705
    return 0;
 
1706
  }
 
1707
  *error= 0;
 
1708
  return ull;
 
1709
 
 
1710
ret_zero:
 
1711
  *endptr= (char*) str;
 
1712
  *error= 0;
 
1713
  return 0;
 
1714
 
 
1715
ret_edom:
 
1716
  *endptr= (char*) str;
 
1717
  *error= MY_ERRNO_EDOM;
 
1718
  return 0;
 
1719
  
 
1720
ret_too_big:
 
1721
  *endptr= (char*) str;
 
1722
  *error= MY_ERRNO_ERANGE;
 
1723
  return unsigned_flag ?
 
1724
         ULONGLONG_MAX :
 
1725
         negative ? (ulonglong) LONGLONG_MIN : (ulonglong) LONGLONG_MAX;
 
1726
}
 
1727
 
 
1728
 
 
1729
/*
 
1730
  Check if a constant can be propagated
 
1731
 
 
1732
  SYNOPSIS:
 
1733
    my_propagate_simple()
 
1734
    cs          Character set information
 
1735
    str         String to convert to double
 
1736
    length      Optional length for string.
 
1737
    
 
1738
  NOTES:
 
1739
   Takes the string in the given charset and check
 
1740
   if it can be safely propagated in the optimizer.
 
1741
   
 
1742
   create table t1 (
 
1743
     s char(5) character set latin1 collate latin1_german2_ci);
 
1744
   insert into t1 values (0xf6); -- o-umlaut
 
1745
   select * from t1 where length(s)=1 and s='oe';
 
1746
 
 
1747
   The above query should return one row.
 
1748
   We cannot convert this query into:
 
1749
   select * from t1 where length('oe')=1 and s='oe';
 
1750
   
 
1751
   Currently we don't check the constant itself,
 
1752
   and decide not to propagate a constant
 
1753
   just if the collation itself allows tricky things
 
1754
   like expansions and contractions. In the future
 
1755
   we can write a more sophisticated functions to
 
1756
   check the constants. For example, 'oa' can always
 
1757
   be safety propagated in German2 because unlike 
 
1758
   'oe' it does not have any special meaning.
 
1759
 
 
1760
  RETURN
 
1761
    1 if constant can be safely propagated
 
1762
    0 if it is not safe to propagate the constant
 
1763
*/
 
1764
 
 
1765
 
 
1766
 
 
1767
my_bool my_propagate_simple(CHARSET_INFO *cs __attribute__((unused)),
 
1768
                            const uchar *str __attribute__((unused)),
 
1769
                            size_t length __attribute__((unused)))
 
1770
{
 
1771
  return 1;
 
1772
}
 
1773
 
 
1774
 
 
1775
my_bool my_propagate_complex(CHARSET_INFO *cs __attribute__((unused)),
 
1776
                             const uchar *str __attribute__((unused)),
 
1777
                             size_t length __attribute__((unused)))
 
1778
{
 
1779
  return 0;
 
1780
}
 
1781
 
 
1782
 
 
1783
MY_CHARSET_HANDLER my_charset_8bit_handler=
 
1784
{
 
1785
    my_cset_init_8bit,
 
1786
    NULL,                       /* ismbchar      */
 
1787
    my_mbcharlen_8bit,          /* mbcharlen     */
 
1788
    my_numchars_8bit,
 
1789
    my_charpos_8bit,
 
1790
    my_well_formed_len_8bit,
 
1791
    my_lengthsp_8bit,
 
1792
    my_numcells_8bit,
 
1793
    my_mb_wc_8bit,
 
1794
    my_wc_mb_8bit,
 
1795
    my_mb_ctype_8bit,
 
1796
    my_caseup_str_8bit,
 
1797
    my_casedn_str_8bit,
 
1798
    my_caseup_8bit,
 
1799
    my_casedn_8bit,
 
1800
    my_snprintf_8bit,
 
1801
    my_long10_to_str_8bit,
 
1802
    my_longlong10_to_str_8bit,
 
1803
    my_fill_8bit,
 
1804
    my_strntol_8bit,
 
1805
    my_strntoul_8bit,
 
1806
    my_strntoll_8bit,
 
1807
    my_strntoull_8bit,
 
1808
    my_strntod_8bit,
 
1809
    my_strtoll10_8bit,
 
1810
    my_strntoull10rnd_8bit,
 
1811
    my_scan_8bit
 
1812
};
 
1813
 
 
1814
MY_COLLATION_HANDLER my_collation_8bit_simple_ci_handler =
 
1815
{
 
1816
    my_coll_init_simple,        /* init */
 
1817
    my_strnncoll_simple,
 
1818
    my_strnncollsp_simple,
 
1819
    my_strnxfrm_simple,
 
1820
    my_strnxfrmlen_simple,
 
1821
    my_like_range_simple,
 
1822
    my_wildcmp_8bit,
 
1823
    my_strcasecmp_8bit,
 
1824
    my_instr_simple,
 
1825
    my_hash_sort_simple,
 
1826
    my_propagate_simple
 
1827
};